Update to 0.5, adding support for video, XEP-166, and XEP-167.
git-svn-id: http://libjingle.googlecode.com/svn/trunk@30 dd674b97-3498-5ee5-1854-bdd07cd0ff33
diff --git a/AUTHORS b/AUTHORS
old mode 100755
new mode 100644
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..3dee65e
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,33 @@
+Libjingle
+
+0.5.0 - Sep 16, 2010
+ - Implemented Jingle protocols XEP-166 and XEP-167.
+ - Backward compatible with Google Talk Call Signaling protocol implemented
+ in previous versions.
+ - Builds on Windows, Linux, and Mac OS X with swtoolkit.
+ - Removed GipsLiteMediaEngine.
+ - Added video support.
+ - Added FileMediaEngine to support both voice and video via RTP dump.
+ - Many bug fixes.
+
+0.4.0 - Feb 01, 2007
+ - Updated protocol.
+ - Added relay server support.
+ - Added proxy detection support.
+ - Many other assorted changes.
+
+0.3.0 - Mar 16 2006
+ - New GipsLiteMediaEngine included to make calls using the GIPS
+ VoiceEngine Lite media componentry on Windows.
+
+0.2.0 - Jan 27 2006
+ - Windows build fixes with Visual Studio Express project files.
+ - Pseudo-TCP support provides TCP-like reliability over a P2PSocket
+ - TunnelSessionClient establishes sessions for reliably sending data
+ using Pseudo-TCP.
+ - A new pcp example application transfers files from one user to
+ another using TunnelSessionClient.
+ - TLS login support for both example applications.
+
+0.1.0 - Dec 15 2005
+ - Initial release.
diff --git a/COPYING b/COPYING
old mode 100755
new mode 100644
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100755
index ce00334..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,13 +0,0 @@
-Libjingle
-
-0.2.0 - Jan 27 2006
- - Windows build fixes with Visual Studio Express project files
- - Pseudo-TCP support provides TCP-like reliability over a P2PSocket
- - TunnelSessionClient establishes sessions for reliably sending data
- using Pseudo-TCP
- - A new pcp example application transfers files from one user to
- another using TunnelSessionClient
- - TLS login support for both example applications
-
-0.1.0 - Dec 15 2005
- - Initial release
diff --git a/DOCUMENTATION b/DOCUMENTATION
deleted file mode 100644
index 7739aef..0000000
--- a/DOCUMENTATION
+++ /dev/null
@@ -1 +0,0 @@
-Documentation for libjingle can be found at http://code.google.com/apis/talk/libjingle/
diff --git a/INSTALL b/INSTALL
deleted file mode 100755
index a4b3414..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,229 +0,0 @@
-Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
-
- This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
- These are generic installation instructions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. (Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.)
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You only need
-`configure.ac' if you want to change it or regenerate `configure' using
-a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system. If you're
- using `csh' on an old version of System V, you might need to type
- `sh ./configure' instead to prevent `csh' from trying to execute
- `configure' itself.
-
- Running `configure' takes awhile. While running, it prints some
- messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package.
-
- 4. Type `make install' to install the programs and any data files and
- documentation.
-
- 5. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. Run `./configure --help'
-for details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
- If you have to use a `make' that does not support the `VPATH'
-variable, you have to compile the package for one architecture at a
-time in the source code directory. After you have installed the
-package for one architecture, use `make distclean' before reconfiguring
-for another architecture.
-
-Installation Names
-==================
-
- By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc. You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on. Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
- Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-`configure' Invocation
-======================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
- Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
-
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100755
index d4cf1cb..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-SUBDIRS=talk
-
-noinst_HEADERS = config.h
-
-EXTRA_DIST=README.win DOCUMENTATION
-
-dist-hook:
- sed -i -f talk/sanitize.sed `find $(distdir) -type f`
diff --git a/NEWS b/NEWS
deleted file mode 100755
index bccf886..0000000
--- a/NEWS
+++ /dev/null
@@ -1,15 +0,0 @@
-0.4.0
-* File transfer support
-* Protocol updates
-* Proxy detection
-* Relay server support
-* Many other assorted changes
-
-0.2.0
-* Windows build files
-* TCP-like reliable stream support
-* pcp example application using pseudo-TCP streams
-* Support for TLS login on both example applications
-
-0.1.0
-* Initial source release
diff --git a/README b/README
old mode 100755
new mode 100644
index 2c4d73d..b127b56
--- a/README
+++ b/README
@@ -1,57 +1,83 @@
-Libjingle
-
-Libjingle is a set of components provided by Google to interoperate with Google
-Talk's peer-to-peer and voice capabilities. This package will create several
-static libraries you may link to your project as needed.
-
--talk - No source files in talk/, just these subdirectories
-|-base - Contains basic low-level portable utility functions for
-| things like threads and sockets
-|-p2p - The P2P stack
- |-base - Base p2p functionality
- |-client - Hooks to tie it into XMPP
-|-session - Signaling
- |-phone - Signaling code specific to making phone calls
-|-third_party - Components that aren't ours
- |-mediastreamer - Media components for dealing with sound hardware and
- | voice codecs
-|-xmllite - XML parser
-|-xmpp - XMPP engine
-
-In addition, this package contains two examples in talk/examples which
-illustrate the basic concepts of how the provided classes work.
-
-The xmllite component of libjingle depends on expat. You can download expat
-from http://expat.sourceforge.net/.
-
-mediastreamer, the media components used by the example applications depend on
-the oRTP and iLBC components from linphone, which can be found at
-http://www.linphone.org. Linphone, in turn depends on GLib, which can be found
-at http://www.gtk.org. This GLib dependency should be removed in future
-releases.
-
-Building Libjingle
-
-Once the dependencies are installed, run ./configure. ./configure will return
-an error if it failed to locate the proper dependencies. If ./configure
-succeeds, run 'make' to build the components and examples.
-
-When the build is complete, you can run the call example from
-talk/examples/call and the pcp example from talk/examples/pcp.
-
-Relay Server
-
-Libjingle will also build a relay server that may be used to relay traffic
-when a direct peer-to-peer connection could not be established. The relay
-server will build in talk/p2p/base/relayserver and will listen on UDP
-ports 5000 and 5001. See the Libjingle Developer Guide at
-http://code.google.com/apis/talk/index.html for information about configuring
-a client to use this relay server.
-
-STUN Server
-
-Lastly, Libjingle builds a STUN server which implements the STUN protocol for
-Simple Traversal of UDP over NAT. The STUN server is built as
-talk/p2p/base/stunserver and listens on UDP port 7000. See the Libjingle
-Developer Guide at http://code.google.com/apis/talk/index.html for information
-about configuring a client to use this STUN server.
+Libjingle
+
+1. Introduction
+
+Libjingle is a set of components provided by Google to implement Jingle
+protocols XEP-166 (http://xmpp.org/extensions/xep-0166.html) and XEP-167
+(http://xmpp.org/extensions/xep-0167.html). Libjingle is also backward
+compatible with Google Talk Call Signaling
+(http://code.google.com/apis/talk/call_signaling.html). This package will
+create several static libraries you may link to your projects as needed.
+
+-talk - No source files in talk/, just these subdirectories
+|-base - Contains basic low-level portable utility functions for
+| things like threads and sockets
+|-p2p - The P2P stack
+ |-base - Base p2p functionality
+ |-client - Hooks to tie it into XMPP
+|-session - Signaling
+ |-phone - Signaling code specific to making phone calls
+ |-testdata - Samples of RTP voice and video dump
+ |-tunnel - Tunnel session and channel
+|-xmllite - XML parser
+|-xmpp - XMPP engine
+
+In addition, this package contains two examples in talk/examples which
+illustrate the basic concepts of how the provided classes work.
+
+2. How to Build
+
+Libjingle is built with swtoolkit (http://code.google.com/p/swtoolkit/), which
+is a set of extensions to the open-source SCons build tool (www.scons.org).
+ * First, install Python 2.4 or later from http://www.python.org/.
+
+ * Second, install the stand alone scons-local package 2.0.0 or later from
+ http://www.scons.org/download.php and set an environment variable,
+ SCONS_DIR, to point to the directory containing SCons, for example,
+ /src/libjingle/scons-local/scons-local-2.0.0.final.0/.
+
+ * Third, install swtoolkit from http://code.google.com/p/swtoolkit/.
+
+ * Finally, Libjingle depends on two open-source projects, expat and srtp.
+ Download expat from http://sourceforge.net/projects/expat/ to
+ talk/third_party/expat-2.0.1/. Follow the instructions at
+ http://sourceforge.net/projects/srtp/develop to download latest srtp to
+ talk/third_party/srtp. Note that srtp-1.4.4 does not work since it misses
+ the extensions used by Libjingle.
+ If you put expat or srtp in a different directory, you need to edit
+ talk/libjingle.scons correspondingly.
+
+2.1 Build Libjingle under Linux or OS X
+ * First, make sure the SCONS_DIR environment variable is set correctly.
+ * Second, run talk/third_party/expat-2.0.1/configure and
+ talk/third_party/srtp/configure.
+ * Third, go to the talk/ directory and run $path_to_swtoolkit/hammer.sh. Run
+ $path_to_swtoolkit/hammer.sh --help for information on how to build for
+ different modes.
+
+2.2 Build Libjingle under Windows
+ * First, make sure the SCONS_DIR environment variable is set correctly and
+ Microsoft Visual Studio is installed.
+ * Second, copy talk/third_party/srtp/config.hw to
+ talk/third_party/srtp/crypto/include/config.h.
+ * Third, go to the talk/ directory and run $path_to_swtoolkit/hammer.bat. Run
+ $path_to_swtoolkit/hammer.sh --help for information on how to build for
+ different modes. You can run the last step under Visual Studio Command
+ Prompt if Visual Studio tools are not under the path environment variable.
+
+The built binaries are under talk/build/dbg/staging or talk/build/opt/staging,
+depending on the build mode. When the build is complete, you can run the
+examples, login or call. For the call sample, you can specify the input and
+output RTP dump for voice and video. This package provides two samples of input
+RTP dump: voice.rtpdump is a single channel, 16Khz voice encoded with G722, and
+video.rtpdump is 320x240 video encoded with H264 AVC at 30 frames per second.
+These provided samples will inter-operate with Google Talk Video. If you use
+other input RTP dump, you may need to change the codecs in call_main.cc, lines
+215 - 222.
+
+Libjingle also builds two server tools, a relay server and a STUN server. The
+relay server may be used to relay traffic when a direct peer-to-peer connection
+could not be established. The STUN Server implements the STUN protocol for
+Simple Traversal of UDP over NAT. See the Libjingle Developer Guide at
+http://code.google.com/apis/talk/index.html for information about configuring a
+client to use this relay server and this STUN server.
\ No newline at end of file
diff --git a/README.win b/README.win
deleted file mode 100755
index 985f251..0000000
--- a/README.win
+++ /dev/null
@@ -1,24 +0,0 @@
-1. Install Visual C++ Express 2005. It is free from this link:
- http://msdn.microsoft.com/vstudio/express/visualc/
-
-2. Install the platform SDK and integrate it into VC++ express
- http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/
-
-3. Download and install binary package for expat:
- http://sourceforge.net/project/showfiles.php?group_id=10127&package_id=11277
-
-4. Update the Visual C++ directories in the Projects and Solutions section in the Options dialog box
- Library files: C:\expat-VERSION\StaticLibs
- Include files: C:\expat-VERSION\Source\Lib
- where VERSION is the version of expat you've downoaded
-
-5. Unzip the libjingle files and open the solution.
-
-6. If you wish to build the call example with GIPS Voice Engine Lite, download Voice Engine Lite from http://developer.globalipsound.com
-
-7. Extract the Interface and Library directories from the Voice Engine Lite zip file into talk\third_party\gips
-
-8. Open talk\third_party\gips\expiration.h and set the GIPS_EXPIRATION #defines to the expiration date provided by GIPS and remove the #error directive
-
-9. Build the solution
-
diff --git a/aclocal.m4 b/aclocal.m4
deleted file mode 100644
index 2178633..0000000
--- a/aclocal.m4
+++ /dev/null
@@ -1,7268 +0,0 @@
-# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005 Free Software Foundation, Inc.
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
-
-# serial 48 Debian 1.5.22-2 AC_PROG_LIBTOOL
-
-
-# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
-# -----------------------------------------------------------
-# If this macro is not defined by Autoconf, define it here.
-m4_ifdef([AC_PROVIDE_IFELSE],
- [],
- [m4_define([AC_PROVIDE_IFELSE],
- [m4_ifdef([AC_PROVIDE_$1],
- [$2], [$3])])])
-
-
-# AC_PROG_LIBTOOL
-# ---------------
-AC_DEFUN([AC_PROG_LIBTOOL],
-[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
-dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
-dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
- AC_PROVIDE_IFELSE([AC_PROG_CXX],
- [AC_LIBTOOL_CXX],
- [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
- ])])
-dnl And a similar setup for Fortran 77 support
- AC_PROVIDE_IFELSE([AC_PROG_F77],
- [AC_LIBTOOL_F77],
- [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
-])])
-
-dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
-dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
-dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
- AC_PROVIDE_IFELSE([AC_PROG_GCJ],
- [AC_LIBTOOL_GCJ],
- [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
- [AC_LIBTOOL_GCJ],
- [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
- [AC_LIBTOOL_GCJ],
- [ifdef([AC_PROG_GCJ],
- [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
- ifdef([A][M_PROG_GCJ],
- [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
- ifdef([LT_AC_PROG_GCJ],
- [define([LT_AC_PROG_GCJ],
- defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
-])])# AC_PROG_LIBTOOL
-
-
-# _AC_PROG_LIBTOOL
-# ----------------
-AC_DEFUN([_AC_PROG_LIBTOOL],
-[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
-AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
-AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
-AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
-
-# This can be used to rebuild libtool when needed
-LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
-
-# Always use our own libtool.
-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
-AC_SUBST(LIBTOOL)dnl
-
-# Prevent multiple expansion
-define([AC_PROG_LIBTOOL], [])
-])# _AC_PROG_LIBTOOL
-
-
-# AC_LIBTOOL_SETUP
-# ----------------
-AC_DEFUN([AC_LIBTOOL_SETUP],
-[AC_PREREQ(2.50)dnl
-AC_REQUIRE([AC_ENABLE_SHARED])dnl
-AC_REQUIRE([AC_ENABLE_STATIC])dnl
-AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_PROG_LD])dnl
-AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
-AC_REQUIRE([AC_PROG_NM])dnl
-
-AC_REQUIRE([AC_PROG_LN_S])dnl
-AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
-# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
-AC_REQUIRE([AC_OBJEXT])dnl
-AC_REQUIRE([AC_EXEEXT])dnl
-dnl
-
-AC_LIBTOOL_SYS_MAX_CMD_LEN
-AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
-AC_LIBTOOL_OBJDIR
-
-AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
-_LT_AC_PROG_ECHO_BACKSLASH
-
-case $host_os in
-aix3*)
- # AIX sometimes has problems with the GCC collect2 program. For some
- # reason, if we set the COLLECT_NAMES environment variable, the problems
- # vanish in a puff of smoke.
- if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
- fi
- ;;
-esac
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
-
-# Same as above, but do not quote variable references.
-[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
-# Constants:
-rm="rm -f"
-
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
-
-# All known linkers require a `.a' archive for static linking (except MSVC,
-# which needs '.lib').
-libext=a
-ltmain="$ac_aux_dir/ltmain.sh"
-ofile="$default_ofile"
-with_gnu_ld="$lt_cv_prog_gnu_ld"
-
-AC_CHECK_TOOL(AR, ar, false)
-AC_CHECK_TOOL(RANLIB, ranlib, :)
-AC_CHECK_TOOL(STRIP, strip, :)
-
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-
-# Set sane defaults for various variables
-test -z "$AR" && AR=ar
-test -z "$AR_FLAGS" && AR_FLAGS=cru
-test -z "$AS" && AS=as
-test -z "$CC" && CC=cc
-test -z "$LTCC" && LTCC=$CC
-test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$LD" && LD=ld
-test -z "$LN_S" && LN_S="ln -s"
-test -z "$MAGIC_CMD" && MAGIC_CMD=file
-test -z "$NM" && NM=nm
-test -z "$SED" && SED=sed
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$RANLIB" && RANLIB=:
-test -z "$STRIP" && STRIP=:
-test -z "$ac_objext" && ac_objext=o
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-if test -n "$RANLIB"; then
- case $host_os in
- openbsd*)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
- ;;
- *)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
- ;;
- esac
- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-fi
-
-_LT_CC_BASENAME([$compiler])
-
-# Only perform the check for file, if the check method requires it
-case $deplibs_check_method in
-file_magic*)
- if test "$file_magic_cmd" = '$MAGIC_CMD'; then
- AC_PATH_MAGIC
- fi
- ;;
-esac
-
-AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
-AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
-enable_win32_dll=yes, enable_win32_dll=no)
-
-AC_ARG_ENABLE([libtool-lock],
- [AC_HELP_STRING([--disable-libtool-lock],
- [avoid locking (might break parallel builds)])])
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-AC_ARG_WITH([pic],
- [AC_HELP_STRING([--with-pic],
- [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
- [pic_mode="$withval"],
- [pic_mode=default])
-test -z "$pic_mode" && pic_mode=default
-
-# Use C for the default configuration in the libtool script
-tagname=
-AC_LIBTOOL_LANG_C_CONFIG
-_LT_AC_TAGCONFIG
-])# AC_LIBTOOL_SETUP
-
-
-# _LT_AC_SYS_COMPILER
-# -------------------
-AC_DEFUN([_LT_AC_SYS_COMPILER],
-[AC_REQUIRE([AC_PROG_CC])dnl
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-])# _LT_AC_SYS_COMPILER
-
-
-# _LT_CC_BASENAME(CC)
-# -------------------
-# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
-AC_DEFUN([_LT_CC_BASENAME],
-[for cc_temp in $1""; do
- case $cc_temp in
- compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
- distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-])
-
-
-# _LT_COMPILER_BOILERPLATE
-# ------------------------
-# Check for compiler boilerplate output or warnings with
-# the simple compiler test code.
-AC_DEFUN([_LT_COMPILER_BOILERPLATE],
-[ac_outfile=conftest.$ac_objext
-printf "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$rm conftest*
-])# _LT_COMPILER_BOILERPLATE
-
-
-# _LT_LINKER_BOILERPLATE
-# ----------------------
-# Check for linker boilerplate output or warnings with
-# the simple link test code.
-AC_DEFUN([_LT_LINKER_BOILERPLATE],
-[ac_outfile=conftest.$ac_objext
-printf "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$rm conftest*
-])# _LT_LINKER_BOILERPLATE
-
-
-# _LT_AC_SYS_LIBPATH_AIX
-# ----------------------
-# Links a minimal program and checks the executable
-# for the system default hardcoded library path. In most cases,
-# this is /usr/lib:/lib, but when the MPI compilers are used
-# the location of the communication and MPI libs are included too.
-# If we don't find anything, use the default library path according
-# to the aix ld manual.
-AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
-[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi],[])
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-])# _LT_AC_SYS_LIBPATH_AIX
-
-
-# _LT_AC_SHELL_INIT(ARG)
-# ----------------------
-AC_DEFUN([_LT_AC_SHELL_INIT],
-[ifdef([AC_DIVERSION_NOTICE],
- [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
- [AC_DIVERT_PUSH(NOTICE)])
-$1
-AC_DIVERT_POP
-])# _LT_AC_SHELL_INIT
-
-
-# _LT_AC_PROG_ECHO_BACKSLASH
-# --------------------------
-# Add some code to the start of the generated configure script which
-# will find an echo command which doesn't interpret backslashes.
-AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
-[_LT_AC_SHELL_INIT([
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-case X$ECHO in
-X*--fallback-echo)
- # Remove one level of quotation (which was required for Make).
- ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
- ;;
-esac
-
-echo=${ECHO-echo}
-if test "X[$]1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X[$]1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
- # Yippee, $echo works!
- :
-else
- # Restart under the correct shell.
- exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
-fi
-
-if test "X[$]1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-[$]*
-EOF
- exit 0
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-if test -z "$ECHO"; then
-if test "X${echo_test_string+set}" != Xset; then
-# find a string as large as possible, as long as the shell can cope with it
- for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
- # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
- if (echo_test_string=`eval $cmd`) 2>/dev/null &&
- echo_test_string=`eval $cmd` &&
- (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
- then
- break
- fi
- done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- :
-else
- # The Solaris, AIX, and Digital Unix default echo programs unquote
- # backslashes. This makes it impossible to quote backslashes using
- # echo "$something" | sed 's/\\/\\\\/g'
- #
- # So, first we look for a working echo in the user's PATH.
-
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for dir in $PATH /usr/ucb; do
- IFS="$lt_save_ifs"
- if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
- test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- echo="$dir/echo"
- break
- fi
- done
- IFS="$lt_save_ifs"
-
- if test "X$echo" = Xecho; then
- # We didn't find a better echo, so look for alternatives.
- if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # This shell has a builtin print -r that does the trick.
- echo='print -r'
- elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
- test "X$CONFIG_SHELL" != X/bin/ksh; then
- # If we have ksh, try running configure again with it.
- ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
- export ORIGINAL_CONFIG_SHELL
- CONFIG_SHELL=/bin/ksh
- export CONFIG_SHELL
- exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
- else
- # Try using printf.
- echo='printf %s\n'
- if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # Cool, printf works
- :
- elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
- export CONFIG_SHELL
- SHELL="$CONFIG_SHELL"
- export SHELL
- echo="$CONFIG_SHELL [$]0 --fallback-echo"
- elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- echo="$CONFIG_SHELL [$]0 --fallback-echo"
- else
- # maybe with a smaller string...
- prev=:
-
- for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
- if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
- then
- break
- fi
- prev="$cmd"
- done
-
- if test "$prev" != 'sed 50q "[$]0"'; then
- echo_test_string=`eval $prev`
- export echo_test_string
- exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
- else
- # Oops. We lost completely, so just stick with echo.
- echo=echo
- fi
- fi
- fi
- fi
-fi
-fi
-
-# Copy echo and quote the copy suitably for passing to libtool from
-# the Makefile, instead of quoting the original, which is used later.
-ECHO=$echo
-if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
- ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
-fi
-
-AC_SUBST(ECHO)
-])])# _LT_AC_PROG_ECHO_BACKSLASH
-
-
-# _LT_AC_LOCK
-# -----------
-AC_DEFUN([_LT_AC_LOCK],
-[AC_ARG_ENABLE([libtool-lock],
- [AC_HELP_STRING([--disable-libtool-lock],
- [avoid locking (might break parallel builds)])])
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case $host in
-ia64-*-hpux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.$ac_objext` in
- *ELF-32*)
- HPUX_IA64_MODE="32"
- ;;
- *ELF-64*)
- HPUX_IA64_MODE="64"
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-*-*-irix6*)
- # Find out which ABI we are using.
- echo '[#]line __oline__ "configure"' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- if test "$lt_cv_prog_gnu_ld" = yes; then
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -melf32bsmip"
- ;;
- *N32*)
- LD="${LD-ld} -melf32bmipn32"
- ;;
- *64-bit*)
- LD="${LD-ld} -melf64bmip"
- ;;
- esac
- else
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -32"
- ;;
- *N32*)
- LD="${LD-ld} -n32"
- ;;
- *64-bit*)
- LD="${LD-ld} -64"
- ;;
- esac
- fi
- fi
- rm -rf conftest*
- ;;
-
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.o` in
- *32-bit*)
- case $host in
- x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
- ;;
- ppc64-*linux*|powerpc64-*linux*)
- LD="${LD-ld} -m elf32ppclinux"
- ;;
- s390x-*linux*)
- LD="${LD-ld} -m elf_s390"
- ;;
- sparc64-*linux*)
- LD="${LD-ld} -m elf32_sparc"
- ;;
- esac
- ;;
- *64-bit*)
- case $host in
- x86_64-*linux*)
- LD="${LD-ld} -m elf_x86_64"
- ;;
- ppc*-*linux*|powerpc*-*linux*)
- LD="${LD-ld} -m elf64ppc"
- ;;
- s390*-*linux*)
- LD="${LD-ld} -m elf64_s390"
- ;;
- sparc*-*linux*)
- LD="${LD-ld} -m elf64_sparc"
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-
-*-*-sco3.2v5*)
- # On SCO OpenServer 5, we need -belf to get full-featured binaries.
- SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -belf"
- AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
- [AC_LANG_PUSH(C)
- AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
- AC_LANG_POP])
- if test x"$lt_cv_cc_needs_belf" != x"yes"; then
- # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
- CFLAGS="$SAVE_CFLAGS"
- fi
- ;;
-sparc*-*solaris*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if AC_TRY_EVAL(ac_compile); then
- case `/usr/bin/file conftest.o` in
- *64-bit*)
- case $lt_cv_prog_gnu_ld in
- yes*) LD="${LD-ld} -m elf64_sparc" ;;
- *) LD="${LD-ld} -64" ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-
-AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
-[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
- AC_CHECK_TOOL(DLLTOOL, dlltool, false)
- AC_CHECK_TOOL(AS, as, false)
- AC_CHECK_TOOL(OBJDUMP, objdump, false)
- ;;
- ])
-esac
-
-need_locks="$enable_libtool_lock"
-
-])# _LT_AC_LOCK
-
-
-# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
-# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
-# ----------------------------------------------------------------
-# Check whether the given compiler option works
-AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
-[AC_REQUIRE([LT_AC_PROG_SED])
-AC_CACHE_CHECK([$1], [$2],
- [$2=no
- ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$3"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&AS_MESSAGE_LOG_FD
- echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- $2=yes
- fi
- fi
- $rm conftest*
-])
-
-if test x"[$]$2" = xyes; then
- ifelse([$5], , :, [$5])
-else
- ifelse([$6], , :, [$6])
-fi
-])# AC_LIBTOOL_COMPILER_OPTION
-
-
-# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
-# [ACTION-SUCCESS], [ACTION-FAILURE])
-# ------------------------------------------------------------
-# Check whether the given compiler option works
-AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
-[AC_CACHE_CHECK([$1], [$2],
- [$2=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $3"
- printf "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&AS_MESSAGE_LOG_FD
- $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- $2=yes
- fi
- else
- $2=yes
- fi
- fi
- $rm conftest*
- LDFLAGS="$save_LDFLAGS"
-])
-
-if test x"[$]$2" = xyes; then
- ifelse([$4], , :, [$4])
-else
- ifelse([$5], , :, [$5])
-fi
-])# AC_LIBTOOL_LINKER_OPTION
-
-
-# AC_LIBTOOL_SYS_MAX_CMD_LEN
-# --------------------------
-AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
-[# find the maximum length of command line arguments
-AC_MSG_CHECKING([the maximum length of command line arguments])
-AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
- i=0
- teststring="ABCD"
-
- case $build_os in
- msdosdjgpp*)
- # On DJGPP, this test can blow up pretty badly due to problems in libc
- # (any single argument exceeding 2000 bytes causes a buffer overrun
- # during glob expansion). Even if it were fixed, the result of this
- # check would be larger than it should be.
- lt_cv_sys_max_cmd_len=12288; # 12K is about right
- ;;
-
- gnu*)
- # Under GNU Hurd, this test is not required because there is
- # no limit to the length of command line arguments.
- # Libtool will interpret -1 as no limit whatsoever
- lt_cv_sys_max_cmd_len=-1;
- ;;
-
- cygwin* | mingw*)
- # On Win9x/ME, this test blows up -- it succeeds, but takes
- # about 5 minutes as the teststring grows exponentially.
- # Worse, since 9x/ME are not pre-emptively multitasking,
- # you end up with a "frozen" computer, even though with patience
- # the test eventually succeeds (with a max line length of 256k).
- # Instead, let's just punt: use the minimum linelength reported by
- # all of the supported platforms: 8192 (on NT/2K/XP).
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- amigaos*)
- # On AmigaOS with pdksh, this test takes hours, literally.
- # So we just punt and use a minimum line length of 8192.
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
- # This has been around since 386BSD, at least. Likely further.
- if test -x /sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
- elif test -x /usr/sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
- else
- lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
- fi
- # And add a safety zone
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- ;;
-
- interix*)
- # We know the value 262144 and hardcode it with a safety zone (like BSD)
- lt_cv_sys_max_cmd_len=196608
- ;;
-
- osf*)
- # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
- # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
- # nice to cause kernel panics so lets avoid the loop below.
- # First set a reasonable default.
- lt_cv_sys_max_cmd_len=16384
- #
- if test -x /sbin/sysconfig; then
- case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
- *1*) lt_cv_sys_max_cmd_len=-1 ;;
- esac
- fi
- ;;
- sco3.2v5*)
- lt_cv_sys_max_cmd_len=102400
- ;;
- sysv5* | sco5v6* | sysv4.2uw2*)
- kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
- if test -n "$kargmax"; then
- lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
- else
- lt_cv_sys_max_cmd_len=32768
- fi
- ;;
- *)
- # If test is not a shell built-in, we'll probably end up computing a
- # maximum length that is only half of the actual maximum length, but
- # we can't tell.
- SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
- while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
- = "XX$teststring") >/dev/null 2>&1 &&
- new_result=`expr "X$teststring" : ".*" 2>&1` &&
- lt_cv_sys_max_cmd_len=$new_result &&
- test $i != 17 # 1/2 MB should be enough
- do
- i=`expr $i + 1`
- teststring=$teststring$teststring
- done
- teststring=
- # Add a significant safety factor because C++ compilers can tack on massive
- # amounts of additional arguments before passing them to the linker.
- # It appears as though 1/2 is a usable value.
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
- ;;
- esac
-])
-if test -n $lt_cv_sys_max_cmd_len ; then
- AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
-else
- AC_MSG_RESULT(none)
-fi
-])# AC_LIBTOOL_SYS_MAX_CMD_LEN
-
-
-# _LT_AC_CHECK_DLFCN
-# ------------------
-AC_DEFUN([_LT_AC_CHECK_DLFCN],
-[AC_CHECK_HEADERS(dlfcn.h)dnl
-])# _LT_AC_CHECK_DLFCN
-
-
-# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
-# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
-# ---------------------------------------------------------------------
-AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
-[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
-if test "$cross_compiling" = yes; then :
- [$4]
-else
- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
- lt_status=$lt_dlunknown
- cat > conftest.$ac_ext <<EOF
-[#line __oline__ "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LT_DLGLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LT_DLGLOBAL DL_GLOBAL
-# else
-# define LT_DLGLOBAL 0
-# endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_DLLAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_DLLAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LT_DLLAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_DLLAZY_OR_NOW DL_NOW
-# else
-# define LT_DLLAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-#ifdef __cplusplus
-extern "C" void exit (int);
-#endif
-
-void fnord() { int i=42;}
-int main ()
-{
- void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
- int status = $lt_dlunknown;
-
- if (self)
- {
- if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
- else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
- /* dlclose (self); */
- }
- else
- puts (dlerror ());
-
- exit (status);
-}]
-EOF
- if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
- (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
- lt_status=$?
- case x$lt_status in
- x$lt_dlno_uscore) $1 ;;
- x$lt_dlneed_uscore) $2 ;;
- x$lt_dlunknown|x*) $3 ;;
- esac
- else :
- # compilation failed
- $3
- fi
-fi
-rm -fr conftest*
-])# _LT_AC_TRY_DLOPEN_SELF
-
-
-# AC_LIBTOOL_DLOPEN_SELF
-# ----------------------
-AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
-[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
-if test "x$enable_dlopen" != xyes; then
- enable_dlopen=unknown
- enable_dlopen_self=unknown
- enable_dlopen_self_static=unknown
-else
- lt_cv_dlopen=no
- lt_cv_dlopen_libs=
-
- case $host_os in
- beos*)
- lt_cv_dlopen="load_add_on"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ;;
-
- mingw* | pw32*)
- lt_cv_dlopen="LoadLibrary"
- lt_cv_dlopen_libs=
- ;;
-
- cygwin*)
- lt_cv_dlopen="dlopen"
- lt_cv_dlopen_libs=
- ;;
-
- darwin*)
- # if libdl is installed we need to link against it
- AC_CHECK_LIB([dl], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
- lt_cv_dlopen="dyld"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ])
- ;;
-
- *)
- AC_CHECK_FUNC([shl_load],
- [lt_cv_dlopen="shl_load"],
- [AC_CHECK_LIB([dld], [shl_load],
- [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
- [AC_CHECK_FUNC([dlopen],
- [lt_cv_dlopen="dlopen"],
- [AC_CHECK_LIB([dl], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
- [AC_CHECK_LIB([svld], [dlopen],
- [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
- [AC_CHECK_LIB([dld], [dld_link],
- [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
- ])
- ])
- ])
- ])
- ])
- ;;
- esac
-
- if test "x$lt_cv_dlopen" != xno; then
- enable_dlopen=yes
- else
- enable_dlopen=no
- fi
-
- case $lt_cv_dlopen in
- dlopen)
- save_CPPFLAGS="$CPPFLAGS"
- test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-
- save_LDFLAGS="$LDFLAGS"
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-
- save_LIBS="$LIBS"
- LIBS="$lt_cv_dlopen_libs $LIBS"
-
- AC_CACHE_CHECK([whether a program can dlopen itself],
- lt_cv_dlopen_self, [dnl
- _LT_AC_TRY_DLOPEN_SELF(
- lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
- lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
- ])
-
- if test "x$lt_cv_dlopen_self" = xyes; then
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
- AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
- lt_cv_dlopen_self_static, [dnl
- _LT_AC_TRY_DLOPEN_SELF(
- lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
- lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
- ])
- fi
-
- CPPFLAGS="$save_CPPFLAGS"
- LDFLAGS="$save_LDFLAGS"
- LIBS="$save_LIBS"
- ;;
- esac
-
- case $lt_cv_dlopen_self in
- yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
- *) enable_dlopen_self=unknown ;;
- esac
-
- case $lt_cv_dlopen_self_static in
- yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
- *) enable_dlopen_self_static=unknown ;;
- esac
-fi
-])# AC_LIBTOOL_DLOPEN_SELF
-
-
-# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
-# ---------------------------------
-# Check to see if options -c and -o are simultaneously supported by compiler
-AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
-[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
-AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
- [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
- [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
- $rm -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&AS_MESSAGE_LOG_FD
- echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
- fi
- fi
- chmod u+w . 2>&AS_MESSAGE_LOG_FD
- $rm conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
- $rm out/* && rmdir out
- cd ..
- rmdir conftest
- $rm conftest*
-])
-])# AC_LIBTOOL_PROG_CC_C_O
-
-
-# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
-# -----------------------------------------
-# Check to see if we can do hard links to lock some files if needed
-AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
-[AC_REQUIRE([_LT_AC_LOCK])dnl
-
-hard_links="nottested"
-if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- AC_MSG_CHECKING([if we can lock with hard links])
- hard_links=yes
- $rm conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- AC_MSG_RESULT([$hard_links])
- if test "$hard_links" = no; then
- AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
-
-
-# AC_LIBTOOL_OBJDIR
-# -----------------
-AC_DEFUN([AC_LIBTOOL_OBJDIR],
-[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
-[rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
- lt_cv_objdir=.libs
-else
- # MS-DOS does not allow filenames that begin with a dot.
- lt_cv_objdir=_libs
-fi
-rmdir .libs 2>/dev/null])
-objdir=$lt_cv_objdir
-])# AC_LIBTOOL_OBJDIR
-
-
-# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
-# ----------------------------------------------
-# Check hardcoding attributes.
-AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
-[AC_MSG_CHECKING([how to hardcode library paths into programs])
-_LT_AC_TAGVAR(hardcode_action, $1)=
-if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
- test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
- test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
-
- # We can hardcode non-existant directories.
- if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
- test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
- # Linking always hardcodes the temporary library directory.
- _LT_AC_TAGVAR(hardcode_action, $1)=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- _LT_AC_TAGVAR(hardcode_action, $1)=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
-fi
-AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
-
-if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
-
-
-# AC_LIBTOOL_SYS_LIB_STRIP
-# ------------------------
-AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
-[striplib=
-old_striplib=
-AC_MSG_CHECKING([whether stripping libraries is possible])
-if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
- test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
- test -z "$striplib" && striplib="$STRIP --strip-unneeded"
- AC_MSG_RESULT([yes])
-else
-# FIXME - insert some real tests, host_os isn't really good enough
- case $host_os in
- darwin*)
- if test -n "$STRIP" ; then
- striplib="$STRIP -x"
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
-fi
- ;;
- *)
- AC_MSG_RESULT([no])
- ;;
- esac
-fi
-])# AC_LIBTOOL_SYS_LIB_STRIP
-
-
-# AC_LIBTOOL_SYS_DYNAMIC_LINKER
-# -----------------------------
-# PORTME Fill in your ld.so characteristics
-AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
-[AC_MSG_CHECKING([dynamic linker characteristics])
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix4* | aix5*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[[01]] | aix4.[[01]].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[[45]]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$host_os in
- yes,cygwin* | yes,mingw* | yes,pw32*)
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $rm \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
- ;;
- mingw*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
- # It is most probably a Windows format PATH printed by
- # mingw gcc, but we are running on Cygwin. Gcc prints its search
- # path with ; separators, and with drive letters. We can handle the
- # drive letters (cygwin fileutils understands them), so leave them,
- # especially as we might pass files found there to a mingw objdump,
- # which wouldn't understand a cygwinified path. Ahh.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- ;;
-
- *)
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
- if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
- else
- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
- fi
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-kfreebsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[[123]]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- version_type=freebsd-$objformat
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[[01]]* | freebsdelf3.[[01]]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
- freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- freebsd*) # from 4.6 on
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- ;;
-
-interix3*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsdelf*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='NetBSD ld.elf_so'
- ;;
-
-knetbsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-nto-qnx*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[[89]] | openbsd2.[[89]].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- export_dynamic_flag_spec='${wl}-Blargedynsym'
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- shlibpath_overrides_runpath=no
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- shlibpath_overrides_runpath=yes
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-AC_MSG_RESULT([$dynamic_linker])
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
-
-
-# _LT_AC_TAGCONFIG
-# ----------------
-AC_DEFUN([_LT_AC_TAGCONFIG],
-[AC_ARG_WITH([tags],
- [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
- [include additional configurations @<:@automatic@:>@])],
- [tagnames="$withval"])
-
-if test -f "$ltmain" && test -n "$tagnames"; then
- if test ! -f "${ofile}"; then
- AC_MSG_WARN([output file `$ofile' does not exist])
- fi
-
- if test -z "$LTCC"; then
- eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
- if test -z "$LTCC"; then
- AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
- else
- AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
- fi
- fi
- if test -z "$LTCFLAGS"; then
- eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
- fi
-
- # Extract list of available tagged configurations in $ofile.
- # Note that this assumes the entire list is on one line.
- available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
-
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for tagname in $tagnames; do
- IFS="$lt_save_ifs"
- # Check whether tagname contains only valid characters
- case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
- "") ;;
- *) AC_MSG_ERROR([invalid tag name: $tagname])
- ;;
- esac
-
- if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
- then
- AC_MSG_ERROR([tag name \"$tagname\" already exists])
- fi
-
- # Update the list of available tags.
- if test -n "$tagname"; then
- echo appending configuration tag \"$tagname\" to $ofile
-
- case $tagname in
- CXX)
- if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
- ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
- (test "X$CXX" != "Xg++"))) ; then
- AC_LIBTOOL_LANG_CXX_CONFIG
- else
- tagname=""
- fi
- ;;
-
- F77)
- if test -n "$F77" && test "X$F77" != "Xno"; then
- AC_LIBTOOL_LANG_F77_CONFIG
- else
- tagname=""
- fi
- ;;
-
- GCJ)
- if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
- AC_LIBTOOL_LANG_GCJ_CONFIG
- else
- tagname=""
- fi
- ;;
-
- RC)
- AC_LIBTOOL_LANG_RC_CONFIG
- ;;
-
- *)
- AC_MSG_ERROR([Unsupported tag name: $tagname])
- ;;
- esac
-
- # Append the new tag name to the list of available tags.
- if test -n "$tagname" ; then
- available_tags="$available_tags $tagname"
- fi
- fi
- done
- IFS="$lt_save_ifs"
-
- # Now substitute the updated list of available tags.
- if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
- mv "${ofile}T" "$ofile"
- chmod +x "$ofile"
- else
- rm -f "${ofile}T"
- AC_MSG_ERROR([unable to update list of available tagged configurations.])
- fi
-fi
-])# _LT_AC_TAGCONFIG
-
-
-# AC_LIBTOOL_DLOPEN
-# -----------------
-# enable checks for dlopen support
-AC_DEFUN([AC_LIBTOOL_DLOPEN],
- [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
-])# AC_LIBTOOL_DLOPEN
-
-
-# AC_LIBTOOL_WIN32_DLL
-# --------------------
-# declare package support for building win32 DLLs
-AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
-[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
-])# AC_LIBTOOL_WIN32_DLL
-
-
-# AC_ENABLE_SHARED([DEFAULT])
-# ---------------------------
-# implement the --enable-shared flag
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-AC_DEFUN([AC_ENABLE_SHARED],
-[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE([shared],
- [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
- [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_shared=yes ;;
- no) enable_shared=no ;;
- *)
- enable_shared=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_shared=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
-])# AC_ENABLE_SHARED
-
-
-# AC_DISABLE_SHARED
-# -----------------
-# set the default shared flag to --disable-shared
-AC_DEFUN([AC_DISABLE_SHARED],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_SHARED(no)
-])# AC_DISABLE_SHARED
-
-
-# AC_ENABLE_STATIC([DEFAULT])
-# ---------------------------
-# implement the --enable-static flag
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-AC_DEFUN([AC_ENABLE_STATIC],
-[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE([static],
- [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
- [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_static=yes ;;
- no) enable_static=no ;;
- *)
- enable_static=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_static=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_static=]AC_ENABLE_STATIC_DEFAULT)
-])# AC_ENABLE_STATIC
-
-
-# AC_DISABLE_STATIC
-# -----------------
-# set the default static flag to --disable-static
-AC_DEFUN([AC_DISABLE_STATIC],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_STATIC(no)
-])# AC_DISABLE_STATIC
-
-
-# AC_ENABLE_FAST_INSTALL([DEFAULT])
-# ---------------------------------
-# implement the --enable-fast-install flag
-# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
-AC_DEFUN([AC_ENABLE_FAST_INSTALL],
-[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE([fast-install],
- [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
- [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
- [p=${PACKAGE-default}
- case $enableval in
- yes) enable_fast_install=yes ;;
- no) enable_fast_install=no ;;
- *)
- enable_fast_install=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_fast_install=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac],
- [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
-])# AC_ENABLE_FAST_INSTALL
-
-
-# AC_DISABLE_FAST_INSTALL
-# -----------------------
-# set the default to --disable-fast-install
-AC_DEFUN([AC_DISABLE_FAST_INSTALL],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_FAST_INSTALL(no)
-])# AC_DISABLE_FAST_INSTALL
-
-
-# AC_LIBTOOL_PICMODE([MODE])
-# --------------------------
-# implement the --with-pic flag
-# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
-AC_DEFUN([AC_LIBTOOL_PICMODE],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-pic_mode=ifelse($#,1,$1,default)
-])# AC_LIBTOOL_PICMODE
-
-
-# AC_PROG_EGREP
-# -------------
-# This is predefined starting with Autoconf 2.54, so this conditional
-# definition can be removed once we require Autoconf 2.54 or later.
-m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
-[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
- [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
- then ac_cv_prog_egrep='grep -E'
- else ac_cv_prog_egrep='egrep'
- fi])
- EGREP=$ac_cv_prog_egrep
- AC_SUBST([EGREP])
-])])
-
-
-# AC_PATH_TOOL_PREFIX
-# -------------------
-# find a file program which can recognise shared library
-AC_DEFUN([AC_PATH_TOOL_PREFIX],
-[AC_REQUIRE([AC_PROG_EGREP])dnl
-AC_MSG_CHECKING([for $1])
-AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
-[case $MAGIC_CMD in
-[[\\/*] | ?:[\\/]*])
- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
- ;;
-*)
- lt_save_MAGIC_CMD="$MAGIC_CMD"
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-dnl $ac_dummy forces splitting on constant user-supplied paths.
-dnl POSIX.2 word splitting is done only on the output of word expansions,
-dnl not every word. This closes a longstanding sh security hole.
- ac_dummy="ifelse([$2], , $PATH, [$2])"
- for ac_dir in $ac_dummy; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$1; then
- lt_cv_path_MAGIC_CMD="$ac_dir/$1"
- if test -n "$file_magic_test_file"; then
- case $deplibs_check_method in
- "file_magic "*)
- file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- $EGREP "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
- fi ;;
- esac
- fi
- break
- fi
- done
- IFS="$lt_save_ifs"
- MAGIC_CMD="$lt_save_MAGIC_CMD"
- ;;
-esac])
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
- AC_MSG_RESULT($MAGIC_CMD)
-else
- AC_MSG_RESULT(no)
-fi
-])# AC_PATH_TOOL_PREFIX
-
-
-# AC_PATH_MAGIC
-# -------------
-# find a file program which can recognise a shared library
-AC_DEFUN([AC_PATH_MAGIC],
-[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
-if test -z "$lt_cv_path_MAGIC_CMD"; then
- if test -n "$ac_tool_prefix"; then
- AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
- else
- MAGIC_CMD=:
- fi
-fi
-])# AC_PATH_MAGIC
-
-
-# AC_PROG_LD
-# ----------
-# find the pathname to the GNU or non-GNU linker
-AC_DEFUN([AC_PROG_LD],
-[AC_ARG_WITH([gnu-ld],
- [AC_HELP_STRING([--with-gnu-ld],
- [assume the C compiler uses GNU ld @<:@default=no@:>@])],
- [test "$withval" = no || with_gnu_ld=yes],
- [with_gnu_ld=no])
-AC_REQUIRE([LT_AC_PROG_SED])dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-ac_prog=ld
-if test "$GCC" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- AC_MSG_CHECKING([for ld used by $CC])
- case $host in
- *-*-mingw*)
- # gcc leaves a trailing carriage return which upsets mingw
- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
- *)
- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
- esac
- case $ac_prog in
- # Accept absolute paths.
- [[\\/]]* | ?:[[\\/]]*)
- re_direlt='/[[^/]][[^/]]*/\.\./'
- # Canonicalize the pathname of ld
- ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
- while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we aren't using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
-elif test "$with_gnu_ld" = yes; then
- AC_MSG_CHECKING([for GNU ld])
-else
- AC_MSG_CHECKING([for non-GNU ld])
-fi
-AC_CACHE_VAL(lt_cv_path_LD,
-[if test -z "$LD"; then
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- lt_cv_path_LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some variants of GNU ld only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
- *GNU* | *'with BFD'*)
- test "$with_gnu_ld" != no && break
- ;;
- *)
- test "$with_gnu_ld" != yes && break
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
-else
- lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi])
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
- AC_MSG_RESULT($LD)
-else
- AC_MSG_RESULT(no)
-fi
-test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
-AC_PROG_LD_GNU
-])# AC_PROG_LD
-
-
-# AC_PROG_LD_GNU
-# --------------
-AC_DEFUN([AC_PROG_LD_GNU],
-[AC_REQUIRE([AC_PROG_EGREP])dnl
-AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
-[# I'd rather use --version here, but apparently some GNU lds only accept -v.
-case `$LD -v 2>&1 </dev/null` in
-*GNU* | *'with BFD'*)
- lt_cv_prog_gnu_ld=yes
- ;;
-*)
- lt_cv_prog_gnu_ld=no
- ;;
-esac])
-with_gnu_ld=$lt_cv_prog_gnu_ld
-])# AC_PROG_LD_GNU
-
-
-# AC_PROG_LD_RELOAD_FLAG
-# ----------------------
-# find reload flag for linker
-# -- PORTME Some linkers may need a different reload flag.
-AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
-[AC_CACHE_CHECK([for $LD option to reload object files],
- lt_cv_ld_reload_flag,
- [lt_cv_ld_reload_flag='-r'])
-reload_flag=$lt_cv_ld_reload_flag
-case $reload_flag in
-"" | " "*) ;;
-*) reload_flag=" $reload_flag" ;;
-esac
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-case $host_os in
- darwin*)
- if test "$GCC" = yes; then
- reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
- else
- reload_cmds='$LD$reload_flag -o $output$reload_objs'
- fi
- ;;
-esac
-])# AC_PROG_LD_RELOAD_FLAG
-
-
-# AC_DEPLIBS_CHECK_METHOD
-# -----------------------
-# how to check for library dependencies
-# -- PORTME fill in with the dynamic library characteristics
-AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
-[AC_CACHE_CHECK([how to recognise dependent libraries],
-lt_cv_deplibs_check_method,
-[lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [[regex]]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given extended regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-
-case $host_os in
-aix4* | aix5*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-beos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-bsdi[[45]]*)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
- lt_cv_file_magic_cmd='/usr/bin/file -L'
- lt_cv_file_magic_test_file=/shlib/libc.so
- ;;
-
-cygwin*)
- # func_win32_libid is a shell function defined in ltmain.sh
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- ;;
-
-mingw* | pw32*)
- # Base MSYS/MinGW do not provide the 'file' command needed by
- # func_win32_libid shell function, so use a weaker test based on 'objdump'.
- lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- ;;
-
-darwin* | rhapsody*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-freebsd* | kfreebsd*-gnu | dragonfly*)
- if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
- case $host_cpu in
- i*86 )
- # Not sure whether the presence of OpenBSD here was a mistake.
- # Let's accept both of them until this is cleared up.
- lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
- ;;
- esac
- else
- lt_cv_deplibs_check_method=pass_all
- fi
- ;;
-
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-hpux10.20* | hpux11*)
- lt_cv_file_magic_cmd=/usr/bin/file
- case $host_cpu in
- ia64*)
- lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
- lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
- ;;
- hppa*64*)
- [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
- lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
- ;;
- *)
- lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
- lt_cv_file_magic_test_file=/usr/lib/libc.sl
- ;;
- esac
- ;;
-
-interix3*)
- # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $LD in
- *-32|*"-32 ") libmagic=32-bit;;
- *-n32|*"-n32 ") libmagic=N32;;
- *-64|*"-64 ") libmagic=64-bit;;
- *) libmagic=never-match;;
- esac
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-# This must be Linux ELF.
-linux*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
- fi
- ;;
-
-newos6*)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=/usr/lib/libnls.so
- ;;
-
-nto-qnx*)
- lt_cv_deplibs_check_method=unknown
- ;;
-
-openbsd*)
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
- fi
- ;;
-
-osf3* | osf4* | osf5*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-solaris*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv4 | sysv4.3*)
- case $host_vendor in
- motorola)
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
- ;;
- ncr)
- lt_cv_deplibs_check_method=pass_all
- ;;
- sequent)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
- ;;
- sni)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
- lt_cv_file_magic_test_file=/lib/libc.so
- ;;
- siemens)
- lt_cv_deplibs_check_method=pass_all
- ;;
- pc)
- lt_cv_deplibs_check_method=pass_all
- ;;
- esac
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-esac
-])
-file_magic_cmd=$lt_cv_file_magic_cmd
-deplibs_check_method=$lt_cv_deplibs_check_method
-test -z "$deplibs_check_method" && deplibs_check_method=unknown
-])# AC_DEPLIBS_CHECK_METHOD
-
-
-# AC_PROG_NM
-# ----------
-# find the pathname to a BSD-compatible name lister
-AC_DEFUN([AC_PROG_NM],
-[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
-[if test -n "$NM"; then
- # Let the user override the test.
- lt_cv_path_NM="$NM"
-else
- lt_nm_to_check="${ac_tool_prefix}nm"
- if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
- lt_nm_to_check="$lt_nm_to_check nm"
- fi
- for lt_tmp_nm in $lt_nm_to_check; do
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- tmp_nm="$ac_dir/$lt_tmp_nm"
- if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
- # Check to see if the nm accepts a BSD-compat flag.
- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
- # nm: unknown option "B" ignored
- # Tru64's nm complains that /dev/null is an invalid object file
- case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
- */dev/null* | *'Invalid file or object type'*)
- lt_cv_path_NM="$tmp_nm -B"
- break
- ;;
- *)
- case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
- */dev/null*)
- lt_cv_path_NM="$tmp_nm -p"
- break
- ;;
- *)
- lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
- continue # so that we can try to find one that supports BSD flags
- ;;
- esac
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
- done
- test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
-fi])
-NM="$lt_cv_path_NM"
-])# AC_PROG_NM
-
-
-# AC_CHECK_LIBM
-# -------------
-# check for math library
-AC_DEFUN([AC_CHECK_LIBM],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-LIBM=
-case $host in
-*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
- # These system don't have libm, or don't need it
- ;;
-*-ncr-sysv4.3*)
- AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
- AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
- ;;
-*)
- AC_CHECK_LIB(m, cos, LIBM="-lm")
- ;;
-esac
-])# AC_CHECK_LIBM
-
-
-# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
-# -----------------------------------
-# sets LIBLTDL to the link flags for the libltdl convenience library and
-# LTDLINCL to the include flags for the libltdl header and adds
-# --enable-ltdl-convenience to the configure arguments. Note that
-# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
-# it is assumed to be `libltdl'. LIBLTDL will be prefixed with
-# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
-# (note the single quotes!). If your package is not flat and you're not
-# using automake, define top_builddir and top_srcdir appropriately in
-# the Makefiles.
-AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
- case $enable_ltdl_convenience in
- no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
- "") enable_ltdl_convenience=yes
- ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
- esac
- LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
- LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
- # For backwards non-gettext consistent compatibility...
- INCLTDL="$LTDLINCL"
-])# AC_LIBLTDL_CONVENIENCE
-
-
-# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
-# -----------------------------------
-# sets LIBLTDL to the link flags for the libltdl installable library and
-# LTDLINCL to the include flags for the libltdl header and adds
-# --enable-ltdl-install to the configure arguments. Note that
-# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
-# and an installed libltdl is not found, it is assumed to be `libltdl'.
-# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
-# '${top_srcdir}/' (note the single quotes!). If your package is not
-# flat and you're not using automake, define top_builddir and top_srcdir
-# appropriately in the Makefiles.
-# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
-AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
-[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
- AC_CHECK_LIB(ltdl, lt_dlinit,
- [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
- [if test x"$enable_ltdl_install" = xno; then
- AC_MSG_WARN([libltdl not installed, but installation disabled])
- else
- enable_ltdl_install=yes
- fi
- ])
- if test x"$enable_ltdl_install" = x"yes"; then
- ac_configure_args="$ac_configure_args --enable-ltdl-install"
- LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
- LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
- else
- ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
- LIBLTDL="-lltdl"
- LTDLINCL=
- fi
- # For backwards non-gettext consistent compatibility...
- INCLTDL="$LTDLINCL"
-])# AC_LIBLTDL_INSTALLABLE
-
-
-# AC_LIBTOOL_CXX
-# --------------
-# enable support for C++ libraries
-AC_DEFUN([AC_LIBTOOL_CXX],
-[AC_REQUIRE([_LT_AC_LANG_CXX])
-])# AC_LIBTOOL_CXX
-
-
-# _LT_AC_LANG_CXX
-# ---------------
-AC_DEFUN([_LT_AC_LANG_CXX],
-[AC_REQUIRE([AC_PROG_CXX])
-AC_REQUIRE([_LT_AC_PROG_CXXCPP])
-_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
-])# _LT_AC_LANG_CXX
-
-# _LT_AC_PROG_CXXCPP
-# ------------------
-AC_DEFUN([_LT_AC_PROG_CXXCPP],
-[
-AC_REQUIRE([AC_PROG_CXX])
-if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
- ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
- (test "X$CXX" != "Xg++"))) ; then
- AC_PROG_CXXCPP
-fi
-])# _LT_AC_PROG_CXXCPP
-
-# AC_LIBTOOL_F77
-# --------------
-# enable support for Fortran 77 libraries
-AC_DEFUN([AC_LIBTOOL_F77],
-[AC_REQUIRE([_LT_AC_LANG_F77])
-])# AC_LIBTOOL_F77
-
-
-# _LT_AC_LANG_F77
-# ---------------
-AC_DEFUN([_LT_AC_LANG_F77],
-[AC_REQUIRE([AC_PROG_F77])
-_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
-])# _LT_AC_LANG_F77
-
-
-# AC_LIBTOOL_GCJ
-# --------------
-# enable support for GCJ libraries
-AC_DEFUN([AC_LIBTOOL_GCJ],
-[AC_REQUIRE([_LT_AC_LANG_GCJ])
-])# AC_LIBTOOL_GCJ
-
-
-# _LT_AC_LANG_GCJ
-# ---------------
-AC_DEFUN([_LT_AC_LANG_GCJ],
-[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
- [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
- [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
- [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
- [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
- [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
-_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
-])# _LT_AC_LANG_GCJ
-
-
-# AC_LIBTOOL_RC
-# -------------
-# enable support for Windows resource files
-AC_DEFUN([AC_LIBTOOL_RC],
-[AC_REQUIRE([LT_AC_PROG_RC])
-_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
-])# AC_LIBTOOL_RC
-
-
-# AC_LIBTOOL_LANG_C_CONFIG
-# ------------------------
-# Ensure that the configuration vars for the C compiler are
-# suitably defined. Those variables are subsequently used by
-# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
-AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
-AC_DEFUN([_LT_AC_LANG_C_CONFIG],
-[lt_save_CC="$CC"
-AC_LANG_PUSH(C)
-
-# Source file extension for C test sources.
-ac_ext=c
-
-# Object file extension for compiled C test sources.
-objext=o
-_LT_AC_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(){return(0);}\n'
-
-_LT_AC_SYS_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
-AC_LIBTOOL_PROG_COMPILER_PIC($1)
-AC_LIBTOOL_PROG_CC_C_O($1)
-AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
-AC_LIBTOOL_PROG_LD_SHLIBS($1)
-AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
-AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
-AC_LIBTOOL_SYS_LIB_STRIP
-AC_LIBTOOL_DLOPEN_SELF
-
-# Report which library types will actually be built
-AC_MSG_CHECKING([if libtool supports shared libraries])
-AC_MSG_RESULT([$can_build_shared])
-
-AC_MSG_CHECKING([whether to build shared libraries])
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case $host_os in
-aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-
-aix4* | aix5*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
-esac
-AC_MSG_RESULT([$enable_shared])
-
-AC_MSG_CHECKING([whether to build static libraries])
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-AC_MSG_RESULT([$enable_static])
-
-AC_LIBTOOL_CONFIG($1)
-
-AC_LANG_POP
-CC="$lt_save_CC"
-])# AC_LIBTOOL_LANG_C_CONFIG
-
-
-# AC_LIBTOOL_LANG_CXX_CONFIG
-# --------------------------
-# Ensure that the configuration vars for the C compiler are
-# suitably defined. Those variables are subsequently used by
-# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
-AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
-AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
-[AC_LANG_PUSH(C++)
-AC_REQUIRE([AC_PROG_CXX])
-AC_REQUIRE([_LT_AC_PROG_CXXCPP])
-
-_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_AC_TAGVAR(allow_undefined_flag, $1)=
-_LT_AC_TAGVAR(always_export_symbols, $1)=no
-_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
-_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_AC_TAGVAR(hardcode_direct, $1)=no
-_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
-_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
-_LT_AC_TAGVAR(hardcode_automatic, $1)=no
-_LT_AC_TAGVAR(module_cmds, $1)=
-_LT_AC_TAGVAR(module_expsym_cmds, $1)=
-_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_AC_TAGVAR(no_undefined_flag, $1)=
-_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Dependencies to place before and after the object being linked:
-_LT_AC_TAGVAR(predep_objects, $1)=
-_LT_AC_TAGVAR(postdep_objects, $1)=
-_LT_AC_TAGVAR(predeps, $1)=
-_LT_AC_TAGVAR(postdeps, $1)=
-_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
-
-# Source file extension for C++ test sources.
-ac_ext=cpp
-
-# Object file extension for compiled C++ test sources.
-objext=o
-_LT_AC_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n'
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_AC_SYS_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC=$CC
-lt_save_LD=$LD
-lt_save_GCC=$GCC
-GCC=$GXX
-lt_save_with_gnu_ld=$with_gnu_ld
-lt_save_path_LD=$lt_cv_path_LD
-if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
- lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
-else
- $as_unset lt_cv_prog_gnu_ld
-fi
-if test -n "${lt_cv_path_LDCXX+set}"; then
- lt_cv_path_LD=$lt_cv_path_LDCXX
-else
- $as_unset lt_cv_path_LD
-fi
-test -z "${LDCXX+set}" || LD=$LDCXX
-CC=${CXX-"c++"}
-compiler=$CC
-_LT_AC_TAGVAR(compiler, $1)=$CC
-_LT_CC_BASENAME([$compiler])
-
-# We don't want -fno-exception wen compiling C++ code, so set the
-# no_builtin_flag separately
-if test "$GXX" = yes; then
- _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
-else
- _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
-fi
-
-if test "$GXX" = yes; then
- # Set up default GNU C++ configuration
-
- AC_PROG_LD
-
- # Check if GNU C++ uses GNU ld as the underlying linker, since the
- # archiving commands below assume that GNU ld is being used.
- if test "$with_gnu_ld" = yes; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-
- # If archive_cmds runs LD, not CC, wlarc should be empty
- # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
- # investigate it a little bit more. (MM)
- wlarc='${wl}'
-
- # ancient GNU ld didn't support --whole-archive et. al.
- if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
- grep 'no-whole-archive' > /dev/null; then
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- else
- with_gnu_ld=no
- wlarc=
-
- # A generic and very simple default shared library creation
- # command for GNU C++ for the case where it uses the native
- # linker, instead of GNU ld. If possible, this setting should
- # overridden to take advantage of the native linker features on
- # the platform it is being used on.
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- fi
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
-
-else
- GXX=no
- with_gnu_ld=no
- wlarc=
-fi
-
-# PORTME: fill in a description of your system's C++ link characteristics
-AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
-_LT_AC_TAGVAR(ld_shlibs, $1)=yes
-case $host_os in
- aix3*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- aix4* | aix5*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
- for ld_flag in $LDFLAGS; do
- case $ld_flag in
- *-brtl*)
- aix_use_runtimelinking=yes
- break
- ;;
- esac
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- _LT_AC_TAGVAR(archive_cmds, $1)=''
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
-
- if test "$GXX" = yes; then
- case $host_os in aix4.[[012]]|aix4.[[012]].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- else
- # We have old collect2
- _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- _LT_AC_TAGVAR(always_export_symbols, $1)=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
- # Determine the default libpath from the value encoded in an empty executable.
- _LT_AC_SYS_LIBPATH_AIX
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
-
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an empty executable.
- _LT_AC_SYS_LIBPATH_AIX
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- beos*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- chorus*)
- case $cc_basename in
- *)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
-
- cygwin* | mingw* | pw32*)
- # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
- # as there is no search path for DLLs.
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_AC_TAGVAR(always_export_symbols, $1)=no
- _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
-
- if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- darwin* | rhapsody*)
- case $host_os in
- rhapsody* | darwin1.[[012]])
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
- ;;
- *) # Darwin 1.3 on
- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- else
- case ${MACOSX_DEPLOYMENT_TARGET} in
- 10.[[012]])
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- ;;
- 10.*)
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
- ;;
- esac
- fi
- ;;
- esac
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
-
- if test "$GXX" = yes ; then
- lt_int_apple_cc_single_mod=no
- output_verbose_link_cmd='echo'
- if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
- lt_int_apple_cc_single_mod=yes
- fi
- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- fi
- _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- fi
- _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- case $cc_basename in
- xlc*)
- output_verbose_link_cmd='echo'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
- _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- ;;
- *)
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- fi
- ;;
-
- dgux*)
- case $cc_basename in
- ec++*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
- freebsd[[12]]*)
- # C++ shared libraries reported to be fairly broken before switch to ELF
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- freebsd-elf*)
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- ;;
- freebsd* | kfreebsd*-gnu | dragonfly*)
- # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
- # conventions
- _LT_AC_TAGVAR(ld_shlibs, $1)=yes
- ;;
- gnu*)
- ;;
- hpux9*)
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
- # but as the default
- # location of the library.
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- aCC*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
- hpux10*|hpux11*)
- if test $with_gnu_ld = no; then
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
- ;;
- *)
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- ;;
- esac
- fi
- case $host_cpu in
- hppa*64*|ia64*)
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
- *)
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
- # but as the default
- # location of the library.
- ;;
- esac
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- aCC*)
- case $host_cpu in
- hppa*64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes; then
- if test $with_gnu_ld = no; then
- case $host_cpu in
- hppa*64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- fi
- else
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
- interix3*)
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
- irix5* | irix6*)
- case $cc_basename in
- CC*)
- # SGI C++
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
-
- # Archives containing C++ object files must be created using
- # "CC -ar", where "CC" is the IRIX C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
- ;;
- *)
- if test "$GXX" = yes; then
- if test "$with_gnu_ld" = no; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
- fi
- fi
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
- ;;
- esac
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
- ;;
- linux*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-
- # Archives containing C++ object files must be created using
- # "CC -Bstatic", where "CC" is the KAI C++ compiler.
- _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
- ;;
- icpc*)
- # Intel C++
- with_gnu_ld=yes
- # version 8.0 and above of icpc choke on multiply defined symbols
- # if we add $predep_objects and $postdep_objects, however 7.1 and
- # earlier do not add the objects themselves.
- case `$CC -V 2>&1` in
- *"Version 7."*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- *) # Version 8.0 or newer
- tmp_idyn=
- case $host_cpu in
- ia64*) tmp_idyn=' -i_dynamic';;
- esac
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- esac
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
- ;;
- pgCC*)
- # Portland Group C++ compiler
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- ;;
- cxx*)
- # Compaq C++
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
-
- runpath_var=LD_RUN_PATH
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- esac
- ;;
- lynxos*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- m88k*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- mvs*)
- case $cc_basename in
- cxx*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
- wlarc=
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- fi
- # Workaround some broken pre-1.5 toolchains
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
- ;;
- openbsd2*)
- # C++ shared libraries are fairly broken
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- openbsd*)
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- fi
- output_verbose_link_cmd='echo'
- ;;
- osf3*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Archives containing C++ object files must be created using
- # "CC -Bstatic", where "CC" is the KAI C++ compiler.
- _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
-
- ;;
- RCC*)
- # Rational C++ 2.4.1
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- cxx*)
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
-
- else
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
- osf4* | osf5*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Archives containing C++ object files must be created using
- # the KAI C++ compiler.
- _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
- ;;
- RCC*)
- # Rational C++ 2.4.1
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- cxx*)
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
- echo "-hidden">> $lib.exp~
- $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
- $rm $lib.exp'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
-
- else
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
- psos*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- lcc*)
- # Lucid
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
- solaris*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
- _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- # The C++ compiler is used as linker so we must use $wl
- # flag to pass the commands to the underlying system
- # linker. We must also pass each convience library through
- # to the system linker between allextract/defaultextract.
- # The C++ compiler will combine linker options so we
- # cannot just pass the convience library names through
- # without $wl.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
- ;;
- esac
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
-
- output_verbose_link_cmd='echo'
-
- # Archives containing C++ object files must be created using
- # "CC -xar", where "CC" is the Sun C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
- ;;
- gcx*)
- # Green Hills C++ Compiler
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
-
- # The C++ compiler must be used to create the archive.
- _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
- ;;
- *)
- # GNU C++ compiler with Solaris linker
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
- if $CC --version | grep -v '^2\.7' > /dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
- else
- # g++ 2.7 appears to require `-G' NOT `-shared' on this
- # platform.
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
- fi
-
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
- fi
- ;;
- esac
- ;;
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
- _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- # For security reasons, it is highly recommended that you always
- # use absolute paths for naming shared libraries, and exclude the
- # DT_RUNPATH tag from executables and libraries. But doing so
- # requires that you compile everything twice, which is a pain.
- # So that behaviour is only enabled if SCOABSPATH is set to a
- # non-empty value in the environment. Most likely only useful for
- # creating official distributions of packages.
- # This is a hack until libtool officially supports absolute path
- # names for shared libraries.
- _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- ;;
- vxworks*)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
-esac
-AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
-test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
-
-_LT_AC_TAGVAR(GCC, $1)="$GXX"
-_LT_AC_TAGVAR(LD, $1)="$LD"
-
-AC_LIBTOOL_POSTDEP_PREDEP($1)
-AC_LIBTOOL_PROG_COMPILER_PIC($1)
-AC_LIBTOOL_PROG_CC_C_O($1)
-AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
-AC_LIBTOOL_PROG_LD_SHLIBS($1)
-AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
-AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
-
-AC_LIBTOOL_CONFIG($1)
-
-AC_LANG_POP
-CC=$lt_save_CC
-LDCXX=$LD
-LD=$lt_save_LD
-GCC=$lt_save_GCC
-with_gnu_ldcxx=$with_gnu_ld
-with_gnu_ld=$lt_save_with_gnu_ld
-lt_cv_path_LDCXX=$lt_cv_path_LD
-lt_cv_path_LD=$lt_save_path_LD
-lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
-lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
-])# AC_LIBTOOL_LANG_CXX_CONFIG
-
-# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
-# ------------------------------------
-# Figure out "hidden" library dependencies from verbose
-# compiler output when linking a shared library.
-# Parse the compiler output and extract the necessary
-# objects, libraries and library flags.
-AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
-dnl we can't use the lt_simple_compile_test_code here,
-dnl because it contains code intended for an executable,
-dnl not a library. It's possible we should let each
-dnl tag define a new lt_????_link_test_code variable,
-dnl but it's only used here...
-ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
-int a;
-void foo (void) { a = 0; }
-EOF
-],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
-class Foo
-{
-public:
- Foo (void) { a = 0; }
-private:
- int a;
-};
-EOF
-],[$1],[F77],[cat > conftest.$ac_ext <<EOF
- subroutine foo
- implicit none
- integer*4 a
- a=0
- return
- end
-EOF
-],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
-public class foo {
- private int a;
- public void bar (void) {
- a = 0;
- }
-};
-EOF
-])
-dnl Parse the compiler output and extract the necessary
-dnl objects, libraries and library flags.
-if AC_TRY_EVAL(ac_compile); then
- # Parse the compiler output and extract the necessary
- # objects, libraries and library flags.
-
- # Sentinel used to keep track of whether or not we are before
- # the conftest object file.
- pre_test_object_deps_done=no
-
- # The `*' in the case matches for architectures that use `case' in
- # $output_verbose_cmd can trigger glob expansion during the loop
- # eval without this substitution.
- output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
-
- for p in `eval $output_verbose_link_cmd`; do
- case $p in
-
- -L* | -R* | -l*)
- # Some compilers place space between "-{L,R}" and the path.
- # Remove the space.
- if test $p = "-L" \
- || test $p = "-R"; then
- prev=$p
- continue
- else
- prev=
- fi
-
- if test "$pre_test_object_deps_done" = no; then
- case $p in
- -L* | -R*)
- # Internal compiler library paths should come after those
- # provided the user. The postdeps already come after the
- # user supplied libs so there is no need to process them.
- if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
- _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
- else
- _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
- fi
- ;;
- # The "-l" case would never come before the object being
- # linked, so don't bother handling this case.
- esac
- else
- if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
- _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
- else
- _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
- fi
- fi
- ;;
-
- *.$objext)
- # This assumes that the test object file only shows up
- # once in the compiler output.
- if test "$p" = "conftest.$objext"; then
- pre_test_object_deps_done=yes
- continue
- fi
-
- if test "$pre_test_object_deps_done" = no; then
- if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
- _LT_AC_TAGVAR(predep_objects, $1)="$p"
- else
- _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
- fi
- else
- if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
- _LT_AC_TAGVAR(postdep_objects, $1)="$p"
- else
- _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
- fi
- fi
- ;;
-
- *) ;; # Ignore the rest.
-
- esac
- done
-
- # Clean up.
- rm -f a.out a.exe
-else
- echo "libtool.m4: error: problem compiling $1 test program"
-fi
-
-$rm -f confest.$objext
-
-# PORTME: override above test on systems where it is broken
-ifelse([$1],[CXX],
-[case $host_os in
-interix3*)
- # Interix 3.5 installs completely hosed .la files for C++, so rather than
- # hack all around it, let's just trust "g++" to DTRT.
- _LT_AC_TAGVAR(predep_objects,$1)=
- _LT_AC_TAGVAR(postdep_objects,$1)=
- _LT_AC_TAGVAR(postdeps,$1)=
- ;;
-
-solaris*)
- case $cc_basename in
- CC*)
- # Adding this requires a known-good setup of shared libraries for
- # Sun compiler versions before 5.6, else PIC objects from an old
- # archive will be linked into the output, leading to subtle bugs.
- _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun'
- ;;
- esac
- ;;
-esac
-])
-
-case " $_LT_AC_TAGVAR(postdeps, $1) " in
-*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
-esac
-])# AC_LIBTOOL_POSTDEP_PREDEP
-
-# AC_LIBTOOL_LANG_F77_CONFIG
-# --------------------------
-# Ensure that the configuration vars for the C compiler are
-# suitably defined. Those variables are subsequently used by
-# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
-AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
-AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
-[AC_REQUIRE([AC_PROG_F77])
-AC_LANG_PUSH(Fortran 77)
-
-_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
-_LT_AC_TAGVAR(allow_undefined_flag, $1)=
-_LT_AC_TAGVAR(always_export_symbols, $1)=no
-_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
-_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
-_LT_AC_TAGVAR(hardcode_direct, $1)=no
-_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
-_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
-_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
-_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
-_LT_AC_TAGVAR(hardcode_automatic, $1)=no
-_LT_AC_TAGVAR(module_cmds, $1)=
-_LT_AC_TAGVAR(module_expsym_cmds, $1)=
-_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
-_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-_LT_AC_TAGVAR(no_undefined_flag, $1)=
-_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
-_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
-
-# Source file extension for f77 test sources.
-ac_ext=f
-
-# Object file extension for compiled f77 test sources.
-objext=o
-_LT_AC_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code=" subroutine t\n return\n end\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code=" program t\n end\n"
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_AC_SYS_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-CC=${F77-"f77"}
-compiler=$CC
-_LT_AC_TAGVAR(compiler, $1)=$CC
-_LT_CC_BASENAME([$compiler])
-
-AC_MSG_CHECKING([if libtool supports shared libraries])
-AC_MSG_RESULT([$can_build_shared])
-
-AC_MSG_CHECKING([whether to build shared libraries])
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case $host_os in
-aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-aix4* | aix5*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
-esac
-AC_MSG_RESULT([$enable_shared])
-
-AC_MSG_CHECKING([whether to build static libraries])
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-AC_MSG_RESULT([$enable_static])
-
-_LT_AC_TAGVAR(GCC, $1)="$G77"
-_LT_AC_TAGVAR(LD, $1)="$LD"
-
-AC_LIBTOOL_PROG_COMPILER_PIC($1)
-AC_LIBTOOL_PROG_CC_C_O($1)
-AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
-AC_LIBTOOL_PROG_LD_SHLIBS($1)
-AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
-AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
-
-AC_LIBTOOL_CONFIG($1)
-
-AC_LANG_POP
-CC="$lt_save_CC"
-])# AC_LIBTOOL_LANG_F77_CONFIG
-
-
-# AC_LIBTOOL_LANG_GCJ_CONFIG
-# --------------------------
-# Ensure that the configuration vars for the C compiler are
-# suitably defined. Those variables are subsequently used by
-# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
-AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
-AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
-[AC_LANG_SAVE
-
-# Source file extension for Java test sources.
-ac_ext=java
-
-# Object file extension for compiled Java test sources.
-objext=o
-_LT_AC_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="class foo {}\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n'
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_AC_SYS_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-CC=${GCJ-"gcj"}
-compiler=$CC
-_LT_AC_TAGVAR(compiler, $1)=$CC
-_LT_CC_BASENAME([$compiler])
-
-# GCJ did not exist at the time GCC didn't implicitly link libc in.
-_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
-
-_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
-
-AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
-AC_LIBTOOL_PROG_COMPILER_PIC($1)
-AC_LIBTOOL_PROG_CC_C_O($1)
-AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
-AC_LIBTOOL_PROG_LD_SHLIBS($1)
-AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
-AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
-
-AC_LIBTOOL_CONFIG($1)
-
-AC_LANG_RESTORE
-CC="$lt_save_CC"
-])# AC_LIBTOOL_LANG_GCJ_CONFIG
-
-
-# AC_LIBTOOL_LANG_RC_CONFIG
-# -------------------------
-# Ensure that the configuration vars for the Windows resource compiler are
-# suitably defined. Those variables are subsequently used by
-# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
-AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
-AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
-[AC_LANG_SAVE
-
-# Source file extension for RC test sources.
-ac_ext=rc
-
-# Object file extension for compiled RC test sources.
-objext=o
-_LT_AC_TAGVAR(objext, $1)=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
-
-# Code to be used in simple link tests
-lt_simple_link_test_code="$lt_simple_compile_test_code"
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-_LT_AC_SYS_COMPILER
-
-# save warnings/boilerplate of simple test code
-_LT_COMPILER_BOILERPLATE
-_LT_LINKER_BOILERPLATE
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-CC=${RC-"windres"}
-compiler=$CC
-_LT_AC_TAGVAR(compiler, $1)=$CC
-_LT_CC_BASENAME([$compiler])
-_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
-
-AC_LIBTOOL_CONFIG($1)
-
-AC_LANG_RESTORE
-CC="$lt_save_CC"
-])# AC_LIBTOOL_LANG_RC_CONFIG
-
-
-# AC_LIBTOOL_CONFIG([TAGNAME])
-# ----------------------------
-# If TAGNAME is not passed, then create an initial libtool script
-# with a default configuration from the untagged config vars. Otherwise
-# add code to config.status for appending the configuration named by
-# TAGNAME from the matching tagged config vars.
-AC_DEFUN([AC_LIBTOOL_CONFIG],
-[# The else clause should only fire when bootstrapping the
-# libtool distribution, otherwise you forgot to ship ltmain.sh
-# with your package, and you will get complaints that there are
-# no rules to generate ltmain.sh.
-if test -f "$ltmain"; then
- # See if we are running on zsh, and set the options which allow our commands through
- # without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
- # Now quote all the things that may contain metacharacters while being
- # careful not to overquote the AC_SUBSTed values. We take copies of the
- # variables and quote the copies for generation of the libtool script.
- for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
- SED SHELL STRIP \
- libname_spec library_names_spec soname_spec extract_expsyms_cmds \
- old_striplib striplib file_magic_cmd finish_cmds finish_eval \
- deplibs_check_method reload_flag reload_cmds need_locks \
- lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
- lt_cv_sys_global_symbol_to_c_name_address \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- old_postinstall_cmds old_postuninstall_cmds \
- _LT_AC_TAGVAR(compiler, $1) \
- _LT_AC_TAGVAR(CC, $1) \
- _LT_AC_TAGVAR(LD, $1) \
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
- _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
- _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
- _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
- _LT_AC_TAGVAR(old_archive_cmds, $1) \
- _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
- _LT_AC_TAGVAR(predep_objects, $1) \
- _LT_AC_TAGVAR(postdep_objects, $1) \
- _LT_AC_TAGVAR(predeps, $1) \
- _LT_AC_TAGVAR(postdeps, $1) \
- _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
- _LT_AC_TAGVAR(archive_cmds, $1) \
- _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
- _LT_AC_TAGVAR(postinstall_cmds, $1) \
- _LT_AC_TAGVAR(postuninstall_cmds, $1) \
- _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
- _LT_AC_TAGVAR(allow_undefined_flag, $1) \
- _LT_AC_TAGVAR(no_undefined_flag, $1) \
- _LT_AC_TAGVAR(export_symbols_cmds, $1) \
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
- _LT_AC_TAGVAR(hardcode_automatic, $1) \
- _LT_AC_TAGVAR(module_cmds, $1) \
- _LT_AC_TAGVAR(module_expsym_cmds, $1) \
- _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
- _LT_AC_TAGVAR(exclude_expsyms, $1) \
- _LT_AC_TAGVAR(include_expsyms, $1); do
-
- case $var in
- _LT_AC_TAGVAR(old_archive_cmds, $1) | \
- _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
- _LT_AC_TAGVAR(archive_cmds, $1) | \
- _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
- _LT_AC_TAGVAR(module_cmds, $1) | \
- _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
- _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
- _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
- extract_expsyms_cmds | reload_cmds | finish_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case $lt_echo in
- *'\[$]0 --fallback-echo"')
- lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
- ;;
- esac
-
-ifelse([$1], [],
- [cfgfile="${ofile}T"
- trap "$rm \"$cfgfile\"; exit 1" 1 2 15
- $rm -f "$cfgfile"
- AC_MSG_NOTICE([creating $ofile])],
- [cfgfile="$ofile"])
-
- cat <<__EOF__ >> "$cfgfile"
-ifelse([$1], [],
-[#! $SHELL
-
-# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
-# Free Software Foundation, Inc.
-#
-# This file is part of GNU Libtool:
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# A sed program that does not truncate output.
-SED=$lt_SED
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="$SED -e 1s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-# The names of the tagged configurations supported by this script.
-available_tags=
-
-# ### BEGIN LIBTOOL CONFIG],
-[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
-
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# An echo program that does not interpret backslashes.
-echo=$lt_echo
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A C compiler.
-LTCC=$lt_LTCC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_LTCFLAGS
-
-# A language-specific compiler.
-CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
-
-# Is the compiler the GNU C compiler?
-with_gcc=$_LT_AC_TAGVAR(GCC, $1)
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# The linker used to build libraries.
-LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
-
-# Whether we need hard or soft links.
-LN_S=$lt_LN_S
-
-# A BSD-compatible nm program.
-NM=$lt_NM
-
-# A symbol stripping program
-STRIP=$lt_STRIP
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=$MAGIC_CMD
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
-
-# Object file suffix (normally "o").
-objext="$ac_objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='$shrext_cmds'
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
-pic_mode=$pic_mode
-
-# What is the maximum length of a command?
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$lt_RANLIB
-old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
-
-# Commands used to build and install a shared archive.
-archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
-archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
-postinstall_cmds=$lt_postinstall_cmds
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
-module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$lt_file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$lt_finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
-
-# If ld is used when linking, flag to hardcode \$libdir into
-# a binary during linking. This must work even if \$libdir does
-# not exist.
-hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
-
-# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
-
-# Set to yes if building a shared library automatically hardcodes DIR into the library
-# and all subsequent libraries and executables linked against it.
-hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="$variables_saved_for_relink"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
-
-# Symbols that must always be exported.
-include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
-
-ifelse([$1],[],
-[# ### END LIBTOOL CONFIG],
-[# ### END LIBTOOL TAG CONFIG: $tagname])
-
-__EOF__
-
-ifelse([$1],[], [
- case $host_os in
- aix3*)
- cat <<\EOF >> "$cfgfile"
-
-# AIX sometimes has problems with the GCC collect2 program. For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
-fi
-EOF
- ;;
- esac
-
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
- sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
-
- mv -f "$cfgfile" "$ofile" || \
- (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
- chmod +x "$ofile"
-])
-else
- # If there is no Makefile yet, we rely on a make rule to execute
- # `config.status --recheck' to rerun these tests and create the
- # libtool script then.
- ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
- if test -f "$ltmain_in"; then
- test -f Makefile && make "$ltmain"
- fi
-fi
-])# AC_LIBTOOL_CONFIG
-
-
-# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
-# -------------------------------------------
-AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
-[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
-
-_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
-
-if test "$GCC" = yes; then
- _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
-
- AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
- lt_cv_prog_compiler_rtti_exceptions,
- [-fno-rtti -fno-exceptions], [],
- [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
-fi
-])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
-
-
-# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
-# ---------------------------------
-AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
-[AC_REQUIRE([AC_CANONICAL_HOST])
-AC_REQUIRE([AC_PROG_NM])
-AC_REQUIRE([AC_OBJEXT])
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-AC_MSG_CHECKING([command to parse $NM output from $compiler object])
-AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
-[
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[[BCDEGRST]]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
-
-# Transform an extracted symbol line into a proper C declaration
-lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
-
-# Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
-
-# Define system-specific variables.
-case $host_os in
-aix*)
- symcode='[[BCDT]]'
- ;;
-cygwin* | mingw* | pw32*)
- symcode='[[ABCDGISTW]]'
- ;;
-hpux*) # Its linker distinguishes data from code symbols
- if test "$host_cpu" = ia64; then
- symcode='[[ABCDEGRST]]'
- fi
- lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
- lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
- ;;
-linux*)
- if test "$host_cpu" = ia64; then
- symcode='[[ABCDGIRSTW]]'
- lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
- lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
- fi
- ;;
-irix* | nonstopux*)
- symcode='[[BCDEGRST]]'
- ;;
-osf*)
- symcode='[[BCDEGQRST]]'
- ;;
-solaris*)
- symcode='[[BDRT]]'
- ;;
-sco3.2v5*)
- symcode='[[DT]]'
- ;;
-sysv4.2uw2*)
- symcode='[[DT]]'
- ;;
-sysv5* | sco5v6* | unixware* | OpenUNIX*)
- symcode='[[ABDT]]'
- ;;
-sysv4)
- symcode='[[DFNSTU]]'
- ;;
-esac
-
-# Handle CRLF in mingw tool chain
-opt_cr=
-case $build_os in
-mingw*)
- opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
- ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-case `$NM -V 2>&1` in
-*GNU* | *'with BFD'*)
- symcode='[[ABCDGIRSTW]]' ;;
-esac
-
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
-
- # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
- symxfrm="\\1 $ac_symprfx\\2 \\2"
-
- # Write the raw and C identifiers.
- lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
-
- # Check to see that the pipe works correctly.
- pipe_works=no
-
- rm -f conftest*
- cat > conftest.$ac_ext <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-int main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
-
- if AC_TRY_EVAL(ac_compile); then
- # Now try to grab the symbols.
- nlist=conftest.nm
- if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
- # Try sorting and uniquifying the output.
- if sort "$nlist" | uniq > "$nlist"T; then
- mv -f "$nlist"T "$nlist"
- else
- rm -f "$nlist"T
- fi
-
- # Make sure that we snagged all the symbols we need.
- if grep ' nm_test_var$' "$nlist" >/dev/null; then
- if grep ' nm_test_func$' "$nlist" >/dev/null; then
- cat <<EOF > conftest.$ac_ext
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
- # Now generate the symbol file.
- eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
-
- cat <<EOF >> conftest.$ac_ext
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- lt_ptr_t address;
-}
-lt_preloaded_symbols[[]] =
-{
-EOF
- $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
- cat <<\EOF >> conftest.$ac_ext
- {0, (lt_ptr_t) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
- # Now try linking the two files.
- mv conftest.$ac_objext conftstm.$ac_objext
- lt_save_LIBS="$LIBS"
- lt_save_CFLAGS="$CFLAGS"
- LIBS="conftstm.$ac_objext"
- CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
- if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
- pipe_works=yes
- fi
- LIBS="$lt_save_LIBS"
- CFLAGS="$lt_save_CFLAGS"
- else
- echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
- fi
- else
- echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
- cat conftest.$ac_ext >&5
- fi
- rm -f conftest* conftst*
-
- # Do not use the global_symbol_pipe unless it works.
- if test "$pipe_works" = yes; then
- break
- else
- lt_cv_sys_global_symbol_pipe=
- fi
-done
-])
-if test -z "$lt_cv_sys_global_symbol_pipe"; then
- lt_cv_sys_global_symbol_to_cdecl=
-fi
-if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
- AC_MSG_RESULT(failed)
-else
- AC_MSG_RESULT(ok)
-fi
-]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
-
-
-# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
-# ---------------------------------------
-AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
-[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
-_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
-_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
-
-AC_MSG_CHECKING([for $compiler option to produce PIC])
- ifelse([$1],[CXX],[
- # C++ specific cases for pic, static, wl, etc.
- if test "$GXX" = yes; then
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
- ;;
- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
- mingw* | os2* | pw32*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
- ;;
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
- ;;
- *djgpp*)
- # DJGPP does not support shared libraries at all
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
- ;;
- interix3*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
- fi
- ;;
- hpux*)
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- ;;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- ;;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- else
- case $host_os in
- aix4* | aix5*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- else
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- chorus*)
- case $cc_basename in
- cxch68*)
- # Green Hills C++ Compiler
- # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
- ;;
- esac
- ;;
- darwin*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- case $cc_basename in
- xlc*)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- ;;
- esac
- ;;
- dgux*)
- case $cc_basename in
- ec++*)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- freebsd* | kfreebsd*-gnu | dragonfly*)
- # FreeBSD uses GNU C++
- ;;
- hpux9* | hpux10* | hpux11*)
- case $cc_basename in
- CC*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- if test "$host_cpu" != ia64; then
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- fi
- ;;
- aCC*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- ;;
- esac
- ;;
- *)
- ;;
- esac
- ;;
- interix*)
- # This is c89, which is MS Visual C++ (no shared libs)
- # Anyone wants to do a port?
- ;;
- irix5* | irix6* | nonstopux*)
- case $cc_basename in
- CC*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- # CC pic flag -KPIC is the default.
- ;;
- *)
- ;;
- esac
- ;;
- linux*)
- case $cc_basename in
- KCC*)
- # KAI C++ Compiler
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- icpc* | ecpc*)
- # Intel C++
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- pgCC*)
- # Portland Group C++ compiler.
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- cxx*)
- # Compaq C++
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- *)
- ;;
- esac
- ;;
- lynxos*)
- ;;
- m88k*)
- ;;
- mvs*)
- case $cc_basename in
- cxx*)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
- ;;
- *)
- ;;
- esac
- ;;
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- ;;
- osf3* | osf4* | osf5*)
- case $cc_basename in
- KCC*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
- ;;
- RCC*)
- # Rational C++ 2.4.1
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- cxx*)
- # Digital/Compaq C++
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- *)
- ;;
- esac
- ;;
- psos*)
- ;;
- solaris*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- ;;
- gcx*)
- # Green Hills C++ Compiler
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
- ;;
- *)
- ;;
- esac
- ;;
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- lcc*)
- # Lucid
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- ;;
- *)
- ;;
- esac
- ;;
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- case $cc_basename in
- CC*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- esac
- ;;
- vxworks*)
- ;;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
- esac
- fi
-],
-[
- if test "$GCC" = yes; then
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
- ;;
-
- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
- ;;
-
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
- ;;
-
- interix3*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
-
- msdosdjgpp*)
- # Just because we use GCC doesn't mean we suddenly get shared libraries
- # on systems that don't support them.
- _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- enable_shared=no
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
- fi
- ;;
-
- hpux*)
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- ;;
-
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
- ;;
- esac
- else
- # PORTME Check for flag to pass linker flags through the system compiler.
- case $host_os in
- aix*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- else
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- darwin*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- case $cc_basename in
- xlc*)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- ;;
- esac
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
- ;;
-
- hpux9* | hpux10* | hpux11*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
- ;;
- esac
- # Is there a better lt_prog_compiler_static that works with the bundled CC?
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
- ;;
-
- irix5* | irix6* | nonstopux*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # PIC (with -KPIC) is the default.
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- newsos6)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- linux*)
- case $cc_basename in
- icc* | ecc*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
- ;;
- pgcc* | pgf77* | pgf90* | pgf95*)
- # Portland Group compilers (*not* the Pentium gcc compiler,
- # which looks to be a dead project)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
- ccc*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # All Alpha code is PIC.
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
- esac
- ;;
-
- osf3* | osf4* | osf5*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- # All OSF/1 code is PIC.
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
- ;;
-
- solaris*)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- case $cc_basename in
- f77* | f90* | f95*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
- esac
- ;;
-
- sunos4*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec ;then
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- fi
- ;;
-
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- unicos*)
- _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
- _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
-
- uts4*)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
- _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
- ;;
-
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
- ;;
- esac
- fi
-])
-AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
- AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
- _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
- [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
- [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
- "" | " "*) ;;
- *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
- esac],
- [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
- _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
-fi
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
- ;;
- *)
- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
- ;;
-esac
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\"
-AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
- _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
- $lt_tmp_static_flag,
- [],
- [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
-])
-
-
-# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
-# ------------------------------------
-# See if the linker supports building shared libraries.
-AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
-[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
-ifelse([$1],[CXX],[
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- case $host_os in
- aix4* | aix5*)
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
- else
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
- fi
- ;;
- pw32*)
- _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
- ;;
- cygwin* | mingw*)
- _LT_AC_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'
- ;;
- kfreebsd*-gnu)
- _LT_AC_TAGVAR(link_all_deplibs, $1)=no
- ;;
- linux*)
- _LT_AC_TAGVAR(link_all_deplibs, $1)=no
- ;;
- *)
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- ;;
- esac
-],[
- runpath_var=
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=
- _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
- _LT_AC_TAGVAR(archive_cmds, $1)=
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
- _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
- _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
- _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
- _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
- _LT_AC_TAGVAR(hardcode_automatic, $1)=no
- _LT_AC_TAGVAR(module_cmds, $1)=
- _LT_AC_TAGVAR(module_expsym_cmds, $1)=
- _LT_AC_TAGVAR(always_export_symbols, $1)=no
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- # include_expsyms should be a list of space-separated symbols to be *always*
- # included in the symbol list
- _LT_AC_TAGVAR(include_expsyms, $1)=
- # exclude_expsyms can be an extended regexp of symbols to exclude
- # it will be wrapped by ` (' and `)$', so one must not match beginning or
- # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
- # as well as any symbol that contains `d'.
- _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
- # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
- # platforms (ab)use it in PIC code, but their linkers get confused if
- # the symbol is explicitly referenced. Since portable code cannot
- # rely on this symbol name, it's probably fine to never include it in
- # preloaded symbol tables.
- extract_expsyms_cmds=
- # Just being paranoid about ensuring that cc_basename is set.
- _LT_CC_BASENAME([$compiler])
- case $host_os in
- cygwin* | mingw* | pw32*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$GCC" != yes; then
- with_gnu_ld=no
- fi
- ;;
- interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
- with_gnu_ld=yes
- ;;
- openbsd*)
- with_gnu_ld=no
- ;;
- esac
-
- _LT_AC_TAGVAR(ld_shlibs, $1)=yes
- if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # Set some defaults for GNU ld with shared library support. These
- # are reset later if shared libraries are not supported. Putting them
- # here allows them to be overridden if necessary.
- runpath_var=LD_RUN_PATH
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- supports_anon_versioning=no
- case `$LD -v 2>/dev/null` in
- *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
- *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
- *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
- *\ 2.11.*) ;; # other 2.11 versions
- *) supports_anon_versioning=yes ;;
- esac
-
- # See if GNU ld supports shared libraries.
- case $host_os in
- aix3* | aix4* | aix5*)
- # On AIX/PPC, the GNU linker is very broken
- if test "$host_cpu" != ia64; then
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
- fi
- ;;
-
- amigaos*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
-
- # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
- # that the semantics of dynamic libraries on AmigaOS, at least up
- # to version 4, is to share data among multiple programs linked
- # with the same dynamic library. Since this doesn't match the
- # behavior of shared libraries on other platforms, we can't use
- # them.
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- beos*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- cygwin* | mingw* | pw32*)
- # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
- # as there is no search path for DLLs.
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_AC_TAGVAR(always_export_symbols, $1)=no
- _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
-
- if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- interix3*)
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
-
- linux*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- tmp_addflag=
- case $cc_basename,$host_cpu in
- pgcc*) # Portland Group C compiler
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag'
- ;;
- pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag -Mnomain' ;;
- ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
- tmp_addflag=' -i_dynamic' ;;
- efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
- tmp_addflag=' -i_dynamic -nofor_main' ;;
- ifc* | ifort*) # Intel Fortran compiler
- tmp_addflag=' -nofor_main' ;;
- esac
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
- if test $supports_anon_versioning = yes; then
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- $echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
- _LT_AC_TAGVAR(link_all_deplibs, $1)=no
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
- wlarc=
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- fi
- ;;
-
- solaris*)
- if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
- elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
- case `$LD -v 2>&1` in
- *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- ;;
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
- ;;
-
- sunos4*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- wlarc=
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- fi
- ;;
- esac
-
- if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then
- runpath_var=
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
- fi
- else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case $host_os in
- aix3*)
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_AC_TAGVAR(always_export_symbols, $1)=yes
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
- fi
- ;;
-
- aix4* | aix5*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
- else
- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
- fi
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
- for ld_flag in $LDFLAGS; do
- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
- aix_use_runtimelinking=yes
- break
- fi
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- _LT_AC_TAGVAR(archive_cmds, $1)=''
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
-
- if test "$GCC" = yes; then
- case $host_os in aix4.[[012]]|aix4.[[012]].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- else
- # We have old collect2
- _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- _LT_AC_TAGVAR(always_export_symbols, $1)=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
- # Determine the default libpath from the value encoded in an empty executable.
- _LT_AC_SYS_LIBPATH_AIX
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an empty executable.
- _LT_AC_SYS_LIBPATH_AIX
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- amigaos*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- # see comment about different semantics on the GNU ld section
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- bsdi[[45]]*)
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
- ;;
-
- cygwin* | mingw* | pw32*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
- # FIXME: Should let the user specify the lib program.
- _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
- _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
- _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
- ;;
-
- darwin* | rhapsody*)
- case $host_os in
- rhapsody* | darwin1.[[012]])
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
- ;;
- *) # Darwin 1.3 on
- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- else
- case ${MACOSX_DEPLOYMENT_TARGET} in
- 10.[[012]])
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- ;;
- 10.*)
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
- ;;
- esac
- fi
- ;;
- esac
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
- if test "$GCC" = yes ; then
- output_verbose_link_cmd='echo'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- case $cc_basename in
- xlc*)
- output_verbose_link_cmd='echo'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
- _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- ;;
- *)
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- fi
- ;;
-
- dgux*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- freebsd1*)
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd* | dragonfly*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- # GNU/kFreeBSD uses gcc -shared to do shared libraries.
- kfreebsd*-gnu)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_AC_TAGVAR(link_all_deplibs, $1)=no
- ;;
-
- hpux9*)
- if test "$GCC" = yes; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- fi
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- ;;
-
- hpux10*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
- fi
- if test "$with_gnu_ld" = no; then
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- fi
- ;;
-
- hpux11*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- case $host_cpu in
- hppa*64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- else
- case $host_cpu in
- hppa*64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- fi
- if test "$with_gnu_ld" = no; then
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
- *)
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- ;;
- esac
- fi
- ;;
-
- irix5* | irix6* | nonstopux*)
- if test "$GCC" = yes; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
- fi
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
- fi
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- newsos6)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- openbsd*)
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
- else
- case $host_os in
- openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- ;;
- *)
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
- ;;
- esac
- fi
- ;;
-
- os2*)
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
- _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
- _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$GCC" = yes; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- fi
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
- ;;
-
- osf4* | osf5*) # as osf3* with the addition of -msym flag
- if test "$GCC" = yes; then
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
- else
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
- $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
-
- # Both c and cxx compiler support -rpath directly
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
- fi
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
- ;;
-
- solaris*)
- _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
- if test "$GCC" = yes; then
- wlarc='${wl}'
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
- else
- wlarc=''
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
- fi
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- case $host_os in
- solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
- *)
- # The compiler driver will combine linker options so we
- # cannot just pass the convience library names through
- # without $wl, iff we do not link with $LD.
- # Luckily, gcc supports the same syntax we need for Sun Studio.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- case $wlarc in
- '')
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
- *)
- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
- esac ;;
- esac
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
- ;;
-
- sunos4*)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
- fi
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes
- _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- sysv4)
- case $host_vendor in
- sni)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
- ;;
- siemens)
- ## LD is ld it makes a PLAMLIB
- ## CC just makes a GrossModule.
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
- _LT_AC_TAGVAR(hardcode_direct, $1)=no
- ;;
- motorola)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
- ;;
- esac
- runpath_var='LD_RUN_PATH'
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- sysv4.3*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- _LT_AC_TAGVAR(ld_shlibs, $1)=yes
- fi
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*)
- _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
- _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
- _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- uts4*)
- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
- ;;
-
- *)
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
- esac
- fi
-])
-AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
-test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
-x|xyes)
- # Assume -lc should be added
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $_LT_AC_TAGVAR(archive_cmds, $1) in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- AC_MSG_CHECKING([whether -lc should be explicitly linked in])
- $rm conftest*
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
- pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=
- if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
- then
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
- else
- _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
- fi
- _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $rm conftest*
- AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
- ;;
- esac
- fi
- ;;
-esac
-])# AC_LIBTOOL_PROG_LD_SHLIBS
-
-
-# _LT_AC_FILE_LTDLL_C
-# -------------------
-# Be careful that the start marker always follows a newline.
-AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
-# /* ltdll.c starts here */
-# #define WIN32_LEAN_AND_MEAN
-# #include <windows.h>
-# #undef WIN32_LEAN_AND_MEAN
-# #include <stdio.h>
-#
-# #ifndef __CYGWIN__
-# # ifdef __CYGWIN32__
-# # define __CYGWIN__ __CYGWIN32__
-# # endif
-# #endif
-#
-# #ifdef __cplusplus
-# extern "C" {
-# #endif
-# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
-# #ifdef __cplusplus
-# }
-# #endif
-#
-# #ifdef __CYGWIN__
-# #include <cygwin/cygwin_dll.h>
-# DECLARE_CYGWIN_DLL( DllMain );
-# #endif
-# HINSTANCE __hDllInstance_base;
-#
-# BOOL APIENTRY
-# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
-# {
-# __hDllInstance_base = hInst;
-# return TRUE;
-# }
-# /* ltdll.c ends here */
-])# _LT_AC_FILE_LTDLL_C
-
-
-# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
-# ---------------------------------
-AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
-
-
-# old names
-AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
-AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
-AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
-AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
-AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
-AC_DEFUN([AM_PROG_LD], [AC_PROG_LD])
-AC_DEFUN([AM_PROG_NM], [AC_PROG_NM])
-
-# This is just to silence aclocal about the macro not being used
-ifelse([AC_DISABLE_FAST_INSTALL])
-
-AC_DEFUN([LT_AC_PROG_GCJ],
-[AC_CHECK_TOOL(GCJ, gcj, no)
- test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
- AC_SUBST(GCJFLAGS)
-])
-
-AC_DEFUN([LT_AC_PROG_RC],
-[AC_CHECK_TOOL(RC, windres, no)
-])
-
-# NOTE: This macro has been submitted for inclusion into #
-# GNU Autoconf as AC_PROG_SED. When it is available in #
-# a released version of Autoconf we should remove this #
-# macro and use it instead. #
-# LT_AC_PROG_SED
-# --------------
-# Check for a fully-functional sed program, that truncates
-# as few characters as possible. Prefer GNU sed if found.
-AC_DEFUN([LT_AC_PROG_SED],
-[AC_MSG_CHECKING([for a sed that does not truncate output])
-AC_CACHE_VAL(lt_cv_path_SED,
-[# Loop through the user's path and test for sed and gsed.
-# Then use that list of sed's as ones to test for truncation.
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for lt_ac_prog in sed gsed; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
- lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
- fi
- done
- done
-done
-lt_ac_max=0
-lt_ac_count=0
-# Add /usr/xpg4/bin/sed as it is typically found on Solaris
-# along with /bin/sed that truncates output.
-for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
- test ! -f $lt_ac_sed && continue
- cat /dev/null > conftest.in
- lt_ac_count=0
- echo $ECHO_N "0123456789$ECHO_C" >conftest.in
- # Check for GNU sed and select it if it is found.
- if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
- lt_cv_path_SED=$lt_ac_sed
- break
- fi
- while true; do
- cat conftest.in conftest.in >conftest.tmp
- mv conftest.tmp conftest.in
- cp conftest.in conftest.nl
- echo >>conftest.nl
- $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
- cmp -s conftest.out conftest.nl || break
- # 10000 chars as input seems more than enough
- test $lt_ac_count -gt 10 && break
- lt_ac_count=`expr $lt_ac_count + 1`
- if test $lt_ac_count -gt $lt_ac_max; then
- lt_ac_max=$lt_ac_count
- lt_cv_path_SED=$lt_ac_sed
- fi
- done
-done
-])
-SED=$lt_cv_path_SED
-AC_MSG_RESULT([$SED])
-])
-
-# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_AUTOMAKE_VERSION(VERSION)
-# ----------------------------
-# Automake X.Y traces this macro to ensure aclocal.m4 has been
-# generated from the m4 files accompanying Automake X.Y.
-AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
-
-# AM_SET_CURRENT_AUTOMAKE_VERSION
-# -------------------------------
-# Call AM_AUTOMAKE_VERSION so it can be traced.
-# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
-AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
- [AM_AUTOMAKE_VERSION([1.9.6])])
-
-# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
-# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
-# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
-#
-# Of course, Automake must honor this variable whenever it calls a
-# tool from the auxiliary directory. The problem is that $srcdir (and
-# therefore $ac_aux_dir as well) can be either absolute or relative,
-# depending on how configure is run. This is pretty annoying, since
-# it makes $ac_aux_dir quite unusable in subdirectories: in the top
-# source directory, any form will work fine, but in subdirectories a
-# relative path needs to be adjusted first.
-#
-# $ac_aux_dir/missing
-# fails when called from a subdirectory if $ac_aux_dir is relative
-# $top_srcdir/$ac_aux_dir/missing
-# fails if $ac_aux_dir is absolute,
-# fails when called from a subdirectory in a VPATH build with
-# a relative $ac_aux_dir
-#
-# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
-# are both prefixed by $srcdir. In an in-source build this is usually
-# harmless because $srcdir is `.', but things will broke when you
-# start a VPATH build or use an absolute $srcdir.
-#
-# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
-# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
-# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
-# and then we would define $MISSING as
-# MISSING="\${SHELL} $am_aux_dir/missing"
-# This will work as long as MISSING is not called from configure, because
-# unfortunately $(top_srcdir) has no meaning in configure.
-# However there are other variables, like CC, which are often used in
-# configure, and could therefore not use this "fixed" $ac_aux_dir.
-#
-# Another solution, used here, is to always expand $ac_aux_dir to an
-# absolute PATH. The drawback is that using absolute paths prevent a
-# configured tree to be moved without reconfiguration.
-
-AC_DEFUN([AM_AUX_DIR_EXPAND],
-[dnl Rely on autoconf to set up CDPATH properly.
-AC_PREREQ([2.50])dnl
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
-])
-
-# AM_CONDITIONAL -*- Autoconf -*-
-
-# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 7
-
-# AM_CONDITIONAL(NAME, SHELL-CONDITION)
-# -------------------------------------
-# Define a conditional.
-AC_DEFUN([AM_CONDITIONAL],
-[AC_PREREQ(2.52)dnl
- ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
- [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
-AC_SUBST([$1_TRUE])
-AC_SUBST([$1_FALSE])
-if $2; then
- $1_TRUE=
- $1_FALSE='#'
-else
- $1_TRUE='#'
- $1_FALSE=
-fi
-AC_CONFIG_COMMANDS_PRE(
-[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
- AC_MSG_ERROR([[conditional "$1" was never defined.
-Usually this means the macro was only invoked conditionally.]])
-fi])])
-
-
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 8
-
-# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
-# written in clear, in which case automake, when reading aclocal.m4,
-# will think it sees a *use*, and therefore will trigger all it's
-# C support machinery. Also note that it means that autoscan, seeing
-# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
-
-
-# _AM_DEPENDENCIES(NAME)
-# ----------------------
-# See how the compiler implements dependency checking.
-# NAME is "CC", "CXX", "GCJ", or "OBJC".
-# We try a few techniques and use that to set a single cache variable.
-#
-# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
-# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
-# dependency, and given that the user is not expected to run this macro,
-# just rely on AC_PROG_CC.
-AC_DEFUN([_AM_DEPENDENCIES],
-[AC_REQUIRE([AM_SET_DEPDIR])dnl
-AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
-AC_REQUIRE([AM_MAKE_INCLUDE])dnl
-AC_REQUIRE([AM_DEP_TRACK])dnl
-
-ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
- [$1], CXX, [depcc="$CXX" am_compiler_list=],
- [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
- [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
- [depcc="$$1" am_compiler_list=])
-
-AC_CACHE_CHECK([dependency style of $depcc],
- [am_cv_$1_dependencies_compiler_type],
-[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
- # We make a subdir and do the tests there. Otherwise we can end up
- # making bogus files that we don't know about and never remove. For
- # instance it was reported that on HP-UX the gcc test will end up
- # making a dummy file named `D' -- because `-MD' means `put the output
- # in D'.
- mkdir conftest.dir
- # Copy depcomp to subdir because otherwise we won't find it if we're
- # using a relative directory.
- cp "$am_depcomp" conftest.dir
- cd conftest.dir
- # We will build objects and dependencies in a subdirectory because
- # it helps to detect inapplicable dependency modes. For instance
- # both Tru64's cc and ICC support -MD to output dependencies as a
- # side effect of compilation, but ICC will put the dependencies in
- # the current directory while Tru64 will put them in the object
- # directory.
- mkdir sub
-
- am_cv_$1_dependencies_compiler_type=none
- if test "$am_compiler_list" = ""; then
- am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
- fi
- for depmode in $am_compiler_list; do
- # Setup a source with many dependencies, because some compilers
- # like to wrap large dependency lists on column 80 (with \), and
- # we should not choose a depcomp mode which is confused by this.
- #
- # We need to recreate these files for each test, as the compiler may
- # overwrite some of them when testing with obscure command lines.
- # This happens at least with the AIX C compiler.
- : > sub/conftest.c
- for i in 1 2 3 4 5 6; do
- echo '#include "conftst'$i'.h"' >> sub/conftest.c
- # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
- # Solaris 8's {/usr,}/bin/sh.
- touch sub/conftst$i.h
- done
- echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
-
- case $depmode in
- nosideeffect)
- # after this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested
- if test "x$enable_dependency_tracking" = xyes; then
- continue
- else
- break
- fi
- ;;
- none) break ;;
- esac
- # We check with `-c' and `-o' for the sake of the "dashmstdout"
- # mode. It turns out that the SunPro C++ compiler does not properly
- # handle `-M -o', and we need to detect this.
- if depmode=$depmode \
- source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
- depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
- >/dev/null 2>conftest.err &&
- grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
- ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
- # icc doesn't choke on unknown options, it will just issue warnings
- # or remarks (even with -Werror). So we grep stderr for any message
- # that says an option was ignored or not supported.
- # When given -MP, icc 7.0 and 7.1 complain thusly:
- # icc: Command line warning: ignoring option '-M'; no argument required
- # The diagnosis changed in icc 8.0:
- # icc: Command line remark: option '-MP' not supported
- if (grep 'ignoring option' conftest.err ||
- grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
- am_cv_$1_dependencies_compiler_type=$depmode
- break
- fi
- fi
- done
-
- cd ..
- rm -rf conftest.dir
-else
- am_cv_$1_dependencies_compiler_type=none
-fi
-])
-AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
-AM_CONDITIONAL([am__fastdep$1], [
- test "x$enable_dependency_tracking" != xno \
- && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
-])
-
-
-# AM_SET_DEPDIR
-# -------------
-# Choose a directory name for dependency files.
-# This macro is AC_REQUIREd in _AM_DEPENDENCIES
-AC_DEFUN([AM_SET_DEPDIR],
-[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
-AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
-])
-
-
-# AM_DEP_TRACK
-# ------------
-AC_DEFUN([AM_DEP_TRACK],
-[AC_ARG_ENABLE(dependency-tracking,
-[ --disable-dependency-tracking speeds up one-time build
- --enable-dependency-tracking do not reject slow dependency extractors])
-if test "x$enable_dependency_tracking" != xno; then
- am_depcomp="$ac_aux_dir/depcomp"
- AMDEPBACKSLASH='\'
-fi
-AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
-AC_SUBST([AMDEPBACKSLASH])
-])
-
-# Generate code to set up dependency tracking. -*- Autoconf -*-
-
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-#serial 3
-
-# _AM_OUTPUT_DEPENDENCY_COMMANDS
-# ------------------------------
-AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
-[for mf in $CONFIG_FILES; do
- # Strip MF so we end up with the name of the file.
- mf=`echo "$mf" | sed -e 's/:.*$//'`
- # Check whether this is an Automake generated Makefile or not.
- # We used to match only the files named `Makefile.in', but
- # some people rename them; so instead we look at the file content.
- # Grep'ing the first line is not enough: some people post-process
- # each Makefile.in and add a new line on top of each file to say so.
- # So let's grep whole file.
- if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
- dirpart=`AS_DIRNAME("$mf")`
- else
- continue
- fi
- # Extract the definition of DEPDIR, am__include, and am__quote
- # from the Makefile without running `make'.
- DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
- test -z "$DEPDIR" && continue
- am__include=`sed -n 's/^am__include = //p' < "$mf"`
- test -z "am__include" && continue
- am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
- # When using ansi2knr, U may be empty or an underscore; expand it
- U=`sed -n 's/^U = //p' < "$mf"`
- # Find all dependency output files, they are included files with
- # $(DEPDIR) in their names. We invoke sed twice because it is the
- # simplest approach to changing $(DEPDIR) to its actual value in the
- # expansion.
- for file in `sed -n "
- s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
- # Make sure the directory exists.
- test -f "$dirpart/$file" && continue
- fdir=`AS_DIRNAME(["$file"])`
- AS_MKDIR_P([$dirpart/$fdir])
- # echo "creating $dirpart/$file"
- echo '# dummy' > "$dirpart/$file"
- done
-done
-])# _AM_OUTPUT_DEPENDENCY_COMMANDS
-
-
-# AM_OUTPUT_DEPENDENCY_COMMANDS
-# -----------------------------
-# This macro should only be invoked once -- use via AC_REQUIRE.
-#
-# This code is only required when automatic dependency tracking
-# is enabled. FIXME. This creates each `.P' file that we will
-# need in order to bootstrap the dependency handling code.
-AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
-[AC_CONFIG_COMMANDS([depfiles],
- [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
- [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
-])
-
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 8
-
-# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
-AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
-
-# Do all the work for Automake. -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 12
-
-# This macro actually does too much. Some checks are only needed if
-# your package does certain things. But this isn't really a big deal.
-
-# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
-# AM_INIT_AUTOMAKE([OPTIONS])
-# -----------------------------------------------
-# The call with PACKAGE and VERSION arguments is the old style
-# call (pre autoconf-2.50), which is being phased out. PACKAGE
-# and VERSION should now be passed to AC_INIT and removed from
-# the call to AM_INIT_AUTOMAKE.
-# We support both call styles for the transition. After
-# the next Automake release, Autoconf can make the AC_INIT
-# arguments mandatory, and then we can depend on a new Autoconf
-# release and drop the old call support.
-AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_PREREQ([2.58])dnl
-dnl Autoconf wants to disallow AM_ names. We explicitly allow
-dnl the ones we care about.
-m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
-AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
-AC_REQUIRE([AC_PROG_INSTALL])dnl
-# test to see if srcdir already configured
-if test "`cd $srcdir && pwd`" != "`pwd`" &&
- test -f $srcdir/config.status; then
- AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
-fi
-
-# test whether we have cygpath
-if test -z "$CYGPATH_W"; then
- if (cygpath --version) >/dev/null 2>/dev/null; then
- CYGPATH_W='cygpath -w'
- else
- CYGPATH_W=echo
- fi
-fi
-AC_SUBST([CYGPATH_W])
-
-# Define the identity of the package.
-dnl Distinguish between old-style and new-style calls.
-m4_ifval([$2],
-[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
- AC_SUBST([PACKAGE], [$1])dnl
- AC_SUBST([VERSION], [$2])],
-[_AM_SET_OPTIONS([$1])dnl
- AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
- AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
-
-_AM_IF_OPTION([no-define],,
-[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
- AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
-
-# Some tools Automake needs.
-AC_REQUIRE([AM_SANITY_CHECK])dnl
-AC_REQUIRE([AC_ARG_PROGRAM])dnl
-AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
-AM_MISSING_PROG(AUTOCONF, autoconf)
-AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
-AM_MISSING_PROG(AUTOHEADER, autoheader)
-AM_MISSING_PROG(MAKEINFO, makeinfo)
-AM_PROG_INSTALL_SH
-AM_PROG_INSTALL_STRIP
-AC_REQUIRE([AM_PROG_MKDIR_P])dnl
-# We need awk for the "check" target. The system "awk" is bad on
-# some platforms.
-AC_REQUIRE([AC_PROG_AWK])dnl
-AC_REQUIRE([AC_PROG_MAKE_SET])dnl
-AC_REQUIRE([AM_SET_LEADING_DOT])dnl
-_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
- [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
- [_AM_PROG_TAR([v7])])])
-_AM_IF_OPTION([no-dependencies],,
-[AC_PROVIDE_IFELSE([AC_PROG_CC],
- [_AM_DEPENDENCIES(CC)],
- [define([AC_PROG_CC],
- defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
-AC_PROVIDE_IFELSE([AC_PROG_CXX],
- [_AM_DEPENDENCIES(CXX)],
- [define([AC_PROG_CXX],
- defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
-])
-])
-
-
-# When config.status generates a header, we must update the stamp-h file.
-# This file resides in the same directory as the config header
-# that is generated. The stamp files are numbered to have different names.
-
-# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
-# loop where config.status creates the headers, so we can generate
-# our stamp files there.
-AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
-[# Compute $1's index in $config_headers.
-_am_stamp_count=1
-for _am_header in $config_headers :; do
- case $_am_header in
- $1 | $1:* )
- break ;;
- * )
- _am_stamp_count=`expr $_am_stamp_count + 1` ;;
- esac
-done
-echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
-
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_PROG_INSTALL_SH
-# ------------------
-# Define $install_sh.
-AC_DEFUN([AM_PROG_INSTALL_SH],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-install_sh=${install_sh-"$am_aux_dir/install-sh"}
-AC_SUBST(install_sh)])
-
-# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 2
-
-# Check whether the underlying file-system supports filenames
-# with a leading dot. For instance MS-DOS doesn't.
-AC_DEFUN([AM_SET_LEADING_DOT],
-[rm -rf .tst 2>/dev/null
-mkdir .tst 2>/dev/null
-if test -d .tst; then
- am__leading_dot=.
-else
- am__leading_dot=_
-fi
-rmdir .tst 2>/dev/null
-AC_SUBST([am__leading_dot])])
-
-# Check to see how 'make' treats includes. -*- Autoconf -*-
-
-# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 3
-
-# AM_MAKE_INCLUDE()
-# -----------------
-# Check to see how make treats includes.
-AC_DEFUN([AM_MAKE_INCLUDE],
-[am_make=${MAKE-make}
-cat > confinc << 'END'
-am__doit:
- @echo done
-.PHONY: am__doit
-END
-# If we don't find an include directive, just comment out the code.
-AC_MSG_CHECKING([for style of include used by $am_make])
-am__include="#"
-am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# We grep out `Entering directory' and `Leaving directory'
-# messages which can occur if `w' ends up in MAKEFLAGS.
-# In particular we don't look at `^make:' because GNU make might
-# be invoked under some other name (usually "gmake"), in which
-# case it prints its new name instead of `make'.
-if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
- am__include=include
- am__quote=
- _am_result=GNU
-fi
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
- echo '.include "confinc"' > confmf
- if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
- am__include=.include
- am__quote="\""
- _am_result=BSD
- fi
-fi
-AC_SUBST([am__include])
-AC_SUBST([am__quote])
-AC_MSG_RESULT([$_am_result])
-rm -f confinc confmf
-])
-
-# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-
-# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 4
-
-# AM_MISSING_PROG(NAME, PROGRAM)
-# ------------------------------
-AC_DEFUN([AM_MISSING_PROG],
-[AC_REQUIRE([AM_MISSING_HAS_RUN])
-$1=${$1-"${am_missing_run}$2"}
-AC_SUBST($1)])
-
-
-# AM_MISSING_HAS_RUN
-# ------------------
-# Define MISSING if not defined so far and test if it supports --run.
-# If it does, set am_missing_run to use it, otherwise, to nothing.
-AC_DEFUN([AM_MISSING_HAS_RUN],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
-# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
-else
- am_missing_run=
- AC_MSG_WARN([`missing' script is too old or missing])
-fi
-])
-
-# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_PROG_MKDIR_P
-# ---------------
-# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
-#
-# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
-# created by `make install' are always world readable, even if the
-# installer happens to have an overly restrictive umask (e.g. 077).
-# This was a mistake. There are at least two reasons why we must not
-# use `-m 0755':
-# - it causes special bits like SGID to be ignored,
-# - it may be too restrictive (some setups expect 775 directories).
-#
-# Do not use -m 0755 and let people choose whatever they expect by
-# setting umask.
-#
-# We cannot accept any implementation of `mkdir' that recognizes `-p'.
-# Some implementations (such as Solaris 8's) are not thread-safe: if a
-# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
-# concurrently, both version can detect that a/ is missing, but only
-# one can create it and the other will error out. Consequently we
-# restrict ourselves to GNU make (using the --version option ensures
-# this.)
-AC_DEFUN([AM_PROG_MKDIR_P],
-[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
- # We used to keeping the `.' as first argument, in order to
- # allow $(mkdir_p) to be used without argument. As in
- # $(mkdir_p) $(somedir)
- # where $(somedir) is conditionally defined. However this is wrong
- # for two reasons:
- # 1. if the package is installed by a user who cannot write `.'
- # make install will fail,
- # 2. the above comment should most certainly read
- # $(mkdir_p) $(DESTDIR)$(somedir)
- # so it does not work when $(somedir) is undefined and
- # $(DESTDIR) is not.
- # To support the latter case, we have to write
- # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
- # so the `.' trick is pointless.
- mkdir_p='mkdir -p --'
-else
- # On NextStep and OpenStep, the `mkdir' command does not
- # recognize any option. It will interpret all options as
- # directories to create, and then abort because `.' already
- # exists.
- for d in ./-p ./--version;
- do
- test -d $d && rmdir $d
- done
- # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
- if test -f "$ac_aux_dir/mkinstalldirs"; then
- mkdir_p='$(mkinstalldirs)'
- else
- mkdir_p='$(install_sh) -d'
- fi
-fi
-AC_SUBST([mkdir_p])])
-
-# Helper functions for option handling. -*- Autoconf -*-
-
-# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 3
-
-# _AM_MANGLE_OPTION(NAME)
-# -----------------------
-AC_DEFUN([_AM_MANGLE_OPTION],
-[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
-
-# _AM_SET_OPTION(NAME)
-# ------------------------------
-# Set option NAME. Presently that only means defining a flag for this option.
-AC_DEFUN([_AM_SET_OPTION],
-[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
-
-# _AM_SET_OPTIONS(OPTIONS)
-# ----------------------------------
-# OPTIONS is a space-separated list of Automake options.
-AC_DEFUN([_AM_SET_OPTIONS],
-[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
-
-# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
-# -------------------------------------------
-# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
-AC_DEFUN([_AM_IF_OPTION],
-[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
-
-# Check to make sure that the build environment is sane. -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 4
-
-# AM_SANITY_CHECK
-# ---------------
-AC_DEFUN([AM_SANITY_CHECK],
-[AC_MSG_CHECKING([whether build environment is sane])
-# Just in case
-sleep 1
-echo timestamp > conftest.file
-# Do `set' in a subshell so we don't clobber the current shell's
-# arguments. Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
- set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
- if test "$[*]" = "X"; then
- # -L didn't work.
- set X `ls -t $srcdir/configure conftest.file`
- fi
- rm -f conftest.file
- if test "$[*]" != "X $srcdir/configure conftest.file" \
- && test "$[*]" != "X conftest.file $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
-alias in your environment])
- fi
-
- test "$[2]" = conftest.file
- )
-then
- # Ok.
- :
-else
- AC_MSG_ERROR([newly created file is older than distributed files!
-Check your system clock])
-fi
-AC_MSG_RESULT(yes)])
-
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_PROG_INSTALL_STRIP
-# ---------------------
-# One issue with vendor `install' (even GNU) is that you can't
-# specify the program used to strip binaries. This is especially
-# annoying in cross-compiling environments, where the build's strip
-# is unlikely to handle the host's binaries.
-# Fortunately install-sh will honor a STRIPPROG variable, so we
-# always use install-sh in `make install-strip', and initialize
-# STRIPPROG with the value of the STRIP variable (set by the user).
-AC_DEFUN([AM_PROG_INSTALL_STRIP],
-[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
-# Installed binaries are usually stripped using `strip' when the user
-# run `make install-strip'. However `strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the `STRIP' environment variable to overrule this program.
-dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
-if test "$cross_compiling" != no; then
- AC_CHECK_TOOL([STRIP], [strip], :)
-fi
-INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
-AC_SUBST([INSTALL_STRIP_PROGRAM])])
-
-# Check how to create a tarball. -*- Autoconf -*-
-
-# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 2
-
-# _AM_PROG_TAR(FORMAT)
-# --------------------
-# Check how to create a tarball in format FORMAT.
-# FORMAT should be one of `v7', `ustar', or `pax'.
-#
-# Substitute a variable $(am__tar) that is a command
-# writing to stdout a FORMAT-tarball containing the directory
-# $tardir.
-# tardir=directory && $(am__tar) > result.tar
-#
-# Substitute a variable $(am__untar) that extract such
-# a tarball read from stdin.
-# $(am__untar) < result.tar
-AC_DEFUN([_AM_PROG_TAR],
-[# Always define AMTAR for backward compatibility.
-AM_MISSING_PROG([AMTAR], [tar])
-m4_if([$1], [v7],
- [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
- [m4_case([$1], [ustar],, [pax],,
- [m4_fatal([Unknown tar format])])
-AC_MSG_CHECKING([how to create a $1 tar archive])
-# Loop over all known methods to create a tar archive until one works.
-_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
-_am_tools=${am_cv_prog_tar_$1-$_am_tools}
-# Do not fold the above two line into one, because Tru64 sh and
-# Solaris sh will not grok spaces in the rhs of `-'.
-for _am_tool in $_am_tools
-do
- case $_am_tool in
- gnutar)
- for _am_tar in tar gnutar gtar;
- do
- AM_RUN_LOG([$_am_tar --version]) && break
- done
- am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
- am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
- am__untar="$_am_tar -xf -"
- ;;
- plaintar)
- # Must skip GNU tar: if it does not support --format= it doesn't create
- # ustar tarball either.
- (tar --version) >/dev/null 2>&1 && continue
- am__tar='tar chf - "$$tardir"'
- am__tar_='tar chf - "$tardir"'
- am__untar='tar xf -'
- ;;
- pax)
- am__tar='pax -L -x $1 -w "$$tardir"'
- am__tar_='pax -L -x $1 -w "$tardir"'
- am__untar='pax -r'
- ;;
- cpio)
- am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
- am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
- am__untar='cpio -i -H $1 -d'
- ;;
- none)
- am__tar=false
- am__tar_=false
- am__untar=false
- ;;
- esac
-
- # If the value was cached, stop now. We just wanted to have am__tar
- # and am__untar set.
- test -n "${am_cv_prog_tar_$1}" && break
-
- # tar/untar a dummy directory, and stop if the command works
- rm -rf conftest.dir
- mkdir conftest.dir
- echo GrepMe > conftest.dir/file
- AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
- rm -rf conftest.dir
- if test -s conftest.tar; then
- AM_RUN_LOG([$am__untar <conftest.tar])
- grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
- fi
-done
-rm -rf conftest.dir
-
-AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
-AC_MSG_RESULT([$am_cv_prog_tar_$1])])
-AC_SUBST([am__tar])
-AC_SUBST([am__untar])
-]) # _AM_PROG_TAR
-
-m4_include([talk/pkg.m4])
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755
index 6bd995a..0000000
--- a/autogen.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-
-(automake --version) < /dev/null > /dev/null 2>&1 || {
- echo;
- echo "You must have automake installed to compile libjingle";
- echo;
- exit;
-}
-
-(autoconf --version) < /dev/null > /dev/null 2>&1 || {
- echo;
- echo "You must have autoconf installed to compile libjingle";
- echo;
- exit;
-}
-
-(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
- echo;
- echo "You must have libtool installed to compile libjingle";
- echo;
- exit;
-}
-
-echo n | libtoolize --copy --force || exit;
-aclocal -I talk || exit;
-autoheader || exit;
-automake --add-missing --copy;
-autoconf || exit;
-automake || exit;
-./configure $@
diff --git a/config.guess b/config.guess
deleted file mode 100755
index ad5281e..0000000
--- a/config.guess
+++ /dev/null
@@ -1,1466 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-
-timestamp='2005-08-03'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner <per@bothner.com>.
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
-#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
- --version | -v )
- echo "$version" ; exit ;;
- --help | --h* | -h )
- echo "$usage"; exit ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help" >&2
- exit 1 ;;
- * )
- break ;;
- esac
-done
-
-if test $# != 0; then
- echo "$me: too many arguments$help" >&2
- exit 1
-fi
-
-trap 'exit 1' 1 2 15
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
- PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- *:NetBSD:*:*)
- # NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
- # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
- # switched to ELF, *-*-netbsd* would select the old
- # object file format. This provides both forward
- # compatibility and a consistent mechanism for selecting the
- # object file format.
- #
- # Note: NetBSD doesn't particularly care about the vendor
- # portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
- esac
- # The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep __ELF__ >/dev/null
- then
- # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
- # Return netbsd for either. FIX?
- os=netbsd
- else
- os=netbsdelf
- fi
- ;;
- *)
- os=netbsd
- ;;
- esac
- # The OS release
- # Debian GNU/NetBSD machines have a different userland, and
- # thus, need a distinct triplet. However, they do not need
- # kernel version information, so it can be replaced with a
- # suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
- Debian*)
- release='-gnu'
- ;;
- *)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
- ;;
- esac
- # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
- # contains redundant information, the shorter form:
- # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
- exit ;;
- *:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
- exit ;;
- *:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit ;;
- macppc:MirBSD:*:*)
- echo powerppc-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- *:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit ;;
- alpha:OSF1:*:*)
- case $UNAME_RELEASE in
- *4.0)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- ;;
- *5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
- ;;
- esac
- # According to Compaq, /usr/sbin/psrinfo has been available on
- # OSF/1 and Tru64 systems produced since 1995. I hope that
- # covers most systems running today. This code pipes the CPU
- # types through head -n 1, so we only detect the type of CPU 0.
- ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
- "EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
- "EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
- "LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
- "EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
- "EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
- "EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
- "EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
- "EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
- "EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
- "EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
- "EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
- "EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
- esac
- # A Pn.n version is a patched version.
- # A Vn.n version is a released version.
- # A Tn.n version is a released field test version.
- # A Xn.n version is an unreleased experimental baselevel.
- # 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
- Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit ;;
- *:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit ;;
- *:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit ;;
- *:OS/390:*:*)
- echo i370-ibm-openedition
- exit ;;
- *:z/VM:*:*)
- echo s390-ibm-zvmoe
- exit ;;
- *:OS400:*:*)
- echo powerpc-ibm-os400
- exit ;;
- arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit ;;
- arm:riscos:*:*|arm:RISCOS:*:*)
- echo arm-unknown-riscos
- exit ;;
- SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit ;;
- Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
- # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit ;;
- NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit ;;
- DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit ;;
- DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
- case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7; exit ;;
- esac ;;
- sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- i86pc:SunOS:5.*:*)
- echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:6*:*)
- # According to config.sub, this is the proper way to canonicalize
- # SunOS6. Hard to guess exactly what SunOS6 will be like, but
- # it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
- Series*|S4*)
- UNAME_RELEASE=`uname -v`
- ;;
- esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit ;;
- sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit ;;
- sun*:*:4.2BSD:*)
- UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
- case "`/bin/arch`" in
- sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
- ;;
- sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
- ;;
- esac
- exit ;;
- aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit ;;
- # The situation for MiNT is a little confusing. The machine name
- # can be virtually everything (everything which is not
- # "atarist" or "atariste" at least should have a processor
- # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
- # to the lowercase version "mint" (or "freemint"). Finally
- # the system name "TOS" denotes a system which is actually not
- # MiNT. But MiNT is downward compatible to TOS, so this should
- # be no problem.
- atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit ;;
- milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit ;;
- hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit ;;
- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit ;;
- m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit ;;
- powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit ;;
- RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit ;;
- RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit ;;
- VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit ;;
- 2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit ;;
- mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-#ifdef __cplusplus
-#include <stdio.h> /* for printf() prototype */
- int main (int argc, char *argv[]) {
-#else
- int main (argc, argv) int argc; char *argv[]; {
-#endif
- #if defined (host_mips) && defined (MIPSEB)
- #if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
- #endif
- #endif
- exit (-1);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
- exit ;;
- Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit ;;
- Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit ;;
- Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit ;;
- m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit ;;
- m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit ;;
- m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit ;;
- AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
- then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
- then
- echo m88k-dg-dgux${UNAME_RELEASE}
- else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
- fi
- else
- echo i586-dg-dgux${UNAME_RELEASE}
- fi
- exit ;;
- M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit ;;
- M88*:*:R3*:*)
- # Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit ;;
- XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit ;;
- Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit ;;
- *:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit ;;
- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
- i*86:AIX:*:*)
- echo i386-ibm-aix
- exit ;;
- ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:2:3)
- if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <sys/systemcfg.h>
-
- main()
- {
- if (!__power_pc())
- exit(1);
- puts("powerpc-ibm-aix3.2.5");
- exit(0);
- }
-EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
- then
- echo "$SYSTEM_NAME"
- else
- echo rs6000-ibm-aix3.2.5
- fi
- elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
- else
- echo rs6000-ibm-aix3.2
- fi
- exit ;;
- *:AIX:*:[45])
- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
- IBM_ARCH=rs6000
- else
- IBM_ARCH=powerpc
- fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit ;;
- *:AIX:*:*)
- echo rs6000-ibm-aix
- exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit ;;
- ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit ;; # report: romp-ibm BSD 4.3
- *:BOSX:*:*)
- echo rs6000-bull-bosx
- exit ;;
- DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit ;;
- 9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit ;;
- hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit ;;
- 9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
- fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
-
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
-
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
-EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
- test -z "$HP_ARCH" && HP_ARCH=hppa
- fi ;;
- esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
- then
- eval $set_cc_for_build
-
- # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
- # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
- # generating 64-bit code. GNU and HP use different nomenclature:
- #
- # $ CC_FOR_BUILD=cc ./config.guess
- # => hppa2.0w-hp-hpux11.23
- # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
- # => hppa64-hp-hpux11.23
-
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
- grep __LP64__ >/dev/null
- then
- HP_ARCH="hppa2.0w"
- else
- HP_ARCH="hppa64"
- fi
- fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit ;;
- ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit ;;
- 3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <unistd.h>
- int
- main ()
- {
- long cpu = sysconf (_SC_CPU_VERSION);
- /* The order matters, because CPU_IS_HP_MC68K erroneously returns
- true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
- results, however. */
- if (CPU_IS_PA_RISC (cpu))
- {
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
- default: puts ("hppa-hitachi-hiuxwe2"); break;
- }
- }
- else if (CPU_IS_HP_MC68K (cpu))
- puts ("m68k-hitachi-hiuxwe2");
- else puts ("unknown-hitachi-hiuxwe2");
- exit (0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
- echo unknown-hitachi-hiuxwe2
- exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit ;;
- 9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit ;;
- *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit ;;
- hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit ;;
- i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
- else
- echo ${UNAME_MACHINE}-unknown-osf1
- fi
- exit ;;
- parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit ;;
- C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit ;;
- C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit ;;
- C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit ;;
- C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit ;;
- CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
- | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
- -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- *:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit ;;
- F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- 5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit ;;
- i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit ;;
- sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit ;;
- *:FreeBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
- i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit ;;
- i*:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
- exit ;;
- i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit ;;
- x86:Interix*:[34]*)
- echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
- exit ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
- i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit ;;
- amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit ;;
- prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit ;;
- *:GNU:*:*)
- # the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit ;;
- *:GNU/*:*:*)
- # other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
- exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit ;;
- arm*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- cris:Linux:*:*)
- echo cris-axis-linux-gnu
- exit ;;
- crisv32:Linux:*:*)
- echo crisv32-axis-linux-gnu
- exit ;;
- frv:Linux:*:*)
- echo frv-unknown-linux-gnu
- exit ;;
- ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- mips:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips
- #undef mipsel
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mipsel
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
- ;;
- mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips64
- #undef mips64el
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mips64el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips64
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
- ;;
- or32:Linux:*:*)
- echo or32-unknown-linux-gnu
- exit ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
- exit ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
- exit ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
- exit ;;
- parisc:Linux:*:* | hppa:Linux:*:*)
- # Look for CPU level
- case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
- esac
- exit ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
- exit ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
- exit ;;
- sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit ;;
- x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
- exit ;;
- i*86:Linux:*:*)
- # The BFD linker knows what the default object file format is, so
- # first see if it will tell us. cd to the root directory to prevent
- # problems with other programs or directories called `ld' in the path.
- # Set LC_ALL=C to ensure ld outputs messages in English.
- ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
- | sed -ne '/supported targets:/!d
- s/[ ][ ]*/ /g
- s/.*supported targets: *//
- s/ .*//
- p'`
- case "$ld_supported_targets" in
- elf32-i386)
- TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
- ;;
- a.out-i386-linux)
- echo "${UNAME_MACHINE}-pc-linux-gnuaout"
- exit ;;
- coff-i386)
- echo "${UNAME_MACHINE}-pc-linux-gnucoff"
- exit ;;
- "")
- # Either a pre-BFD a.out linker (linux-gnuoldld) or
- # one that does not give us useful --help.
- echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
- exit ;;
- esac
- # Determine whether the default compiler is a.out or elf
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #ifdef __ELF__
- # ifdef __GLIBC__
- # if __GLIBC__ >= 2
- LIBC=gnu
- # else
- LIBC=gnulibc1
- # endif
- # else
- LIBC=gnulibc1
- # endif
- #else
- #ifdef __INTEL_COMPILER
- LIBC=gnu
- #else
- LIBC=gnuaout
- #endif
- #endif
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- test x"${LIBC}" != x && {
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
- exit
- }
- test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
- ;;
- i*86:DYNIX/ptx:4*:*)
- # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
- # earlier versions are messed up and put the nodename in both
- # sysname and nodename.
- echo i386-sequent-sysv4
- exit ;;
- i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
- # I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit ;;
- i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
- # is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit ;;
- i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit ;;
- i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit ;;
- i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
- if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
- else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
- fi
- exit ;;
- i*86:*:5:[678]*)
- # UnixWare 7.x, OpenUNIX and OpenServer 6.
- case `/bin/uname -X | grep "^Machine"` in
- *486*) UNAME_MACHINE=i486 ;;
- *Pentium) UNAME_MACHINE=i586 ;;
- *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
- esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit ;;
- i*86:*:3.2:*)
- if test -f /usr/options/cb.name; then
- UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
- elif /bin/uname -X 2>/dev/null >/dev/null ; then
- UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
- (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
- (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
- && UNAME_MACHINE=i586
- (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
- && UNAME_MACHINE=i686
- (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
- && UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
- else
- echo ${UNAME_MACHINE}-pc-sysv32
- fi
- exit ;;
- pc:*:*:*)
- # Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i386.
- echo i386-pc-msdosdjgpp
- exit ;;
- Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit ;;
- paragon:*:*:*)
- echo i860-intel-osf1
- exit ;;
- i860:*:4.*:*) # i860-SVR4
- if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
- else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
- fi
- exit ;;
- mini*:CTIX:SYS*5:*)
- # "miniframe"
- echo m68010-convergent-sysv
- exit ;;
- mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit ;;
- M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit ;;
- M68*:*:R3V[5678]*:*)
- test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
- 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
- OS_REL=''
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
- 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4; exit; } ;;
- m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit ;;
- TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit ;;
- SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit ;;
- RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit ;;
- *:SINIX-*:*:*)
- if uname -p 2>/dev/null >/dev/null ; then
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
- else
- echo ns32k-sni-sysv
- fi
- exit ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes <hewes@openmarket.com>.
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
- i*86:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
- exit ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit ;;
- mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit ;;
- news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit ;;
- R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
- else
- echo mips-unknown-sysv${UNAME_RELEASE}
- fi
- exit ;;
- BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit ;;
- BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit ;;
- BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit ;;
- SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit ;;
- SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit ;;
- *:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
- *86) UNAME_PROCESSOR=i686 ;;
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit ;;
- *:procnto*:*:* | *:QNX:[0123456789]*:*)
- UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
- UNAME_PROCESSOR=i386
- UNAME_MACHINE=pc
- fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit ;;
- *:QNX:*:4*)
- echo i386-pc-qnx
- exit ;;
- NSE-?:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
- exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit ;;
- *:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit ;;
- BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit ;;
- DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit ;;
- *:Plan9:*:*)
- # "uname -m" is not consistent, so use $cputype instead. 386
- # is converted to i386 for consistency with other x86
- # operating systems.
- if test "$cputype" = "386"; then
- UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
- fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit ;;
- *:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit ;;
- *:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit ;;
- KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit ;;
- XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit ;;
- *:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit ;;
- *:ITS:*:*)
- echo pdp10-unknown-its
- exit ;;
- SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit ;;
- *:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit ;;
- *:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms ; exit ;;
- I*) echo ia64-dec-vms ; exit ;;
- V*) echo vax-dec-vms ; exit ;;
- esac ;;
- *:XENIX:*:SysV)
- echo i386-pc-xenix
- exit ;;
- i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
- exit ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
- { echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit ;;
- c34*)
- echo c34-convex-bsd
- exit ;;
- c38*)
- echo c38-convex-bsd
- exit ;;
- c4*)
- echo c4-convex-bsd
- exit ;;
- esac
-fi
-
-cat >&2 <<EOF
-$0: unable to guess system type
-
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
-
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
-and
- http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
-
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo = `(hostinfo) 2>/dev/null`
-/bin/universe = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
-EOF
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/config.h b/config.h
deleted file mode 100644
index 369419b..0000000
--- a/config.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* config.h. Generated by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Chat archving */
-#define FEATURE_ENABLE_CHAT_ARCHIVING 1
-
-/* Enable SSL */
-#define FEATURE_ENABLE_SSL 1
-
-/* voice mail */
-#define FEATURE_ENABLE_VOICEMAIL 1
-
-/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
-#define HAVE_ALSA_ASOUNDLIB_H 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Have GIPS Voice Engine */
-/* #undef HAVE_GIPS */
-
-/* Glib is required for oRTP code */
-#define HAVE_GLIB 1
-
-/* Defined when we have ilbc codec lib */
-/* #undef HAVE_ILBC */
-
-/* Define to 1 if you have the <iLBC_decode.h> header file. */
-/* #undef HAVE_ILBC_DECODE_H */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* oRTP provides RTP supprt */
-#define HAVE_ORTP 1
-
-/* has speex */
-#define HAVE_SPEEX 1
-
-/* Define to 1 if you have the <speex.h> header file. */
-/* #undef HAVE_SPEEX_H */
-
-/* Define to 1 if you have the <speex/speex.h> header file. */
-#define HAVE_SPEEX_SPEEX_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Building on Linux */
-#define LINUX 1
-
-/* Logging */
-#define LOGGING 1
-
-/* Building on OSX */
-/* #undef OSX */
-
-/* Name of package */
-#define PACKAGE "libjingle"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "google-talk-open@googlegroups.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libjingle"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libjingle 0.4.0"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libjingle"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.4.0"
-
-/* If we're using configure, we're on POSIX */
-#define POSIX 1
-
-/* Build as a production build */
-#define PRODUCTION 1
-
-/* Build as a production build */
-#define PRODUCTION_BUILD 1
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.4.0"
-
-/* Defined when alsa support is enabled */
-#define __ALSA_ENABLED__ 1
diff --git a/config.h.in b/config.h.in
deleted file mode 100644
index 88a4f96..0000000
--- a/config.h.in
+++ /dev/null
@@ -1,112 +0,0 @@
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Chat archving */
-#undef FEATURE_ENABLE_CHAT_ARCHIVING
-
-/* Enable SSL */
-#undef FEATURE_ENABLE_SSL
-
-/* voice mail */
-#undef FEATURE_ENABLE_VOICEMAIL
-
-/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
-#undef HAVE_ALSA_ASOUNDLIB_H
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Have GIPS Voice Engine */
-#undef HAVE_GIPS
-
-/* Glib is required for oRTP code */
-#undef HAVE_GLIB
-
-/* Defined when we have ilbc codec lib */
-#undef HAVE_ILBC
-
-/* Define to 1 if you have the <iLBC_decode.h> header file. */
-#undef HAVE_ILBC_DECODE_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* oRTP provides RTP supprt */
-#undef HAVE_ORTP
-
-/* has speex */
-#undef HAVE_SPEEX
-
-/* Define to 1 if you have the <speex.h> header file. */
-#undef HAVE_SPEEX_H
-
-/* Define to 1 if you have the <speex/speex.h> header file. */
-#undef HAVE_SPEEX_SPEEX_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Building on Linux */
-#undef LINUX
-
-/* Logging */
-#undef LOGGING
-
-/* Building on OSX */
-#undef OSX
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* If we're using configure, we're on POSIX */
-#undef POSIX
-
-/* Build as a production build */
-#undef PRODUCTION
-
-/* Build as a production build */
-#undef PRODUCTION_BUILD
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Version number of package */
-#undef VERSION
-
-/* Defined when alsa support is enabled */
-#undef __ALSA_ENABLED__
diff --git a/config.sub b/config.sub
deleted file mode 100755
index 1c366df..0000000
--- a/config.sub
+++ /dev/null
@@ -1,1579 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-
-timestamp='2005-07-08'
-
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support. The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
-
-Canonicalize a configuration name.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit ;;
- --version | -v )
- echo "$version" ; exit ;;
- --help | --h* | -h )
- echo "$usage"; exit ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help"
- exit 1 ;;
-
- *local*)
- # First pass through any local machine types.
- echo $1
- exit ;;
-
- * )
- break ;;
- esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
- exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
- exit 1;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
- kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray)
- os=
- basic_machine=$1
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*)
- os=-lynxos
- ;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
- ;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
- ;;
- -psos*)
- os=-psos
- ;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
- | bfin \
- | c4x | clipper \
- | d10v | d30v | dlx | dsp16xx \
- | fr30 | frv \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64vr | mips64vrel \
- | mips64orion | mips64orionel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | ms1 \
- | msp430 \
- | ns16k | ns32k \
- | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
- | pyramid \
- | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b \
- | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
- | v850 | v850e \
- | we32k \
- | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
- | z8k)
- basic_machine=$basic_machine-unknown
- ;;
- m32c)
- basic_machine=$basic_machine-unknown
- ;;
- m6811 | m68hc11 | m6812 | m68hc12)
- # Motorola 68HC11/12.
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
-
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* \
- | bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
- | clipper-* | craynv-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | elxsi-* \
- | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | m32r-* | m32rle-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipstx39-* | mipstx39el-* \
- | mmix-* \
- | ms1-* \
- | msp430-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
- | pyramid-* \
- | romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
- | sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tron-* \
- | v850-* | v850e-* | vax-* \
- | we32k-* \
- | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
- | xstormy16-* | xtensa-* \
- | ymp-* \
- | z8k-*)
- ;;
- m32c-*)
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
- ;;
- 3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- abacus)
- basic_machine=abacus-unknown
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16c)
- basic_machine=cr16c-unknown
- os=-elf
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- ;;
- decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
- ;;
- decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
- ;;
- encore | umax | mmax)
- basic_machine=ns32k-encore
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
- ;;
- fx2800)
- basic_machine=i860-alliant
- ;;
- genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
- ;;
- h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
- ;;
- hp9k3[2-9][0-9])
- basic_machine=m68k-hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
- ;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
- i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
- ;;
- i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
- ;;
- i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
- ;;
- i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
- ;;
- iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
- ;;
- *)
- os=-irix4
- ;;
- esac
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- mingw32)
- basic_machine=i386-pc
- os=-mingw32
- ;;
- miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
- ;;
- news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
- ;;
- -ns2*)
- os=-nextstep2
- ;;
- *)
- os=-nextstep3
- ;;
- esac
- ;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
- np1)
- basic_machine=np1-gould
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
- ;;
- op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
- ;;
- pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- pbd)
- basic_machine=sparc-tti
- ;;
- pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
- ;;
- pentium4)
- basic_machine=i786-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
- ;;
- ppc) basic_machine=powerpc-unknown
- ;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle | ppc-le | powerpc-little)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little | ppc64-le | powerpc64-little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- rm[46]00)
- basic_machine=mips-siemens
- ;;
- rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
- ;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
- ;;
- sei)
- basic_machine=mips-sei
- os=-seiux
- ;;
- sequent)
- basic_machine=i386-sequent
- ;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
- ;;
- sh64)
- basic_machine=sh64-unknown
- ;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
- ;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
- ;;
- spur)
- basic_machine=spur-unknown
- ;;
- st2000)
- basic_machine=m68k-tandem
- ;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
- ;;
- sun2)
- basic_machine=m68000-sun
- ;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
- ;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
- ;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
- ;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
- ;;
- sun4)
- basic_machine=sparc-sun
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- ;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
- ;;
- t90)
- basic_machine=t90-cray
- os=-unicos
- ;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
- ;;
- tx39)
- basic_machine=mipstx39-unknown
- ;;
- tx39el)
- basic_machine=mipstx39el-unknown
- ;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
- ;;
- tower | tower-32)
- basic_machine=m68k-ncr
- ;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
- ;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
- ;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
- ;;
- vms)
- basic_machine=vax-dec
- os=-vms
- ;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
- ;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
- ;;
- w65*)
- basic_machine=w65-wdc
- os=-none
- ;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
- ;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- xps | xps100)
- basic_machine=xps100-honeywell
- ;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
- ;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
- ;;
- none)
- basic_machine=none-none
- os=-none
- ;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
- ;;
- op50n)
- basic_machine=hppa1.1-oki
- ;;
- op60c)
- basic_machine=hppa1.1-oki
- ;;
- romp)
- basic_machine=romp-ibm
- ;;
- mmix)
- basic_machine=mmix-knuth
- ;;
- rs6000)
- basic_machine=rs6000-ibm
- ;;
- vax)
- basic_machine=vax-dec
- ;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
- ;;
- pdp11)
- basic_machine=pdp11-dec
- ;;
- we32k)
- basic_machine=we32k-att
- ;;
- sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
- ;;
- sparc | sparcv8 | sparcv9 | sparcv9b)
- basic_machine=sparc-sun
- ;;
- cydra)
- basic_machine=cydra-cydrome
- ;;
- orion)
- basic_machine=orion-highlevel
- ;;
- orion105)
- basic_machine=clipper-highlevel
- ;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
- ;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
- ;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
- ;;
- *)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
- ;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
- ;;
- *)
- ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if [ x"$os" != x"" ]
-then
-case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
- ;;
- -solaris)
- os=-solaris2
- ;;
- -svr4*)
- os=-sysv4
- ;;
- -unixware*)
- os=-sysv4.2uw
- ;;
- -gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
- ;;
- # First accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku*)
- # Remember, each alternative MUST END IN *, to match a version number.
- ;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
- ;;
- *)
- os=-nto$os
- ;;
- esac
- ;;
- -nto-qnx*)
- ;;
- -nto*)
- os=`echo $os | sed -e 's|nto|nto-qnx|'`
- ;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
- ;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
- ;;
- -linux-dietlibc)
- os=-linux-dietlibc
- ;;
- -linux*)
- os=`echo $os | sed -e 's|linux|linux-gnu|'`
- ;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
- ;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
- ;;
- -opened*)
- os=-openedition
- ;;
- -os400*)
- os=-os400
- ;;
- -wince*)
- os=-wince
- ;;
- -osfrose*)
- os=-osfrose
- ;;
- -osf*)
- os=-osf
- ;;
- -utek*)
- os=-bsd
- ;;
- -dynix*)
- os=-bsd
- ;;
- -acis*)
- os=-aos
- ;;
- -atheos*)
- os=-atheos
- ;;
- -syllable*)
- os=-syllable
- ;;
- -386bsd)
- os=-bsd
- ;;
- -ctix* | -uts*)
- os=-sysv
- ;;
- -nova*)
- os=-rtmk-nova
- ;;
- -ns2 )
- os=-nextstep2
- ;;
- -nsk*)
- os=-nsk
- ;;
- # Preserve the version number of sinix5.
- -sinix5.*)
- os=`echo $os | sed -e 's|sinix|sysv|'`
- ;;
- -sinix*)
- os=-sysv4
- ;;
- -tpf*)
- os=-tpf
- ;;
- -triton*)
- os=-sysv3
- ;;
- -oss*)
- os=-sysv3
- ;;
- -svr4)
- os=-sysv4
- ;;
- -svr3)
- os=-sysv3
- ;;
- -sysvr4)
- os=-sysv4
- ;;
- # This must come after -sysvr4.
- -sysv*)
- ;;
- -ose*)
- os=-ose
- ;;
- -es1800*)
- os=-ose
- ;;
- -xenix)
- os=-xenix
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
- ;;
- -aros*)
- os=-aros
- ;;
- -kaos*)
- os=-kaos
- ;;
- -zvmoe)
- os=-zvmoe
- ;;
- -none)
- ;;
- *)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
- exit 1
- ;;
-esac
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system. Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-case $basic_machine in
- *-acorn)
- os=-riscix1.2
- ;;
- arm*-rebel)
- os=-linux
- ;;
- arm*-semi)
- os=-aout
- ;;
- c4x-* | tic4x-*)
- os=-coff
- ;;
- # This must come before the *-dec entry.
- pdp10-*)
- os=-tops20
- ;;
- pdp11-*)
- os=-none
- ;;
- *-dec | vax-*)
- os=-ultrix4.2
- ;;
- m68*-apollo)
- os=-domain
- ;;
- i386-sun)
- os=-sunos4.0.2
- ;;
- m68000-sun)
- os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
- ;;
- m68*-cisco)
- os=-aout
- ;;
- mips*-cisco)
- os=-elf
- ;;
- mips*-*)
- os=-elf
- ;;
- or32-*)
- os=-coff
- ;;
- *-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
- ;;
- sparc-* | *-sun)
- os=-sunos4.1.1
- ;;
- *-be)
- os=-beos
- ;;
- *-haiku)
- os=-haiku
- ;;
- *-ibm)
- os=-aix
- ;;
- *-knuth)
- os=-mmixware
- ;;
- *-wec)
- os=-proelf
- ;;
- *-winbond)
- os=-proelf
- ;;
- *-oki)
- os=-proelf
- ;;
- *-hp)
- os=-hpux
- ;;
- *-hitachi)
- os=-hiux
- ;;
- i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
- ;;
- *-cbm)
- os=-amigaos
- ;;
- *-dg)
- os=-dgux
- ;;
- *-dolphin)
- os=-sysv3
- ;;
- m68k-ccur)
- os=-rtu
- ;;
- m88k-omron*)
- os=-luna
- ;;
- *-next )
- os=-nextstep
- ;;
- *-sequent)
- os=-ptx
- ;;
- *-crds)
- os=-unos
- ;;
- *-ns)
- os=-genix
- ;;
- i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
- ;;
- *-gould)
- os=-sysv
- ;;
- *-highlevel)
- os=-bsd
- ;;
- *-encore)
- os=-bsd
- ;;
- *-sgi)
- os=-irix
- ;;
- *-siemens)
- os=-sysv4
- ;;
- *-masscomp)
- os=-rtu
- ;;
- f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
- ;;
- *-rom68k)
- os=-coff
- ;;
- *-*bug)
- os=-coff
- ;;
- *-apple)
- os=-macos
- ;;
- *-atari*)
- os=-mint
- ;;
- *)
- os=-none
- ;;
-esac
-fi
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
- vendor=acorn
- ;;
- -sunos*)
- vendor=sun
- ;;
- -aix*)
- vendor=ibm
- ;;
- -beos*)
- vendor=be
- ;;
- -hpux*)
- vendor=hp
- ;;
- -mpeix*)
- vendor=hp
- ;;
- -hiux*)
- vendor=hitachi
- ;;
- -unos*)
- vendor=crds
- ;;
- -dgux*)
- vendor=dg
- ;;
- -luna*)
- vendor=omron
- ;;
- -genix*)
- vendor=ns
- ;;
- -mvs* | -opened*)
- vendor=ibm
- ;;
- -os400*)
- vendor=ibm
- ;;
- -ptx*)
- vendor=sequent
- ;;
- -tpf*)
- vendor=ibm
- ;;
- -vxsim* | -vxworks* | -windiss*)
- vendor=wrs
- ;;
- -aux*)
- vendor=apple
- ;;
- -hms*)
- vendor=hitachi
- ;;
- -mpw* | -macos*)
- vendor=apple
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- vendor=atari
- ;;
- -vos*)
- vendor=stratus
- ;;
- esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
- ;;
-esac
-
-echo $basic_machine$os
-exit
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/configure b/configure
deleted file mode 100755
index 2c8bdb5..0000000
--- a/configure
+++ /dev/null
@@ -1,21525 +0,0 @@
-#! /bin/sh
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for libjingle 0.4.0.
-#
-# Report bugs to <google-talk-open@googlegroups.com>.
-#
-# Copyright (C) 2003 Free Software Foundation, Inc.
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
- set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- $as_unset $as_var
- fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)$' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
- /^X\/\(\/\/\)$/{ s//\1/; q; }
- /^X\/\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" || {
- # Find who we are. Look in the path if we contain no path at all
- # relative or not.
- case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
- ;;
- esac
- # We did not find ourselves, most probably we were run as `sh COMMAND'
- # in which case we are not to be found in the path.
- if test "x$as_myself" = x; then
- as_myself=$0
- fi
- if test ! -f "$as_myself"; then
- { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
- { (exit 1); exit 1; }; }
- fi
- case $CONFIG_SHELL in
- '')
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for as_base in sh bash ksh sh5; do
- case $as_dir in
- /*)
- if ("$as_dir/$as_base" -c '
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
- $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
- $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
- CONFIG_SHELL=$as_dir/$as_base
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" ${1+"$@"}
- fi;;
- esac
- done
-done
-;;
- esac
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line before each line; the second 'sed' does the real
- # work. The second script uses 'N' to pair each line-number line
- # with the numbered line, and appends trailing '-' during
- # substitution so that $LINENO is not a special case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
- sed '=' <$as_myself |
- sed '
- N
- s,$,-,
- : loop
- s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
- t loop
- s,-$,,
- s,^['$as_cr_digits']*\n,,
- ' >$as_me.lineno &&
- chmod +x $as_me.lineno ||
- { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensible to this).
- . ./$as_me.lineno
- # Exit status is that of the last command.
- exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
- *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T=' ' ;;
- *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
- *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- # We could just check for DJGPP; but this test a) works b) is more generic
- # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
- if test -f conf$$.exe; then
- # Don't use ln at all; we don't have any links
- as_ln_s='cp -p'
- else
- as_ln_s='ln -s'
- fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-case X$ECHO in
-X*--fallback-echo)
- # Remove one level of quotation (which was required for Make).
- ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
- ;;
-esac
-
-echo=${ECHO-echo}
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
- # Yippee, $echo works!
- :
-else
- # Restart under the correct shell.
- exec $SHELL "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-$*
-EOF
- exit 0
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-if test -z "$ECHO"; then
-if test "X${echo_test_string+set}" != Xset; then
-# find a string as large as possible, as long as the shell can cope with it
- for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
- # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
- if (echo_test_string=`eval $cmd`) 2>/dev/null &&
- echo_test_string=`eval $cmd` &&
- (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
- then
- break
- fi
- done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- :
-else
- # The Solaris, AIX, and Digital Unix default echo programs unquote
- # backslashes. This makes it impossible to quote backslashes using
- # echo "$something" | sed 's/\\/\\\\/g'
- #
- # So, first we look for a working echo in the user's PATH.
-
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for dir in $PATH /usr/ucb; do
- IFS="$lt_save_ifs"
- if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
- test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- echo="$dir/echo"
- break
- fi
- done
- IFS="$lt_save_ifs"
-
- if test "X$echo" = Xecho; then
- # We didn't find a better echo, so look for alternatives.
- if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # This shell has a builtin print -r that does the trick.
- echo='print -r'
- elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
- test "X$CONFIG_SHELL" != X/bin/ksh; then
- # If we have ksh, try running configure again with it.
- ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
- export ORIGINAL_CONFIG_SHELL
- CONFIG_SHELL=/bin/ksh
- export CONFIG_SHELL
- exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
- else
- # Try using printf.
- echo='printf %s\n'
- if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
- echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- # Cool, printf works
- :
- elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
- export CONFIG_SHELL
- SHELL="$CONFIG_SHELL"
- export SHELL
- echo="$CONFIG_SHELL $0 --fallback-echo"
- elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
- test "X$echo_testing_string" = 'X\t' &&
- echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
- test "X$echo_testing_string" = "X$echo_test_string"; then
- echo="$CONFIG_SHELL $0 --fallback-echo"
- else
- # maybe with a smaller string...
- prev=:
-
- for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
- if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
- then
- break
- fi
- prev="$cmd"
- done
-
- if test "$prev" != 'sed 50q "$0"'; then
- echo_test_string=`eval $prev`
- export echo_test_string
- exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
- else
- # Oops. We lost completely, so just stick with echo.
- echo=echo
- fi
- fi
- fi
- fi
-fi
-fi
-
-# Copy echo and quote the copy suitably for passing to libtool from
-# the Makefile, instead of quoting the original, which is used later.
-ECHO=$echo
-if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
- ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
-fi
-
-
-
-
-tagnames=${tagnames+${tagnames},}CXX
-
-tagnames=${tagnames+${tagnames},}F77
-
-# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-exec 6>&1
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_config_libobj_dir=.
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete. It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
-
-# Identity of this package.
-PACKAGE_NAME='libjingle'
-PACKAGE_TARNAME='libjingle'
-PACKAGE_VERSION='0.4.0'
-PACKAGE_STRING='libjingle 0.4.0'
-PACKAGE_BUGREPORT='google-talk-open@googlegroups.com'
-
-# Factoring default headers for most tests.
-ac_includes_default="\
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# if HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
-# include <memory.h>
-# endif
-# include <string.h>
-#endif
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif"
-
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL EXPAT_LIBS ALSA_LIBS PKG_CONFIG GLIB_CFLAGS GLIB_LIBS ORTP_CFLAGS ORTP_LIBS SPEEX_CFLAGS SPEEX_LIBS ILBC_CFLAGS ILBC_LIBS GIPS_TRUE GIPS_FALSE PHONE_TRUE PHONE_FALSE MEDIA_LIBS LIBOBJS LTLIBOBJS'
-ac_subst_files=''
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-ac_prev=
-for ac_option
-do
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
- ac_prev=
- continue
- fi
-
- ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case $ac_option in
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir=$ac_optarg ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build_alias ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build_alias=$ac_optarg ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file=$ac_optarg ;;
-
- --config-cache | -C)
- cache_file=config.cache ;;
-
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir=$ac_optarg ;;
-
- -disable-* | --disable-*)
- ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
- eval "enable_$ac_feature=no" ;;
-
- -enable-* | --enable-*)
- ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
- case $ac_option in
- *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
- *) ac_optarg=yes ;;
- esac
- eval "enable_$ac_feature='$ac_optarg'" ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix=$ac_optarg ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he | -h)
- ac_init_help=long ;;
- -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
- ac_init_help=recursive ;;
- -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
- ac_init_help=short ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host_alias ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host_alias=$ac_optarg ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir=$ac_optarg ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir=$ac_optarg ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir=$ac_optarg ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir=$ac_optarg ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir=$ac_optarg ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir=$ac_optarg ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c | -n)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir=$ac_optarg ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix=$ac_optarg ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix=$ac_optarg ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix=$ac_optarg ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name=$ac_optarg ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir=$ac_optarg ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir=$ac_optarg ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site=$ac_optarg ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir=$ac_optarg ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir=$ac_optarg ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target_alias ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target_alias=$ac_optarg ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers | -V)
- ac_init_version=: ;;
-
- -with-* | --with-*)
- ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case $ac_option in
- *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
- *) ac_optarg=yes ;;
- esac
- eval "with_$ac_package='$ac_optarg'" ;;
-
- -without-* | --without-*)
- ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package | sed 's/-/_/g'`
- eval "with_$ac_package=no" ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes=$ac_optarg ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries=$ac_optarg ;;
-
- -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; }
- ;;
-
- *=*)
- ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
- # Reject names that are not valid shell variable names.
- expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
- { (exit 1); exit 1; }; }
- ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
- eval "$ac_envvar='$ac_optarg'"
- export $ac_envvar ;;
-
- *)
- # FIXME: should be removed in autoconf 3.0.
- echo "$as_me: WARNING: you should use --build, --host, --target" >&2
- expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- echo "$as_me: WARNING: invalid host type: $ac_option" >&2
- : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- { echo "$as_me: error: missing argument to $ac_option" >&2
- { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
-do
- eval ac_val=$`echo $ac_var`
- case $ac_val in
- [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
- *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; };;
- esac
-done
-
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
- localstatedir libdir includedir oldincludedir infodir mandir
-do
- eval ac_val=$`echo $ac_var`
- case $ac_val in
- [\\/$]* | ?:[\\/]* ) ;;
- *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; };;
- esac
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
- if test "x$build_alias" = x; then
- cross_compiling=maybe
- echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used." >&2
- elif test "x$build_alias" != "x$host_alias"; then
- cross_compiling=yes
- fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_confdir=`(dirname "$0") 2>/dev/null ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$0" : 'X\(//\)[^/]' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$0" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
- { (exit 1); exit 1; }; }
- else
- { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
- { (exit 1); exit 1; }; }
- fi
-fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
- { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
- { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-ac_env_CXX_set=${CXX+set}
-ac_env_CXX_value=$CXX
-ac_cv_env_CXX_set=${CXX+set}
-ac_cv_env_CXX_value=$CXX
-ac_env_CXXFLAGS_set=${CXXFLAGS+set}
-ac_env_CXXFLAGS_value=$CXXFLAGS
-ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
-ac_cv_env_CXXFLAGS_value=$CXXFLAGS
-ac_env_CPP_set=${CPP+set}
-ac_env_CPP_value=$CPP
-ac_cv_env_CPP_set=${CPP+set}
-ac_cv_env_CPP_value=$CPP
-ac_env_CXXCPP_set=${CXXCPP+set}
-ac_env_CXXCPP_value=$CXXCPP
-ac_cv_env_CXXCPP_set=${CXXCPP+set}
-ac_cv_env_CXXCPP_value=$CXXCPP
-ac_env_F77_set=${F77+set}
-ac_env_F77_value=$F77
-ac_cv_env_F77_set=${F77+set}
-ac_cv_env_F77_value=$F77
-ac_env_FFLAGS_set=${FFLAGS+set}
-ac_env_FFLAGS_value=$FFLAGS
-ac_cv_env_FFLAGS_set=${FFLAGS+set}
-ac_cv_env_FFLAGS_value=$FFLAGS
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat <<_ACEOF
-\`configure' configures libjingle 0.4.0 to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE. See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
- -h, --help display this help and exit
- --help=short display options specific to this package
- --help=recursive display the short help of all the included packages
- -V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking...' messages
- --cache-file=FILE cache test results in FILE [disabled]
- -C, --config-cache alias for \`--cache-file=config.cache'
- -n, --no-create do not create output files
- --srcdir=DIR find the sources in DIR [configure dir or \`..']
-
-_ACEOF
-
- cat <<_ACEOF
-Installation directories:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
- --bindir=DIR user executables [EPREFIX/bin]
- --sbindir=DIR system admin executables [EPREFIX/sbin]
- --libexecdir=DIR program executables [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --libdir=DIR object code libraries [EPREFIX/lib]
- --includedir=DIR C header files [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc [/usr/include]
- --infodir=DIR info documentation [PREFIX/info]
- --mandir=DIR man documentation [PREFIX/man]
-_ACEOF
-
- cat <<\_ACEOF
-
-Program names:
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM run sed PROGRAM on installed program names
-
-System types:
- --build=BUILD configure for building on BUILD [guessed]
- --host=HOST cross-compile to build programs to run on HOST [BUILD]
- --target=TARGET configure for building compilers for TARGET [HOST]
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of libjingle 0.4.0:";;
- esac
- cat <<\_ACEOF
-
-Optional Features:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --disable-dependency-tracking speeds up one-time build
- --enable-dependency-tracking do not reject slow dependency extractors
- --enable-shared[=PKGS]
- build shared libraries [default=yes]
- --enable-static[=PKGS]
- build static libraries [default=yes]
- --enable-fast-install[=PKGS]
- optimize for fast installation [default=yes]
- --disable-libtool-lock avoid locking (might break parallel builds)
-
-Optional Packages:
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --with-gnu-ld assume the C compiler uses GNU ld [default=no]
- --with-pic try to use only PIC/non-PIC objects [default=use
- both]
- --with-tags[=TAGS]
- include additional configurations [automatic]
- --with-speex Set prefix where speex lib can be found (ex:/usr, /usr/local) default=/usr
- --with-ilbc Set prefix where ilbc headers and libs can be found (ex:/usr, /usr/local, none to disable ilbc support) default=/usr
-
-Some influential environment variables:
- CC C compiler command
- CFLAGS C compiler flags
- LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
- nonstandard directory <lib dir>
- CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
- headers in a nonstandard directory <include dir>
- CXX C++ compiler command
- CXXFLAGS C++ compiler flags
- CPP C preprocessor
- CXXCPP C++ preprocessor
- F77 Fortran 77 compiler command
- FFLAGS Fortran 77 compiler flags
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-Report bugs to <google-talk-open@googlegroups.com>.
-_ACEOF
-fi
-
-if test "$ac_init_help" = "recursive"; then
- # If there are subdirs, report their specific --help.
- ac_popdir=`pwd`
- for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
- test -d $ac_dir || continue
- ac_builddir=.
-
-if test "$ac_dir" != .; then
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A "../" for each directory in $ac_dir_suffix.
- ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
- ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
- .) # No --srcdir option. We are building in place.
- ac_srcdir=.
- if test -z "$ac_top_builddir"; then
- ac_top_srcdir=.
- else
- ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
- fi ;;
- [\\/]* | ?:[\\/]* ) # Absolute path.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir ;;
- *) # Relative path.
- ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
- case "$ac_dir" in
- .) ac_abs_builddir=`pwd`;;
- [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
- *) ac_abs_builddir=`pwd`/"$ac_dir";;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
- case ${ac_top_builddir}. in
- .) ac_abs_top_builddir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
- *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
- case $ac_srcdir in
- .) ac_abs_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
- *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
- case $ac_top_srcdir in
- .) ac_abs_top_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
- *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
- esac;;
-esac
-
- cd $ac_dir
- # Check for guested configure; otherwise get Cygnus style configure.
- if test -f $ac_srcdir/configure.gnu; then
- echo
- $SHELL $ac_srcdir/configure.gnu --help=recursive
- elif test -f $ac_srcdir/configure; then
- echo
- $SHELL $ac_srcdir/configure --help=recursive
- elif test -f $ac_srcdir/configure.ac ||
- test -f $ac_srcdir/configure.in; then
- echo
- $ac_configure --help
- else
- echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
- fi
- cd "$ac_popdir"
- done
-fi
-
-test -n "$ac_init_help" && exit 0
-if $ac_init_version; then
- cat <<\_ACEOF
-libjingle configure 0.4.0
-generated by GNU Autoconf 2.59
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
- exit 0
-fi
-exec 5>config.log
-cat >&5 <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by libjingle $as_me 0.4.0, which was
-generated by GNU Autoconf 2.59. Invocation command line was
-
- $ $0 $@
-
-_ACEOF
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
-
-/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
-/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
-/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- echo "PATH: $as_dir"
-done
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_sep=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
- for ac_arg
- do
- case $ac_arg in
- -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- continue ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
- ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
- esac
- case $ac_pass in
- 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
- 2)
- ac_configure_args1="$ac_configure_args1 '$ac_arg'"
- if test $ac_must_keep_next = true; then
- ac_must_keep_next=false # Got value, back to normal.
- else
- case $ac_arg in
- *=* | --config-cache | -C | -disable-* | --disable-* \
- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
- | -with-* | --with-* | -without-* | --without-* | --x)
- case "$ac_configure_args0 " in
- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
- esac
- ;;
- -* ) ac_must_keep_next=true ;;
- esac
- fi
- ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
- # Get rid of the leading space.
- ac_sep=" "
- ;;
- esac
- done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log. We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
-trap 'exit_status=$?
- # Save into config.log some information that might help in debugging.
- {
- echo
-
- cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
- echo
- # The following way of writing the cache mishandles newlines in values,
-{
- (set) 2>&1 |
- case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- sed -n \
- "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
- ;;
- *)
- sed -n \
- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
- ;;
- esac;
-}
- echo
-
- cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
- echo
- for ac_var in $ac_subst_vars
- do
- eval ac_val=$`echo $ac_var`
- echo "$ac_var='"'"'$ac_val'"'"'"
- done | sort
- echo
-
- if test -n "$ac_subst_files"; then
- cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
-_ASBOX
- echo
- for ac_var in $ac_subst_files
- do
- eval ac_val=$`echo $ac_var`
- echo "$ac_var='"'"'$ac_val'"'"'"
- done | sort
- echo
- fi
-
- if test -s confdefs.h; then
- cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
- echo
- sed "/^$/d" confdefs.h | sort
- echo
- fi
- test "$ac_signal" != 0 &&
- echo "$as_me: caught signal $ac_signal"
- echo "$as_me: exit $exit_status"
- } >&5
- rm -f core *.core &&
- rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
- exit $exit_status
- ' 0
-for ac_signal in 1 2 13 15; do
- trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
- sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special
- # files actually), so we avoid doing that.
- if test -f "$cache_file"; then
- { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
- case $cache_file in
- [\\/]* | ?:[\\/]* ) . $cache_file;;
- *) . ./$cache_file;;
- esac
- fi
-else
- { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
- >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
- sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
- eval ac_old_set=\$ac_cv_env_${ac_var}_set
- eval ac_new_set=\$ac_env_${ac_var}_set
- eval ac_old_val="\$ac_cv_env_${ac_var}_value"
- eval ac_new_val="\$ac_env_${ac_var}_value"
- case $ac_old_set,$ac_new_set in
- set,)
- { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,set)
- { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,);;
- *)
- if test "x$ac_old_val" != "x$ac_new_val"; then
- { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
- { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
-echo "$as_me: former value: $ac_old_val" >&2;}
- { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
-echo "$as_me: current value: $ac_new_val" >&2;}
- ac_cache_corrupted=:
- fi;;
- esac
- # Pass precious variables to config.status.
- if test "$ac_new_set" = set; then
- case $ac_new_val in
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
- ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
- *) ac_arg=$ac_var=$ac_new_val ;;
- esac
- case " $ac_configure_args " in
- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
- *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- esac
- fi
-done
-if $ac_cache_corrupted; then
- { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-ac_aux_dir=
-for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
- if test -f $ac_dir/install-sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f $ac_dir/install.sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f $ac_dir/shtool; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
-echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
- { (exit 1); exit 1; }; }
-fi
-ac_config_guess="$SHELL $ac_aux_dir/config.guess"
-ac_config_sub="$SHELL $ac_aux_dir/config.sub"
-ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
-
-# Make sure we can run config.sub.
-$ac_config_sub sun4 >/dev/null 2>&1 ||
- { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
-echo "$as_me: error: cannot run $ac_config_sub" >&2;}
- { (exit 1); exit 1; }; }
-
-echo "$as_me:$LINENO: checking build system type" >&5
-echo $ECHO_N "checking build system type... $ECHO_C" >&6
-if test "${ac_cv_build+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_build_alias=$build_alias
-test -z "$ac_cv_build_alias" &&
- ac_cv_build_alias=`$ac_config_guess`
-test -z "$ac_cv_build_alias" &&
- { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
-echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
- { (exit 1); exit 1; }; }
-ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
- { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
-echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_build" >&5
-echo "${ECHO_T}$ac_cv_build" >&6
-build=$ac_cv_build
-build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-
-echo "$as_me:$LINENO: checking host system type" >&5
-echo $ECHO_N "checking host system type... $ECHO_C" >&6
-if test "${ac_cv_host+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_host_alias=$host_alias
-test -z "$ac_cv_host_alias" &&
- ac_cv_host_alias=$ac_cv_build_alias
-ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
- { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
-echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_host" >&5
-echo "${ECHO_T}$ac_cv_host" >&6
-host=$ac_cv_host
-host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-
-echo "$as_me:$LINENO: checking target system type" >&5
-echo $ECHO_N "checking target system type... $ECHO_C" >&6
-if test "${ac_cv_target+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_target_alias=$target_alias
-test "x$ac_cv_target_alias" = "x" &&
- ac_cv_target_alias=$ac_cv_host_alias
-ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
- { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5
-echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
- { (exit 1); exit 1; }; }
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_target" >&5
-echo "${ECHO_T}$ac_cv_target" >&6
-target=$ac_cv_target
-target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-
-# The aliases save the names the user supplied, while $host etc.
-# will get canonicalized.
-test -n "$target_alias" &&
- test "$program_prefix$program_suffix$program_transform_name" = \
- NONENONEs,x,x, &&
- program_prefix=${target_alias}-
- ac_config_headers="$ac_config_headers config.h"
-
-am__api_version="1.9"
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
-echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
-if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in
- ./ | .// | /cC/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- done
- done
- ;;
-esac
-done
-
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL=$ac_install_sh
- fi
-fi
-echo "$as_me:$LINENO: result: $INSTALL" >&5
-echo "${ECHO_T}$INSTALL" >&6
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-echo "$as_me:$LINENO: checking whether build environment is sane" >&5
-echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
-# Just in case
-sleep 1
-echo timestamp > conftest.file
-# Do `set' in a subshell so we don't clobber the current shell's
-# arguments. Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
- set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
- if test "$*" = "X"; then
- # -L didn't work.
- set X `ls -t $srcdir/configure conftest.file`
- fi
- rm -f conftest.file
- if test "$*" != "X $srcdir/configure conftest.file" \
- && test "$*" != "X conftest.file $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
-alias in your environment" >&5
-echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
-alias in your environment" >&2;}
- { (exit 1); exit 1; }; }
- fi
-
- test "$2" = conftest.file
- )
-then
- # Ok.
- :
-else
- { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
-Check your system clock" >&5
-echo "$as_me: error: newly created file is older than distributed files!
-Check your system clock" >&2;}
- { (exit 1); exit 1; }; }
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-test "$program_prefix" != NONE &&
- program_transform_name="s,^,$program_prefix,;$program_transform_name"
-# Use a double $ so make ignores it.
-test "$program_suffix" != NONE &&
- program_transform_name="s,\$,$program_suffix,;$program_transform_name"
-# Double any \ or $. echo might interpret backslashes.
-# By default was `s,x,x', remove it if useless.
-cat <<\_ACEOF >conftest.sed
-s/[\\$]/&&/g;s/;s,x,x,$//
-_ACEOF
-program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
-rm conftest.sed
-
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
-
-test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
-# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
-else
- am_missing_run=
- { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
-echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
-fi
-
-if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
- # We used to keeping the `.' as first argument, in order to
- # allow $(mkdir_p) to be used without argument. As in
- # $(mkdir_p) $(somedir)
- # where $(somedir) is conditionally defined. However this is wrong
- # for two reasons:
- # 1. if the package is installed by a user who cannot write `.'
- # make install will fail,
- # 2. the above comment should most certainly read
- # $(mkdir_p) $(DESTDIR)$(somedir)
- # so it does not work when $(somedir) is undefined and
- # $(DESTDIR) is not.
- # To support the latter case, we have to write
- # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
- # so the `.' trick is pointless.
- mkdir_p='mkdir -p --'
-else
- # On NextStep and OpenStep, the `mkdir' command does not
- # recognize any option. It will interpret all options as
- # directories to create, and then abort because `.' already
- # exists.
- for d in ./-p ./--version;
- do
- test -d $d && rmdir $d
- done
- # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
- if test -f "$ac_aux_dir/mkinstalldirs"; then
- mkdir_p='$(mkinstalldirs)'
- else
- mkdir_p='$(install_sh) -d'
- fi
-fi
-
-for ac_prog in gawk mawk nawk awk
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_AWK+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$AWK"; then
- ac_cv_prog_AWK="$AWK" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_AWK="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-AWK=$ac_cv_prog_AWK
-if test -n "$AWK"; then
- echo "$as_me:$LINENO: result: $AWK" >&5
-echo "${ECHO_T}$AWK" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$AWK" && break
-done
-
-echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
-echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
-set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
-if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.make <<\_ACEOF
-all:
- @echo 'ac_maketemp="$(MAKE)"'
-_ACEOF
-# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
-eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
-if test -n "$ac_maketemp"; then
- eval ac_cv_prog_make_${ac_make}_set=yes
-else
- eval ac_cv_prog_make_${ac_make}_set=no
-fi
-rm -f conftest.make
-fi
-if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
- SET_MAKE=
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
- SET_MAKE="MAKE=${MAKE-make}"
-fi
-
-rm -rf .tst 2>/dev/null
-mkdir .tst 2>/dev/null
-if test -d .tst; then
- am__leading_dot=.
-else
- am__leading_dot=_
-fi
-rmdir .tst 2>/dev/null
-
-# test to see if srcdir already configured
-if test "`cd $srcdir && pwd`" != "`pwd`" &&
- test -f $srcdir/config.status; then
- { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
-echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-# test whether we have cygpath
-if test -z "$CYGPATH_W"; then
- if (cygpath --version) >/dev/null 2>/dev/null; then
- CYGPATH_W='cygpath -w'
- else
- CYGPATH_W=echo
- fi
-fi
-
-
-# Define the identity of the package.
- PACKAGE='libjingle'
- VERSION='0.4.0'
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE "$PACKAGE"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define VERSION "$VERSION"
-_ACEOF
-
-# Some tools Automake needs.
-
-ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
-
-
-AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
-
-
-AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
-
-
-AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
-
-
-MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
-
-install_sh=${install_sh-"$am_aux_dir/install-sh"}
-
-# Installed binaries are usually stripped using `strip' when the user
-# run `make install-strip'. However `strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the `STRIP' environment variable to overrule this program.
-if test "$cross_compiling" != no; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_STRIP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$STRIP"; then
- ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_STRIP="${ac_tool_prefix}strip"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
- echo "$as_me:$LINENO: result: $STRIP" >&5
-echo "${ECHO_T}$STRIP" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_STRIP"; then
- ac_ct_STRIP=$STRIP
- # Extract the first word of "strip", so it can be a program name with args.
-set dummy strip; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_STRIP"; then
- ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_STRIP="strip"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
- test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
-fi
-fi
-ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
-if test -n "$ac_ct_STRIP"; then
- echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
-echo "${ECHO_T}$ac_ct_STRIP" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- STRIP=$ac_ct_STRIP
-else
- STRIP="$ac_cv_prog_STRIP"
-fi
-
-fi
-INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
-
-# We need awk for the "check" target. The system "awk" is bad on
-# some platforms.
-# Always define AMTAR for backward compatibility.
-
-AMTAR=${AMTAR-"${am_missing_run}tar"}
-
-am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
-
-
-
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- CC=$ac_ct_CC
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- CC=$ac_ct_CC
-else
- CC="$ac_cv_prog_CC"
-fi
-
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$CC" && break
- done
-fi
-if test -z "$CC"; then
- ac_ct_CC=$CC
- for ac_prog in cl
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$ac_ct_CC" && break
-done
-
- CC=$ac_ct_CC
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
- "checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
- (eval $ac_compiler --version </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
- (eval $ac_compiler -v </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
- (eval $ac_compiler -V </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
- (eval $ac_link_default) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # Find the output, starting from the most likely. This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
-do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
- ;;
- conftest.$ac_ext )
- # This is the source file.
- ;;
- [ab].out )
- # We found the default executable, but exeext='' is most
- # certainly right.
- break;;
- *.* )
- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- # FIXME: I believe we export ac_cv_exeext for Libtool,
- # but it would be cool to find out if it's true. Does anybody
- # maintain Libtool? --akim.
- export ac_cv_exeext
- break;;
- * )
- break;;
- esac
-done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
-
-# Check the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
- fi
- fi
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- export ac_cv_exeext
- break;;
- * ) break;;
- esac
-done
-else
- { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
-if test "${ac_cv_objext+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
- break;;
- esac
-done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_compiler_gnu=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cc_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_prog_cc_stdc=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std1 is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std1. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
-_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX -qlanglvl=ansi
-# Ultrix and OSF/1 -std1
-# HP-UX 10.20 and later -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
- CC="$ac_save_CC $ac_arg"
- rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_stdc=$ac_arg
-break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext
-done
-rm -f conftest.$ac_ext conftest.$ac_objext
-CC=$ac_save_CC
-
-fi
-
-case "x$ac_cv_prog_cc_stdc" in
- x|xno)
- echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
- *)
- echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
- CC="$CC $ac_cv_prog_cc_stdc" ;;
-esac
-
-# Some people use a C++ compiler to compile C. Since we use `exit',
-# in C++ we need to declare it. In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
- choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- for ac_declaration in \
- '' \
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);'
-do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
-fi
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-DEPDIR="${am__leading_dot}deps"
-
- ac_config_commands="$ac_config_commands depfiles"
-
-
-am_make=${MAKE-make}
-cat > confinc << 'END'
-am__doit:
- @echo done
-.PHONY: am__doit
-END
-# If we don't find an include directive, just comment out the code.
-echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
-echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6
-am__include="#"
-am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# We grep out `Entering directory' and `Leaving directory'
-# messages which can occur if `w' ends up in MAKEFLAGS.
-# In particular we don't look at `^make:' because GNU make might
-# be invoked under some other name (usually "gmake"), in which
-# case it prints its new name instead of `make'.
-if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
- am__include=include
- am__quote=
- _am_result=GNU
-fi
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
- echo '.include "confinc"' > confmf
- if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
- am__include=.include
- am__quote="\""
- _am_result=BSD
- fi
-fi
-
-
-echo "$as_me:$LINENO: result: $_am_result" >&5
-echo "${ECHO_T}$_am_result" >&6
-rm -f confinc confmf
-
-# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given.
-if test "${enable_dependency_tracking+set}" = set; then
- enableval="$enable_dependency_tracking"
-
-fi;
-if test "x$enable_dependency_tracking" != xno; then
- am_depcomp="$ac_aux_dir/depcomp"
- AMDEPBACKSLASH='\'
-fi
-
-
-if test "x$enable_dependency_tracking" != xno; then
- AMDEP_TRUE=
- AMDEP_FALSE='#'
-else
- AMDEP_TRUE='#'
- AMDEP_FALSE=
-fi
-
-
-
-
-depcc="$CC" am_compiler_list=
-
-echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
-echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
-if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
- # We make a subdir and do the tests there. Otherwise we can end up
- # making bogus files that we don't know about and never remove. For
- # instance it was reported that on HP-UX the gcc test will end up
- # making a dummy file named `D' -- because `-MD' means `put the output
- # in D'.
- mkdir conftest.dir
- # Copy depcomp to subdir because otherwise we won't find it if we're
- # using a relative directory.
- cp "$am_depcomp" conftest.dir
- cd conftest.dir
- # We will build objects and dependencies in a subdirectory because
- # it helps to detect inapplicable dependency modes. For instance
- # both Tru64's cc and ICC support -MD to output dependencies as a
- # side effect of compilation, but ICC will put the dependencies in
- # the current directory while Tru64 will put them in the object
- # directory.
- mkdir sub
-
- am_cv_CC_dependencies_compiler_type=none
- if test "$am_compiler_list" = ""; then
- am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
- fi
- for depmode in $am_compiler_list; do
- # Setup a source with many dependencies, because some compilers
- # like to wrap large dependency lists on column 80 (with \), and
- # we should not choose a depcomp mode which is confused by this.
- #
- # We need to recreate these files for each test, as the compiler may
- # overwrite some of them when testing with obscure command lines.
- # This happens at least with the AIX C compiler.
- : > sub/conftest.c
- for i in 1 2 3 4 5 6; do
- echo '#include "conftst'$i'.h"' >> sub/conftest.c
- # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
- # Solaris 8's {/usr,}/bin/sh.
- touch sub/conftst$i.h
- done
- echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
-
- case $depmode in
- nosideeffect)
- # after this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested
- if test "x$enable_dependency_tracking" = xyes; then
- continue
- else
- break
- fi
- ;;
- none) break ;;
- esac
- # We check with `-c' and `-o' for the sake of the "dashmstdout"
- # mode. It turns out that the SunPro C++ compiler does not properly
- # handle `-M -o', and we need to detect this.
- if depmode=$depmode \
- source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
- depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
- >/dev/null 2>conftest.err &&
- grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
- ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
- # icc doesn't choke on unknown options, it will just issue warnings
- # or remarks (even with -Werror). So we grep stderr for any message
- # that says an option was ignored or not supported.
- # When given -MP, icc 7.0 and 7.1 complain thusly:
- # icc: Command line warning: ignoring option '-M'; no argument required
- # The diagnosis changed in icc 8.0:
- # icc: Command line remark: option '-MP' not supported
- if (grep 'ignoring option' conftest.err ||
- grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
- am_cv_CC_dependencies_compiler_type=$depmode
- break
- fi
- fi
- done
-
- cd ..
- rm -rf conftest.dir
-else
- am_cv_CC_dependencies_compiler_type=none
-fi
-
-fi
-echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
-echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6
-CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
-
-
-
-if
- test "x$enable_dependency_tracking" != xno \
- && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
- am__fastdepCC_TRUE=
- am__fastdepCC_FALSE='#'
-else
- am__fastdepCC_TRUE='#'
- am__fastdepCC_FALSE=
-fi
-
-
-ac_ext=cc
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CXX"; then
- ac_cv_prog_CXX="$CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-CXX=$ac_cv_prog_CXX
-if test -n "$CXX"; then
- echo "$as_me:$LINENO: result: $CXX" >&5
-echo "${ECHO_T}$CXX" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$CXX" && break
- done
-fi
-if test -z "$CXX"; then
- ac_ct_CXX=$CXX
- for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CXX"; then
- ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CXX="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
-if test -n "$ac_ct_CXX"; then
- echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
-echo "${ECHO_T}$ac_ct_CXX" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$ac_ct_CXX" && break
-done
-test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
-
- CXX=$ac_ct_CXX
-fi
-
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
- "checking for C++ compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
- (eval $ac_compiler --version </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
- (eval $ac_compiler -v </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
- (eval $ac_compiler -V </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-
-echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_compiler_gnu=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
-GXX=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CXXFLAGS=${CXXFLAGS+set}
-ac_save_CXXFLAGS=$CXXFLAGS
-CXXFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
-echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cxx_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cxx_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cxx_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
-if test "$ac_test_CXXFLAGS" = set; then
- CXXFLAGS=$ac_save_CXXFLAGS
-elif test $ac_cv_prog_cxx_g = yes; then
- if test "$GXX" = yes; then
- CXXFLAGS="-g -O2"
- else
- CXXFLAGS="-g"
- fi
-else
- if test "$GXX" = yes; then
- CXXFLAGS="-O2"
- else
- CXXFLAGS=
- fi
-fi
-for ac_declaration in \
- '' \
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);'
-do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-depcc="$CXX" am_compiler_list=
-
-echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
-echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
-if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
- # We make a subdir and do the tests there. Otherwise we can end up
- # making bogus files that we don't know about and never remove. For
- # instance it was reported that on HP-UX the gcc test will end up
- # making a dummy file named `D' -- because `-MD' means `put the output
- # in D'.
- mkdir conftest.dir
- # Copy depcomp to subdir because otherwise we won't find it if we're
- # using a relative directory.
- cp "$am_depcomp" conftest.dir
- cd conftest.dir
- # We will build objects and dependencies in a subdirectory because
- # it helps to detect inapplicable dependency modes. For instance
- # both Tru64's cc and ICC support -MD to output dependencies as a
- # side effect of compilation, but ICC will put the dependencies in
- # the current directory while Tru64 will put them in the object
- # directory.
- mkdir sub
-
- am_cv_CXX_dependencies_compiler_type=none
- if test "$am_compiler_list" = ""; then
- am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
- fi
- for depmode in $am_compiler_list; do
- # Setup a source with many dependencies, because some compilers
- # like to wrap large dependency lists on column 80 (with \), and
- # we should not choose a depcomp mode which is confused by this.
- #
- # We need to recreate these files for each test, as the compiler may
- # overwrite some of them when testing with obscure command lines.
- # This happens at least with the AIX C compiler.
- : > sub/conftest.c
- for i in 1 2 3 4 5 6; do
- echo '#include "conftst'$i'.h"' >> sub/conftest.c
- # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
- # Solaris 8's {/usr,}/bin/sh.
- touch sub/conftst$i.h
- done
- echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
-
- case $depmode in
- nosideeffect)
- # after this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested
- if test "x$enable_dependency_tracking" = xyes; then
- continue
- else
- break
- fi
- ;;
- none) break ;;
- esac
- # We check with `-c' and `-o' for the sake of the "dashmstdout"
- # mode. It turns out that the SunPro C++ compiler does not properly
- # handle `-M -o', and we need to detect this.
- if depmode=$depmode \
- source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
- depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
- >/dev/null 2>conftest.err &&
- grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
- ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
- # icc doesn't choke on unknown options, it will just issue warnings
- # or remarks (even with -Werror). So we grep stderr for any message
- # that says an option was ignored or not supported.
- # When given -MP, icc 7.0 and 7.1 complain thusly:
- # icc: Command line warning: ignoring option '-M'; no argument required
- # The diagnosis changed in icc 8.0:
- # icc: Command line remark: option '-MP' not supported
- if (grep 'ignoring option' conftest.err ||
- grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
- am_cv_CXX_dependencies_compiler_type=$depmode
- break
- fi
- fi
- done
-
- cd ..
- rm -rf conftest.dir
-else
- am_cv_CXX_dependencies_compiler_type=none
-fi
-
-fi
-echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
-echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6
-CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
-
-
-
-if
- test "x$enable_dependency_tracking" != xno \
- && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
- am__fastdepCXX_TRUE=
- am__fastdepCXX_FALSE='#'
-else
- am__fastdepCXX_TRUE='#'
- am__fastdepCXX_FALSE=
-fi
-
-
-# Check whether --enable-shared or --disable-shared was given.
-if test "${enable_shared+set}" = set; then
- enableval="$enable_shared"
- p=${PACKAGE-default}
- case $enableval in
- yes) enable_shared=yes ;;
- no) enable_shared=no ;;
- *)
- enable_shared=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_shared=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_shared=yes
-fi;
-
-# Check whether --enable-static or --disable-static was given.
-if test "${enable_static+set}" = set; then
- enableval="$enable_static"
- p=${PACKAGE-default}
- case $enableval in
- yes) enable_static=yes ;;
- no) enable_static=no ;;
- *)
- enable_static=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_static=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_static=yes
-fi;
-
-# Check whether --enable-fast-install or --disable-fast-install was given.
-if test "${enable_fast_install+set}" = set; then
- enableval="$enable_fast_install"
- p=${PACKAGE-default}
- case $enableval in
- yes) enable_fast_install=yes ;;
- no) enable_fast_install=no ;;
- *)
- enable_fast_install=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_fast_install=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_fast_install=yes
-fi;
-
-echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
-echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6
-if test "${lt_cv_path_SED+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Loop through the user's path and test for sed and gsed.
-# Then use that list of sed's as ones to test for truncation.
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for lt_ac_prog in sed gsed; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
- lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
- fi
- done
- done
-done
-lt_ac_max=0
-lt_ac_count=0
-# Add /usr/xpg4/bin/sed as it is typically found on Solaris
-# along with /bin/sed that truncates output.
-for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
- test ! -f $lt_ac_sed && continue
- cat /dev/null > conftest.in
- lt_ac_count=0
- echo $ECHO_N "0123456789$ECHO_C" >conftest.in
- # Check for GNU sed and select it if it is found.
- if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
- lt_cv_path_SED=$lt_ac_sed
- break
- fi
- while true; do
- cat conftest.in conftest.in >conftest.tmp
- mv conftest.tmp conftest.in
- cp conftest.in conftest.nl
- echo >>conftest.nl
- $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
- cmp -s conftest.out conftest.nl || break
- # 10000 chars as input seems more than enough
- test $lt_ac_count -gt 10 && break
- lt_ac_count=`expr $lt_ac_count + 1`
- if test $lt_ac_count -gt $lt_ac_max; then
- lt_ac_max=$lt_ac_count
- lt_cv_path_SED=$lt_ac_sed
- fi
- done
-done
-
-fi
-
-SED=$lt_cv_path_SED
-echo "$as_me:$LINENO: result: $SED" >&5
-echo "${ECHO_T}$SED" >&6
-
-echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6
-if test "${ac_cv_prog_egrep+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if echo a | (grep -E '(a|b)') >/dev/null 2>&1
- then ac_cv_prog_egrep='grep -E'
- else ac_cv_prog_egrep='egrep'
- fi
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
-echo "${ECHO_T}$ac_cv_prog_egrep" >&6
- EGREP=$ac_cv_prog_egrep
-
-
-
-# Check whether --with-gnu-ld or --without-gnu-ld was given.
-if test "${with_gnu_ld+set}" = set; then
- withval="$with_gnu_ld"
- test "$withval" = no || with_gnu_ld=yes
-else
- with_gnu_ld=no
-fi;
-ac_prog=ld
-if test "$GCC" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- echo "$as_me:$LINENO: checking for ld used by $CC" >&5
-echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
- case $host in
- *-*-mingw*)
- # gcc leaves a trailing carriage return which upsets mingw
- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
- *)
- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
- esac
- case $ac_prog in
- # Accept absolute paths.
- [\\/]* | ?:[\\/]*)
- re_direlt='/[^/][^/]*/\.\./'
- # Canonicalize the pathname of ld
- ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
- while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we aren't using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
-elif test "$with_gnu_ld" = yes; then
- echo "$as_me:$LINENO: checking for GNU ld" >&5
-echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
-else
- echo "$as_me:$LINENO: checking for non-GNU ld" >&5
-echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
-fi
-if test "${lt_cv_path_LD+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -z "$LD"; then
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- lt_cv_path_LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some variants of GNU ld only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
- *GNU* | *'with BFD'*)
- test "$with_gnu_ld" != no && break
- ;;
- *)
- test "$with_gnu_ld" != yes && break
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
-else
- lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi
-fi
-
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
- echo "$as_me:$LINENO: result: $LD" >&5
-echo "${ECHO_T}$LD" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
-echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
- { (exit 1); exit 1; }; }
-echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
-echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
-if test "${lt_cv_prog_gnu_ld+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # I'd rather use --version here, but apparently some GNU lds only accept -v.
-case `$LD -v 2>&1 </dev/null` in
-*GNU* | *'with BFD'*)
- lt_cv_prog_gnu_ld=yes
- ;;
-*)
- lt_cv_prog_gnu_ld=no
- ;;
-esac
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
-echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
-with_gnu_ld=$lt_cv_prog_gnu_ld
-
-
-echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
-echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
-if test "${lt_cv_ld_reload_flag+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_ld_reload_flag='-r'
-fi
-echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
-echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
-reload_flag=$lt_cv_ld_reload_flag
-case $reload_flag in
-"" | " "*) ;;
-*) reload_flag=" $reload_flag" ;;
-esac
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-case $host_os in
- darwin*)
- if test "$GCC" = yes; then
- reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
- else
- reload_cmds='$LD$reload_flag -o $output$reload_objs'
- fi
- ;;
-esac
-
-echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
-echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
-if test "${lt_cv_path_NM+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$NM"; then
- # Let the user override the test.
- lt_cv_path_NM="$NM"
-else
- lt_nm_to_check="${ac_tool_prefix}nm"
- if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
- lt_nm_to_check="$lt_nm_to_check nm"
- fi
- for lt_tmp_nm in $lt_nm_to_check; do
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- tmp_nm="$ac_dir/$lt_tmp_nm"
- if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
- # Check to see if the nm accepts a BSD-compat flag.
- # Adding the `sed 1q' prevents false positives on HP-UX, which says:
- # nm: unknown option "B" ignored
- # Tru64's nm complains that /dev/null is an invalid object file
- case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
- */dev/null* | *'Invalid file or object type'*)
- lt_cv_path_NM="$tmp_nm -B"
- break
- ;;
- *)
- case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
- */dev/null*)
- lt_cv_path_NM="$tmp_nm -p"
- break
- ;;
- *)
- lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
- continue # so that we can try to find one that supports BSD flags
- ;;
- esac
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
- done
- test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
-fi
-fi
-echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
-echo "${ECHO_T}$lt_cv_path_NM" >&6
-NM="$lt_cv_path_NM"
-
-echo "$as_me:$LINENO: checking whether ln -s works" >&5
-echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-else
- echo "$as_me:$LINENO: result: no, using $LN_S" >&5
-echo "${ECHO_T}no, using $LN_S" >&6
-fi
-
-echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
-echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6
-if test "${lt_cv_deplibs_check_method+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [[regex]]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given extended regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-
-case $host_os in
-aix4* | aix5*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-beos*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-bsdi[45]*)
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
- lt_cv_file_magic_cmd='/usr/bin/file -L'
- lt_cv_file_magic_test_file=/shlib/libc.so
- ;;
-
-cygwin*)
- # func_win32_libid is a shell function defined in ltmain.sh
- lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
- lt_cv_file_magic_cmd='func_win32_libid'
- ;;
-
-mingw* | pw32*)
- # Base MSYS/MinGW do not provide the 'file' command needed by
- # func_win32_libid shell function, so use a weaker test based on 'objdump'.
- lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
- lt_cv_file_magic_cmd='$OBJDUMP -f'
- ;;
-
-darwin* | rhapsody*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-freebsd* | kfreebsd*-gnu | dragonfly*)
- if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
- case $host_cpu in
- i*86 )
- # Not sure whether the presence of OpenBSD here was a mistake.
- # Let's accept both of them until this is cleared up.
- lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
- ;;
- esac
- else
- lt_cv_deplibs_check_method=pass_all
- fi
- ;;
-
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-hpux10.20* | hpux11*)
- lt_cv_file_magic_cmd=/usr/bin/file
- case $host_cpu in
- ia64*)
- lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
- lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
- ;;
- hppa*64*)
- lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
- lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
- ;;
- *)
- lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
- lt_cv_file_magic_test_file=/usr/lib/libc.sl
- ;;
- esac
- ;;
-
-interix3*)
- # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $LD in
- *-32|*"-32 ") libmagic=32-bit;;
- *-n32|*"-n32 ") libmagic=N32;;
- *-64|*"-64 ") libmagic=64-bit;;
- *) libmagic=never-match;;
- esac
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-# This must be Linux ELF.
-linux*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
- fi
- ;;
-
-newos6*)
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
- lt_cv_file_magic_cmd=/usr/bin/file
- lt_cv_file_magic_test_file=/usr/lib/libnls.so
- ;;
-
-nto-qnx*)
- lt_cv_deplibs_check_method=unknown
- ;;
-
-openbsd*)
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
- else
- lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
- fi
- ;;
-
-osf3* | osf4* | osf5*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-solaris*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
-sysv4 | sysv4.3*)
- case $host_vendor in
- motorola)
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
- lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
- ;;
- ncr)
- lt_cv_deplibs_check_method=pass_all
- ;;
- sequent)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
- ;;
- sni)
- lt_cv_file_magic_cmd='/bin/file'
- lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
- lt_cv_file_magic_test_file=/lib/libc.so
- ;;
- siemens)
- lt_cv_deplibs_check_method=pass_all
- ;;
- pc)
- lt_cv_deplibs_check_method=pass_all
- ;;
- esac
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-esac
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
-echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
-file_magic_cmd=$lt_cv_file_magic_cmd
-deplibs_check_method=$lt_cv_deplibs_check_method
-test -z "$deplibs_check_method" && deplibs_check_method=unknown
-
-
-
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
-if test "${enable_libtool_lock+set}" = set; then
- enableval="$enable_libtool_lock"
-
-fi;
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case $host in
-ia64-*-hpux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- case `/usr/bin/file conftest.$ac_objext` in
- *ELF-32*)
- HPUX_IA64_MODE="32"
- ;;
- *ELF-64*)
- HPUX_IA64_MODE="64"
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-*-*-irix6*)
- # Find out which ABI we are using.
- echo '#line 4159 "configure"' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- if test "$lt_cv_prog_gnu_ld" = yes; then
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -melf32bsmip"
- ;;
- *N32*)
- LD="${LD-ld} -melf32bmipn32"
- ;;
- *64-bit*)
- LD="${LD-ld} -melf64bmip"
- ;;
- esac
- else
- case `/usr/bin/file conftest.$ac_objext` in
- *32-bit*)
- LD="${LD-ld} -32"
- ;;
- *N32*)
- LD="${LD-ld} -n32"
- ;;
- *64-bit*)
- LD="${LD-ld} -64"
- ;;
- esac
- fi
- fi
- rm -rf conftest*
- ;;
-
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- case `/usr/bin/file conftest.o` in
- *32-bit*)
- case $host in
- x86_64-*linux*)
- LD="${LD-ld} -m elf_i386"
- ;;
- ppc64-*linux*|powerpc64-*linux*)
- LD="${LD-ld} -m elf32ppclinux"
- ;;
- s390x-*linux*)
- LD="${LD-ld} -m elf_s390"
- ;;
- sparc64-*linux*)
- LD="${LD-ld} -m elf32_sparc"
- ;;
- esac
- ;;
- *64-bit*)
- case $host in
- x86_64-*linux*)
- LD="${LD-ld} -m elf_x86_64"
- ;;
- ppc*-*linux*|powerpc*-*linux*)
- LD="${LD-ld} -m elf64ppc"
- ;;
- s390*-*linux*)
- LD="${LD-ld} -m elf64_s390"
- ;;
- sparc*-*linux*)
- LD="${LD-ld} -m elf64_sparc"
- ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-
-*-*-sco3.2v5*)
- # On SCO OpenServer 5, we need -belf to get full-featured binaries.
- SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -belf"
- echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
-echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
-if test "${lt_cv_cc_needs_belf+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- lt_cv_cc_needs_belf=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-lt_cv_cc_needs_belf=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
-echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
- if test x"$lt_cv_cc_needs_belf" != x"yes"; then
- # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
- CFLAGS="$SAVE_CFLAGS"
- fi
- ;;
-sparc*-*solaris*)
- # Find out which ABI we are using.
- echo 'int i;' > conftest.$ac_ext
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- case `/usr/bin/file conftest.o` in
- *64-bit*)
- case $lt_cv_prog_gnu_ld in
- yes*) LD="${LD-ld} -m elf64_sparc" ;;
- *) LD="${LD-ld} -64" ;;
- esac
- ;;
- esac
- fi
- rm -rf conftest*
- ;;
-
-
-esac
-
-need_locks="$enable_libtool_lock"
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if test "${ac_cv_prog_CPP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether non-existent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether non-existent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- :
-else
- { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
-if test "${ac_cv_header_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_header_stdc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_header_stdc=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then
- :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then
- :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then
- :
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ctype.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- exit(2);
- exit (0);
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-fi
-fi
-echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-
-
-
-
-
-
-
-
-
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- eval "$as_ac_Header=yes"
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_Header=no"
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-
-for ac_header in dlfcn.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------------ ##
-## Report this to google-talk-open@googlegroups.com ##
-## ------------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-
-if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
- ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
- (test "X$CXX" != "Xg++"))) ; then
- ac_ext=cc
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
-echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6
-if test -z "$CXXCPP"; then
- if test "${ac_cv_prog_CXXCPP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # Double quotes because CXXCPP needs to be expanded
- for CXXCPP in "$CXX -E" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_cxx_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_cxx_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether non-existent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_cxx_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- break
-fi
-
- done
- ac_cv_prog_CXXCPP=$CXXCPP
-
-fi
- CXXCPP=$ac_cv_prog_CXXCPP
-else
- ac_cv_prog_CXXCPP=$CXXCPP
-fi
-echo "$as_me:$LINENO: result: $CXXCPP" >&5
-echo "${ECHO_T}$CXXCPP" >&6
-ac_preproc_ok=false
-for ac_cxx_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_cxx_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether non-existent headers
- # can be detected and how.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_cxx_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- # Broken: success on invalid input.
-continue
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
- :
-else
- { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-ac_ext=cc
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
-fi
-
-
-ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_F77+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$F77"; then
- ac_cv_prog_F77="$F77" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-F77=$ac_cv_prog_F77
-if test -n "$F77"; then
- echo "$as_me:$LINENO: result: $F77" >&5
-echo "${ECHO_T}$F77" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$F77" && break
- done
-fi
-if test -z "$F77"; then
- ac_ct_F77=$F77
- for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_F77"; then
- ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_F77="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_F77=$ac_cv_prog_ac_ct_F77
-if test -n "$ac_ct_F77"; then
- echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
-echo "${ECHO_T}$ac_ct_F77" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$ac_ct_F77" && break
-done
-
- F77=$ac_ct_F77
-fi
-
-
-# Provide some information about the compiler.
-echo "$as_me:5290:" \
- "checking for Fortran 77 compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
- (eval $ac_compiler --version </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
- (eval $ac_compiler -v </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
- (eval $ac_compiler -V </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-rm -f a.out
-
-# If we don't use `.F' as extension, the preprocessor is not run on the
-# input file. (Note that this only needs to work for GNU compilers.)
-ac_save_ext=$ac_ext
-ac_ext=F
-echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6
-if test "${ac_cv_f77_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
- program main
-#ifndef __GNUC__
- choke me
-#endif
-
- end
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_compiler_gnu=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_f77_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6
-ac_ext=$ac_save_ext
-ac_test_FFLAGS=${FFLAGS+set}
-ac_save_FFLAGS=$FFLAGS
-FFLAGS=
-echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
-echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_f77_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- FFLAGS=-g
-cat >conftest.$ac_ext <<_ACEOF
- program main
-
- end
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_f77_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_f77_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
-echo "${ECHO_T}$ac_cv_prog_f77_g" >&6
-if test "$ac_test_FFLAGS" = set; then
- FFLAGS=$ac_save_FFLAGS
-elif test $ac_cv_prog_f77_g = yes; then
- if test "x$ac_cv_f77_compiler_gnu" = xyes; then
- FFLAGS="-g -O2"
- else
- FFLAGS="-g"
- fi
-else
- if test "x$ac_cv_f77_compiler_gnu" = xyes; then
- FFLAGS="-O2"
- else
- FFLAGS=
- fi
-fi
-
-G77=`test $ac_compiler_gnu = yes && echo yes`
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
-
-# find the maximum length of command line arguments
-echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
-echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6
-if test "${lt_cv_sys_max_cmd_len+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- i=0
- teststring="ABCD"
-
- case $build_os in
- msdosdjgpp*)
- # On DJGPP, this test can blow up pretty badly due to problems in libc
- # (any single argument exceeding 2000 bytes causes a buffer overrun
- # during glob expansion). Even if it were fixed, the result of this
- # check would be larger than it should be.
- lt_cv_sys_max_cmd_len=12288; # 12K is about right
- ;;
-
- gnu*)
- # Under GNU Hurd, this test is not required because there is
- # no limit to the length of command line arguments.
- # Libtool will interpret -1 as no limit whatsoever
- lt_cv_sys_max_cmd_len=-1;
- ;;
-
- cygwin* | mingw*)
- # On Win9x/ME, this test blows up -- it succeeds, but takes
- # about 5 minutes as the teststring grows exponentially.
- # Worse, since 9x/ME are not pre-emptively multitasking,
- # you end up with a "frozen" computer, even though with patience
- # the test eventually succeeds (with a max line length of 256k).
- # Instead, let's just punt: use the minimum linelength reported by
- # all of the supported platforms: 8192 (on NT/2K/XP).
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- amigaos*)
- # On AmigaOS with pdksh, this test takes hours, literally.
- # So we just punt and use a minimum line length of 8192.
- lt_cv_sys_max_cmd_len=8192;
- ;;
-
- netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
- # This has been around since 386BSD, at least. Likely further.
- if test -x /sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
- elif test -x /usr/sbin/sysctl; then
- lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
- else
- lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
- fi
- # And add a safety zone
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
- ;;
-
- interix*)
- # We know the value 262144 and hardcode it with a safety zone (like BSD)
- lt_cv_sys_max_cmd_len=196608
- ;;
-
- osf*)
- # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
- # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
- # nice to cause kernel panics so lets avoid the loop below.
- # First set a reasonable default.
- lt_cv_sys_max_cmd_len=16384
- #
- if test -x /sbin/sysconfig; then
- case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
- *1*) lt_cv_sys_max_cmd_len=-1 ;;
- esac
- fi
- ;;
- sco3.2v5*)
- lt_cv_sys_max_cmd_len=102400
- ;;
- sysv5* | sco5v6* | sysv4.2uw2*)
- kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
- if test -n "$kargmax"; then
- lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
- else
- lt_cv_sys_max_cmd_len=32768
- fi
- ;;
- *)
- # If test is not a shell built-in, we'll probably end up computing a
- # maximum length that is only half of the actual maximum length, but
- # we can't tell.
- SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
- while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
- = "XX$teststring") >/dev/null 2>&1 &&
- new_result=`expr "X$teststring" : ".*" 2>&1` &&
- lt_cv_sys_max_cmd_len=$new_result &&
- test $i != 17 # 1/2 MB should be enough
- do
- i=`expr $i + 1`
- teststring=$teststring$teststring
- done
- teststring=
- # Add a significant safety factor because C++ compilers can tack on massive
- # amounts of additional arguments before passing them to the linker.
- # It appears as though 1/2 is a usable value.
- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
- ;;
- esac
-
-fi
-
-if test -n $lt_cv_sys_max_cmd_len ; then
- echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
-echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6
-else
- echo "$as_me:$LINENO: result: none" >&5
-echo "${ECHO_T}none" >&6
-fi
-
-
-
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
-echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6
-if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix. What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Transform an extracted symbol line into a proper C declaration
-lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
-
-# Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
-
-# Define system-specific variables.
-case $host_os in
-aix*)
- symcode='[BCDT]'
- ;;
-cygwin* | mingw* | pw32*)
- symcode='[ABCDGISTW]'
- ;;
-hpux*) # Its linker distinguishes data from code symbols
- if test "$host_cpu" = ia64; then
- symcode='[ABCDEGRST]'
- fi
- lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
- lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
- ;;
-linux*)
- if test "$host_cpu" = ia64; then
- symcode='[ABCDGIRSTW]'
- lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
- lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
- fi
- ;;
-irix* | nonstopux*)
- symcode='[BCDEGRST]'
- ;;
-osf*)
- symcode='[BCDEGQRST]'
- ;;
-solaris*)
- symcode='[BDRT]'
- ;;
-sco3.2v5*)
- symcode='[DT]'
- ;;
-sysv4.2uw2*)
- symcode='[DT]'
- ;;
-sysv5* | sco5v6* | unixware* | OpenUNIX*)
- symcode='[ABDT]'
- ;;
-sysv4)
- symcode='[DFNSTU]'
- ;;
-esac
-
-# Handle CRLF in mingw tool chain
-opt_cr=
-case $build_os in
-mingw*)
- opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
- ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-case `$NM -V 2>&1` in
-*GNU* | *'with BFD'*)
- symcode='[ABCDGIRSTW]' ;;
-esac
-
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
-
- # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
- symxfrm="\\1 $ac_symprfx\\2 \\2"
-
- # Write the raw and C identifiers.
- lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
-
- # Check to see that the pipe works correctly.
- pipe_works=no
-
- rm -f conftest*
- cat > conftest.$ac_ext <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-int main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
-
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # Now try to grab the symbols.
- nlist=conftest.nm
- if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
- (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s "$nlist"; then
- # Try sorting and uniquifying the output.
- if sort "$nlist" | uniq > "$nlist"T; then
- mv -f "$nlist"T "$nlist"
- else
- rm -f "$nlist"T
- fi
-
- # Make sure that we snagged all the symbols we need.
- if grep ' nm_test_var$' "$nlist" >/dev/null; then
- if grep ' nm_test_func$' "$nlist" >/dev/null; then
- cat <<EOF > conftest.$ac_ext
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
- # Now generate the symbol file.
- eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
-
- cat <<EOF >> conftest.$ac_ext
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
- const char *name;
- lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{
-EOF
- $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
- cat <<\EOF >> conftest.$ac_ext
- {0, (lt_ptr_t) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
- # Now try linking the two files.
- mv conftest.$ac_objext conftstm.$ac_objext
- lt_save_LIBS="$LIBS"
- lt_save_CFLAGS="$CFLAGS"
- LIBS="conftstm.$ac_objext"
- CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
- if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s conftest${ac_exeext}; then
- pipe_works=yes
- fi
- LIBS="$lt_save_LIBS"
- CFLAGS="$lt_save_CFLAGS"
- else
- echo "cannot find nm_test_func in $nlist" >&5
- fi
- else
- echo "cannot find nm_test_var in $nlist" >&5
- fi
- else
- echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
- fi
- else
- echo "$progname: failed program was:" >&5
- cat conftest.$ac_ext >&5
- fi
- rm -f conftest* conftst*
-
- # Do not use the global_symbol_pipe unless it works.
- if test "$pipe_works" = yes; then
- break
- else
- lt_cv_sys_global_symbol_pipe=
- fi
-done
-
-fi
-
-if test -z "$lt_cv_sys_global_symbol_pipe"; then
- lt_cv_sys_global_symbol_to_cdecl=
-fi
-if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
- echo "$as_me:$LINENO: result: failed" >&5
-echo "${ECHO_T}failed" >&6
-else
- echo "$as_me:$LINENO: result: ok" >&5
-echo "${ECHO_T}ok" >&6
-fi
-
-echo "$as_me:$LINENO: checking for objdir" >&5
-echo $ECHO_N "checking for objdir... $ECHO_C" >&6
-if test "${lt_cv_objdir+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
- lt_cv_objdir=.libs
-else
- # MS-DOS does not allow filenames that begin with a dot.
- lt_cv_objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-fi
-echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
-echo "${ECHO_T}$lt_cv_objdir" >&6
-objdir=$lt_cv_objdir
-
-
-
-
-
-case $host_os in
-aix3*)
- # AIX sometimes has problems with the GCC collect2 program. For some
- # reason, if we set the COLLECT_NAMES environment variable, the problems
- # vanish in a puff of smoke.
- if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
- fi
- ;;
-esac
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
-# Constants:
-rm="rm -f"
-
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
-
-# All known linkers require a `.a' archive for static linking (except MSVC,
-# which needs '.lib').
-libext=a
-ltmain="$ac_aux_dir/ltmain.sh"
-ofile="$default_ofile"
-with_gnu_ld="$lt_cv_prog_gnu_ld"
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ar; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_AR+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$AR"; then
- ac_cv_prog_AR="$AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_AR="${ac_tool_prefix}ar"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-AR=$ac_cv_prog_AR
-if test -n "$AR"; then
- echo "$as_me:$LINENO: result: $AR" >&5
-echo "${ECHO_T}$AR" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_AR"; then
- ac_ct_AR=$AR
- # Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_AR"; then
- ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_AR="ar"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
- test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false"
-fi
-fi
-ac_ct_AR=$ac_cv_prog_ac_ct_AR
-if test -n "$ac_ct_AR"; then
- echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
-echo "${ECHO_T}$ac_ct_AR" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- AR=$ac_ct_AR
-else
- AR="$ac_cv_prog_AR"
-fi
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_RANLIB+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
- echo "$as_me:$LINENO: result: $RANLIB" >&5
-echo "${ECHO_T}$RANLIB" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
- ac_ct_RANLIB=$RANLIB
- # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_RANLIB"; then
- ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_RANLIB="ranlib"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
- test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
- echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
-echo "${ECHO_T}$ac_ct_RANLIB" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- RANLIB=$ac_ct_RANLIB
-else
- RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_STRIP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$STRIP"; then
- ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_STRIP="${ac_tool_prefix}strip"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
- echo "$as_me:$LINENO: result: $STRIP" >&5
-echo "${ECHO_T}$STRIP" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_STRIP"; then
- ac_ct_STRIP=$STRIP
- # Extract the first word of "strip", so it can be a program name with args.
-set dummy strip; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_STRIP"; then
- ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_STRIP="strip"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
- test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
-fi
-fi
-ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
-if test -n "$ac_ct_STRIP"; then
- echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
-echo "${ECHO_T}$ac_ct_STRIP" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- STRIP=$ac_ct_STRIP
-else
- STRIP="$ac_cv_prog_STRIP"
-fi
-
-
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-
-# Set sane defaults for various variables
-test -z "$AR" && AR=ar
-test -z "$AR_FLAGS" && AR_FLAGS=cru
-test -z "$AS" && AS=as
-test -z "$CC" && CC=cc
-test -z "$LTCC" && LTCC=$CC
-test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$LD" && LD=ld
-test -z "$LN_S" && LN_S="ln -s"
-test -z "$MAGIC_CMD" && MAGIC_CMD=file
-test -z "$NM" && NM=nm
-test -z "$SED" && SED=sed
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$RANLIB" && RANLIB=:
-test -z "$STRIP" && STRIP=:
-test -z "$ac_objext" && ac_objext=o
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-if test -n "$RANLIB"; then
- case $host_os in
- openbsd*)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
- ;;
- *)
- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
- ;;
- esac
- old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-fi
-
-for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
-
-# Only perform the check for file, if the check method requires it
-case $deplibs_check_method in
-file_magic*)
- if test "$file_magic_cmd" = '$MAGIC_CMD'; then
- echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
-echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
-if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $MAGIC_CMD in
-[\\/*] | ?:[\\/]*)
- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
- ;;
-*)
- lt_save_MAGIC_CMD="$MAGIC_CMD"
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
- for ac_dir in $ac_dummy; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/${ac_tool_prefix}file; then
- lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
- if test -n "$file_magic_test_file"; then
- case $deplibs_check_method in
- "file_magic "*)
- file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- $EGREP "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
- fi ;;
- esac
- fi
- break
- fi
- done
- IFS="$lt_save_ifs"
- MAGIC_CMD="$lt_save_MAGIC_CMD"
- ;;
-esac
-fi
-
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
- echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
-echo "${ECHO_T}$MAGIC_CMD" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-if test -z "$lt_cv_path_MAGIC_CMD"; then
- if test -n "$ac_tool_prefix"; then
- echo "$as_me:$LINENO: checking for file" >&5
-echo $ECHO_N "checking for file... $ECHO_C" >&6
-if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $MAGIC_CMD in
-[\\/*] | ?:[\\/]*)
- lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
- ;;
-*)
- lt_save_MAGIC_CMD="$MAGIC_CMD"
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
- for ac_dir in $ac_dummy; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/file; then
- lt_cv_path_MAGIC_CMD="$ac_dir/file"
- if test -n "$file_magic_test_file"; then
- case $deplibs_check_method in
- "file_magic "*)
- file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
- MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
- if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
- $EGREP "$file_magic_regex" > /dev/null; then
- :
- else
- cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such. This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem. Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
- fi ;;
- esac
- fi
- break
- fi
- done
- IFS="$lt_save_ifs"
- MAGIC_CMD="$lt_save_MAGIC_CMD"
- ;;
-esac
-fi
-
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
- echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
-echo "${ECHO_T}$MAGIC_CMD" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- else
- MAGIC_CMD=:
- fi
-fi
-
- fi
- ;;
-esac
-
-enable_dlopen=no
-enable_win32_dll=no
-
-# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
-if test "${enable_libtool_lock+set}" = set; then
- enableval="$enable_libtool_lock"
-
-fi;
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-
-# Check whether --with-pic or --without-pic was given.
-if test "${with_pic+set}" = set; then
- withval="$with_pic"
- pic_mode="$withval"
-else
- pic_mode=default
-fi;
-test -z "$pic_mode" && pic_mode=default
-
-# Use C for the default configuration in the libtool script
-tagname=
-lt_save_CC="$CC"
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-# Source file extension for C test sources.
-ac_ext=c
-
-# Object file extension for compiled C test sources.
-objext=o
-objext=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(){return(0);}\n'
-
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$rm conftest*
-
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$rm conftest*
-
-
-
-lt_prog_compiler_no_builtin_flag=
-
-if test "$GCC" = yes; then
- lt_prog_compiler_no_builtin_flag=' -fno-builtin'
-
-
-echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
-if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_prog_compiler_rtti_exceptions=no
- ac_outfile=conftest.$ac_objext
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="-fno-rtti -fno-exceptions"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6351: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:6355: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_rtti_exceptions=yes
- fi
- fi
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
-
-if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
- lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
-else
- :
-fi
-
-fi
-
-lt_prog_compiler_wl=
-lt_prog_compiler_pic=
-lt_prog_compiler_static=
-
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
-
- if test "$GCC" = yes; then
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_static='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static='-Bstatic'
- fi
- ;;
-
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
- ;;
-
- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic='-DDLL_EXPORT'
- ;;
-
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- lt_prog_compiler_pic='-fno-common'
- ;;
-
- interix3*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
-
- msdosdjgpp*)
- # Just because we use GCC doesn't mean we suddenly get shared libraries
- # on systems that don't support them.
- lt_prog_compiler_can_build_shared=no
- enable_shared=no
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- lt_prog_compiler_pic=-Kconform_pic
- fi
- ;;
-
- hpux*)
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic='-fPIC'
- ;;
- esac
- ;;
-
- *)
- lt_prog_compiler_pic='-fPIC'
- ;;
- esac
- else
- # PORTME Check for flag to pass linker flags through the system compiler.
- case $host_os in
- aix*)
- lt_prog_compiler_wl='-Wl,'
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static='-Bstatic'
- else
- lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- darwin*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- case $cc_basename in
- xlc*)
- lt_prog_compiler_pic='-qnocommon'
- lt_prog_compiler_wl='-Wl,'
- ;;
- esac
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic='-DDLL_EXPORT'
- ;;
-
- hpux9* | hpux10* | hpux11*)
- lt_prog_compiler_wl='-Wl,'
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic='+Z'
- ;;
- esac
- # Is there a better lt_prog_compiler_static that works with the bundled CC?
- lt_prog_compiler_static='${wl}-a ${wl}archive'
- ;;
-
- irix5* | irix6* | nonstopux*)
- lt_prog_compiler_wl='-Wl,'
- # PIC (with -KPIC) is the default.
- lt_prog_compiler_static='-non_shared'
- ;;
-
- newsos6)
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- linux*)
- case $cc_basename in
- icc* | ecc*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-static'
- ;;
- pgcc* | pgf77* | pgf90* | pgf95*)
- # Portland Group compilers (*not* the Pentium gcc compiler,
- # which looks to be a dead project)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-fpic'
- lt_prog_compiler_static='-Bstatic'
- ;;
- ccc*)
- lt_prog_compiler_wl='-Wl,'
- # All Alpha code is PIC.
- lt_prog_compiler_static='-non_shared'
- ;;
- esac
- ;;
-
- osf3* | osf4* | osf5*)
- lt_prog_compiler_wl='-Wl,'
- # All OSF/1 code is PIC.
- lt_prog_compiler_static='-non_shared'
- ;;
-
- solaris*)
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- case $cc_basename in
- f77* | f90* | f95*)
- lt_prog_compiler_wl='-Qoption ld ';;
- *)
- lt_prog_compiler_wl='-Wl,';;
- esac
- ;;
-
- sunos4*)
- lt_prog_compiler_wl='-Qoption ld '
- lt_prog_compiler_pic='-PIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec ;then
- lt_prog_compiler_pic='-Kconform_pic'
- lt_prog_compiler_static='-Bstatic'
- fi
- ;;
-
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_pic='-KPIC'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- unicos*)
- lt_prog_compiler_wl='-Wl,'
- lt_prog_compiler_can_build_shared=no
- ;;
-
- uts4*)
- lt_prog_compiler_pic='-pic'
- lt_prog_compiler_static='-Bstatic'
- ;;
-
- *)
- lt_prog_compiler_can_build_shared=no
- ;;
- esac
- fi
-
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic" >&6
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$lt_prog_compiler_pic"; then
-
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6
-if test "${lt_prog_compiler_pic_works+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_pic_works=no
- ac_outfile=conftest.$ac_objext
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6619: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:6623: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_pic_works=yes
- fi
- fi
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6
-
-if test x"$lt_prog_compiler_pic_works" = xyes; then
- case $lt_prog_compiler_pic in
- "" | " "*) ;;
- *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
- esac
-else
- lt_prog_compiler_pic=
- lt_prog_compiler_can_build_shared=no
-fi
-
-fi
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- lt_prog_compiler_pic=
- ;;
- *)
- lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
- ;;
-esac
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
-if test "${lt_prog_compiler_static_works+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_static_works=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
- printf "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_static_works=yes
- fi
- else
- lt_prog_compiler_static_works=yes
- fi
- fi
- $rm conftest*
- LDFLAGS="$save_LDFLAGS"
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works" >&6
-
-if test x"$lt_prog_compiler_static_works" = xyes; then
- :
-else
- lt_prog_compiler_static=
-fi
-
-
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
-if test "${lt_cv_prog_compiler_c_o+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_prog_compiler_c_o=no
- $rm -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6723: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&5
- echo "$as_me:6727: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_c_o=yes
- fi
- fi
- chmod u+w . 2>&5
- $rm conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
- $rm out/* && rmdir out
- cd ..
- rmdir conftest
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6
-
-
-hard_links="nottested"
-if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
- hard_links=yes
- $rm conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6
- if test "$hard_links" = no; then
- { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
-echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
-
- runpath_var=
- allow_undefined_flag=
- enable_shared_with_static_runtimes=no
- archive_cmds=
- archive_expsym_cmds=
- old_archive_From_new_cmds=
- old_archive_from_expsyms_cmds=
- export_dynamic_flag_spec=
- whole_archive_flag_spec=
- thread_safe_flag_spec=
- hardcode_libdir_flag_spec=
- hardcode_libdir_flag_spec_ld=
- hardcode_libdir_separator=
- hardcode_direct=no
- hardcode_minus_L=no
- hardcode_shlibpath_var=unsupported
- link_all_deplibs=unknown
- hardcode_automatic=no
- module_cmds=
- module_expsym_cmds=
- always_export_symbols=no
- export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- # include_expsyms should be a list of space-separated symbols to be *always*
- # included in the symbol list
- include_expsyms=
- # exclude_expsyms can be an extended regexp of symbols to exclude
- # it will be wrapped by ` (' and `)$', so one must not match beginning or
- # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
- # as well as any symbol that contains `d'.
- exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
- # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
- # platforms (ab)use it in PIC code, but their linkers get confused if
- # the symbol is explicitly referenced. Since portable code cannot
- # rely on this symbol name, it's probably fine to never include it in
- # preloaded symbol tables.
- extract_expsyms_cmds=
- # Just being paranoid about ensuring that cc_basename is set.
- for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
- case $host_os in
- cygwin* | mingw* | pw32*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$GCC" != yes; then
- with_gnu_ld=no
- fi
- ;;
- interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
- with_gnu_ld=yes
- ;;
- openbsd*)
- with_gnu_ld=no
- ;;
- esac
-
- ld_shlibs=yes
- if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # Set some defaults for GNU ld with shared library support. These
- # are reset later if shared libraries are not supported. Putting them
- # here allows them to be overridden if necessary.
- runpath_var=LD_RUN_PATH
- hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
- export_dynamic_flag_spec='${wl}--export-dynamic'
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
- whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- whole_archive_flag_spec=
- fi
- supports_anon_versioning=no
- case `$LD -v 2>/dev/null` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
- *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
- *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
- *\ 2.11.*) ;; # other 2.11 versions
- *) supports_anon_versioning=yes ;;
- esac
-
- # See if GNU ld supports shared libraries.
- case $host_os in
- aix3* | aix4* | aix5*)
- # On AIX/PPC, the GNU linker is very broken
- if test "$host_cpu" != ia64; then
- ld_shlibs=no
- cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
- fi
- ;;
-
- amigaos*)
- archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
-
- # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
- # that the semantics of dynamic libraries on AmigaOS, at least up
- # to version 4, is to share data among multiple programs linked
- # with the same dynamic library. Since this doesn't match the
- # behavior of shared libraries on other platforms, we can't use
- # them.
- ld_shlibs=no
- ;;
-
- beos*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- allow_undefined_flag=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- cygwin* | mingw* | pw32*)
- # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
- # as there is no search path for DLLs.
- hardcode_libdir_flag_spec='-L$libdir'
- allow_undefined_flag=unsupported
- always_export_symbols=no
- enable_shared_with_static_runtimes=yes
- export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
-
- if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- interix3*)
- hardcode_direct=no
- hardcode_shlibpath_var=no
- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
- export_dynamic_flag_spec='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
-
- linux*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- tmp_addflag=
- case $cc_basename,$host_cpu in
- pgcc*) # Portland Group C compiler
- whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag'
- ;;
- pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
- whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag -Mnomain' ;;
- ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
- tmp_addflag=' -i_dynamic' ;;
- efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
- tmp_addflag=' -i_dynamic -nofor_main' ;;
- ifc* | ifort*) # Intel Fortran compiler
- tmp_addflag=' -nofor_main' ;;
- esac
- archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
- if test $supports_anon_versioning = yes; then
- archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- $echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
- link_all_deplibs=no
- else
- ld_shlibs=no
- fi
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
- wlarc=
- else
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- fi
- ;;
-
- solaris*)
- if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
- ld_shlibs=no
- cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
- elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
- case `$LD -v 2>&1` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
- ld_shlibs=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- ;;
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
- esac
- ;;
-
- sunos4*)
- archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- wlarc=
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs=no
- fi
- ;;
- esac
-
- if test "$ld_shlibs" = no; then
- runpath_var=
- hardcode_libdir_flag_spec=
- export_dynamic_flag_spec=
- whole_archive_flag_spec=
- fi
- else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case $host_os in
- aix3*)
- allow_undefined_flag=unsupported
- always_export_symbols=yes
- archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- hardcode_minus_L=yes
- if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- hardcode_direct=unsupported
- fi
- ;;
-
- aix4* | aix5*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
- export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- else
- export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- fi
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[23]|aix4.[23].*|aix5*)
- for ld_flag in $LDFLAGS; do
- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
- aix_use_runtimelinking=yes
- break
- fi
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- archive_cmds=''
- hardcode_direct=yes
- hardcode_libdir_separator=':'
- link_all_deplibs=yes
-
- if test "$GCC" = yes; then
- case $host_os in aix4.[012]|aix4.[012].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- hardcode_direct=yes
- else
- # We have old collect2
- hardcode_direct=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- hardcode_minus_L=yes
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_libdir_separator=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- always_export_symbols=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- allow_undefined_flag='-berok'
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
- archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
- allow_undefined_flag="-z nodefs"
- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- no_undefined_flag=' ${wl}-bernotok'
- allow_undefined_flag=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- whole_archive_flag_spec='$convenience'
- archive_cmds_need_lc=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- amigaos*)
- archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- # see comment about different semantics on the GNU ld section
- ld_shlibs=no
- ;;
-
- bsdi[45]*)
- export_dynamic_flag_spec=-rdynamic
- ;;
-
- cygwin* | mingw* | pw32*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec=' '
- allow_undefined_flag=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- old_archive_From_new_cmds='true'
- # FIXME: Should let the user specify the lib program.
- old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
- fix_srcfile_path='`cygpath -w "$srcfile"`'
- enable_shared_with_static_runtimes=yes
- ;;
-
- darwin* | rhapsody*)
- case $host_os in
- rhapsody* | darwin1.[012])
- allow_undefined_flag='${wl}-undefined ${wl}suppress'
- ;;
- *) # Darwin 1.3 on
- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
- allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- else
- case ${MACOSX_DEPLOYMENT_TARGET} in
- 10.[012])
- allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- ;;
- 10.*)
- allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
- ;;
- esac
- fi
- ;;
- esac
- archive_cmds_need_lc=no
- hardcode_direct=no
- hardcode_automatic=yes
- hardcode_shlibpath_var=unsupported
- whole_archive_flag_spec=''
- link_all_deplibs=yes
- if test "$GCC" = yes ; then
- output_verbose_link_cmd='echo'
- archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- case $cc_basename in
- xlc*)
- output_verbose_link_cmd='echo'
- archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
- module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- ;;
- *)
- ld_shlibs=no
- ;;
- esac
- fi
- ;;
-
- dgux*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- freebsd1*)
- ld_shlibs=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd* | dragonfly*)
- archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- # GNU/kFreeBSD uses gcc -shared to do shared libraries.
- kfreebsd*-gnu)
- archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- link_all_deplibs=no
- ;;
-
- hpux9*)
- if test "$GCC" = yes; then
- archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- fi
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator=:
- hardcode_direct=yes
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L=yes
- export_dynamic_flag_spec='${wl}-E'
- ;;
-
- hpux10*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator=:
-
- hardcode_direct=yes
- export_dynamic_flag_spec='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L=yes
- fi
- ;;
-
- hpux11*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- case $host_cpu in
- hppa*64*)
- archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- else
- case $host_cpu in
- hppa*64*)
- archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- hardcode_libdir_flag_spec_ld='+b $libdir'
- hardcode_direct=no
- hardcode_shlibpath_var=no
- ;;
- *)
- hardcode_direct=yes
- export_dynamic_flag_spec='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L=yes
- ;;
- esac
- fi
- ;;
-
- irix5* | irix6* | nonstopux*)
- if test "$GCC" = yes; then
- archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- hardcode_libdir_flag_spec_ld='-rpath $libdir'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- link_all_deplibs=yes
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
- else
- archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
- fi
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- ;;
-
- newsos6)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=yes
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- hardcode_shlibpath_var=no
- ;;
-
- openbsd*)
- hardcode_direct=yes
- hardcode_shlibpath_var=no
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
- export_dynamic_flag_spec='${wl}-E'
- else
- case $host_os in
- openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec='-R$libdir'
- ;;
- *)
- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
- ;;
- esac
- fi
- ;;
-
- os2*)
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_minus_L=yes
- allow_undefined_flag=unsupported
- archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
- old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$GCC" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator=:
- ;;
-
- osf4* | osf5*) # as osf3* with the addition of -msym flag
- if test "$GCC" = yes; then
- allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
- else
- allow_undefined_flag=' -expect_unresolved \*'
- archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
- $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
-
- # Both c and cxx compiler support -rpath directly
- hardcode_libdir_flag_spec='-rpath $libdir'
- fi
- hardcode_libdir_separator=:
- ;;
-
- solaris*)
- no_undefined_flag=' -z text'
- if test "$GCC" = yes; then
- wlarc='${wl}'
- archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
- else
- wlarc=''
- archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
- archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
- fi
- hardcode_libdir_flag_spec='-R$libdir'
- hardcode_shlibpath_var=no
- case $host_os in
- solaris2.[0-5] | solaris2.[0-5].*) ;;
- *)
- # The compiler driver will combine linker options so we
- # cannot just pass the convience library names through
- # without $wl, iff we do not link with $LD.
- # Luckily, gcc supports the same syntax we need for Sun Studio.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- case $wlarc in
- '')
- whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
- *)
- whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
- esac ;;
- esac
- link_all_deplibs=yes
- ;;
-
- sunos4*)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
- fi
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_direct=yes
- hardcode_minus_L=yes
- hardcode_shlibpath_var=no
- ;;
-
- sysv4)
- case $host_vendor in
- sni)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=yes # is this really true???
- ;;
- siemens)
- ## LD is ld it makes a PLAMLIB
- ## CC just makes a GrossModule.
- archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
- reload_cmds='$CC -r -o $output$reload_objs'
- hardcode_direct=no
- ;;
- motorola)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct=no #Motorola manual says yes, but my tests say they lie
- ;;
- esac
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var=no
- ;;
-
- sysv4.3*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var=no
- export_dynamic_flag_spec='-Bexport'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ld_shlibs=yes
- fi
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
- no_undefined_flag='${wl}-z,text'
- archive_cmds_need_lc=no
- hardcode_shlibpath_var=no
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- no_undefined_flag='${wl}-z,text'
- allow_undefined_flag='${wl}-z,nodefs'
- archive_cmds_need_lc=no
- hardcode_shlibpath_var=no
- hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
- hardcode_libdir_separator=':'
- link_all_deplibs=yes
- export_dynamic_flag_spec='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- uts4*)
- archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec='-L$libdir'
- hardcode_shlibpath_var=no
- ;;
-
- *)
- ld_shlibs=no
- ;;
- esac
- fi
-
-echo "$as_me:$LINENO: result: $ld_shlibs" >&5
-echo "${ECHO_T}$ld_shlibs" >&6
-test "$ld_shlibs" = no && can_build_shared=no
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$archive_cmds_need_lc" in
-x|xyes)
- # Assume -lc should be added
- archive_cmds_need_lc=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $archive_cmds in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
- $rm conftest*
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$lt_prog_compiler_wl
- pic_flag=$lt_prog_compiler_pic
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$allow_undefined_flag
- allow_undefined_flag=
- if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
- (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
- then
- archive_cmds_need_lc=no
- else
- archive_cmds_need_lc=yes
- fi
- allow_undefined_flag=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $rm conftest*
- echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
-echo "${ECHO_T}$archive_cmds_need_lc" >&6
- ;;
- esac
- fi
- ;;
-esac
-
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix4* | aix5*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[01] | aix4.[01].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[45]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$host_os in
- yes,cygwin* | yes,mingw* | yes,pw32*)
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $rm \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
- ;;
- mingw*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
- # It is most probably a Windows format PATH printed by
- # mingw gcc, but we are running on Cygwin. Gcc prints its search
- # path with ; separators, and with drive letters. We can handle the
- # drive letters (cygwin fileutils understands them), so leave them,
- # especially as we might pass files found there to a mingw objdump,
- # which wouldn't understand a cygwinified path. Ahh.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- ;;
-
- *)
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
- if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
- else
- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
- fi
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-kfreebsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[123]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- version_type=freebsd-$objformat
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[01]* | freebsdelf3.[01]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
- freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- freebsd*) # from 4.6 on
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- ;;
-
-interix3*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsdelf*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='NetBSD ld.elf_so'
- ;;
-
-knetbsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-nto-qnx*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[89] | openbsd2.[89].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- export_dynamic_flag_spec='${wl}-Blargedynsym'
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- shlibpath_overrides_runpath=no
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- shlibpath_overrides_runpath=yes
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" || \
- test -n "$runpath_var" || \
- test "X$hardcode_automatic" = "Xyes" ; then
-
- # We can hardcode non-existant directories.
- if test "$hardcode_direct" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
- test "$hardcode_minus_L" != no; then
- # Linking always hardcodes the temporary library directory.
- hardcode_action=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- hardcode_action=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- hardcode_action=unsupported
-fi
-echo "$as_me:$LINENO: result: $hardcode_action" >&5
-echo "${ECHO_T}$hardcode_action" >&6
-
-if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-
-striplib=
-old_striplib=
-echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
-echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6
-if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
- test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
- test -z "$striplib" && striplib="$STRIP --strip-unneeded"
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-else
-# FIXME - insert some real tests, host_os isn't really good enough
- case $host_os in
- darwin*)
- if test -n "$STRIP" ; then
- striplib="$STRIP -x"
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
- else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
- ;;
- *)
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
- ;;
- esac
-fi
-
-if test "x$enable_dlopen" != xyes; then
- enable_dlopen=unknown
- enable_dlopen_self=unknown
- enable_dlopen_self_static=unknown
-else
- lt_cv_dlopen=no
- lt_cv_dlopen_libs=
-
- case $host_os in
- beos*)
- lt_cv_dlopen="load_add_on"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
- ;;
-
- mingw* | pw32*)
- lt_cv_dlopen="LoadLibrary"
- lt_cv_dlopen_libs=
- ;;
-
- cygwin*)
- lt_cv_dlopen="dlopen"
- lt_cv_dlopen_libs=
- ;;
-
- darwin*)
- # if libdl is installed we need to link against it
- echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
-echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char dlopen ();
-int
-main ()
-{
-dlopen ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_dl_dlopen=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_dl_dlopen=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
-if test $ac_cv_lib_dl_dlopen = yes; then
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
-
- lt_cv_dlopen="dyld"
- lt_cv_dlopen_libs=
- lt_cv_dlopen_self=yes
-
-fi
-
- ;;
-
- *)
- echo "$as_me:$LINENO: checking for shl_load" >&5
-echo $ECHO_N "checking for shl_load... $ECHO_C" >&6
-if test "${ac_cv_func_shl_load+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define shl_load innocuous_shl_load
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char shl_load (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef shl_load
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char shl_load ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_shl_load) || defined (__stub___shl_load)
-choke me
-#else
-char (*f) () = shl_load;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != shl_load;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_shl_load=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_func_shl_load=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
-echo "${ECHO_T}$ac_cv_func_shl_load" >&6
-if test $ac_cv_func_shl_load = yes; then
- lt_cv_dlopen="shl_load"
-else
- echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
-echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
-if test "${ac_cv_lib_dld_shl_load+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldld $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char shl_load ();
-int
-main ()
-{
-shl_load ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_dld_shl_load=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_dld_shl_load=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
-echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
-if test $ac_cv_lib_dld_shl_load = yes; then
- lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
-else
- echo "$as_me:$LINENO: checking for dlopen" >&5
-echo $ECHO_N "checking for dlopen... $ECHO_C" >&6
-if test "${ac_cv_func_dlopen+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define dlopen innocuous_dlopen
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char dlopen (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef dlopen
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char dlopen ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_dlopen) || defined (__stub___dlopen)
-choke me
-#else
-char (*f) () = dlopen;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != dlopen;
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_func_dlopen=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_func_dlopen=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
-echo "${ECHO_T}$ac_cv_func_dlopen" >&6
-if test $ac_cv_func_dlopen = yes; then
- lt_cv_dlopen="dlopen"
-else
- echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
-echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char dlopen ();
-int
-main ()
-{
-dlopen ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_dl_dlopen=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_dl_dlopen=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
-if test $ac_cv_lib_dl_dlopen = yes; then
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
- echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
-echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6
-if test "${ac_cv_lib_svld_dlopen+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsvld $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char dlopen ();
-int
-main ()
-{
-dlopen ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_svld_dlopen=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_svld_dlopen=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6
-if test $ac_cv_lib_svld_dlopen = yes; then
- lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
-else
- echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
-echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6
-if test "${ac_cv_lib_dld_dld_link+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldld $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char dld_link ();
-int
-main ()
-{
-dld_link ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_dld_dld_link=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_dld_dld_link=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
-echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6
-if test $ac_cv_lib_dld_dld_link = yes; then
- lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
- ;;
- esac
-
- if test "x$lt_cv_dlopen" != xno; then
- enable_dlopen=yes
- else
- enable_dlopen=no
- fi
-
- case $lt_cv_dlopen in
- dlopen)
- save_CPPFLAGS="$CPPFLAGS"
- test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-
- save_LDFLAGS="$LDFLAGS"
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-
- save_LIBS="$LIBS"
- LIBS="$lt_cv_dlopen_libs $LIBS"
-
- echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
-echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6
-if test "${lt_cv_dlopen_self+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "$cross_compiling" = yes; then :
- lt_cv_dlopen_self=cross
-else
- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
- lt_status=$lt_dlunknown
- cat > conftest.$ac_ext <<EOF
-#line 9081 "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LT_DLGLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LT_DLGLOBAL DL_GLOBAL
-# else
-# define LT_DLGLOBAL 0
-# endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_DLLAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_DLLAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LT_DLLAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_DLLAZY_OR_NOW DL_NOW
-# else
-# define LT_DLLAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-#ifdef __cplusplus
-extern "C" void exit (int);
-#endif
-
-void fnord() { int i=42;}
-int main ()
-{
- void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
- int status = $lt_dlunknown;
-
- if (self)
- {
- if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
- else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
- /* dlclose (self); */
- }
- else
- puts (dlerror ());
-
- exit (status);
-}
-EOF
- if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
- (./conftest; exit; ) >&5 2>/dev/null
- lt_status=$?
- case x$lt_status in
- x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
- x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
- x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
- esac
- else :
- # compilation failed
- lt_cv_dlopen_self=no
- fi
-fi
-rm -fr conftest*
-
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
-echo "${ECHO_T}$lt_cv_dlopen_self" >&6
-
- if test "x$lt_cv_dlopen_self" = xyes; then
- wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
- echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
-echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6
-if test "${lt_cv_dlopen_self_static+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test "$cross_compiling" = yes; then :
- lt_cv_dlopen_self_static=cross
-else
- lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
- lt_status=$lt_dlunknown
- cat > conftest.$ac_ext <<EOF
-#line 9181 "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LT_DLGLOBAL RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-# define LT_DLGLOBAL DL_GLOBAL
-# else
-# define LT_DLGLOBAL 0
-# endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
- find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-# ifdef RTLD_LAZY
-# define LT_DLLAZY_OR_NOW RTLD_LAZY
-# else
-# ifdef DL_LAZY
-# define LT_DLLAZY_OR_NOW DL_LAZY
-# else
-# ifdef RTLD_NOW
-# define LT_DLLAZY_OR_NOW RTLD_NOW
-# else
-# ifdef DL_NOW
-# define LT_DLLAZY_OR_NOW DL_NOW
-# else
-# define LT_DLLAZY_OR_NOW 0
-# endif
-# endif
-# endif
-# endif
-#endif
-
-#ifdef __cplusplus
-extern "C" void exit (int);
-#endif
-
-void fnord() { int i=42;}
-int main ()
-{
- void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
- int status = $lt_dlunknown;
-
- if (self)
- {
- if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
- else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
- /* dlclose (self); */
- }
- else
- puts (dlerror ());
-
- exit (status);
-}
-EOF
- if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
- (./conftest; exit; ) >&5 2>/dev/null
- lt_status=$?
- case x$lt_status in
- x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
- x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
- x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
- esac
- else :
- # compilation failed
- lt_cv_dlopen_self_static=no
- fi
-fi
-rm -fr conftest*
-
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
-echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6
- fi
-
- CPPFLAGS="$save_CPPFLAGS"
- LDFLAGS="$save_LDFLAGS"
- LIBS="$save_LIBS"
- ;;
- esac
-
- case $lt_cv_dlopen_self in
- yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
- *) enable_dlopen_self=unknown ;;
- esac
-
- case $lt_cv_dlopen_self_static in
- yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
- *) enable_dlopen_self_static=unknown ;;
- esac
-fi
-
-
-# Report which library types will actually be built
-echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
-echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $can_build_shared" >&5
-echo "${ECHO_T}$can_build_shared" >&6
-
-echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
-echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case $host_os in
-aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-
-aix4* | aix5*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
-esac
-echo "$as_me:$LINENO: result: $enable_shared" >&5
-echo "${ECHO_T}$enable_shared" >&6
-
-echo "$as_me:$LINENO: checking whether to build static libraries" >&5
-echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-echo "$as_me:$LINENO: result: $enable_static" >&5
-echo "${ECHO_T}$enable_static" >&6
-
-# The else clause should only fire when bootstrapping the
-# libtool distribution, otherwise you forgot to ship ltmain.sh
-# with your package, and you will get complaints that there are
-# no rules to generate ltmain.sh.
-if test -f "$ltmain"; then
- # See if we are running on zsh, and set the options which allow our commands through
- # without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
- # Now quote all the things that may contain metacharacters while being
- # careful not to overquote the AC_SUBSTed values. We take copies of the
- # variables and quote the copies for generation of the libtool script.
- for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
- SED SHELL STRIP \
- libname_spec library_names_spec soname_spec extract_expsyms_cmds \
- old_striplib striplib file_magic_cmd finish_cmds finish_eval \
- deplibs_check_method reload_flag reload_cmds need_locks \
- lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
- lt_cv_sys_global_symbol_to_c_name_address \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- old_postinstall_cmds old_postuninstall_cmds \
- compiler \
- CC \
- LD \
- lt_prog_compiler_wl \
- lt_prog_compiler_pic \
- lt_prog_compiler_static \
- lt_prog_compiler_no_builtin_flag \
- export_dynamic_flag_spec \
- thread_safe_flag_spec \
- whole_archive_flag_spec \
- enable_shared_with_static_runtimes \
- old_archive_cmds \
- old_archive_from_new_cmds \
- predep_objects \
- postdep_objects \
- predeps \
- postdeps \
- compiler_lib_search_path \
- archive_cmds \
- archive_expsym_cmds \
- postinstall_cmds \
- postuninstall_cmds \
- old_archive_from_expsyms_cmds \
- allow_undefined_flag \
- no_undefined_flag \
- export_symbols_cmds \
- hardcode_libdir_flag_spec \
- hardcode_libdir_flag_spec_ld \
- hardcode_libdir_separator \
- hardcode_automatic \
- module_cmds \
- module_expsym_cmds \
- lt_cv_prog_compiler_c_o \
- exclude_expsyms \
- include_expsyms; do
-
- case $var in
- old_archive_cmds | \
- old_archive_from_new_cmds | \
- archive_cmds | \
- archive_expsym_cmds | \
- module_cmds | \
- module_expsym_cmds | \
- old_archive_from_expsyms_cmds | \
- export_symbols_cmds | \
- extract_expsyms_cmds | reload_cmds | finish_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case $lt_echo in
- *'\$0 --fallback-echo"')
- lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
- ;;
- esac
-
-cfgfile="${ofile}T"
- trap "$rm \"$cfgfile\"; exit 1" 1 2 15
- $rm -f "$cfgfile"
- { echo "$as_me:$LINENO: creating $ofile" >&5
-echo "$as_me: creating $ofile" >&6;}
-
- cat <<__EOF__ >> "$cfgfile"
-#! $SHELL
-
-# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
-# Free Software Foundation, Inc.
-#
-# This file is part of GNU Libtool:
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# A sed program that does not truncate output.
-SED=$lt_SED
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="$SED -e 1s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-# The names of the tagged configurations supported by this script.
-available_tags=
-
-# ### BEGIN LIBTOOL CONFIG
-
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# An echo program that does not interpret backslashes.
-echo=$lt_echo
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A C compiler.
-LTCC=$lt_LTCC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_LTCFLAGS
-
-# A language-specific compiler.
-CC=$lt_compiler
-
-# Is the compiler the GNU C compiler?
-with_gcc=$GCC
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# The linker used to build libraries.
-LD=$lt_LD
-
-# Whether we need hard or soft links.
-LN_S=$lt_LN_S
-
-# A BSD-compatible nm program.
-NM=$lt_NM
-
-# A symbol stripping program
-STRIP=$lt_STRIP
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=$MAGIC_CMD
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl
-
-# Object file suffix (normally "o").
-objext="$ac_objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='$shrext_cmds'
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic
-pic_mode=$pic_mode
-
-# What is the maximum length of a command?
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$lt_thread_safe_flag_spec
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$lt_RANLIB
-old_archive_cmds=$lt_old_archive_cmds
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
-
-# Commands used to build and install a shared archive.
-archive_cmds=$lt_archive_cmds
-archive_expsym_cmds=$lt_archive_expsym_cmds
-postinstall_cmds=$lt_postinstall_cmds
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=$lt_module_cmds
-module_expsym_cmds=$lt_module_expsym_cmds
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=$lt_predep_objects
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=$lt_postdep_objects
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=$lt_predeps
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=$lt_postdeps
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=$lt_compiler_lib_search_path
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$lt_file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$lt_finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
-
-# If ld is used when linking, flag to hardcode \$libdir into
-# a binary during linking. This must work even if \$libdir does
-# not exist.
-hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator
-
-# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Set to yes if building a shared library automatically hardcodes DIR into the library
-# and all subsequent libraries and executables linked against it.
-hardcode_automatic=$hardcode_automatic
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="$variables_saved_for_relink"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms
-
-# ### END LIBTOOL CONFIG
-
-__EOF__
-
-
- case $host_os in
- aix3*)
- cat <<\EOF >> "$cfgfile"
-
-# AIX sometimes has problems with the GCC collect2 program. For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
- COLLECT_NAMES=
- export COLLECT_NAMES
-fi
-EOF
- ;;
- esac
-
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
- sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
-
- mv -f "$cfgfile" "$ofile" || \
- (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
- chmod +x "$ofile"
-
-else
- # If there is no Makefile yet, we rely on a make rule to execute
- # `config.status --recheck' to rerun these tests and create the
- # libtool script then.
- ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
- if test -f "$ltmain_in"; then
- test -f Makefile && make "$ltmain"
- fi
-fi
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC="$lt_save_CC"
-
-
-# Check whether --with-tags or --without-tags was given.
-if test "${with_tags+set}" = set; then
- withval="$with_tags"
- tagnames="$withval"
-fi;
-
-if test -f "$ltmain" && test -n "$tagnames"; then
- if test ! -f "${ofile}"; then
- { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
-echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
- fi
-
- if test -z "$LTCC"; then
- eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
- if test -z "$LTCC"; then
- { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
-echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
- else
- { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
-echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
- fi
- fi
- if test -z "$LTCFLAGS"; then
- eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
- fi
-
- # Extract list of available tagged configurations in $ofile.
- # Note that this assumes the entire list is on one line.
- available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
-
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for tagname in $tagnames; do
- IFS="$lt_save_ifs"
- # Check whether tagname contains only valid characters
- case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
- "") ;;
- *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
-echo "$as_me: error: invalid tag name: $tagname" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
-
- if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
- then
- { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
-echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
- { (exit 1); exit 1; }; }
- fi
-
- # Update the list of available tags.
- if test -n "$tagname"; then
- echo appending configuration tag \"$tagname\" to $ofile
-
- case $tagname in
- CXX)
- if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
- ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
- (test "X$CXX" != "Xg++"))) ; then
- ac_ext=cc
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
-
-
-
-archive_cmds_need_lc_CXX=no
-allow_undefined_flag_CXX=
-always_export_symbols_CXX=no
-archive_expsym_cmds_CXX=
-export_dynamic_flag_spec_CXX=
-hardcode_direct_CXX=no
-hardcode_libdir_flag_spec_CXX=
-hardcode_libdir_flag_spec_ld_CXX=
-hardcode_libdir_separator_CXX=
-hardcode_minus_L_CXX=no
-hardcode_shlibpath_var_CXX=unsupported
-hardcode_automatic_CXX=no
-module_cmds_CXX=
-module_expsym_cmds_CXX=
-link_all_deplibs_CXX=unknown
-old_archive_cmds_CXX=$old_archive_cmds
-no_undefined_flag_CXX=
-whole_archive_flag_spec_CXX=
-enable_shared_with_static_runtimes_CXX=no
-
-# Dependencies to place before and after the object being linked:
-predep_objects_CXX=
-postdep_objects_CXX=
-predeps_CXX=
-postdeps_CXX=
-compiler_lib_search_path_CXX=
-
-# Source file extension for C++ test sources.
-ac_ext=cpp
-
-# Object file extension for compiled C++ test sources.
-objext=o
-objext_CXX=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$rm conftest*
-
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$rm conftest*
-
-
-# Allow CC to be a program name with arguments.
-lt_save_CC=$CC
-lt_save_LD=$LD
-lt_save_GCC=$GCC
-GCC=$GXX
-lt_save_with_gnu_ld=$with_gnu_ld
-lt_save_path_LD=$lt_cv_path_LD
-if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
- lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
-else
- $as_unset lt_cv_prog_gnu_ld
-fi
-if test -n "${lt_cv_path_LDCXX+set}"; then
- lt_cv_path_LD=$lt_cv_path_LDCXX
-else
- $as_unset lt_cv_path_LD
-fi
-test -z "${LDCXX+set}" || LD=$LDCXX
-CC=${CXX-"c++"}
-compiler=$CC
-compiler_CXX=$CC
-for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
-
-# We don't want -fno-exception wen compiling C++ code, so set the
-# no_builtin_flag separately
-if test "$GXX" = yes; then
- lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
-else
- lt_prog_compiler_no_builtin_flag_CXX=
-fi
-
-if test "$GXX" = yes; then
- # Set up default GNU C++ configuration
-
-
-# Check whether --with-gnu-ld or --without-gnu-ld was given.
-if test "${with_gnu_ld+set}" = set; then
- withval="$with_gnu_ld"
- test "$withval" = no || with_gnu_ld=yes
-else
- with_gnu_ld=no
-fi;
-ac_prog=ld
-if test "$GCC" = yes; then
- # Check if gcc -print-prog-name=ld gives a path.
- echo "$as_me:$LINENO: checking for ld used by $CC" >&5
-echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
- case $host in
- *-*-mingw*)
- # gcc leaves a trailing carriage return which upsets mingw
- ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
- *)
- ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
- esac
- case $ac_prog in
- # Accept absolute paths.
- [\\/]* | ?:[\\/]*)
- re_direlt='/[^/][^/]*/\.\./'
- # Canonicalize the pathname of ld
- ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
- while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
- ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
- done
- test -z "$LD" && LD="$ac_prog"
- ;;
- "")
- # If it fails, then pretend we aren't using GCC.
- ac_prog=ld
- ;;
- *)
- # If it is relative, then search for the first ld in PATH.
- with_gnu_ld=unknown
- ;;
- esac
-elif test "$with_gnu_ld" = yes; then
- echo "$as_me:$LINENO: checking for GNU ld" >&5
-echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
-else
- echo "$as_me:$LINENO: checking for non-GNU ld" >&5
-echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
-fi
-if test "${lt_cv_path_LD+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -z "$LD"; then
- lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
- for ac_dir in $PATH; do
- IFS="$lt_save_ifs"
- test -z "$ac_dir" && ac_dir=.
- if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
- lt_cv_path_LD="$ac_dir/$ac_prog"
- # Check to see if the program is GNU ld. I'd rather use --version,
- # but apparently some variants of GNU ld only accept -v.
- # Break only if it was the GNU/non-GNU ld that we prefer.
- case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
- *GNU* | *'with BFD'*)
- test "$with_gnu_ld" != no && break
- ;;
- *)
- test "$with_gnu_ld" != yes && break
- ;;
- esac
- fi
- done
- IFS="$lt_save_ifs"
-else
- lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi
-fi
-
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
- echo "$as_me:$LINENO: result: $LD" >&5
-echo "${ECHO_T}$LD" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
-echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
- { (exit 1); exit 1; }; }
-echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
-echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
-if test "${lt_cv_prog_gnu_ld+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # I'd rather use --version here, but apparently some GNU lds only accept -v.
-case `$LD -v 2>&1 </dev/null` in
-*GNU* | *'with BFD'*)
- lt_cv_prog_gnu_ld=yes
- ;;
-*)
- lt_cv_prog_gnu_ld=no
- ;;
-esac
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
-echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
-with_gnu_ld=$lt_cv_prog_gnu_ld
-
-
-
- # Check if GNU C++ uses GNU ld as the underlying linker, since the
- # archiving commands below assume that GNU ld is being used.
- if test "$with_gnu_ld" = yes; then
- archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-
- hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
- export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
-
- # If archive_cmds runs LD, not CC, wlarc should be empty
- # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
- # investigate it a little bit more. (MM)
- wlarc='${wl}'
-
- # ancient GNU ld didn't support --whole-archive et. al.
- if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
- grep 'no-whole-archive' > /dev/null; then
- whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- whole_archive_flag_spec_CXX=
- fi
- else
- with_gnu_ld=no
- wlarc=
-
- # A generic and very simple default shared library creation
- # command for GNU C++ for the case where it uses the native
- # linker, instead of GNU ld. If possible, this setting should
- # overridden to take advantage of the native linker features on
- # the platform it is being used on.
- archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- fi
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
-
-else
- GXX=no
- with_gnu_ld=no
- wlarc=
-fi
-
-# PORTME: fill in a description of your system's C++ link characteristics
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
-ld_shlibs_CXX=yes
-case $host_os in
- aix3*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- aix4* | aix5*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[23]|aix4.[23].*|aix5*)
- for ld_flag in $LDFLAGS; do
- case $ld_flag in
- *-brtl*)
- aix_use_runtimelinking=yes
- break
- ;;
- esac
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- archive_cmds_CXX=''
- hardcode_direct_CXX=yes
- hardcode_libdir_separator_CXX=':'
- link_all_deplibs_CXX=yes
-
- if test "$GXX" = yes; then
- case $host_os in aix4.[012]|aix4.[012].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- hardcode_direct_CXX=yes
- else
- # We have old collect2
- hardcode_direct_CXX=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- hardcode_minus_L_CXX=yes
- hardcode_libdir_flag_spec_CXX='-L$libdir'
- hardcode_libdir_separator_CXX=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- always_export_symbols_CXX=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- allow_undefined_flag_CXX='-berok'
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
-
- archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
- allow_undefined_flag_CXX="-z nodefs"
- archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- no_undefined_flag_CXX=' ${wl}-bernotok'
- allow_undefined_flag_CXX=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- whole_archive_flag_spec_CXX='$convenience'
- archive_cmds_need_lc_CXX=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- beos*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- allow_undefined_flag_CXX=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- ld_shlibs_CXX=no
- fi
- ;;
-
- chorus*)
- case $cc_basename in
- *)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- esac
- ;;
-
- cygwin* | mingw* | pw32*)
- # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
- # as there is no search path for DLLs.
- hardcode_libdir_flag_spec_CXX='-L$libdir'
- allow_undefined_flag_CXX=unsupported
- always_export_symbols_CXX=no
- enable_shared_with_static_runtimes_CXX=yes
-
- if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
- archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- ld_shlibs_CXX=no
- fi
- ;;
- darwin* | rhapsody*)
- case $host_os in
- rhapsody* | darwin1.[012])
- allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
- ;;
- *) # Darwin 1.3 on
- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
- allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- else
- case ${MACOSX_DEPLOYMENT_TARGET} in
- 10.[012])
- allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- ;;
- 10.*)
- allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
- ;;
- esac
- fi
- ;;
- esac
- archive_cmds_need_lc_CXX=no
- hardcode_direct_CXX=no
- hardcode_automatic_CXX=yes
- hardcode_shlibpath_var_CXX=unsupported
- whole_archive_flag_spec_CXX=''
- link_all_deplibs_CXX=yes
-
- if test "$GXX" = yes ; then
- lt_int_apple_cc_single_mod=no
- output_verbose_link_cmd='echo'
- if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
- lt_int_apple_cc_single_mod=yes
- fi
- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
- archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- else
- archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- fi
- module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
- archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- fi
- module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- case $cc_basename in
- xlc*)
- output_verbose_link_cmd='echo'
- archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
- module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- ;;
- *)
- ld_shlibs_CXX=no
- ;;
- esac
- fi
- ;;
-
- dgux*)
- case $cc_basename in
- ec++*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- esac
- ;;
- freebsd[12]*)
- # C++ shared libraries reported to be fairly broken before switch to ELF
- ld_shlibs_CXX=no
- ;;
- freebsd-elf*)
- archive_cmds_need_lc_CXX=no
- ;;
- freebsd* | kfreebsd*-gnu | dragonfly*)
- # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
- # conventions
- ld_shlibs_CXX=yes
- ;;
- gnu*)
- ;;
- hpux9*)
- hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_CXX=:
- export_dynamic_flag_spec_CXX='${wl}-E'
- hardcode_direct_CXX=yes
- hardcode_minus_L_CXX=yes # Not in the search PATH,
- # but as the default
- # location of the library.
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- aCC*)
- archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes; then
- archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- fi
- ;;
- esac
- ;;
- hpux10*|hpux11*)
- if test $with_gnu_ld = no; then
- hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_CXX=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- hardcode_libdir_flag_spec_ld_CXX='+b $libdir'
- ;;
- *)
- export_dynamic_flag_spec_CXX='${wl}-E'
- ;;
- esac
- fi
- case $host_cpu in
- hppa*64*|ia64*)
- hardcode_direct_CXX=no
- hardcode_shlibpath_var_CXX=no
- ;;
- *)
- hardcode_direct_CXX=yes
- hardcode_minus_L_CXX=yes # Not in the search PATH,
- # but as the default
- # location of the library.
- ;;
- esac
-
- case $cc_basename in
- CC*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- aCC*)
- case $host_cpu in
- hppa*64*)
- archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes; then
- if test $with_gnu_ld = no; then
- case $host_cpu in
- hppa*64*)
- archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- ia64*)
- archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- *)
- archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- ;;
- esac
- fi
- else
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- fi
- ;;
- esac
- ;;
- interix3*)
- hardcode_direct_CXX=no
- hardcode_shlibpath_var_CXX=no
- hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
- export_dynamic_flag_spec_CXX='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
- irix5* | irix6*)
- case $cc_basename in
- CC*)
- # SGI C++
- archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
-
- # Archives containing C++ object files must be created using
- # "CC -ar", where "CC" is the IRIX C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
- ;;
- *)
- if test "$GXX" = yes; then
- if test "$with_gnu_ld" = no; then
- archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
- fi
- fi
- link_all_deplibs_CXX=yes
- ;;
- esac
- hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_CXX=:
- ;;
- linux*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
- archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
-
- hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
- export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
-
- # Archives containing C++ object files must be created using
- # "CC -Bstatic", where "CC" is the KAI C++ compiler.
- old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
- ;;
- icpc*)
- # Intel C++
- with_gnu_ld=yes
- # version 8.0 and above of icpc choke on multiply defined symbols
- # if we add $predep_objects and $postdep_objects, however 7.1 and
- # earlier do not add the objects themselves.
- case `$CC -V 2>&1` in
- *"Version 7."*)
- archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- *) # Version 8.0 or newer
- tmp_idyn=
- case $host_cpu in
- ia64*) tmp_idyn=' -i_dynamic';;
- esac
- archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- ;;
- esac
- archive_cmds_need_lc_CXX=no
- hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
- export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
- whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
- ;;
- pgCC*)
- # Portland Group C++ compiler
- archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
- archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
-
- hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
- export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
- whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- ;;
- cxx*)
- # Compaq C++
- archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
-
- runpath_var=LD_RUN_PATH
- hardcode_libdir_flag_spec_CXX='-rpath $libdir'
- hardcode_libdir_separator_CXX=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- esac
- ;;
- lynxos*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- m88k*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- mvs*)
- case $cc_basename in
- cxx*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- esac
- ;;
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
- wlarc=
- hardcode_libdir_flag_spec_CXX='-R$libdir'
- hardcode_direct_CXX=yes
- hardcode_shlibpath_var_CXX=no
- fi
- # Workaround some broken pre-1.5 toolchains
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
- ;;
- openbsd2*)
- # C++ shared libraries are fairly broken
- ld_shlibs_CXX=no
- ;;
- openbsd*)
- hardcode_direct_CXX=yes
- hardcode_shlibpath_var_CXX=no
- archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
- hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
- export_dynamic_flag_spec_CXX='${wl}-E'
- whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- fi
- output_verbose_link_cmd='echo'
- ;;
- osf3*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
-
- hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
- hardcode_libdir_separator_CXX=:
-
- # Archives containing C++ object files must be created using
- # "CC -Bstatic", where "CC" is the KAI C++ compiler.
- old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
-
- ;;
- RCC*)
- # Rational C++ 2.4.1
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- cxx*)
- allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
-
- hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_CXX=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-
- hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_CXX=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
-
- else
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- fi
- ;;
- esac
- ;;
- osf4* | osf5*)
- case $cc_basename in
- KCC*)
- # Kuck and Associates, Inc. (KAI) C++ Compiler
-
- # KCC will only create a shared library if the output file
- # ends with ".so" (or ".sl" for HP-UX), so rename the library
- # to its proper name (with version) after linking.
- archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
-
- hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
- hardcode_libdir_separator_CXX=:
-
- # Archives containing C++ object files must be created using
- # the KAI C++ compiler.
- old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
- ;;
- RCC*)
- # Rational C++ 2.4.1
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- cxx*)
- allow_undefined_flag_CXX=' -expect_unresolved \*'
- archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
- echo "-hidden">> $lib.exp~
- $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
- $rm $lib.exp'
-
- hardcode_libdir_flag_spec_CXX='-rpath $libdir'
- hardcode_libdir_separator_CXX=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- #
- # There doesn't appear to be a way to prevent this compiler from
- # explicitly linking system object files so we need to strip them
- # from the output so that they don't get included in the library
- # dependencies.
- output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
- ;;
- *)
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-
- hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_CXX=:
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
-
- else
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- fi
- ;;
- esac
- ;;
- psos*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- lcc*)
- # Lucid
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- esac
- ;;
- solaris*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- archive_cmds_need_lc_CXX=yes
- no_undefined_flag_CXX=' -zdefs'
- archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
- archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
-
- hardcode_libdir_flag_spec_CXX='-R$libdir'
- hardcode_shlibpath_var_CXX=no
- case $host_os in
- solaris2.[0-5] | solaris2.[0-5].*) ;;
- *)
- # The C++ compiler is used as linker so we must use $wl
- # flag to pass the commands to the underlying system
- # linker. We must also pass each convience library through
- # to the system linker between allextract/defaultextract.
- # The C++ compiler will combine linker options so we
- # cannot just pass the convience library names through
- # without $wl.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
- ;;
- esac
- link_all_deplibs_CXX=yes
-
- output_verbose_link_cmd='echo'
-
- # Archives containing C++ object files must be created using
- # "CC -xar", where "CC" is the Sun C++ compiler. This is
- # necessary to make sure instantiated templates are included
- # in the archive.
- old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
- ;;
- gcx*)
- # Green Hills C++ Compiler
- archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
-
- # The C++ compiler must be used to create the archive.
- old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
- ;;
- *)
- # GNU C++ compiler with Solaris linker
- if test "$GXX" = yes && test "$with_gnu_ld" = no; then
- no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
- if $CC --version | grep -v '^2\.7' > /dev/null; then
- archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
- else
- # g++ 2.7 appears to require `-G' NOT `-shared' on this
- # platform.
- archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
- archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
-
- # Commands to make compiler produce verbose output that lists
- # what "hidden" libraries, object files and flags are used when
- # linking a shared library.
- output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
- fi
-
- hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
- fi
- ;;
- esac
- ;;
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
- no_undefined_flag_CXX='${wl}-z,text'
- archive_cmds_need_lc_CXX=no
- hardcode_shlibpath_var_CXX=no
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- # For security reasons, it is highly recommended that you always
- # use absolute paths for naming shared libraries, and exclude the
- # DT_RUNPATH tag from executables and libraries. But doing so
- # requires that you compile everything twice, which is a pain.
- # So that behaviour is only enabled if SCOABSPATH is set to a
- # non-empty value in the environment. Most likely only useful for
- # creating official distributions of packages.
- # This is a hack until libtool officially supports absolute path
- # names for shared libraries.
- no_undefined_flag_CXX='${wl}-z,text'
- allow_undefined_flag_CXX='${wl}-z,nodefs'
- archive_cmds_need_lc_CXX=no
- hardcode_shlibpath_var_CXX=no
- hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
- hardcode_libdir_separator_CXX=':'
- link_all_deplibs_CXX=yes
- export_dynamic_flag_spec_CXX='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- case $cc_basename in
- CC*)
- archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- ;;
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- esac
- ;;
- vxworks*)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
- *)
- # FIXME: insert proper C++ library support
- ld_shlibs_CXX=no
- ;;
-esac
-echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
-echo "${ECHO_T}$ld_shlibs_CXX" >&6
-test "$ld_shlibs_CXX" = no && can_build_shared=no
-
-GCC_CXX="$GXX"
-LD_CXX="$LD"
-
-
-cat > conftest.$ac_ext <<EOF
-class Foo
-{
-public:
- Foo (void) { a = 0; }
-private:
- int a;
-};
-EOF
-
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # Parse the compiler output and extract the necessary
- # objects, libraries and library flags.
-
- # Sentinel used to keep track of whether or not we are before
- # the conftest object file.
- pre_test_object_deps_done=no
-
- # The `*' in the case matches for architectures that use `case' in
- # $output_verbose_cmd can trigger glob expansion during the loop
- # eval without this substitution.
- output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
-
- for p in `eval $output_verbose_link_cmd`; do
- case $p in
-
- -L* | -R* | -l*)
- # Some compilers place space between "-{L,R}" and the path.
- # Remove the space.
- if test $p = "-L" \
- || test $p = "-R"; then
- prev=$p
- continue
- else
- prev=
- fi
-
- if test "$pre_test_object_deps_done" = no; then
- case $p in
- -L* | -R*)
- # Internal compiler library paths should come after those
- # provided the user. The postdeps already come after the
- # user supplied libs so there is no need to process them.
- if test -z "$compiler_lib_search_path_CXX"; then
- compiler_lib_search_path_CXX="${prev}${p}"
- else
- compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
- fi
- ;;
- # The "-l" case would never come before the object being
- # linked, so don't bother handling this case.
- esac
- else
- if test -z "$postdeps_CXX"; then
- postdeps_CXX="${prev}${p}"
- else
- postdeps_CXX="${postdeps_CXX} ${prev}${p}"
- fi
- fi
- ;;
-
- *.$objext)
- # This assumes that the test object file only shows up
- # once in the compiler output.
- if test "$p" = "conftest.$objext"; then
- pre_test_object_deps_done=yes
- continue
- fi
-
- if test "$pre_test_object_deps_done" = no; then
- if test -z "$predep_objects_CXX"; then
- predep_objects_CXX="$p"
- else
- predep_objects_CXX="$predep_objects_CXX $p"
- fi
- else
- if test -z "$postdep_objects_CXX"; then
- postdep_objects_CXX="$p"
- else
- postdep_objects_CXX="$postdep_objects_CXX $p"
- fi
- fi
- ;;
-
- *) ;; # Ignore the rest.
-
- esac
- done
-
- # Clean up.
- rm -f a.out a.exe
-else
- echo "libtool.m4: error: problem compiling CXX test program"
-fi
-
-$rm -f confest.$objext
-
-# PORTME: override above test on systems where it is broken
-case $host_os in
-interix3*)
- # Interix 3.5 installs completely hosed .la files for C++, so rather than
- # hack all around it, let's just trust "g++" to DTRT.
- predep_objects_CXX=
- postdep_objects_CXX=
- postdeps_CXX=
- ;;
-
-solaris*)
- case $cc_basename in
- CC*)
- # Adding this requires a known-good setup of shared libraries for
- # Sun compiler versions before 5.6, else PIC objects from an old
- # archive will be linked into the output, leading to subtle bugs.
- postdeps_CXX='-lCstd -lCrun'
- ;;
- esac
- ;;
-esac
-
-
-case " $postdeps_CXX " in
-*" -lc "*) archive_cmds_need_lc_CXX=no ;;
-esac
-
-lt_prog_compiler_wl_CXX=
-lt_prog_compiler_pic_CXX=
-lt_prog_compiler_static_CXX=
-
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
-
- # C++ specific cases for pic, static, wl, etc.
- if test "$GXX" = yes; then
- lt_prog_compiler_wl_CXX='-Wl,'
- lt_prog_compiler_static_CXX='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static_CXX='-Bstatic'
- fi
- ;;
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
- ;;
- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
- mingw* | os2* | pw32*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
- ;;
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- lt_prog_compiler_pic_CXX='-fno-common'
- ;;
- *djgpp*)
- # DJGPP does not support shared libraries at all
- lt_prog_compiler_pic_CXX=
- ;;
- interix3*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
- sysv4*MP*)
- if test -d /usr/nec; then
- lt_prog_compiler_pic_CXX=-Kconform_pic
- fi
- ;;
- hpux*)
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- ;;
- *)
- lt_prog_compiler_pic_CXX='-fPIC'
- ;;
- esac
- ;;
- *)
- lt_prog_compiler_pic_CXX='-fPIC'
- ;;
- esac
- else
- case $host_os in
- aix4* | aix5*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static_CXX='-Bstatic'
- else
- lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- chorus*)
- case $cc_basename in
- cxch68*)
- # Green Hills C++ Compiler
- # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
- ;;
- esac
- ;;
- darwin*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- case $cc_basename in
- xlc*)
- lt_prog_compiler_pic_CXX='-qnocommon'
- lt_prog_compiler_wl_CXX='-Wl,'
- ;;
- esac
- ;;
- dgux*)
- case $cc_basename in
- ec++*)
- lt_prog_compiler_pic_CXX='-KPIC'
- ;;
- ghcx*)
- # Green Hills C++ Compiler
- lt_prog_compiler_pic_CXX='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- freebsd* | kfreebsd*-gnu | dragonfly*)
- # FreeBSD uses GNU C++
- ;;
- hpux9* | hpux10* | hpux11*)
- case $cc_basename in
- CC*)
- lt_prog_compiler_wl_CXX='-Wl,'
- lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
- if test "$host_cpu" != ia64; then
- lt_prog_compiler_pic_CXX='+Z'
- fi
- ;;
- aCC*)
- lt_prog_compiler_wl_CXX='-Wl,'
- lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic_CXX='+Z'
- ;;
- esac
- ;;
- *)
- ;;
- esac
- ;;
- interix*)
- # This is c89, which is MS Visual C++ (no shared libs)
- # Anyone wants to do a port?
- ;;
- irix5* | irix6* | nonstopux*)
- case $cc_basename in
- CC*)
- lt_prog_compiler_wl_CXX='-Wl,'
- lt_prog_compiler_static_CXX='-non_shared'
- # CC pic flag -KPIC is the default.
- ;;
- *)
- ;;
- esac
- ;;
- linux*)
- case $cc_basename in
- KCC*)
- # KAI C++ Compiler
- lt_prog_compiler_wl_CXX='--backend -Wl,'
- lt_prog_compiler_pic_CXX='-fPIC'
- ;;
- icpc* | ecpc*)
- # Intel C++
- lt_prog_compiler_wl_CXX='-Wl,'
- lt_prog_compiler_pic_CXX='-KPIC'
- lt_prog_compiler_static_CXX='-static'
- ;;
- pgCC*)
- # Portland Group C++ compiler.
- lt_prog_compiler_wl_CXX='-Wl,'
- lt_prog_compiler_pic_CXX='-fpic'
- lt_prog_compiler_static_CXX='-Bstatic'
- ;;
- cxx*)
- # Compaq C++
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- lt_prog_compiler_pic_CXX=
- lt_prog_compiler_static_CXX='-non_shared'
- ;;
- *)
- ;;
- esac
- ;;
- lynxos*)
- ;;
- m88k*)
- ;;
- mvs*)
- case $cc_basename in
- cxx*)
- lt_prog_compiler_pic_CXX='-W c,exportall'
- ;;
- *)
- ;;
- esac
- ;;
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- ;;
- osf3* | osf4* | osf5*)
- case $cc_basename in
- KCC*)
- lt_prog_compiler_wl_CXX='--backend -Wl,'
- ;;
- RCC*)
- # Rational C++ 2.4.1
- lt_prog_compiler_pic_CXX='-pic'
- ;;
- cxx*)
- # Digital/Compaq C++
- lt_prog_compiler_wl_CXX='-Wl,'
- # Make sure the PIC flag is empty. It appears that all Alpha
- # Linux and Compaq Tru64 Unix objects are PIC.
- lt_prog_compiler_pic_CXX=
- lt_prog_compiler_static_CXX='-non_shared'
- ;;
- *)
- ;;
- esac
- ;;
- psos*)
- ;;
- solaris*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.2, 5.x and Centerline C++
- lt_prog_compiler_pic_CXX='-KPIC'
- lt_prog_compiler_static_CXX='-Bstatic'
- lt_prog_compiler_wl_CXX='-Qoption ld '
- ;;
- gcx*)
- # Green Hills C++ Compiler
- lt_prog_compiler_pic_CXX='-PIC'
- ;;
- *)
- ;;
- esac
- ;;
- sunos4*)
- case $cc_basename in
- CC*)
- # Sun C++ 4.x
- lt_prog_compiler_pic_CXX='-pic'
- lt_prog_compiler_static_CXX='-Bstatic'
- ;;
- lcc*)
- # Lucid
- lt_prog_compiler_pic_CXX='-pic'
- ;;
- *)
- ;;
- esac
- ;;
- tandem*)
- case $cc_basename in
- NCC*)
- # NonStop-UX NCC 3.20
- lt_prog_compiler_pic_CXX='-KPIC'
- ;;
- *)
- ;;
- esac
- ;;
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- case $cc_basename in
- CC*)
- lt_prog_compiler_wl_CXX='-Wl,'
- lt_prog_compiler_pic_CXX='-KPIC'
- lt_prog_compiler_static_CXX='-Bstatic'
- ;;
- esac
- ;;
- vxworks*)
- ;;
- *)
- lt_prog_compiler_can_build_shared_CXX=no
- ;;
- esac
- fi
-
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$lt_prog_compiler_pic_CXX"; then
-
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6
-if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_pic_works_CXX=no
- ac_outfile=conftest.$ac_objext
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:11519: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:11523: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_pic_works_CXX=yes
- fi
- fi
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6
-
-if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
- case $lt_prog_compiler_pic_CXX in
- "" | " "*) ;;
- *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
- esac
-else
- lt_prog_compiler_pic_CXX=
- lt_prog_compiler_can_build_shared_CXX=no
-fi
-
-fi
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- lt_prog_compiler_pic_CXX=
- ;;
- *)
- lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
- ;;
-esac
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
-if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_static_works_CXX=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
- printf "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_static_works_CXX=yes
- fi
- else
- lt_prog_compiler_static_works_CXX=yes
- fi
- fi
- $rm conftest*
- LDFLAGS="$save_LDFLAGS"
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6
-
-if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
- :
-else
- lt_prog_compiler_static_CXX=
-fi
-
-
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
-if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_prog_compiler_c_o_CXX=no
- $rm -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:11623: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&5
- echo "$as_me:11627: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_c_o_CXX=yes
- fi
- fi
- chmod u+w . 2>&5
- $rm conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
- $rm out/* && rmdir out
- cd ..
- rmdir conftest
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6
-
-
-hard_links="nottested"
-if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
- hard_links=yes
- $rm conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6
- if test "$hard_links" = no; then
- { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
-echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
-
- export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- case $host_os in
- aix4* | aix5*)
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
- export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- else
- export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- fi
- ;;
- pw32*)
- export_symbols_cmds_CXX="$ltdll_cmds"
- ;;
- cygwin* | mingw*)
- export_symbols_cmds_CXX='$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'
- ;;
- kfreebsd*-gnu)
- link_all_deplibs_CXX=no
- ;;
- linux*)
- link_all_deplibs_CXX=no
- ;;
- *)
- export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- ;;
- esac
-
-echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
-echo "${ECHO_T}$ld_shlibs_CXX" >&6
-test "$ld_shlibs_CXX" = no && can_build_shared=no
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$archive_cmds_need_lc_CXX" in
-x|xyes)
- # Assume -lc should be added
- archive_cmds_need_lc_CXX=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $archive_cmds_CXX in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
- $rm conftest*
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$lt_prog_compiler_wl_CXX
- pic_flag=$lt_prog_compiler_pic_CXX
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
- allow_undefined_flag_CXX=
- if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
- (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
- then
- archive_cmds_need_lc_CXX=no
- else
- archive_cmds_need_lc_CXX=yes
- fi
- allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $rm conftest*
- echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
-echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6
- ;;
- esac
- fi
- ;;
-esac
-
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix4* | aix5*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[01] | aix4.[01].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[45]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$host_os in
- yes,cygwin* | yes,mingw* | yes,pw32*)
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $rm \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
- ;;
- mingw*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
- # It is most probably a Windows format PATH printed by
- # mingw gcc, but we are running on Cygwin. Gcc prints its search
- # path with ; separators, and with drive letters. We can handle the
- # drive letters (cygwin fileutils understands them), so leave them,
- # especially as we might pass files found there to a mingw objdump,
- # which wouldn't understand a cygwinified path. Ahh.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- ;;
-
- *)
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
- if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
- else
- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
- fi
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-kfreebsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[123]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- version_type=freebsd-$objformat
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[01]* | freebsdelf3.[01]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
- freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- freebsd*) # from 4.6 on
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- ;;
-
-interix3*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsdelf*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='NetBSD ld.elf_so'
- ;;
-
-knetbsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-nto-qnx*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[89] | openbsd2.[89].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- export_dynamic_flag_spec='${wl}-Blargedynsym'
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- shlibpath_overrides_runpath=no
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- shlibpath_overrides_runpath=yes
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
-hardcode_action_CXX=
-if test -n "$hardcode_libdir_flag_spec_CXX" || \
- test -n "$runpath_var_CXX" || \
- test "X$hardcode_automatic_CXX" = "Xyes" ; then
-
- # We can hardcode non-existant directories.
- if test "$hardcode_direct_CXX" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
- test "$hardcode_minus_L_CXX" != no; then
- # Linking always hardcodes the temporary library directory.
- hardcode_action_CXX=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- hardcode_action_CXX=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- hardcode_action_CXX=unsupported
-fi
-echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
-echo "${ECHO_T}$hardcode_action_CXX" >&6
-
-if test "$hardcode_action_CXX" = relink; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-
-
-# The else clause should only fire when bootstrapping the
-# libtool distribution, otherwise you forgot to ship ltmain.sh
-# with your package, and you will get complaints that there are
-# no rules to generate ltmain.sh.
-if test -f "$ltmain"; then
- # See if we are running on zsh, and set the options which allow our commands through
- # without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
- # Now quote all the things that may contain metacharacters while being
- # careful not to overquote the AC_SUBSTed values. We take copies of the
- # variables and quote the copies for generation of the libtool script.
- for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
- SED SHELL STRIP \
- libname_spec library_names_spec soname_spec extract_expsyms_cmds \
- old_striplib striplib file_magic_cmd finish_cmds finish_eval \
- deplibs_check_method reload_flag reload_cmds need_locks \
- lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
- lt_cv_sys_global_symbol_to_c_name_address \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- old_postinstall_cmds old_postuninstall_cmds \
- compiler_CXX \
- CC_CXX \
- LD_CXX \
- lt_prog_compiler_wl_CXX \
- lt_prog_compiler_pic_CXX \
- lt_prog_compiler_static_CXX \
- lt_prog_compiler_no_builtin_flag_CXX \
- export_dynamic_flag_spec_CXX \
- thread_safe_flag_spec_CXX \
- whole_archive_flag_spec_CXX \
- enable_shared_with_static_runtimes_CXX \
- old_archive_cmds_CXX \
- old_archive_from_new_cmds_CXX \
- predep_objects_CXX \
- postdep_objects_CXX \
- predeps_CXX \
- postdeps_CXX \
- compiler_lib_search_path_CXX \
- archive_cmds_CXX \
- archive_expsym_cmds_CXX \
- postinstall_cmds_CXX \
- postuninstall_cmds_CXX \
- old_archive_from_expsyms_cmds_CXX \
- allow_undefined_flag_CXX \
- no_undefined_flag_CXX \
- export_symbols_cmds_CXX \
- hardcode_libdir_flag_spec_CXX \
- hardcode_libdir_flag_spec_ld_CXX \
- hardcode_libdir_separator_CXX \
- hardcode_automatic_CXX \
- module_cmds_CXX \
- module_expsym_cmds_CXX \
- lt_cv_prog_compiler_c_o_CXX \
- exclude_expsyms_CXX \
- include_expsyms_CXX; do
-
- case $var in
- old_archive_cmds_CXX | \
- old_archive_from_new_cmds_CXX | \
- archive_cmds_CXX | \
- archive_expsym_cmds_CXX | \
- module_cmds_CXX | \
- module_expsym_cmds_CXX | \
- old_archive_from_expsyms_cmds_CXX | \
- export_symbols_cmds_CXX | \
- extract_expsyms_cmds | reload_cmds | finish_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case $lt_echo in
- *'\$0 --fallback-echo"')
- lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
- ;;
- esac
-
-cfgfile="$ofile"
-
- cat <<__EOF__ >> "$cfgfile"
-# ### BEGIN LIBTOOL TAG CONFIG: $tagname
-
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc_CXX
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# An echo program that does not interpret backslashes.
-echo=$lt_echo
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A C compiler.
-LTCC=$lt_LTCC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_LTCFLAGS
-
-# A language-specific compiler.
-CC=$lt_compiler_CXX
-
-# Is the compiler the GNU C compiler?
-with_gcc=$GCC_CXX
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# The linker used to build libraries.
-LD=$lt_LD_CXX
-
-# Whether we need hard or soft links.
-LN_S=$lt_LN_S
-
-# A BSD-compatible nm program.
-NM=$lt_NM
-
-# A symbol stripping program
-STRIP=$lt_STRIP
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=$MAGIC_CMD
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl_CXX
-
-# Object file suffix (normally "o").
-objext="$ac_objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='$shrext_cmds'
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic_CXX
-pic_mode=$pic_mode
-
-# What is the maximum length of a command?
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static_CXX
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$lt_RANLIB
-old_archive_cmds=$lt_old_archive_cmds_CXX
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
-
-# Commands used to build and install a shared archive.
-archive_cmds=$lt_archive_cmds_CXX
-archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
-postinstall_cmds=$lt_postinstall_cmds
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=$lt_module_cmds_CXX
-module_expsym_cmds=$lt_module_expsym_cmds_CXX
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=$lt_predep_objects_CXX
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=$lt_postdep_objects_CXX
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=$lt_predeps_CXX
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=$lt_postdeps_CXX
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$lt_file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag_CXX
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag_CXX
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$lt_finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action_CXX
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
-
-# If ld is used when linking, flag to hardcode \$libdir into
-# a binary during linking. This must work even if \$libdir does
-# not exist.
-hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
-
-# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct_CXX
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L_CXX
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
-
-# Set to yes if building a shared library automatically hardcodes DIR into the library
-# and all subsequent libraries and executables linked against it.
-hardcode_automatic=$hardcode_automatic_CXX
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="$variables_saved_for_relink"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs_CXX
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path_CXX"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols_CXX
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds_CXX
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms_CXX
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms_CXX
-
-# ### END LIBTOOL TAG CONFIG: $tagname
-
-__EOF__
-
-
-else
- # If there is no Makefile yet, we rely on a make rule to execute
- # `config.status --recheck' to rerun these tests and create the
- # libtool script then.
- ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
- if test -f "$ltmain_in"; then
- test -f Makefile && make "$ltmain"
- fi
-fi
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC=$lt_save_CC
-LDCXX=$LD
-LD=$lt_save_LD
-GCC=$lt_save_GCC
-with_gnu_ldcxx=$with_gnu_ld
-with_gnu_ld=$lt_save_with_gnu_ld
-lt_cv_path_LDCXX=$lt_cv_path_LD
-lt_cv_path_LD=$lt_save_path_LD
-lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
-lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
-
- else
- tagname=""
- fi
- ;;
-
- F77)
- if test -n "$F77" && test "X$F77" != "Xno"; then
-
-ac_ext=f
-ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
-ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_f77_compiler_gnu
-
-
-archive_cmds_need_lc_F77=no
-allow_undefined_flag_F77=
-always_export_symbols_F77=no
-archive_expsym_cmds_F77=
-export_dynamic_flag_spec_F77=
-hardcode_direct_F77=no
-hardcode_libdir_flag_spec_F77=
-hardcode_libdir_flag_spec_ld_F77=
-hardcode_libdir_separator_F77=
-hardcode_minus_L_F77=no
-hardcode_automatic_F77=no
-module_cmds_F77=
-module_expsym_cmds_F77=
-link_all_deplibs_F77=unknown
-old_archive_cmds_F77=$old_archive_cmds
-no_undefined_flag_F77=
-whole_archive_flag_spec_F77=
-enable_shared_with_static_runtimes_F77=no
-
-# Source file extension for f77 test sources.
-ac_ext=f
-
-# Object file extension for compiled f77 test sources.
-objext=o
-objext_F77=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code=" subroutine t\n return\n end\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code=" program t\n end\n"
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$rm conftest*
-
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$rm conftest*
-
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-CC=${F77-"f77"}
-compiler=$CC
-compiler_F77=$CC
-for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
-
-echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
-echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $can_build_shared" >&5
-echo "${ECHO_T}$can_build_shared" >&6
-
-echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
-echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case $host_os in
-aix3*)
- test "$enable_shared" = yes && enable_static=no
- if test -n "$RANLIB"; then
- archive_cmds="$archive_cmds~\$RANLIB \$lib"
- postinstall_cmds='$RANLIB $lib'
- fi
- ;;
-aix4* | aix5*)
- if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
- test "$enable_shared" = yes && enable_static=no
- fi
- ;;
-esac
-echo "$as_me:$LINENO: result: $enable_shared" >&5
-echo "${ECHO_T}$enable_shared" >&6
-
-echo "$as_me:$LINENO: checking whether to build static libraries" >&5
-echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-echo "$as_me:$LINENO: result: $enable_static" >&5
-echo "${ECHO_T}$enable_static" >&6
-
-GCC_F77="$G77"
-LD_F77="$LD"
-
-lt_prog_compiler_wl_F77=
-lt_prog_compiler_pic_F77=
-lt_prog_compiler_static_F77=
-
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
-
- if test "$GCC" = yes; then
- lt_prog_compiler_wl_F77='-Wl,'
- lt_prog_compiler_static_F77='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static_F77='-Bstatic'
- fi
- ;;
-
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
- ;;
-
- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic_F77='-DDLL_EXPORT'
- ;;
-
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- lt_prog_compiler_pic_F77='-fno-common'
- ;;
-
- interix3*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
-
- msdosdjgpp*)
- # Just because we use GCC doesn't mean we suddenly get shared libraries
- # on systems that don't support them.
- lt_prog_compiler_can_build_shared_F77=no
- enable_shared=no
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- lt_prog_compiler_pic_F77=-Kconform_pic
- fi
- ;;
-
- hpux*)
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic_F77='-fPIC'
- ;;
- esac
- ;;
-
- *)
- lt_prog_compiler_pic_F77='-fPIC'
- ;;
- esac
- else
- # PORTME Check for flag to pass linker flags through the system compiler.
- case $host_os in
- aix*)
- lt_prog_compiler_wl_F77='-Wl,'
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static_F77='-Bstatic'
- else
- lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- darwin*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- case $cc_basename in
- xlc*)
- lt_prog_compiler_pic_F77='-qnocommon'
- lt_prog_compiler_wl_F77='-Wl,'
- ;;
- esac
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic_F77='-DDLL_EXPORT'
- ;;
-
- hpux9* | hpux10* | hpux11*)
- lt_prog_compiler_wl_F77='-Wl,'
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic_F77='+Z'
- ;;
- esac
- # Is there a better lt_prog_compiler_static that works with the bundled CC?
- lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
- ;;
-
- irix5* | irix6* | nonstopux*)
- lt_prog_compiler_wl_F77='-Wl,'
- # PIC (with -KPIC) is the default.
- lt_prog_compiler_static_F77='-non_shared'
- ;;
-
- newsos6)
- lt_prog_compiler_pic_F77='-KPIC'
- lt_prog_compiler_static_F77='-Bstatic'
- ;;
-
- linux*)
- case $cc_basename in
- icc* | ecc*)
- lt_prog_compiler_wl_F77='-Wl,'
- lt_prog_compiler_pic_F77='-KPIC'
- lt_prog_compiler_static_F77='-static'
- ;;
- pgcc* | pgf77* | pgf90* | pgf95*)
- # Portland Group compilers (*not* the Pentium gcc compiler,
- # which looks to be a dead project)
- lt_prog_compiler_wl_F77='-Wl,'
- lt_prog_compiler_pic_F77='-fpic'
- lt_prog_compiler_static_F77='-Bstatic'
- ;;
- ccc*)
- lt_prog_compiler_wl_F77='-Wl,'
- # All Alpha code is PIC.
- lt_prog_compiler_static_F77='-non_shared'
- ;;
- esac
- ;;
-
- osf3* | osf4* | osf5*)
- lt_prog_compiler_wl_F77='-Wl,'
- # All OSF/1 code is PIC.
- lt_prog_compiler_static_F77='-non_shared'
- ;;
-
- solaris*)
- lt_prog_compiler_pic_F77='-KPIC'
- lt_prog_compiler_static_F77='-Bstatic'
- case $cc_basename in
- f77* | f90* | f95*)
- lt_prog_compiler_wl_F77='-Qoption ld ';;
- *)
- lt_prog_compiler_wl_F77='-Wl,';;
- esac
- ;;
-
- sunos4*)
- lt_prog_compiler_wl_F77='-Qoption ld '
- lt_prog_compiler_pic_F77='-PIC'
- lt_prog_compiler_static_F77='-Bstatic'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3*)
- lt_prog_compiler_wl_F77='-Wl,'
- lt_prog_compiler_pic_F77='-KPIC'
- lt_prog_compiler_static_F77='-Bstatic'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec ;then
- lt_prog_compiler_pic_F77='-Kconform_pic'
- lt_prog_compiler_static_F77='-Bstatic'
- fi
- ;;
-
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- lt_prog_compiler_wl_F77='-Wl,'
- lt_prog_compiler_pic_F77='-KPIC'
- lt_prog_compiler_static_F77='-Bstatic'
- ;;
-
- unicos*)
- lt_prog_compiler_wl_F77='-Wl,'
- lt_prog_compiler_can_build_shared_F77=no
- ;;
-
- uts4*)
- lt_prog_compiler_pic_F77='-pic'
- lt_prog_compiler_static_F77='-Bstatic'
- ;;
-
- *)
- lt_prog_compiler_can_build_shared_F77=no
- ;;
- esac
- fi
-
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$lt_prog_compiler_pic_F77"; then
-
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6
-if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_pic_works_F77=no
- ac_outfile=conftest.$ac_objext
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$lt_prog_compiler_pic_F77"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13211: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:13215: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_pic_works_F77=yes
- fi
- fi
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6
-
-if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
- case $lt_prog_compiler_pic_F77 in
- "" | " "*) ;;
- *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
- esac
-else
- lt_prog_compiler_pic_F77=
- lt_prog_compiler_can_build_shared_F77=no
-fi
-
-fi
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- lt_prog_compiler_pic_F77=
- ;;
- *)
- lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
- ;;
-esac
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
-if test "${lt_prog_compiler_static_works_F77+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_static_works_F77=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
- printf "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_static_works_F77=yes
- fi
- else
- lt_prog_compiler_static_works_F77=yes
- fi
- fi
- $rm conftest*
- LDFLAGS="$save_LDFLAGS"
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6
-
-if test x"$lt_prog_compiler_static_works_F77" = xyes; then
- :
-else
- lt_prog_compiler_static_F77=
-fi
-
-
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
-if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_prog_compiler_c_o_F77=no
- $rm -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13315: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&5
- echo "$as_me:13319: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_c_o_F77=yes
- fi
- fi
- chmod u+w . 2>&5
- $rm conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
- $rm out/* && rmdir out
- cd ..
- rmdir conftest
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6
-
-
-hard_links="nottested"
-if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
- hard_links=yes
- $rm conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6
- if test "$hard_links" = no; then
- { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
-echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
-
- runpath_var=
- allow_undefined_flag_F77=
- enable_shared_with_static_runtimes_F77=no
- archive_cmds_F77=
- archive_expsym_cmds_F77=
- old_archive_From_new_cmds_F77=
- old_archive_from_expsyms_cmds_F77=
- export_dynamic_flag_spec_F77=
- whole_archive_flag_spec_F77=
- thread_safe_flag_spec_F77=
- hardcode_libdir_flag_spec_F77=
- hardcode_libdir_flag_spec_ld_F77=
- hardcode_libdir_separator_F77=
- hardcode_direct_F77=no
- hardcode_minus_L_F77=no
- hardcode_shlibpath_var_F77=unsupported
- link_all_deplibs_F77=unknown
- hardcode_automatic_F77=no
- module_cmds_F77=
- module_expsym_cmds_F77=
- always_export_symbols_F77=no
- export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- # include_expsyms should be a list of space-separated symbols to be *always*
- # included in the symbol list
- include_expsyms_F77=
- # exclude_expsyms can be an extended regexp of symbols to exclude
- # it will be wrapped by ` (' and `)$', so one must not match beginning or
- # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
- # as well as any symbol that contains `d'.
- exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
- # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
- # platforms (ab)use it in PIC code, but their linkers get confused if
- # the symbol is explicitly referenced. Since portable code cannot
- # rely on this symbol name, it's probably fine to never include it in
- # preloaded symbol tables.
- extract_expsyms_cmds=
- # Just being paranoid about ensuring that cc_basename is set.
- for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
- case $host_os in
- cygwin* | mingw* | pw32*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$GCC" != yes; then
- with_gnu_ld=no
- fi
- ;;
- interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
- with_gnu_ld=yes
- ;;
- openbsd*)
- with_gnu_ld=no
- ;;
- esac
-
- ld_shlibs_F77=yes
- if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # Set some defaults for GNU ld with shared library support. These
- # are reset later if shared libraries are not supported. Putting them
- # here allows them to be overridden if necessary.
- runpath_var=LD_RUN_PATH
- hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
- export_dynamic_flag_spec_F77='${wl}--export-dynamic'
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
- whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- whole_archive_flag_spec_F77=
- fi
- supports_anon_versioning=no
- case `$LD -v 2>/dev/null` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
- *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
- *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
- *\ 2.11.*) ;; # other 2.11 versions
- *) supports_anon_versioning=yes ;;
- esac
-
- # See if GNU ld supports shared libraries.
- case $host_os in
- aix3* | aix4* | aix5*)
- # On AIX/PPC, the GNU linker is very broken
- if test "$host_cpu" != ia64; then
- ld_shlibs_F77=no
- cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
- fi
- ;;
-
- amigaos*)
- archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec_F77='-L$libdir'
- hardcode_minus_L_F77=yes
-
- # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
- # that the semantics of dynamic libraries on AmigaOS, at least up
- # to version 4, is to share data among multiple programs linked
- # with the same dynamic library. Since this doesn't match the
- # behavior of shared libraries on other platforms, we can't use
- # them.
- ld_shlibs_F77=no
- ;;
-
- beos*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- allow_undefined_flag_F77=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- ld_shlibs_F77=no
- fi
- ;;
-
- cygwin* | mingw* | pw32*)
- # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
- # as there is no search path for DLLs.
- hardcode_libdir_flag_spec_F77='-L$libdir'
- allow_undefined_flag_F77=unsupported
- always_export_symbols_F77=no
- enable_shared_with_static_runtimes_F77=yes
- export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
-
- if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
- archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- ld_shlibs_F77=no
- fi
- ;;
-
- interix3*)
- hardcode_direct_F77=no
- hardcode_shlibpath_var_F77=no
- hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
- export_dynamic_flag_spec_F77='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
-
- linux*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- tmp_addflag=
- case $cc_basename,$host_cpu in
- pgcc*) # Portland Group C compiler
- whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag'
- ;;
- pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
- whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag -Mnomain' ;;
- ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
- tmp_addflag=' -i_dynamic' ;;
- efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
- tmp_addflag=' -i_dynamic -nofor_main' ;;
- ifc* | ifort*) # Intel Fortran compiler
- tmp_addflag=' -nofor_main' ;;
- esac
- archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
- if test $supports_anon_versioning = yes; then
- archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- $echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
- link_all_deplibs_F77=no
- else
- ld_shlibs_F77=no
- fi
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
- wlarc=
- else
- archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- fi
- ;;
-
- solaris*)
- if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
- ld_shlibs_F77=no
- cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
- elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs_F77=no
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
- case `$LD -v 2>&1` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
- ld_shlibs_F77=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- ;;
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
- archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
- archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
- else
- ld_shlibs_F77=no
- fi
- ;;
- esac
- ;;
-
- sunos4*)
- archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- wlarc=
- hardcode_direct_F77=yes
- hardcode_shlibpath_var_F77=no
- ;;
-
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs_F77=no
- fi
- ;;
- esac
-
- if test "$ld_shlibs_F77" = no; then
- runpath_var=
- hardcode_libdir_flag_spec_F77=
- export_dynamic_flag_spec_F77=
- whole_archive_flag_spec_F77=
- fi
- else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case $host_os in
- aix3*)
- allow_undefined_flag_F77=unsupported
- always_export_symbols_F77=yes
- archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- hardcode_minus_L_F77=yes
- if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- hardcode_direct_F77=unsupported
- fi
- ;;
-
- aix4* | aix5*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
- export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- else
- export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- fi
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[23]|aix4.[23].*|aix5*)
- for ld_flag in $LDFLAGS; do
- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
- aix_use_runtimelinking=yes
- break
- fi
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- archive_cmds_F77=''
- hardcode_direct_F77=yes
- hardcode_libdir_separator_F77=':'
- link_all_deplibs_F77=yes
-
- if test "$GCC" = yes; then
- case $host_os in aix4.[012]|aix4.[012].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- hardcode_direct_F77=yes
- else
- # We have old collect2
- hardcode_direct_F77=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- hardcode_minus_L_F77=yes
- hardcode_libdir_flag_spec_F77='-L$libdir'
- hardcode_libdir_separator_F77=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- always_export_symbols_F77=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- allow_undefined_flag_F77='-berok'
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
- program main
-
- end
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
- archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
- allow_undefined_flag_F77="-z nodefs"
- archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
- program main
-
- end
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- no_undefined_flag_F77=' ${wl}-bernotok'
- allow_undefined_flag_F77=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- whole_archive_flag_spec_F77='$convenience'
- archive_cmds_need_lc_F77=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- amigaos*)
- archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec_F77='-L$libdir'
- hardcode_minus_L_F77=yes
- # see comment about different semantics on the GNU ld section
- ld_shlibs_F77=no
- ;;
-
- bsdi[45]*)
- export_dynamic_flag_spec_F77=-rdynamic
- ;;
-
- cygwin* | mingw* | pw32*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec_F77=' '
- allow_undefined_flag_F77=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- old_archive_From_new_cmds_F77='true'
- # FIXME: Should let the user specify the lib program.
- old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs'
- fix_srcfile_path_F77='`cygpath -w "$srcfile"`'
- enable_shared_with_static_runtimes_F77=yes
- ;;
-
- darwin* | rhapsody*)
- case $host_os in
- rhapsody* | darwin1.[012])
- allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
- ;;
- *) # Darwin 1.3 on
- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
- allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- else
- case ${MACOSX_DEPLOYMENT_TARGET} in
- 10.[012])
- allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- ;;
- 10.*)
- allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
- ;;
- esac
- fi
- ;;
- esac
- archive_cmds_need_lc_F77=no
- hardcode_direct_F77=no
- hardcode_automatic_F77=yes
- hardcode_shlibpath_var_F77=unsupported
- whole_archive_flag_spec_F77=''
- link_all_deplibs_F77=yes
- if test "$GCC" = yes ; then
- output_verbose_link_cmd='echo'
- archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- case $cc_basename in
- xlc*)
- output_verbose_link_cmd='echo'
- archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
- module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- ;;
- *)
- ld_shlibs_F77=no
- ;;
- esac
- fi
- ;;
-
- dgux*)
- archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec_F77='-L$libdir'
- hardcode_shlibpath_var_F77=no
- ;;
-
- freebsd1*)
- ld_shlibs_F77=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
- hardcode_libdir_flag_spec_F77='-R$libdir'
- hardcode_direct_F77=yes
- hardcode_shlibpath_var_F77=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_F77=yes
- hardcode_minus_L_F77=yes
- hardcode_shlibpath_var_F77=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd* | dragonfly*)
- archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec_F77='-R$libdir'
- hardcode_direct_F77=yes
- hardcode_shlibpath_var_F77=no
- ;;
-
- # GNU/kFreeBSD uses gcc -shared to do shared libraries.
- kfreebsd*-gnu)
- archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec_F77='-R$libdir'
- hardcode_direct_F77=yes
- hardcode_shlibpath_var_F77=no
- link_all_deplibs_F77=no
- ;;
-
- hpux9*)
- if test "$GCC" = yes; then
- archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- fi
- hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_F77=:
- hardcode_direct_F77=yes
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L_F77=yes
- export_dynamic_flag_spec_F77='${wl}-E'
- ;;
-
- hpux10*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_F77=:
-
- hardcode_direct_F77=yes
- export_dynamic_flag_spec_F77='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L_F77=yes
- fi
- ;;
-
- hpux11*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- case $host_cpu in
- hppa*64*)
- archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- else
- case $host_cpu in
- hppa*64*)
- archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_F77=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- hardcode_libdir_flag_spec_ld_F77='+b $libdir'
- hardcode_direct_F77=no
- hardcode_shlibpath_var_F77=no
- ;;
- *)
- hardcode_direct_F77=yes
- export_dynamic_flag_spec_F77='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L_F77=yes
- ;;
- esac
- fi
- ;;
-
- irix5* | irix6* | nonstopux*)
- if test "$GCC" = yes; then
- archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
- fi
- hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_F77=:
- link_all_deplibs_F77=yes
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
- else
- archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
- fi
- hardcode_libdir_flag_spec_F77='-R$libdir'
- hardcode_direct_F77=yes
- hardcode_shlibpath_var_F77=no
- ;;
-
- newsos6)
- archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_F77=yes
- hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_F77=:
- hardcode_shlibpath_var_F77=no
- ;;
-
- openbsd*)
- hardcode_direct_F77=yes
- hardcode_shlibpath_var_F77=no
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
- hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
- export_dynamic_flag_spec_F77='${wl}-E'
- else
- case $host_os in
- openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
- archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec_F77='-R$libdir'
- ;;
- *)
- archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
- ;;
- esac
- fi
- ;;
-
- os2*)
- hardcode_libdir_flag_spec_F77='-L$libdir'
- hardcode_minus_L_F77=yes
- allow_undefined_flag_F77=unsupported
- archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
- old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$GCC" = yes; then
- allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- allow_undefined_flag_F77=' -expect_unresolved \*'
- archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_F77=:
- ;;
-
- osf4* | osf5*) # as osf3* with the addition of -msym flag
- if test "$GCC" = yes; then
- allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
- else
- allow_undefined_flag_F77=' -expect_unresolved \*'
- archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
- $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
-
- # Both c and cxx compiler support -rpath directly
- hardcode_libdir_flag_spec_F77='-rpath $libdir'
- fi
- hardcode_libdir_separator_F77=:
- ;;
-
- solaris*)
- no_undefined_flag_F77=' -z text'
- if test "$GCC" = yes; then
- wlarc='${wl}'
- archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
- else
- wlarc=''
- archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
- archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
- fi
- hardcode_libdir_flag_spec_F77='-R$libdir'
- hardcode_shlibpath_var_F77=no
- case $host_os in
- solaris2.[0-5] | solaris2.[0-5].*) ;;
- *)
- # The compiler driver will combine linker options so we
- # cannot just pass the convience library names through
- # without $wl, iff we do not link with $LD.
- # Luckily, gcc supports the same syntax we need for Sun Studio.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- case $wlarc in
- '')
- whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;;
- *)
- whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
- esac ;;
- esac
- link_all_deplibs_F77=yes
- ;;
-
- sunos4*)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
- fi
- hardcode_libdir_flag_spec_F77='-L$libdir'
- hardcode_direct_F77=yes
- hardcode_minus_L_F77=yes
- hardcode_shlibpath_var_F77=no
- ;;
-
- sysv4)
- case $host_vendor in
- sni)
- archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_F77=yes # is this really true???
- ;;
- siemens)
- ## LD is ld it makes a PLAMLIB
- ## CC just makes a GrossModule.
- archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
- reload_cmds_F77='$CC -r -o $output$reload_objs'
- hardcode_direct_F77=no
- ;;
- motorola)
- archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
- ;;
- esac
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var_F77=no
- ;;
-
- sysv4.3*)
- archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var_F77=no
- export_dynamic_flag_spec_F77='-Bexport'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var_F77=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ld_shlibs_F77=yes
- fi
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
- no_undefined_flag_F77='${wl}-z,text'
- archive_cmds_need_lc_F77=no
- hardcode_shlibpath_var_F77=no
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- no_undefined_flag_F77='${wl}-z,text'
- allow_undefined_flag_F77='${wl}-z,nodefs'
- archive_cmds_need_lc_F77=no
- hardcode_shlibpath_var_F77=no
- hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
- hardcode_libdir_separator_F77=':'
- link_all_deplibs_F77=yes
- export_dynamic_flag_spec_F77='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- uts4*)
- archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec_F77='-L$libdir'
- hardcode_shlibpath_var_F77=no
- ;;
-
- *)
- ld_shlibs_F77=no
- ;;
- esac
- fi
-
-echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
-echo "${ECHO_T}$ld_shlibs_F77" >&6
-test "$ld_shlibs_F77" = no && can_build_shared=no
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$archive_cmds_need_lc_F77" in
-x|xyes)
- # Assume -lc should be added
- archive_cmds_need_lc_F77=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $archive_cmds_F77 in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
- $rm conftest*
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$lt_prog_compiler_wl_F77
- pic_flag=$lt_prog_compiler_pic_F77
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$allow_undefined_flag_F77
- allow_undefined_flag_F77=
- if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
- (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
- then
- archive_cmds_need_lc_F77=no
- else
- archive_cmds_need_lc_F77=yes
- fi
- allow_undefined_flag_F77=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $rm conftest*
- echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
-echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6
- ;;
- esac
- fi
- ;;
-esac
-
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix4* | aix5*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[01] | aix4.[01].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[45]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$host_os in
- yes,cygwin* | yes,mingw* | yes,pw32*)
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $rm \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
- ;;
- mingw*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
- # It is most probably a Windows format PATH printed by
- # mingw gcc, but we are running on Cygwin. Gcc prints its search
- # path with ; separators, and with drive letters. We can handle the
- # drive letters (cygwin fileutils understands them), so leave them,
- # especially as we might pass files found there to a mingw objdump,
- # which wouldn't understand a cygwinified path. Ahh.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- ;;
-
- *)
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
- if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
- else
- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
- fi
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-kfreebsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[123]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- version_type=freebsd-$objformat
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[01]* | freebsdelf3.[01]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
- freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- freebsd*) # from 4.6 on
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- ;;
-
-interix3*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsdelf*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='NetBSD ld.elf_so'
- ;;
-
-knetbsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-nto-qnx*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[89] | openbsd2.[89].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- export_dynamic_flag_spec='${wl}-Blargedynsym'
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- shlibpath_overrides_runpath=no
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- shlibpath_overrides_runpath=yes
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
-hardcode_action_F77=
-if test -n "$hardcode_libdir_flag_spec_F77" || \
- test -n "$runpath_var_F77" || \
- test "X$hardcode_automatic_F77" = "Xyes" ; then
-
- # We can hardcode non-existant directories.
- if test "$hardcode_direct_F77" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
- test "$hardcode_minus_L_F77" != no; then
- # Linking always hardcodes the temporary library directory.
- hardcode_action_F77=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- hardcode_action_F77=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- hardcode_action_F77=unsupported
-fi
-echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
-echo "${ECHO_T}$hardcode_action_F77" >&6
-
-if test "$hardcode_action_F77" = relink; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-
-
-# The else clause should only fire when bootstrapping the
-# libtool distribution, otherwise you forgot to ship ltmain.sh
-# with your package, and you will get complaints that there are
-# no rules to generate ltmain.sh.
-if test -f "$ltmain"; then
- # See if we are running on zsh, and set the options which allow our commands through
- # without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
- # Now quote all the things that may contain metacharacters while being
- # careful not to overquote the AC_SUBSTed values. We take copies of the
- # variables and quote the copies for generation of the libtool script.
- for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
- SED SHELL STRIP \
- libname_spec library_names_spec soname_spec extract_expsyms_cmds \
- old_striplib striplib file_magic_cmd finish_cmds finish_eval \
- deplibs_check_method reload_flag reload_cmds need_locks \
- lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
- lt_cv_sys_global_symbol_to_c_name_address \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- old_postinstall_cmds old_postuninstall_cmds \
- compiler_F77 \
- CC_F77 \
- LD_F77 \
- lt_prog_compiler_wl_F77 \
- lt_prog_compiler_pic_F77 \
- lt_prog_compiler_static_F77 \
- lt_prog_compiler_no_builtin_flag_F77 \
- export_dynamic_flag_spec_F77 \
- thread_safe_flag_spec_F77 \
- whole_archive_flag_spec_F77 \
- enable_shared_with_static_runtimes_F77 \
- old_archive_cmds_F77 \
- old_archive_from_new_cmds_F77 \
- predep_objects_F77 \
- postdep_objects_F77 \
- predeps_F77 \
- postdeps_F77 \
- compiler_lib_search_path_F77 \
- archive_cmds_F77 \
- archive_expsym_cmds_F77 \
- postinstall_cmds_F77 \
- postuninstall_cmds_F77 \
- old_archive_from_expsyms_cmds_F77 \
- allow_undefined_flag_F77 \
- no_undefined_flag_F77 \
- export_symbols_cmds_F77 \
- hardcode_libdir_flag_spec_F77 \
- hardcode_libdir_flag_spec_ld_F77 \
- hardcode_libdir_separator_F77 \
- hardcode_automatic_F77 \
- module_cmds_F77 \
- module_expsym_cmds_F77 \
- lt_cv_prog_compiler_c_o_F77 \
- exclude_expsyms_F77 \
- include_expsyms_F77; do
-
- case $var in
- old_archive_cmds_F77 | \
- old_archive_from_new_cmds_F77 | \
- archive_cmds_F77 | \
- archive_expsym_cmds_F77 | \
- module_cmds_F77 | \
- module_expsym_cmds_F77 | \
- old_archive_from_expsyms_cmds_F77 | \
- export_symbols_cmds_F77 | \
- extract_expsyms_cmds | reload_cmds | finish_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case $lt_echo in
- *'\$0 --fallback-echo"')
- lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
- ;;
- esac
-
-cfgfile="$ofile"
-
- cat <<__EOF__ >> "$cfgfile"
-# ### BEGIN LIBTOOL TAG CONFIG: $tagname
-
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc_F77
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# An echo program that does not interpret backslashes.
-echo=$lt_echo
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A C compiler.
-LTCC=$lt_LTCC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_LTCFLAGS
-
-# A language-specific compiler.
-CC=$lt_compiler_F77
-
-# Is the compiler the GNU C compiler?
-with_gcc=$GCC_F77
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# The linker used to build libraries.
-LD=$lt_LD_F77
-
-# Whether we need hard or soft links.
-LN_S=$lt_LN_S
-
-# A BSD-compatible nm program.
-NM=$lt_NM
-
-# A symbol stripping program
-STRIP=$lt_STRIP
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=$MAGIC_CMD
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl_F77
-
-# Object file suffix (normally "o").
-objext="$ac_objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='$shrext_cmds'
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic_F77
-pic_mode=$pic_mode
-
-# What is the maximum length of a command?
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static_F77
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$lt_RANLIB
-old_archive_cmds=$lt_old_archive_cmds_F77
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
-
-# Commands used to build and install a shared archive.
-archive_cmds=$lt_archive_cmds_F77
-archive_expsym_cmds=$lt_archive_expsym_cmds_F77
-postinstall_cmds=$lt_postinstall_cmds
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=$lt_module_cmds_F77
-module_expsym_cmds=$lt_module_expsym_cmds_F77
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=$lt_predep_objects_F77
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=$lt_postdep_objects_F77
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=$lt_predeps_F77
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=$lt_postdeps_F77
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=$lt_compiler_lib_search_path_F77
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$lt_file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag_F77
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag_F77
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$lt_finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action_F77
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
-
-# If ld is used when linking, flag to hardcode \$libdir into
-# a binary during linking. This must work even if \$libdir does
-# not exist.
-hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
-
-# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct_F77
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L_F77
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
-
-# Set to yes if building a shared library automatically hardcodes DIR into the library
-# and all subsequent libraries and executables linked against it.
-hardcode_automatic=$hardcode_automatic_F77
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="$variables_saved_for_relink"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs_F77
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path_F77"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols_F77
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds_F77
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms_F77
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms_F77
-
-# ### END LIBTOOL TAG CONFIG: $tagname
-
-__EOF__
-
-
-else
- # If there is no Makefile yet, we rely on a make rule to execute
- # `config.status --recheck' to rerun these tests and create the
- # libtool script then.
- ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
- if test -f "$ltmain_in"; then
- test -f Makefile && make "$ltmain"
- fi
-fi
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC="$lt_save_CC"
-
- else
- tagname=""
- fi
- ;;
-
- GCJ)
- if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
-
-
-
-# Source file extension for Java test sources.
-ac_ext=java
-
-# Object file extension for compiled Java test sources.
-objext=o
-objext_GCJ=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="class foo {}\n"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$rm conftest*
-
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$rm conftest*
-
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-CC=${GCJ-"gcj"}
-compiler=$CC
-compiler_GCJ=$CC
-for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
-
-# GCJ did not exist at the time GCC didn't implicitly link libc in.
-archive_cmds_need_lc_GCJ=no
-
-old_archive_cmds_GCJ=$old_archive_cmds
-
-
-lt_prog_compiler_no_builtin_flag_GCJ=
-
-if test "$GCC" = yes; then
- lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
-
-
-echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
-if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_prog_compiler_rtti_exceptions=no
- ac_outfile=conftest.$ac_objext
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="-fno-rtti -fno-exceptions"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15538: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:15542: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_rtti_exceptions=yes
- fi
- fi
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
-
-if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
- lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
-else
- :
-fi
-
-fi
-
-lt_prog_compiler_wl_GCJ=
-lt_prog_compiler_pic_GCJ=
-lt_prog_compiler_static_GCJ=
-
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
-
- if test "$GCC" = yes; then
- lt_prog_compiler_wl_GCJ='-Wl,'
- lt_prog_compiler_static_GCJ='-static'
-
- case $host_os in
- aix*)
- # All AIX code is PIC.
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static_GCJ='-Bstatic'
- fi
- ;;
-
- amigaos*)
- # FIXME: we need at least 68020 code to build shared libraries, but
- # adding the `-m68020' flag to GCC prevents building anything better,
- # like `-m68040'.
- lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
- ;;
-
- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
- # PIC is the default for these OSes.
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
- ;;
-
- darwin* | rhapsody*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- lt_prog_compiler_pic_GCJ='-fno-common'
- ;;
-
- interix3*)
- # Interix 3.x gcc -fpic/-fPIC options generate broken code.
- # Instead, we relocate shared libraries at runtime.
- ;;
-
- msdosdjgpp*)
- # Just because we use GCC doesn't mean we suddenly get shared libraries
- # on systems that don't support them.
- lt_prog_compiler_can_build_shared_GCJ=no
- enable_shared=no
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- lt_prog_compiler_pic_GCJ=-Kconform_pic
- fi
- ;;
-
- hpux*)
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic_GCJ='-fPIC'
- ;;
- esac
- ;;
-
- *)
- lt_prog_compiler_pic_GCJ='-fPIC'
- ;;
- esac
- else
- # PORTME Check for flag to pass linker flags through the system compiler.
- case $host_os in
- aix*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- if test "$host_cpu" = ia64; then
- # AIX 5 now supports IA64 processor
- lt_prog_compiler_static_GCJ='-Bstatic'
- else
- lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
- fi
- ;;
- darwin*)
- # PIC is the default on this platform
- # Common symbols not allowed in MH_DYLIB files
- case $cc_basename in
- xlc*)
- lt_prog_compiler_pic_GCJ='-qnocommon'
- lt_prog_compiler_wl_GCJ='-Wl,'
- ;;
- esac
- ;;
-
- mingw* | pw32* | os2*)
- # This hack is so that the source file can tell whether it is being
- # built for inclusion in a dll (and should export symbols for example).
- lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
- ;;
-
- hpux9* | hpux10* | hpux11*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
- # not for PA HP-UX.
- case $host_cpu in
- hppa*64*|ia64*)
- # +Z the default
- ;;
- *)
- lt_prog_compiler_pic_GCJ='+Z'
- ;;
- esac
- # Is there a better lt_prog_compiler_static that works with the bundled CC?
- lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
- ;;
-
- irix5* | irix6* | nonstopux*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- # PIC (with -KPIC) is the default.
- lt_prog_compiler_static_GCJ='-non_shared'
- ;;
-
- newsos6)
- lt_prog_compiler_pic_GCJ='-KPIC'
- lt_prog_compiler_static_GCJ='-Bstatic'
- ;;
-
- linux*)
- case $cc_basename in
- icc* | ecc*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- lt_prog_compiler_pic_GCJ='-KPIC'
- lt_prog_compiler_static_GCJ='-static'
- ;;
- pgcc* | pgf77* | pgf90* | pgf95*)
- # Portland Group compilers (*not* the Pentium gcc compiler,
- # which looks to be a dead project)
- lt_prog_compiler_wl_GCJ='-Wl,'
- lt_prog_compiler_pic_GCJ='-fpic'
- lt_prog_compiler_static_GCJ='-Bstatic'
- ;;
- ccc*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- # All Alpha code is PIC.
- lt_prog_compiler_static_GCJ='-non_shared'
- ;;
- esac
- ;;
-
- osf3* | osf4* | osf5*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- # All OSF/1 code is PIC.
- lt_prog_compiler_static_GCJ='-non_shared'
- ;;
-
- solaris*)
- lt_prog_compiler_pic_GCJ='-KPIC'
- lt_prog_compiler_static_GCJ='-Bstatic'
- case $cc_basename in
- f77* | f90* | f95*)
- lt_prog_compiler_wl_GCJ='-Qoption ld ';;
- *)
- lt_prog_compiler_wl_GCJ='-Wl,';;
- esac
- ;;
-
- sunos4*)
- lt_prog_compiler_wl_GCJ='-Qoption ld '
- lt_prog_compiler_pic_GCJ='-PIC'
- lt_prog_compiler_static_GCJ='-Bstatic'
- ;;
-
- sysv4 | sysv4.2uw2* | sysv4.3*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- lt_prog_compiler_pic_GCJ='-KPIC'
- lt_prog_compiler_static_GCJ='-Bstatic'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec ;then
- lt_prog_compiler_pic_GCJ='-Kconform_pic'
- lt_prog_compiler_static_GCJ='-Bstatic'
- fi
- ;;
-
- sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- lt_prog_compiler_pic_GCJ='-KPIC'
- lt_prog_compiler_static_GCJ='-Bstatic'
- ;;
-
- unicos*)
- lt_prog_compiler_wl_GCJ='-Wl,'
- lt_prog_compiler_can_build_shared_GCJ=no
- ;;
-
- uts4*)
- lt_prog_compiler_pic_GCJ='-pic'
- lt_prog_compiler_static_GCJ='-Bstatic'
- ;;
-
- *)
- lt_prog_compiler_can_build_shared_GCJ=no
- ;;
- esac
- fi
-
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$lt_prog_compiler_pic_GCJ"; then
-
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6
-if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_pic_works_GCJ=no
- ac_outfile=conftest.$ac_objext
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
- lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- # The option is referenced via a variable to avoid confusing sed.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15806: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>conftest.err)
- ac_status=$?
- cat conftest.err >&5
- echo "$as_me:15810: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s "$ac_outfile"; then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings other than the usual output.
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_pic_works_GCJ=yes
- fi
- fi
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6
-
-if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
- case $lt_prog_compiler_pic_GCJ in
- "" | " "*) ;;
- *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
- esac
-else
- lt_prog_compiler_pic_GCJ=
- lt_prog_compiler_can_build_shared_GCJ=no
-fi
-
-fi
-case $host_os in
- # For platforms which do not support PIC, -DPIC is meaningless:
- *djgpp*)
- lt_prog_compiler_pic_GCJ=
- ;;
- *)
- lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
- ;;
-esac
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
-if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_prog_compiler_static_works_GCJ=no
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
- printf "$lt_simple_link_test_code" > conftest.$ac_ext
- if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
- # The linker can only warn and ignore the option if not recognized
- # So say no if there are warnings
- if test -s conftest.err; then
- # Append any errors to the config.log.
- cat conftest.err 1>&5
- $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
- $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
- if diff conftest.exp conftest.er2 >/dev/null; then
- lt_prog_compiler_static_works_GCJ=yes
- fi
- else
- lt_prog_compiler_static_works_GCJ=yes
- fi
- fi
- $rm conftest*
- LDFLAGS="$save_LDFLAGS"
-
-fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6
-
-if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
- :
-else
- lt_prog_compiler_static_GCJ=
-fi
-
-
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
-if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- lt_cv_prog_compiler_c_o_GCJ=no
- $rm -r conftest 2>/dev/null
- mkdir conftest
- cd conftest
- mkdir out
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- lt_compiler_flag="-o out/conftest2.$ac_objext"
- # Insert the option either (1) after the last *FLAGS variable, or
- # (2) before a word containing "conftest.", or (3) at the end.
- # Note that $ac_compile itself does not contain backslashes and begins
- # with a dollar sign (not a hyphen), so the echo should work correctly.
- lt_compile=`echo "$ac_compile" | $SED \
- -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
- -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
- -e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15910: $lt_compile\"" >&5)
- (eval "$lt_compile" 2>out/conftest.err)
- ac_status=$?
- cat out/conftest.err >&5
- echo "$as_me:15914: \$? = $ac_status" >&5
- if (exit $ac_status) && test -s out/conftest2.$ac_objext
- then
- # The compiler can only warn and ignore the option if not recognized
- # So say no if there are warnings
- $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
- $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
- if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
- lt_cv_prog_compiler_c_o_GCJ=yes
- fi
- fi
- chmod u+w . 2>&5
- $rm conftest*
- # SGI C++ compiler will create directory out/ii_files/ for
- # template instantiation
- test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
- $rm out/* && rmdir out
- cd ..
- rmdir conftest
- $rm conftest*
-
-fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6
-
-
-hard_links="nottested"
-if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
- # do not overwrite the value of need_locks provided by the user
- echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
- hard_links=yes
- $rm conftest*
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- touch conftest.a
- ln conftest.a conftest.b 2>&5 || hard_links=no
- ln conftest.a conftest.b 2>/dev/null && hard_links=no
- echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6
- if test "$hard_links" = no; then
- { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
-echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
- need_locks=warn
- fi
-else
- need_locks=no
-fi
-
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
-
- runpath_var=
- allow_undefined_flag_GCJ=
- enable_shared_with_static_runtimes_GCJ=no
- archive_cmds_GCJ=
- archive_expsym_cmds_GCJ=
- old_archive_From_new_cmds_GCJ=
- old_archive_from_expsyms_cmds_GCJ=
- export_dynamic_flag_spec_GCJ=
- whole_archive_flag_spec_GCJ=
- thread_safe_flag_spec_GCJ=
- hardcode_libdir_flag_spec_GCJ=
- hardcode_libdir_flag_spec_ld_GCJ=
- hardcode_libdir_separator_GCJ=
- hardcode_direct_GCJ=no
- hardcode_minus_L_GCJ=no
- hardcode_shlibpath_var_GCJ=unsupported
- link_all_deplibs_GCJ=unknown
- hardcode_automatic_GCJ=no
- module_cmds_GCJ=
- module_expsym_cmds_GCJ=
- always_export_symbols_GCJ=no
- export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
- # include_expsyms should be a list of space-separated symbols to be *always*
- # included in the symbol list
- include_expsyms_GCJ=
- # exclude_expsyms can be an extended regexp of symbols to exclude
- # it will be wrapped by ` (' and `)$', so one must not match beginning or
- # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
- # as well as any symbol that contains `d'.
- exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
- # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
- # platforms (ab)use it in PIC code, but their linkers get confused if
- # the symbol is explicitly referenced. Since portable code cannot
- # rely on this symbol name, it's probably fine to never include it in
- # preloaded symbol tables.
- extract_expsyms_cmds=
- # Just being paranoid about ensuring that cc_basename is set.
- for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
- case $host_os in
- cygwin* | mingw* | pw32*)
- # FIXME: the MSVC++ port hasn't been tested in a loooong time
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- if test "$GCC" != yes; then
- with_gnu_ld=no
- fi
- ;;
- interix*)
- # we just hope/assume this is gcc and not c89 (= MSVC++)
- with_gnu_ld=yes
- ;;
- openbsd*)
- with_gnu_ld=no
- ;;
- esac
-
- ld_shlibs_GCJ=yes
- if test "$with_gnu_ld" = yes; then
- # If archive_cmds runs LD, not CC, wlarc should be empty
- wlarc='${wl}'
-
- # Set some defaults for GNU ld with shared library support. These
- # are reset later if shared libraries are not supported. Putting them
- # here allows them to be overridden if necessary.
- runpath_var=LD_RUN_PATH
- hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
- export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
- # ancient GNU ld didn't support --whole-archive et. al.
- if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
- whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
- else
- whole_archive_flag_spec_GCJ=
- fi
- supports_anon_versioning=no
- case `$LD -v 2>/dev/null` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
- *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
- *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
- *\ 2.11.*) ;; # other 2.11 versions
- *) supports_anon_versioning=yes ;;
- esac
-
- # See if GNU ld supports shared libraries.
- case $host_os in
- aix3* | aix4* | aix5*)
- # On AIX/PPC, the GNU linker is very broken
- if test "$host_cpu" != ia64; then
- ld_shlibs_GCJ=no
- cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support. If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
- fi
- ;;
-
- amigaos*)
- archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- hardcode_minus_L_GCJ=yes
-
- # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
- # that the semantics of dynamic libraries on AmigaOS, at least up
- # to version 4, is to share data among multiple programs linked
- # with the same dynamic library. Since this doesn't match the
- # behavior of shared libraries on other platforms, we can't use
- # them.
- ld_shlibs_GCJ=no
- ;;
-
- beos*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- allow_undefined_flag_GCJ=unsupported
- # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
- # support --undefined. This deserves some investigation. FIXME
- archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- else
- ld_shlibs_GCJ=no
- fi
- ;;
-
- cygwin* | mingw* | pw32*)
- # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
- # as there is no search path for DLLs.
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- allow_undefined_flag_GCJ=unsupported
- always_export_symbols_GCJ=no
- enable_shared_with_static_runtimes_GCJ=yes
- export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
-
- if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
- archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- # If the export-symbols file already is a .def file (1st line
- # is EXPORTS), use it as is; otherwise, prepend...
- archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
- cp $export_symbols $output_objdir/$soname.def;
- else
- echo EXPORTS > $output_objdir/$soname.def;
- cat $export_symbols >> $output_objdir/$soname.def;
- fi~
- $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
- else
- ld_shlibs_GCJ=no
- fi
- ;;
-
- interix3*)
- hardcode_direct_GCJ=no
- hardcode_shlibpath_var_GCJ=no
- hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
- export_dynamic_flag_spec_GCJ='${wl}-E'
- # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
- # Instead, shared libraries are loaded at an image base (0x10000000 by
- # default) and relocated if they conflict, which is a slow very memory
- # consuming and fragmenting process. To avoid this, we pick a random,
- # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
- # time. Moving up from 0x10000000 also allows more sbrk(2) space.
- archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
- ;;
-
- linux*)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- tmp_addflag=
- case $cc_basename,$host_cpu in
- pgcc*) # Portland Group C compiler
- whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag'
- ;;
- pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
- whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
- tmp_addflag=' $pic_flag -Mnomain' ;;
- ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
- tmp_addflag=' -i_dynamic' ;;
- efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
- tmp_addflag=' -i_dynamic -nofor_main' ;;
- ifc* | ifort*) # Intel Fortran compiler
- tmp_addflag=' -nofor_main' ;;
- esac
- archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
- if test $supports_anon_versioning = yes; then
- archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
- cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
- $echo "local: *; };" >> $output_objdir/$libname.ver~
- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
- fi
- link_all_deplibs_GCJ=no
- else
- ld_shlibs_GCJ=no
- fi
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
- wlarc=
- else
- archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- fi
- ;;
-
- solaris*)
- if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
- ld_shlibs_GCJ=no
- cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
- elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs_GCJ=no
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
- case `$LD -v 2>&1` in
- *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
- ld_shlibs_GCJ=no
- cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems. Therefore, libtool
-*** is disabling shared libraries support. We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
- ;;
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
- archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
- archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
- else
- ld_shlibs_GCJ=no
- fi
- ;;
- esac
- ;;
-
- sunos4*)
- archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- wlarc=
- hardcode_direct_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- *)
- if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
- archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
- archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
- else
- ld_shlibs_GCJ=no
- fi
- ;;
- esac
-
- if test "$ld_shlibs_GCJ" = no; then
- runpath_var=
- hardcode_libdir_flag_spec_GCJ=
- export_dynamic_flag_spec_GCJ=
- whole_archive_flag_spec_GCJ=
- fi
- else
- # PORTME fill in a description of your system's linker (not GNU ld)
- case $host_os in
- aix3*)
- allow_undefined_flag_GCJ=unsupported
- always_export_symbols_GCJ=yes
- archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
- # Note: this linker hardcodes the directories in LIBPATH if there
- # are no directories specified by -L.
- hardcode_minus_L_GCJ=yes
- if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
- # Neither direct hardcoding nor static linking is supported with a
- # broken collect2.
- hardcode_direct_GCJ=unsupported
- fi
- ;;
-
- aix4* | aix5*)
- if test "$host_cpu" = ia64; then
- # On IA64, the linker does run time linking by default, so we don't
- # have to do anything special.
- aix_use_runtimelinking=no
- exp_sym_flag='-Bexport'
- no_entry_flag=""
- else
- # If we're using GNU nm, then we don't want the "-C" option.
- # -C means demangle to AIX nm, but means don't demangle with GNU nm
- if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
- export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- else
- export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
- fi
- aix_use_runtimelinking=no
-
- # Test if we are trying to use run time linking or normal
- # AIX style linking. If -brtl is somewhere in LDFLAGS, we
- # need to do runtime linking.
- case $host_os in aix4.[23]|aix4.[23].*|aix5*)
- for ld_flag in $LDFLAGS; do
- if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
- aix_use_runtimelinking=yes
- break
- fi
- done
- ;;
- esac
-
- exp_sym_flag='-bexport'
- no_entry_flag='-bnoentry'
- fi
-
- # When large executables or shared objects are built, AIX ld can
- # have problems creating the table of contents. If linking a library
- # or program results in "error TOC overflow" add -mminimal-toc to
- # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
- # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
- archive_cmds_GCJ=''
- hardcode_direct_GCJ=yes
- hardcode_libdir_separator_GCJ=':'
- link_all_deplibs_GCJ=yes
-
- if test "$GCC" = yes; then
- case $host_os in aix4.[012]|aix4.[012].*)
- # We only want to do this on AIX 4.2 and lower, the check
- # below for broken collect2 doesn't work under 4.3+
- collect2name=`${CC} -print-prog-name=collect2`
- if test -f "$collect2name" && \
- strings "$collect2name" | grep resolve_lib_name >/dev/null
- then
- # We have reworked collect2
- hardcode_direct_GCJ=yes
- else
- # We have old collect2
- hardcode_direct_GCJ=unsupported
- # It fails to find uninstalled libraries when the uninstalled
- # path is not listed in the libpath. Setting hardcode_minus_L
- # to unsupported forces relinking
- hardcode_minus_L_GCJ=yes
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- hardcode_libdir_separator_GCJ=
- fi
- ;;
- esac
- shared_flag='-shared'
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag="$shared_flag "'${wl}-G'
- fi
- else
- # not using gcc
- if test "$host_cpu" = ia64; then
- # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
- # chokes on -Wl,-G. The following line is correct:
- shared_flag='-G'
- else
- if test "$aix_use_runtimelinking" = yes; then
- shared_flag='${wl}-G'
- else
- shared_flag='${wl}-bM:SRE'
- fi
- fi
- fi
-
- # It seems that -bexpall does not export symbols beginning with
- # underscore (_), so it is better to generate a list of symbols to export.
- always_export_symbols_GCJ=yes
- if test "$aix_use_runtimelinking" = yes; then
- # Warning - without using the other runtime loading flags (-brtl),
- # -berok will link without error, but may produce a broken library.
- allow_undefined_flag_GCJ='-berok'
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
- archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
- else
- if test "$host_cpu" = ia64; then
- hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
- allow_undefined_flag_GCJ="-z nodefs"
- archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
- else
- # Determine the default libpath from the value encoded in an empty executable.
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
-
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
-}'`; fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
-
- hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
- # Warning - without using the other run time loading flags,
- # -berok will link without error, but may produce a broken library.
- no_undefined_flag_GCJ=' ${wl}-bernotok'
- allow_undefined_flag_GCJ=' ${wl}-berok'
- # Exported symbols can be pulled into shared objects from archives
- whole_archive_flag_spec_GCJ='$convenience'
- archive_cmds_need_lc_GCJ=yes
- # This is similar to how AIX traditionally builds its shared libraries.
- archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
- fi
- fi
- ;;
-
- amigaos*)
- archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- hardcode_minus_L_GCJ=yes
- # see comment about different semantics on the GNU ld section
- ld_shlibs_GCJ=no
- ;;
-
- bsdi[45]*)
- export_dynamic_flag_spec_GCJ=-rdynamic
- ;;
-
- cygwin* | mingw* | pw32*)
- # When not using gcc, we currently assume that we are using
- # Microsoft Visual C++.
- # hardcode_libdir_flag_spec is actually meaningless, as there is
- # no search path for DLLs.
- hardcode_libdir_flag_spec_GCJ=' '
- allow_undefined_flag_GCJ=unsupported
- # Tell ltmain to make .lib files, not .a files.
- libext=lib
- # Tell ltmain to make .dll files, not .so files.
- shrext_cmds=".dll"
- # FIXME: Setting linknames here is a bad hack.
- archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
- # The linker will automatically build a .lib file if we build a DLL.
- old_archive_From_new_cmds_GCJ='true'
- # FIXME: Should let the user specify the lib program.
- old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs'
- fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`'
- enable_shared_with_static_runtimes_GCJ=yes
- ;;
-
- darwin* | rhapsody*)
- case $host_os in
- rhapsody* | darwin1.[012])
- allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
- ;;
- *) # Darwin 1.3 on
- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
- allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- else
- case ${MACOSX_DEPLOYMENT_TARGET} in
- 10.[012])
- allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
- ;;
- 10.*)
- allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
- ;;
- esac
- fi
- ;;
- esac
- archive_cmds_need_lc_GCJ=no
- hardcode_direct_GCJ=no
- hardcode_automatic_GCJ=yes
- hardcode_shlibpath_var_GCJ=unsupported
- whole_archive_flag_spec_GCJ=''
- link_all_deplibs_GCJ=yes
- if test "$GCC" = yes ; then
- output_verbose_link_cmd='echo'
- archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
- module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- else
- case $cc_basename in
- xlc*)
- output_verbose_link_cmd='echo'
- archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
- module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
- archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
- ;;
- *)
- ld_shlibs_GCJ=no
- ;;
- esac
- fi
- ;;
-
- dgux*)
- archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- freebsd1*)
- ld_shlibs_GCJ=no
- ;;
-
- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
- # support. Future versions do this automatically, but an explicit c++rt0.o
- # does not break anything, and helps significantly (at the cost of a little
- # extra space).
- freebsd2.2*)
- archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
- hardcode_libdir_flag_spec_GCJ='-R$libdir'
- hardcode_direct_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- # Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
- archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_GCJ=yes
- hardcode_minus_L_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
- freebsd* | dragonfly*)
- archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec_GCJ='-R$libdir'
- hardcode_direct_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- # GNU/kFreeBSD uses gcc -shared to do shared libraries.
- kfreebsd*-gnu)
- archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec_GCJ='-R$libdir'
- hardcode_direct_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- link_all_deplibs_GCJ=no
- ;;
-
- hpux9*)
- if test "$GCC" = yes; then
- archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- else
- archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
- fi
- hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_GCJ=:
- hardcode_direct_GCJ=yes
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L_GCJ=yes
- export_dynamic_flag_spec_GCJ='${wl}-E'
- ;;
-
- hpux10*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_GCJ=:
-
- hardcode_direct_GCJ=yes
- export_dynamic_flag_spec_GCJ='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L_GCJ=yes
- fi
- ;;
-
- hpux11*)
- if test "$GCC" = yes -a "$with_gnu_ld" = no; then
- case $host_cpu in
- hppa*64*)
- archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- else
- case $host_cpu in
- hppa*64*)
- archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- ia64*)
- archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- *)
- archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
- ;;
- esac
- fi
- if test "$with_gnu_ld" = no; then
- hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
- hardcode_libdir_separator_GCJ=:
-
- case $host_cpu in
- hppa*64*|ia64*)
- hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
- hardcode_direct_GCJ=no
- hardcode_shlibpath_var_GCJ=no
- ;;
- *)
- hardcode_direct_GCJ=yes
- export_dynamic_flag_spec_GCJ='${wl}-E'
-
- # hardcode_minus_L: Not really in the search PATH,
- # but as the default location of the library.
- hardcode_minus_L_GCJ=yes
- ;;
- esac
- fi
- ;;
-
- irix5* | irix6* | nonstopux*)
- if test "$GCC" = yes; then
- archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
- fi
- hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_GCJ=:
- link_all_deplibs_GCJ=yes
- ;;
-
- netbsd* | netbsdelf*-gnu | knetbsd*-gnu)
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
- else
- archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
- fi
- hardcode_libdir_flag_spec_GCJ='-R$libdir'
- hardcode_direct_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- newsos6)
- archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_GCJ=yes
- hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_GCJ=:
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- openbsd*)
- hardcode_direct_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
- hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
- export_dynamic_flag_spec_GCJ='${wl}-E'
- else
- case $host_os in
- openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
- archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec_GCJ='-R$libdir'
- ;;
- *)
- archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
- hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
- ;;
- esac
- fi
- ;;
-
- os2*)
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- hardcode_minus_L_GCJ=yes
- allow_undefined_flag_GCJ=unsupported
- archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
- old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
- ;;
-
- osf3*)
- if test "$GCC" = yes; then
- allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- else
- allow_undefined_flag_GCJ=' -expect_unresolved \*'
- archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- fi
- hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
- hardcode_libdir_separator_GCJ=:
- ;;
-
- osf4* | osf5*) # as osf3* with the addition of -msym flag
- if test "$GCC" = yes; then
- allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
- archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
- hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
- else
- allow_undefined_flag_GCJ=' -expect_unresolved \*'
- archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
- archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
- $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
-
- # Both c and cxx compiler support -rpath directly
- hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
- fi
- hardcode_libdir_separator_GCJ=:
- ;;
-
- solaris*)
- no_undefined_flag_GCJ=' -z text'
- if test "$GCC" = yes; then
- wlarc='${wl}'
- archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
- else
- wlarc=''
- archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
- archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
- $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
- fi
- hardcode_libdir_flag_spec_GCJ='-R$libdir'
- hardcode_shlibpath_var_GCJ=no
- case $host_os in
- solaris2.[0-5] | solaris2.[0-5].*) ;;
- *)
- # The compiler driver will combine linker options so we
- # cannot just pass the convience library names through
- # without $wl, iff we do not link with $LD.
- # Luckily, gcc supports the same syntax we need for Sun Studio.
- # Supported since Solaris 2.6 (maybe 2.5.1?)
- case $wlarc in
- '')
- whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;;
- *)
- whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
- esac ;;
- esac
- link_all_deplibs_GCJ=yes
- ;;
-
- sunos4*)
- if test "x$host_vendor" = xsequent; then
- # Use $CC to link under sequent, because it throws in some extra .o
- # files that make .init and .fini sections work.
- archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
- fi
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- hardcode_direct_GCJ=yes
- hardcode_minus_L_GCJ=yes
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- sysv4)
- case $host_vendor in
- sni)
- archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_GCJ=yes # is this really true???
- ;;
- siemens)
- ## LD is ld it makes a PLAMLIB
- ## CC just makes a GrossModule.
- archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
- reload_cmds_GCJ='$CC -r -o $output$reload_objs'
- hardcode_direct_GCJ=no
- ;;
- motorola)
- archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
- ;;
- esac
- runpath_var='LD_RUN_PATH'
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- sysv4.3*)
- archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var_GCJ=no
- export_dynamic_flag_spec_GCJ='-Bexport'
- ;;
-
- sysv4*MP*)
- if test -d /usr/nec; then
- archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_shlibpath_var_GCJ=no
- runpath_var=LD_RUN_PATH
- hardcode_runpath_var=yes
- ld_shlibs_GCJ=yes
- fi
- ;;
-
- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
- no_undefined_flag_GCJ='${wl}-z,text'
- archive_cmds_need_lc_GCJ=no
- hardcode_shlibpath_var_GCJ=no
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- sysv5* | sco3.2v5* | sco5v6*)
- # Note: We can NOT use -z defs as we might desire, because we do not
- # link with -lc, and that would cause any symbols used from libc to
- # always be unresolved, which means just about no library would
- # ever link correctly. If we're not using GNU ld we use -z text
- # though, which does catch some bad symbols but isn't as heavy-handed
- # as -z defs.
- no_undefined_flag_GCJ='${wl}-z,text'
- allow_undefined_flag_GCJ='${wl}-z,nodefs'
- archive_cmds_need_lc_GCJ=no
- hardcode_shlibpath_var_GCJ=no
- hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
- hardcode_libdir_separator_GCJ=':'
- link_all_deplibs_GCJ=yes
- export_dynamic_flag_spec_GCJ='${wl}-Bexport'
- runpath_var='LD_RUN_PATH'
-
- if test "$GCC" = yes; then
- archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- else
- archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
- fi
- ;;
-
- uts4*)
- archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
- hardcode_libdir_flag_spec_GCJ='-L$libdir'
- hardcode_shlibpath_var_GCJ=no
- ;;
-
- *)
- ld_shlibs_GCJ=no
- ;;
- esac
- fi
-
-echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
-echo "${ECHO_T}$ld_shlibs_GCJ" >&6
-test "$ld_shlibs_GCJ" = no && can_build_shared=no
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$archive_cmds_need_lc_GCJ" in
-x|xyes)
- # Assume -lc should be added
- archive_cmds_need_lc_GCJ=yes
-
- if test "$enable_shared" = yes && test "$GCC" = yes; then
- case $archive_cmds_GCJ in
- *'~'*)
- # FIXME: we may have to deal with multi-command sequences.
- ;;
- '$CC '*)
- # Test whether the compiler implicitly links with -lc since on some
- # systems, -lgcc has to come before -lc. If gcc already passes -lc
- # to ld, don't add -lc before -lgcc.
- echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
- $rm conftest*
- printf "$lt_simple_compile_test_code" > conftest.$ac_ext
-
- if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } 2>conftest.err; then
- soname=conftest
- lib=conftest
- libobjs=conftest.$ac_objext
- deplibs=
- wl=$lt_prog_compiler_wl_GCJ
- pic_flag=$lt_prog_compiler_pic_GCJ
- compiler_flags=-v
- linker_flags=-v
- verstring=
- output_objdir=.
- libname=conftest
- lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
- allow_undefined_flag_GCJ=
- if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
- (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
- then
- archive_cmds_need_lc_GCJ=no
- else
- archive_cmds_need_lc_GCJ=yes
- fi
- allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
- else
- cat conftest.err 1>&5
- fi
- $rm conftest*
- echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
-echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6
- ;;
- esac
- fi
- ;;
-esac
-
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
- # if the path contains ";" then we assume it to be the separator
- # otherwise default to the standard path separator (i.e. ":") - it is
- # assumed that no part of a normal pathname contains ";" but that should
- # okay in the real world where ";" in dirpaths is itself problematic.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
-else
- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
- shlibpath_var=LIBPATH
-
- # AIX 3 has no versioning support, so we append a major version to the name.
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
-
-aix4* | aix5*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- hardcode_into_libs=yes
- if test "$host_cpu" = ia64; then
- # AIX 5 supports IA64
- library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- else
- # With GCC up to 2.95.x, collect2 would create an import file
- # for dependence libraries. The import file would start with
- # the line `#! .'. This would cause the generated library to
- # depend on `.', always an invalid library. This was fixed in
- # development snapshots of GCC prior to 3.0.
- case $host_os in
- aix4 | aix4.[01] | aix4.[01].*)
- if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
- echo ' yes '
- echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
- :
- else
- can_build_shared=no
- fi
- ;;
- esac
- # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
- # soname into executable. Probably we can add versioning support to
- # collect2, so additional links can be useful in future.
- if test "$aix_use_runtimelinking" = yes; then
- # If using run time linking (on AIX 4.2 or later) use lib<name>.so
- # instead of lib<name>.a to let people know that these are not
- # typical AIX shared libraries.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- else
- # We preserve .a as extension for shared libraries through AIX4.2
- # and later when we are not doing run time linking.
- library_names_spec='${libname}${release}.a $libname.a'
- soname_spec='${libname}${release}${shared_ext}$major'
- fi
- shlibpath_var=LIBPATH
- fi
- ;;
-
-amigaos*)
- library_names_spec='$libname.ixlibrary $libname.a'
- # Create ${libname}_ixlibrary.a entries in /sys/libs.
- finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
- ;;
-
-beos*)
- library_names_spec='${libname}${shared_ext}'
- dynamic_linker="$host_os ld.so"
- shlibpath_var=LIBRARY_PATH
- ;;
-
-bsdi[45]*)
- version_type=linux
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
- sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
- # the default ld.so.conf also contains /usr/contrib/lib and
- # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
- # libtool to hard-code these into programs
- ;;
-
-cygwin* | mingw* | pw32*)
- version_type=windows
- shrext_cmds=".dll"
- need_version=no
- need_lib_prefix=no
-
- case $GCC,$host_os in
- yes,cygwin* | yes,mingw* | yes,pw32*)
- library_names_spec='$libname.dll.a'
- # DLL is installed to $(libdir)/../bin by postinstall_cmds
- postinstall_cmds='base_file=`basename \${file}`~
- dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
- dldir=$destdir/`dirname \$dlpath`~
- test -d \$dldir || mkdir -p \$dldir~
- $install_prog $dir/$dlname \$dldir/$dlname~
- chmod a+x \$dldir/$dlname'
- postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
- dlpath=$dir/\$dldll~
- $rm \$dlpath'
- shlibpath_overrides_runpath=yes
-
- case $host_os in
- cygwin*)
- # Cygwin DLLs use 'cyg' prefix rather than 'lib'
- soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
- ;;
- mingw*)
- # MinGW DLLs use traditional 'lib' prefix
- soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
- if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
- # It is most probably a Windows format PATH printed by
- # mingw gcc, but we are running on Cygwin. Gcc prints its search
- # path with ; separators, and with drive letters. We can handle the
- # drive letters (cygwin fileutils understands them), so leave them,
- # especially as we might pass files found there to a mingw objdump,
- # which wouldn't understand a cygwinified path. Ahh.
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
- else
- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
- fi
- ;;
- pw32*)
- # pw32 DLLs use 'pw' prefix rather than 'lib'
- library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
- ;;
- esac
- ;;
-
- *)
- library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
- ;;
- esac
- dynamic_linker='Win32 ld.exe'
- # FIXME: first we should search . and the directory the executable is in
- shlibpath_var=PATH
- ;;
-
-darwin* | rhapsody*)
- dynamic_linker="$host_os dyld"
- version_type=darwin
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
- soname_spec='${libname}${release}${major}$shared_ext'
- shlibpath_overrides_runpath=yes
- shlibpath_var=DYLD_LIBRARY_PATH
- shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
- if test "$GCC" = yes; then
- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
- else
- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
- fi
- sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
- ;;
-
-dgux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-freebsd1*)
- dynamic_linker=no
- ;;
-
-kfreebsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-freebsd* | dragonfly*)
- # DragonFly does not have aout. When/if they implement a new
- # versioning mechanism, adjust this.
- if test -x /usr/bin/objformat; then
- objformat=`/usr/bin/objformat`
- else
- case $host_os in
- freebsd[123]*) objformat=aout ;;
- *) objformat=elf ;;
- esac
- fi
- version_type=freebsd-$objformat
- case $version_type in
- freebsd-elf*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- need_version=no
- need_lib_prefix=no
- ;;
- freebsd-*)
- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
- need_version=yes
- ;;
- esac
- shlibpath_var=LD_LIBRARY_PATH
- case $host_os in
- freebsd2*)
- shlibpath_overrides_runpath=yes
- ;;
- freebsd3.[01]* | freebsdelf3.[01]*)
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
- freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
- freebsd*) # from 4.6 on
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
- esac
- ;;
-
-gnu*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- ;;
-
-hpux9* | hpux10* | hpux11*)
- # Give a soname corresponding to the major version so that dld.sl refuses to
- # link against other versions.
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- case $host_cpu in
- ia64*)
- shrext_cmds='.so'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.so"
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- if test "X$HPUX_IA64_MODE" = X32; then
- sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
- else
- sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
- fi
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- hppa*64*)
- shrext_cmds='.sl'
- hardcode_into_libs=yes
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
- shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
- sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
- ;;
- *)
- shrext_cmds='.sl'
- dynamic_linker="$host_os dld.sl"
- shlibpath_var=SHLIB_PATH
- shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- ;;
- esac
- # HP-UX runs *really* slowly unless shared libraries are mode 555.
- postinstall_cmds='chmod 555 $lib'
- ;;
-
-interix3*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
-irix5* | irix6* | nonstopux*)
- case $host_os in
- nonstopux*) version_type=nonstopux ;;
- *)
- if test "$lt_cv_prog_gnu_ld" = yes; then
- version_type=linux
- else
- version_type=irix
- fi ;;
- esac
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
- case $host_os in
- irix5* | nonstopux*)
- libsuff= shlibsuff=
- ;;
- *)
- case $LD in # libtool.m4 will add one of these switches to LD
- *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
- libsuff= shlibsuff= libmagic=32-bit;;
- *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
- libsuff=32 shlibsuff=N32 libmagic=N32;;
- *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
- libsuff=64 shlibsuff=64 libmagic=64-bit;;
- *) libsuff= shlibsuff= libmagic=never-match;;
- esac
- ;;
- esac
- shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
- sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
- hardcode_into_libs=yes
- ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
- dynamic_linker=no
- ;;
-
-# This must be Linux ELF.
-linux*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- # This implies no fast_install, which is unacceptable.
- # Some rework will be needed to allow for fast_install
- # before this can be enabled.
- hardcode_into_libs=yes
-
- # Append ld.so.conf contents to the search path
- if test -f /etc/ld.so.conf; then
- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
- sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
- fi
-
- # We used to test for /lib/ld.so.1 and disable shared libraries on
- # powerpc, because MkLinux only supported shared libraries with the
- # GNU dynamic linker. Since this was broken with cross compilers,
- # most powerpc-linux boxes support dynamic linking these days and
- # people can always --disable-shared, the test was removed, and we
- # assume the GNU/Linux dynamic linker is in use.
- dynamic_linker='GNU/Linux ld.so'
- ;;
-
-netbsdelf*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='NetBSD ld.elf_so'
- ;;
-
-knetbsd*-gnu)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- dynamic_linker='GNU ld.so'
- ;;
-
-netbsd*)
- version_type=sunos
- need_lib_prefix=no
- need_version=no
- if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- dynamic_linker='NetBSD (a.out) ld.so'
- else
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- dynamic_linker='NetBSD ld.elf_so'
- fi
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- ;;
-
-newsos6)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-nto-qnx*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- ;;
-
-openbsd*)
- version_type=sunos
- sys_lib_dlsearch_path_spec="/usr/lib"
- need_lib_prefix=no
- # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
- case $host_os in
- openbsd3.3 | openbsd3.3.*) need_version=yes ;;
- *) need_version=no ;;
- esac
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
- case $host_os in
- openbsd2.[89] | openbsd2.[89].*)
- shlibpath_overrides_runpath=no
- ;;
- *)
- shlibpath_overrides_runpath=yes
- ;;
- esac
- else
- shlibpath_overrides_runpath=yes
- fi
- ;;
-
-os2*)
- libname_spec='$name'
- shrext_cmds=".dll"
- need_lib_prefix=no
- library_names_spec='$libname${shared_ext} $libname.a'
- dynamic_linker='OS/2 ld.exe'
- shlibpath_var=LIBPATH
- ;;
-
-osf3* | osf4* | osf5*)
- version_type=osf
- need_lib_prefix=no
- need_version=no
- soname_spec='${libname}${release}${shared_ext}$major'
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- shlibpath_var=LD_LIBRARY_PATH
- sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
- sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
- ;;
-
-solaris*)
- version_type=linux
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- hardcode_into_libs=yes
- # ldd complains unless libraries are executable
- postinstall_cmds='chmod +x $lib'
- ;;
-
-sunos4*)
- version_type=sunos
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
- finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=yes
- if test "$with_gnu_ld" = yes; then
- need_lib_prefix=no
- fi
- need_version=yes
- ;;
-
-sysv4 | sysv4.3*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- case $host_vendor in
- sni)
- shlibpath_overrides_runpath=no
- need_lib_prefix=no
- export_dynamic_flag_spec='${wl}-Blargedynsym'
- runpath_var=LD_RUN_PATH
- ;;
- siemens)
- need_lib_prefix=no
- ;;
- motorola)
- need_lib_prefix=no
- need_version=no
- shlibpath_overrides_runpath=no
- sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
- ;;
- esac
- ;;
-
-sysv4*MP*)
- if test -d /usr/nec ;then
- version_type=linux
- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
- soname_spec='$libname${shared_ext}.$major'
- shlibpath_var=LD_LIBRARY_PATH
- fi
- ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
- version_type=freebsd-elf
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- hardcode_into_libs=yes
- if test "$with_gnu_ld" = yes; then
- sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
- shlibpath_overrides_runpath=no
- else
- sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
- shlibpath_overrides_runpath=yes
- case $host_os in
- sco3.2v5*)
- sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
- ;;
- esac
- fi
- sys_lib_dlsearch_path_spec='/usr/lib'
- ;;
-
-uts4*)
- version_type=linux
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- ;;
-
-*)
- dynamic_linker=no
- ;;
-esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
- variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
-hardcode_action_GCJ=
-if test -n "$hardcode_libdir_flag_spec_GCJ" || \
- test -n "$runpath_var_GCJ" || \
- test "X$hardcode_automatic_GCJ" = "Xyes" ; then
-
- # We can hardcode non-existant directories.
- if test "$hardcode_direct_GCJ" != no &&
- # If the only mechanism to avoid hardcoding is shlibpath_var, we
- # have to relink, otherwise we might link with an installed library
- # when we should be linking with a yet-to-be-installed one
- ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
- test "$hardcode_minus_L_GCJ" != no; then
- # Linking always hardcodes the temporary library directory.
- hardcode_action_GCJ=relink
- else
- # We can link without hardcoding, and we can hardcode nonexisting dirs.
- hardcode_action_GCJ=immediate
- fi
-else
- # We cannot hardcode anything, or else we can only hardcode existing
- # directories.
- hardcode_action_GCJ=unsupported
-fi
-echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
-echo "${ECHO_T}$hardcode_action_GCJ" >&6
-
-if test "$hardcode_action_GCJ" = relink; then
- # Fast installation is not supported
- enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
- test "$enable_shared" = no; then
- # Fast installation is not necessary
- enable_fast_install=needless
-fi
-
-
-# The else clause should only fire when bootstrapping the
-# libtool distribution, otherwise you forgot to ship ltmain.sh
-# with your package, and you will get complaints that there are
-# no rules to generate ltmain.sh.
-if test -f "$ltmain"; then
- # See if we are running on zsh, and set the options which allow our commands through
- # without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
- # Now quote all the things that may contain metacharacters while being
- # careful not to overquote the AC_SUBSTed values. We take copies of the
- # variables and quote the copies for generation of the libtool script.
- for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
- SED SHELL STRIP \
- libname_spec library_names_spec soname_spec extract_expsyms_cmds \
- old_striplib striplib file_magic_cmd finish_cmds finish_eval \
- deplibs_check_method reload_flag reload_cmds need_locks \
- lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
- lt_cv_sys_global_symbol_to_c_name_address \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- old_postinstall_cmds old_postuninstall_cmds \
- compiler_GCJ \
- CC_GCJ \
- LD_GCJ \
- lt_prog_compiler_wl_GCJ \
- lt_prog_compiler_pic_GCJ \
- lt_prog_compiler_static_GCJ \
- lt_prog_compiler_no_builtin_flag_GCJ \
- export_dynamic_flag_spec_GCJ \
- thread_safe_flag_spec_GCJ \
- whole_archive_flag_spec_GCJ \
- enable_shared_with_static_runtimes_GCJ \
- old_archive_cmds_GCJ \
- old_archive_from_new_cmds_GCJ \
- predep_objects_GCJ \
- postdep_objects_GCJ \
- predeps_GCJ \
- postdeps_GCJ \
- compiler_lib_search_path_GCJ \
- archive_cmds_GCJ \
- archive_expsym_cmds_GCJ \
- postinstall_cmds_GCJ \
- postuninstall_cmds_GCJ \
- old_archive_from_expsyms_cmds_GCJ \
- allow_undefined_flag_GCJ \
- no_undefined_flag_GCJ \
- export_symbols_cmds_GCJ \
- hardcode_libdir_flag_spec_GCJ \
- hardcode_libdir_flag_spec_ld_GCJ \
- hardcode_libdir_separator_GCJ \
- hardcode_automatic_GCJ \
- module_cmds_GCJ \
- module_expsym_cmds_GCJ \
- lt_cv_prog_compiler_c_o_GCJ \
- exclude_expsyms_GCJ \
- include_expsyms_GCJ; do
-
- case $var in
- old_archive_cmds_GCJ | \
- old_archive_from_new_cmds_GCJ | \
- archive_cmds_GCJ | \
- archive_expsym_cmds_GCJ | \
- module_cmds_GCJ | \
- module_expsym_cmds_GCJ | \
- old_archive_from_expsyms_cmds_GCJ | \
- export_symbols_cmds_GCJ | \
- extract_expsyms_cmds | reload_cmds | finish_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case $lt_echo in
- *'\$0 --fallback-echo"')
- lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
- ;;
- esac
-
-cfgfile="$ofile"
-
- cat <<__EOF__ >> "$cfgfile"
-# ### BEGIN LIBTOOL TAG CONFIG: $tagname
-
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc_GCJ
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# An echo program that does not interpret backslashes.
-echo=$lt_echo
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A C compiler.
-LTCC=$lt_LTCC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_LTCFLAGS
-
-# A language-specific compiler.
-CC=$lt_compiler_GCJ
-
-# Is the compiler the GNU C compiler?
-with_gcc=$GCC_GCJ
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# The linker used to build libraries.
-LD=$lt_LD_GCJ
-
-# Whether we need hard or soft links.
-LN_S=$lt_LN_S
-
-# A BSD-compatible nm program.
-NM=$lt_NM
-
-# A symbol stripping program
-STRIP=$lt_STRIP
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=$MAGIC_CMD
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl_GCJ
-
-# Object file suffix (normally "o").
-objext="$ac_objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='$shrext_cmds'
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic_GCJ
-pic_mode=$pic_mode
-
-# What is the maximum length of a command?
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static_GCJ
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$lt_RANLIB
-old_archive_cmds=$lt_old_archive_cmds_GCJ
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
-
-# Commands used to build and install a shared archive.
-archive_cmds=$lt_archive_cmds_GCJ
-archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
-postinstall_cmds=$lt_postinstall_cmds
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=$lt_module_cmds_GCJ
-module_expsym_cmds=$lt_module_expsym_cmds_GCJ
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=$lt_predep_objects_GCJ
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=$lt_postdep_objects_GCJ
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=$lt_predeps_GCJ
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=$lt_postdeps_GCJ
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$lt_file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag_GCJ
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag_GCJ
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$lt_finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action_GCJ
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
-
-# If ld is used when linking, flag to hardcode \$libdir into
-# a binary during linking. This must work even if \$libdir does
-# not exist.
-hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
-
-# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct_GCJ
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L_GCJ
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
-
-# Set to yes if building a shared library automatically hardcodes DIR into the library
-# and all subsequent libraries and executables linked against it.
-hardcode_automatic=$hardcode_automatic_GCJ
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="$variables_saved_for_relink"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs_GCJ
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path_GCJ"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols_GCJ
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds_GCJ
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms_GCJ
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms_GCJ
-
-# ### END LIBTOOL TAG CONFIG: $tagname
-
-__EOF__
-
-
-else
- # If there is no Makefile yet, we rely on a make rule to execute
- # `config.status --recheck' to rerun these tests and create the
- # libtool script then.
- ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
- if test -f "$ltmain_in"; then
- test -f Makefile && make "$ltmain"
- fi
-fi
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC="$lt_save_CC"
-
- else
- tagname=""
- fi
- ;;
-
- RC)
-
-
-
-# Source file extension for RC test sources.
-ac_ext=rc
-
-# Object file extension for compiled RC test sources.
-objext=o
-objext_RC=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
-
-# Code to be used in simple link tests
-lt_simple_link_test_code="$lt_simple_compile_test_code"
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$rm conftest*
-
-ac_outfile=conftest.$ac_objext
-printf "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$rm conftest*
-
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-CC=${RC-"windres"}
-compiler=$CC
-compiler_RC=$CC
-for cc_temp in $compiler""; do
- case $cc_temp in
- compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
- distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
- \-*) ;;
- *) break;;
- esac
-done
-cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
-
-lt_cv_prog_compiler_c_o_RC=yes
-
-# The else clause should only fire when bootstrapping the
-# libtool distribution, otherwise you forgot to ship ltmain.sh
-# with your package, and you will get complaints that there are
-# no rules to generate ltmain.sh.
-if test -f "$ltmain"; then
- # See if we are running on zsh, and set the options which allow our commands through
- # without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
- # Now quote all the things that may contain metacharacters while being
- # careful not to overquote the AC_SUBSTed values. We take copies of the
- # variables and quote the copies for generation of the libtool script.
- for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
- SED SHELL STRIP \
- libname_spec library_names_spec soname_spec extract_expsyms_cmds \
- old_striplib striplib file_magic_cmd finish_cmds finish_eval \
- deplibs_check_method reload_flag reload_cmds need_locks \
- lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
- lt_cv_sys_global_symbol_to_c_name_address \
- sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
- old_postinstall_cmds old_postuninstall_cmds \
- compiler_RC \
- CC_RC \
- LD_RC \
- lt_prog_compiler_wl_RC \
- lt_prog_compiler_pic_RC \
- lt_prog_compiler_static_RC \
- lt_prog_compiler_no_builtin_flag_RC \
- export_dynamic_flag_spec_RC \
- thread_safe_flag_spec_RC \
- whole_archive_flag_spec_RC \
- enable_shared_with_static_runtimes_RC \
- old_archive_cmds_RC \
- old_archive_from_new_cmds_RC \
- predep_objects_RC \
- postdep_objects_RC \
- predeps_RC \
- postdeps_RC \
- compiler_lib_search_path_RC \
- archive_cmds_RC \
- archive_expsym_cmds_RC \
- postinstall_cmds_RC \
- postuninstall_cmds_RC \
- old_archive_from_expsyms_cmds_RC \
- allow_undefined_flag_RC \
- no_undefined_flag_RC \
- export_symbols_cmds_RC \
- hardcode_libdir_flag_spec_RC \
- hardcode_libdir_flag_spec_ld_RC \
- hardcode_libdir_separator_RC \
- hardcode_automatic_RC \
- module_cmds_RC \
- module_expsym_cmds_RC \
- lt_cv_prog_compiler_c_o_RC \
- exclude_expsyms_RC \
- include_expsyms_RC; do
-
- case $var in
- old_archive_cmds_RC | \
- old_archive_from_new_cmds_RC | \
- archive_cmds_RC | \
- archive_expsym_cmds_RC | \
- module_cmds_RC | \
- module_expsym_cmds_RC | \
- old_archive_from_expsyms_cmds_RC | \
- export_symbols_cmds_RC | \
- extract_expsyms_cmds | reload_cmds | finish_cmds | \
- postinstall_cmds | postuninstall_cmds | \
- old_postinstall_cmds | old_postuninstall_cmds | \
- sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
- # Double-quote double-evaled strings.
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
- ;;
- *)
- eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
- ;;
- esac
- done
-
- case $lt_echo in
- *'\$0 --fallback-echo"')
- lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
- ;;
- esac
-
-cfgfile="$ofile"
-
- cat <<__EOF__ >> "$cfgfile"
-# ### BEGIN LIBTOOL TAG CONFIG: $tagname
-
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc_RC
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# An echo program that does not interpret backslashes.
-echo=$lt_echo
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A C compiler.
-LTCC=$lt_LTCC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_LTCFLAGS
-
-# A language-specific compiler.
-CC=$lt_compiler_RC
-
-# Is the compiler the GNU C compiler?
-with_gcc=$GCC_RC
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# The linker used to build libraries.
-LD=$lt_LD_RC
-
-# Whether we need hard or soft links.
-LN_S=$lt_LN_S
-
-# A BSD-compatible nm program.
-NM=$lt_NM
-
-# A symbol stripping program
-STRIP=$lt_STRIP
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=$MAGIC_CMD
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl_RC
-
-# Object file suffix (normally "o").
-objext="$ac_objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='$shrext_cmds'
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic_RC
-pic_mode=$pic_mode
-
-# What is the maximum length of a command?
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static_RC
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$lt_RANLIB
-old_archive_cmds=$lt_old_archive_cmds_RC
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
-
-# Commands used to build and install a shared archive.
-archive_cmds=$lt_archive_cmds_RC
-archive_expsym_cmds=$lt_archive_expsym_cmds_RC
-postinstall_cmds=$lt_postinstall_cmds
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=$lt_module_cmds_RC
-module_expsym_cmds=$lt_module_expsym_cmds_RC
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=$lt_predep_objects_RC
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=$lt_postdep_objects_RC
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=$lt_predeps_RC
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=$lt_postdeps_RC
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=$lt_compiler_lib_search_path_RC
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$lt_file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag_RC
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag_RC
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$lt_finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action_RC
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
-
-# If ld is used when linking, flag to hardcode \$libdir into
-# a binary during linking. This must work even if \$libdir does
-# not exist.
-hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
-
-# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct_RC
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L_RC
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
-
-# Set to yes if building a shared library automatically hardcodes DIR into the library
-# and all subsequent libraries and executables linked against it.
-hardcode_automatic=$hardcode_automatic_RC
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="$variables_saved_for_relink"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs_RC
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path_RC"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols_RC
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds_RC
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms_RC
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms_RC
-
-# ### END LIBTOOL TAG CONFIG: $tagname
-
-__EOF__
-
-
-else
- # If there is no Makefile yet, we rely on a make rule to execute
- # `config.status --recheck' to rerun these tests and create the
- # libtool script then.
- ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
- if test -f "$ltmain_in"; then
- test -f Makefile && make "$ltmain"
- fi
-fi
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC="$lt_save_CC"
-
- ;;
-
- *)
- { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
-echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
-
- # Append the new tag name to the list of available tags.
- if test -n "$tagname" ; then
- available_tags="$available_tags $tagname"
- fi
- fi
- done
- IFS="$lt_save_ifs"
-
- # Now substitute the updated list of available tags.
- if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
- mv "${ofile}T" "$ofile"
- chmod +x "$ofile"
- else
- rm -f "${ofile}T"
- { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
-echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
- { (exit 1); exit 1; }; }
- fi
-fi
-
-
-
-# This can be used to rebuild libtool when needed
-LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
-
-# Always use our own libtool.
-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
-
-# Prevent multiple expansion
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-LIBTOOL="$LIBTOOL --silent"
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
-echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
-if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in
- ./ | .// | /cC/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- done
- done
- ;;
-esac
-done
-
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL=$ac_install_sh
- fi
-fi
-echo "$as_me:$LINENO: result: $INSTALL" >&5
-echo "${ECHO_T}$INSTALL" >&6
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-
-cat >>confdefs.h <<\_ACEOF
-#define PRODUCTION_BUILD 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define PRODUCTION 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define POSIX 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define FEATURE_ENABLE_SSL 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define FEATURE_ENABLE_CHAT_ARCHIVING 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define FEATURE_ENABLE_VOICEMAIL 1
-_ACEOF
-
-
-cat >>confdefs.h <<\_ACEOF
-#define LOGGING 1
-_ACEOF
-
-
-HAVE_EXPAT=no
-echo "$as_me:$LINENO: checking for XML_ParserCreate in -lexpat" >&5
-echo $ECHO_N "checking for XML_ParserCreate in -lexpat... $ECHO_C" >&6
-if test "${ac_cv_lib_expat_XML_ParserCreate+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lexpat $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char XML_ParserCreate ();
-int
-main ()
-{
-XML_ParserCreate ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_expat_XML_ParserCreate=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_expat_XML_ParserCreate=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_expat_XML_ParserCreate" >&5
-echo "${ECHO_T}$ac_cv_lib_expat_XML_ParserCreate" >&6
-if test $ac_cv_lib_expat_XML_ParserCreate = yes; then
- HAVE_EXPAT="yes"
-fi
-
-if test "x$HAVE_EXPAT" = xyes ; then
- EXPAT_LIBS="-lexpat"
-
-else
- { { echo "$as_me:$LINENO: error: Expat is required to build libjingle. You can get it from http://expat.sourceforge.net/" >&5
-echo "$as_me: error: Expat is required to build libjingle. You can get it from http://expat.sourceforge.net/" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-enable_phone=yes
-if test `uname -s` = Linux ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define LINUX 1
-_ACEOF
-
- if test x`ls talk/third_party/gips/VoiceEngine_Linux_gcc.a` != x ; then
- enable_gips=yes
- MEDIA_LIBS=$PWD/talk/third_party/gips/VoiceEngine_Linux_gcc.a
- fi
-elif test `uname -s` = Darwin ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define OSX 1
-_ACEOF
-
- if test x`ls talk/third_party/gips/VoiceEngine_mac_gcc.a` != x ; then
- enable_gips=yes
- MEDIA_LIBS="$PWD/talk/third_party/gips/VoiceEngine_mac_gcc.a -framework CoreAudio -framework AudioToolbox"
- fi
-fi
-
-if test x$enable_gips = xyes ; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_GIPS 1
-_ACEOF
-
-elif test `uname -s` = Linux ; then
-
-
-for ac_header in alsa/asoundlib.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------------ ##
-## Report this to google-talk-open@googlegroups.com ##
-## ------------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
- echo "$as_me:$LINENO: checking for snd_pcm_open in -lasound" >&5
-echo $ECHO_N "checking for snd_pcm_open in -lasound... $ECHO_C" >&6
-if test "${ac_cv_lib_asound_snd_pcm_open+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lasound $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char snd_pcm_open ();
-int
-main ()
-{
-snd_pcm_open ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_asound_snd_pcm_open=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_asound_snd_pcm_open=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_asound_snd_pcm_open" >&5
-echo "${ECHO_T}$ac_cv_lib_asound_snd_pcm_open" >&6
-if test $ac_cv_lib_asound_snd_pcm_open = yes; then
- ALSA_LIBS="-lasound" ;
-cat >>confdefs.h <<\_ACEOF
-#define __ALSA_ENABLED__ 1
-_ACEOF
-
-fi
-
-
-
-fi
-
-done
-
-
-
-
- succeeded=no
-
- if test -z "$PKG_CONFIG"; then
- # Extract the first word of "pkg-config", so it can be a program name with args.
-set dummy pkg-config; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $PKG_CONFIG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
- test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
- ;;
-esac
-fi
-PKG_CONFIG=$ac_cv_path_PKG_CONFIG
-
-if test -n "$PKG_CONFIG"; then
- echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
-echo "${ECHO_T}$PKG_CONFIG" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- fi
-
- if test "$PKG_CONFIG" = "no" ; then
- echo "*** The pkg-config script could not be found. Make sure it is"
- echo "*** in your path, or set the PKG_CONFIG environment variable"
- echo "*** to the full path to pkg-config."
- echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
- else
- PKG_CONFIG_MIN_VERSION=0.9.0
- if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
- echo "$as_me:$LINENO: checking for glib-2.0 gmodule-2.0 gthread-2.0" >&5
-echo $ECHO_N "checking for glib-2.0 gmodule-2.0 gthread-2.0... $ECHO_C" >&6
-
- if $PKG_CONFIG --exists "glib-2.0 gmodule-2.0 gthread-2.0" ; then
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
- succeeded=yes
-
- echo "$as_me:$LINENO: checking GLIB_CFLAGS" >&5
-echo $ECHO_N "checking GLIB_CFLAGS... $ECHO_C" >&6
- GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 gmodule-2.0 gthread-2.0"`
- echo "$as_me:$LINENO: result: $GLIB_CFLAGS" >&5
-echo "${ECHO_T}$GLIB_CFLAGS" >&6
-
- echo "$as_me:$LINENO: checking GLIB_LIBS" >&5
-echo $ECHO_N "checking GLIB_LIBS... $ECHO_C" >&6
- GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0 gmodule-2.0 gthread-2.0"`
- echo "$as_me:$LINENO: result: $GLIB_LIBS" >&5
-echo "${ECHO_T}$GLIB_LIBS" >&6
- else
- GLIB_CFLAGS=""
- GLIB_LIBS=""
- ## If we have a custom action on failure, don't print errors, but
- ## do set a variable so people can do so.
- GLIB_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "glib-2.0 gmodule-2.0 gthread-2.0"`
-
- fi
-
-
-
- else
- echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
- echo "*** See http://www.freedesktop.org/software/pkgconfig"
- fi
- fi
-
- if test $succeeded = yes; then
- enable_glib=yes
- else
- enable_glib=no
- fi
-
-if test x$enable_glib = xno; then
- enable_phone=no
- { echo "$as_me:$LINENO: GLib 2.0 is required to build libjingle. You can get it from http://www.gtk.org/" >&5
-echo "$as_me: GLib 2.0 is required to build libjingle. You can get it from http://www.gtk.org/" >&6;}
-else
-
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_GLIB 1
-_ACEOF
-
-fi
-
-
- succeeded=no
-
- if test -z "$PKG_CONFIG"; then
- # Extract the first word of "pkg-config", so it can be a program name with args.
-set dummy pkg-config; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- case $PKG_CONFIG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
- test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
- ;;
-esac
-fi
-PKG_CONFIG=$ac_cv_path_PKG_CONFIG
-
-if test -n "$PKG_CONFIG"; then
- echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
-echo "${ECHO_T}$PKG_CONFIG" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- fi
-
- if test "$PKG_CONFIG" = "no" ; then
- echo "*** The pkg-config script could not be found. Make sure it is"
- echo "*** in your path, or set the PKG_CONFIG environment variable"
- echo "*** to the full path to pkg-config."
- echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
- else
- PKG_CONFIG_MIN_VERSION=0.9.0
- if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
- echo "$as_me:$LINENO: checking for ortp >= 0.7.0" >&5
-echo $ECHO_N "checking for ortp >= 0.7.0... $ECHO_C" >&6
-
- if $PKG_CONFIG --exists "ortp >= 0.7.0" ; then
- echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
- succeeded=yes
-
- echo "$as_me:$LINENO: checking ORTP_CFLAGS" >&5
-echo $ECHO_N "checking ORTP_CFLAGS... $ECHO_C" >&6
- ORTP_CFLAGS=`$PKG_CONFIG --cflags "ortp >= 0.7.0"`
- echo "$as_me:$LINENO: result: $ORTP_CFLAGS" >&5
-echo "${ECHO_T}$ORTP_CFLAGS" >&6
-
- echo "$as_me:$LINENO: checking ORTP_LIBS" >&5
-echo $ECHO_N "checking ORTP_LIBS... $ECHO_C" >&6
- ORTP_LIBS=`$PKG_CONFIG --libs "ortp >= 0.7.0"`
- echo "$as_me:$LINENO: result: $ORTP_LIBS" >&5
-echo "${ECHO_T}$ORTP_LIBS" >&6
- else
- ORTP_CFLAGS=""
- ORTP_LIBS=""
- ## If we have a custom action on failure, don't print errors, but
- ## do set a variable so people can do so.
- ORTP_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "ortp >= 0.7.0"`
-
- fi
-
-
-
- else
- echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
- echo "*** See http://www.freedesktop.org/software/pkgconfig"
- fi
- fi
-
- if test $succeeded = yes; then
- enable_ortp=yes
- else
- enable_ortp=no
- fi
-
-if test x$enable_ortp = xno ; then
- enable_phone=no
- { echo "$as_me:$LINENO: oRTP is required to build libjingle. You can get it from http://www.linphone.org/ortp/" >&5
-echo "$as_me: oRTP is required to build libjingle. You can get it from http://www.linphone.org/ortp/" >&6;}
-else
-
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ORTP 1
-_ACEOF
-
-fi
-
-MEDIA_LIBS="$PWD/talk/third_party/mediastreamer/libmediastreamer.la -lasound"
-
-
-# Check whether --with-speex or --without-speex was given.
-if test "${with_speex+set}" = set; then
- withval="$with_speex"
- speex_prefix=${withval}
-else
- speex_prefix="/usr"
-fi;
-
-
-for ac_header in speex.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------------ ##
-## Report this to google-talk-open@googlegroups.com ##
-## ------------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
- echo "$as_me:$LINENO: checking for speex_encode_int in -lspeex" >&5
-echo $ECHO_N "checking for speex_encode_int in -lspeex... $ECHO_C" >&6
-if test "${ac_cv_lib_speex_speex_encode_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lspeex $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char speex_encode_int ();
-int
-main ()
-{
-speex_encode_int ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_speex_speex_encode_int=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_speex_speex_encode_int=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_speex_speex_encode_int" >&5
-echo "${ECHO_T}$ac_cv_lib_speex_speex_encode_int" >&6
-if test $ac_cv_lib_speex_speex_encode_int = yes; then
- speex_found=yes
-else
- speex_found=no
-fi
-
-
-else
- speex_found=no
-fi
-
-done
-
-
-if test "$speex_found" = "no" ; then
-
-for ac_header in speex/speex.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------------ ##
-## Report this to google-talk-open@googlegroups.com ##
-## ------------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
- echo "$as_me:$LINENO: checking for speex_encode_int in -lspeex" >&5
-echo $ECHO_N "checking for speex_encode_int in -lspeex... $ECHO_C" >&6
-if test "${ac_cv_lib_speex_speex_encode_int+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lspeex $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char speex_encode_int ();
-int
-main ()
-{
-speex_encode_int ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_speex_speex_encode_int=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_speex_speex_encode_int=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_speex_speex_encode_int" >&5
-echo "${ECHO_T}$ac_cv_lib_speex_speex_encode_int" >&6
-if test $ac_cv_lib_speex_speex_encode_int = yes; then
- speex_found=yes
-else
- speex_found=no
-fi
-
-
-else
- speex_found=no
-fi
-
-done
-
-fi
-
-if test "$speex_found" = "no" ; then
-{ echo "$as_me:$LINENO: WARNING: Could not find a libspeex version that have the speex_encode_int() function. Please install libspeex=1.0.5 or libspeex>=1.1.6 from http://www.speex.org/" >&5
-echo "$as_me: WARNING: Could not find a libspeex version that have the speex_encode_int() function. Please install libspeex=1.0.5 or libspeex>=1.1.6 from http://www.speex.org/" >&2;}
-else
-SPEEX_CFLAGS=" -I${speex_prefix}/include -I${speex_prefix}/include/speex"
-SPEEX_LIBS="-L${speex_prefix}/lib -L${speex_prefix}/speex/lib -lspeex -lm"
-CPPFLAGS_save=$CPPFLAGS
-CPPFLAGS=$SPEEX_CFLAGS
-LDFLAGS_save=$LDFLAGS
-LDFLAGS=$SPEEX_LIBS
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_SPEEX 1
-_ACEOF
-
-fi
-
-
-
-CPPFLAGS+=$CPPFLAGS_save
-LDFLAGS+=$LDFLAGS_save
-
-
-# Check whether --with-ilbc or --without-ilbc was given.
-if test "${with_ilbc+set}" = set; then
- withval="$with_ilbc"
- ilbc_prefix=${withval}
-else
- ilbc_prefix="/usr"
-fi;
-
-if test "$ilbc_prefix" = "none" ; then
- { echo "$as_me:$LINENO: iLBC codec support disabled. " >&5
-echo "$as_me: iLBC codec support disabled. " >&6;}
-else
- ILBC_CFLAGS=" -I${ilbc_prefix}/include/ilbc"
- ILBC_LIBS="-L${ilbc_prefix}/lib -lilbc -lm"
- CPPFLAGS_save=$CPPFLAGS
- CPPFLAGS=$ILBC_CFLAGS
- LDFLAGS_save=$LDFLAGS
- LDFLAGS=$ILBC_LIBS
-
-for ac_header in iLBC_decode.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
- # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_header_compiler=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
- ac_header_preproc=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
- yes:no: )
- { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
- ac_header_preproc=yes
- ;;
- no:yes:* )
- { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
- { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
- (
- cat <<\_ASBOX
-## ------------------------------------------------ ##
-## Report this to google-talk-open@googlegroups.com ##
-## ------------------------------------------------ ##
-_ASBOX
- ) |
- sed "s/^/$as_me: WARNING: /" >&2
- ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
- cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
- echo "$as_me:$LINENO: checking for iLBC_decode in -lilbc" >&5
-echo $ECHO_N "checking for iLBC_decode in -lilbc... $ECHO_C" >&6
-if test "${ac_cv_lib_ilbc_iLBC_decode+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lilbc $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any gcc2 internal prototype to avoid an error. */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char iLBC_decode ();
-int
-main ()
-{
-iLBC_decode ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_ilbc_iLBC_decode=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_ilbc_iLBC_decode=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_ilbc_iLBC_decode" >&5
-echo "${ECHO_T}$ac_cv_lib_ilbc_iLBC_decode" >&6
-if test $ac_cv_lib_ilbc_iLBC_decode = yes; then
- ilbc_found=yes
-else
- ilbc_found=no
-fi
-
-
-else
- ilbc_found=no
-fi
-
-done
-
-
- CPPFLAGS=$CPPFLAGS_save
- LDFLAGS=$LDFLAGS_save
-
- if test "$ilbc_found" = "no" ; then
- { echo "$as_me:$LINENO: WARNING: Could not find ilbc headers or libs. Please install ilbc package from http://www.linphone.org if you want iLBC codec support in libjingle." >&5
-echo "$as_me: WARNING: Could not find ilbc headers or libs. Please install ilbc package from http://www.linphone.org if you want iLBC codec support in libjingle." >&2;}
- ILBC_CFLAGS=
- ILBC_LIBS=
- else
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_ILBC 1
-_ACEOF
-
-
-
- fi
-fi
-
-else
- enable_phone=no
-fi # Linux check
-
-
-
-if test x$enable_gips = xyes; then
- GIPS_TRUE=
- GIPS_FALSE='#'
-else
- GIPS_TRUE='#'
- GIPS_FALSE=
-fi
-
-
-
-if test x$enable_phone = xyes; then
- PHONE_TRUE=
- PHONE_FALSE='#'
-else
- PHONE_TRUE='#'
- PHONE_FALSE=
-fi
-
-
-
- ac_config_files="$ac_config_files Makefile talk/Makefile talk/base/Makefile talk/third_party/Makefile talk/third_party/gips/Makefile talk/third_party/mediastreamer/Makefile talk/examples/Makefile talk/examples/login/Makefile talk/examples/call/Makefile talk/examples/pcp/Makefile talk/p2p/Makefile talk/p2p/base/Makefile talk/p2p/client/Makefile talk/session/Makefile talk/session/fileshare/Makefile talk/session/tunnel/Makefile talk/session/phone/Makefile talk/xmllite/Makefile talk/xmpp/Makefile"
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-{
- (set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- "s/'/'\\\\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n \
- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
- ;;
- esac;
-} |
- sed '
- t clear
- : clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
- t end
- /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
- : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
- if test -w $cache_file; then
- test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
- cat confcache >$cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[ ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[ ]*$//;
-}'
-fi
-
-DEFS=-DHAVE_CONFIG_H
-
-ac_libobjs=
-ac_ltlibobjs=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
- # 1. Remove the extension, and $U if already installed.
- ac_i=`echo "$ac_i" |
- sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
- # 2. Add them.
- ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
- ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
- { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
-Usually this means the macro was only invoked conditionally." >&5
-echo "$as_me: error: conditional \"AMDEP\" was never defined.
-Usually this means the macro was only invoked conditionally." >&2;}
- { (exit 1); exit 1; }; }
-fi
-if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
- { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
-Usually this means the macro was only invoked conditionally." >&5
-echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
-Usually this means the macro was only invoked conditionally." >&2;}
- { (exit 1); exit 1; }; }
-fi
-if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
- { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
-Usually this means the macro was only invoked conditionally." >&5
-echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
-Usually this means the macro was only invoked conditionally." >&2;}
- { (exit 1); exit 1; }; }
-fi
-if test -z "${GIPS_TRUE}" && test -z "${GIPS_FALSE}"; then
- { { echo "$as_me:$LINENO: error: conditional \"GIPS\" was never defined.
-Usually this means the macro was only invoked conditionally." >&5
-echo "$as_me: error: conditional \"GIPS\" was never defined.
-Usually this means the macro was only invoked conditionally." >&2;}
- { (exit 1); exit 1; }; }
-fi
-if test -z "${PHONE_TRUE}" && test -z "${PHONE_FALSE}"; then
- { { echo "$as_me:$LINENO: error: conditional \"PHONE\" was never defined.
-Usually this means the macro was only invoked conditionally." >&5
-echo "$as_me: error: conditional \"PHONE\" was never defined.
-Usually this means the macro was only invoked conditionally." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
- set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- $as_unset $as_var
- fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)$' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
- /^X\/\(\/\/\)$/{ s//\1/; q; }
- /^X\/\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" || {
- # Find who we are. Look in the path if we contain no path at all
- # relative or not.
- case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
- ;;
- esac
- # We did not find ourselves, most probably we were run as `sh COMMAND'
- # in which case we are not to be found in the path.
- if test "x$as_myself" = x; then
- as_myself=$0
- fi
- if test ! -f "$as_myself"; then
- { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
- { (exit 1); exit 1; }; }
- fi
- case $CONFIG_SHELL in
- '')
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for as_base in sh bash ksh sh5; do
- case $as_dir in
- /*)
- if ("$as_dir/$as_base" -c '
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
- $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
- $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
- CONFIG_SHELL=$as_dir/$as_base
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" ${1+"$@"}
- fi;;
- esac
- done
-done
-;;
- esac
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line before each line; the second 'sed' does the real
- # work. The second script uses 'N' to pair each line-number line
- # with the numbered line, and appends trailing '-' during
- # substitution so that $LINENO is not a special case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
- sed '=' <$as_myself |
- sed '
- N
- s,$,-,
- : loop
- s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
- t loop
- s,-$,,
- s,^['$as_cr_digits']*\n,,
- ' >$as_me.lineno &&
- chmod +x $as_me.lineno ||
- { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensible to this).
- . ./$as_me.lineno
- # Exit status is that of the last command.
- exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
- *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T=' ' ;;
- *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
- *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- # We could just check for DJGPP; but this test a) works b) is more generic
- # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
- if test -f conf$$.exe; then
- # Don't use ln at all; we don't have any links
- as_ln_s='cp -p'
- else
- as_ln_s='ln -s'
- fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-exec 6>&1
-
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling. Logging --version etc. is OK.
-exec 5>>config.log
-{
- echo
- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
-This file was extended by libjingle $as_me 0.4.0, which was
-generated by GNU Autoconf 2.59. Invocation command line was
-
- CONFIG_FILES = $CONFIG_FILES
- CONFIG_HEADERS = $CONFIG_HEADERS
- CONFIG_LINKS = $CONFIG_LINKS
- CONFIG_COMMANDS = $CONFIG_COMMANDS
- $ $0 $@
-
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
-_ACEOF
-
-# Files that config.status was made for.
-if test -n "$ac_config_files"; then
- echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_headers"; then
- echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_links"; then
- echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_commands"; then
- echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
- -h, --help print this help, then exit
- -V, --version print version number, then exit
- -q, --quiet do not print progress messages
- -d, --debug don't remove temporary files
- --recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
- instantiate the configuration file FILE
- --header=FILE[:TEMPLATE]
- instantiate the configuration header FILE
-
-Configuration files:
-$config_files
-
-Configuration headers:
-$config_headers
-
-Configuration commands:
-$config_commands
-
-Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-libjingle config.status 0.4.0
-configured by $0, generated by GNU Autoconf 2.59,
- with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
-INSTALL="$INSTALL"
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value. By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
- case $1 in
- --*=*)
- ac_option=`expr "x$1" : 'x\([^=]*\)='`
- ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
- ac_shift=:
- ;;
- -*)
- ac_option=$1
- ac_optarg=$2
- ac_shift=shift
- ;;
- *) # This is not an option, so the user has probably given explicit
- # arguments.
- ac_option=$1
- ac_need_defaults=false;;
- esac
-
- case $ac_option in
- # Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- ac_cs_recheck=: ;;
- --version | --vers* | -V )
- echo "$ac_cs_version"; exit 0 ;;
- --he | --h)
- # Conflict between --help and --header
- { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
- { (exit 1); exit 1; }; };;
- --help | --hel | -h )
- echo "$ac_cs_usage"; exit 0 ;;
- --debug | --d* | -d )
- debug=: ;;
- --file | --fil | --fi | --f )
- $ac_shift
- CONFIG_FILES="$CONFIG_FILES $ac_optarg"
- ac_need_defaults=false;;
- --header | --heade | --head | --hea )
- $ac_shift
- CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
- ac_need_defaults=false;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil | --si | --s)
- ac_cs_silent=: ;;
-
- # This is an error.
- -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
- { (exit 1); exit 1; }; } ;;
-
- *) ac_config_targets="$ac_config_targets $1" ;;
-
- esac
- shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
- exec 6>/dev/null
- ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-if \$ac_cs_recheck; then
- echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
- exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-#
-# INIT-COMMANDS section.
-#
-
-AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
-
-_ACEOF
-
-
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_config_target in $ac_config_targets
-do
- case "$ac_config_target" in
- # Handling of arguments.
- "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "talk/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/Makefile" ;;
- "talk/base/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/base/Makefile" ;;
- "talk/third_party/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/third_party/Makefile" ;;
- "talk/third_party/gips/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/third_party/gips/Makefile" ;;
- "talk/third_party/mediastreamer/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/third_party/mediastreamer/Makefile" ;;
- "talk/examples/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/examples/Makefile" ;;
- "talk/examples/login/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/examples/login/Makefile" ;;
- "talk/examples/call/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/examples/call/Makefile" ;;
- "talk/examples/pcp/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/examples/pcp/Makefile" ;;
- "talk/p2p/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/p2p/Makefile" ;;
- "talk/p2p/base/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/p2p/base/Makefile" ;;
- "talk/p2p/client/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/p2p/client/Makefile" ;;
- "talk/session/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/session/Makefile" ;;
- "talk/session/fileshare/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/session/fileshare/Makefile" ;;
- "talk/session/tunnel/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/session/tunnel/Makefile" ;;
- "talk/session/phone/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/session/phone/Makefile" ;;
- "talk/xmllite/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/xmllite/Makefile" ;;
- "talk/xmpp/Makefile" ) CONFIG_FILES="$CONFIG_FILES talk/xmpp/Makefile" ;;
- "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
- "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
- *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
- { (exit 1); exit 1; }; };;
- esac
-done
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used. Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
- test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
-fi
-
-# Have a temporary directory for convenience. Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
-$debug ||
-{
- trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
- trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-
-# Create a (secure) tmp directory for tmp files.
-
-{
- tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
- test -n "$tmp" && test -d "$tmp"
-} ||
-{
- tmp=./confstat$$-$RANDOM
- (umask 077 && mkdir $tmp)
-} ||
-{
- echo "$me: cannot create a temporary directory in ." >&2
- { (exit 1); exit 1; }
-}
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-
-#
-# CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
- # Protect against being on the right side of a sed subst in config.status.
- sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
- s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@build@,$build,;t t
-s,@build_cpu@,$build_cpu,;t t
-s,@build_vendor@,$build_vendor,;t t
-s,@build_os@,$build_os,;t t
-s,@host@,$host,;t t
-s,@host_cpu@,$host_cpu,;t t
-s,@host_vendor@,$host_vendor,;t t
-s,@host_os@,$host_os,;t t
-s,@target@,$target,;t t
-s,@target_cpu@,$target_cpu,;t t
-s,@target_vendor@,$target_vendor,;t t
-s,@target_os@,$target_os,;t t
-s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
-s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
-s,@INSTALL_DATA@,$INSTALL_DATA,;t t
-s,@CYGPATH_W@,$CYGPATH_W,;t t
-s,@PACKAGE@,$PACKAGE,;t t
-s,@VERSION@,$VERSION,;t t
-s,@ACLOCAL@,$ACLOCAL,;t t
-s,@AUTOCONF@,$AUTOCONF,;t t
-s,@AUTOMAKE@,$AUTOMAKE,;t t
-s,@AUTOHEADER@,$AUTOHEADER,;t t
-s,@MAKEINFO@,$MAKEINFO,;t t
-s,@install_sh@,$install_sh,;t t
-s,@STRIP@,$STRIP,;t t
-s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
-s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t
-s,@mkdir_p@,$mkdir_p,;t t
-s,@AWK@,$AWK,;t t
-s,@SET_MAKE@,$SET_MAKE,;t t
-s,@am__leading_dot@,$am__leading_dot,;t t
-s,@AMTAR@,$AMTAR,;t t
-s,@am__tar@,$am__tar,;t t
-s,@am__untar@,$am__untar,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@DEPDIR@,$DEPDIR,;t t
-s,@am__include@,$am__include,;t t
-s,@am__quote@,$am__quote,;t t
-s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t
-s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t
-s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t
-s,@CCDEPMODE@,$CCDEPMODE,;t t
-s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t
-s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t
-s,@CXX@,$CXX,;t t
-s,@CXXFLAGS@,$CXXFLAGS,;t t
-s,@ac_ct_CXX@,$ac_ct_CXX,;t t
-s,@CXXDEPMODE@,$CXXDEPMODE,;t t
-s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t
-s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t
-s,@EGREP@,$EGREP,;t t
-s,@LN_S@,$LN_S,;t t
-s,@ECHO@,$ECHO,;t t
-s,@AR@,$AR,;t t
-s,@ac_ct_AR@,$ac_ct_AR,;t t
-s,@RANLIB@,$RANLIB,;t t
-s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
-s,@CPP@,$CPP,;t t
-s,@CXXCPP@,$CXXCPP,;t t
-s,@F77@,$F77,;t t
-s,@FFLAGS@,$FFLAGS,;t t
-s,@ac_ct_F77@,$ac_ct_F77,;t t
-s,@LIBTOOL@,$LIBTOOL,;t t
-s,@EXPAT_LIBS@,$EXPAT_LIBS,;t t
-s,@ALSA_LIBS@,$ALSA_LIBS,;t t
-s,@PKG_CONFIG@,$PKG_CONFIG,;t t
-s,@GLIB_CFLAGS@,$GLIB_CFLAGS,;t t
-s,@GLIB_LIBS@,$GLIB_LIBS,;t t
-s,@ORTP_CFLAGS@,$ORTP_CFLAGS,;t t
-s,@ORTP_LIBS@,$ORTP_LIBS,;t t
-s,@SPEEX_CFLAGS@,$SPEEX_CFLAGS,;t t
-s,@SPEEX_LIBS@,$SPEEX_LIBS,;t t
-s,@ILBC_CFLAGS@,$ILBC_CFLAGS,;t t
-s,@ILBC_LIBS@,$ILBC_LIBS,;t t
-s,@GIPS_TRUE@,$GIPS_TRUE,;t t
-s,@GIPS_FALSE@,$GIPS_FALSE,;t t
-s,@PHONE_TRUE@,$PHONE_TRUE,;t t
-s,@PHONE_FALSE@,$PHONE_FALSE,;t t
-s,@MEDIA_LIBS@,$MEDIA_LIBS,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
-
-_ACEOF
-
- cat >>$CONFIG_STATUS <<\_ACEOF
- # Split the substitutions into bite-sized pieces for seds with
- # small command number limits, like on Digital OSF/1 and HP-UX.
- ac_max_sed_lines=48
- ac_sed_frag=1 # Number of current file.
- ac_beg=1 # First line for current file.
- ac_end=$ac_max_sed_lines # Line after last line for current file.
- ac_more_lines=:
- ac_sed_cmds=
- while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
- else
- sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
- fi
- if test ! -s $tmp/subs.frag; then
- ac_more_lines=false
- else
- # The purpose of the label and of the branching condition is to
- # speed up the sed processing (if there are no `@' at all, there
- # is no need to browse any of the substitutions).
- # These are the two extra sed commands mentioned above.
- (echo ':t
- /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
- fi
- ac_sed_frag=`expr $ac_sed_frag + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_lines`
- fi
- done
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
- fi
-fi # test -n "$CONFIG_FILES"
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case $ac_file in
- - | *:- | *:-:* ) # input from stdin
- cat >$tmp/stdin
- ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- * ) ac_file_in=$ac_file.in ;;
- esac
-
- # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
- ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- { if $as_mkdir_p; then
- mkdir -p "$ac_dir"
- else
- as_dir="$ac_dir"
- as_dirs=
- while test ! -d "$as_dir"; do
- as_dirs="$as_dir $as_dirs"
- as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- done
- test ! -n "$as_dirs" || mkdir $as_dirs
- fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }; }
-
- ac_builddir=.
-
-if test "$ac_dir" != .; then
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A "../" for each directory in $ac_dir_suffix.
- ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
- ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
- .) # No --srcdir option. We are building in place.
- ac_srcdir=.
- if test -z "$ac_top_builddir"; then
- ac_top_srcdir=.
- else
- ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
- fi ;;
- [\\/]* | ?:[\\/]* ) # Absolute path.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir ;;
- *) # Relative path.
- ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
- case "$ac_dir" in
- .) ac_abs_builddir=`pwd`;;
- [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
- *) ac_abs_builddir=`pwd`/"$ac_dir";;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
- case ${ac_top_builddir}. in
- .) ac_abs_top_builddir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
- *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
- case $ac_srcdir in
- .) ac_abs_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
- *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
- case $ac_top_srcdir in
- .) ac_abs_top_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
- *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
- esac;;
-esac
-
-
- case $INSTALL in
- [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
- esac
-
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- if test x"$ac_file" = x-; then
- configure_input=
- else
- configure_input="$ac_file. "
- fi
- configure_input=$configure_input"Generated from `echo $ac_file_in |
- sed 's,.*/,,'` by configure."
-
- # First look for the input files in the build tree, otherwise in the
- # src tree.
- ac_file_inputs=`IFS=:
- for f in $ac_file_in; do
- case $f in
- -) echo $tmp/stdin ;;
- [\\/$]*)
- # Absolute (can't be DOS-style, as IFS=:)
- test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- echo "$f";;
- *) # Relative
- if test -f "$f"; then
- # Build tree
- echo "$f"
- elif test -f "$srcdir/$f"; then
- # Source tree
- echo "$srcdir/$f"
- else
- # /dev/null tree
- { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- fi;;
- esac
- done` || { (exit 1); exit 1; }
-
- if test x"$ac_file" != x-; then
- { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
- rm -f "$ac_file"
- fi
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
- sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-s,@INSTALL@,$ac_INSTALL,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
- rm -f $tmp/stdin
- if test x"$ac_file" != x-; then
- mv $tmp/out $ac_file
- else
- cat $tmp/out
- rm -f $tmp/out
- fi
-
-done
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-#
-# CONFIG_HEADER section.
-#
-
-# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
-# NAME is the cpp macro being defined and VALUE is the value it is being given.
-#
-# ac_d sets the value in "#define NAME VALUE" lines.
-ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
-ac_dB='[ ].*$,\1#\2'
-ac_dC=' '
-ac_dD=',;t'
-# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
-ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_uB='$,\1#\2define\3'
-ac_uC=' '
-ac_uD=',;t'
-
-for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case $ac_file in
- - | *:- | *:-:* ) # input from stdin
- cat >$tmp/stdin
- ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- * ) ac_file_in=$ac_file.in ;;
- esac
-
- test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-
- # First look for the input files in the build tree, otherwise in the
- # src tree.
- ac_file_inputs=`IFS=:
- for f in $ac_file_in; do
- case $f in
- -) echo $tmp/stdin ;;
- [\\/$]*)
- # Absolute (can't be DOS-style, as IFS=:)
- test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- # Do quote $f, to prevent DOS paths from being IFS'd.
- echo "$f";;
- *) # Relative
- if test -f "$f"; then
- # Build tree
- echo "$f"
- elif test -f "$srcdir/$f"; then
- # Source tree
- echo "$srcdir/$f"
- else
- # /dev/null tree
- { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- fi;;
- esac
- done` || { (exit 1); exit 1; }
- # Remove the trailing spaces.
- sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
-
-_ACEOF
-
-# Transform confdefs.h into two sed scripts, `conftest.defines' and
-# `conftest.undefs', that substitutes the proper values into
-# config.h.in to produce config.h. The first handles `#define'
-# templates, and the second `#undef' templates.
-# And first: Protect against being on the right side of a sed subst in
-# config.status. Protect against being in an unquoted here document
-# in config.status.
-rm -f conftest.defines conftest.undefs
-# Using a here document instead of a string reduces the quoting nightmare.
-# Putting comments in sed scripts is not portable.
-#
-# `end' is used to avoid that the second main sed command (meant for
-# 0-ary CPP macros) applies to n-ary macro definitions.
-# See the Autoconf documentation for `clear'.
-cat >confdef2sed.sed <<\_ACEOF
-s/[\\&,]/\\&/g
-s,[\\$`],\\&,g
-t clear
-: clear
-s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
-t end
-s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
-: end
-_ACEOF
-# If some macros were called several times there might be several times
-# the same #defines, which is useless. Nevertheless, we may not want to
-# sort them, since we want the *last* AC-DEFINE to be honored.
-uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
-sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
-rm -f confdef2sed.sed
-
-# This sed command replaces #undef with comments. This is necessary, for
-# example, in the case of _POSIX_SOURCE, which is predefined and required
-# on some systems where configure will not decide to define it.
-cat >>conftest.undefs <<\_ACEOF
-s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
-_ACEOF
-
-# Break up conftest.defines because some shells have a limit on the size
-# of here documents, and old seds have small limits too (100 cmds).
-echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
-echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
-echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
-echo ' :' >>$CONFIG_STATUS
-rm -f conftest.tail
-while grep . conftest.defines >/dev/null
-do
- # Write a limited-size here document to $tmp/defines.sed.
- echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
- # Speed up: don't consider the non `#define' lines.
- echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
- # Work around the forget-to-reset-the-flag bug.
- echo 't clr' >>$CONFIG_STATUS
- echo ': clr' >>$CONFIG_STATUS
- sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
- echo 'CEOF
- sed -f $tmp/defines.sed $tmp/in >$tmp/out
- rm -f $tmp/in
- mv $tmp/out $tmp/in
-' >>$CONFIG_STATUS
- sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
- rm -f conftest.defines
- mv conftest.tail conftest.defines
-done
-rm -f conftest.defines
-echo ' fi # grep' >>$CONFIG_STATUS
-echo >>$CONFIG_STATUS
-
-# Break up conftest.undefs because some shells have a limit on the size
-# of here documents, and old seds have small limits too (100 cmds).
-echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
-rm -f conftest.tail
-while grep . conftest.undefs >/dev/null
-do
- # Write a limited-size here document to $tmp/undefs.sed.
- echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
- # Speed up: don't consider the non `#undef'
- echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
- # Work around the forget-to-reset-the-flag bug.
- echo 't clr' >>$CONFIG_STATUS
- echo ': clr' >>$CONFIG_STATUS
- sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
- echo 'CEOF
- sed -f $tmp/undefs.sed $tmp/in >$tmp/out
- rm -f $tmp/in
- mv $tmp/out $tmp/in
-' >>$CONFIG_STATUS
- sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
- rm -f conftest.undefs
- mv conftest.tail conftest.undefs
-done
-rm -f conftest.undefs
-
-cat >>$CONFIG_STATUS <<\_ACEOF
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- if test x"$ac_file" = x-; then
- echo "/* Generated by configure. */" >$tmp/config.h
- else
- echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
- fi
- cat $tmp/in >>$tmp/config.h
- rm -f $tmp/in
- if test x"$ac_file" != x-; then
- if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
- { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
-echo "$as_me: $ac_file is unchanged" >&6;}
- else
- ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- { if $as_mkdir_p; then
- mkdir -p "$ac_dir"
- else
- as_dir="$ac_dir"
- as_dirs=
- while test ! -d "$as_dir"; do
- as_dirs="$as_dir $as_dirs"
- as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- done
- test ! -n "$as_dirs" || mkdir $as_dirs
- fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }; }
-
- rm -f $ac_file
- mv $tmp/config.h $ac_file
- fi
- else
- cat $tmp/config.h
- rm -f $tmp/config.h
- fi
-# Compute $ac_file's index in $config_headers.
-_am_stamp_count=1
-for _am_header in $config_headers :; do
- case $_am_header in
- $ac_file | $ac_file:* )
- break ;;
- * )
- _am_stamp_count=`expr $_am_stamp_count + 1` ;;
- esac
-done
-echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null ||
-$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X$ac_file : 'X\(//\)[^/]' \| \
- X$ac_file : 'X\(//\)$' \| \
- X$ac_file : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X$ac_file |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`/stamp-h$_am_stamp_count
-done
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-#
-# CONFIG_COMMANDS section.
-#
-for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
- ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
- ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
-$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_dest" : 'X\(//\)[^/]' \| \
- X"$ac_dest" : 'X\(//\)$' \| \
- X"$ac_dest" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$ac_dest" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- { if $as_mkdir_p; then
- mkdir -p "$ac_dir"
- else
- as_dir="$ac_dir"
- as_dirs=
- while test ! -d "$as_dir"; do
- as_dirs="$as_dir $as_dirs"
- as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- done
- test ! -n "$as_dirs" || mkdir $as_dirs
- fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }; }
-
- ac_builddir=.
-
-if test "$ac_dir" != .; then
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A "../" for each directory in $ac_dir_suffix.
- ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
- ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
- .) # No --srcdir option. We are building in place.
- ac_srcdir=.
- if test -z "$ac_top_builddir"; then
- ac_top_srcdir=.
- else
- ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
- fi ;;
- [\\/]* | ?:[\\/]* ) # Absolute path.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir ;;
- *) # Relative path.
- ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
- case "$ac_dir" in
- .) ac_abs_builddir=`pwd`;;
- [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
- *) ac_abs_builddir=`pwd`/"$ac_dir";;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
- case ${ac_top_builddir}. in
- .) ac_abs_top_builddir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
- *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
- case $ac_srcdir in
- .) ac_abs_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
- *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
- case $ac_top_srcdir in
- .) ac_abs_top_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
- *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
- esac;;
-esac
-
-
- { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
-echo "$as_me: executing $ac_dest commands" >&6;}
- case $ac_dest in
- depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
- # Strip MF so we end up with the name of the file.
- mf=`echo "$mf" | sed -e 's/:.*$//'`
- # Check whether this is an Automake generated Makefile or not.
- # We used to match only the files named `Makefile.in', but
- # some people rename them; so instead we look at the file content.
- # Grep'ing the first line is not enough: some people post-process
- # each Makefile.in and add a new line on top of each file to say so.
- # So let's grep whole file.
- if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
- dirpart=`(dirname "$mf") 2>/dev/null ||
-$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$mf" : 'X\(//\)[^/]' \| \
- X"$mf" : 'X\(//\)$' \| \
- X"$mf" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$mf" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- else
- continue
- fi
- # Extract the definition of DEPDIR, am__include, and am__quote
- # from the Makefile without running `make'.
- DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
- test -z "$DEPDIR" && continue
- am__include=`sed -n 's/^am__include = //p' < "$mf"`
- test -z "am__include" && continue
- am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
- # When using ansi2knr, U may be empty or an underscore; expand it
- U=`sed -n 's/^U = //p' < "$mf"`
- # Find all dependency output files, they are included files with
- # $(DEPDIR) in their names. We invoke sed twice because it is the
- # simplest approach to changing $(DEPDIR) to its actual value in the
- # expansion.
- for file in `sed -n "
- s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
- # Make sure the directory exists.
- test -f "$dirpart/$file" && continue
- fdir=`(dirname "$file") 2>/dev/null ||
-$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$file" : 'X\(//\)[^/]' \| \
- X"$file" : 'X\(//\)$' \| \
- X"$file" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- { if $as_mkdir_p; then
- mkdir -p $dirpart/$fdir
- else
- as_dir=$dirpart/$fdir
- as_dirs=
- while test ! -d "$as_dir"; do
- as_dirs="$as_dir $as_dirs"
- as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- done
- test ! -n "$as_dirs" || mkdir $as_dirs
- fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5
-echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;}
- { (exit 1); exit 1; }; }; }
-
- # echo "creating $dirpart/$file"
- echo '# dummy' > "$dirpart/$file"
- done
-done
- ;;
- esac
-done
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded. So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status. When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
- ac_cs_success=:
- ac_config_status_args=
- test "$silent" = yes &&
- ac_config_status_args="$ac_config_status_args --quiet"
- exec 5>/dev/null
- $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
- exec 5>>config.log
- # Use ||, not &&, to avoid exiting from the if with $? = 1, which
- # would make configure fail if this is the last instruction.
- $ac_cs_success || { (exit 1); exit 1; }
-fi
-
-
-echo
-echo $PACKAGE $VERSION
-echo
-
-if test x$enable_phone = xyes ; then
- echo
- echo Supported Examples: call pcp
- echo Supported Codecs:
- if test x$enable_gips = xyes ; then
- echo GIPS: yes
- else
- echo Speex: $speex_found
- echo iLBC: $ilbc_found
- echo MULAW: yes
- fi
-else
- echo Supported Examples: pcp
-fi
-echo
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index b3daac4..0000000
--- a/configure.ac
+++ /dev/null
@@ -1,182 +0,0 @@
-AC_INIT([libjingle], [0.4.0], [google-talk-open@googlegroups.com])
-AC_CANONICAL_SYSTEM
-AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE([dist-zip])
-AC_PROG_CC
-AC_PROG_CXX
-AM_PROG_LIBTOOL
-LIBTOOL="$LIBTOOL --silent"
-AC_PROG_INSTALL
-AC_DEFINE(PRODUCTION_BUILD, 1, [Build as a production build])
-AC_DEFINE(PRODUCTION, 1, [Build as a production build])
-AC_DEFINE(POSIX, 1, [If we're using configure, we're on POSIX])
-AC_DEFINE(FEATURE_ENABLE_SSL, 1, [Enable SSL])
-AC_DEFINE(FEATURE_ENABLE_CHAT_ARCHIVING, 1, [Chat archving])
-AC_DEFINE(FEATURE_ENABLE_VOICEMAIL, 1, [voice mail])
-AC_DEFINE(LOGGING, 1, [Logging])
-
-HAVE_EXPAT=no
-AC_CHECK_LIB(expat, XML_ParserCreate, HAVE_EXPAT="yes")
-if test "x$HAVE_EXPAT" = xyes ; then
- EXPAT_LIBS="-lexpat"
- AC_SUBST(EXPAT_LIBS)
-else
- AC_ERROR([Expat is required to build libjingle. You can get it from http://expat.sourceforge.net/])
-fi
-
-enable_phone=yes
-if test `uname -s` = Linux ; then
- AC_DEFINE(LINUX, 1, [Building on Linux])
- if test x`ls talk/third_party/gips/VoiceEngine_Linux_gcc.a` != x ; then
- enable_gips=yes
- MEDIA_LIBS=$PWD/talk/third_party/gips/VoiceEngine_Linux_gcc.a
- fi
-elif test `uname -s` = Darwin ; then
- AC_DEFINE(OSX, 1, [Building on OSX])
- if test x`ls talk/third_party/gips/VoiceEngine_mac_gcc.a` != x ; then
- enable_gips=yes
- MEDIA_LIBS="$PWD/talk/third_party/gips/VoiceEngine_mac_gcc.a -framework CoreAudio -framework AudioToolbox"
- fi
-fi
-
-if test x$enable_gips = xyes ; then
- AC_DEFINE(HAVE_GIPS, 1, [Have GIPS Voice Engine])
-elif test `uname -s` = Linux ; then
-
-AC_CHECK_HEADERS(alsa/asoundlib.h,
- [AC_CHECK_LIB(asound, snd_pcm_open,
- [ALSA_LIBS="-lasound" ; AC_DEFINE(__ALSA_ENABLED__,1,[Defined when alsa support is enabled]) ])
- ]
-)
-AC_SUBST(ALSA_LIBS)
-
-PKG_CHECK_MODULES(GLIB, glib-2.0 gmodule-2.0 gthread-2.0, enable_glib=yes, enable_glib=no)
-if test x$enable_glib = xno; then
- enable_phone=no
- AC_MSG_NOTICE([GLib 2.0 is required to build libjingle. You can get it from http://www.gtk.org/])
-else
- AC_SUBST(GLIB_CFLAGS)
- AC_SUBST(GLIB_LIBS)
- AC_DEFINE(HAVE_GLIB, 1, [Glib is required for oRTP code])
-fi
-
-PKG_CHECK_MODULES(ORTP, ortp >= 0.7.0, enable_ortp=yes, enable_ortp=no)
-if test x$enable_ortp = xno ; then
- enable_phone=no
- AC_MSG_NOTICE([oRTP is required to build libjingle. You can get it from http://www.linphone.org/ortp/])
-else
- AC_SUBST(ORTP_CFLAGS)
- AC_SUBST(ORTP_LIBS)
- AC_DEFINE(HAVE_ORTP, 1, [oRTP provides RTP supprt])
-fi
-
-MEDIA_LIBS="$PWD/talk/third_party/mediastreamer/libmediastreamer.la -lasound"
-
-dnl only accept speex>=1.1.6 or 1.0.5 (the versions that have speex_encode_int )
-AC_ARG_WITH( speex,
- [ --with-speex Set prefix where speex lib can be found (ex:/usr, /usr/local) [default=/usr] ],
- [ speex_prefix=${withval}],[ speex_prefix="/usr" ])
-
-AC_CHECK_HEADERS(speex.h,[AC_CHECK_LIB(speex,speex_encode_int,speex_found=yes,speex_found=no)
-],speex_found=no)
-
-if test "$speex_found" = "no" ; then
-AC_CHECK_HEADERS(speex/speex.h,[AC_CHECK_LIB(speex,speex_encode_int,speex_found=yes,speex_found=no)
-],speex_found=no)
-fi
-
-if test "$speex_found" = "no" ; then
-AC_MSG_WARN([Could not find a libspeex version that have the speex_encode_int() function. Please install libspeex=1.0.5 or libspeex>=1.1.6 from http://www.speex.org/])
-else
-SPEEX_CFLAGS=" -I${speex_prefix}/include -I${speex_prefix}/include/speex"
-SPEEX_LIBS="-L${speex_prefix}/lib -L${speex_prefix}/speex/lib -lspeex -lm"
-CPPFLAGS_save=$CPPFLAGS
-CPPFLAGS=$SPEEX_CFLAGS
-LDFLAGS_save=$LDFLAGS
-LDFLAGS=$SPEEX_LIBS
-AC_DEFINE(HAVE_SPEEX,1,[has speex])
-fi
-
-AC_SUBST(SPEEX_CFLAGS)
-AC_SUBST(SPEEX_LIBS)
-CPPFLAGS+=$CPPFLAGS_save
-LDFLAGS+=$LDFLAGS_save
-
-AC_ARG_WITH( ilbc,
- [ --with-ilbc Set prefix where ilbc headers and libs can be found (ex:/usr, /usr/local, none to disable ilbc support) [default=/usr] ],
- [ ilbc_prefix=${withval}],[ ilbc_prefix="/usr" ])
-
-if test "$ilbc_prefix" = "none" ; then
- AC_MSG_NOTICE([iLBC codec support disabled. ])
-else
- ILBC_CFLAGS=" -I${ilbc_prefix}/include/ilbc"
- ILBC_LIBS="-L${ilbc_prefix}/lib -lilbc -lm"
- CPPFLAGS_save=$CPPFLAGS
- CPPFLAGS=$ILBC_CFLAGS
- LDFLAGS_save=$LDFLAGS
- LDFLAGS=$ILBC_LIBS
- AC_CHECK_HEADERS(iLBC_decode.h,[AC_CHECK_LIB(ilbc,iLBC_decode,ilbc_found=yes,ilbc_found=no)
- ],ilbc_found=no)
-
- CPPFLAGS=$CPPFLAGS_save
- LDFLAGS=$LDFLAGS_save
-
- if test "$ilbc_found" = "no" ; then
- AC_MSG_WARN([Could not find ilbc headers or libs. Please install ilbc package from http://www.linphone.org if you want iLBC codec support in libjingle.])
- ILBC_CFLAGS=
- ILBC_LIBS=
- else
- AC_DEFINE(HAVE_ILBC,1,[Defined when we have ilbc codec lib])
- AC_SUBST(ILBC_CFLAGS)
- AC_SUBST(ILBC_LIBS)
- fi
-fi
-
-else
- enable_phone=no
-fi # Linux check
-
-AM_CONDITIONAL(GIPS, test x$enable_gips = xyes)
-AM_CONDITIONAL(PHONE, test x$enable_phone = xyes)
-AC_SUBST(MEDIA_LIBS)
-
-AC_OUTPUT([Makefile
- talk/Makefile
- talk/base/Makefile
- talk/third_party/Makefile
- talk/third_party/gips/Makefile
- talk/third_party/mediastreamer/Makefile
- talk/examples/Makefile
- talk/examples/login/Makefile
- talk/examples/call/Makefile
- talk/examples/pcp/Makefile
- talk/p2p/Makefile
- talk/p2p/base/Makefile
- talk/p2p/client/Makefile
- talk/session/Makefile
- talk/session/fileshare/Makefile
- talk/session/tunnel/Makefile
- talk/session/phone/Makefile
- talk/xmllite/Makefile
- talk/xmpp/Makefile
- ])
-
-echo
-echo $PACKAGE $VERSION
-echo
-
-if test x$enable_phone = xyes ; then
- echo
- echo Supported Examples: call pcp
- echo Supported Codecs:
- if test x$enable_gips = xyes ; then
- echo GIPS: yes
- else
- echo Speex: $speex_found
- echo iLBC: $ilbc_found
- echo MULAW: yes
- fi
-else
- echo Supported Examples: pcp
-fi
-echo
diff --git a/depcomp b/depcomp
deleted file mode 100755
index 04701da..0000000
--- a/depcomp
+++ /dev/null
@@ -1,530 +0,0 @@
-#! /bin/sh
-# depcomp - compile a program generating dependencies as side-effects
-
-scriptversion=2005-07-09.11
-
-# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
-
-case $1 in
- '')
- echo "$0: No command. Try \`$0 --help' for more information." 1>&2
- exit 1;
- ;;
- -h | --h*)
- cat <<\EOF
-Usage: depcomp [--help] [--version] PROGRAM [ARGS]
-
-Run PROGRAMS ARGS to compile a file, generating dependencies
-as side-effects.
-
-Environment variables:
- depmode Dependency tracking mode.
- source Source file read by `PROGRAMS ARGS'.
- object Object file output by `PROGRAMS ARGS'.
- DEPDIR directory where to store dependencies.
- depfile Dependency file to output.
- tmpdepfile Temporary file to use when outputing dependencies.
- libtool Whether libtool is used (yes/no).
-
-Report bugs to <bug-automake@gnu.org>.
-EOF
- exit $?
- ;;
- -v | --v*)
- echo "depcomp $scriptversion"
- exit $?
- ;;
-esac
-
-if test -z "$depmode" || test -z "$source" || test -z "$object"; then
- echo "depcomp: Variables source, object and depmode must be set" 1>&2
- exit 1
-fi
-
-# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
-depfile=${depfile-`echo "$object" |
- sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
-tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
-
-rm -f "$tmpdepfile"
-
-# Some modes work just like other modes, but use different flags. We
-# parameterize here, but still list the modes in the big case below,
-# to make depend.m4 easier to write. Note that we *cannot* use a case
-# here, because this file can only contain one case statement.
-if test "$depmode" = hp; then
- # HP compiler uses -M and no extra arg.
- gccflag=-M
- depmode=gcc
-fi
-
-if test "$depmode" = dashXmstdout; then
- # This is just like dashmstdout with a different argument.
- dashmflag=-xM
- depmode=dashmstdout
-fi
-
-case "$depmode" in
-gcc3)
-## gcc 3 implements dependency tracking that does exactly what
-## we want. Yay! Note: for some reason libtool 1.4 doesn't like
-## it if -MD -MP comes after the -MF stuff. Hmm.
- "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
- mv "$tmpdepfile" "$depfile"
- ;;
-
-gcc)
-## There are various ways to get dependency output from gcc. Here's
-## why we pick this rather obscure method:
-## - Don't want to use -MD because we'd like the dependencies to end
-## up in a subdir. Having to rename by hand is ugly.
-## (We might end up doing this anyway to support other compilers.)
-## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
-## -MM, not -M (despite what the docs say).
-## - Using -M directly means running the compiler twice (even worse
-## than renaming).
- if test -z "$gccflag"; then
- gccflag=-MD,
- fi
- "$@" -Wp,"$gccflag$tmpdepfile"
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
- rm -f "$depfile"
- echo "$object : \\" > "$depfile"
- alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
-## The second -e expression handles DOS-style file names with drive letters.
- sed -e 's/^[^:]*: / /' \
- -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
-## The problem is that when a header file which appears in a .P file
-## is deleted, the dependency causes make to die (because there is
-## typically no way to rebuild the header). We avoid this by adding
-## dummy dependencies for each header file. Too bad gcc doesn't do
-## this for us directly.
- tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'. On the theory
-## that the space means something, we add a space to the output as
-## well.
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-hp)
- # This case exists only to let depend.m4 do its work. It works by
- # looking at the text of this script. This case will never be run,
- # since it is checked for above.
- exit 1
- ;;
-
-sgi)
- if test "$libtool" = yes; then
- "$@" "-Wp,-MDupdate,$tmpdepfile"
- else
- "$@" -MDupdate "$tmpdepfile"
- fi
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
- rm -f "$depfile"
-
- if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
- echo "$object : \\" > "$depfile"
-
- # Clip off the initial element (the dependent). Don't try to be
- # clever and replace this with sed code, as IRIX sed won't handle
- # lines with more than a fixed number of characters (4096 in
- # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
- # the IRIX cc adds comments like `#:fec' to the end of the
- # dependency line.
- tr ' ' '
-' < "$tmpdepfile" \
- | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
- tr '
-' ' ' >> $depfile
- echo >> $depfile
-
- # The second pass generates a dummy entry for each header file.
- tr ' ' '
-' < "$tmpdepfile" \
- | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
- >> $depfile
- else
- # The sourcefile does not contain any dependencies, so just
- # store a dummy comment line, to avoid errors with the Makefile
- # "include basename.Plo" scheme.
- echo "#dummy" > "$depfile"
- fi
- rm -f "$tmpdepfile"
- ;;
-
-aix)
- # The C for AIX Compiler uses -M and outputs the dependencies
- # in a .u file. In older versions, this file always lives in the
- # current directory. Also, the AIX compiler puts `$object:' at the
- # start of each line; $object doesn't have directory information.
- # Version 6 uses the directory in both cases.
- stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
- tmpdepfile="$stripped.u"
- if test "$libtool" = yes; then
- "$@" -Wc,-M
- else
- "$@" -M
- fi
- stat=$?
-
- if test -f "$tmpdepfile"; then :
- else
- stripped=`echo "$stripped" | sed 's,^.*/,,'`
- tmpdepfile="$stripped.u"
- fi
-
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
-
- if test -f "$tmpdepfile"; then
- outname="$stripped.o"
- # Each line is of the form `foo.o: dependent.h'.
- # Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
- sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
- sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
- else
- # The sourcefile does not contain any dependencies, so just
- # store a dummy comment line, to avoid errors with the Makefile
- # "include basename.Plo" scheme.
- echo "#dummy" > "$depfile"
- fi
- rm -f "$tmpdepfile"
- ;;
-
-icc)
- # Intel's C compiler understands `-MD -MF file'. However on
- # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
- # ICC 7.0 will fill foo.d with something like
- # foo.o: sub/foo.c
- # foo.o: sub/foo.h
- # which is wrong. We want:
- # sub/foo.o: sub/foo.c
- # sub/foo.o: sub/foo.h
- # sub/foo.c:
- # sub/foo.h:
- # ICC 7.1 will output
- # foo.o: sub/foo.c sub/foo.h
- # and will wrap long lines using \ :
- # foo.o: sub/foo.c ... \
- # sub/foo.h ... \
- # ...
-
- "$@" -MD -MF "$tmpdepfile"
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile"
- exit $stat
- fi
- rm -f "$depfile"
- # Each line is of the form `foo.o: dependent.h',
- # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
- # Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
- sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
- # Some versions of the HPUX 10.20 sed can't process this invocation
- # correctly. Breaking it into two sed invocations is a workaround.
- sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
- sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-tru64)
- # The Tru64 compiler uses -MD to generate dependencies as a side
- # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
- # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
- # dependencies in `foo.d' instead, so we check for that too.
- # Subdirectories are respected.
- dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
- test "x$dir" = "x$object" && dir=
- base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
-
- if test "$libtool" = yes; then
- # With Tru64 cc, shared objects can also be used to make a
- # static library. This mecanism is used in libtool 1.4 series to
- # handle both shared and static libraries in a single compilation.
- # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
- #
- # With libtool 1.5 this exception was removed, and libtool now
- # generates 2 separate objects for the 2 libraries. These two
- # compilations output dependencies in in $dir.libs/$base.o.d and
- # in $dir$base.o.d. We have to check for both files, because
- # one of the two compilations can be disabled. We should prefer
- # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
- # automatically cleaned when .libs/ is deleted, while ignoring
- # the former would cause a distcleancheck panic.
- tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
- tmpdepfile2=$dir$base.o.d # libtool 1.5
- tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
- tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
- "$@" -Wc,-MD
- else
- tmpdepfile1=$dir$base.o.d
- tmpdepfile2=$dir$base.d
- tmpdepfile3=$dir$base.d
- tmpdepfile4=$dir$base.d
- "$@" -MD
- fi
-
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
- exit $stat
- fi
-
- for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
- do
- test -f "$tmpdepfile" && break
- done
- if test -f "$tmpdepfile"; then
- sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a tab and a space in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
- else
- echo "#dummy" > "$depfile"
- fi
- rm -f "$tmpdepfile"
- ;;
-
-#nosideeffect)
- # This comment above is used by automake to tell side-effect
- # dependency tracking mechanisms from slower ones.
-
-dashmstdout)
- # Important note: in order to support this mode, a compiler *must*
- # always write the preprocessed file to stdout, regardless of -o.
- "$@" || exit $?
-
- # Remove the call to Libtool.
- if test "$libtool" = yes; then
- while test $1 != '--mode=compile'; do
- shift
- done
- shift
- fi
-
- # Remove `-o $object'.
- IFS=" "
- for arg
- do
- case $arg in
- -o)
- shift
- ;;
- $object)
- shift
- ;;
- *)
- set fnord "$@" "$arg"
- shift # fnord
- shift # $arg
- ;;
- esac
- done
-
- test -z "$dashmflag" && dashmflag=-M
- # Require at least two characters before searching for `:'
- # in the target name. This is to cope with DOS-style filenames:
- # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
- "$@" $dashmflag |
- sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
- rm -f "$depfile"
- cat < "$tmpdepfile" > "$depfile"
- tr ' ' '
-' < "$tmpdepfile" | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-dashXmstdout)
- # This case only exists to satisfy depend.m4. It is never actually
- # run, as this mode is specially recognized in the preamble.
- exit 1
- ;;
-
-makedepend)
- "$@" || exit $?
- # Remove any Libtool call
- if test "$libtool" = yes; then
- while test $1 != '--mode=compile'; do
- shift
- done
- shift
- fi
- # X makedepend
- shift
- cleared=no
- for arg in "$@"; do
- case $cleared in
- no)
- set ""; shift
- cleared=yes ;;
- esac
- case "$arg" in
- -D*|-I*)
- set fnord "$@" "$arg"; shift ;;
- # Strip any option that makedepend may not understand. Remove
- # the object too, otherwise makedepend will parse it as a source file.
- -*|$object)
- ;;
- *)
- set fnord "$@" "$arg"; shift ;;
- esac
- done
- obj_suffix="`echo $object | sed 's/^.*\././'`"
- touch "$tmpdepfile"
- ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
- rm -f "$depfile"
- cat < "$tmpdepfile" > "$depfile"
- sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile" "$tmpdepfile".bak
- ;;
-
-cpp)
- # Important note: in order to support this mode, a compiler *must*
- # always write the preprocessed file to stdout.
- "$@" || exit $?
-
- # Remove the call to Libtool.
- if test "$libtool" = yes; then
- while test $1 != '--mode=compile'; do
- shift
- done
- shift
- fi
-
- # Remove `-o $object'.
- IFS=" "
- for arg
- do
- case $arg in
- -o)
- shift
- ;;
- $object)
- shift
- ;;
- *)
- set fnord "$@" "$arg"
- shift # fnord
- shift # $arg
- ;;
- esac
- done
-
- "$@" -E |
- sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
- -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
- sed '$ s: \\$::' > "$tmpdepfile"
- rm -f "$depfile"
- echo "$object : \\" > "$depfile"
- cat < "$tmpdepfile" >> "$depfile"
- sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-msvisualcpp)
- # Important note: in order to support this mode, a compiler *must*
- # always write the preprocessed file to stdout, regardless of -o,
- # because we must use -o when running libtool.
- "$@" || exit $?
- IFS=" "
- for arg
- do
- case "$arg" in
- "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
- set fnord "$@"
- shift
- shift
- ;;
- *)
- set fnord "$@" "$arg"
- shift
- shift
- ;;
- esac
- done
- "$@" -E |
- sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
- rm -f "$depfile"
- echo "$object : \\" > "$depfile"
- . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
- echo " " >> "$depfile"
- . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
-none)
- exec "$@"
- ;;
-
-*)
- echo "Unknown depmode $depmode" 1>&2
- exit 1
- ;;
-esac
-
-exit 0
-
-# Local Variables:
-# mode: shell-script
-# sh-indentation: 2
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
-# End:
diff --git a/install-sh b/install-sh
deleted file mode 100755
index 4d4a951..0000000
--- a/install-sh
+++ /dev/null
@@ -1,323 +0,0 @@
-#!/bin/sh
-# install - install a program, script, or datafile
-
-scriptversion=2005-05-14.22
-
-# This originates from X11R5 (mit/util/scripts/install.sh), which was
-# later released in X11R6 (xc/config/util/install.sh) with the
-# following copyright and license.
-#
-# Copyright (C) 1994 X Consortium
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
-# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the name of the X Consortium shall not
-# be used in advertising or otherwise to promote the sale, use or other deal-
-# ings in this Software without prior written authorization from the X Consor-
-# tium.
-#
-#
-# FSF changes to this file are in the public domain.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch. It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-chmodcmd="$chmodprog 0755"
-chowncmd=
-chgrpcmd=
-stripcmd=
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=
-dst=
-dir_arg=
-dstarg=
-no_target_directory=
-
-usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
- or: $0 [OPTION]... SRCFILES... DIRECTORY
- or: $0 [OPTION]... -t DIRECTORY SRCFILES...
- or: $0 [OPTION]... -d DIRECTORIES...
-
-In the 1st form, copy SRCFILE to DSTFILE.
-In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
-In the 4th, create DIRECTORIES.
-
-Options:
--c (ignored)
--d create directories instead of installing files.
--g GROUP $chgrpprog installed files to GROUP.
--m MODE $chmodprog installed files to MODE.
--o USER $chownprog installed files to USER.
--s $stripprog installed files.
--t DIRECTORY install into DIRECTORY.
--T report an error if DSTFILE is a directory.
---help display this help and exit.
---version display version info and exit.
-
-Environment variables override the default commands:
- CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
-"
-
-while test -n "$1"; do
- case $1 in
- -c) shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- --help) echo "$usage"; exit $?;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd=$stripprog
- shift
- continue;;
-
- -t) dstarg=$2
- shift
- shift
- continue;;
-
- -T) no_target_directory=true
- shift
- continue;;
-
- --version) echo "$0 $scriptversion"; exit $?;;
-
- *) # When -d is used, all remaining arguments are directories to create.
- # When -t is used, the destination is already specified.
- test -n "$dir_arg$dstarg" && break
- # Otherwise, the last argument is the destination. Remove it from $@.
- for arg
- do
- if test -n "$dstarg"; then
- # $@ is not empty: it contains at least $arg.
- set fnord "$@" "$dstarg"
- shift # fnord
- fi
- shift # arg
- dstarg=$arg
- done
- break;;
- esac
-done
-
-if test -z "$1"; then
- if test -z "$dir_arg"; then
- echo "$0: no input file specified." >&2
- exit 1
- fi
- # It's OK to call `install-sh -d' without argument.
- # This can happen when creating conditional directories.
- exit 0
-fi
-
-for src
-do
- # Protect names starting with `-'.
- case $src in
- -*) src=./$src ;;
- esac
-
- if test -n "$dir_arg"; then
- dst=$src
- src=
-
- if test -d "$dst"; then
- mkdircmd=:
- chmodcmd=
- else
- mkdircmd=$mkdirprog
- fi
- else
- # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
- # might cause directories to be created, which would be especially bad
- # if $src (and thus $dsttmp) contains '*'.
- if test ! -f "$src" && test ! -d "$src"; then
- echo "$0: $src does not exist." >&2
- exit 1
- fi
-
- if test -z "$dstarg"; then
- echo "$0: no destination specified." >&2
- exit 1
- fi
-
- dst=$dstarg
- # Protect names starting with `-'.
- case $dst in
- -*) dst=./$dst ;;
- esac
-
- # If destination is a directory, append the input filename; won't work
- # if double slashes aren't ignored.
- if test -d "$dst"; then
- if test -n "$no_target_directory"; then
- echo "$0: $dstarg: Is a directory" >&2
- exit 1
- fi
- dst=$dst/`basename "$src"`
- fi
- fi
-
- # This sed command emulates the dirname command.
- dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
-
- # Make sure that the destination directory exists.
-
- # Skip lots of stat calls in the usual case.
- if test ! -d "$dstdir"; then
- defaultIFS='
- '
- IFS="${IFS-$defaultIFS}"
-
- oIFS=$IFS
- # Some sh's can't handle IFS=/ for some reason.
- IFS='%'
- set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
- shift
- IFS=$oIFS
-
- pathcomp=
-
- while test $# -ne 0 ; do
- pathcomp=$pathcomp$1
- shift
- if test ! -d "$pathcomp"; then
- $mkdirprog "$pathcomp"
- # mkdir can fail with a `File exist' error in case several
- # install-sh are creating the directory concurrently. This
- # is OK.
- test -d "$pathcomp" || exit
- fi
- pathcomp=$pathcomp/
- done
- fi
-
- if test -n "$dir_arg"; then
- $doit $mkdircmd "$dst" \
- && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
- && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
- && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
- && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
-
- else
- dstfile=`basename "$dst"`
-
- # Make a couple of temp file names in the proper directory.
- dsttmp=$dstdir/_inst.$$_
- rmtmp=$dstdir/_rm.$$_
-
- # Trap to clean up those temp files at exit.
- trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
- trap '(exit $?); exit' 1 2 13 15
-
- # Copy the file name to the temp name.
- $doit $cpprog "$src" "$dsttmp" &&
-
- # and set any options; do chmod last to preserve setuid bits.
- #
- # If any of these fail, we abort the whole thing. If we want to
- # ignore errors from any of these, just make sure not to ignore
- # errors from the above "$doit $cpprog $src $dsttmp" command.
- #
- { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
- && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
- && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
- && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
-
- # Now rename the file to the real destination.
- { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
- || {
- # The rename failed, perhaps because mv can't rename something else
- # to itself, or perhaps because mv is so ancient that it does not
- # support -f.
-
- # Now remove or move aside any old file at destination location.
- # We try this two ways since rm can't unlink itself on some
- # systems and the destination file might be busy for other
- # reasons. In this case, the final cleanup might fail but the new
- # file should still install successfully.
- {
- if test -f "$dstdir/$dstfile"; then
- $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
- || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
- || {
- echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
- (exit 1); exit 1
- }
- else
- :
- fi
- } &&
-
- # Now rename the file to the real destination.
- $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
- }
- }
- fi || { (exit 1); exit 1; }
-done
-
-# The final little trick to "correctly" pass the exit status to the exit trap.
-{
- (exit 0); exit 0
-}
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
-# End:
diff --git a/ltmain.sh b/ltmain.sh
deleted file mode 100644
index 8fc56db..0000000
--- a/ltmain.sh
+++ /dev/null
@@ -1,6871 +0,0 @@
-# ltmain.sh - Provide generalized library-building support services.
-# NOTE: Changing this file will not affect anything until you rerun configure.
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-basename="s,^.*/,,g"
-
-# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
-# is ksh but when the shell is invoked as "sh" and the current value of
-# the _XPG environment variable is not equal to 1 (one), the special
-# positional parameter $0, within a function call, is the name of the
-# function.
-progpath="$0"
-
-# The name of this program:
-progname=`echo "$progpath" | $SED $basename`
-modename="$progname"
-
-# Global variables:
-EXIT_SUCCESS=0
-EXIT_FAILURE=1
-
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION="1.5.22 Debian 1.5.22-2"
-TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
-
-# See if we are running on zsh, and set the options which allow our
-# commands through without removal of \ escapes.
-if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-
-# Check that we have a working $echo.
-if test "X$1" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
-elif test "X$1" = X--fallback-echo; then
- # Avoid inline document here, it may be left over
- :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
- # Yippee, $echo works!
- :
-else
- # Restart under the correct shell, and then maybe $echo will work.
- exec $SHELL "$progpath" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
- # used as fallback echo
- shift
- cat <<EOF
-$*
-EOF
- exit $EXIT_SUCCESS
-fi
-
-default_mode=
-help="Try \`$progname --help' for more information."
-magic="%%%MAGIC variable%%%"
-mkdir="mkdir"
-mv="mv -f"
-rm="rm -f"
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed="${SED}"' -e 1s/^X//'
-sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
-# test EBCDIC or ASCII
-case `echo X|tr X '\101'` in
- A) # ASCII based system
- # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
- SP2NL='tr \040 \012'
- NL2SP='tr \015\012 \040\040'
- ;;
- *) # EBCDIC based system
- SP2NL='tr \100 \n'
- NL2SP='tr \r\n \100\100'
- ;;
-esac
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-# We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
- save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
- save_LANG="$LANG"; LANG=C; export LANG
-fi
-
-# Make sure IFS has a sensible default
-lt_nl='
-'
-IFS=" $lt_nl"
-
-if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
- $echo "$modename: not configured to build any kind of library" 1>&2
- $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit $EXIT_FAILURE
-fi
-
-# Global variables.
-mode=$default_mode
-nonopt=
-prev=
-prevopt=
-run=
-show="$echo"
-show_help=
-execute_dlfiles=
-duplicate_deps=no
-preserve_args=
-lo2o="s/\\.lo\$/.${objext}/"
-o2lo="s/\\.${objext}\$/.lo/"
-
-#####################################
-# Shell function definitions:
-# This seems to be the best place for them
-
-# func_mktempdir [string]
-# Make a temporary directory that won't clash with other running
-# libtool processes, and avoids race conditions if possible. If
-# given, STRING is the basename for that directory.
-func_mktempdir ()
-{
- my_template="${TMPDIR-/tmp}/${1-$progname}"
-
- if test "$run" = ":"; then
- # Return a directory name, but don't create it in dry-run mode
- my_tmpdir="${my_template}-$$"
- else
-
- # If mktemp works, use that first and foremost
- my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
-
- if test ! -d "$my_tmpdir"; then
- # Failing that, at least try and use $RANDOM to avoid a race
- my_tmpdir="${my_template}-${RANDOM-0}$$"
-
- save_mktempdir_umask=`umask`
- umask 0077
- $mkdir "$my_tmpdir"
- umask $save_mktempdir_umask
- fi
-
- # If we're not in dry-run mode, bomb out on failure
- test -d "$my_tmpdir" || {
- $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
- exit $EXIT_FAILURE
- }
- fi
-
- $echo "X$my_tmpdir" | $Xsed
-}
-
-
-# func_win32_libid arg
-# return the library type of file 'arg'
-#
-# Need a lot of goo to handle *both* DLLs and import libs
-# Has to be a shell function in order to 'eat' the argument
-# that is supplied when $file_magic_command is called.
-func_win32_libid ()
-{
- win32_libid_type="unknown"
- win32_fileres=`file -L $1 2>/dev/null`
- case $win32_fileres in
- *ar\ archive\ import\ library*) # definitely import
- win32_libid_type="x86 archive import"
- ;;
- *ar\ archive*) # could be an import, or static
- if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
- $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
- win32_nmres=`eval $NM -f posix -A $1 | \
- $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
- case $win32_nmres in
- import*) win32_libid_type="x86 archive import";;
- *) win32_libid_type="x86 archive static";;
- esac
- fi
- ;;
- *DLL*)
- win32_libid_type="x86 DLL"
- ;;
- *executable*) # but shell scripts are "executable" too...
- case $win32_fileres in
- *MS\ Windows\ PE\ Intel*)
- win32_libid_type="x86 DLL"
- ;;
- esac
- ;;
- esac
- $echo $win32_libid_type
-}
-
-
-# func_infer_tag arg
-# Infer tagged configuration to use if any are available and
-# if one wasn't chosen via the "--tag" command line option.
-# Only attempt this if the compiler in the base compile
-# command doesn't match the default compiler.
-# arg is usually of the form 'gcc ...'
-func_infer_tag ()
-{
- if test -n "$available_tags" && test -z "$tagname"; then
- CC_quoted=
- for arg in $CC; do
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- CC_quoted="$CC_quoted $arg"
- done
- case $@ in
- # Blanks in the command may have been stripped by the calling shell,
- # but not from the CC environment variable when configure was run.
- " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
- # Blanks at the start of $base_compile will cause this to fail
- # if we don't check for them as well.
- *)
- for z in $available_tags; do
- if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
- # Evaluate the configuration.
- eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
- CC_quoted=
- for arg in $CC; do
- # Double-quote args containing other shell metacharacters.
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- CC_quoted="$CC_quoted $arg"
- done
- case "$@ " in
- " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
- # The compiler in the base compile command matches
- # the one in the tagged configuration.
- # Assume this is the tagged configuration we want.
- tagname=$z
- break
- ;;
- esac
- fi
- done
- # If $tagname still isn't set, then no tagged configuration
- # was found and let the user know that the "--tag" command
- # line option must be used.
- if test -z "$tagname"; then
- $echo "$modename: unable to infer tagged configuration"
- $echo "$modename: specify a tag with \`--tag'" 1>&2
- exit $EXIT_FAILURE
-# else
-# $echo "$modename: using $tagname tagged configuration"
- fi
- ;;
- esac
- fi
-}
-
-
-# func_extract_an_archive dir oldlib
-func_extract_an_archive ()
-{
- f_ex_an_ar_dir="$1"; shift
- f_ex_an_ar_oldlib="$1"
-
- $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
- $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
- if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
- exit $EXIT_FAILURE
- fi
-}
-
-# func_extract_archives gentop oldlib ...
-func_extract_archives ()
-{
- my_gentop="$1"; shift
- my_oldlibs=${1+"$@"}
- my_oldobjs=""
- my_xlib=""
- my_xabs=""
- my_xdir=""
- my_status=""
-
- $show "${rm}r $my_gentop"
- $run ${rm}r "$my_gentop"
- $show "$mkdir $my_gentop"
- $run $mkdir "$my_gentop"
- my_status=$?
- if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
- exit $my_status
- fi
-
- for my_xlib in $my_oldlibs; do
- # Extract the objects.
- case $my_xlib in
- [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
- *) my_xabs=`pwd`"/$my_xlib" ;;
- esac
- my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
- my_xdir="$my_gentop/$my_xlib"
-
- $show "${rm}r $my_xdir"
- $run ${rm}r "$my_xdir"
- $show "$mkdir $my_xdir"
- $run $mkdir "$my_xdir"
- exit_status=$?
- if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
- exit $exit_status
- fi
- case $host in
- *-darwin*)
- $show "Extracting $my_xabs"
- # Do not bother doing anything if just a dry run
- if test -z "$run"; then
- darwin_orig_dir=`pwd`
- cd $my_xdir || exit $?
- darwin_archive=$my_xabs
- darwin_curdir=`pwd`
- darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
- darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
- if test -n "$darwin_arches"; then
- darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
- darwin_arch=
- $show "$darwin_base_archive has multiple architectures $darwin_arches"
- for darwin_arch in $darwin_arches ; do
- mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
- lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
- cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
- func_extract_an_archive "`pwd`" "${darwin_base_archive}"
- cd "$darwin_curdir"
- $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
- done # $darwin_arches
- ## Okay now we have a bunch of thin objects, gotta fatten them up :)
- darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
- darwin_file=
- darwin_files=
- for darwin_file in $darwin_filelist; do
- darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
- lipo -create -output "$darwin_file" $darwin_files
- done # $darwin_filelist
- ${rm}r unfat-$$
- cd "$darwin_orig_dir"
- else
- cd "$darwin_orig_dir"
- func_extract_an_archive "$my_xdir" "$my_xabs"
- fi # $darwin_arches
- fi # $run
- ;;
- *)
- func_extract_an_archive "$my_xdir" "$my_xabs"
- ;;
- esac
- my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
- done
- func_extract_archives_result="$my_oldobjs"
-}
-# End of Shell function definitions
-#####################################
-
-# Darwin sucks
-eval std_shrext=\"$shrext_cmds\"
-
-disable_libs=no
-
-# Parse our command line options once, thoroughly.
-while test "$#" -gt 0
-do
- arg="$1"
- shift
-
- case $arg in
- -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
- *) optarg= ;;
- esac
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- case $prev in
- execute_dlfiles)
- execute_dlfiles="$execute_dlfiles $arg"
- ;;
- tag)
- tagname="$arg"
- preserve_args="${preserve_args}=$arg"
-
- # Check whether tagname contains only valid characters
- case $tagname in
- *[!-_A-Za-z0-9,/]*)
- $echo "$progname: invalid tag name: $tagname" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- case $tagname in
- CC)
- # Don't test for the "default" C tag, as we know, it's there, but
- # not specially marked.
- ;;
- *)
- if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
- taglist="$taglist $tagname"
- # Evaluate the configuration.
- eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
- else
- $echo "$progname: ignoring unknown tag $tagname" 1>&2
- fi
- ;;
- esac
- ;;
- *)
- eval "$prev=\$arg"
- ;;
- esac
-
- prev=
- prevopt=
- continue
- fi
-
- # Have we seen a non-optional argument yet?
- case $arg in
- --help)
- show_help=yes
- ;;
-
- --version)
- $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
- $echo
- $echo "Copyright (C) 2005 Free Software Foundation, Inc."
- $echo "This is free software; see the source for copying conditions. There is NO"
- $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
- exit $?
- ;;
-
- --config)
- ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
- # Now print the configurations for the tags.
- for tagname in $taglist; do
- ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
- done
- exit $?
- ;;
-
- --debug)
- $echo "$progname: enabling shell trace mode"
- set -x
- preserve_args="$preserve_args $arg"
- ;;
-
- --dry-run | -n)
- run=:
- ;;
-
- --features)
- $echo "host: $host"
- if test "$build_libtool_libs" = yes; then
- $echo "enable shared libraries"
- else
- $echo "disable shared libraries"
- fi
- if test "$build_old_libs" = yes; then
- $echo "enable static libraries"
- else
- $echo "disable static libraries"
- fi
- exit $?
- ;;
-
- --finish) mode="finish" ;;
-
- --mode) prevopt="--mode" prev=mode ;;
- --mode=*) mode="$optarg" ;;
-
- --preserve-dup-deps) duplicate_deps="yes" ;;
-
- --quiet | --silent)
- show=:
- preserve_args="$preserve_args $arg"
- ;;
-
- --tag)
- prevopt="--tag"
- prev=tag
- preserve_args="$preserve_args --tag"
- ;;
- --tag=*)
- set tag "$optarg" ${1+"$@"}
- shift
- prev=tag
- preserve_args="$preserve_args --tag"
- ;;
-
- -dlopen)
- prevopt="-dlopen"
- prev=execute_dlfiles
- ;;
-
- -*)
- $echo "$modename: unrecognized option \`$arg'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
-
- *)
- nonopt="$arg"
- break
- ;;
- esac
-done
-
-if test -n "$prevopt"; then
- $echo "$modename: option \`$prevopt' requires an argument" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
-fi
-
-case $disable_libs in
-no)
- ;;
-shared)
- build_libtool_libs=no
- build_old_libs=yes
- ;;
-static)
- build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
- ;;
-esac
-
-# If this variable is set in any of the actions, the command in it
-# will be execed at the end. This prevents here-documents from being
-# left over by shells.
-exec_cmd=
-
-if test -z "$show_help"; then
-
- # Infer the operation mode.
- if test -z "$mode"; then
- $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
- $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
- case $nonopt in
- *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
- mode=link
- for arg
- do
- case $arg in
- -c)
- mode=compile
- break
- ;;
- esac
- done
- ;;
- *db | *dbx | *strace | *truss)
- mode=execute
- ;;
- *install*|cp|mv)
- mode=install
- ;;
- *rm)
- mode=uninstall
- ;;
- *)
- # If we have no mode, but dlfiles were specified, then do execute mode.
- test -n "$execute_dlfiles" && mode=execute
-
- # Just use the default operation mode.
- if test -z "$mode"; then
- if test -n "$nonopt"; then
- $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
- else
- $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
- fi
- fi
- ;;
- esac
- fi
-
- # Only execute mode is allowed to have -dlopen flags.
- if test -n "$execute_dlfiles" && test "$mode" != execute; then
- $echo "$modename: unrecognized option \`-dlopen'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Change the help message to a mode-specific one.
- generic_help="$help"
- help="Try \`$modename --help --mode=$mode' for more information."
-
- # These modes are in order of execution frequency so that they run quickly.
- case $mode in
- # libtool compile mode
- compile)
- modename="$modename: compile"
- # Get the compilation command and the source file.
- base_compile=
- srcfile="$nonopt" # always keep a non-empty value in "srcfile"
- suppress_opt=yes
- suppress_output=
- arg_mode=normal
- libobj=
- later=
-
- for arg
- do
- case $arg_mode in
- arg )
- # do not "continue". Instead, add this to base_compile
- lastarg="$arg"
- arg_mode=normal
- ;;
-
- target )
- libobj="$arg"
- arg_mode=normal
- continue
- ;;
-
- normal )
- # Accept any command-line options.
- case $arg in
- -o)
- if test -n "$libobj" ; then
- $echo "$modename: you cannot specify \`-o' more than once" 1>&2
- exit $EXIT_FAILURE
- fi
- arg_mode=target
- continue
- ;;
-
- -static | -prefer-pic | -prefer-non-pic)
- later="$later $arg"
- continue
- ;;
-
- -no-suppress)
- suppress_opt=no
- continue
- ;;
-
- -Xcompiler)
- arg_mode=arg # the next one goes into the "base_compile" arg list
- continue # The current "srcfile" will either be retained or
- ;; # replaced later. I would guess that would be a bug.
-
- -Wc,*)
- args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
- lastarg=
- save_ifs="$IFS"; IFS=','
- for arg in $args; do
- IFS="$save_ifs"
-
- # Double-quote args containing other shell metacharacters.
- # Many Bourne shells cannot handle close brackets correctly
- # in scan sets, so we specify it separately.
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- lastarg="$lastarg $arg"
- done
- IFS="$save_ifs"
- lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
-
- # Add the arguments to base_compile.
- base_compile="$base_compile $lastarg"
- continue
- ;;
-
- * )
- # Accept the current argument as the source file.
- # The previous "srcfile" becomes the current argument.
- #
- lastarg="$srcfile"
- srcfile="$arg"
- ;;
- esac # case $arg
- ;;
- esac # case $arg_mode
-
- # Aesthetically quote the previous argument.
- lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
-
- case $lastarg in
- # Double-quote args containing other shell metacharacters.
- # Many Bourne shells cannot handle close brackets correctly
- # in scan sets, and some SunOS ksh mistreat backslash-escaping
- # in scan sets (worked around with variable expansion),
- # and furthermore cannot handle '|' '&' '(' ')' in scan sets
- # at all, so we specify them separately.
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- lastarg="\"$lastarg\""
- ;;
- esac
-
- base_compile="$base_compile $lastarg"
- done # for arg
-
- case $arg_mode in
- arg)
- $echo "$modename: you must specify an argument for -Xcompile"
- exit $EXIT_FAILURE
- ;;
- target)
- $echo "$modename: you must specify a target with \`-o'" 1>&2
- exit $EXIT_FAILURE
- ;;
- *)
- # Get the name of the library object.
- [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
- ;;
- esac
-
- # Recognize several different file suffixes.
- # If the user specifies -o file.o, it is replaced with file.lo
- xform='[cCFSifmso]'
- case $libobj in
- *.ada) xform=ada ;;
- *.adb) xform=adb ;;
- *.ads) xform=ads ;;
- *.asm) xform=asm ;;
- *.c++) xform=c++ ;;
- *.cc) xform=cc ;;
- *.ii) xform=ii ;;
- *.class) xform=class ;;
- *.cpp) xform=cpp ;;
- *.cxx) xform=cxx ;;
- *.f90) xform=f90 ;;
- *.for) xform=for ;;
- *.java) xform=java ;;
- esac
-
- libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
-
- case $libobj in
- *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
- *)
- $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- func_infer_tag $base_compile
-
- for arg in $later; do
- case $arg in
- -static)
- build_old_libs=yes
- continue
- ;;
-
- -prefer-pic)
- pic_mode=yes
- continue
- ;;
-
- -prefer-non-pic)
- pic_mode=no
- continue
- ;;
- esac
- done
-
- qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
- case $qlibobj in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- qlibobj="\"$qlibobj\"" ;;
- esac
- test "X$libobj" != "X$qlibobj" \
- && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \
- && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
- objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
- xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$obj"; then
- xdir=
- else
- xdir=$xdir/
- fi
- lobj=${xdir}$objdir/$objname
-
- if test -z "$base_compile"; then
- $echo "$modename: you must specify a compilation command" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Delete any leftover library objects.
- if test "$build_old_libs" = yes; then
- removelist="$obj $lobj $libobj ${libobj}T"
- else
- removelist="$lobj $libobj ${libobj}T"
- fi
-
- $run $rm $removelist
- trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
-
- # On Cygwin there's no "real" PIC flag so we must build both object types
- case $host_os in
- cygwin* | mingw* | pw32* | os2*)
- pic_mode=default
- ;;
- esac
- if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
- # non-PIC code in shared libraries is not supported
- pic_mode=default
- fi
-
- # Calculate the filename of the output object if compiler does
- # not support -o with -c
- if test "$compiler_c_o" = no; then
- output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
- lockfile="$output_obj.lock"
- removelist="$removelist $output_obj $lockfile"
- trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
- else
- output_obj=
- need_locks=no
- lockfile=
- fi
-
- # Lock this critical section if it is needed
- # We use this script file to make the link, it avoids creating a new file
- if test "$need_locks" = yes; then
- until $run ln "$progpath" "$lockfile" 2>/dev/null; do
- $show "Waiting for $lockfile to be removed"
- sleep 2
- done
- elif test "$need_locks" = warn; then
- if test -f "$lockfile"; then
- $echo "\
-*** ERROR, $lockfile exists and contains:
-`cat $lockfile 2>/dev/null`
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit $EXIT_FAILURE
- fi
- $echo "$srcfile" > "$lockfile"
- fi
-
- if test -n "$fix_srcfile_path"; then
- eval srcfile=\"$fix_srcfile_path\"
- fi
- qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
- case $qsrcfile in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- qsrcfile="\"$qsrcfile\"" ;;
- esac
-
- $run $rm "$libobj" "${libobj}T"
-
- # Create a libtool object file (analogous to a ".la" file),
- # but don't create it if we're doing a dry run.
- test -z "$run" && cat > ${libobj}T <<EOF
-# $libobj - a libtool object file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# Name of the PIC object.
-EOF
-
- # Only build a PIC object if we are building libtool libraries.
- if test "$build_libtool_libs" = yes; then
- # Without this assignment, base_compile gets emptied.
- fbsd_hideous_sh_bug=$base_compile
-
- if test "$pic_mode" != no; then
- command="$base_compile $qsrcfile $pic_flag"
- else
- # Don't build PIC code
- command="$base_compile $qsrcfile"
- fi
-
- if test ! -d "${xdir}$objdir"; then
- $show "$mkdir ${xdir}$objdir"
- $run $mkdir ${xdir}$objdir
- exit_status=$?
- if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
- exit $exit_status
- fi
- fi
-
- if test -z "$output_obj"; then
- # Place PIC objects in $objdir
- command="$command -o $lobj"
- fi
-
- $run $rm "$lobj" "$output_obj"
-
- $show "$command"
- if $run eval "$command"; then :
- else
- test -n "$output_obj" && $run $rm $removelist
- exit $EXIT_FAILURE
- fi
-
- if test "$need_locks" = warn &&
- test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
- $echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit $EXIT_FAILURE
- fi
-
- # Just move the object if needed, then go on to compile the next one
- if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
- $show "$mv $output_obj $lobj"
- if $run $mv $output_obj $lobj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
-
- # Append the name of the PIC object to the libtool object file.
- test -z "$run" && cat >> ${libobj}T <<EOF
-pic_object='$objdir/$objname'
-
-EOF
-
- # Allow error messages only from the first compilation.
- if test "$suppress_opt" = yes; then
- suppress_output=' >/dev/null 2>&1'
- fi
- else
- # No PIC object so indicate it doesn't exist in the libtool
- # object file.
- test -z "$run" && cat >> ${libobj}T <<EOF
-pic_object=none
-
-EOF
- fi
-
- # Only build a position-dependent object if we build old libraries.
- if test "$build_old_libs" = yes; then
- if test "$pic_mode" != yes; then
- # Don't build PIC code
- command="$base_compile $qsrcfile"
- else
- command="$base_compile $qsrcfile $pic_flag"
- fi
- if test "$compiler_c_o" = yes; then
- command="$command -o $obj"
- fi
-
- # Suppress compiler output if we already did a PIC compilation.
- command="$command$suppress_output"
- $run $rm "$obj" "$output_obj"
- $show "$command"
- if $run eval "$command"; then :
- else
- $run $rm $removelist
- exit $EXIT_FAILURE
- fi
-
- if test "$need_locks" = warn &&
- test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
- $echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together. If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
- $run $rm $removelist
- exit $EXIT_FAILURE
- fi
-
- # Just move the object if needed
- if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
- $show "$mv $output_obj $obj"
- if $run $mv $output_obj $obj; then :
- else
- error=$?
- $run $rm $removelist
- exit $error
- fi
- fi
-
- # Append the name of the non-PIC object the libtool object file.
- # Only append if the libtool object file exists.
- test -z "$run" && cat >> ${libobj}T <<EOF
-# Name of the non-PIC object.
-non_pic_object='$objname'
-
-EOF
- else
- # Append the name of the non-PIC object the libtool object file.
- # Only append if the libtool object file exists.
- test -z "$run" && cat >> ${libobj}T <<EOF
-# Name of the non-PIC object.
-non_pic_object=none
-
-EOF
- fi
-
- $run $mv "${libobj}T" "${libobj}"
-
- # Unlock the critical section if it was locked
- if test "$need_locks" != no; then
- $run $rm "$lockfile"
- fi
-
- exit $EXIT_SUCCESS
- ;;
-
- # libtool link mode
- link | relink)
- modename="$modename: link"
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- # It is impossible to link a dll without this setting, and
- # we shouldn't force the makefile maintainer to figure out
- # which system we are compiling for in order to pass an extra
- # flag for every libtool invocation.
- # allow_undefined=no
-
- # FIXME: Unfortunately, there are problems with the above when trying
- # to make a dll which has undefined symbols, in which case not
- # even a static library is built. For now, we need to specify
- # -no-undefined on the libtool link line when we can be certain
- # that all symbols are satisfied, otherwise we get a static library.
- allow_undefined=yes
- ;;
- *)
- allow_undefined=yes
- ;;
- esac
- libtool_args="$nonopt"
- base_compile="$nonopt $@"
- compile_command="$nonopt"
- finalize_command="$nonopt"
-
- compile_rpath=
- finalize_rpath=
- compile_shlibpath=
- finalize_shlibpath=
- convenience=
- old_convenience=
- deplibs=
- old_deplibs=
- compiler_flags=
- linker_flags=
- dllsearchpath=
- lib_search_path=`pwd`
- inst_prefix_dir=
-
- avoid_version=no
- dlfiles=
- dlprefiles=
- dlself=no
- export_dynamic=no
- export_symbols=
- export_symbols_regex=
- generated=
- libobjs=
- ltlibs=
- module=no
- no_install=no
- objs=
- non_pic_objects=
- notinst_path= # paths that contain not-installed libtool libraries
- precious_files_regex=
- prefer_static_libs=no
- preload=no
- prev=
- prevarg=
- release=
- rpath=
- xrpath=
- perm_rpath=
- temp_rpath=
- thread_safe=no
- vinfo=
- vinfo_number=no
-
- func_infer_tag $base_compile
-
- # We need to know -static, to get the right output filenames.
- for arg
- do
- case $arg in
- -all-static | -static)
- if test "X$arg" = "X-all-static"; then
- if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
- $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
- fi
- if test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- prefer_static_libs=yes
- else
- if test -z "$pic_flag" && test -n "$link_static_flag"; then
- dlopen_self=$dlopen_self_static
- fi
- prefer_static_libs=built
- fi
- build_libtool_libs=no
- build_old_libs=yes
- break
- ;;
- esac
- done
-
- # See if our shared archives depend on static archives.
- test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
- # Go through the arguments, transforming them on the way.
- while test "$#" -gt 0; do
- arg="$1"
- shift
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
- ;;
- *) qarg=$arg ;;
- esac
- libtool_args="$libtool_args $qarg"
-
- # If the previous option needs an argument, assign it.
- if test -n "$prev"; then
- case $prev in
- output)
- compile_command="$compile_command @OUTPUT@"
- finalize_command="$finalize_command @OUTPUT@"
- ;;
- esac
-
- case $prev in
- dlfiles|dlprefiles)
- if test "$preload" = no; then
- # Add the symbol object into the linking commands.
- compile_command="$compile_command @SYMFILE@"
- finalize_command="$finalize_command @SYMFILE@"
- preload=yes
- fi
- case $arg in
- *.la | *.lo) ;; # We handle these cases below.
- force)
- if test "$dlself" = no; then
- dlself=needless
- export_dynamic=yes
- fi
- prev=
- continue
- ;;
- self)
- if test "$prev" = dlprefiles; then
- dlself=yes
- elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
- dlself=yes
- else
- dlself=needless
- export_dynamic=yes
- fi
- prev=
- continue
- ;;
- *)
- if test "$prev" = dlfiles; then
- dlfiles="$dlfiles $arg"
- else
- dlprefiles="$dlprefiles $arg"
- fi
- prev=
- continue
- ;;
- esac
- ;;
- expsyms)
- export_symbols="$arg"
- if test ! -f "$arg"; then
- $echo "$modename: symbol file \`$arg' does not exist"
- exit $EXIT_FAILURE
- fi
- prev=
- continue
- ;;
- expsyms_regex)
- export_symbols_regex="$arg"
- prev=
- continue
- ;;
- inst_prefix)
- inst_prefix_dir="$arg"
- prev=
- continue
- ;;
- precious_regex)
- precious_files_regex="$arg"
- prev=
- continue
- ;;
- release)
- release="-$arg"
- prev=
- continue
- ;;
- objectlist)
- if test -f "$arg"; then
- save_arg=$arg
- moreargs=
- for fil in `cat $save_arg`
- do
-# moreargs="$moreargs $fil"
- arg=$fil
- # A libtool-controlled object.
-
- # Check to see that this really is a libtool object.
- if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- pic_object=
- non_pic_object=
-
- # Read the .lo file
- # If there is no directory component, then add one.
- case $arg in
- */* | *\\*) . $arg ;;
- *) . ./$arg ;;
- esac
-
- if test -z "$pic_object" || \
- test -z "$non_pic_object" ||
- test "$pic_object" = none && \
- test "$non_pic_object" = none; then
- $echo "$modename: cannot find name of object for \`$arg'" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- if test "$pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- pic_object="$xdir$pic_object"
-
- if test "$prev" = dlfiles; then
- if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
- dlfiles="$dlfiles $pic_object"
- prev=
- continue
- else
- # If libtool objects are unsupported, then we need to preload.
- prev=dlprefiles
- fi
- fi
-
- # CHECK ME: I think I busted this. -Ossama
- if test "$prev" = dlprefiles; then
- # Preload the old-style object.
- dlprefiles="$dlprefiles $pic_object"
- prev=
- fi
-
- # A PIC object.
- libobjs="$libobjs $pic_object"
- arg="$pic_object"
- fi
-
- # Non-PIC object.
- if test "$non_pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- non_pic_object="$xdir$non_pic_object"
-
- # A standard non-PIC object
- non_pic_objects="$non_pic_objects $non_pic_object"
- if test -z "$pic_object" || test "$pic_object" = none ; then
- arg="$non_pic_object"
- fi
- else
- # If the PIC object exists, use it instead.
- # $xdir was prepended to $pic_object above.
- non_pic_object="$pic_object"
- non_pic_objects="$non_pic_objects $non_pic_object"
- fi
- else
- # Only an error if not doing a dry-run.
- if test -z "$run"; then
- $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
- exit $EXIT_FAILURE
- else
- # Dry-run case.
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
- non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
- libobjs="$libobjs $pic_object"
- non_pic_objects="$non_pic_objects $non_pic_object"
- fi
- fi
- done
- else
- $echo "$modename: link input file \`$save_arg' does not exist"
- exit $EXIT_FAILURE
- fi
- arg=$save_arg
- prev=
- continue
- ;;
- rpath | xrpath)
- # We need an absolute path.
- case $arg in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- if test "$prev" = rpath; then
- case "$rpath " in
- *" $arg "*) ;;
- *) rpath="$rpath $arg" ;;
- esac
- else
- case "$xrpath " in
- *" $arg "*) ;;
- *) xrpath="$xrpath $arg" ;;
- esac
- fi
- prev=
- continue
- ;;
- xcompiler)
- compiler_flags="$compiler_flags $qarg"
- prev=
- compile_command="$compile_command $qarg"
- finalize_command="$finalize_command $qarg"
- continue
- ;;
- xlinker)
- linker_flags="$linker_flags $qarg"
- compiler_flags="$compiler_flags $wl$qarg"
- prev=
- compile_command="$compile_command $wl$qarg"
- finalize_command="$finalize_command $wl$qarg"
- continue
- ;;
- xcclinker)
- linker_flags="$linker_flags $qarg"
- compiler_flags="$compiler_flags $qarg"
- prev=
- compile_command="$compile_command $qarg"
- finalize_command="$finalize_command $qarg"
- continue
- ;;
- shrext)
- shrext_cmds="$arg"
- prev=
- continue
- ;;
- darwin_framework|darwin_framework_skip)
- test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- prev=
- continue
- ;;
- *)
- eval "$prev=\"\$arg\""
- prev=
- continue
- ;;
- esac
- fi # test -n "$prev"
-
- prevarg="$arg"
-
- case $arg in
- -all-static)
- if test -n "$link_static_flag"; then
- compile_command="$compile_command $link_static_flag"
- finalize_command="$finalize_command $link_static_flag"
- fi
- continue
- ;;
-
- -allow-undefined)
- # FIXME: remove this flag sometime in the future.
- $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
- continue
- ;;
-
- -avoid-version)
- avoid_version=yes
- continue
- ;;
-
- -dlopen)
- prev=dlfiles
- continue
- ;;
-
- -dlpreopen)
- prev=dlprefiles
- continue
- ;;
-
- -export-dynamic)
- export_dynamic=yes
- continue
- ;;
-
- -export-symbols | -export-symbols-regex)
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: more than one -exported-symbols argument is not allowed"
- exit $EXIT_FAILURE
- fi
- if test "X$arg" = "X-export-symbols"; then
- prev=expsyms
- else
- prev=expsyms_regex
- fi
- continue
- ;;
-
- -framework|-arch|-isysroot)
- case " $CC " in
- *" ${arg} ${1} "* | *" ${arg} ${1} "*)
- prev=darwin_framework_skip ;;
- *) compiler_flags="$compiler_flags $arg"
- prev=darwin_framework ;;
- esac
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- continue
- ;;
-
- -inst-prefix-dir)
- prev=inst_prefix
- continue
- ;;
-
- # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
- # so, if we see these flags be careful not to treat them like -L
- -L[A-Z][A-Z]*:*)
- case $with_gcc/$host in
- no/*-*-irix* | /*-*-irix*)
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- ;;
- esac
- continue
- ;;
-
- -L*)
- dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
- absdir="$dir"
- notinst_path="$notinst_path $dir"
- fi
- dir="$absdir"
- ;;
- esac
- case "$deplibs " in
- *" -L$dir "*) ;;
- *)
- deplibs="$deplibs -L$dir"
- lib_search_path="$lib_search_path $dir"
- ;;
- esac
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
- case :$dllsearchpath: in
- *":$dir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$dir";;
- esac
- case :$dllsearchpath: in
- *":$testbindir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$testbindir";;
- esac
- ;;
- esac
- continue
- ;;
-
- -l*)
- if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
- # These systems don't actually have a C or math library (as such)
- continue
- ;;
- *-*-os2*)
- # These systems don't actually have a C library (as such)
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc due to us having libc/libc_r.
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-rhapsody* | *-*-darwin1.[012])
- # Rhapsody C and math libraries are in the System framework
- deplibs="$deplibs -framework System"
- continue
- ;;
- *-*-sco3.2v5* | *-*-sco5v6*)
- # Causes problems with __ctype
- test "X$arg" = "X-lc" && continue
- ;;
- *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
- # Compiler inserts libc in the correct place for threads to work
- test "X$arg" = "X-lc" && continue
- ;;
- esac
- elif test "X$arg" = "X-lc_r"; then
- case $host in
- *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc_r directly, use -pthread flag.
- continue
- ;;
- esac
- fi
- deplibs="$deplibs $arg"
- continue
- ;;
-
- # Tru64 UNIX uses -model [arg] to determine the layout of C++
- # classes, name mangling, and exception handling.
- -model)
- compile_command="$compile_command $arg"
- compiler_flags="$compiler_flags $arg"
- finalize_command="$finalize_command $arg"
- prev=xcompiler
- continue
- ;;
-
- -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
- compiler_flags="$compiler_flags $arg"
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- continue
- ;;
-
- -module)
- module=yes
- continue
- ;;
-
- # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
- # -r[0-9][0-9]* specifies the processor on the SGI compiler
- # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
- # +DA*, +DD* enable 64-bit mode on the HP compiler
- # -q* pass through compiler args for the IBM compiler
- # -m* pass through architecture-specific compiler args for GCC
- # -m*, -t[45]*, -txscale* pass through architecture-specific
- # compiler args for GCC
- # -pg pass through profiling flag for GCC
- # @file GCC response files
- -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
- -t[45]*|-txscale*|@*)
-
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- compiler_flags="$compiler_flags $arg"
- continue
- ;;
-
- -shrext)
- prev=shrext
- continue
- ;;
-
- -no-fast-install)
- fast_install=no
- continue
- ;;
-
- -no-install)
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- # The PATH hackery in wrapper scripts is required on Windows
- # in order for the loader to find any dlls it needs.
- $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
- $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
- fast_install=no
- ;;
- *) no_install=yes ;;
- esac
- continue
- ;;
-
- -no-undefined)
- allow_undefined=no
- continue
- ;;
-
- -objectlist)
- prev=objectlist
- continue
- ;;
-
- -o) prev=output ;;
-
- -precious-files-regex)
- prev=precious_regex
- continue
- ;;
-
- -release)
- prev=release
- continue
- ;;
-
- -rpath)
- prev=rpath
- continue
- ;;
-
- -R)
- prev=xrpath
- continue
- ;;
-
- -R*)
- dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- $echo "$modename: only absolute run-paths are allowed" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- case "$xrpath " in
- *" $dir "*) ;;
- *) xrpath="$xrpath $dir" ;;
- esac
- continue
- ;;
-
- -static)
- # The effects of -static are defined in a previous loop.
- # We used to do the same as -all-static on platforms that
- # didn't have a PIC flag, but the assumption that the effects
- # would be equivalent was wrong. It would break on at least
- # Digital Unix and AIX.
- continue
- ;;
-
- -thread-safe)
- thread_safe=yes
- continue
- ;;
-
- -version-info)
- prev=vinfo
- continue
- ;;
- -version-number)
- prev=vinfo
- vinfo_number=yes
- continue
- ;;
-
- -Wc,*)
- args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
- arg=
- save_ifs="$IFS"; IFS=','
- for flag in $args; do
- IFS="$save_ifs"
- case $flag in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- flag="\"$flag\""
- ;;
- esac
- arg="$arg $wl$flag"
- compiler_flags="$compiler_flags $flag"
- done
- IFS="$save_ifs"
- arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
- ;;
-
- -Wl,*)
- args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
- arg=
- save_ifs="$IFS"; IFS=','
- for flag in $args; do
- IFS="$save_ifs"
- case $flag in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- flag="\"$flag\""
- ;;
- esac
- arg="$arg $wl$flag"
- compiler_flags="$compiler_flags $wl$flag"
- linker_flags="$linker_flags $flag"
- done
- IFS="$save_ifs"
- arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
- ;;
-
- -Xcompiler)
- prev=xcompiler
- continue
- ;;
-
- -Xlinker)
- prev=xlinker
- continue
- ;;
-
- -XCClinker)
- prev=xcclinker
- continue
- ;;
-
- # Some other compiler flag.
- -* | +*)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- ;;
-
- *.$objext)
- # A standard object.
- objs="$objs $arg"
- ;;
-
- *.lo)
- # A libtool-controlled object.
-
- # Check to see that this really is a libtool object.
- if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- pic_object=
- non_pic_object=
-
- # Read the .lo file
- # If there is no directory component, then add one.
- case $arg in
- */* | *\\*) . $arg ;;
- *) . ./$arg ;;
- esac
-
- if test -z "$pic_object" || \
- test -z "$non_pic_object" ||
- test "$pic_object" = none && \
- test "$non_pic_object" = none; then
- $echo "$modename: cannot find name of object for \`$arg'" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- if test "$pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- pic_object="$xdir$pic_object"
-
- if test "$prev" = dlfiles; then
- if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
- dlfiles="$dlfiles $pic_object"
- prev=
- continue
- else
- # If libtool objects are unsupported, then we need to preload.
- prev=dlprefiles
- fi
- fi
-
- # CHECK ME: I think I busted this. -Ossama
- if test "$prev" = dlprefiles; then
- # Preload the old-style object.
- dlprefiles="$dlprefiles $pic_object"
- prev=
- fi
-
- # A PIC object.
- libobjs="$libobjs $pic_object"
- arg="$pic_object"
- fi
-
- # Non-PIC object.
- if test "$non_pic_object" != none; then
- # Prepend the subdirectory the object is found in.
- non_pic_object="$xdir$non_pic_object"
-
- # A standard non-PIC object
- non_pic_objects="$non_pic_objects $non_pic_object"
- if test -z "$pic_object" || test "$pic_object" = none ; then
- arg="$non_pic_object"
- fi
- else
- # If the PIC object exists, use it instead.
- # $xdir was prepended to $pic_object above.
- non_pic_object="$pic_object"
- non_pic_objects="$non_pic_objects $non_pic_object"
- fi
- else
- # Only an error if not doing a dry-run.
- if test -z "$run"; then
- $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
- exit $EXIT_FAILURE
- else
- # Dry-run case.
-
- # Extract subdirectory from the argument.
- xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$xdir" = "X$arg"; then
- xdir=
- else
- xdir="$xdir/"
- fi
-
- pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
- non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
- libobjs="$libobjs $pic_object"
- non_pic_objects="$non_pic_objects $non_pic_object"
- fi
- fi
- ;;
-
- *.$libext)
- # An archive.
- deplibs="$deplibs $arg"
- old_deplibs="$old_deplibs $arg"
- continue
- ;;
-
- *.la)
- # A libtool-controlled library.
-
- if test "$prev" = dlfiles; then
- # This library was specified with -dlopen.
- dlfiles="$dlfiles $arg"
- prev=
- elif test "$prev" = dlprefiles; then
- # The library was specified with -dlpreopen.
- dlprefiles="$dlprefiles $arg"
- prev=
- else
- deplibs="$deplibs $arg"
- fi
- continue
- ;;
-
- # Some other compiler argument.
- *)
- # Unknown arguments in both finalize_command and compile_command need
- # to be aesthetically quoted because they are evaled later.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- ;;
- esac # arg
-
- # Now actually substitute the argument into the commands.
- if test -n "$arg"; then
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- fi
- done # argument parsing loop
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
- eval arg=\"$export_dynamic_flag_spec\"
- compile_command="$compile_command $arg"
- finalize_command="$finalize_command $arg"
- fi
-
- oldlibs=
- # calculate the name of the file, without its directory
- outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
- libobjs_save="$libobjs"
-
- if test -n "$shlibpath_var"; then
- # get the directories listed in $shlibpath_var
- eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
- else
- shlib_search_path=
- fi
- eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
- eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-
- output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$output_objdir" = "X$output"; then
- output_objdir="$objdir"
- else
- output_objdir="$output_objdir/$objdir"
- fi
- # Create the object directory.
- if test ! -d "$output_objdir"; then
- $show "$mkdir $output_objdir"
- $run $mkdir $output_objdir
- exit_status=$?
- if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
- exit $exit_status
- fi
- fi
-
- # Determine the type of output
- case $output in
- "")
- $echo "$modename: you must specify an output file" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
- *.$libext) linkmode=oldlib ;;
- *.lo | *.$objext) linkmode=obj ;;
- *.la) linkmode=lib ;;
- *) linkmode=prog ;; # Anything else should be a program.
- esac
-
- case $host in
- *cygwin* | *mingw* | *pw32*)
- # don't eliminate duplications in $postdeps and $predeps
- duplicate_compiler_generated_deps=yes
- ;;
- *)
- duplicate_compiler_generated_deps=$duplicate_deps
- ;;
- esac
- specialdeplibs=
-
- libs=
- # Find all interdependent deplibs by searching for libraries
- # that are linked more than once (e.g. -la -lb -la)
- for deplib in $deplibs; do
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- libs="$libs $deplib"
- done
-
- if test "$linkmode" = lib; then
- libs="$predeps $libs $compiler_lib_search_path $postdeps"
-
- # Compute libraries that are listed more than once in $predeps
- # $postdeps and mark them as special (i.e., whose duplicates are
- # not to be eliminated).
- pre_post_deps=
- if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
- for pre_post_dep in $predeps $postdeps; do
- case "$pre_post_deps " in
- *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
- esac
- pre_post_deps="$pre_post_deps $pre_post_dep"
- done
- fi
- pre_post_deps=
- fi
-
- deplibs=
- newdependency_libs=
- newlib_search_path=
- need_relink=no # whether we're linking any uninstalled libtool libraries
- notinst_deplibs= # not-installed libtool libraries
- case $linkmode in
- lib)
- passes="conv link"
- for file in $dlfiles $dlprefiles; do
- case $file in
- *.la) ;;
- *)
- $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- done
- ;;
- prog)
- compile_deplibs=
- finalize_deplibs=
- alldeplibs=no
- newdlfiles=
- newdlprefiles=
- passes="conv scan dlopen dlpreopen link"
- ;;
- *) passes="conv"
- ;;
- esac
- for pass in $passes; do
- if test "$linkmode,$pass" = "lib,link" ||
- test "$linkmode,$pass" = "prog,scan"; then
- libs="$deplibs"
- deplibs=
- fi
- if test "$linkmode" = prog; then
- case $pass in
- dlopen) libs="$dlfiles" ;;
- dlpreopen) libs="$dlprefiles" ;;
- link)
- libs="$deplibs %DEPLIBS%"
- test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
- ;;
- esac
- fi
- if test "$pass" = dlopen; then
- # Collect dlpreopened libraries
- save_deplibs="$deplibs"
- deplibs=
- fi
- for deplib in $libs; do
- lib=
- found=no
- case $deplib in
- -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- compiler_flags="$compiler_flags $deplib"
- fi
- continue
- ;;
- -l*)
- if test "$linkmode" != lib && test "$linkmode" != prog; then
- $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
- continue
- fi
- name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
- for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
- for search_ext in .la $std_shrext .so .a; do
- # Search the libtool library
- lib="$searchdir/lib${name}${search_ext}"
- if test -f "$lib"; then
- if test "$search_ext" = ".la"; then
- found=yes
- else
- found=no
- fi
- break 2
- fi
- done
- done
- if test "$found" != yes; then
- # deplib doesn't seem to be a libtool library
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
- test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
- fi
- continue
- else # deplib is a libtool library
- # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
- # We need to do some special things here, and not later.
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $deplib "*)
- if (${SED} -e '2q' $lib |
- grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- library_names=
- old_library=
- case $lib in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
- for l in $old_library $library_names; do
- ll="$l"
- done
- if test "X$ll" = "X$old_library" ; then # only static version available
- found=no
- ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
- test "X$ladir" = "X$lib" && ladir="."
- lib=$ladir/$old_library
- if test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- deplibs="$deplib $deplibs"
- test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
- fi
- continue
- fi
- fi
- ;;
- *) ;;
- esac
- fi
- fi
- ;; # -l
- -L*)
- case $linkmode in
- lib)
- deplibs="$deplib $deplibs"
- test "$pass" = conv && continue
- newdependency_libs="$deplib $newdependency_libs"
- newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- ;;
- prog)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- if test "$pass" = scan; then
- deplibs="$deplib $deplibs"
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- fi
- newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
- ;;
- *)
- $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
- ;;
- esac # linkmode
- continue
- ;; # -L
- -R*)
- if test "$pass" = link; then
- dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
- # Make sure the xrpath contains only unique directories.
- case "$xrpath " in
- *" $dir "*) ;;
- *) xrpath="$xrpath $dir" ;;
- esac
- fi
- deplibs="$deplib $deplibs"
- continue
- ;;
- *.la) lib="$deplib" ;;
- *.$libext)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- case $linkmode in
- lib)
- valid_a_lib=no
- case $deplibs_check_method in
- match_pattern*)
- set dummy $deplibs_check_method
- match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- if eval $echo \"$deplib\" 2>/dev/null \
- | $SED 10q \
- | $EGREP "$match_pattern_regex" > /dev/null; then
- valid_a_lib=yes
- fi
- ;;
- pass_all)
- valid_a_lib=yes
- ;;
- esac
- if test "$valid_a_lib" != yes; then
- $echo
- $echo "*** Warning: Trying to link with static lib archive $deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because the file extensions .$libext of this argument makes me believe"
- $echo "*** that it is just a static archive that I should not used here."
- else
- $echo
- $echo "*** Warning: Linking the shared library $output against the"
- $echo "*** static library $deplib is not portable!"
- deplibs="$deplib $deplibs"
- fi
- continue
- ;;
- prog)
- if test "$pass" != link; then
- deplibs="$deplib $deplibs"
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- fi
- continue
- ;;
- esac # linkmode
- ;; # *.$libext
- *.lo | *.$objext)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- elif test "$linkmode" = prog; then
- if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
- # If there is no dlopen support or we're linking statically,
- # we need to preload.
- newdlprefiles="$newdlprefiles $deplib"
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
- else
- newdlfiles="$newdlfiles $deplib"
- fi
- fi
- continue
- ;;
- %DEPLIBS%)
- alldeplibs=yes
- continue
- ;;
- esac # case $deplib
- if test "$found" = yes || test -f "$lib"; then :
- else
- $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
-
- ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
- test "X$ladir" = "X$lib" && ladir="."
-
- dlname=
- dlopen=
- dlpreopen=
- libdir=
- library_names=
- old_library=
- # If the library was installed with an old release of libtool,
- # it will not redefine variables installed, or shouldnotlink
- installed=yes
- shouldnotlink=no
- avoidtemprpath=
-
-
- # Read the .la file
- case $lib in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
-
- if test "$linkmode,$pass" = "lib,link" ||
- test "$linkmode,$pass" = "prog,scan" ||
- { test "$linkmode" != prog && test "$linkmode" != lib; }; then
- test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
- test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
- fi
-
- if test "$pass" = conv; then
- # Only check for convenience libraries
- deplibs="$lib $deplibs"
- if test -z "$libdir"; then
- if test -z "$old_library"; then
- $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
- exit $EXIT_FAILURE
- fi
- # It is a libtool convenience library, so add in its objects.
- convenience="$convenience $ladir/$objdir/$old_library"
- old_convenience="$old_convenience $ladir/$objdir/$old_library"
- tmp_libs=
- for deplib in $dependency_libs; do
- deplibs="$deplib $deplibs"
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done
- elif test "$linkmode" != prog && test "$linkmode" != lib; then
- $echo "$modename: \`$lib' is not a convenience library" 1>&2
- exit $EXIT_FAILURE
- fi
- continue
- fi # $pass = conv
-
-
- # Get the name of the library we link against.
- linklib=
- for l in $old_library $library_names; do
- linklib="$l"
- done
- if test -z "$linklib"; then
- $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # This library was specified with -dlopen.
- if test "$pass" = dlopen; then
- if test -z "$libdir"; then
- $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
- exit $EXIT_FAILURE
- fi
- if test -z "$dlname" ||
- test "$dlopen_support" != yes ||
- test "$build_libtool_libs" = no; then
- # If there is no dlname, no dlopen support or we're linking
- # statically, we need to preload. We also need to preload any
- # dependent libraries so libltdl's deplib preloader doesn't
- # bomb out in the load deplibs phase.
- dlprefiles="$dlprefiles $lib $dependency_libs"
- else
- newdlfiles="$newdlfiles $lib"
- fi
- continue
- fi # $pass = dlopen
-
- # We need an absolute path.
- case $ladir in
- [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
- *)
- abs_ladir=`cd "$ladir" && pwd`
- if test -z "$abs_ladir"; then
- $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
- $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
- abs_ladir="$ladir"
- fi
- ;;
- esac
- laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
-
- # Find the relevant object directory and library name.
- if test "X$installed" = Xyes; then
- if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
- $echo "$modename: warning: library \`$lib' was moved." 1>&2
- dir="$ladir"
- absdir="$abs_ladir"
- libdir="$abs_ladir"
- else
- dir="$libdir"
- absdir="$libdir"
- fi
- test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
- else
- if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
- dir="$ladir"
- absdir="$abs_ladir"
- # Remove this search path later
- notinst_path="$notinst_path $abs_ladir"
- else
- dir="$ladir/$objdir"
- absdir="$abs_ladir/$objdir"
- # Remove this search path later
- notinst_path="$notinst_path $abs_ladir"
- fi
- fi # $installed = yes
- name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-
- # This library was specified with -dlpreopen.
- if test "$pass" = dlpreopen; then
- if test -z "$libdir"; then
- $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
- exit $EXIT_FAILURE
- fi
- # Prefer using a static library (so that no silly _DYNAMIC symbols
- # are required to link).
- if test -n "$old_library"; then
- newdlprefiles="$newdlprefiles $dir/$old_library"
- # Otherwise, use the dlname, so that lt_dlopen finds it.
- elif test -n "$dlname"; then
- newdlprefiles="$newdlprefiles $dir/$dlname"
- else
- newdlprefiles="$newdlprefiles $dir/$linklib"
- fi
- fi # $pass = dlpreopen
-
- if test -z "$libdir"; then
- # Link the convenience library
- if test "$linkmode" = lib; then
- deplibs="$dir/$old_library $deplibs"
- elif test "$linkmode,$pass" = "prog,link"; then
- compile_deplibs="$dir/$old_library $compile_deplibs"
- finalize_deplibs="$dir/$old_library $finalize_deplibs"
- else
- deplibs="$lib $deplibs" # used for prog,scan pass
- fi
- continue
- fi
-
-
- if test "$linkmode" = prog && test "$pass" != link; then
- newlib_search_path="$newlib_search_path $ladir"
- deplibs="$lib $deplibs"
-
- linkalldeplibs=no
- if test "$link_all_deplibs" != no || test -z "$library_names" ||
- test "$build_libtool_libs" = no; then
- linkalldeplibs=yes
- fi
-
- tmp_libs=
- for deplib in $dependency_libs; do
- case $deplib in
- -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
- esac
- # Need to link against all dependency_libs?
- if test "$linkalldeplibs" = yes; then
- deplibs="$deplib $deplibs"
- else
- # Need to hardcode shared library paths
- # or/and link against static libraries
- newdependency_libs="$deplib $newdependency_libs"
- fi
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done # for deplib
- continue
- fi # $linkmode = prog...
-
- if test "$linkmode,$pass" = "prog,link"; then
- if test -n "$library_names" &&
- { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
- # We need to hardcode the library path
- if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
- # Make sure the rpath contains only unique directories.
- case "$temp_rpath " in
- *" $dir "*) ;;
- *" $absdir "*) ;;
- *) temp_rpath="$temp_rpath $absdir" ;;
- esac
- fi
-
- # Hardcode the library path.
- # Skip directories that are in the system default run-time
- # search path.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
- esac
- ;;
- esac
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
- esac
- ;;
- esac
- fi # $linkmode,$pass = prog,link...
-
- if test "$alldeplibs" = yes &&
- { test "$deplibs_check_method" = pass_all ||
- { test "$build_libtool_libs" = yes &&
- test -n "$library_names"; }; }; then
- # We only need to search for static libraries
- continue
- fi
- fi
-
- link_static=no # Whether the deplib will be linked statically
- use_static_libs=$prefer_static_libs
- if test "$use_static_libs" = built && test "$installed" = yes ; then
- use_static_libs=no
- fi
- if test -n "$library_names" &&
- { test "$use_static_libs" = no || test -z "$old_library"; }; then
- if test "$installed" = no; then
- notinst_deplibs="$notinst_deplibs $lib"
- need_relink=yes
- fi
- # This is a shared library
-
- # Warn about portability, can't link against -module's on
- # some systems (darwin)
- if test "$shouldnotlink" = yes && test "$pass" = link ; then
- $echo
- if test "$linkmode" = prog; then
- $echo "*** Warning: Linking the executable $output against the loadable module"
- else
- $echo "*** Warning: Linking the shared library $output against the loadable module"
- fi
- $echo "*** $linklib is not portable!"
- fi
- if test "$linkmode" = lib &&
- test "$hardcode_into_libs" = yes; then
- # Hardcode the library path.
- # Skip directories that are in the system default run-time
- # search path.
- case " $sys_lib_dlsearch_path " in
- *" $absdir "*) ;;
- *)
- case "$compile_rpath " in
- *" $absdir "*) ;;
- *) compile_rpath="$compile_rpath $absdir"
- esac
- ;;
- esac
- case " $sys_lib_dlsearch_path " in
- *" $libdir "*) ;;
- *)
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir"
- esac
- ;;
- esac
- fi
-
- if test -n "$old_archive_from_expsyms_cmds"; then
- # figure out the soname
- set dummy $library_names
- realname="$2"
- shift; shift
- libname=`eval \\$echo \"$libname_spec\"`
- # use dlname if we got it. it's perfectly good, no?
- if test -n "$dlname"; then
- soname="$dlname"
- elif test -n "$soname_spec"; then
- # bleh windows
- case $host in
- *cygwin* | mingw*)
- major=`expr $current - $age`
- versuffix="-$major"
- ;;
- esac
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
-
- # Make a new name for the extract_expsyms_cmds to use
- soroot="$soname"
- soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
- newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
-
- # If the library has no export list, then create one now
- if test -f "$output_objdir/$soname-def"; then :
- else
- $show "extracting exported symbol list from \`$soname'"
- save_ifs="$IFS"; IFS='~'
- cmds=$extract_expsyms_cmds
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
-
- # Create $newlib
- if test -f "$output_objdir/$newlib"; then :; else
- $show "generating import library for \`$soname'"
- save_ifs="$IFS"; IFS='~'
- cmds=$old_archive_from_expsyms_cmds
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
- # make sure the library variables are pointing to the new library
- dir=$output_objdir
- linklib=$newlib
- fi # test -n "$old_archive_from_expsyms_cmds"
-
- if test "$linkmode" = prog || test "$mode" != relink; then
- add_shlibpath=
- add_dir=
- add=
- lib_linked=yes
- case $hardcode_action in
- immediate | unsupported)
- if test "$hardcode_direct" = no; then
- add="$dir/$linklib"
- case $host in
- *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
- *-*-sysv4*uw2*) add_dir="-L$dir" ;;
- *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
- *-*-unixware7*) add_dir="-L$dir" ;;
- *-*-darwin* )
- # if the lib is a module then we can not link against
- # it, someone is ignoring the new warnings I added
- if /usr/bin/file -L $add 2> /dev/null |
- $EGREP ": [^:]* bundle" >/dev/null ; then
- $echo "** Warning, lib $linklib is a module, not a shared library"
- if test -z "$old_library" ; then
- $echo
- $echo "** And there doesn't seem to be a static archive available"
- $echo "** The link will probably fail, sorry"
- else
- add="$dir/$old_library"
- fi
- fi
- esac
- elif test "$hardcode_minus_L" = no; then
- case $host in
- *-*-sunos*) add_shlibpath="$dir" ;;
- esac
- add_dir="-L$dir"
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = no; then
- add_shlibpath="$dir"
- add="-l$name"
- else
- lib_linked=no
- fi
- ;;
- relink)
- if test "$hardcode_direct" = yes; then
- add="$dir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- add_dir="-L$dir"
- # Try looking first in the location we're being installed to.
- if test -n "$inst_prefix_dir"; then
- case $libdir in
- [\\/]*)
- add_dir="$add_dir -L$inst_prefix_dir$libdir"
- ;;
- esac
- fi
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- add_shlibpath="$dir"
- add="-l$name"
- else
- lib_linked=no
- fi
- ;;
- *) lib_linked=no ;;
- esac
-
- if test "$lib_linked" != yes; then
- $echo "$modename: configuration error: unsupported hardcode properties"
- exit $EXIT_FAILURE
- fi
-
- if test -n "$add_shlibpath"; then
- case :$compile_shlibpath: in
- *":$add_shlibpath:"*) ;;
- *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
- esac
- fi
- if test "$linkmode" = prog; then
- test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
- test -n "$add" && compile_deplibs="$add $compile_deplibs"
- else
- test -n "$add_dir" && deplibs="$add_dir $deplibs"
- test -n "$add" && deplibs="$add $deplibs"
- if test "$hardcode_direct" != yes && \
- test "$hardcode_minus_L" != yes && \
- test "$hardcode_shlibpath_var" = yes; then
- case :$finalize_shlibpath: in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
- esac
- fi
- fi
- fi
-
- if test "$linkmode" = prog || test "$mode" = relink; then
- add_shlibpath=
- add_dir=
- add=
- # Finalize command for both is simple: just hardcode it.
- if test "$hardcode_direct" = yes; then
- add="$libdir/$linklib"
- elif test "$hardcode_minus_L" = yes; then
- add_dir="-L$libdir"
- add="-l$name"
- elif test "$hardcode_shlibpath_var" = yes; then
- case :$finalize_shlibpath: in
- *":$libdir:"*) ;;
- *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
- esac
- add="-l$name"
- elif test "$hardcode_automatic" = yes; then
- if test -n "$inst_prefix_dir" &&
- test -f "$inst_prefix_dir$libdir/$linklib" ; then
- add="$inst_prefix_dir$libdir/$linklib"
- else
- add="$libdir/$linklib"
- fi
- else
- # We cannot seem to hardcode it, guess we'll fake it.
- add_dir="-L$libdir"
- # Try looking first in the location we're being installed to.
- if test -n "$inst_prefix_dir"; then
- case $libdir in
- [\\/]*)
- add_dir="$add_dir -L$inst_prefix_dir$libdir"
- ;;
- esac
- fi
- add="-l$name"
- fi
-
- if test "$linkmode" = prog; then
- test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
- test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
- else
- test -n "$add_dir" && deplibs="$add_dir $deplibs"
- test -n "$add" && deplibs="$add $deplibs"
- fi
- fi
- elif test "$linkmode" = prog; then
- # Here we assume that one of hardcode_direct or hardcode_minus_L
- # is not unsupported. This is valid on all known static and
- # shared platforms.
- if test "$hardcode_direct" != unsupported; then
- test -n "$old_library" && linklib="$old_library"
- compile_deplibs="$dir/$linklib $compile_deplibs"
- finalize_deplibs="$dir/$linklib $finalize_deplibs"
- else
- compile_deplibs="-l$name -L$dir $compile_deplibs"
- finalize_deplibs="-l$name -L$dir $finalize_deplibs"
- fi
- elif test "$build_libtool_libs" = yes; then
- # Not a shared library
- if test "$deplibs_check_method" != pass_all; then
- # We're trying link a shared library against a static one
- # but the system doesn't support it.
-
- # Just print a warning and add the library to dependency_libs so
- # that the program can be linked against the static library.
- $echo
- $echo "*** Warning: This system can not link to static lib archive $lib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have."
- if test "$module" = yes; then
- $echo "*** But as you try to build a module library, libtool will still create "
- $echo "*** a static module, that should work as long as the dlopening application"
- $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
- if test -z "$global_symbol_pipe"; then
- $echo
- $echo "*** However, this would only work if libtool was able to extract symbol"
- $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $echo "*** not find such a program. So, this module is probably useless."
- $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- else
- deplibs="$dir/$old_library $deplibs"
- link_static=yes
- fi
- fi # link shared/static library?
-
- if test "$linkmode" = lib; then
- if test -n "$dependency_libs" &&
- { test "$hardcode_into_libs" != yes ||
- test "$build_old_libs" = yes ||
- test "$link_static" = yes; }; then
- # Extract -R from dependency_libs
- temp_deplibs=
- for libdir in $dependency_libs; do
- case $libdir in
- -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
- case " $xrpath " in
- *" $temp_xrpath "*) ;;
- *) xrpath="$xrpath $temp_xrpath";;
- esac;;
- *) temp_deplibs="$temp_deplibs $libdir";;
- esac
- done
- dependency_libs="$temp_deplibs"
- fi
-
- newlib_search_path="$newlib_search_path $absdir"
- # Link against this library
- test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
- # ... and its dependency_libs
- tmp_libs=
- for deplib in $dependency_libs; do
- newdependency_libs="$deplib $newdependency_libs"
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done
-
- if test "$link_all_deplibs" != no; then
- # Add the search paths of all dependency libraries
- for deplib in $dependency_libs; do
- case $deplib in
- -L*) path="$deplib" ;;
- *.la)
- dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$deplib" && dir="."
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
- absdir="$dir"
- fi
- ;;
- esac
- if grep "^installed=no" $deplib > /dev/null; then
- path="$absdir/$objdir"
- else
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- if test "$absdir" != "$libdir"; then
- $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
- fi
- path="$absdir"
- fi
- depdepl=
- case $host in
- *-*-darwin*)
- # we do not want to link against static libs,
- # but need to link against shared
- eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
- if test -n "$deplibrary_names" ; then
- for tmp in $deplibrary_names ; do
- depdepl=$tmp
- done
- if test -f "$path/$depdepl" ; then
- depdepl="$path/$depdepl"
- fi
- # do not add paths which are already there
- case " $newlib_search_path " in
- *" $path "*) ;;
- *) newlib_search_path="$newlib_search_path $path";;
- esac
- fi
- path=""
- ;;
- *)
- path="-L$path"
- ;;
- esac
- ;;
- -l*)
- case $host in
- *-*-darwin*)
- # Again, we only want to link against shared libraries
- eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
- for tmp in $newlib_search_path ; do
- if test -f "$tmp/lib$tmp_libs.dylib" ; then
- eval depdepl="$tmp/lib$tmp_libs.dylib"
- break
- fi
- done
- path=""
- ;;
- *) continue ;;
- esac
- ;;
- *) continue ;;
- esac
- case " $deplibs " in
- *" $path "*) ;;
- *) deplibs="$path $deplibs" ;;
- esac
- case " $deplibs " in
- *" $depdepl "*) ;;
- *) deplibs="$depdepl $deplibs" ;;
- esac
- done
- fi # link_all_deplibs != no
- fi # linkmode = lib
- done # for deplib in $libs
- dependency_libs="$newdependency_libs"
- if test "$pass" = dlpreopen; then
- # Link the dlpreopened libraries before other libraries
- for deplib in $save_deplibs; do
- deplibs="$deplib $deplibs"
- done
- fi
- if test "$pass" != dlopen; then
- if test "$pass" != conv; then
- # Make sure lib_search_path contains only unique directories.
- lib_search_path=
- for dir in $newlib_search_path; do
- case "$lib_search_path " in
- *" $dir "*) ;;
- *) lib_search_path="$lib_search_path $dir" ;;
- esac
- done
- newlib_search_path=
- fi
-
- if test "$linkmode,$pass" != "prog,link"; then
- vars="deplibs"
- else
- vars="compile_deplibs finalize_deplibs"
- fi
- for var in $vars dependency_libs; do
- # Add libraries to $var in reverse order
- eval tmp_libs=\"\$$var\"
- new_libs=
- for deplib in $tmp_libs; do
- # FIXME: Pedantically, this is the right thing to do, so
- # that some nasty dependency loop isn't accidentally
- # broken:
- #new_libs="$deplib $new_libs"
- # Pragmatically, this seems to cause very few problems in
- # practice:
- case $deplib in
- -L*) new_libs="$deplib $new_libs" ;;
- -R*) ;;
- *)
- # And here is the reason: when a library appears more
- # than once as an explicit dependence of a library, or
- # is implicitly linked in more than once by the
- # compiler, it is considered special, and multiple
- # occurrences thereof are not removed. Compare this
- # with having the same library being listed as a
- # dependency of multiple other libraries: in this case,
- # we know (pedantically, we assume) the library does not
- # need to be listed more than once, so we keep only the
- # last copy. This is not always right, but it is rare
- # enough that we require users that really mean to play
- # such unportable linking tricks to link the library
- # using -Wl,-lname, so that libtool does not consider it
- # for duplicate removal.
- case " $specialdeplibs " in
- *" $deplib "*) new_libs="$deplib $new_libs" ;;
- *)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$deplib $new_libs" ;;
- esac
- ;;
- esac
- ;;
- esac
- done
- tmp_libs=
- for deplib in $new_libs; do
- case $deplib in
- -L*)
- case " $tmp_libs " in
- *" $deplib "*) ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- done
- eval $var=\"$tmp_libs\"
- done # for var
- fi
- # Last step: remove runtime libs from dependency_libs
- # (they stay in deplibs)
- tmp_libs=
- for i in $dependency_libs ; do
- case " $predeps $postdeps $compiler_lib_search_path " in
- *" $i "*)
- i=""
- ;;
- esac
- if test -n "$i" ; then
- tmp_libs="$tmp_libs $i"
- fi
- done
- dependency_libs=$tmp_libs
- done # for pass
- if test "$linkmode" = prog; then
- dlfiles="$newdlfiles"
- dlprefiles="$newdlprefiles"
- fi
-
- case $linkmode in
- oldlib)
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
- fi
-
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
- fi
-
- # Now set the variables for building old libraries.
- build_libtool_libs=no
- oldlibs="$output"
- objs="$objs$old_deplibs"
- ;;
-
- lib)
- # Make sure we only generate libraries of the form `libNAME.la'.
- case $outputname in
- lib*)
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
- eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- ;;
- *)
- if test "$module" = no; then
- $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
- if test "$need_lib_prefix" != no; then
- # Add the "lib" prefix for modules if required
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- else
- libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- fi
- ;;
- esac
-
- if test -n "$objs"; then
- if test "$deplibs_check_method" != pass_all; then
- $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
- exit $EXIT_FAILURE
- else
- $echo
- $echo "*** Warning: Linking the shared library $output against the non-libtool"
- $echo "*** objects $objs is not portable!"
- libobjs="$libobjs $objs"
- fi
- fi
-
- if test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
- fi
-
- set dummy $rpath
- if test "$#" -gt 2; then
- $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
- fi
- install_libdir="$2"
-
- oldlibs=
- if test -z "$rpath"; then
- if test "$build_libtool_libs" = yes; then
- # Building a libtool convenience library.
- # Some compilers have problems with a `.al' extension so
- # convenience libraries should have the same extension an
- # archive normally would.
- oldlibs="$output_objdir/$libname.$libext $oldlibs"
- build_libtool_libs=convenience
- build_old_libs=yes
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
- fi
- else
-
- # Parse the version information argument.
- save_ifs="$IFS"; IFS=':'
- set dummy $vinfo 0 0 0
- IFS="$save_ifs"
-
- if test -n "$8"; then
- $echo "$modename: too many parameters to \`-version-info'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # convert absolute version numbers to libtool ages
- # this retains compatibility with .la files and attempts
- # to make the code below a bit more comprehensible
-
- case $vinfo_number in
- yes)
- number_major="$2"
- number_minor="$3"
- number_revision="$4"
- #
- # There are really only two kinds -- those that
- # use the current revision as the major version
- # and those that subtract age and use age as
- # a minor version. But, then there is irix
- # which has an extra 1 added just for fun
- #
- case $version_type in
- darwin|linux|osf|windows)
- current=`expr $number_major + $number_minor`
- age="$number_minor"
- revision="$number_revision"
- ;;
- freebsd-aout|freebsd-elf|sunos)
- current="$number_major"
- revision="$number_minor"
- age="0"
- ;;
- irix|nonstopux)
- current=`expr $number_major + $number_minor - 1`
- age="$number_minor"
- revision="$number_minor"
- ;;
- *)
- $echo "$modename: unknown library version type \`$version_type'" 1>&2
- $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- ;;
- no)
- current="$2"
- revision="$3"
- age="$4"
- ;;
- esac
-
- # Check that each of the things are valid numbers.
- case $current in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- case $revision in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- case $age in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- if test "$age" -gt "$current"; then
- $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Calculate the version variables.
- major=
- versuffix=
- verstring=
- case $version_type in
- none) ;;
-
- darwin)
- # Like Linux, but with the current version available in
- # verstring for coding it into the library header
- major=.`expr $current - $age`
- versuffix="$major.$age.$revision"
- # Darwin ld doesn't like 0 for these options...
- minor_current=`expr $current + 1`
- verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
- ;;
-
- freebsd-aout)
- major=".$current"
- versuffix=".$current.$revision";
- ;;
-
- freebsd-elf)
- major=".$current"
- versuffix=".$current";
- ;;
-
- irix | nonstopux)
- major=`expr $current - $age + 1`
-
- case $version_type in
- nonstopux) verstring_prefix=nonstopux ;;
- *) verstring_prefix=sgi ;;
- esac
- verstring="$verstring_prefix$major.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$revision
- while test "$loop" -ne 0; do
- iface=`expr $revision - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring_prefix$major.$iface:$verstring"
- done
-
- # Before this point, $major must not contain `.'.
- major=.$major
- versuffix="$major.$revision"
- ;;
-
- linux)
- major=.`expr $current - $age`
- versuffix="$major.$age.$revision"
- ;;
-
- osf)
- major=.`expr $current - $age`
- versuffix=".$current.$age.$revision"
- verstring="$current.$age.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$age
- while test "$loop" -ne 0; do
- iface=`expr $current - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring:${iface}.0"
- done
-
- # Make executables depend on our current version.
- verstring="$verstring:${current}.0"
- ;;
-
- sunos)
- major=".$current"
- versuffix=".$current.$revision"
- ;;
-
- windows)
- # Use '-' rather than '.', since we only want one
- # extension on DOS 8.3 filesystems.
- major=`expr $current - $age`
- versuffix="-$major"
- ;;
-
- *)
- $echo "$modename: unknown library version type \`$version_type'" 1>&2
- $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- # Clear the version info if we defaulted, and they specified a release.
- if test -z "$vinfo" && test -n "$release"; then
- major=
- case $version_type in
- darwin)
- # we can't check for "0.0" in archive_cmds due to quoting
- # problems, so we reset it completely
- verstring=
- ;;
- *)
- verstring="0.0"
- ;;
- esac
- if test "$need_version" = no; then
- versuffix=
- else
- versuffix=".0.0"
- fi
- fi
-
- # Remove version info from name if versioning should be avoided
- if test "$avoid_version" = yes && test "$need_version" = no; then
- major=
- versuffix=
- verstring=""
- fi
-
- # Check to see if the archive will have undefined symbols.
- if test "$allow_undefined" = yes; then
- if test "$allow_undefined_flag" = unsupported; then
- $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
- build_libtool_libs=no
- build_old_libs=yes
- fi
- else
- # Don't allow undefined symbols.
- allow_undefined_flag="$no_undefined_flag"
- fi
- fi
-
- if test "$mode" != relink; then
- # Remove our outputs, but don't remove object files since they
- # may have been created when compiling PIC objects.
- removelist=
- tempremovelist=`$echo "$output_objdir/*"`
- for p in $tempremovelist; do
- case $p in
- *.$objext)
- ;;
- $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
- if test "X$precious_files_regex" != "X"; then
- if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
- then
- continue
- fi
- fi
- removelist="$removelist $p"
- ;;
- *) ;;
- esac
- done
- if test -n "$removelist"; then
- $show "${rm}r $removelist"
- $run ${rm}r $removelist
- fi
- fi
-
- # Now set the variables for building old libraries.
- if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
- oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
- # Transform .lo files to .o files.
- oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
- fi
-
- # Eliminate all temporary directories.
- for path in $notinst_path; do
- lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
- deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
- dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
- done
-
- if test -n "$xrpath"; then
- # If the user specified any rpath flags, then add them.
- temp_xrpath=
- for libdir in $xrpath; do
- temp_xrpath="$temp_xrpath -R$libdir"
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
- dependency_libs="$temp_xrpath $dependency_libs"
- fi
- fi
-
- # Make sure dlfiles contains only unique files that won't be dlpreopened
- old_dlfiles="$dlfiles"
- dlfiles=
- for lib in $old_dlfiles; do
- case " $dlprefiles $dlfiles " in
- *" $lib "*) ;;
- *) dlfiles="$dlfiles $lib" ;;
- esac
- done
-
- # Make sure dlprefiles contains only unique files
- old_dlprefiles="$dlprefiles"
- dlprefiles=
- for lib in $old_dlprefiles; do
- case "$dlprefiles " in
- *" $lib "*) ;;
- *) dlprefiles="$dlprefiles $lib" ;;
- esac
- done
-
- if test "$build_libtool_libs" = yes; then
- if test -n "$rpath"; then
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
- # these systems don't actually have a c library (as such)!
- ;;
- *-*-rhapsody* | *-*-darwin1.[012])
- # Rhapsody C library is in the System framework
- deplibs="$deplibs -framework System"
- ;;
- *-*-netbsd*)
- # Don't link with libc until the a.out ld.so is fixed.
- ;;
- *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc due to us having libc/libc_r.
- ;;
- *-*-sco3.2v5* | *-*-sco5v6*)
- # Causes problems with __ctype
- ;;
- *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
- # Compiler inserts libc in the correct place for threads to work
- ;;
- *)
- # Add libc to deplibs on all other systems if necessary.
- if test "$build_libtool_need_lc" = "yes"; then
- deplibs="$deplibs -lc"
- fi
- ;;
- esac
- fi
-
- # Transform deplibs into only deplibs that can be linked in shared.
- name_save=$name
- libname_save=$libname
- release_save=$release
- versuffix_save=$versuffix
- major_save=$major
- # I'm not sure if I'm treating the release correctly. I think
- # release should show up in the -l (ie -lgmp5) so we don't want to
- # add it in twice. Is that correct?
- release=""
- versuffix=""
- major=""
- newdeplibs=
- droppeddeps=no
- case $deplibs_check_method in
- pass_all)
- # Don't check for shared/static. Everything works.
- # This might be a little naive. We might want to check
- # whether the library exists or not. But this is on
- # osf3 & osf4 and I'm not really sure... Just
- # implementing what was already the behavior.
- newdeplibs=$deplibs
- ;;
- test_compile)
- # This code stresses the "libraries are programs" paradigm to its
- # limits. Maybe even breaks it. We compile a program, linking it
- # against the deplibs as a proxy for the library. Then we can check
- # whether they linked in statically or dynamically with ldd.
- $rm conftest.c
- cat > conftest.c <<EOF
- int main() { return 0; }
-EOF
- $rm conftest
- $LTCC $LTCFLAGS -o conftest conftest.c $deplibs
- if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
- for i in $deplibs; do
- name=`expr $i : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" -ne "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning: dynamic linker does not accept needed library $i."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which I believe you do not have"
- $echo "*** because a test_compile did reveal that the linker did not use it for"
- $echo "*** its dynamic dependency list that programs get resolved with at runtime."
- fi
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- else
- # Error occurred in the first compile. Let's try to salvage
- # the situation: Compile a separate program for each library.
- for i in $deplibs; do
- name=`expr $i : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" != "0"; then
- $rm conftest
- $LTCC $LTCFLAGS -o conftest conftest.c $i
- # Did it work?
- if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning: dynamic linker does not accept needed library $i."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because a test_compile did reveal that the linker did not use this one"
- $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
- fi
- fi
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning! Library $i is needed by this library but I was not able to"
- $echo "*** make it link in! You will probably need to install it or some"
- $echo "*** library that it depends on before this library will be fully"
- $echo "*** functional. Installing it before continuing would be even better."
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- fi
- ;;
- file_magic*)
- set dummy $deplibs_check_method
- file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
- name=`expr $a_deplib : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" != "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- # Follow soft links.
- if ls -lLd "$potent_lib" 2>/dev/null \
- | grep " -> " >/dev/null; then
- continue
- fi
- # The statement above tries to avoid entering an
- # endless loop below, in case of cyclic links.
- # We might still enter an endless loop, since a link
- # loop can be closed while we follow links,
- # but so what?
- potlib="$potent_lib"
- while test -h "$potlib" 2>/dev/null; do
- potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
- case $potliblink in
- [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
- *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
- esac
- done
- if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
- | ${SED} 10q \
- | $EGREP "$file_magic_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $echo
- $echo "*** Warning: linker path does not have real file for library $a_deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $echo "*** with $libname but no candidates were found. (...for file magic test)"
- else
- $echo "*** with $libname and none of the candidates passed a file format test"
- $echo "*** using a file magic. Last file checked: $potlib"
- fi
- fi
- else
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- fi
- done # Gone through all deplibs.
- ;;
- match_pattern*)
- set dummy $deplibs_check_method
- match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
- name=`expr $a_deplib : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test -n "$name" && test "$name" != "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- potlib="$potent_lib" # see symlink-check above in file_magic test
- if eval $echo \"$potent_lib\" 2>/dev/null \
- | ${SED} 10q \
- | $EGREP "$match_pattern_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $echo
- $echo "*** Warning: linker path does not have real file for library $a_deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
- else
- $echo "*** with $libname and none of the candidates passed a file format test"
- $echo "*** using a regex pattern. Last file checked: $potlib"
- fi
- fi
- else
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- fi
- done # Gone through all deplibs.
- ;;
- none | unknown | *)
- newdeplibs=""
- tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
- -e 's/ -[LR][^ ]*//g'`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- for i in $predeps $postdeps ; do
- # can't use Xsed below, because $i might contain '/'
- tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
- done
- fi
- if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
- | grep . >/dev/null; then
- $echo
- if test "X$deplibs_check_method" = "Xnone"; then
- $echo "*** Warning: inter-library dependencies are not supported in this platform."
- else
- $echo "*** Warning: inter-library dependencies are not known to be supported."
- fi
- $echo "*** All declared inter-library dependencies are being dropped."
- droppeddeps=yes
- fi
- ;;
- esac
- versuffix=$versuffix_save
- major=$major_save
- release=$release_save
- libname=$libname_save
- name=$name_save
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library is the System framework
- newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
- ;;
- esac
-
- if test "$droppeddeps" = yes; then
- if test "$module" = yes; then
- $echo
- $echo "*** Warning: libtool could not satisfy all declared inter-library"
- $echo "*** dependencies of module $libname. Therefore, libtool will create"
- $echo "*** a static module, that should work as long as the dlopening"
- $echo "*** application is linked with the -dlopen flag."
- if test -z "$global_symbol_pipe"; then
- $echo
- $echo "*** However, this would only work if libtool was able to extract symbol"
- $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $echo "*** not find such a program. So, this module is probably useless."
- $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- else
- $echo "*** The inter-library dependencies that have been dropped here will be"
- $echo "*** automatically added whenever a program is linked with this library"
- $echo "*** or is declared to -dlopen it."
-
- if test "$allow_undefined" = no; then
- $echo
- $echo "*** Since this library must not contain undefined symbols,"
- $echo "*** because either the platform does not support them or"
- $echo "*** it was explicitly requested with -no-undefined,"
- $echo "*** libtool will only create a static version of it."
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- fi
- fi
- # Done checking deplibs!
- deplibs=$newdeplibs
- fi
-
-
- # move library search paths that coincide with paths to not yet
- # installed libraries to the beginning of the library search list
- new_libs=
- for path in $notinst_path; do
- case " $new_libs " in
- *" -L$path/$objdir "*) ;;
- *)
- case " $deplibs " in
- *" -L$path/$objdir "*)
- new_libs="$new_libs -L$path/$objdir" ;;
- esac
- ;;
- esac
- done
- for deplib in $deplibs; do
- case $deplib in
- -L*)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- done
- deplibs="$new_libs"
-
-
- # All the library-specific variables (install_libdir is set above).
- library_names=
- old_library=
- dlname=
-
- # Test again, we may have decided not to build it any more
- if test "$build_libtool_libs" = yes; then
- if test "$hardcode_into_libs" = yes; then
- # Hardcode the library paths
- hardcode_libdirs=
- dep_rpath=
- rpath="$finalize_rpath"
- test "$mode" != relink && rpath="$compile_rpath$rpath"
- for libdir in $rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- dep_rpath="$dep_rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- if test -n "$hardcode_libdir_flag_spec_ld"; then
- eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
- else
- eval dep_rpath=\"$hardcode_libdir_flag_spec\"
- fi
- fi
- if test -n "$runpath_var" && test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
- fi
- test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
- fi
-
- shlibpath="$finalize_shlibpath"
- test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
- if test -n "$shlibpath"; then
- eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
- fi
-
- # Get the real and link names of the library.
- eval shared_ext=\"$shrext_cmds\"
- eval library_names=\"$library_names_spec\"
- set dummy $library_names
- realname="$2"
- shift; shift
-
- if test -n "$soname_spec"; then
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
- if test -z "$dlname"; then
- dlname=$soname
- fi
-
- lib="$output_objdir/$realname"
- linknames=
- for link
- do
- linknames="$linknames $link"
- done
-
- # Use standard objects if they are pic
- test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
- cmds=$export_symbols_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- if len=`expr "X$cmd" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- $show "$cmd"
- $run eval "$cmd" || exit $?
- skipped_export=false
- else
- # The command line is too long to execute in one step.
- $show "using reloadable object file for export list..."
- skipped_export=:
- # Break out early, otherwise skipped_export may be
- # set to false by a later but shorter cmd.
- break
- fi
- done
- IFS="$save_ifs"
- if test -n "$export_symbols_regex"; then
- $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
- $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
- $show "$mv \"${export_symbols}T\" \"$export_symbols\""
- $run eval '$mv "${export_symbols}T" "$export_symbols"'
- fi
- fi
- fi
-
- if test -n "$export_symbols" && test -n "$include_expsyms"; then
- $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
- fi
-
- tmp_deplibs=
- for test_deplib in $deplibs; do
- case " $convenience " in
- *" $test_deplib "*) ;;
- *)
- tmp_deplibs="$tmp_deplibs $test_deplib"
- ;;
- esac
- done
- deplibs="$tmp_deplibs"
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- else
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $convenience
- libobjs="$libobjs $func_extract_archives_result"
- fi
- fi
-
- if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
- eval flag=\"$thread_safe_flag_spec\"
- linker_flags="$linker_flags $flag"
- fi
-
- # Make a backup of the uninstalled library when relinking
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
- fi
-
- # Do each of the archive commands.
- if test "$module" = yes && test -n "$module_cmds" ; then
- if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
- eval test_cmds=\"$module_expsym_cmds\"
- cmds=$module_expsym_cmds
- else
- eval test_cmds=\"$module_cmds\"
- cmds=$module_cmds
- fi
- else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- eval test_cmds=\"$archive_expsym_cmds\"
- cmds=$archive_expsym_cmds
- else
- eval test_cmds=\"$archive_cmds\"
- cmds=$archive_cmds
- fi
- fi
-
- if test "X$skipped_export" != "X:" &&
- len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- :
- else
- # The command line is too long to link in one step, link piecewise.
- $echo "creating reloadable object files..."
-
- # Save the value of $output and $libobjs because we want to
- # use them later. If we have whole_archive_flag_spec, we
- # want to use save_libobjs as it was before
- # whole_archive_flag_spec was expanded, because we can't
- # assume the linker understands whole_archive_flag_spec.
- # This may have to be revisited, in case too many
- # convenience libraries get linked in and end up exceeding
- # the spec.
- if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- fi
- save_output=$output
- output_la=`$echo "X$output" | $Xsed -e "$basename"`
-
- # Clear the reloadable object creation command queue and
- # initialize k to one.
- test_cmds=
- concat_cmds=
- objlist=
- delfiles=
- last_robj=
- k=1
- output=$output_objdir/$output_la-${k}.$objext
- # Loop over the list of objects to be linked.
- for obj in $save_libobjs
- do
- eval test_cmds=\"$reload_cmds $objlist $last_robj\"
- if test "X$objlist" = X ||
- { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len"; }; then
- objlist="$objlist $obj"
- else
- # The command $test_cmds is almost too long, add a
- # command to the queue.
- if test "$k" -eq 1 ; then
- # The first file doesn't have a previous command to add.
- eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
- else
- # All subsequent reloadable object files will link in
- # the last one created.
- eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
- fi
- last_robj=$output_objdir/$output_la-${k}.$objext
- k=`expr $k + 1`
- output=$output_objdir/$output_la-${k}.$objext
- objlist=$obj
- len=1
- fi
- done
- # Handle the remaining objects by creating one last
- # reloadable object file. All subsequent reloadable object
- # files will link in the last one created.
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
-
- if ${skipped_export-false}; then
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
- libobjs=$output
- # Append the command to create the export file.
- eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
- fi
-
- # Set up a command to remove the reloadable object files
- # after they are used.
- i=0
- while test "$i" -lt "$k"
- do
- i=`expr $i + 1`
- delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
- done
-
- $echo "creating a temporary reloadable object file: $output"
-
- # Loop through the commands generated above and execute them.
- save_ifs="$IFS"; IFS='~'
- for cmd in $concat_cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- libobjs=$output
- # Restore the value of output.
- output=$save_output
-
- if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- fi
- # Expand the library linking commands again to reset the
- # value of $libobjs for piecewise linking.
-
- # Do each of the archive commands.
- if test "$module" = yes && test -n "$module_cmds" ; then
- if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
- cmds=$module_expsym_cmds
- else
- cmds=$module_cmds
- fi
- else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- cmds=$archive_expsym_cmds
- else
- cmds=$archive_cmds
- fi
- fi
-
- # Append the command to remove the reloadable object files
- # to the just-reset $cmds.
- eval cmds=\"\$cmds~\$rm $delfiles\"
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || {
- lt_exit=$?
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
- fi
-
- exit $lt_exit
- }
- done
- IFS="$save_ifs"
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
-
- if test -n "$convenience"; then
- if test -z "$whole_archive_flag_spec"; then
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- fi
- fi
-
- exit $EXIT_SUCCESS
- fi
-
- # Create links to the real library.
- for linkname in $linknames; do
- if test "$realname" != "$linkname"; then
- $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
- $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
- fi
- done
-
- # If -module or -export-dynamic was specified, set the dlname.
- if test "$module" = yes || test "$export_dynamic" = yes; then
- # On all known operating systems, these are identical.
- dlname="$soname"
- fi
- fi
- ;;
-
- obj)
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
- fi
-
- case $output in
- *.lo)
- if test -n "$objs$old_deplibs"; then
- $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
- exit $EXIT_FAILURE
- fi
- libobj="$output"
- obj=`$echo "X$output" | $Xsed -e "$lo2o"`
- ;;
- *)
- libobj=
- obj="$output"
- ;;
- esac
-
- # Delete the old objects.
- $run $rm $obj $libobj
-
- # Objects from convenience libraries. This assumes
- # single-version convenience libraries. Whenever we create
- # different ones for PIC/non-PIC, this we'll have to duplicate
- # the extraction.
- reload_conv_objs=
- gentop=
- # reload_cmds runs $LD directly, so let us get rid of
- # -Wl from whole_archive_flag_spec
- wl=
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
- eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
- else
- gentop="$output_objdir/${obj}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $convenience
- reload_conv_objs="$reload_objs $func_extract_archives_result"
- fi
- fi
-
- # Create the old-style object.
- reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
-
- output="$obj"
- cmds=$reload_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- # Exit if we aren't doing a library object file.
- if test -z "$libobj"; then
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- exit $EXIT_SUCCESS
- fi
-
- if test "$build_libtool_libs" != yes; then
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- # Create an invalid libtool object if no PIC, so that we don't
- # accidentally link it into a program.
- # $show "echo timestamp > $libobj"
- # $run eval "echo timestamp > $libobj" || exit $?
- exit $EXIT_SUCCESS
- fi
-
- if test -n "$pic_flag" || test "$pic_mode" != default; then
- # Only do commands if we really have different PIC objects.
- reload_objs="$libobjs $reload_conv_objs"
- output="$libobj"
- cmds=$reload_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
-
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- exit $EXIT_SUCCESS
- ;;
-
- prog)
- case $host in
- *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
- esac
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
- fi
-
- if test "$preload" = yes; then
- if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
- test "$dlopen_self_static" = unknown; then
- $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
- fi
- fi
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library is the System framework
- compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
- finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
- ;;
- esac
-
- case $host in
- *darwin*)
- # Don't allow lazy linking, it breaks C++ global constructors
- if test "$tagname" = CXX ; then
- compile_command="$compile_command ${wl}-bind_at_load"
- finalize_command="$finalize_command ${wl}-bind_at_load"
- fi
- ;;
- esac
-
-
- # move library search paths that coincide with paths to not yet
- # installed libraries to the beginning of the library search list
- new_libs=
- for path in $notinst_path; do
- case " $new_libs " in
- *" -L$path/$objdir "*) ;;
- *)
- case " $compile_deplibs " in
- *" -L$path/$objdir "*)
- new_libs="$new_libs -L$path/$objdir" ;;
- esac
- ;;
- esac
- done
- for deplib in $compile_deplibs; do
- case $deplib in
- -L*)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- done
- compile_deplibs="$new_libs"
-
-
- compile_command="$compile_command $compile_deplibs"
- finalize_command="$finalize_command $finalize_deplibs"
-
- if test -n "$rpath$xrpath"; then
- # If the user specified any rpath flags, then add them.
- for libdir in $rpath $xrpath; do
- # This is the magic to use -rpath.
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- fi
-
- # Now hardcode the library paths
- rpath=
- hardcode_libdirs=
- for libdir in $compile_rpath $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
- case :$dllsearchpath: in
- *":$libdir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$libdir";;
- esac
- case :$dllsearchpath: in
- *":$testbindir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$testbindir";;
- esac
- ;;
- esac
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- compile_rpath="$rpath"
-
- rpath=
- hardcode_libdirs=
- for libdir in $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$finalize_perm_rpath " in
- *" $libdir "*) ;;
- *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- finalize_rpath="$rpath"
-
- if test -n "$libobjs" && test "$build_old_libs" = yes; then
- # Transform all the library objects into standard objects.
- compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- fi
-
- dlsyms=
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- if test -n "$NM" && test -n "$global_symbol_pipe"; then
- dlsyms="${outputname}S.c"
- else
- $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
- fi
- fi
-
- if test -n "$dlsyms"; then
- case $dlsyms in
- "") ;;
- *.c)
- # Discover the nlist of each of the dlfiles.
- nlist="$output_objdir/${outputname}.nm"
-
- $show "$rm $nlist ${nlist}S ${nlist}T"
- $run $rm "$nlist" "${nlist}S" "${nlist}T"
-
- # Parse the name list into a source file.
- $show "creating $output_objdir/$dlsyms"
-
- test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
-/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
-/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* Prevent the only kind of declaration conflicts we can make. */
-#define lt_preloaded_symbols some_other_symbol
-
-/* External symbol declarations for the compiler. */\
-"
-
- if test "$dlself" = yes; then
- $show "generating symbol list for \`$output'"
-
- test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
-
- # Add our own program objects to the symbol list.
- progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- for arg in $progfiles; do
- $show "extracting global C symbols from \`$arg'"
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -n "$exclude_expsyms"; then
- $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- if test -n "$export_symbols_regex"; then
- $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- export_symbols="$output_objdir/$outputname.exp"
- $run $rm $export_symbols
- $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
- case $host in
- *cygwin* | *mingw* )
- $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
- $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
- ;;
- esac
- else
- $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
- $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
- $run eval 'mv "$nlist"T "$nlist"'
- case $host in
- *cygwin* | *mingw* )
- $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
- $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
- ;;
- esac
- fi
- fi
-
- for arg in $dlprefiles; do
- $show "extracting global C symbols from \`$arg'"
- name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
- $run eval '$echo ": $name " >> "$nlist"'
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -z "$run"; then
- # Make sure we have at least an empty file.
- test -f "$nlist" || : > "$nlist"
-
- if test -n "$exclude_expsyms"; then
- $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
- $mv "$nlist"T "$nlist"
- fi
-
- # Try sorting and uniquifying the output.
- if grep -v "^: " < "$nlist" |
- if sort -k 3 </dev/null >/dev/null 2>&1; then
- sort -k 3
- else
- sort +2
- fi |
- uniq > "$nlist"S; then
- :
- else
- grep -v "^: " < "$nlist" > "$nlist"S
- fi
-
- if test -f "$nlist"S; then
- eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
- else
- $echo '/* NONE */' >> "$output_objdir/$dlsyms"
- fi
-
- $echo >> "$output_objdir/$dlsyms" "\
-
-#undef lt_preloaded_symbols
-
-#if defined (__STDC__) && __STDC__
-# define lt_ptr void *
-#else
-# define lt_ptr char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-"
-
- case $host in
- *cygwin* | *mingw* )
- $echo >> "$output_objdir/$dlsyms" "\
-/* DATA imports from DLLs on WIN32 can't be const, because
- runtime relocations are performed -- see ld's documentation
- on pseudo-relocs */
-struct {
-"
- ;;
- * )
- $echo >> "$output_objdir/$dlsyms" "\
-const struct {
-"
- ;;
- esac
-
-
- $echo >> "$output_objdir/$dlsyms" "\
- const char *name;
- lt_ptr address;
-}
-lt_preloaded_symbols[] =
-{\
-"
-
- eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
-
- $echo >> "$output_objdir/$dlsyms" "\
- {0, (lt_ptr) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
- fi
-
- pic_flag_for_symtable=
- case $host in
- # compiling the symbol table file with pic_flag works around
- # a FreeBSD bug that causes programs to crash when -lm is
- # linked before any other PIC object. But we must not use
- # pic_flag when linking with -static. The problem exists in
- # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
- *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
- case "$compile_command " in
- *" -static "*) ;;
- *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
- esac;;
- *-*-hpux*)
- case "$compile_command " in
- *" -static "*) ;;
- *) pic_flag_for_symtable=" $pic_flag";;
- esac
- esac
-
- # Now compile the dynamic symbol file.
- $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
- $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
- # Clean up the generated files.
- $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
- $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
- # Transform the symbol file into the correct name.
- case $host in
- *cygwin* | *mingw* )
- if test -f "$output_objdir/${outputname}.def" ; then
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
- else
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- fi
- ;;
- * )
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- ;;
- esac
- ;;
- *)
- $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- else
- # We keep going just in case the user didn't refer to
- # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
- # really was required.
-
- # Nullify the symbol file.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
- fi
-
- if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
- # Replace the output file specification.
- compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- link_command="$compile_command$compile_rpath"
-
- # We have no uninstalled library dependencies, so finalize right now.
- $show "$link_command"
- $run eval "$link_command"
- exit_status=$?
-
- # Delete the generated files.
- if test -n "$dlsyms"; then
- $show "$rm $output_objdir/${outputname}S.${objext}"
- $run $rm "$output_objdir/${outputname}S.${objext}"
- fi
-
- exit $exit_status
- fi
-
- if test -n "$shlibpath_var"; then
- # We should set the shlibpath_var
- rpath=
- for dir in $temp_rpath; do
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*)
- # Absolute path.
- rpath="$rpath$dir:"
- ;;
- *)
- # Relative path: add a thisdir entry.
- rpath="$rpath\$thisdir/$dir:"
- ;;
- esac
- done
- temp_rpath="$rpath"
- fi
-
- if test -n "$compile_shlibpath$finalize_shlibpath"; then
- compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
- fi
- if test -n "$finalize_shlibpath"; then
- finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
- fi
-
- compile_var=
- finalize_var=
- if test -n "$runpath_var"; then
- if test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- if test -n "$finalize_perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $finalize_perm_rpath; do
- rpath="$rpath$dir:"
- done
- finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- fi
-
- if test "$no_install" = yes; then
- # We don't need to create a wrapper script.
- link_command="$compile_var$compile_command$compile_rpath"
- # Replace the output file specification.
- link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- # Delete the old output file.
- $run $rm $output
- # Link the executable and exit
- $show "$link_command"
- $run eval "$link_command" || exit $?
- exit $EXIT_SUCCESS
- fi
-
- if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
-
- $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
- $echo "$modename: \`$output' will be relinked during installation" 1>&2
- else
- if test "$fast_install" != no; then
- link_command="$finalize_var$compile_command$finalize_rpath"
- if test "$fast_install" = yes; then
- relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
- else
- # fast_install is set to needless
- relink_command=
- fi
- else
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
- fi
- fi
-
- # Replace the output file specification.
- link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-
- # Delete the old output files.
- $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
- $show "$link_command"
- $run eval "$link_command" || exit $?
-
- # Now create the wrapper script.
- $show "creating $output"
-
- # Quote the relink command for shipping.
- if test -n "$relink_command"; then
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
- relink_command="$var=\"$var_value\"; export $var; $relink_command"
- fi
- done
- relink_command="(cd `pwd`; $relink_command)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Quote $echo for shipping.
- if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
- case $progpath in
- [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
- *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
- esac
- qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
- else
- qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Only actually do things if our run command is non-null.
- if test -z "$run"; then
- # win32 will think the script is a binary if it has
- # a .exe suffix, so we strip it off here.
- case $output in
- *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
- esac
- # test for cygwin because mv fails w/o .exe extensions
- case $host in
- *cygwin*)
- exeext=.exe
- outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
- *) exeext= ;;
- esac
- case $host in
- *cygwin* | *mingw* )
- output_name=`basename $output`
- output_path=`dirname $output`
- cwrappersource="$output_path/$objdir/lt-$output_name.c"
- cwrapper="$output_path/$output_name.exe"
- $rm $cwrappersource $cwrapper
- trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
-
- cat > $cwrappersource <<EOF
-
-/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
- Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-
- The $output program cannot be directly executed until all the libtool
- libraries that it depends on are installed.
-
- This wrapper executable should never be moved out of the build directory.
- If it is, it will not operate correctly.
-
- Currently, it simply execs the wrapper *script* "/bin/sh $output",
- but could eventually absorb all of the scripts functionality and
- exec $objdir/$outputname directly.
-*/
-EOF
- cat >> $cwrappersource<<"EOF"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/stat.h>
-
-#if defined(PATH_MAX)
-# define LT_PATHMAX PATH_MAX
-#elif defined(MAXPATHLEN)
-# define LT_PATHMAX MAXPATHLEN
-#else
-# define LT_PATHMAX 1024
-#endif
-
-#ifndef DIR_SEPARATOR
-# define DIR_SEPARATOR '/'
-# define PATH_SEPARATOR ':'
-#endif
-
-#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
- defined (__OS2__)
-# define HAVE_DOS_BASED_FILE_SYSTEM
-# ifndef DIR_SEPARATOR_2
-# define DIR_SEPARATOR_2 '\\'
-# endif
-# ifndef PATH_SEPARATOR_2
-# define PATH_SEPARATOR_2 ';'
-# endif
-#endif
-
-#ifndef DIR_SEPARATOR_2
-# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
-#else /* DIR_SEPARATOR_2 */
-# define IS_DIR_SEPARATOR(ch) \
- (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
-#endif /* DIR_SEPARATOR_2 */
-
-#ifndef PATH_SEPARATOR_2
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
-#else /* PATH_SEPARATOR_2 */
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
-#endif /* PATH_SEPARATOR_2 */
-
-#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
-#define XFREE(stale) do { \
- if (stale) { free ((void *) stale); stale = 0; } \
-} while (0)
-
-/* -DDEBUG is fairly common in CFLAGS. */
-#undef DEBUG
-#if defined DEBUGWRAPPER
-# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
-#else
-# define DEBUG(format, ...)
-#endif
-
-const char *program_name = NULL;
-
-void * xmalloc (size_t num);
-char * xstrdup (const char *string);
-const char * base_name (const char *name);
-char * find_executable(const char *wrapper);
-int check_executable(const char *path);
-char * strendzap(char *str, const char *pat);
-void lt_fatal (const char *message, ...);
-
-int
-main (int argc, char *argv[])
-{
- char **newargz;
- int i;
-
- program_name = (char *) xstrdup (base_name (argv[0]));
- DEBUG("(main) argv[0] : %s\n",argv[0]);
- DEBUG("(main) program_name : %s\n",program_name);
- newargz = XMALLOC(char *, argc+2);
-EOF
-
- cat >> $cwrappersource <<EOF
- newargz[0] = (char *) xstrdup("$SHELL");
-EOF
-
- cat >> $cwrappersource <<"EOF"
- newargz[1] = find_executable(argv[0]);
- if (newargz[1] == NULL)
- lt_fatal("Couldn't find %s", argv[0]);
- DEBUG("(main) found exe at : %s\n",newargz[1]);
- /* we know the script has the same name, without the .exe */
- /* so make sure newargz[1] doesn't end in .exe */
- strendzap(newargz[1],".exe");
- for (i = 1; i < argc; i++)
- newargz[i+1] = xstrdup(argv[i]);
- newargz[argc+1] = NULL;
-
- for (i=0; i<argc+1; i++)
- {
- DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
- ;
- }
-
-EOF
-
- case $host_os in
- mingw*)
- cat >> $cwrappersource <<EOF
- execv("$SHELL",(char const **)newargz);
-EOF
- ;;
- *)
- cat >> $cwrappersource <<EOF
- execv("$SHELL",newargz);
-EOF
- ;;
- esac
-
- cat >> $cwrappersource <<"EOF"
- return 127;
-}
-
-void *
-xmalloc (size_t num)
-{
- void * p = (void *) malloc (num);
- if (!p)
- lt_fatal ("Memory exhausted");
-
- return p;
-}
-
-char *
-xstrdup (const char *string)
-{
- return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
-;
-}
-
-const char *
-base_name (const char *name)
-{
- const char *base;
-
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- /* Skip over the disk name in MSDOS pathnames. */
- if (isalpha ((unsigned char)name[0]) && name[1] == ':')
- name += 2;
-#endif
-
- for (base = name; *name; name++)
- if (IS_DIR_SEPARATOR (*name))
- base = name + 1;
- return base;
-}
-
-int
-check_executable(const char * path)
-{
- struct stat st;
-
- DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
- if ((!path) || (!*path))
- return 0;
-
- if ((stat (path, &st) >= 0) &&
- (
- /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
-#if defined (S_IXOTH)
- ((st.st_mode & S_IXOTH) == S_IXOTH) ||
-#endif
-#if defined (S_IXGRP)
- ((st.st_mode & S_IXGRP) == S_IXGRP) ||
-#endif
- ((st.st_mode & S_IXUSR) == S_IXUSR))
- )
- return 1;
- else
- return 0;
-}
-
-/* Searches for the full path of the wrapper. Returns
- newly allocated full path name if found, NULL otherwise */
-char *
-find_executable (const char* wrapper)
-{
- int has_slash = 0;
- const char* p;
- const char* p_next;
- /* static buffer for getcwd */
- char tmp[LT_PATHMAX + 1];
- int tmp_len;
- char* concat_name;
-
- DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
-
- if ((wrapper == NULL) || (*wrapper == '\0'))
- return NULL;
-
- /* Absolute path? */
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
- {
- concat_name = xstrdup (wrapper);
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- }
- else
- {
-#endif
- if (IS_DIR_SEPARATOR (wrapper[0]))
- {
- concat_name = xstrdup (wrapper);
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- }
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- }
-#endif
-
- for (p = wrapper; *p; p++)
- if (*p == '/')
- {
- has_slash = 1;
- break;
- }
- if (!has_slash)
- {
- /* no slashes; search PATH */
- const char* path = getenv ("PATH");
- if (path != NULL)
- {
- for (p = path; *p; p = p_next)
- {
- const char* q;
- size_t p_len;
- for (q = p; *q; q++)
- if (IS_PATH_SEPARATOR(*q))
- break;
- p_len = q - p;
- p_next = (*q == '\0' ? q : q + 1);
- if (p_len == 0)
- {
- /* empty path: current directory */
- if (getcwd (tmp, LT_PATHMAX) == NULL)
- lt_fatal ("getcwd failed");
- tmp_len = strlen(tmp);
- concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
- memcpy (concat_name, tmp, tmp_len);
- concat_name[tmp_len] = '/';
- strcpy (concat_name + tmp_len + 1, wrapper);
- }
- else
- {
- concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
- memcpy (concat_name, p, p_len);
- concat_name[p_len] = '/';
- strcpy (concat_name + p_len + 1, wrapper);
- }
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- }
- }
- /* not found in PATH; assume curdir */
- }
- /* Relative path | not found in path: prepend cwd */
- if (getcwd (tmp, LT_PATHMAX) == NULL)
- lt_fatal ("getcwd failed");
- tmp_len = strlen(tmp);
- concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
- memcpy (concat_name, tmp, tmp_len);
- concat_name[tmp_len] = '/';
- strcpy (concat_name + tmp_len + 1, wrapper);
-
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- return NULL;
-}
-
-char *
-strendzap(char *str, const char *pat)
-{
- size_t len, patlen;
-
- assert(str != NULL);
- assert(pat != NULL);
-
- len = strlen(str);
- patlen = strlen(pat);
-
- if (patlen <= len)
- {
- str += len - patlen;
- if (strcmp(str, pat) == 0)
- *str = '\0';
- }
- return str;
-}
-
-static void
-lt_error_core (int exit_status, const char * mode,
- const char * message, va_list ap)
-{
- fprintf (stderr, "%s: %s: ", program_name, mode);
- vfprintf (stderr, message, ap);
- fprintf (stderr, ".\n");
-
- if (exit_status >= 0)
- exit (exit_status);
-}
-
-void
-lt_fatal (const char *message, ...)
-{
- va_list ap;
- va_start (ap, message);
- lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
- va_end (ap);
-}
-EOF
- # we should really use a build-platform specific compiler
- # here, but OTOH, the wrappers (shell script and this C one)
- # are only useful if you want to execute the "real" binary.
- # Since the "real" binary is built for $host, then this
- # wrapper might as well be built for $host, too.
- $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
- ;;
- esac
- $rm $output
- trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
-
- $echo > $output "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='${SED} -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
- # install mode needs the following variable:
- notinst_deplibs='$notinst_deplibs'
-else
- # When we are sourced in execute mode, \$file and \$echo are already set.
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- echo=\"$qecho\"
- file=\"\$0\"
- # Make sure echo works.
- if test \"X\$1\" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
- elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
- # Yippee, \$echo works!
- :
- else
- # Restart under the correct shell, and then maybe \$echo will work.
- exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
- fi
- fi\
-"
- $echo >> $output "\
-
- # Find the directory that this script lives in.
- thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
- test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
- # Follow symbolic links until we get to the real thisdir.
- file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
- while test -n \"\$file\"; do
- destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
- # If there was a directory component, then change thisdir.
- if test \"x\$destdir\" != \"x\$file\"; then
- case \"\$destdir\" in
- [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
- *) thisdir=\"\$thisdir/\$destdir\" ;;
- esac
- fi
-
- file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
- file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
- done
-
- # Try to get the absolute directory name.
- absdir=\`cd \"\$thisdir\" && pwd\`
- test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
- if test "$fast_install" = yes; then
- $echo >> $output "\
- program=lt-'$outputname'$exeext
- progdir=\"\$thisdir/$objdir\"
-
- if test ! -f \"\$progdir/\$program\" || \\
- { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
- test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
- file=\"\$\$-\$program\"
-
- if test ! -d \"\$progdir\"; then
- $mkdir \"\$progdir\"
- else
- $rm \"\$progdir/\$file\"
- fi"
-
- $echo >> $output "\
-
- # relink executable if necessary
- if test -n \"\$relink_command\"; then
- if relink_command_output=\`eval \$relink_command 2>&1\`; then :
- else
- $echo \"\$relink_command_output\" >&2
- $rm \"\$progdir/\$file\"
- exit $EXIT_FAILURE
- fi
- fi
-
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
- { $rm \"\$progdir/\$program\";
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
- $rm \"\$progdir/\$file\"
- fi"
- else
- $echo >> $output "\
- program='$outputname'
- progdir=\"\$thisdir/$objdir\"
-"
- fi
-
- $echo >> $output "\
-
- if test -f \"\$progdir/\$program\"; then"
-
- # Export our shlibpath_var if we have one.
- if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
- $echo >> $output "\
- # Add our own library path to $shlibpath_var
- $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
- # Some systems cannot cope with colon-terminated $shlibpath_var
- # The second colon is a workaround for a bug in BeOS R4 sed
- $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
- export $shlibpath_var
-"
- fi
-
- # fixup the dll searchpath if we need to.
- if test -n "$dllsearchpath"; then
- $echo >> $output "\
- # Add the dll search path components to the executable PATH
- PATH=$dllsearchpath:\$PATH
-"
- fi
-
- $echo >> $output "\
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- # Run the actual program with our arguments.
-"
- case $host in
- # Backslashes separate directories on plain windows
- *-*-mingw | *-*-os2*)
- $echo >> $output "\
- exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
-"
- ;;
-
- *)
- $echo >> $output "\
- exec \"\$progdir/\$program\" \${1+\"\$@\"}
-"
- ;;
- esac
- $echo >> $output "\
- \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
- exit $EXIT_FAILURE
- fi
- else
- # The program doesn't exist.
- \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
- \$echo \"This script is just a wrapper for \$program.\" 1>&2
- $echo \"See the $PACKAGE documentation for more information.\" 1>&2
- exit $EXIT_FAILURE
- fi
-fi\
-"
- chmod +x $output
- fi
- exit $EXIT_SUCCESS
- ;;
- esac
-
- # See if we need to build an old-fashioned archive.
- for oldlib in $oldlibs; do
-
- if test "$build_libtool_libs" = convenience; then
- oldobjs="$libobjs_save"
- addlibs="$convenience"
- build_libtool_libs=no
- else
- if test "$build_libtool_libs" = module; then
- oldobjs="$libobjs_save"
- build_libtool_libs=no
- else
- oldobjs="$old_deplibs $non_pic_objects"
- fi
- addlibs="$old_convenience"
- fi
-
- if test -n "$addlibs"; then
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $addlibs
- oldobjs="$oldobjs $func_extract_archives_result"
- fi
-
- # Do each command in the archive commands.
- if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
- cmds=$old_archive_from_new_cmds
- else
- # POSIX demands no paths to be encoded in archives. We have
- # to avoid creating archives with duplicate basenames if we
- # might have to extract them afterwards, e.g., when creating a
- # static archive out of a convenience library, or when linking
- # the entirety of a libtool archive into another (currently
- # not supported by libtool).
- if (for obj in $oldobjs
- do
- $echo "X$obj" | $Xsed -e 's%^.*/%%'
- done | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "copying selected object files to avoid basename conflicts..."
-
- if test -z "$gentop"; then
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- exit_status=$?
- if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
- exit $exit_status
- fi
- fi
-
- save_oldobjs=$oldobjs
- oldobjs=
- counter=1
- for obj in $save_oldobjs
- do
- objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
- case " $oldobjs " in
- " ") oldobjs=$obj ;;
- *[\ /]"$objbase "*)
- while :; do
- # Make sure we don't pick an alternate name that also
- # overlaps.
- newobj=lt$counter-$objbase
- counter=`expr $counter + 1`
- case " $oldobjs " in
- *[\ /]"$newobj "*) ;;
- *) if test ! -f "$gentop/$newobj"; then break; fi ;;
- esac
- done
- $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
- $run ln "$obj" "$gentop/$newobj" ||
- $run cp "$obj" "$gentop/$newobj"
- oldobjs="$oldobjs $gentop/$newobj"
- ;;
- *) oldobjs="$oldobjs $obj" ;;
- esac
- done
- fi
-
- eval cmds=\"$old_archive_cmds\"
-
- if len=`expr "X$cmds" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- cmds=$old_archive_cmds
- else
- # the command line is too long to link in one step, link in parts
- $echo "using piecewise archive linking..."
- save_RANLIB=$RANLIB
- RANLIB=:
- objlist=
- concat_cmds=
- save_oldobjs=$oldobjs
-
- # Is there a better way of finding the last object in the list?
- for obj in $save_oldobjs
- do
- last_oldobj=$obj
- done
- for obj in $save_oldobjs
- do
- oldobjs="$objlist $obj"
- objlist="$objlist $obj"
- eval test_cmds=\"$old_archive_cmds\"
- if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len"; then
- :
- else
- # the above command should be used before it gets too long
- oldobjs=$objlist
- if test "$obj" = "$last_oldobj" ; then
- RANLIB=$save_RANLIB
- fi
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
- objlist=
- fi
- done
- RANLIB=$save_RANLIB
- oldobjs=$objlist
- if test "X$oldobjs" = "X" ; then
- eval cmds=\"\$concat_cmds\"
- else
- eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
- fi
- fi
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- eval cmd=\"$cmd\"
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$generated"; then
- $show "${rm}r$generated"
- $run ${rm}r$generated
- fi
-
- # Now create the libtool archive.
- case $output in
- *.la)
- old_library=
- test "$build_old_libs" = yes && old_library="$libname.$libext"
- $show "creating $output"
-
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
- relink_command="$var=\"$var_value\"; export $var; $relink_command"
- fi
- done
- # Quote the link command for shipping.
- relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- if test "$hardcode_automatic" = yes ; then
- relink_command=
- fi
-
-
- # Only create the output if not a dry run.
- if test -z "$run"; then
- for installed in no yes; do
- if test "$installed" = yes; then
- if test -z "$install_libdir"; then
- break
- fi
- output="$output_objdir/$outputname"i
- # Replace all uninstalled libtool libraries with the installed ones
- newdependency_libs=
- for deplib in $dependency_libs; do
- case $deplib in
- *.la)
- name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- newdependency_libs="$newdependency_libs $libdir/$name"
- ;;
- *) newdependency_libs="$newdependency_libs $deplib" ;;
- esac
- done
- dependency_libs="$newdependency_libs"
- newdlfiles=
- for lib in $dlfiles; do
- name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- newdlfiles="$newdlfiles $libdir/$name"
- done
- dlfiles="$newdlfiles"
- newdlprefiles=
- for lib in $dlprefiles; do
- name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- newdlprefiles="$newdlprefiles $libdir/$name"
- done
- dlprefiles="$newdlprefiles"
- else
- newdlfiles=
- for lib in $dlfiles; do
- case $lib in
- [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
- *) abs=`pwd`"/$lib" ;;
- esac
- newdlfiles="$newdlfiles $abs"
- done
- dlfiles="$newdlfiles"
- newdlprefiles=
- for lib in $dlprefiles; do
- case $lib in
- [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
- *) abs=`pwd`"/$lib" ;;
- esac
- newdlprefiles="$newdlprefiles $abs"
- done
- dlprefiles="$newdlprefiles"
- fi
- $rm $output
- # place dlname in correct position for cygwin
- tdlname=$dlname
- case $host,$output,$installed,$module,$dlname in
- *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
- esac
- $echo > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$tdlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Should we warn about portability when linking against -modules?
-shouldnotlink=$module
-
-# Files to dlopen/dlpreopen
-dlopen='$dlfiles'
-dlpreopen='$dlprefiles'
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'"
- if test "$installed" = no && test "$need_relink" = yes; then
- $echo >> $output "\
-relink_command=\"$relink_command\""
- fi
- done
- fi
-
- # Do a symbolic link so that the libtool archive can be found in
- # LD_LIBRARY_PATH before the program is installed.
- $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
- $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
- ;;
- esac
- exit $EXIT_SUCCESS
- ;;
-
- # libtool install mode
- install)
- modename="$modename: install"
-
- # There may be an optional sh(1) argument at the beginning of
- # install_prog (especially on Windows NT).
- if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
- # Allow the use of GNU shtool's install command.
- $echo "X$nonopt" | grep shtool > /dev/null; then
- # Aesthetically quote it.
- arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- install_prog="$arg "
- arg="$1"
- shift
- else
- install_prog=
- arg=$nonopt
- fi
-
- # The real first argument should be the name of the installation program.
- # Aesthetically quote it.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog$arg"
-
- # We need to accept at least all the BSD install flags.
- dest=
- files=
- opts=
- prev=
- install_type=
- isdir=no
- stripme=
- for arg
- do
- if test -n "$dest"; then
- files="$files $dest"
- dest=$arg
- continue
- fi
-
- case $arg in
- -d) isdir=yes ;;
- -f)
- case " $install_prog " in
- *[\\\ /]cp\ *) ;;
- *) prev=$arg ;;
- esac
- ;;
- -g | -m | -o) prev=$arg ;;
- -s)
- stripme=" -s"
- continue
- ;;
- -*)
- ;;
- *)
- # If the previous option needed an argument, then skip it.
- if test -n "$prev"; then
- prev=
- else
- dest=$arg
- continue
- fi
- ;;
- esac
-
- # Aesthetically quote the argument.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog $arg"
- done
-
- if test -z "$install_prog"; then
- $echo "$modename: you must specify an install program" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prev' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- if test -z "$files"; then
- if test -z "$dest"; then
- $echo "$modename: no file or destination specified" 1>&2
- else
- $echo "$modename: you must specify a destination" 1>&2
- fi
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Strip any trailing slash from the destination.
- dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
-
- # Check to see that the destination is a directory.
- test -d "$dest" && isdir=yes
- if test "$isdir" = yes; then
- destdir="$dest"
- destname=
- else
- destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
- test "X$destdir" = "X$dest" && destdir=.
- destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
-
- # Not a directory, so check to see that there is only one file specified.
- set dummy $files
- if test "$#" -gt 2; then
- $echo "$modename: \`$dest' is not a directory" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
- fi
- case $destdir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- for file in $files; do
- case $file in
- *.lo) ;;
- *)
- $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- done
- ;;
- esac
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- staticlibs=
- future_libdirs=
- current_libdirs=
- for file in $files; do
-
- # Do each installation.
- case $file in
- *.$libext)
- # Do the static libraries later.
- staticlibs="$staticlibs $file"
- ;;
-
- *.la)
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- library_names=
- old_library=
- relink_command=
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Add the libdir to current_libdirs if it is the destination.
- if test "X$destdir" = "X$libdir"; then
- case "$current_libdirs " in
- *" $libdir "*) ;;
- *) current_libdirs="$current_libdirs $libdir" ;;
- esac
- else
- # Note the libdir as a future libdir.
- case "$future_libdirs " in
- *" $libdir "*) ;;
- *) future_libdirs="$future_libdirs $libdir" ;;
- esac
- fi
-
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
- test "X$dir" = "X$file/" && dir=
- dir="$dir$objdir"
-
- if test -n "$relink_command"; then
- # Determine the prefix the user has applied to our future dir.
- inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
-
- # Don't allow the user to place us outside of our expected
- # location b/c this prevents finding dependent libraries that
- # are installed to the same prefix.
- # At present, this check doesn't affect windows .dll's that
- # are installed into $libdir/../bin (currently, that works fine)
- # but it's something to keep an eye on.
- if test "$inst_prefix_dir" = "$destdir"; then
- $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
- exit $EXIT_FAILURE
- fi
-
- if test -n "$inst_prefix_dir"; then
- # Stick the inst_prefix_dir data into the link command.
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
- else
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
- fi
-
- $echo "$modename: warning: relinking \`$file'" 1>&2
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
- exit $EXIT_FAILURE
- fi
- fi
-
- # See the names of the shared library.
- set dummy $library_names
- if test -n "$2"; then
- realname="$2"
- shift
- shift
-
- srcname="$realname"
- test -n "$relink_command" && srcname="$realname"T
-
- # Install the shared library and build the symlinks.
- $show "$install_prog $dir/$srcname $destdir/$realname"
- $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
- if test -n "$stripme" && test -n "$striplib"; then
- $show "$striplib $destdir/$realname"
- $run eval "$striplib $destdir/$realname" || exit $?
- fi
-
- if test "$#" -gt 0; then
- # Delete the old symlinks, and create new ones.
- # Try `ln -sf' first, because the `ln' binary might depend on
- # the symlink we replace! Solaris /bin/ln does not understand -f,
- # so we also need to try rm && ln -s.
- for linkname
- do
- if test "$linkname" != "$realname"; then
- $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
- $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
- fi
- done
- fi
-
- # Do each command in the postinstall commands.
- lib="$destdir/$realname"
- cmds=$postinstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || {
- lt_exit=$?
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
- fi
-
- exit $lt_exit
- }
- done
- IFS="$save_ifs"
- fi
-
- # Install the pseudo-library for information purposes.
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- instname="$dir/$name"i
- $show "$install_prog $instname $destdir/$name"
- $run eval "$install_prog $instname $destdir/$name" || exit $?
-
- # Maybe install the static library, too.
- test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
- ;;
-
- *.lo)
- # Install (i.e. copy) a libtool object.
-
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # Deduce the name of the destination old-style object file.
- case $destfile in
- *.lo)
- staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
- ;;
- *.$objext)
- staticdest="$destfile"
- destfile=
- ;;
- *)
- $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- # Install the libtool object if requested.
- if test -n "$destfile"; then
- $show "$install_prog $file $destfile"
- $run eval "$install_prog $file $destfile" || exit $?
- fi
-
- # Install the old object if enabled.
- if test "$build_old_libs" = yes; then
- # Deduce the name of the old-style object file.
- staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
-
- $show "$install_prog $staticobj $staticdest"
- $run eval "$install_prog \$staticobj \$staticdest" || exit $?
- fi
- exit $EXIT_SUCCESS
- ;;
-
- *)
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # If the file is missing, and there is a .exe on the end, strip it
- # because it is most likely a libtool script we actually want to
- # install
- stripped_ext=""
- case $file in
- *.exe)
- if test ! -f "$file"; then
- file=`$echo $file|${SED} 's,.exe$,,'`
- stripped_ext=".exe"
- fi
- ;;
- esac
-
- # Do a test to see if this is really a libtool program.
- case $host in
- *cygwin*|*mingw*)
- wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
- ;;
- *)
- wrapper=$file
- ;;
- esac
- if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
- notinst_deplibs=
- relink_command=
-
- # Note that it is not necessary on cygwin/mingw to append a dot to
- # foo even if both foo and FILE.exe exist: automatic-append-.exe
- # behavior happens only for exec(3), not for open(2)! Also, sourcing
- # `FILE.' does not work on cygwin managed mounts.
- #
- # If there is no directory component, then add one.
- case $wrapper in
- */* | *\\*) . ${wrapper} ;;
- *) . ./${wrapper} ;;
- esac
-
- # Check the variables that should have been set.
- if test -z "$notinst_deplibs"; then
- $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
- exit $EXIT_FAILURE
- fi
-
- finalize=yes
- for lib in $notinst_deplibs; do
- # Check to see that each library is installed.
- libdir=
- if test -f "$lib"; then
- # If there is no directory component, then add one.
- case $lib in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
- fi
- libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
- if test -n "$libdir" && test ! -f "$libfile"; then
- $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
- finalize=no
- fi
- done
-
- relink_command=
- # Note that it is not necessary on cygwin/mingw to append a dot to
- # foo even if both foo and FILE.exe exist: automatic-append-.exe
- # behavior happens only for exec(3), not for open(2)! Also, sourcing
- # `FILE.' does not work on cygwin managed mounts.
- #
- # If there is no directory component, then add one.
- case $wrapper in
- */* | *\\*) . ${wrapper} ;;
- *) . ./${wrapper} ;;
- esac
-
- outputname=
- if test "$fast_install" = no && test -n "$relink_command"; then
- if test "$finalize" = yes && test -z "$run"; then
- tmpdir=`func_mktempdir`
- file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
- outputname="$tmpdir/$file"
- # Replace the output file specification.
- relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
- ${rm}r "$tmpdir"
- continue
- fi
- file="$outputname"
- else
- $echo "$modename: warning: cannot relink \`$file'" 1>&2
- fi
- else
- # Install the binary that we compiled earlier.
- file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
- fi
- fi
-
- # remove .exe since cygwin /usr/bin/install will append another
- # one anyway
- case $install_prog,$host in
- */usr/bin/install*,*cygwin*)
- case $file:$destfile in
- *.exe:*.exe)
- # this is ok
- ;;
- *.exe:*)
- destfile=$destfile.exe
- ;;
- *:*.exe)
- destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
- ;;
- esac
- ;;
- esac
- $show "$install_prog$stripme $file $destfile"
- $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
- test -n "$outputname" && ${rm}r "$tmpdir"
- ;;
- esac
- done
-
- for file in $staticlibs; do
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
- # Set up the ranlib parameters.
- oldlib="$destdir/$name"
-
- $show "$install_prog $file $oldlib"
- $run eval "$install_prog \$file \$oldlib" || exit $?
-
- if test -n "$stripme" && test -n "$old_striplib"; then
- $show "$old_striplib $oldlib"
- $run eval "$old_striplib $oldlib" || exit $?
- fi
-
- # Do each command in the postinstall commands.
- cmds=$old_postinstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$future_libdirs"; then
- $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
- fi
-
- if test -n "$current_libdirs"; then
- # Maybe just do a dry run.
- test -n "$run" && current_libdirs=" -n$current_libdirs"
- exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
- else
- exit $EXIT_SUCCESS
- fi
- ;;
-
- # libtool finish mode
- finish)
- modename="$modename: finish"
- libdirs="$nonopt"
- admincmds=
-
- if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
- for dir
- do
- libdirs="$libdirs $dir"
- done
-
- for libdir in $libdirs; do
- if test -n "$finish_cmds"; then
- # Do each command in the finish commands.
- cmds=$finish_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || admincmds="$admincmds
- $cmd"
- done
- IFS="$save_ifs"
- fi
- if test -n "$finish_eval"; then
- # Do the single finish_eval.
- eval cmds=\"$finish_eval\"
- $run eval "$cmds" || admincmds="$admincmds
- $cmds"
- fi
- done
- fi
-
- # Exit here if they wanted silent mode.
- test "$show" = : && exit $EXIT_SUCCESS
-
- $echo "X----------------------------------------------------------------------" | $Xsed
- $echo "Libraries have been installed in:"
- for libdir in $libdirs; do
- $echo " $libdir"
- done
- $echo
- $echo "If you ever happen to want to link against installed libraries"
- $echo "in a given directory, LIBDIR, you must either use libtool, and"
- $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
- $echo "flag during linking and do at least one of the following:"
- if test -n "$shlibpath_var"; then
- $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
- $echo " during execution"
- fi
- if test -n "$runpath_var"; then
- $echo " - add LIBDIR to the \`$runpath_var' environment variable"
- $echo " during linking"
- fi
- if test -n "$hardcode_libdir_flag_spec"; then
- libdir=LIBDIR
- eval flag=\"$hardcode_libdir_flag_spec\"
-
- $echo " - use the \`$flag' linker flag"
- fi
- if test -n "$admincmds"; then
- $echo " - have your system administrator run these commands:$admincmds"
- fi
- if test -f /etc/ld.so.conf; then
- $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
- fi
- $echo
- $echo "See any operating system documentation about shared libraries for"
- $echo "more information, such as the ld(1) and ld.so(8) manual pages."
- $echo "X----------------------------------------------------------------------" | $Xsed
- exit $EXIT_SUCCESS
- ;;
-
- # libtool execute mode
- execute)
- modename="$modename: execute"
-
- # The first argument is the command name.
- cmd="$nonopt"
- if test -z "$cmd"; then
- $echo "$modename: you must specify a COMMAND" 1>&2
- $echo "$help"
- exit $EXIT_FAILURE
- fi
-
- # Handle -dlopen flags immediately.
- for file in $execute_dlfiles; do
- if test ! -f "$file"; then
- $echo "$modename: \`$file' is not a file" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- dir=
- case $file in
- *.la)
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Read the libtool library.
- dlname=
- library_names=
-
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Skip this library if it cannot be dlopened.
- if test -z "$dlname"; then
- # Warn if it was a shared library.
- test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
- continue
- fi
-
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
-
- if test -f "$dir/$objdir/$dlname"; then
- dir="$dir/$objdir"
- else
- $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
- exit $EXIT_FAILURE
- fi
- ;;
-
- *.lo)
- # Just add the directory containing the .lo file.
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
- ;;
-
- *)
- $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
- continue
- ;;
- esac
-
- # Get the absolute pathname.
- absdir=`cd "$dir" && pwd`
- test -n "$absdir" && dir="$absdir"
-
- # Now add the directory to shlibpath_var.
- if eval "test -z \"\$$shlibpath_var\""; then
- eval "$shlibpath_var=\"\$dir\""
- else
- eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
- fi
- done
-
- # This variable tells wrapper scripts just to set shlibpath_var
- # rather than running their programs.
- libtool_execute_magic="$magic"
-
- # Check if any of the arguments is a wrapper script.
- args=
- for file
- do
- case $file in
- -*) ;;
- *)
- # Do a test to see if this is really a libtool program.
- if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Transform arg to wrapped name.
- file="$progdir/$program"
- fi
- ;;
- esac
- # Quote arguments (to preserve shell metacharacters).
- file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
- args="$args \"$file\""
- done
-
- if test -z "$run"; then
- if test -n "$shlibpath_var"; then
- # Export the shlibpath_var.
- eval "export $shlibpath_var"
- fi
-
- # Restore saved environment variables
- if test "${save_LC_ALL+set}" = set; then
- LC_ALL="$save_LC_ALL"; export LC_ALL
- fi
- if test "${save_LANG+set}" = set; then
- LANG="$save_LANG"; export LANG
- fi
-
- # Now prepare to actually exec the command.
- exec_cmd="\$cmd$args"
- else
- # Display what would be done.
- if test -n "$shlibpath_var"; then
- eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
- $echo "export $shlibpath_var"
- fi
- $echo "$cmd$args"
- exit $EXIT_SUCCESS
- fi
- ;;
-
- # libtool clean and uninstall mode
- clean | uninstall)
- modename="$modename: $mode"
- rm="$nonopt"
- files=
- rmforce=
- exit_status=0
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- for arg
- do
- case $arg in
- -f) rm="$rm $arg"; rmforce=yes ;;
- -*) rm="$rm $arg" ;;
- *) files="$files $arg" ;;
- esac
- done
-
- if test -z "$rm"; then
- $echo "$modename: you must specify an RM program" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- rmdirs=
-
- origobjdir="$objdir"
- for file in $files; do
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$dir" = "X$file"; then
- dir=.
- objdir="$origobjdir"
- else
- objdir="$dir/$origobjdir"
- fi
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- test "$mode" = uninstall && objdir="$dir"
-
- # Remember objdir for removal later, being careful to avoid duplicates
- if test "$mode" = clean; then
- case " $rmdirs " in
- *" $objdir "*) ;;
- *) rmdirs="$rmdirs $objdir" ;;
- esac
- fi
-
- # Don't error if the file doesn't exist and rm -f was used.
- if (test -L "$file") >/dev/null 2>&1 \
- || (test -h "$file") >/dev/null 2>&1 \
- || test -f "$file"; then
- :
- elif test -d "$file"; then
- exit_status=1
- continue
- elif test "$rmforce" = yes; then
- continue
- fi
-
- rmfiles="$file"
-
- case $name in
- *.la)
- # Possibly a libtool archive, so verify it.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- . $dir/$name
-
- # Delete the libtool libraries and symlinks.
- for n in $library_names; do
- rmfiles="$rmfiles $objdir/$n"
- done
- test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
-
- case "$mode" in
- clean)
- case " $library_names " in
- # " " in the beginning catches empty $dlname
- *" $dlname "*) ;;
- *) rmfiles="$rmfiles $objdir/$dlname" ;;
- esac
- test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
- ;;
- uninstall)
- if test -n "$library_names"; then
- # Do each command in the postuninstall commands.
- cmds=$postuninstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd"
- if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
- IFS="$save_ifs"
- fi
-
- if test -n "$old_library"; then
- # Do each command in the old_postuninstall commands.
- cmds=$old_postuninstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd"
- if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
- IFS="$save_ifs"
- fi
- # FIXME: should reinstall the best remaining shared library.
- ;;
- esac
- fi
- ;;
-
- *.lo)
- # Possibly a libtool object, so verify it.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-
- # Read the .lo file
- . $dir/$name
-
- # Add PIC object to the list of files to remove.
- if test -n "$pic_object" \
- && test "$pic_object" != none; then
- rmfiles="$rmfiles $dir/$pic_object"
- fi
-
- # Add non-PIC object to the list of files to remove.
- if test -n "$non_pic_object" \
- && test "$non_pic_object" != none; then
- rmfiles="$rmfiles $dir/$non_pic_object"
- fi
- fi
- ;;
-
- *)
- if test "$mode" = clean ; then
- noexename=$name
- case $file in
- *.exe)
- file=`$echo $file|${SED} 's,.exe$,,'`
- noexename=`$echo $name|${SED} 's,.exe$,,'`
- # $file with .exe has already been added to rmfiles,
- # add $file without .exe
- rmfiles="$rmfiles $file"
- ;;
- esac
- # Do a test to see if this is a libtool program.
- if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- relink_command=
- . $dir/$noexename
-
- # note $name still contains .exe if it was in $file originally
- # as does the version of $file that was added into $rmfiles
- rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
- if test "$fast_install" = yes && test -n "$relink_command"; then
- rmfiles="$rmfiles $objdir/lt-$name"
- fi
- if test "X$noexename" != "X$name" ; then
- rmfiles="$rmfiles $objdir/lt-${noexename}.c"
- fi
- fi
- fi
- ;;
- esac
- $show "$rm $rmfiles"
- $run $rm $rmfiles || exit_status=1
- done
- objdir="$origobjdir"
-
- # Try to remove the ${objdir}s in the directories where we deleted files
- for dir in $rmdirs; do
- if test -d "$dir"; then
- $show "rmdir $dir"
- $run rmdir $dir >/dev/null 2>&1
- fi
- done
-
- exit $exit_status
- ;;
-
- "")
- $echo "$modename: you must specify a MODE" 1>&2
- $echo "$generic_help" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- if test -z "$exec_cmd"; then
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$generic_help" 1>&2
- exit $EXIT_FAILURE
- fi
-fi # test -z "$show_help"
-
-if test -n "$exec_cmd"; then
- eval exec $exec_cmd
- exit $EXIT_FAILURE
-fi
-
-# We need to display help for each of the modes.
-case $mode in
-"") $echo \
-"Usage: $modename [OPTION]... [MODE-ARG]...
-
-Provide generalized library-building support services.
-
- --config show all configuration variables
- --debug enable verbose shell tracing
--n, --dry-run display commands without modifying any files
- --features display basic configuration information and exit
- --finish same as \`--mode=finish'
- --help display this help message and exit
- --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
- --quiet same as \`--silent'
- --silent don't print informational messages
- --tag=TAG use configuration variables from tag TAG
- --version print version information
-
-MODE must be one of the following:
-
- clean remove files from the build directory
- compile compile a source file into a libtool object
- execute automatically set library path, then run a program
- finish complete the installation of libtool libraries
- install install libraries or executables
- link create a library or an executable
- uninstall remove libraries from an installed directory
-
-MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE.
-
-Report bugs to <bug-libtool@gnu.org>."
- exit $EXIT_SUCCESS
- ;;
-
-clean)
- $echo \
-"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
-
-Remove files from the build directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, object or program, all the files associated
-with it are deleted. Otherwise, only FILE itself is deleted using RM."
- ;;
-
-compile)
- $echo \
-"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
- -o OUTPUT-FILE set the output file name to OUTPUT-FILE
- -prefer-pic try to building PIC objects only
- -prefer-non-pic try to building non-PIC objects only
- -static always build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
- ;;
-
-execute)
- $echo \
-"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
- -dlopen FILE add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
- ;;
-
-finish)
- $echo \
-"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges. Use
-the \`--dry-run' option if you just want to see what would be executed."
- ;;
-
-install)
- $echo \
-"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command. The first component should be
-either the \`install' or \`cp' program.
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
- ;;
-
-link)
- $echo \
-"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
- -all-static do not do any dynamic linking at all
- -avoid-version do not add a version suffix if possible
- -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
- -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
- -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
- -export-symbols SYMFILE
- try to export only the symbols listed in SYMFILE
- -export-symbols-regex REGEX
- try to export only the symbols matching REGEX
- -LLIBDIR search LIBDIR for required installed libraries
- -lNAME OUTPUT-FILE requires the installed library libNAME
- -module build a library that can dlopened
- -no-fast-install disable the fast-install mode
- -no-install link a not-installable executable
- -no-undefined declare that a library does not refer to external symbols
- -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
- -objectlist FILE Use a list of object files found in FILE to specify objects
- -precious-files-regex REGEX
- don't remove output files matching REGEX
- -release RELEASE specify package release information
- -rpath LIBDIR the created library will eventually be installed in LIBDIR
- -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
- -static do not do any dynamic linking of libtool libraries
- -version-info CURRENT[:REVISION[:AGE]]
- specify library version info [each variable defaults to 0]
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename. Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
- ;;
-
-uninstall)
- $echo \
-"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
- ;;
-
-*)
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
-esac
-
-$echo
-$echo "Try \`$modename --help' for more information about other modes."
-
-exit $?
-
-# The TAGs below are defined such that we never get into a situation
-# in which we disable both kinds of libraries. Given conflicting
-# choices, we go for a static library, that is the most portable,
-# since we can't tell whether shared libraries were disabled because
-# the user asked for that or because the platform doesn't support
-# them. This is particularly important on AIX, because we don't
-# support having both static and shared libraries enabled at the same
-# time on that platform, so we default to a shared-only configuration.
-# If a disable-shared tag is given, we'll fallback to a static-only
-# configuration. But we'll never go from static-only to shared-only.
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-disable_libs=shared
-# ### END LIBTOOL TAG CONFIG: disable-shared
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-static
-disable_libs=static
-# ### END LIBTOOL TAG CONFIG: disable-static
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/missing b/missing
deleted file mode 100755
index 894e786..0000000
--- a/missing
+++ /dev/null
@@ -1,360 +0,0 @@
-#! /bin/sh
-# Common stub for a few missing GNU programs while installing.
-
-scriptversion=2005-06-08.21
-
-# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-if test $# -eq 0; then
- echo 1>&2 "Try \`$0 --help' for more information"
- exit 1
-fi
-
-run=:
-
-# In the cases where this matters, `missing' is being run in the
-# srcdir already.
-if test -f configure.ac; then
- configure_ac=configure.ac
-else
- configure_ac=configure.in
-fi
-
-msg="missing on your system"
-
-case "$1" in
---run)
- # Try to run requested program, and just exit if it succeeds.
- run=
- shift
- "$@" && exit 0
- # Exit code 63 means version mismatch. This often happens
- # when the user try to use an ancient version of a tool on
- # a file that requires a minimum version. In this case we
- # we should proceed has if the program had been absent, or
- # if --run hadn't been passed.
- if test $? = 63; then
- run=:
- msg="probably too old"
- fi
- ;;
-
- -h|--h|--he|--hel|--help)
- echo "\
-$0 [OPTION]... PROGRAM [ARGUMENT]...
-
-Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
-error status if there is no known handling for PROGRAM.
-
-Options:
- -h, --help display this help and exit
- -v, --version output version information and exit
- --run try to run the given command, and emulate it if it fails
-
-Supported PROGRAM values:
- aclocal touch file \`aclocal.m4'
- autoconf touch file \`configure'
- autoheader touch file \`config.h.in'
- automake touch all \`Makefile.in' files
- bison create \`y.tab.[ch]', if possible, from existing .[ch]
- flex create \`lex.yy.c', if possible, from existing .c
- help2man touch the output file
- lex create \`lex.yy.c', if possible, from existing .c
- makeinfo touch the output file
- tar try tar, gnutar, gtar, then tar without non-portable flags
- yacc create \`y.tab.[ch]', if possible, from existing .[ch]
-
-Send bug reports to <bug-automake@gnu.org>."
- exit $?
- ;;
-
- -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
- echo "missing $scriptversion (GNU Automake)"
- exit $?
- ;;
-
- -*)
- echo 1>&2 "$0: Unknown \`$1' option"
- echo 1>&2 "Try \`$0 --help' for more information"
- exit 1
- ;;
-
-esac
-
-# Now exit if we have it, but it failed. Also exit now if we
-# don't have it and --version was passed (most likely to detect
-# the program).
-case "$1" in
- lex|yacc)
- # Not GNU programs, they don't have --version.
- ;;
-
- tar)
- if test -n "$run"; then
- echo 1>&2 "ERROR: \`tar' requires --run"
- exit 1
- elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
- exit 1
- fi
- ;;
-
- *)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
- # Could not run --version or --help. This is probably someone
- # running `$TOOL --version' or `$TOOL --help' to check whether
- # $TOOL exists and not knowing $TOOL uses missing.
- exit 1
- fi
- ;;
-esac
-
-# If it does not exist, or fails to run (possibly an outdated version),
-# try to emulate it.
-case "$1" in
- aclocal*)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`acinclude.m4' or \`${configure_ac}'. You might want
- to install the \`Automake' and \`Perl' packages. Grab them from
- any GNU archive site."
- touch aclocal.m4
- ;;
-
- autoconf)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`${configure_ac}'. You might want to install the
- \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
- archive site."
- touch configure
- ;;
-
- autoheader)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`acconfig.h' or \`${configure_ac}'. You might want
- to install the \`Autoconf' and \`GNU m4' packages. Grab them
- from any GNU archive site."
- files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
- test -z "$files" && files="config.h"
- touch_files=
- for f in $files; do
- case "$f" in
- *:*) touch_files="$touch_files "`echo "$f" |
- sed -e 's/^[^:]*://' -e 's/:.*//'`;;
- *) touch_files="$touch_files $f.in";;
- esac
- done
- touch $touch_files
- ;;
-
- automake*)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
- You might want to install the \`Automake' and \`Perl' packages.
- Grab them from any GNU archive site."
- find . -type f -name Makefile.am -print |
- sed 's/\.am$/.in/' |
- while read f; do touch "$f"; done
- ;;
-
- autom4te)
- echo 1>&2 "\
-WARNING: \`$1' is needed, but is $msg.
- You might have modified some files without having the
- proper tools for further handling them.
- You can get \`$1' as part of \`Autoconf' from any GNU
- archive site."
-
- file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
- test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
- if test -f "$file"; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo "#! /bin/sh"
- echo "# Created by GNU Automake missing as a replacement of"
- echo "# $ $@"
- echo "exit 0"
- chmod +x $file
- exit 1
- fi
- ;;
-
- bison|yacc)
- echo 1>&2 "\
-WARNING: \`$1' $msg. You should only need it if
- you modified a \`.y' file. You may need the \`Bison' package
- in order for those modifications to take effect. You can get
- \`Bison' from any GNU archive site."
- rm -f y.tab.c y.tab.h
- if [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.y)
- SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.c
- fi
- SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.h
- fi
- ;;
- esac
- fi
- if [ ! -f y.tab.h ]; then
- echo >y.tab.h
- fi
- if [ ! -f y.tab.c ]; then
- echo 'main() { return 0; }' >y.tab.c
- fi
- ;;
-
- lex|flex)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified a \`.l' file. You may need the \`Flex' package
- in order for those modifications to take effect. You can get
- \`Flex' from any GNU archive site."
- rm -f lex.yy.c
- if [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.l)
- SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" lex.yy.c
- fi
- ;;
- esac
- fi
- if [ ! -f lex.yy.c ]; then
- echo 'main() { return 0; }' >lex.yy.c
- fi
- ;;
-
- help2man)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified a dependency of a manual page. You may need the
- \`Help2man' package in order for those modifications to take
- effect. You can get \`Help2man' from any GNU archive site."
-
- file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
- if test -z "$file"; then
- file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
- fi
- if [ -f "$file" ]; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo ".ab help2man is required to generate this page"
- exit 1
- fi
- ;;
-
- makeinfo)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified a \`.texi' or \`.texinfo' file, or any other file
- indirectly affecting the aspect of the manual. The spurious
- call might also be the consequence of using a buggy \`make' (AIX,
- DU, IRIX). You might want to install the \`Texinfo' package or
- the \`GNU make' package. Grab either from any GNU archive site."
- # The file to touch is that specified with -o ...
- file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
- if test -z "$file"; then
- # ... or it is the one specified with @setfilename ...
- infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
- file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
- # ... or it is derived from the source name (dir/f.texi becomes f.info)
- test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
- fi
- # If the file does not exist, the user really needs makeinfo;
- # let's fail without touching anything.
- test -f $file || exit 1
- touch $file
- ;;
-
- tar)
- shift
-
- # We have already tried tar in the generic part.
- # Look for gnutar/gtar before invocation to avoid ugly error
- # messages.
- if (gnutar --version > /dev/null 2>&1); then
- gnutar "$@" && exit 0
- fi
- if (gtar --version > /dev/null 2>&1); then
- gtar "$@" && exit 0
- fi
- firstarg="$1"
- if shift; then
- case "$firstarg" in
- *o*)
- firstarg=`echo "$firstarg" | sed s/o//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- case "$firstarg" in
- *h*)
- firstarg=`echo "$firstarg" | sed s/h//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- fi
-
- echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
- You may want to install GNU tar or Free paxutils, or check the
- command line arguments."
- exit 1
- ;;
-
- *)
- echo 1>&2 "\
-WARNING: \`$1' is needed, and is $msg.
- You might have modified some files without having the
- proper tools for further handling them. Check the \`README' file,
- it often tells you about the needed prerequisites for installing
- this package. You may also peek at any GNU archive site, in case
- some other package would contain this missing \`$1' program."
- exit 1
- ;;
-esac
-
-exit 0
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
-# End:
diff --git a/talk/Makefile.am b/talk/Makefile.am
deleted file mode 100755
index dc6cc26..0000000
--- a/talk/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-SUBDIRS=base xmllite xmpp p2p session third_party examples
-
-EXTRA_DIST=libjingle.sln libjingle.vcproj
diff --git a/talk/base/Equifax_Secure_Global_eBusiness_CA-1.h b/talk/base/Equifax_Secure_Global_eBusiness_CA-1.h
old mode 100755
new mode 100644
diff --git a/talk/base/Makefile.am b/talk/base/Makefile.am
deleted file mode 100755
index 57a9962..0000000
--- a/talk/base/Makefile.am
+++ /dev/null
@@ -1,152 +0,0 @@
-libcricketbase_la_SOURCES = socketaddress.cc \
- time.cc \
- asyncudpsocket.cc \
- messagequeue.cc \
- thread.cc \
- physicalsocketserver.cc \
- bytebuffer.cc \
- asyncpacketsocket.cc \
- network.cc \
- asynctcpsocket.cc \
- socketadapters.cc \
- md5c.c \
- base64.cc \
- task.cc \
- taskrunner.cc \
- host.cc \
- proxydetect.cc \
- socketaddresspair.cc \
- stringencode.cc \
- stringdigest.cc \
- stringutils.cc \
- proxyinfo.cc \
- common.cc \
- logging.cc \
- stream.cc \
- ssladapter.cc \
- openssladapter.cc \
- helpers.cc \
- asynchttprequest.cc \
- firewallsocketserver.cc \
- httpcommon.cc \
- httpbase.cc \
- httpclient.cc \
- httpserver.cc \
- socketpool.cc \
- signalthread.cc \
- autodetectproxy.cc \
- urlencode.cc \
- pathutils.cc \
- fileutils.cc \
- unixfilesystem.cc \
- tarstream.cc \
- streamutils.cc \
- diskcache.cc \
- diskcachestd.cc
-
-libcrickettest_la_SOURCES = testclient.cc \
- natserver.cc \
- natsocketfactory.cc \
- nattypes.cc \
- virtualsocketserver.cc
-
-noinst_HEADERS = asyncfile.h \
- common.h \
- convert.h \
- asyncpacketsocket.h \
- socketfactory.h \
- asyncsocket.h \
- socket.h \
- asynctcpsocket.h \
- linked_ptr.h \
- asyncudpsocket.h \
- logging.h \
- socketserver.h \
- base64.h \
- md5.h \
- stl_decl.h \
- basicdefs.h \
- messagequeue.h \
- basictypes.h \
- stringdigest.h \
- stringencode.h \
- stringutils.h \
- bytebuffer.h \
- task.h \
- byteorder.h \
- taskrunner.h \
- criticalsection.h \
- network.h \
- thread.h \
- time.h \
- physicalsocketserver.h \
- proxyinfo.h \
- host.h \
- scoped_ptr.h \
- sigslot.h \
- winping.h \
- socketadapters.h \
- socketaddress.h \
- host.h \
- socketaddresspair.h \
- Equifax_Secure_Global_eBusiness_CA-1.h \
- stream.h \
- ssladapter.h \
- openssladapter.h \
- cryptstring.h \
- httpbase.h \
- httpclient.h \
- httpcommon.h \
- httpserver.h \
- httpcommon-inl.h \
- proxydetect.h \
- helpers.h \
- socketpool.h \
- asynchttprequest.h \
- signalthread.h \
- firewallsocketserver.h \
- diskcache.h \
- pathutils.h \
- socketstream.h \
- autodetectproxy.h \
- urlencode.h \
- fileutils.h \
- unixfilesystem.h \
- win32filesystem.h \
- tarstream.h \
- streamutils.h \
- diskcachestd.h \
- testclient.h \
- natserver.h \
- nattypes.h \
- natsocketfactory.h \
- virtualsocketserver.h \
- event.h
-
-AM_CXXFLAGS = -DPOSIX
-DEFAULT_INCLUDES = -I$(top_srcdir)
-
-noinst_LTLIBRARIES = libcricketbase.la libcrickettest.la
-noinst_PROGRAMS = natserver nat_unittest virtualsocket_unittest
-
-natserver_SOURCES = natserver_main.cc
-natserver_LDADD = libcrickettest.la libcricketbase.la -lpthread
-nat_unittest_SOURCES = nat_unittest.cc
-nat_unittest_LDADD = libcrickettest.la libcricketbase.la -lpthread
-virtualsocket_unittest_SOURCES = virtualsocket_unittest.cc
-virtualsocket_unittest_LDADD = libcrickettest.la libcricketbase.la -lpthread
-
-EXTRA_DIST = diskcache_win32.h \
- diskcache_win32.cc \
- win32.h \
- winping.h \
- winping.cc \
- win32filesystem.cc \
- win32socketserver.cc \
- win32socketserver.h \
- win32window.h \
- winfirewall.h \
- winfirewall.cc \
- schanneladapter.h \
- schanneladapter.cc \
- sec_buffer.h
diff --git a/talk/base/natsocketfactory.h b/talk/base/asyncfile.cc
old mode 100755
new mode 100644
similarity index 64%
copy from talk/base/natsocketfactory.h
copy to talk/base/asyncfile.cc
index a689158..5c6e11d
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/asyncfile.cc
@@ -1,51 +1,38 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
-
-#include "talk/base/socketfactory.h"
+#include "talk/base/asyncfile.h"
namespace talk_base {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+AsyncFile::AsyncFile() {
+}
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+AsyncFile::~AsyncFile() {
+}
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
-};
-
-} // namespace talk_base
-
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+} // namespace talk_base
diff --git a/talk/base/asyncfile.h b/talk/base/asyncfile.h
old mode 100755
new mode 100644
index 1437979..8af52be
--- a/talk/base/asyncfile.h
+++ b/talk/base/asyncfile.h
@@ -1,27 +1,27 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -35,8 +35,9 @@
// Provides the ability to perform file I/O asynchronously.
// TODO: Create a common base class with AsyncSocket.
class AsyncFile {
-public:
- virtual ~AsyncFile() {}
+ public:
+ AsyncFile();
+ virtual ~AsyncFile();
// Determines whether the file will receive read events.
virtual bool readable() = 0;
@@ -48,9 +49,9 @@
sigslot::signal1<AsyncFile*> SignalReadEvent;
sigslot::signal1<AsyncFile*> SignalWriteEvent;
- sigslot::signal2<AsyncFile*,int> SignalCloseEvent;
+ sigslot::signal2<AsyncFile*, int> SignalCloseEvent;
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_ASYNCFILE_H__
+#endif // TALK_BASE_ASYNCFILE_H__
diff --git a/talk/base/asynchttprequest.cc b/talk/base/asynchttprequest.cc
old mode 100755
new mode 100644
index bf7bc85..1e05d82
--- a/talk/base/asynchttprequest.cc
+++ b/talk/base/asynchttprequest.cc
@@ -1,155 +1,111 @@
-#include "talk/base/common.h"
-#include "talk/base/firewallsocketserver.h"
-#include "talk/base/httpclient.h"
-#include "talk/base/logging.h"
-#include "talk/base/physicalsocketserver.h"
-#include "talk/base/socketadapters.h"
-#include "talk/base/socketpool.h"
-#include "talk/base/ssladapter.h"
+/*
+ * libjingle
+ * Copyright 2004--2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include "talk/base/asynchttprequest.h"
-using namespace talk_base;
+namespace talk_base {
-///////////////////////////////////////////////////////////////////////////////
-// HttpMonitor
-///////////////////////////////////////////////////////////////////////////////
-
-HttpMonitor::HttpMonitor(SocketServer *ss) {
- ASSERT(talk_base::Thread::Current() != NULL);
- ss_ = ss;
- reset();
-}
-
-void HttpMonitor::Connect(talk_base::HttpClient *http) {
- http->SignalHttpClientComplete.connect(this,
- &HttpMonitor::OnHttpClientComplete);
-}
-
-void HttpMonitor::OnHttpClientComplete(talk_base::HttpClient * http, int err) {
- complete_ = true;
- err_ = err;
- ss_->WakeUp();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// SslSocketFactory
-///////////////////////////////////////////////////////////////////////////////
-
-talk_base::Socket * SslSocketFactory::CreateSocket(int type) {
- return factory_->CreateSocket(type);
-}
-
-talk_base::AsyncSocket * SslSocketFactory::CreateAsyncSocket(int type) {
- talk_base::AsyncSocket * socket = factory_->CreateAsyncSocket(type);
- if (!socket)
- return 0;
-
- // Binary logging happens at the lowest level
- if (!logging_label_.empty() && binary_mode_) {
- socket = new talk_base::LoggingSocketAdapter(socket, logging_level_,
- logging_label_.c_str(),
- binary_mode_);
- }
-
- if (proxy_.type) {
- talk_base::AsyncSocket * proxy_socket = 0;
- if (proxy_.type == talk_base::PROXY_SOCKS5) {
- proxy_socket = new talk_base::AsyncSocksProxySocket(socket, proxy_.address,
- proxy_.username, proxy_.password);
- } else {
- // Note: we are trying unknown proxies as HTTPS currently
- proxy_socket = new talk_base::AsyncHttpsProxySocket(socket,
- agent_, proxy_.address,
- proxy_.username, proxy_.password);
- }
- if (!proxy_socket) {
- delete socket;
- return 0;
- }
- socket = proxy_socket; // for our purposes the proxy is now the socket
- }
-
- if (!hostname_.empty()) {
- talk_base::SSLAdapter * ssl_adapter = talk_base::SSLAdapter::Create(socket);
- ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_);
- ssl_adapter->StartSSL(hostname_.c_str(), true);
- socket = ssl_adapter;
- }
-
- // Regular logging occurs at the highest level
- if (!logging_label_.empty() && !binary_mode_) {
- socket = new talk_base::LoggingSocketAdapter(socket, logging_level_,
- logging_label_.c_str(),
- binary_mode_);
- }
- return socket;
-}
+enum { MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE };
+static const int kDefaultHTTPTimeout = 30 * 1000; // 30 sec
///////////////////////////////////////////////////////////////////////////////
// AsyncHttpRequest
///////////////////////////////////////////////////////////////////////////////
-const int kDefaultHTTPTimeout = 30 * 1000; // 30 sec
-
AsyncHttpRequest::AsyncHttpRequest(const std::string &user_agent)
-: firewall_(0), port_(80), secure_(false),
- timeout_(kDefaultHTTPTimeout), fail_redirect_(false),
- client_(user_agent.c_str(), NULL)
-{
+ : firewall_(NULL), port_(80), secure_(false),
+ timeout_(kDefaultHTTPTimeout), fail_redirect_(false),
+ factory_(Thread::Current()->socketserver(), user_agent),
+ pool_(&factory_), client_(user_agent.c_str(), &pool_), error_(HE_NONE) {
+ client_.SignalHttpClientComplete.connect(this,
+ &AsyncHttpRequest::OnComplete);
}
-void AsyncHttpRequest::DoWork() {
- // TODO: Rewrite this to use the thread's native socket server, and a more
- // natural flow?
+AsyncHttpRequest::~AsyncHttpRequest() {
+}
- talk_base::PhysicalSocketServer physical;
- talk_base::SocketServer * ss = &physical;
- if (firewall_) {
- ss = new talk_base::FirewallSocketServer(ss, firewall_);
- }
-
- SslSocketFactory factory(ss, client_.agent());
- factory.SetProxy(proxy_);
+void AsyncHttpRequest::OnWorkStart() {
+ factory_.SetProxy(proxy_);
if (secure_)
- factory.UseSSL(host_.c_str());
+ factory_.UseSSL(host_.c_str());
- //factory.SetLogging("AsyncHttpRequest");
-
- talk_base::ReuseSocketPool pool(&factory);
- client_.set_pool(&pool);
-
- bool transparent_proxy = (port_ == 80)
- && ((proxy_.type == talk_base::PROXY_HTTPS)
- || (proxy_.type == talk_base::PROXY_UNKNOWN));
-
+ bool transparent_proxy = (port_ == 80) &&
+ ((proxy_.type == PROXY_HTTPS) || (proxy_.type == PROXY_UNKNOWN));
if (transparent_proxy) {
client_.set_proxy(proxy_);
}
client_.set_fail_redirect(fail_redirect_);
+ client_.set_server(SocketAddress(host_, port_));
- talk_base::SocketAddress server(host_, port_);
- client_.set_server(server);
+ LOG(LS_INFO) << "HttpRequest start: " << host_ + client_.request().path;
- HttpMonitor monitor(ss);
- monitor.Connect(&client_);
+ Thread::Current()->PostDelayed(timeout_, this, MSG_TIMEOUT);
client_.start();
- ss->Wait(timeout_, true);
- if (!monitor.done()) {
- LOG(LS_INFO) << "AsyncHttpRequest request timed out";
- client_.reset();
- return;
- }
-
- if (monitor.error()) {
- LOG(LS_INFO) << "AsyncHttpRequest request error: " << monitor.error();
- if (monitor.error() == talk_base::HE_AUTH) {
- //proxy_auth_required_ = true;
+}
+
+void AsyncHttpRequest::OnWorkStop() {
+ // worker is already quitting, no need to explicitly quit
+ LOG(LS_INFO) << "HttpRequest cancelled";
+}
+
+void AsyncHttpRequest::OnComplete(HttpClient* client, HttpErrorType error) {
+ Thread::Current()->Clear(this, MSG_TIMEOUT);
+
+ set_error(error);
+ if (!error) {
+ LOG(LS_INFO) << "HttpRequest completed successfully";
+
+ std::string value;
+ if (client_.response().hasHeader(HH_LOCATION, &value)) {
+ response_redirect_ = value.c_str();
}
+ } else {
+ LOG(LS_INFO) << "HttpRequest completed with error: " << error;
+ }
+
+ worker()->Quit();
+}
+
+void AsyncHttpRequest::OnMessage(Message* message) {
+ if (message->message_id != MSG_TIMEOUT) {
+ SignalThread::OnMessage(message);
return;
}
- std::string value;
- if (client_.response().hasHeader(HH_LOCATION, &value)) {
- response_redirect_ = value.c_str();
- }
+ LOG(LS_INFO) << "HttpRequest timed out";
+ client_.reset();
+ worker()->Quit();
}
+
+void AsyncHttpRequest::DoWork() {
+ // Do nothing while we wait for the request to finish. We only do this so
+ // that we can be a SignalThread; in the future this class should not be
+ // a SignalThread, since it does not need to spawn a new thread.
+ Thread::Current()->ProcessMessages(kForever);
+}
+
+} // namespace talk_base
diff --git a/talk/base/asynchttprequest.h b/talk/base/asynchttprequest.h
old mode 100755
new mode 100644
index 65bfa26..f5d7f46
--- a/talk/base/asynchttprequest.h
+++ b/talk/base/asynchttprequest.h
@@ -1,34 +1,59 @@
-#ifndef _ASYNCHTTPREQUEST_H_
-#define _ASYNCHTTPREQUEST_H_
+/*
+ * libjingle
+ * Copyright 2004--2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TALK_BASE_ASYNCHTTPREQUEST_H_
+#define TALK_BASE_ASYNCHTTPREQUEST_H_
+
+#include <string>
+#include "talk/base/event.h"
#include "talk/base/httpclient.h"
-#include "talk/base/logging.h"
-#include "talk/base/proxyinfo.h"
-#include "talk/base/socketserver.h"
-#include "talk/base/thread.h"
#include "talk/base/signalthread.h"
+#include "talk/base/socketpool.h"
+#include "talk/base/sslsocketfactory.h"
namespace talk_base {
+class FirewallManager;
+
///////////////////////////////////////////////////////////////////////////////
// AsyncHttpRequest
// Performs an HTTP request on a background thread. Notifies on the foreground
// thread once the request is done (successfully or unsuccessfully).
///////////////////////////////////////////////////////////////////////////////
-class FirewallManager;
-class MemoryStream;
+class AsyncHttpRequest : public SignalThread {
+ public:
+ explicit AsyncHttpRequest(const std::string &user_agent);
+ ~AsyncHttpRequest();
-class AsyncHttpRequest:
- public SignalThread,
- public sigslot::has_slots<> {
-public:
- AsyncHttpRequest(const std::string &user_agent);
-
- void set_proxy(const talk_base::ProxyInfo& proxy) {
+ void set_proxy(const ProxyInfo& proxy) {
proxy_ = proxy;
}
- void set_firewall(talk_base::FirewallManager * firewall) {
+ void set_firewall(FirewallManager * firewall) {
firewall_ = firewall;
}
@@ -39,102 +64,49 @@
// The port to connect to on the target host.
int port() { return port_; }
void set_port(int port) { port_ = port; }
-
- // Whether the request should use SSL.
+
+ // Whether the request should use SSL.
bool secure() { return secure_; }
void set_secure(bool secure) { secure_ = secure; }
- // Returns the redirect when redirection occurs
- const std::string& response_redirect() { return response_redirect_; }
-
- // Time to wait on the download, in ms. Default is 5000 (5s)
+ // Time to wait on the download, in ms.
int timeout() { return timeout_; }
void set_timeout(int timeout) { timeout_ = timeout; }
// Fail redirects to allow analysis of redirect urls, etc.
bool fail_redirect() const { return fail_redirect_; }
- void set_fail_redirect(bool fail_redirect) { fail_redirect_ = fail_redirect; }
+ void set_fail_redirect(bool redirect) { fail_redirect_ = redirect; }
+
+ // Returns the redirect when redirection occurs
+ const std::string& response_redirect() { return response_redirect_; }
HttpRequestData& request() { return client_.request(); }
HttpResponseData& response() { return client_.response(); }
-
-private:
- // SignalThread Interface
+ HttpErrorType error() { return error_; }
+
+ protected:
+ void set_error(HttpErrorType error) { error_ = error; }
+ virtual void OnWorkStart();
+ virtual void OnWorkStop();
+ void OnComplete(HttpClient* client, HttpErrorType error);
+ virtual void OnMessage(Message* message);
virtual void DoWork();
-
- talk_base::ProxyInfo proxy_;
- talk_base::FirewallManager * firewall_;
+
+ private:
+ ProxyInfo proxy_;
+ FirewallManager* firewall_;
std::string host_;
int port_;
bool secure_;
int timeout_;
bool fail_redirect_;
+ SslSocketFactory factory_;
+ ReuseSocketPool pool_;
HttpClient client_;
+ HttpErrorType error_;
std::string response_redirect_;
};
-///////////////////////////////////////////////////////////////////////////////
-// HttpMonitor
-///////////////////////////////////////////////////////////////////////////////
+} // namespace talk_base
-class HttpMonitor : public sigslot::has_slots<> {
-public:
- HttpMonitor(SocketServer *ss);
-
- void reset() { complete_ = false; }
-
- bool done() const { return complete_; }
- int error() const { return err_; }
-
- void Connect(talk_base::HttpClient* http);
- void OnHttpClientComplete(talk_base::HttpClient * http, int err);
-
-private:
- bool complete_;
- int err_;
- SocketServer *ss_;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// SslSocketFactory
-///////////////////////////////////////////////////////////////////////////////
-
-class SslSocketFactory : public talk_base::SocketFactory {
- public:
- SslSocketFactory(talk_base::SocketFactory * factory, const std::string &user_agent)
- : factory_(factory), logging_level_(talk_base::LS_VERBOSE),
- binary_mode_(false), agent_(user_agent) { }
-
- void UseSSL(const char * hostname) { hostname_ = hostname; }
- void DisableSSL() { hostname_.clear(); }
-
- void SetProxy(const talk_base::ProxyInfo& proxy) { proxy_ = proxy; }
- const talk_base::ProxyInfo& proxy() const { return proxy_; }
- bool ignore_bad_cert() {return ignore_bad_cert_;}
- void SetIgnoreBadCert(bool ignore) { ignore_bad_cert_ = ignore; }
-
- void SetLogging(talk_base::LoggingSeverity level, const std::string& label,
- bool binary_mode = false) {
- logging_level_ = level;
- logging_label_ = label;
- binary_mode_ = binary_mode;
- }
-
- virtual talk_base::Socket * CreateSocket(int type);
- virtual talk_base::AsyncSocket * CreateAsyncSocket(int type);
-
-private:
- talk_base::SocketFactory * factory_;
- talk_base::ProxyInfo proxy_;
- std::string hostname_, logging_label_;
- talk_base::LoggingSeverity logging_level_;
- bool binary_mode_;
- std::string agent_;
- bool ignore_bad_cert_;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-} // namespace talk_base_
-
-#endif // _ASYNCHTTPREQUEST_H_
+#endif // TALK_BASE_ASYNCHTTPREQUEST_H_
diff --git a/talk/base/asyncpacketsocket.cc b/talk/base/asyncpacketsocket.cc
old mode 100755
new mode 100644
index 37ba058..7628c12
--- a/talk/base/asyncpacketsocket.cc
+++ b/talk/base/asyncpacketsocket.cc
@@ -69,6 +69,14 @@
return socket_->Close();
}
+Socket::ConnState AsyncPacketSocket::GetState() const {
+ return socket_->GetState();
+}
+
+int AsyncPacketSocket::GetOption(Socket::Option opt, int* value) {
+ return socket_->GetOption(opt, value);
+}
+
int AsyncPacketSocket::SetOption(Socket::Option opt, int value) {
return socket_->SetOption(opt, value);
}
@@ -81,4 +89,4 @@
return socket_->SetError(error);
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/asyncpacketsocket.h b/talk/base/asyncpacketsocket.h
old mode 100755
new mode 100644
index c6172a7..9cb82ec
--- a/talk/base/asyncpacketsocket.h
+++ b/talk/base/asyncpacketsocket.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_ASYNCPACKETSOCKET_H__
-#define TALK_BASE_ASYNCPACKETSOCKET_H__
+#ifndef TALK_BASE_ASYNCPACKETSOCKET_H_
+#define TALK_BASE_ASYNCPACKETSOCKET_H_
#include "talk/base/asyncsocket.h"
@@ -35,8 +35,8 @@
// Provides the ability to receive packets asynchronously. Sends are not
// buffered since it is acceptable to drop packets under high load.
class AsyncPacketSocket : public sigslot::has_slots<> {
-public:
- AsyncPacketSocket(AsyncSocket* socket);
+ public:
+ explicit AsyncPacketSocket(AsyncSocket* socket);
virtual ~AsyncPacketSocket();
// Relevant socket methods:
@@ -47,17 +47,22 @@
virtual int Send(const void *pv, size_t cb);
virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr);
virtual int Close();
+
+ virtual Socket::ConnState GetState() const;
+ virtual int GetOption(Socket::Option opt, int* value);
virtual int SetOption(Socket::Option opt, int value);
virtual int GetError() const;
virtual void SetError(int error);
// Emitted each time a packet is read.
- sigslot::signal4<const char*, size_t, const SocketAddress&, AsyncPacketSocket*> SignalReadPacket;
+ sigslot::signal4<const char*, size_t,
+ const SocketAddress&, AsyncPacketSocket*> SignalReadPacket;
-protected:
+ protected:
AsyncSocket* socket_;
+ DISALLOW_EVIL_CONSTRUCTORS(AsyncPacketSocket);
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_ASYNCPACKETSOCKET_H__
+#endif // TALK_BASE_ASYNCPACKETSOCKET_H_
diff --git a/talk/base/natsocketfactory.h b/talk/base/asyncsocket.cc
old mode 100755
new mode 100644
similarity index 61%
copy from talk/base/natsocketfactory.h
copy to talk/base/asyncsocket.cc
index a689158..d9ed94c
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/asyncsocket.cc
@@ -1,51 +1,61 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
-
-#include "talk/base/socketfactory.h"
+#include "talk/base/asyncsocket.h"
namespace talk_base {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+AsyncSocket::AsyncSocket() {
+}
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+AsyncSocket::~AsyncSocket() {
+}
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
-};
+AsyncSocketAdapter::AsyncSocketAdapter(AsyncSocket* socket) : socket_(NULL) {
+ Attach(socket);
+}
-} // namespace talk_base
+AsyncSocketAdapter::~AsyncSocketAdapter() {
+ delete socket_;
+}
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+void AsyncSocketAdapter::Attach(AsyncSocket* socket) {
+ ASSERT(!socket_);
+ socket_ = socket;
+ if (socket_) {
+ socket_->SignalConnectEvent.connect(this,
+ &AsyncSocketAdapter::OnConnectEvent);
+ socket_->SignalReadEvent.connect(this,
+ &AsyncSocketAdapter::OnReadEvent);
+ socket_->SignalWriteEvent.connect(this,
+ &AsyncSocketAdapter::OnWriteEvent);
+ socket_->SignalCloseEvent.connect(this,
+ &AsyncSocketAdapter::OnCloseEvent);
+ }
+}
+
+} // namespace talk_base
diff --git a/talk/base/asyncsocket.h b/talk/base/asyncsocket.h
old mode 100755
new mode 100644
index ad0dfb4..3d12984
--- a/talk/base/asyncsocket.h
+++ b/talk/base/asyncsocket.h
@@ -1,91 +1,133 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_ASYNCSOCKET_H__
-#define TALK_BASE_ASYNCSOCKET_H__
+#ifndef TALK_BASE_ASYNCSOCKET_H_
+#define TALK_BASE_ASYNCSOCKET_H_
+#include "talk/base/common.h"
#include "talk/base/sigslot.h"
#include "talk/base/socket.h"
namespace talk_base {
+// TODO: Remove Socket and rename AsyncSocket to Socket.
+
// Provides the ability to perform socket I/O asynchronously.
-class AsyncSocket : public Socket, public sigslot::has_slots<> {
-public:
- virtual ~AsyncSocket() {}
+class AsyncSocket : public Socket {
+ public:
+ AsyncSocket();
+ virtual ~AsyncSocket();
- sigslot::signal1<AsyncSocket*> SignalReadEvent; // ready to read
- sigslot::signal1<AsyncSocket*> SignalWriteEvent; // ready to write
- sigslot::signal1<AsyncSocket*> SignalConnectEvent; // connected
- sigslot::signal2<AsyncSocket*,int> SignalCloseEvent; // closed
- // TODO: error
+ virtual AsyncSocket* Accept(SocketAddress* paddr) = 0;
+
+ sigslot::signal1<AsyncSocket*> SignalReadEvent; // ready to read
+ sigslot::signal1<AsyncSocket*> SignalWriteEvent; // ready to write
+ sigslot::signal1<AsyncSocket*> SignalConnectEvent; // connected
+ sigslot::signal2<AsyncSocket*, int> SignalCloseEvent; // closed
};
-class AsyncSocketAdapter : public AsyncSocket {
-public:
- AsyncSocketAdapter(Socket * socket) : socket_(socket) {
+class AsyncSocketAdapter : public AsyncSocket, public sigslot::has_slots<> {
+ public:
+ // The adapted socket may explicitly be NULL, and later assigned using Attach.
+ // However, subclasses which support detached mode must override any methods
+ // that will be called during the detached period (usually GetState()), to
+ // avoid dereferencing a null pointer.
+ explicit AsyncSocketAdapter(AsyncSocket* socket);
+ virtual ~AsyncSocketAdapter();
+ void Attach(AsyncSocket* socket);
+ virtual SocketAddress GetLocalAddress() const {
+ return socket_->GetLocalAddress();
}
- AsyncSocketAdapter(AsyncSocket * socket) : socket_(socket) {
- socket->SignalConnectEvent.connect(this, &AsyncSocketAdapter::OnConnectEvent);
- socket->SignalReadEvent.connect(this, &AsyncSocketAdapter::OnReadEvent);
- socket->SignalWriteEvent.connect(this, &AsyncSocketAdapter::OnWriteEvent);
- socket->SignalCloseEvent.connect(this, &AsyncSocketAdapter::OnCloseEvent);
+ virtual SocketAddress GetRemoteAddress() const {
+ return socket_->GetRemoteAddress();
}
- virtual ~AsyncSocketAdapter() { delete socket_; }
+ virtual int Bind(const SocketAddress& addr) {
+ return socket_->Bind(addr);
+ }
+ virtual int Connect(const SocketAddress& addr) {
+ return socket_->Connect(addr);
+ }
+ virtual int Send(const void* pv, size_t cb) {
+ return socket_->Send(pv, cb);
+ }
+ virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
+ return socket_->SendTo(pv, cb, addr);
+ }
+ virtual int Recv(void* pv, size_t cb) {
+ return socket_->Recv(pv, cb);
+ }
+ virtual int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
+ return socket_->RecvFrom(pv, cb, paddr);
+ }
+ virtual int Listen(int backlog) {
+ return socket_->Listen(backlog);
+ }
+ virtual AsyncSocket* Accept(SocketAddress* paddr) {
+ return socket_->Accept(paddr);
+ }
+ virtual int Close() {
+ return socket_->Close();
+ }
+ virtual int GetError() const {
+ return socket_->GetError();
+ }
+ virtual void SetError(int error) {
+ return socket_->SetError(error);
+ }
+ virtual ConnState GetState() const {
+ return socket_->GetState();
+ }
+ virtual int EstimateMTU(uint16* mtu) {
+ return socket_->EstimateMTU(mtu);
+ }
+ virtual int GetOption(Option opt, int* value) {
+ return socket_->GetOption(opt, value);
+ }
+ virtual int SetOption(Option opt, int value) {
+ return socket_->SetOption(opt, value);
+ }
- virtual SocketAddress GetLocalAddress() const { return socket_->GetLocalAddress(); }
- virtual SocketAddress GetRemoteAddress() const { return socket_->GetRemoteAddress(); }
+ protected:
+ virtual void OnConnectEvent(AsyncSocket* socket) {
+ SignalConnectEvent(this);
+ }
+ virtual void OnReadEvent(AsyncSocket* socket) {
+ SignalReadEvent(this);
+ }
+ virtual void OnWriteEvent(AsyncSocket* socket) {
+ SignalWriteEvent(this);
+ }
+ virtual void OnCloseEvent(AsyncSocket* socket, int err) {
+ SignalCloseEvent(this, err);
+ }
- virtual int Bind(const SocketAddress& addr) { return socket_->Bind(addr); }
- virtual int Connect(const SocketAddress& addr) {return socket_->Connect(addr); }
- virtual int Send(const void *pv, size_t cb) { return socket_->Send(pv, cb); }
- virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr) { return socket_->SendTo(pv, cb, addr); }
- virtual int Recv(void *pv, size_t cb) { return socket_->Recv(pv, cb); }
- virtual int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) { return socket_->RecvFrom(pv, cb, paddr); }
- virtual int Listen(int backlog) { return socket_->Listen(backlog); }
- virtual Socket *Accept(SocketAddress *paddr) { return socket_->Accept(paddr); }
- virtual int Close() { return socket_->Close(); }
- virtual int GetError() const { return socket_->GetError(); }
- virtual void SetError(int error) { return socket_->SetError(error); }
-
- virtual ConnState GetState() const { return socket_->GetState(); }
-
- virtual int EstimateMTU(uint16* mtu) { return socket_->EstimateMTU(mtu); }
- virtual int SetOption(Option opt, int value) { return socket_->SetOption(opt, value); }
-
-protected:
- virtual void OnConnectEvent(AsyncSocket * socket) { SignalConnectEvent(this); }
- virtual void OnReadEvent(AsyncSocket * socket) { SignalReadEvent(this); }
- virtual void OnWriteEvent(AsyncSocket * socket) { SignalWriteEvent(this); }
- virtual void OnCloseEvent(AsyncSocket * socket, int err) { SignalCloseEvent(this, err); }
-
- Socket * socket_;
+ AsyncSocket* socket_;
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_ASYNCSOCKET_H__
+#endif // TALK_BASE_ASYNCSOCKET_H_
diff --git a/talk/base/asynctcpsocket.cc b/talk/base/asynctcpsocket.cc
old mode 100755
new mode 100644
index 84d1401..37c7a6c
--- a/talk/base/asynctcpsocket.cc
+++ b/talk/base/asynctcpsocket.cc
@@ -1,50 +1,41 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma warning(disable:4786)
-#endif
-
#include "talk/base/asynctcpsocket.h"
+
+#include <cstring>
+
#include "talk/base/byteorder.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::strerror;
-}
-#endif
-
#ifdef POSIX
-extern "C" {
#include <errno.h>
-}
-#endif // POSIX
+#endif // POSIX
namespace talk_base {
@@ -55,7 +46,17 @@
const size_t BUF_SIZE = MAX_PACKET_SIZE + PKT_LEN_SIZE;
-AsyncTCPSocket::AsyncTCPSocket(AsyncSocket* socket) : AsyncPacketSocket(socket), insize_(BUF_SIZE), inpos_(0), outsize_(BUF_SIZE), outpos_(0) {
+AsyncTCPSocket* AsyncTCPSocket::Create(SocketFactory* factory) {
+ AsyncSocket* sock = factory->CreateAsyncSocket(SOCK_STREAM);
+ return (sock) ? new AsyncTCPSocket(sock) : NULL;
+}
+
+AsyncTCPSocket::AsyncTCPSocket(AsyncSocket* socket)
+ : AsyncPacketSocket(socket),
+ insize_(BUF_SIZE),
+ inpos_(0),
+ outsize_(BUF_SIZE),
+ outpos_(0) {
inbuf_ = new char[insize_];
outbuf_ = new char[outsize_];
@@ -89,7 +90,7 @@
int res = Flush();
if (res <= 0) {
// drop packet if we made no progress
- outpos_ = 0;
+ outpos_ = 0;
return res;
}
@@ -97,7 +98,8 @@
return static_cast<int>(cb);
}
-int AsyncTCPSocket::SendTo(const void *pv, size_t cb, const SocketAddress& addr) {
+int AsyncTCPSocket::SendTo(const void *pv, size_t cb,
+ const SocketAddress& addr) {
if (addr == GetRemoteAddress())
return Send(pv, cb);
@@ -169,7 +171,7 @@
if (len < 0) {
// TODO: Do something better like forwarding the error to the user.
if (!socket_->IsBlocking()) {
- LOG(LS_ERROR) << "recvfrom: " << errno << " " << std::strerror(errno);
+ LOG_ERR(LS_ERROR) << "recvfrom";
}
return;
}
@@ -197,4 +199,4 @@
SignalClose(this, error);
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/asynctcpsocket.h b/talk/base/asynctcpsocket.h
old mode 100755
new mode 100644
index 2509451..8f24861
--- a/talk/base/asynctcpsocket.h
+++ b/talk/base/asynctcpsocket.h
@@ -1,34 +1,35 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_ASYNCTCPSOCKET_H__
-#define TALK_BASE_ASYNCTCPSOCKET_H__
+#ifndef TALK_BASE_ASYNCTCPSOCKET_H_
+#define TALK_BASE_ASYNCTCPSOCKET_H_
#include "talk/base/asyncpacketsocket.h"
+#include "talk/base/socketfactory.h"
namespace talk_base {
@@ -36,24 +37,22 @@
// are preserved, and drops packets silently on Send, rather than
// buffer them in user space.
class AsyncTCPSocket : public AsyncPacketSocket {
-public:
- AsyncTCPSocket(AsyncSocket* socket);
+ public:
+ static AsyncTCPSocket* Create(SocketFactory* factory);
+ explicit AsyncTCPSocket(AsyncSocket* socket);
virtual ~AsyncTCPSocket();
- virtual int Send(const void *pv, size_t cb);
- virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr);
+ virtual int Send(const void* pv, size_t cb);
+ virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr);
sigslot::signal1<AsyncTCPSocket*> SignalConnect;
- sigslot::signal2<AsyncTCPSocket*,int> SignalClose;
+ sigslot::signal2<AsyncTCPSocket*, int> SignalClose;
-protected:
- int SendRaw(const void * pv, size_t cb);
- virtual void ProcessInput(char * data, size_t& len);
+ protected:
+ int SendRaw(const void* pv, size_t cb);
+ virtual void ProcessInput(char* data, size_t& len);
-private:
- char* inbuf_, * outbuf_;
- size_t insize_, inpos_, outsize_, outpos_;
-
+ private:
int Flush();
// Called by the underlying socket
@@ -61,8 +60,11 @@
void OnReadEvent(AsyncSocket* socket);
void OnWriteEvent(AsyncSocket* socket);
void OnCloseEvent(AsyncSocket* socket, int error);
+
+ char* inbuf_, * outbuf_;
+ size_t insize_, inpos_, outsize_, outpos_;
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_ASYNCTCPSOCKET_H__
+#endif // TALK_BASE_ASYNCTCPSOCKET_H_
diff --git a/talk/base/asyncudpsocket.cc b/talk/base/asyncudpsocket.cc
old mode 100755
new mode 100644
index a0c967d..2899606
--- a/talk/base/asyncudpsocket.cc
+++ b/talk/base/asyncudpsocket.cc
@@ -29,34 +29,19 @@
#pragma warning(disable:4786)
#endif
-#include <cassert>
-#include <cstring>
-#include <iostream>
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
#include "talk/base/asyncudpsocket.h"
#include "talk/base/logging.h"
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::strerror;
-}
-#endif
-
namespace talk_base {
const int BUF_SIZE = 64 * 1024;
-AsyncUDPSocket::AsyncUDPSocket(AsyncSocket* socket) : AsyncPacketSocket(socket) {
+AsyncUDPSocket::AsyncUDPSocket(AsyncSocket* socket)
+ : AsyncPacketSocket(socket) {
+ ASSERT(socket_ != NULL);
size_ = BUF_SIZE;
buf_ = new char[size_];
- assert(socket_);
// The socket should start out readable but not writable.
socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
}
@@ -66,20 +51,24 @@
}
void AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) {
- assert(socket == socket_);
+ ASSERT(socket == socket_);
SocketAddress remote_addr;
int len = socket_->RecvFrom(buf_, size_, &remote_addr);
if (len < 0) {
+ // An error here typically means we got an ICMP error in response to our
+ // send datagram, indicating the remote address was unreachable.
+ // When doing ICE, this kind of thing will often happen.
// TODO: Do something better like forwarding the error to the user.
- PLOG(LS_ERROR, socket_->GetError()) << "recvfrom";
+ SocketAddress local_addr = socket_->GetLocalAddress();
+ LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToString() << "] "
+ << "receive failed with error " << socket_->GetError();
return;
}
- // TODO: Make sure that we got all of the packet. If we did not, then we
- // should resize our buffer to be large enough.
-
+ // TODO: Make sure that we got all of the packet.
+ // If we did not, then we should resize our buffer to be large enough.
SignalReadPacket(buf_, (size_t)len, remote_addr, this);
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/asyncudpsocket.h b/talk/base/asyncudpsocket.h
old mode 100755
new mode 100644
index 8232938..3a6960c
--- a/talk/base/asyncudpsocket.h
+++ b/talk/base/asyncudpsocket.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_ASYNCUDPSOCKET_H__
-#define TALK_BASE_ASYNCUDPSOCKET_H__
+#ifndef TALK_BASE_ASYNCUDPSOCKET_H_
+#define TALK_BASE_ASYNCUDPSOCKET_H_
#include "talk/base/asyncpacketsocket.h"
#include "talk/base/socketfactory.h"
@@ -36,24 +36,29 @@
// Provides the ability to receive packets asynchronously. Sends are not
// buffered since it is acceptable to drop packets under high load.
class AsyncUDPSocket : public AsyncPacketSocket {
-public:
- AsyncUDPSocket(AsyncSocket* socket);
+ public:
+ // Creates a new socket for sending asynchronous UDP packets using an
+ // asynchronous socket from the given factory.
+ static AsyncUDPSocket* Create(SocketFactory* factory) {
+ AsyncSocket* sock = factory->CreateAsyncSocket(SOCK_DGRAM);
+ return (sock) ? new AsyncUDPSocket(sock) : NULL;
+ }
+ explicit AsyncUDPSocket(AsyncSocket* socket);
virtual ~AsyncUDPSocket();
-private:
- char* buf_;
- size_t size_;
-
+ private:
// Called when the underlying socket is ready to be read from.
void OnReadEvent(AsyncSocket* socket);
+
+ char* buf_;
+ size_t size_;
};
-// Creates a new socket for sending asynchronous UDP packets using an
-// asynchronous socket from the given factory.
+// TODO: This is now deprecated. Remove it.
inline AsyncUDPSocket* CreateAsyncUDPSocket(SocketFactory* factory) {
- return new AsyncUDPSocket(factory->CreateAsyncSocket(SOCK_DGRAM));
+ return AsyncUDPSocket::Create(factory);
}
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_ASYNCUDPSOCKET_H__
+#endif // TALK_BASE_ASYNCUDPSOCKET_H_
diff --git a/talk/base/autodetectproxy.cc b/talk/base/autodetectproxy.cc
old mode 100755
new mode 100644
index aa2feed..ffcac26
--- a/talk/base/autodetectproxy.cc
+++ b/talk/base/autodetectproxy.cc
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2006, Google Inc.
+ * Copyright 2004--2005, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -27,43 +27,48 @@
#include "talk/base/autodetectproxy.h"
#include "talk/base/httpcommon.h"
-#include "talk/xmpp/xmppclientsettings.h"
+#include "talk/base/httpcommon-inl.h"
#include "talk/base/proxydetect.h"
-using namespace talk_base;
+namespace talk_base {
enum { MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE };
-const talk_base::ProxyType TEST_ORDER[] = {
- talk_base::PROXY_HTTPS, /*talk_base::PROXY_SOCKS5,*/ talk_base::PROXY_UNKNOWN
+static const ProxyType TEST_ORDER[] = {
+ PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN
};
AutoDetectProxy::AutoDetectProxy(const std::string& user_agent)
-: agent_(user_agent), socket_(NULL), next_(0)
-{
+ : agent_(user_agent), socket_(NULL), next_(0) {
}
AutoDetectProxy::~AutoDetectProxy() {
- delete socket_;
}
void AutoDetectProxy::DoWork() {
+ // TODO: Try connecting to server_url without proxy first here?
if (!server_url_.empty()) {
LOG(LS_INFO) << "GetProxySettingsForUrl(" << server_url_ << ") - start";
GetProxySettingsForUrl(agent_.c_str(), server_url_.c_str(), proxy_, true);
LOG(LS_INFO) << "GetProxySettingsForUrl - stop";
}
- talk_base::Url<char> url(proxy_.address.IPAsString());
+ Url<char> url(proxy_.address.IPAsString());
if (url.valid()) {
LOG(LS_WARNING) << "AutoDetectProxy removing http prefix on proxy host";
- proxy_.address.SetIP(url.server());
+ proxy_.address.SetIP(url.host());
}
- if (proxy_.type == talk_base::PROXY_UNKNOWN) {
- //LOG(LS_INFO) << "Proxy classification start";
+ LOG(LS_INFO) << "AutoDetectProxy found proxy at " << proxy_.address;
+ if (proxy_.type == PROXY_UNKNOWN) {
+ LOG(LS_INFO) << "AutoDetectProxy initiating proxy classification";
Next();
// Process I/O until Stop()
Thread::Current()->ProcessMessages(kForever);
+ // Clean up the autodetect socket, from the thread that created it
+ delete socket_;
}
+ // TODO: If we found a proxy, try to use it to verify that it
+ // works by sending a request to server_url. This could either be
+ // done here or by the HttpPortAllocator.
}
void AutoDetectProxy::OnMessage(Message *msg) {
@@ -75,8 +80,8 @@
}
void AutoDetectProxy::Next() {
- if (TEST_ORDER[next_] >= talk_base::PROXY_UNKNOWN) {
- Complete(talk_base::PROXY_UNKNOWN);
+ if (TEST_ORDER[next_] >= PROXY_UNKNOWN) {
+ Complete(PROXY_UNKNOWN);
return;
}
@@ -100,39 +105,38 @@
Thread::Current()->PostDelayed(2000, this, MSG_TIMEOUT);
}
-void AutoDetectProxy::Complete(talk_base::ProxyType type) {
+void AutoDetectProxy::Complete(ProxyType type) {
Thread::Current()->Clear(this, MSG_TIMEOUT);
socket_->Close();
proxy_.type = type;
- talk_base::LoggingSeverity sev
- = (proxy_.type == talk_base::PROXY_UNKNOWN)
- ? talk_base::LS_ERROR : talk_base::LS_VERBOSE;
+ LoggingSeverity sev = (proxy_.type == PROXY_UNKNOWN) ? LS_ERROR : LS_INFO;
LOG_V(sev) << "AutoDetectProxy detected " << proxy_.address.ToString()
<< " as type " << proxy_.type;
- Thread::Current()->MessageQueue::Stop();
+ Thread::Current()->Quit();
}
-void AutoDetectProxy::OnConnectEvent(talk_base::AsyncSocket * socket) {
+void AutoDetectProxy::OnConnectEvent(AsyncSocket * socket) {
std::string probe;
switch (TEST_ORDER[next_]) {
- case talk_base::PROXY_HTTPS:
- probe.assign("\005\001"
- "CONNECT www.google.com:443 HTTP/1.0\r\n"
- "User-Agent: ");
- probe.append(agent_);
- probe.append("\r\n"
- "Host: www.google.com\r\n"
- "Content-Length: 0\r\n"
- "Proxy-Connection: Keep-Alive\r\n"
- "\r\n");
- //probe = "CONNECT www.google.com:443 HTTP/1.0\r\n\r\n";
- break;
- case talk_base::PROXY_SOCKS5:
- probe.assign("\005\001\000", 3);
- break;
+ case PROXY_HTTPS:
+ probe.assign("CONNECT www.google.com:443 HTTP/1.0\r\n"
+ "User-Agent: ");
+ probe.append(agent_);
+ probe.append("\r\n"
+ "Host: www.google.com\r\n"
+ "Content-Length: 0\r\n"
+ "Proxy-Connection: Keep-Alive\r\n"
+ "\r\n");
+ break;
+ case PROXY_SOCKS5:
+ probe.assign("\005\001\000", 3);
+ break;
+ default:
+ ASSERT(false);
+ return;
}
LOG(LS_VERBOSE) << "AutoDetectProxy probing type " << TEST_ORDER[next_]
@@ -140,7 +144,7 @@
socket_->Send(probe.data(), probe.size());
}
-void AutoDetectProxy::OnReadEvent(talk_base::AsyncSocket * socket) {
+void AutoDetectProxy::OnReadEvent(AsyncSocket * socket) {
char data[257];
int len = socket_->Recv(data, 256);
if (len > 0) {
@@ -149,30 +153,35 @@
}
switch (TEST_ORDER[next_]) {
- case talk_base::PROXY_HTTPS:
- if ((len >= 2) && (data[0] == '\x05')) {
- Complete(talk_base::PROXY_SOCKS5);
+ case PROXY_HTTPS:
+ if ((len >= 2) && (data[0] == '\x05')) {
+ Complete(PROXY_SOCKS5);
+ return;
+ }
+ if ((len >= 5) && (strncmp(data, "HTTP/", 5) == 0)) {
+ Complete(PROXY_HTTPS);
+ return;
+ }
+ break;
+ case PROXY_SOCKS5:
+ if ((len >= 2) && (data[0] == '\x05')) {
+ Complete(PROXY_SOCKS5);
+ return;
+ }
+ break;
+ default:
+ ASSERT(false);
return;
- }
- if ((len >= 5) && (strncmp(data, "HTTP/", 5) == 0)) {
- Complete(talk_base::PROXY_HTTPS);
- return;
- }
- break;
- case talk_base::PROXY_SOCKS5:
- if ((len >= 2) && (data[0] == '\x05')) {
- Complete(talk_base::PROXY_SOCKS5);
- return;
- }
- break;
}
++next_;
Next();
}
-void AutoDetectProxy::OnCloseEvent(talk_base::AsyncSocket * socket, int error) {
+void AutoDetectProxy::OnCloseEvent(AsyncSocket * socket, int error) {
LOG(LS_VERBOSE) << "AutoDetectProxy closed with error: " << error;
++next_;
Next();
}
+
+} // namespace talk_base
diff --git a/talk/base/autodetectproxy.h b/talk/base/autodetectproxy.h
old mode 100755
new mode 100644
index 9633d31..6bb2a4b
--- a/talk/base/autodetectproxy.h
+++ b/talk/base/autodetectproxy.h
@@ -1,17 +1,40 @@
-#ifndef _AUTODETECTPROXY_H_
-#define _AUTODETECTPROXY_H_
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
-#include "talk/base/sigslot.h"
-#include "talk/base/physicalsocketserver.h"
+#ifndef TALK_BASE_AUTODETECTPROXY_H_
+#define TALK_BASE_AUTODETECTPROXY_H_
+
+#include <string>
+
+#include "talk/base/cryptstring.h"
#include "talk/base/proxyinfo.h"
#include "talk/base/signalthread.h"
-#include "talk/base/cryptstring.h"
-namespace buzz {
-class XmppClientSettings;
-}
-
-namespace talk_base {
+namespace talk_base {
///////////////////////////////////////////////////////////////////////////////
// AutoDetectProxy
@@ -19,11 +42,11 @@
class AsyncSocket;
-class AutoDetectProxy : public SignalThread, public sigslot::has_slots<> {
-public:
- AutoDetectProxy(const std::string& user_agent);
+class AutoDetectProxy : public SignalThread {
+ public:
+ explicit AutoDetectProxy(const std::string& user_agent);
- const talk_base::ProxyInfo& proxy() const { return proxy_; }
+ const ProxyInfo& proxy() const { return proxy_; }
void set_server_url(const std::string& url) {
server_url_ = url;
@@ -33,14 +56,14 @@
proxy_.address = proxy;
}
void set_auth_info(bool use_auth, const std::string& username,
- const CryptString& password) {
+ const CryptString& password) {
if (use_auth) {
proxy_.username = username;
proxy_.password = password;
}
}
-protected:
+ protected:
virtual ~AutoDetectProxy();
// SignalThread Interface
@@ -54,15 +77,14 @@
void OnReadEvent(AsyncSocket * socket);
void OnCloseEvent(AsyncSocket * socket, int error);
-private:
- std::string agent_, server_url_;
+ private:
+ std::string agent_;
+ std::string server_url_;
ProxyInfo proxy_;
- AsyncSocket * socket_;
+ AsyncSocket* socket_;
int next_;
};
-///////////////////////////////////////////////////////////////////////////////
-
} // namespace talk_base
-#endif // _AUTODETECTPROXY_H_
+#endif // TALK_BASE_AUTODETECTPROXY_H_
diff --git a/talk/base/base64.cc b/talk/base/base64.cc
old mode 100755
new mode 100644
index 53e5bac..363c378
--- a/talk/base/base64.cc
+++ b/talk/base/base64.cc
@@ -15,182 +15,229 @@
//*********************************************************************
#include "talk/base/base64.h"
+#include "talk/base/common.h"
using std::string;
+using std::vector;
namespace talk_base {
-static const char fillchar = '=';
-static const string::size_type np = string::npos;
+static const char kPad = '=';
+static const unsigned char pd = 0xFD; // Padding
+static const unsigned char sp = 0xFE; // Whitespace
+static const unsigned char il = 0xFF; // Illegal base64 character
const string Base64::Base64Table(
- // 0000000000111111111122222222223333333333444444444455555555556666
- // 0123456789012345678901234567890123456789012345678901234567890123
+// 0000000000111111111122222222223333333333444444444455555555556666
+// 0123456789012345678901234567890123456789012345678901234567890123
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
-// Decode Table gives the index of any valid base64 character in the
+// Decode Table gives the index of any valid base64 character in the
// Base64 table
// 65 == A, 97 == a, 48 == 0, 43 == +, 47 == /
-const string::size_type Base64::DecodeTable[] = {
+const unsigned char Base64::DecodeTable[] = {
// 0 1 2 3 4 5 6 7 8 9
- np,np,np,np,np,np,np,np,np,np, // 0 - 9
- np,np,np,np,np,np,np,np,np,np, //10 -19
- np,np,np,np,np,np,np,np,np,np, //20 -29
- np,np,np,np,np,np,np,np,np,np, //30 -39
- np,np,np,62,np,np,np,63,52,53, //40 -49
- 54,55,56,57,58,59,60,61,np,np, //50 -59
- np,np,np,np,np, 0, 1, 2, 3, 4, //60 -69
- 5, 6, 7, 8, 9,10,11,12,13,14, //70 -79
- 15,16,17,18,19,20,21,22,23,24, //80 -89
- 25,np,np,np,np,np,np,26,27,28, //90 -99
- 29,30,31,32,33,34,35,36,37,38, //100 -109
- 39,40,41,42,43,44,45,46,47,48, //110 -119
- 49,50,51,np,np,np,np,np,np,np, //120 -129
- np,np,np,np,np,np,np,np,np,np, //130 -139
- np,np,np,np,np,np,np,np,np,np, //140 -149
- np,np,np,np,np,np,np,np,np,np, //150 -159
- np,np,np,np,np,np,np,np,np,np, //160 -169
- np,np,np,np,np,np,np,np,np,np, //170 -179
- np,np,np,np,np,np,np,np,np,np, //180 -189
- np,np,np,np,np,np,np,np,np,np, //190 -199
- np,np,np,np,np,np,np,np,np,np, //200 -209
- np,np,np,np,np,np,np,np,np,np, //210 -219
- np,np,np,np,np,np,np,np,np,np, //220 -229
- np,np,np,np,np,np,np,np,np,np, //230 -239
- np,np,np,np,np,np,np,np,np,np, //240 -249
- np,np,np,np,np,np //250 -256
+ il,il,il,il,il,il,il,il,il,sp, // 0 - 9
+ sp,sp,sp,sp,il,il,il,il,il,il, // 10 - 19
+ il,il,il,il,il,il,il,il,il,il, // 20 - 29
+ il,il,sp,il,il,il,il,il,il,il, // 30 - 39
+ il,il,il,62,il,il,il,63,52,53, // 40 - 49
+ 54,55,56,57,58,59,60,61,il,il, // 50 - 59
+ il,pd,il,il,il, 0, 1, 2, 3, 4, // 60 - 69
+ 5, 6, 7, 8, 9,10,11,12,13,14, // 70 - 79
+ 15,16,17,18,19,20,21,22,23,24, // 80 - 89
+ 25,il,il,il,il,il,il,26,27,28, // 90 - 99
+ 29,30,31,32,33,34,35,36,37,38, // 100 - 109
+ 39,40,41,42,43,44,45,46,47,48, // 110 - 119
+ 49,50,51,il,il,il,il,il,il,il, // 120 - 129
+ il,il,il,il,il,il,il,il,il,il, // 130 - 139
+ il,il,il,il,il,il,il,il,il,il, // 140 - 149
+ il,il,il,il,il,il,il,il,il,il, // 150 - 159
+ il,il,il,il,il,il,il,il,il,il, // 160 - 169
+ il,il,il,il,il,il,il,il,il,il, // 170 - 179
+ il,il,il,il,il,il,il,il,il,il, // 180 - 189
+ il,il,il,il,il,il,il,il,il,il, // 190 - 199
+ il,il,il,il,il,il,il,il,il,il, // 200 - 209
+ il,il,il,il,il,il,il,il,il,il, // 210 - 219
+ il,il,il,il,il,il,il,il,il,il, // 220 - 229
+ il,il,il,il,il,il,il,il,il,il, // 230 - 239
+ il,il,il,il,il,il,il,il,il,il, // 240 - 249
+ il,il,il,il,il,il // 250 - 255
};
-string Base64::encodeFromArray(const char * data, size_t len) {
- size_t i;
- char c;
- string ret;
-
- ret.reserve(len * 2);
-
- for (i = 0; i < len; ++i) {
- c = (data[i] >> 2) & 0x3f;
- ret.append(1, Base64Table[c]);
- c = (data[i] << 4) & 0x3f;
- if (++i < len) {
- c |= (data[i] >> 4) & 0x0f;
- }
-
- ret.append(1, Base64Table[c]);
- if (i < len) {
- c = (data[i] << 2) & 0x3f;
- if (++i < len) {
- c |= (data[i] >> 6) & 0x03;
- }
- ret.append(1, Base64Table[c]);
- } else {
- ++i;
- ret.append(1, fillchar);
- }
-
- if (i < len) {
- c = data[i] & 0x3f;
- ret.append(1, Base64Table[c]);
- } else {
- ret.append(1, fillchar);
- }
- }
-
- return(ret);
+bool Base64::IsBase64Char(char ch) {
+ return (('A' <= ch) && (ch <= 'Z')) ||
+ (('a' <= ch) && (ch <= 'z')) ||
+ (('0' <= ch) && (ch <= '9')) ||
+ (ch == '+') || (ch == '/');
}
-string Base64::encode(const string& data) {
- string::size_type i;
- char c;
- string::size_type len = data.length();
- string ret;
+bool Base64::IsBase64Encoded(const std::string& str) {
+ for (size_t i = 0; i < str.size(); ++i) {
+ if (!IsBase64Char(str.at(i)))
+ return false;
+ }
+ return true;
+}
- ret.reserve(len * 2);
+void Base64::EncodeFromArray(const void* data, size_t len, string* result) {
+ ASSERT(NULL != result);
+ result->clear();
+ result->reserve(((len + 2) / 3) * 4);
+ const unsigned char* byte_data = static_cast<const unsigned char*>(data);
- for (i = 0; i < len; ++i) {
- c = (data[i] >> 2) & 0x3f;
- ret.append(1, Base64Table[c]);
- c = (data[i] << 4) & 0x3f;
+ unsigned char c;
+ size_t i = 0;
+ while (i < len) {
+ c = (byte_data[i] >> 2) & 0x3f;
+ result->push_back(Base64Table[c]);
+
+ c = (byte_data[i] << 4) & 0x3f;
if (++i < len) {
- c |= (data[i] >> 4) & 0x0f;
+ c |= (byte_data[i] >> 4) & 0x0f;
+ }
+ result->push_back(Base64Table[c]);
+
+ if (i < len) {
+ c = (byte_data[i] << 2) & 0x3f;
+ if (++i < len) {
+ c |= (byte_data[i] >> 6) & 0x03;
+ }
+ result->push_back(Base64Table[c]);
+ } else {
+ result->push_back(kPad);
}
- ret.append(1, Base64Table[c]);
if (i < len) {
- c = (data[i] << 2) & 0x3f;
- if (++i < len) {
- c |= (data[i] >> 6) & 0x03;
- }
-
- ret.append(1, Base64Table[c]);
- } else {
+ c = byte_data[i] & 0x3f;
+ result->push_back(Base64Table[c]);
++i;
- ret.append(1, fillchar);
- }
-
- if (i < len) {
- c = data[i] & 0x3f;
- ret.append(1, Base64Table[c]);
} else {
- ret.append(1, fillchar);
+ result->push_back(kPad);
}
}
-
- return(ret);
}
-string Base64::decode(const string& data) {
- string::size_type i;
- char c;
- char c1;
- string::size_type len = data.length();
- string ret;
-
- ret.reserve(len);
-
- for (i = 0; i < len; ++i) {
- do {
- c = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]);
- } while (c == np && ++i < len);
-
- ++i;
-
- do {
- c1 = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]);
- } while (c == np && ++i < len);
-
- c = (c << 2) | ((c1 >> 4) & 0x3);
- ret.append(1, c);
- if (++i < len) {
- c = data[i];
- if (fillchar == c) {
+size_t Base64::GetNextQuantum(DecodeFlags parse_flags, bool illegal_pads,
+ const char* data, size_t len, size_t* dpos,
+ unsigned char qbuf[4], bool* padded)
+{
+ size_t byte_len = 0, pad_len = 0, pad_start = 0;
+ for (; (byte_len < 4) && (*dpos < len); ++*dpos) {
+ qbuf[byte_len] = DecodeTable[static_cast<unsigned char>(data[*dpos])];
+ if ((il == qbuf[byte_len]) || (illegal_pads && (pd == qbuf[byte_len]))) {
+ if (parse_flags != DO_PARSE_ANY)
break;
- }
-
- do {
- c = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]);
- } while (c == np && ++i < len);
- c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
- ret.append(1, c1);
- }
-
- if (++i < len) {
- c1 = data[i];
- if (fillchar == c1) {
+ // Ignore illegal characters
+ } else if (sp == qbuf[byte_len]) {
+ if (parse_flags == DO_PARSE_STRICT)
break;
+ // Ignore spaces
+ } else if (pd == qbuf[byte_len]) {
+ if (byte_len < 2) {
+ if (parse_flags != DO_PARSE_ANY)
+ break;
+ // Ignore unexpected padding
+ } else if (byte_len + pad_len >= 4) {
+ if (parse_flags != DO_PARSE_ANY)
+ break;
+ // Ignore extra pads
+ } else {
+ if (1 == ++pad_len) {
+ pad_start = *dpos;
+ }
}
-
- do {
- c1 = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]);
- } while (c == np && ++i < len);
-
- c = ((c << 6) & 0xc0) | c1;
- ret.append(1, c);
+ } else {
+ if (pad_len > 0) {
+ if (parse_flags != DO_PARSE_ANY)
+ break;
+ // Ignore pads which are followed by data
+ pad_len = 0;
+ }
+ ++byte_len;
}
}
+ for (size_t i = byte_len; i < 4; ++i) {
+ qbuf[i] = 0;
+ }
+ if (4 == byte_len + pad_len) {
+ *padded = true;
+ } else {
+ *padded = false;
+ if (pad_len) {
+ // Roll back illegal padding
+ *dpos = pad_start;
+ }
+ }
+ return byte_len;
+}
- return(ret);
+bool Base64::DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
+ string* result, size_t* data_used) {
+ return DecodeFromArrayTemplate<string>(data, len, flags, result, data_used);
+}
+
+bool Base64::DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
+ vector<char>* result, size_t* data_used) {
+ return DecodeFromArrayTemplate<vector<char> >(data, len, flags, result,
+ data_used);
+}
+
+template<typename T>
+bool Base64::DecodeFromArrayTemplate(const char* data, size_t len,
+ DecodeFlags flags, T* result,
+ size_t* data_used)
+{
+ ASSERT(NULL != result);
+ ASSERT(flags <= (DO_PARSE_MASK | DO_PAD_MASK | DO_TERM_MASK));
+
+ const DecodeFlags parse_flags = flags & DO_PARSE_MASK;
+ const DecodeFlags pad_flags = flags & DO_PAD_MASK;
+ const DecodeFlags term_flags = flags & DO_TERM_MASK;
+ ASSERT(0 != parse_flags);
+ ASSERT(0 != pad_flags);
+ ASSERT(0 != term_flags);
+
+ result->clear();
+ result->reserve(len);
+
+ size_t dpos = 0;
+ bool success = true, padded;
+ unsigned char c, qbuf[4];
+ while (dpos < len) {
+ size_t qlen = GetNextQuantum(parse_flags, (DO_PAD_NO == pad_flags),
+ data, len, &dpos, qbuf, &padded);
+ c = (qbuf[0] << 2) | ((qbuf[1] >> 4) & 0x3);
+ if (qlen >= 2) {
+ result->push_back(c);
+ c = ((qbuf[1] << 4) & 0xf0) | ((qbuf[2] >> 2) & 0xf);
+ if (qlen >= 3) {
+ result->push_back(c);
+ c = ((qbuf[2] << 6) & 0xc0) | qbuf[3];
+ if (qlen >= 4) {
+ result->push_back(c);
+ c = 0;
+ }
+ }
+ }
+ if (qlen < 4) {
+ if ((DO_TERM_ANY != term_flags) && (0 != c)) {
+ success = false; // unused bits
+ }
+ if ((DO_PAD_YES == pad_flags) && !padded) {
+ success = false; // expected padding
+ }
+ break;
+ }
+ }
+ if ((DO_TERM_BUFFER == term_flags) && (dpos != len)) {
+ success = false; // unused chars
+ }
+ if (data_used) {
+ *data_used = dpos;
+ }
+ return success;
}
} // namespace talk_base
diff --git a/talk/base/base64.h b/talk/base/base64.h
old mode 100755
new mode 100644
index 2b58761..73904dc
--- a/talk/base/base64.h
+++ b/talk/base/base64.h
@@ -13,18 +13,82 @@
#define TALK_BASE_BASE64_H__
#include <string>
+#include <vector>
namespace talk_base {
class Base64
{
public:
- static std::string encode(const std::string & data);
- static std::string decode(const std::string & data);
- static std::string encodeFromArray(const char * data, size_t len);
+ enum DecodeOption {
+ DO_PARSE_STRICT = 1, // Parse only base64 characters
+ DO_PARSE_WHITE = 2, // Parse only base64 and whitespace characters
+ DO_PARSE_ANY = 3, // Parse all characters
+ DO_PARSE_MASK = 3,
+
+ DO_PAD_YES = 4, // Padding is required
+ DO_PAD_ANY = 8, // Padding is optional
+ DO_PAD_NO = 12, // Padding is disallowed
+ DO_PAD_MASK = 12,
+
+ DO_TERM_BUFFER = 16, // Must termiante at end of buffer
+ DO_TERM_CHAR = 32, // May terminate at any character boundary
+ DO_TERM_ANY = 48, // May terminate at a sub-character bit offset
+ DO_TERM_MASK = 48,
+
+ // Strictest interpretation
+ DO_STRICT = DO_PARSE_STRICT | DO_PAD_YES | DO_TERM_BUFFER,
+
+ DO_LAX = DO_PARSE_ANY | DO_PAD_ANY | DO_TERM_CHAR,
+ };
+ typedef int DecodeFlags;
+
+ static bool IsBase64Char(char ch);
+
+ // Determines whether the given string consists entirely of valid base64
+ // encoded characters.
+ static bool IsBase64Encoded(const std::string& str);
+
+ static void EncodeFromArray(const void* data, size_t len,
+ std::string* result);
+ static bool DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
+ std::string* result, size_t* data_used);
+ static bool DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
+ std::vector<char>* result, size_t* data_used);
+
+ // Convenience Methods
+ static inline std::string Encode(const std::string& data) {
+ std::string result;
+ EncodeFromArray(data.data(), data.size(), &result);
+ return result;
+ }
+ static inline std::string Decode(const std::string& data, DecodeFlags flags) {
+ std::string result;
+ DecodeFromArray(data.data(), data.size(), flags, &result, NULL);
+ return result;
+ }
+ static inline bool Decode(const std::string& data, DecodeFlags flags,
+ std::string* result, size_t* data_used)
+ {
+ return DecodeFromArray(data.data(), data.size(), flags, result, data_used);
+ }
+ static inline bool Decode(const std::string& data, DecodeFlags flags,
+ std::vector<char>* result, size_t* data_used)
+ {
+ return DecodeFromArray(data.data(), data.size(), flags, result, data_used);
+ }
+
private:
- static const std::string Base64::Base64Table;
- static const std::string::size_type Base64::DecodeTable[];
+ static const std::string Base64Table;
+ static const unsigned char DecodeTable[];
+
+ static size_t GetNextQuantum(DecodeFlags parse_flags, bool illegal_pads,
+ const char* data, size_t len, size_t* dpos,
+ unsigned char qbuf[4], bool* padded);
+ template<typename T>
+ static bool DecodeFromArrayTemplate(const char* data, size_t len,
+ DecodeFlags flags, T* result,
+ size_t* data_used);
};
} // namespace talk_base
diff --git a/talk/base/basicdefs.h b/talk/base/basicdefs.h
old mode 100755
new mode 100644
index 886c287..0e58bf6
--- a/talk/base/basicdefs.h
+++ b/talk/base/basicdefs.h
@@ -26,7 +26,7 @@
*/
#ifndef TALK_BASE_BASICDEFS_H__
-#define TAKL_BASE_BASICDEFS_H__
+#define TALK_BASE_BASICDEFS_H__
#if HAVE_CONFIG_H
#include "config.h"
diff --git a/talk/base/basictypes.h b/talk/base/basictypes.h
old mode 100755
new mode 100644
index 47588ad..781d428
--- a/talk/base/basictypes.h
+++ b/talk/base/basictypes.h
@@ -2,51 +2,78 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_BASE_BASICTYPES_H__
#define TALK_BASE_BASICTYPES_H__
+#ifndef WIN32
+#include <stdint.h> // for uintptr_t
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "talk/base/constructormagic.h"
+
+#ifndef INT_TYPES_DEFINED
+#define INT_TYPES_DEFINED
#ifdef COMPILER_MSVC
typedef __int64 int64;
#else
typedef long long int64;
#endif /* COMPILER_MSVC */
-typedef long int32;
+typedef int int32;
typedef short int16;
typedef char int8;
#ifdef COMPILER_MSVC
typedef unsigned __int64 uint64;
typedef __int64 int64;
+#ifndef INT64_C
+#define INT64_C(x) x ## I64
+#endif
+#ifndef UINT64_C
+#define UINT64_C(x) x ## UI64
+#endif
+#define INT64_F "I64"
#else
typedef unsigned long long uint64;
typedef long long int64;
+#ifndef INT64_C
+#define INT64_C(x) x ## LL
+#endif
+#ifndef UINT64_C
+#define UINT64_C(x) x ## ULL
+#endif
+#define INT64_F "ll"
#endif /* COMPILER_MSVC */
-typedef unsigned long uint32;
+typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
+#endif // INT_TYPES_DEFINED
#ifdef WIN32
typedef int socklen_t;
@@ -55,23 +82,21 @@
namespace talk_base {
template<class T> inline T _min(T a, T b) { return (a > b) ? b : a; }
template<class T> inline T _max(T a, T b) { return (a < b) ? b : a; }
+
+ // For wait functions that take a number of milliseconds, kForever indicates
+ // unlimited time.
+ const int kForever = -1;
}
-// A macro to disallow the evil copy constructor and operator= functions
-// This should be used in the private: declarations for a class
-#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-// A macro to disallow all the implicit constructors, namely the
-// default constructor, copy constructor and operator= functions.
-//
-// This should be used in the private: declarations for a class
-// that wants to prevent anyone from instantiating it. This is
-// especially useful for classes containing only static methods.
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
- TypeName(); \
- DISALLOW_EVIL_CONSTRUCTORS(TypeName)
+#ifdef WIN32
+#define alignof(t) __alignof(t)
+#else // !WIN32
+#define alignof(t) __alignof__(t)
+#endif // !WIN32
+#define IS_ALIGNED(p, a) (0==(reinterpret_cast<uintptr_t>(p) & ((a)-1)))
+#define ALIGNP(p, t) \
+ (reinterpret_cast<uint8*>(((reinterpret_cast<uintptr_t>(p) + \
+ ((t)-1)) & ~((t)-1))))
#ifndef UNUSED
#define UNUSED(x) Unused(static_cast<const void *>(&x))
@@ -82,4 +107,10 @@
inline void Unused(const void *) { }
#endif // UNUSED
+#if defined(__GNUC__)
+#define GCC_ATTR(x) __attribute__ ((x))
+#else // !__GNUC__
+#define GCC_ATTR(x)
+#endif // !__GNUC__
+
#endif // TALK_BASE_BASICTYPES_H__
diff --git a/talk/base/bytebuffer.cc b/talk/base/bytebuffer.cc
old mode 100755
new mode 100644
index 7082e1a..9aef159
--- a/talk/base/bytebuffer.cc
+++ b/talk/base/bytebuffer.cc
@@ -25,19 +25,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "talk/base/bytebuffer.h"
+
#include <algorithm>
#include <cassert>
+#include <cstring>
#include "talk/base/basictypes.h"
-#include "talk/base/bytebuffer.h"
#include "talk/base/byteorder.h"
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::memcpy;
-}
-#endif
-
namespace talk_base {
static const int DEFAULT_SIZE = 4096;
@@ -66,38 +62,70 @@
}
ByteBuffer::~ByteBuffer() {
- delete bytes_;
+ delete[] bytes_;
}
-bool ByteBuffer::ReadUInt8(uint8& val) {
- return ReadBytes(reinterpret_cast<char*>(&val), 1);
+bool ByteBuffer::ReadUInt8(uint8* val) {
+ if (!val) return false;
+
+ return ReadBytes(reinterpret_cast<char*>(val), 1);
}
-bool ByteBuffer::ReadUInt16(uint16& val) {
+bool ByteBuffer::ReadUInt16(uint16* val) {
+ if (!val) return false;
+
uint16 v;
if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) {
return false;
} else {
- val = NetworkToHost16(v);
+ *val = NetworkToHost16(v);
return true;
}
}
-bool ByteBuffer::ReadUInt32(uint32& val) {
+bool ByteBuffer::ReadUInt24(uint32* val) {
+ if (!val) return false;
+
+ uint32 v = 0;
+ if (!ReadBytes(reinterpret_cast<char*>(&v) + 1, 3)) {
+ return false;
+ } else {
+ *val = NetworkToHost32(v);
+ return true;
+ }
+}
+
+bool ByteBuffer::ReadUInt32(uint32* val) {
+ if (!val) return false;
+
uint32 v;
if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) {
return false;
} else {
- val = NetworkToHost32(v);
+ *val = NetworkToHost32(v);
return true;
}
}
-bool ByteBuffer::ReadString(std::string& val, size_t len) {
+bool ByteBuffer::ReadUInt64(uint64* val) {
+ if (!val) return false;
+
+ uint64 v;
+ if (!ReadBytes(reinterpret_cast<char*>(&v), 8)) {
+ return false;
+ } else {
+ *val = NetworkToHost64(v);
+ return true;
+ }
+}
+
+bool ByteBuffer::ReadString(std::string* val, size_t len) {
+ if (!val) return false;
+
if (len > Length()) {
return false;
} else {
- val.append(bytes_ + start_, len);
+ val->append(bytes_ + start_, len);
start_ += len;
return true;
}
@@ -122,11 +150,21 @@
WriteBytes(reinterpret_cast<const char*>(&v), 2);
}
+void ByteBuffer::WriteUInt24(uint32 val) {
+ uint32 v = HostToNetwork32(val);
+ WriteBytes(reinterpret_cast<const char*>(&v) + 1, 3);
+}
+
void ByteBuffer::WriteUInt32(uint32 val) {
uint32 v = HostToNetwork32(val);
WriteBytes(reinterpret_cast<const char*>(&v), 4);
}
+void ByteBuffer::WriteUInt64(uint64 val) {
+ uint64 v = HostToNetwork64(val);
+ WriteBytes(reinterpret_cast<const char*>(&v), 8);
+}
+
void ByteBuffer::WriteString(const std::string& val) {
WriteBytes(val.c_str(), val.size());
}
@@ -154,6 +192,13 @@
bytes_ = new_bytes;
}
+void ByteBuffer::Consume(size_t size) {
+ if (size > Length())
+ return;
+
+ start_ += size;
+}
+
void ByteBuffer::Shift(size_t size) {
if (size > Length())
return;
@@ -163,4 +208,4 @@
start_ = 0;
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/bytebuffer.h b/talk/base/bytebuffer.h
old mode 100755
new mode 100644
index 0a93194..bb162ec
--- a/talk/base/bytebuffer.h
+++ b/talk/base/bytebuffer.h
@@ -25,47 +25,58 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_BYTEBUFFER_H__
-#define TALK_BASE_BYTEBUFFER_H__
+#ifndef TALK_BASE_BYTEBUFFER_H_
+#define TALK_BASE_BYTEBUFFER_H_
#include <string>
+
#include "talk/base/basictypes.h"
+#include "talk/base/constructormagic.h"
namespace talk_base {
class ByteBuffer {
-public:
+ public:
ByteBuffer();
ByteBuffer(const char* bytes, size_t len);
- ByteBuffer(const char* bytes); // uses strlen
+ explicit ByteBuffer(const char* bytes); // uses strlen
~ByteBuffer();
const char* Data() const { return bytes_ + start_; }
- size_t Length() { return end_ - start_; }
- size_t Capacity() { return size_ - start_; }
+ size_t Length() const { return end_ - start_; }
+ size_t Capacity() const { return size_ - start_; }
- bool ReadUInt8(uint8& val);
- bool ReadUInt16(uint16& val);
- bool ReadUInt32(uint32& val);
- bool ReadString(std::string& val, size_t len); // append to val
+ bool ReadUInt8(uint8* val);
+ bool ReadUInt16(uint16* val);
+ bool ReadUInt24(uint32* val);
+ bool ReadUInt32(uint32* val);
+ bool ReadUInt64(uint64* val);
+ bool ReadString(std::string* val, size_t len); // append to val
bool ReadBytes(char* val, size_t len);
void WriteUInt8(uint8 val);
void WriteUInt16(uint16 val);
+ void WriteUInt24(uint32 val);
void WriteUInt32(uint32 val);
+ void WriteUInt64(uint64 val);
void WriteString(const std::string& val);
void WriteBytes(const char* val, size_t len);
void Resize(size_t size);
+ void Consume(size_t size);
void Shift(size_t size);
-private:
+ private:
char* bytes_;
size_t size_;
size_t start_;
size_t end_;
+
+ // There are sensible ways to define these, but they aren't needed in our code
+ // base.
+ DISALLOW_COPY_AND_ASSIGN(ByteBuffer);
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_BYTEBUFFER_H__
+#endif // TALK_BASE_BYTEBUFFER_H_
diff --git a/talk/base/byteorder.h b/talk/base/byteorder.h
old mode 100755
new mode 100644
index 16834c2..08094b8
--- a/talk/base/byteorder.h
+++ b/talk/base/byteorder.h
@@ -28,20 +28,119 @@
#ifndef TALK_BASE_BYTEORDER_H__
#define TALK_BASE_BYTEORDER_H__
-#include "talk/base/basictypes.h"
-
#ifdef POSIX
-extern "C" {
#include <arpa/inet.h>
-}
#endif
#ifdef WIN32
#include <winsock2.h>
#endif
+#include "talk/base/basictypes.h"
+
namespace talk_base {
+// Reading and writing of little and big-endian numbers from memory
+// TODO: Add HostEndian #defines (HE)
+// TODO: Consider NetworkEndian as synonym for BigEndian, for clarity in use.
+// TODO: Consider creating optimized versions, such as direct read/writes of
+// integers in host-endian format, when the platform supports it.
+
+inline void Set8(void* memory, size_t offset, uint8 v) {
+ static_cast<uint8*>(memory)[offset] = v;
+}
+inline uint8 Get8(const void* memory, size_t offset) {
+ return static_cast<const uint8*>(memory)[offset];
+}
+
+inline void SetBE16(void* memory, uint16 v) {
+ Set8(memory, 0, static_cast<uint8>(v >> 8));
+ Set8(memory, 1, static_cast<uint8>(v >> 0));
+}
+inline void SetBE32(void* memory, uint32 v) {
+ Set8(memory, 0, static_cast<uint8>(v >> 24));
+ Set8(memory, 1, static_cast<uint8>(v >> 16));
+ Set8(memory, 2, static_cast<uint8>(v >> 8));
+ Set8(memory, 3, static_cast<uint8>(v >> 0));
+}
+inline void SetBE64(void* memory, uint64 v) {
+ Set8(memory, 0, static_cast<uint8>(v >> 56));
+ Set8(memory, 1, static_cast<uint8>(v >> 48));
+ Set8(memory, 2, static_cast<uint8>(v >> 40));
+ Set8(memory, 3, static_cast<uint8>(v >> 32));
+ Set8(memory, 4, static_cast<uint8>(v >> 24));
+ Set8(memory, 5, static_cast<uint8>(v >> 16));
+ Set8(memory, 6, static_cast<uint8>(v >> 8));
+ Set8(memory, 7, static_cast<uint8>(v >> 0));
+}
+inline uint16 GetBE16(const void* memory) {
+ return (static_cast<uint16>(Get8(memory, 0)) << 8)
+ | (static_cast<uint16>(Get8(memory, 1)) << 0);
+}
+inline uint32 GetBE32(const void* memory) {
+ return (static_cast<uint32>(Get8(memory, 0)) << 24)
+ | (static_cast<uint32>(Get8(memory, 1)) << 16)
+ | (static_cast<uint32>(Get8(memory, 2)) << 8)
+ | (static_cast<uint32>(Get8(memory, 3)) << 0);
+}
+inline uint64 GetBE64(const void* memory) {
+ return (static_cast<uint64>(Get8(memory, 0)) << 56)
+ | (static_cast<uint64>(Get8(memory, 1)) << 48)
+ | (static_cast<uint64>(Get8(memory, 2)) << 40)
+ | (static_cast<uint64>(Get8(memory, 3)) << 32)
+ | (static_cast<uint64>(Get8(memory, 4)) << 24)
+ | (static_cast<uint64>(Get8(memory, 5)) << 16)
+ | (static_cast<uint64>(Get8(memory, 6)) << 8)
+ | (static_cast<uint64>(Get8(memory, 7)) << 0);
+}
+
+inline void SetLE16(void* memory, uint16 v) {
+ Set8(memory, 1, static_cast<uint8>(v >> 8));
+ Set8(memory, 0, static_cast<uint8>(v >> 0));
+}
+inline void SetLE32(void* memory, uint32 v) {
+ Set8(memory, 3, static_cast<uint8>(v >> 24));
+ Set8(memory, 2, static_cast<uint8>(v >> 16));
+ Set8(memory, 1, static_cast<uint8>(v >> 8));
+ Set8(memory, 0, static_cast<uint8>(v >> 0));
+}
+inline void SetLE64(void* memory, uint64 v) {
+ Set8(memory, 7, static_cast<uint8>(v >> 56));
+ Set8(memory, 6, static_cast<uint8>(v >> 48));
+ Set8(memory, 5, static_cast<uint8>(v >> 40));
+ Set8(memory, 4, static_cast<uint8>(v >> 32));
+ Set8(memory, 3, static_cast<uint8>(v >> 24));
+ Set8(memory, 2, static_cast<uint8>(v >> 16));
+ Set8(memory, 1, static_cast<uint8>(v >> 8));
+ Set8(memory, 0, static_cast<uint8>(v >> 0));
+}
+inline uint16 GetLE16(const void* memory) {
+ return (static_cast<uint16>(Get8(memory, 1)) << 8)
+ | (static_cast<uint16>(Get8(memory, 0)) << 0);
+}
+inline uint32 GetLE32(const void* memory) {
+ return (static_cast<uint32>(Get8(memory, 3)) << 24)
+ | (static_cast<uint32>(Get8(memory, 2)) << 16)
+ | (static_cast<uint32>(Get8(memory, 1)) << 8)
+ | (static_cast<uint32>(Get8(memory, 0)) << 0);
+}
+inline uint64 GetLE64(const void* memory) {
+ return (static_cast<uint64>(Get8(memory, 7)) << 56)
+ | (static_cast<uint64>(Get8(memory, 6)) << 48)
+ | (static_cast<uint64>(Get8(memory, 5)) << 40)
+ | (static_cast<uint64>(Get8(memory, 4)) << 32)
+ | (static_cast<uint64>(Get8(memory, 3)) << 24)
+ | (static_cast<uint64>(Get8(memory, 2)) << 16)
+ | (static_cast<uint64>(Get8(memory, 1)) << 8)
+ | (static_cast<uint64>(Get8(memory, 0)) << 0);
+}
+
+// Check if the current host is big endian.
+inline bool IsHostBigEndian() {
+ static const int number = 1;
+ return (0 == *reinterpret_cast<const char*>(&number));
+}
+
inline uint16 HostToNetwork16(uint16 n) {
return htons(n);
}
@@ -50,6 +149,11 @@
return htonl(n);
}
+inline uint64 HostToNetwork64(uint64 n) {
+ // If the host is little endian, GetBE64 converts n to big network endian.
+ return IsHostBigEndian() ? n : GetBE64(&n);
+}
+
inline uint16 NetworkToHost16(uint16 n) {
return ntohs(n);
}
@@ -58,6 +162,11 @@
return ntohl(n);
}
-} // namespace talk_base
+inline uint64 NetworkToHost64(uint64 n) {
+ // If the host is little endian, GetBE64 converts n to little endian.
+ return IsHostBigEndian() ? n : GetBE64(&n);
+}
-#endif // TALK_BASE_BYTEORDER_H__
+} // namespace talk_base
+
+#endif // TALK_BASE_BYTEORDER_H__
diff --git a/talk/base/natsocketfactory.h b/talk/base/checks.cc
old mode 100755
new mode 100644
similarity index 63%
copy from talk/base/natsocketfactory.h
copy to talk/base/checks.cc
index a689158..5466783
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/checks.cc
@@ -1,51 +1,47 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2006, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
-#include "talk/base/socketfactory.h"
+#include "talk/base/checks.h"
+#include "talk/base/logging.h"
-namespace talk_base {
+void Fatal(const char* file, int line, const char* format, ...) {
+ char msg[256];
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+ va_list arguments;
+ va_start(arguments, format);
+ vsnprintf(msg, sizeof(msg), format, arguments);
+ va_end(arguments);
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
-
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
-};
-
-} // namespace talk_base
-
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+ LOG(LS_ERROR) << "\n\n#\n# Fatal error in " << file
+ << ", line " << line << "\n#" << msg
+ << "\n#\n";
+ abort();
+}
diff --git a/talk/base/natsocketfactory.h b/talk/base/checks.h
old mode 100755
new mode 100644
similarity index 67%
copy from talk/base/natsocketfactory.h
copy to talk/base/checks.h
index a689158..12adc25
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/checks.h
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2006, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,27 +25,20 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+// This module contains some basic debugging facilities.
-#include "talk/base/socketfactory.h"
-namespace talk_base {
+#ifndef SHARED_COMMANDLINEFLAGS_CHECKS_H__
+#define SHARED_COMMANDLINEFLAGS_CHECKS_H__
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+#include <string.h>
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+// Prints an error message to stderr and aborts execution.
+void Fatal(const char* file, int line, const char* format, ...);
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
-};
-} // namespace talk_base
+// The UNREACHABLE macro is very useful during development.
+#define UNREACHABLE() \
+ Fatal(__FILE__, __LINE__, "unreachable code")
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif // SHARED_COMMANDLINEFLAGS_CHECKS_H__
diff --git a/talk/base/common.cc b/talk/base/common.cc
old mode 100755
new mode 100644
index aa5c56a..59e73d5
--- a/talk/base/common.cc
+++ b/talk/base/common.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,13 +29,18 @@
#include <stdio.h>
#include <memory.h>
-#ifdef WIN32
+#if WIN32
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif // WIN32
-#include <algorithm>
+#if OSX
+#include <CoreServices/CoreServices.h>
+#endif // OSX
+#include <algorithm>
#include "talk/base/common.h"
+#include "talk/base/logging.h"
//////////////////////////////////////////////////////////////////////
// Assertions
@@ -44,19 +49,23 @@
namespace talk_base {
void Break() {
-#ifdef WIN32
+#if WIN32
::DebugBreak();
-#else // !WIN32
+#elif OSX // !WIN32
+ ::Debugger();
+#else // !OSX && !WIN32
#if _DEBUG_HAVE_BACKTRACE
OutputTrace();
#endif
abort();
-#endif // !WIN32
+#endif // !OSX && !WIN32
}
-void LogAssert(const char * function, const char * file, int line, const char * expression) {
+void LogAssert(const char * function, const char * file, int line,
+ const char * expression) {
// TODO - if we put hooks in here, we can do a lot fancier logging
- fprintf(stderr, "%s(%d): %s @ %s\n", file, line, expression, function);
+ LOG(LS_ERROR) << file << "(" << line << ")" << ": ASSERT FAILED: "
+ << expression << " @ " << function;
}
-} // namespace talk_base
\ No newline at end of file
+} // namespace talk_base
diff --git a/talk/base/common.h b/talk/base/common.h
old mode 100755
new mode 100644
index d652f81..ba9c5ae
--- a/talk/base/common.h
+++ b/talk/base/common.h
@@ -25,8 +25,10 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_COMMON_H__
-#define TALK_BASE_COMMON_H__
+#ifndef TALK_BASE_COMMON_H_
+#define TALK_BASE_COMMON_H_
+
+#include "talk/base/constructormagic.h"
#if defined(_MSC_VER)
// warning C4355: 'this' : used in base member initializer list
@@ -49,9 +51,12 @@
#ifndef WIN32
#define strnicmp(x,y,n) strncasecmp(x,y,n)
#define stricmp(x,y) strcasecmp(x,y)
+
+// TODO: Remove this. std::max should be used everywhere in the code.
+// NOMINMAX must be defined where we include <windows.h>.
#define stdmax(x,y) std::max(x,y)
#else
-#define stdmax(x,y) max(x,y)
+#define stdmax(x,y) talk_base::_max(x,y)
#endif
@@ -61,7 +66,11 @@
// Assertions
/////////////////////////////////////////////////////////////////////////////
-#ifdef ENABLE_DEBUG
+#ifndef ENABLE_DEBUG
+#define ENABLE_DEBUG _DEBUG
+#endif // !defined(ENABLE_DEBUG)
+
+#if ENABLE_DEBUG
namespace talk_base {
@@ -69,23 +78,27 @@
void Break();
// LogAssert writes information about an assertion to the log
-void LogAssert(const char * function, const char * file, int line, const char * expression);
+void LogAssert(const char * function, const char * file, int line,
+ const char * expression);
-inline void Assert(bool result, const char * function, const char * file, int line, const char * expression) {
+inline bool Assert(bool result, const char * function, const char * file,
+ int line, const char * expression) {
if (!result) {
LogAssert(function, file, line, expression);
Break();
+ return false;
}
+ return true;
}
-}; // namespace talk_base
+} // namespace talk_base
#if defined(_MSC_VER) && _MSC_VER < 1300
#define __FUNCTION__ ""
#endif
#ifndef ASSERT
-#define ASSERT(x) talk_base::Assert((x),__FUNCTION__,__FILE__,__LINE__,#x)
+#define ASSERT(x) (void)talk_base::Assert((x),__FUNCTION__,__FILE__,__LINE__,#x)
#endif
#ifndef VERIFY
@@ -94,12 +107,18 @@
#else // !ENABLE_DEBUG
+namespace talk_base {
+
+inline bool ImplicitCastToBool(bool result) { return result; }
+
+} // namespace talk_base
+
#ifndef ASSERT
#define ASSERT(x) (void)0
#endif
#ifndef VERIFY
-#define VERIFY(x) (void)(x)
+#define VERIFY(x) talk_base::ImplicitCastToBool(x)
#endif
#endif // !ENABLE_DEBUG
@@ -109,12 +128,11 @@
#define CTA_MAKE_NAME(line) MAKE_NAME2(line)
#define CTA_MAKE_NAME2(line) constraint_ ## line
-//////////////////////////////////////////////////////////////////////
+#ifdef __GNUC__
+// Forces compiler to inline, even against its better judgement. Use wisely.
+#define FORCE_INLINE __attribute__((always_inline))
+#else
+#define FORCE_INLINE
+#endif
-// A macro to disallow the evil copy constructor and operator= functions
-// This should be used in the private: declarations for a class
-#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-#endif // TALK_BASE_COMMON_H__
+#endif // TALK_BASE_COMMON_H_
diff --git a/talk/base/constructormagic.h b/talk/base/constructormagic.h
new file mode 100644
index 0000000..8b1f7ff
--- /dev/null
+++ b/talk/base/constructormagic.h
@@ -0,0 +1,55 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_CONSTRUCTORMAGIC_H_
+#define TALK_BASE_CONSTRUCTORMAGIC_H_
+
+#define DISALLOW_ASSIGN(TypeName) \
+ void operator=(const TypeName&)
+
+// A macro to disallow the evil copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ DISALLOW_ASSIGN(TypeName)
+
+// Alternative, less-accurate legacy name.
+#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
+ DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName(); \
+ DISALLOW_EVIL_CONSTRUCTORS(TypeName)
+
+
+#endif // TALK_BASE_CONSTRUCTORMAGIC_H_
diff --git a/talk/base/convert.h b/talk/base/convert.h
deleted file mode 100755
index 26c6d32..0000000
--- a/talk/base/convert.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * libjingle
- * Copyright 2007, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _CONVERT_H_
-#define _CONVERT_H_
-
-#include <string>
-#include <windows.h>
-
-#ifndef NO_ATL
-#include <atlstr.h>
-#endif // NO_ATL
-
-#include "talk/base/basictypes.h"
-
-class Utf8 {
-public:
-#ifndef NO_ATL
- explicit Utf8(const CString & str) {
- *this = str;
- }
-#else
- explicit Utf8(const wchar_t *str) {
- *this = str;
- }
-#endif
-
- explicit Utf8() {}
-#ifndef NO_ATL
- inline Utf8& operator =(const CString & str) {
- // TODO: deal with errors
- int len8 = WideCharToMultiByte(CP_UTF8, 0, str.GetString(), str.GetLength(),
- NULL, 0, NULL, NULL);
- char * ns = static_cast<char*>(_alloca(len8));
- WideCharToMultiByte(CP_UTF8, 0, str.GetString(), str.GetLength(),
- ns, len8, NULL, NULL);
- str_.assign(ns, len8);
- return *this;
- }
-#else
-inline Utf8& operator =(const wchar_t *str) {
- // TODO: deal with errors
- int len8 = WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str),
- NULL, 0, NULL, NULL);
- char * ns = static_cast<char*>(_alloca(len8));
- WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str),
- ns, len8, NULL, NULL);
- str_.assign(ns, len8);
- return *this;
- }
-#endif // NO_ATL
-
- inline operator const std::string & () const {
- return str_;
- }
-
- inline const char * AsSz() const {
- return str_.c_str();
- }
-
- // Deprecated
- inline const std::string & AsString() const {
- return str_;
- }
-
- // Deprecated
- inline int Len8() const {
- return (int)str_.length();
- }
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(Utf8);
- std::string str_;
-};
-
-class Utf16 {
-public:
- explicit Utf16(const std::string & str) {
- // TODO: deal with errors
- int len16 = MultiByteToWideChar(CP_UTF8, 0, str.data(), -1,
- NULL, 0);
-#ifndef NO_ATL
- wchar_t * ws = cstr_.GetBuffer(len16);
- MultiByteToWideChar(CP_UTF8, 0, str.data(), str.length(), ws, len16);
- cstr_.ReleaseBuffer(len16);
-#else
- str_ = new wchar_t[len16];
- MultiByteToWideChar(CP_UTF8, 0, str.data(), -1, str_, len16);
-#endif
- }
-
-#ifndef NO_ATL
- inline operator const CString & () const {
- return cstr_;
- }
- // Deprecated
- inline const CString & AsCString() const {
- return cstr_;
- }
- // Deprecated
- inline int Len16() const {
- return cstr_.GetLength();
- }
- inline const wchar_t * AsWz() const {
- return cstr_.GetString();
- }
-#else
- ~Utf16() {
- delete[] str_;
- }
- inline const wchar_t * AsWz() const {
- return str_;
- }
-#endif
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(Utf16);
-#ifndef NO_ATL
- CString cstr_;
-#else
- wchar_t *str_;
-#endif
-};
-
-#endif // _CONVERT_H_
diff --git a/talk/base/criticalsection.h b/talk/base/criticalsection.h
old mode 100755
new mode 100644
index fbe7382..ee3db1a
--- a/talk/base/criticalsection.h
+++ b/talk/base/criticalsection.h
@@ -83,20 +83,31 @@
public:
CriticalSection() {
pthread_mutexattr_t mutex_attribute;
+ pthread_mutexattr_init(&mutex_attribute);
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex_, &mutex_attribute);
+ pthread_mutexattr_destroy(&mutex_attribute);
+ TRACK_OWNER(thread_ = 0);
}
~CriticalSection() {
pthread_mutex_destroy(&mutex_);
}
void Enter() {
pthread_mutex_lock(&mutex_);
+ TRACK_OWNER(thread_ = pthread_self());
}
void Leave() {
+ TRACK_OWNER(thread_ = 0);
pthread_mutex_unlock(&mutex_);
}
+
+#if CS_TRACK_OWNER
+ bool CurrentThreadIsOwner() const { return pthread_equal(thread_, pthread_self()); }
+#endif // CS_TRACK_OWNER
+
private:
pthread_mutex_t mutex_;
+ TRACK_OWNER(pthread_t thread_);
};
#endif // POSIX
diff --git a/talk/base/cryptstring.h b/talk/base/cryptstring.h
old mode 100755
new mode 100644
index 64a7e57..eb39be2
--- a/talk/base/cryptstring.h
+++ b/talk/base/cryptstring.h
@@ -28,7 +28,9 @@
#ifndef _TALK_BASE_CRYPTSTRING_H_
#define _TALK_BASE_CRYPTSTRING_H_
+#include <cstring>
#include <string>
+#include <vector>
#include "talk/base/linked_ptr.h"
#include "talk/base/scoped_ptr.h"
@@ -41,6 +43,7 @@
virtual void CopyTo(char * dest, bool nullterminate) const = 0;
virtual std::string UrlEncode() const = 0;
virtual CryptStringImpl * Copy() const = 0;
+ virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0;
};
class EmptyCryptStringImpl : public CryptStringImpl {
@@ -54,6 +57,9 @@
}
virtual std::string UrlEncode() const { return ""; }
virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); }
+ virtual void CopyRawTo(std::vector<unsigned char> * dest) const {
+ dest->clear();
+ }
};
class CryptString {
@@ -71,6 +77,9 @@
}
void Clear() { impl_.reset(new EmptyCryptStringImpl()); }
std::string UrlEncode() const { return impl_->UrlEncode(); }
+ void CopyRawTo(std::vector<unsigned char> * dest) const {
+ return impl_->CopyRawTo(dest);
+ }
private:
scoped_ptr<const CryptStringImpl> impl_;
@@ -176,6 +185,10 @@
copy->password() = password_;
return copy;
}
+ virtual void CopyRawTo(std::vector<unsigned char> * dest) const {
+ dest->resize(password_.size());
+ memcpy(&dest->front(), password_.data(), password_.size());
+ }
private:
std::string password_;
};
diff --git a/talk/base/diskcache.cc b/talk/base/diskcache.cc
old mode 100755
new mode 100644
index 44e37d9..4e70543
--- a/talk/base/diskcache.cc
+++ b/talk/base/diskcache.cc
@@ -31,7 +31,6 @@
#include "talk/base/win32.h"
#endif
-#include "talk/base/basicdefs.h"
#include "talk/base/common.h"
#include "talk/base/diskcache.h"
#include "talk/base/fileutils.h"
@@ -297,9 +296,12 @@
bool DiskCache::FilenameToId(const std::string& filename, std::string* id,
size_t* index) const {
Pathname pathname(filename);
- if (1 != sscanf(pathname.extension().c_str(), ".%u", index))
+ unsigned tempdex;
+ if (1 != sscanf(pathname.extension().c_str(), ".%u", &tempdex))
return false;
+ *index = static_cast<size_t>(tempdex);
+
size_t buffer_size = pathname.basename().length() + 1;
char* buffer = new char[buffer_size];
decode(buffer, buffer_size, pathname.basename().data(),
diff --git a/talk/base/diskcache.h b/talk/base/diskcache.h
old mode 100755
new mode 100644
index b42e3e0..c5a1dfc
--- a/talk/base/diskcache.h
+++ b/talk/base/diskcache.h
@@ -54,7 +54,7 @@
class DiskCache {
public:
DiskCache();
- ~DiskCache();
+ virtual ~DiskCache();
bool Initialize(const std::string& folder, size_t size);
bool Purge();
diff --git a/talk/base/diskcache_win32.cc b/talk/base/diskcache_win32.cc
deleted file mode 100755
index 3132602..0000000
--- a/talk/base/diskcache_win32.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "talk/base/win32.h"
-#include <shellapi.h>
-#include <shlobj.h>
-#include <tchar.h>
-
-#include <time.h>
-
-#include "talk/base/common.h"
-#include "talk/base/diskcache.h"
-#include "talk/base/pathutils.h"
-#include "talk/base/stream.h"
-#include "talk/base/stringencode.h"
-#include "talk/base/stringutils.h"
-
-#include "talk/base/diskcache_win32.h"
-
-namespace talk_base {
-
-bool DiskCacheWin32::InitializeEntries() {
- // Note: We could store the cache information in a separate file, for faster
- // initialization. Figuring it out empirically works, too.
-
- std::wstring path16 = ToUtf16(folder_);
- path16.append(1, '*');
-
- WIN32_FIND_DATA find_data;
- HANDLE find_handle = FindFirstFile(path16.c_str(), &find_data);
- if (find_handle != INVALID_HANDLE_VALUE) {
- do {
- size_t index;
- std::string id;
- if (!FilenameToId(ToUtf8(find_data.cFileName), &id, &index))
- continue;
-
- Entry* entry = GetOrCreateEntry(id, true);
- entry->size += find_data.nFileSizeLow;
- total_size_ += find_data.nFileSizeLow;
- entry->streams = max(entry->streams, index + 1);
- FileTimeToUnixTime(find_data.ftLastWriteTime, &entry->last_modified);
-
- } while (FindNextFile(find_handle, &find_data));
-
- FindClose(find_handle);
- }
-
- return true;
-}
-
-bool DiskCacheWin32::PurgeFiles() {
- std::wstring path16 = ToUtf16(folder_);
- path16.append(1, '*');
- path16.append(1, '\0');
-
- SHFILEOPSTRUCT file_op = { 0 };
- file_op.wFunc = FO_DELETE;
- file_op.pFrom = path16.c_str();
- file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT
- | FOF_NORECURSION | FOF_FILESONLY;
- if (0 != SHFileOperation(&file_op)) {
- LOG_F(LS_ERROR) << "Couldn't delete cache files";
- return false;
- }
-
- return true;
-}
-
-bool DiskCacheWin32::FileExists(const std::string& filename) const {
- DWORD result = ::GetFileAttributes(ToUtf16(filename).c_str());
- return (INVALID_FILE_ATTRIBUTES != result);
-}
-
-bool DiskCacheWin32::DeleteFile(const std::string& filename) const {
- return ::DeleteFile(ToUtf16(filename).c_str()) != 0;
-}
-
-}
diff --git a/talk/base/diskcache_win32.h b/talk/base/diskcache_win32.h
deleted file mode 100755
index aa5a1b6..0000000
--- a/talk/base/diskcache_win32.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// DiskCacheWin32.h
-// Macshroom
-//
-// Created by Moishe Lettvin on 11/7/06.
-// Copyright (C) 2006 Google Inc. All rights reserved.
-//
-//
-
-#ifndef TALK_BASE_DISKCACHEWIN32_H__
-#define TALK_BASE_DISKCACHEWIN32_H__
-
-#include "talk/base/diskcache.h"
-
-namespace talk_base {
-
-class DiskCacheWin32 : public DiskCache {
- protected:
- virtual bool InitializeEntries();
- virtual bool PurgeFiles();
-
- virtual bool FileExists(const std::string& filename) const;
- virtual bool DeleteFile(const std::string& filename) const;
-};
-
-}
-
-#endif // TALK_BASE_DISKCACHEWIN32_H__
diff --git a/talk/base/diskcachestd.cc b/talk/base/diskcachestd.cc
deleted file mode 100755
index f50c7d7..0000000
--- a/talk/base/diskcachestd.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// DiskCacheStd.cc
-// Macshroom
-//
-// Created by Moishe Lettvin on 11/7/06.
-// Copyright (C) 2006 Google Inc. All rights reserved.
-//
-//
-
-#include "diskcachestd.h"
-
-namespace talk_base {
-
-bool DiskCacheStd::InitializeEntries() {
- return false;
-}
-
-bool DiskCacheStd::PurgeFiles() {
- return false;
-}
-
-bool DiskCacheStd::FileExists(const std::string& filename) const {
- return false;
-}
-
-bool DiskCacheStd::DeleteFile(const std::string& filename) const {
- return false;
-}
-
-}
diff --git a/talk/base/diskcachestd.h b/talk/base/diskcachestd.h
deleted file mode 100755
index b676771..0000000
--- a/talk/base/diskcachestd.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// DiskCacheStd.h
-// Macshroom
-//
-// Created by Moishe Lettvin on 11/7/06.
-// Copyright (C) 2006 Google Inc. All rights reserved.
-//
-//
-
-#ifndef TALK_BASE_DISKCACHESTD_H__
-#define TALK_BASE_DISKCACHESTD_H__
-
-#include "talk/base/diskcache.h"
-
-namespace talk_base {
-
-class DiskCacheStd : public DiskCache {
- protected:
- virtual bool InitializeEntries();
- virtual bool PurgeFiles();
-
- virtual bool FileExists(const std::string& filename) const;
- virtual bool DeleteFile(const std::string& filename) const;
-};
-
-}
-
-#endif // TALK_BASE_DISKCACHESTD_H__
diff --git a/talk/base/event.cc b/talk/base/event.cc
new file mode 100644
index 0000000..f2fd04d
--- /dev/null
+++ b/talk/base/event.cc
@@ -0,0 +1,193 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/event.h"
+
+#if defined(WIN32)
+#include <windows.h>
+#elif defined(POSIX)
+#include <pthread.h>
+#include <sys/time.h>
+#include <time.h>
+#else
+#error "Must define either WIN32 or POSIX."
+#endif
+
+namespace talk_base {
+
+#if defined(WIN32)
+
+Event::Event(bool manual_reset, bool initially_signaled)
+ : is_manual_reset_(manual_reset),
+ is_initially_signaled_(initially_signaled),
+ event_handle_(NULL) {
+}
+
+bool Event::EnsureInitialized() {
+ if (event_handle_ == NULL) {
+ event_handle_ = ::CreateEvent(NULL, // Security attributes.
+ is_manual_reset_,
+ is_initially_signaled_,
+ NULL); // Name.
+ }
+
+ return (event_handle_ != NULL);
+}
+
+Event::~Event() {
+ if (event_handle_ != NULL) {
+ CloseHandle(event_handle_);
+ event_handle_ = NULL;
+ }
+}
+
+bool Event::Set() {
+ if (!EnsureInitialized())
+ return false;
+
+ SetEvent(event_handle_);
+ return true;
+}
+
+bool Event::Reset() {
+ if (!EnsureInitialized())
+ return false;
+
+ ResetEvent(event_handle_);
+ return true;
+}
+
+bool Event::Wait(int cms) {
+ DWORD ms = (cms == kForever)? INFINITE : cms;
+
+ if (!EnsureInitialized())
+ return false;
+ else
+ return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0);
+}
+
+#elif defined(POSIX)
+
+Event::Event(bool manual_reset, bool initially_signaled)
+ : is_manual_reset_(manual_reset),
+ event_status_(initially_signaled),
+ event_mutex_initialized_(false),
+ event_cond_initialized_(false) {
+}
+
+bool Event::EnsureInitialized() {
+ if (!event_mutex_initialized_) {
+ if (pthread_mutex_init(&event_mutex_, NULL) == 0)
+ event_mutex_initialized_ = true;
+ }
+
+ if (!event_cond_initialized_) {
+ if (pthread_cond_init(&event_cond_, NULL) == 0)
+ event_cond_initialized_ = true;
+ }
+
+ return (event_mutex_initialized_ && event_cond_initialized_);
+}
+
+Event::~Event() {
+ if (event_mutex_initialized_) {
+ pthread_mutex_destroy(&event_mutex_);
+ event_mutex_initialized_ = false;
+ }
+
+ if (event_cond_initialized_) {
+ pthread_cond_destroy(&event_cond_);
+ event_cond_initialized_ = false;
+ }
+}
+
+bool Event::Set() {
+ if (!EnsureInitialized())
+ return false;
+
+ pthread_mutex_lock(&event_mutex_);
+ event_status_ = true;
+ pthread_cond_broadcast(&event_cond_);
+ pthread_mutex_unlock(&event_mutex_);
+ return true;
+}
+
+bool Event::Reset() {
+ if (!EnsureInitialized())
+ return false;
+
+ pthread_mutex_lock(&event_mutex_);
+ event_status_ = false;
+ pthread_mutex_unlock(&event_mutex_);
+ return true;
+}
+
+bool Event::Wait(int cms) {
+ if (!EnsureInitialized())
+ return false;
+
+ pthread_mutex_lock(&event_mutex_);
+ int error = 0;
+
+ if (cms != kForever) {
+ // Converting from seconds and microseconds (1e-6) plus
+ // milliseconds (1e-3) to seconds and nanoseconds (1e-9).
+
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ struct timespec ts;
+ ts.tv_sec = tv.tv_sec + (cms / 1000);
+ ts.tv_nsec = tv.tv_usec * 1000 + (cms % 1000) * 1000000;
+
+ // Handle overflow.
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000;
+ }
+
+ while (!event_status_ && error == 0)
+ error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts);
+ } else {
+ while (!event_status_ && error == 0)
+ error = pthread_cond_wait(&event_cond_, &event_mutex_);
+ }
+
+ // NOTE(liulk): Exactly one thread will auto-reset this event. All
+ // the other threads will think it's unsignaled. This seems to be
+ // consistent with auto-reset events in WIN32.
+ if (error == 0 && !is_manual_reset_)
+ event_status_ = false;
+
+ pthread_mutex_unlock(&event_mutex_);
+
+ return (error == 0);
+}
+
+#endif
+
+} // namespace talk_base
diff --git a/talk/base/event.h b/talk/base/event.h
old mode 100755
new mode 100644
index ca15c38..757164c
--- a/talk/base/event.h
+++ b/talk/base/event.h
@@ -1,79 +1,71 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2008, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_BASE_EVENT_H__
#define TALK_BASE_EVENT_H__
+#if defined(WIN32)
+#include "talk/base/win32.h" // NOLINT: consider this a system header.
+#elif defined(POSIX)
+#include <pthread.h>
+#else
+#error "Must define either WIN32 or POSIX."
+#endif
+
+#include "talk/base/basictypes.h"
+
namespace talk_base {
-#ifdef WIN32
class Event {
-public:
- Event() {
- event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
- }
- ~Event() {
- CloseHandle(event_);
- }
- void Set() {
- SetEvent(event_);
- }
- void Reset() {
- ResetEvent(event_);
- }
- void Wait() {
- WaitForSingleObject(event_, INFINITE);
- }
-private:
- HANDLE event_;
-};
+ public:
+ Event(bool manual_reset, bool initially_signaled);
+ ~Event();
+
+ bool Set();
+ bool Reset();
+ bool Wait(int cms);
+
+ private:
+ bool EnsureInitialized();
+
+ bool is_manual_reset_;
+
+#if defined(WIN32)
+ bool is_initially_signaled_;
+ HANDLE event_handle_;
+#elif defined(POSIX)
+ bool event_status_;
+ bool event_mutex_initialized_;
+ pthread_mutex_t event_mutex_;
+ bool event_cond_initialized_;
+ pthread_cond_t event_cond_;
#endif
-
-#ifdef POSIX
-#include <cassert>
-class Event {
- Event() {
- assert(false);
- }
- ~Event() {
- assert(false);
- }
- void Set() {
- assert(false);
- }
- void Reset() {
- assert(false);
- }
- void Wait() {
- assert(false);
- }
};
-#endif
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_EVENT_H__
+#endif // TALK_BASE_EVENT_H__
diff --git a/talk/base/fileutils.cc b/talk/base/fileutils.cc
old mode 100755
new mode 100644
index 12c2576..acfd2f8
--- a/talk/base/fileutils.cc
+++ b/talk/base/fileutils.cc
@@ -25,11 +25,10 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <cassert>
#ifdef WIN32
-#include "talk/base/convert.h"
+#include "talk/base/win32.h"
#endif
#include "talk/base/pathutils.h"
@@ -41,7 +40,7 @@
#include "talk/base/win32filesystem.h"
#ifndef WIN32
-#define MAX_PATH 256
+#define MAX_PATH 260
#endif
namespace talk_base {
@@ -50,18 +49,18 @@
// Directory Iterator //
//////////////////////////
-// A Directoryraverser is created with a given directory. It originally points to
-// the first file in the directory, and can be advanecd with Next(). This allows you
-// to get information about each file.
+// A DirectoryIterator is created with a given directory. It originally points
+// to the first file in the directory, and can be advanecd with Next(). This
+// allows you to get information about each file.
// Constructor
-DirectoryIterator::DirectoryIterator() :
+DirectoryIterator::DirectoryIterator()
#ifdef _WIN32
- handle_(INVALID_HANDLE_VALUE)
+ : handle_(INVALID_HANDLE_VALUE) {
#else
- dir_(NULL), dirent_(NULL)
+ : dir_(NULL), dirent_(NULL) {
#endif
-{}
+}
// Destructor
DirectoryIterator::~DirectoryIterator() {
@@ -83,7 +82,7 @@
if (handle_ != INVALID_HANDLE_VALUE)
::FindClose(handle_);
std::string d = dir.pathname() + '*';
- handle_ = ::FindFirstFile(Utf16(d).AsWz(), &data_);
+ handle_ = ::FindFirstFile(ToUtf16(d).c_str(), &data_);
if (handle_ == INVALID_HANDLE_VALUE)
return false;
#else
@@ -95,7 +94,7 @@
dirent_ = readdir(dir_);
if (dirent_ == NULL)
return false;
-
+
if (::stat(std::string(directory_ + Name()).c_str(), &stat_) != 0)
return false;
#endif
@@ -128,7 +127,7 @@
// returns the name of the file currently pointed to
std::string DirectoryIterator::Name() const {
#ifdef WIN32
- return Utf8(data_.cFileName).AsString();
+ return ToUtf8(data_.cFileName);
#else
assert(dirent_ != NULL);
return dirent_->d_name;
@@ -138,95 +137,106 @@
// returns the size of the file currently pointed to
size_t DirectoryIterator::FileSize() const {
#ifndef WIN32
- return stat_.st_size;
+ return stat_.st_size;
#else
- return data_.nFileSizeLow;
+ return data_.nFileSizeLow;
#endif
}
-
+
// returns the last modified time of this file
time_t DirectoryIterator::FileModifyTime() const {
#ifdef WIN32
-return 0;
+ time_t val;
+ FileTimeToUnixTime(data_.ftLastWriteTime, &val);
+ return val;
#else
return stat_.st_mtime;
#endif
}
-Filesystem *Filesystem::default_filesystem_ = 0;
-
-
-bool Filesystem::CreateFolder(const Pathname &pathname)
-{
- return EnsureDefaultFilesystem()->CreateFolderI(pathname);
-}
-
-FileStream *Filesystem::OpenFile(const Pathname &filename,
- const std::string &mode)
-{
- return EnsureDefaultFilesystem()->OpenFileI(filename, mode);
-}
-
-bool Filesystem::DeleteFile(const Pathname &filename)
-{
- return EnsureDefaultFilesystem()->DeleteFileI(filename);
-}
-
-bool Filesystem::MoveFile(const Pathname &old_path, const Pathname &new_path)
-{
- return EnsureDefaultFilesystem()->MoveFileI(old_path, new_path);
-}
-
-bool Filesystem::CopyFile(const Pathname &old_path, const Pathname &new_path)
-{
- return EnsureDefaultFilesystem()->CopyFileI(old_path, new_path);
-}
-
-bool Filesystem::IsFolder(const Pathname& pathname)
-{
- return EnsureDefaultFilesystem()->IsFolderI(pathname);
-}
-
-bool Filesystem::FileExists(const Pathname& pathname)
-{
- return EnsureDefaultFilesystem()->FileExistsI(pathname);
-}
-
-bool Filesystem::IsTemporaryPath(const Pathname& pathname)
-{
- return EnsureDefaultFilesystem()->IsTemporaryPathI(pathname);
-}
-
-bool Filesystem::GetTemporaryFolder(Pathname &path, bool create,
- const std::string *append)
-{
- return EnsureDefaultFilesystem()->GetTemporaryFolderI(path,create, append);
-}
-
-std::string Filesystem::TempFilename(const Pathname &dir, const std::string &prefix)
-{
- return EnsureDefaultFilesystem()->TempFilenameI(dir, prefix);
-}
-
-bool Filesystem::GetFileSize(const Pathname &dir, size_t *size)
-{
- return EnsureDefaultFilesystem()->GetFileSizeI(dir, size);
-}
-
-Filesystem *Filesystem::EnsureDefaultFilesystem()
-{
- if (!default_filesystem_)
+scoped_ptr<FilesystemInterface> Filesystem::default_filesystem_;
+FilesystemInterface *Filesystem::EnsureDefaultFilesystem() {
+ if (!default_filesystem_.get())
#ifdef WIN32
- default_filesystem_ = new Win32Filesystem();
+ default_filesystem_.reset(new Win32Filesystem());
#else
- default_filesystem_ = new UnixFilesystem();
+ default_filesystem_.reset(new UnixFilesystem());
#endif
- return default_filesystem_;
+ return default_filesystem_.get();
+}
+
+bool FilesystemInterface::CopyFolder(const Pathname &old_path,
+ const Pathname &new_path) {
+ VERIFY(IsFolder(old_path));
+ Pathname new_dir;
+ new_dir.SetFolder(new_path.pathname());
+ Pathname old_dir;
+ old_dir.SetFolder(old_path.pathname());
+ if (!CreateFolder(new_dir))
+ return false;
+ DirectoryIterator di;
+ di.Iterate(old_dir.pathname());
+ while (di.Next()) {
+ if (di.Name() == "." || di.Name() == "..")
+ continue;
+ Pathname source;
+ Pathname dest;
+ source.SetFolder(old_dir.pathname());
+ dest.SetFolder(new_path.pathname());
+ source.SetFilename(di.Name());
+ dest.SetFilename(di.Name());
+ if (!CopyFileOrFolder(source, dest))
+ return false;
+ }
+ return true;
+}
+
+bool FilesystemInterface::DeleteFolderContents(const Pathname &folder) {
+ bool success = true;
+ VERIFY(IsFolder(folder));
+ DirectoryIterator *di = IterateDirectory();
+ di->Iterate(folder);
+ while (di->Next()) {
+ if (di->Name() == "." || di->Name() == "..")
+ continue;
+ Pathname subdir;
+ subdir.SetFolder(folder.pathname());
+ if (di->IsDirectory()) {
+ subdir.AppendFolder(di->Name());
+ if (!DeleteFolderAndContents(subdir)) {
+ success = false;
+ }
+ } else {
+ subdir.SetFilename(di->Name());
+ if (!DeleteFile(subdir)) {
+ success = false;
+ }
+ }
+ }
+ delete di;
+ return success;
+}
+
+bool FilesystemInterface::CleanAppTempFolder() {
+ Pathname path;
+ if (!GetAppTempFolder(&path))
+ return false;
+ if (IsAbsent(path))
+ return true;
+ if (!IsTemporaryPath(path)) {
+ ASSERT(false);
+ return false;
+ }
+ return DeleteFolderContents(path);
+}
+
+Pathname Filesystem::GetCurrentDirectory() {
+ return EnsureDefaultFilesystem()->GetCurrentDirectory();
}
bool CreateUniqueFile(Pathname& path, bool create_empty) {
LOG(LS_INFO) << "Path " << path.pathname() << std::endl;
- // If not folder is supplied, use the temporary folder
+ // If no folder is supplied, use the temporary folder
if (path.folder().empty()) {
Pathname temporary_path;
if (!Filesystem::GetTemporaryFolder(temporary_path, true, NULL)) {
@@ -236,17 +246,17 @@
path.SetFolder(temporary_path.pathname());
}
- // If not filename is supplied, use a temporary name
+ // If no filename is supplied, use a temporary name
if (path.filename().empty()) {
std::string folder(path.folder());
std::string filename = Filesystem::TempFilename(folder, "gt");
- path.SetFilename(filename);
+ path.SetPathname(filename);
if (!create_empty) {
Filesystem::DeleteFile(path.pathname());
}
return true;
}
-
+
// Otherwise, create a unique name based on the given filename
// foo.txt -> foo-N.txt
const std::string basename = path.basename();
@@ -254,20 +264,21 @@
size_t version = 0;
while (version < MAX_VERSION) {
std::string pathname = path.pathname();
-
- if (!Filesystem::FileExists(pathname)) {
+
+ if (!Filesystem::IsFile(pathname)) {
if (create_empty) {
- FileStream* fs = Filesystem::OpenFile(pathname,"w");
- delete fs;
+ FileStream* fs = Filesystem::OpenFile(pathname, "w");
+ delete fs;
}
return true;
}
version += 1;
char version_base[MAX_PATH];
- talk_base::sprintfn(version_base, ARRAY_SIZE(version_base), "%s-%u",
- basename.c_str(), version);
+ sprintfn(version_base, ARRAY_SIZE(version_base), "%s-%u",
+ basename.c_str(), version);
path.SetBasename(version_base);
}
return true;
}
-}
+
+} // namespace talk_base
diff --git a/talk/base/fileutils.h b/talk/base/fileutils.h
old mode 100755
new mode 100644
index 868f4c2..8ad631f
--- a/talk/base/fileutils.h
+++ b/talk/base/fileutils.h
@@ -25,13 +25,13 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_FILEUTILS_H__
-#define TALK_BASE_FILEUTILS_H__
+#ifndef TALK_BASE_FILEUTILS_H_
+#define TALK_BASE_FILEUTILS_H_
#include <string>
-#ifdef _WINDOWS
-#include <windows.h>
+#ifdef WIN32
+#include "talk/base/win32.h"
#else
#include <sys/types.h>
#include <dirent.h>
@@ -39,7 +39,9 @@
#include <unistd.h>
#endif
+#include "talk/base/basictypes.h"
#include "talk/base/common.h"
+#include "talk/base/scoped_ptr.h"
namespace talk_base {
@@ -50,44 +52,49 @@
// Directory Iterator //
//////////////////////////
-// A DirectoryTraverser is created with a given directory. It originally points to
-// the first file in the directory, and can be advanecd with Next(). This allows you
-// to get information about each file.
+// A DirectoryIterator is created with a given directory. It originally points
+// to the first file in the directory, and can be advanecd with Next(). This
+// allows you to get information about each file.
class DirectoryIterator {
-
+ friend class Filesystem;
public:
- // Constructor
+ // Constructor
DirectoryIterator();
-
// Destructor
- ~DirectoryIterator();
+ virtual ~DirectoryIterator();
// Starts traversing a directory
// dir is the directory to traverse
// returns true if the directory exists and is valid
// The iterator will point to the first entry in the directory
- bool Iterate(const Pathname &path);
+ virtual bool Iterate(const Pathname &path);
// Advances to the next file
// returns true if there were more files in the directory.
- bool Next();
+ virtual bool Next();
// returns true if the file currently pointed to is a directory
- bool IsDirectory() const;
+ virtual bool IsDirectory() const;
// returns the name of the file currently pointed to
- std::string Name() const;
+ virtual std::string Name() const;
// returns the size of the file currently pointed to
- size_t FileSize() const;
+ virtual size_t FileSize() const;
- // returns the last modified time of the file currently poitned to
- time_t FileModifyTime() const;
+ // returns the last modified time of the file currently pointed to
+ virtual time_t FileModifyTime() const;
+
+ // checks whether current file is a special directory file "." or ".."
+ bool IsDots() const {
+ std::string filename(Name());
+ return (filename.compare(".") == 0) || (filename.compare("..") == 0);
+ }
private:
std::string directory_;
-#ifdef _WINDOWS
+#ifdef WIN32
WIN32_FIND_DATA data_;
HANDLE handle_;
#else
@@ -97,89 +104,349 @@
#endif
};
-class Filesystem {
+enum FileTimeType { FTT_CREATED, FTT_MODIFIED, FTT_ACCESSED };
+
+class FilesystemInterface {
public:
-
- virtual bool CreateFolderI(const Pathname &pathname) = 0;
-
- // Opens a file. Returns an open StreamInterface if function succeeds. Otherwise,
- // returns NULL.
- virtual FileStream *OpenFileI(const Pathname &filename,
- const std::string &mode) = 0;
+ virtual ~FilesystemInterface() {}
- // This will attempt to delete the path located at filename. If filename is a file,
- // it will be unlinked. If the path is a directory, it will recursively unlink and remove
- // all the files and directory within it
- virtual bool DeleteFileI(const Pathname &filename) = 0;
+ // Returns a DirectoryIterator for a given pathname.
+ // TODO: Do fancy abstracted stuff
+ virtual DirectoryIterator *IterateDirectory() {
+ return new DirectoryIterator();
+ }
- // Creates a directory. This will call itself recursively to create /foo/bar even if
- // /foo does not exist.
- // Returns TRUE if function succeeds
-
- // This moves a file from old_path to new_path, where "file" can be a plain file
- // or directory, which will be moved recursively.
- // Returns true if function succeeds.
- virtual bool MoveFileI(const Pathname &old_path, const Pathname &new_path) = 0;
+ // Opens a file. Returns an open StreamInterface if function succeeds.
+ // Otherwise, returns NULL.
+ virtual FileStream *OpenFile(const Pathname &filename,
+ const std::string &mode) = 0;
- // This copies a file from old_path to _new_path where "file" can be a plain file
- // or directory, which will be copied recursively.
- // Returns true if function succeeds
- virtual bool CopyFileI(const Pathname &old_path, const Pathname &new_path) = 0;
+ // Atomically creates an empty file accessible only to the current user if one
+ // does not already exist at the given path, otherwise fails. This is the only
+ // secure way to create a file in a shared temp directory (e.g., C:\Temp on
+ // Windows or /tmp on Linux).
+ // Note that if it is essential that a file be successfully created then the
+ // app must generate random names and retry on failure, or else it will be
+ // vulnerable to a trivial DoS.
+ virtual bool CreatePrivateFile(const Pathname &filename) = 0;
- // Returns true if a pathname is a directory
- virtual bool IsFolderI(const Pathname& pathname) = 0;
+ // This will attempt to delete the path located at filename.
+ // It ASSERTS and returns false if the path points to a folder or a
+ // non-existent file.
+ virtual bool DeleteFile(const Pathname &filename) = 0;
- // Returns true if a file exists at this path
- virtual bool FileExistsI(const Pathname& pathname) = 0;
+ // This will attempt to delete the empty folder located at 'folder'
+ // It ASSERTS and returns false if the path points to a file or a non-existent
+ // folder. It fails normally if the folder is not empty or can otherwise
+ // not be deleted.
+ virtual bool DeleteEmptyFolder(const Pathname &folder) = 0;
+
+ // This will call IterateDirectory, to get a directory iterator, and then
+ // call DeleteFolderAndContents and DeleteFile on every path contained in this
+ // folder. If the folder is empty, this returns true.
+ virtual bool DeleteFolderContents(const Pathname &folder);
+
+ // This deletes the contents of a folder, recursively, and then deletes
+ // the folder itself.
+ virtual bool DeleteFolderAndContents(const Pathname &folder) {
+ return DeleteFolderContents(folder) && DeleteEmptyFolder(folder);
+ }
+
+ // This will delete whatever is located at path, be it a file or a folder.
+ // If it is a folder, it will delete it recursively by calling
+ // DeleteFolderAndContents
+ bool DeleteFileOrFolder(const Pathname &path) {
+ if (IsFolder(path))
+ return DeleteFolderAndContents(path);
+ else
+ return DeleteFile(path);
+ }
+
+ // Creates a directory. This will call itself recursively to create /foo/bar
+ // even if /foo does not exist. Returns true if the function succeeds.
+ virtual bool CreateFolder(const Pathname &pathname) = 0;
+
+ // This moves a file from old_path to new_path, where "old_path" is a
+ // plain file. This ASSERTs and returns false if old_path points to a
+ // directory, and returns true if the function succeeds.
+ // If the new path is on a different volume than the old path, this function
+ // will attempt to copy and, if that succeeds, delete the old path.
+ virtual bool MoveFolder(const Pathname &old_path,
+ const Pathname &new_path) = 0;
+
+ // This moves a directory from old_path to new_path, where "old_path" is a
+ // directory. This ASSERTs and returns false if old_path points to a plain
+ // file, and returns true if the function succeeds.
+ // If the new path is on a different volume, this function will attempt to
+ // copy and if that succeeds, delete the old path.
+ virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path) = 0;
+
+ // This attempts to move whatever is located at old_path to new_path,
+ // be it a file or folder.
+ bool MoveFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
+ if (IsFile(old_path)) {
+ return MoveFile(old_path, new_path);
+ } else {
+ return MoveFolder(old_path, new_path);
+ }
+ }
+
+ // This copies a file from old_path to new_path. This method ASSERTs and
+ // returns false if old_path is a folder, and returns true if the copy
+ // succeeds.
+ virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0;
+
+ // This copies a folder from old_path to new_path.
+ bool CopyFolder(const Pathname &old_path, const Pathname &new_path);
+
+ bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
+ if (IsFile(old_path))
+ return CopyFile(old_path, new_path);
+ else
+ return CopyFolder(old_path, new_path);
+ }
+
+ // Returns true if pathname refers to a directory
+ virtual bool IsFolder(const Pathname& pathname) = 0;
+
+ // Returns true if pathname refers to a file
+ virtual bool IsFile(const Pathname& pathname) = 0;
+
+ // Returns true if pathname refers to no filesystem object, every parent
+ // directory either exists, or is also absent.
+ virtual bool IsAbsent(const Pathname& pathname) = 0;
// Returns true if pathname represents a temporary location on the system.
- virtual bool IsTemporaryPathI(const Pathname& pathname) = 0;
+ virtual bool IsTemporaryPath(const Pathname& pathname) = 0;
// A folder appropriate for storing temporary files (Contents are
- // automatically deleted when the program exists)
- virtual bool GetTemporaryFolderI(Pathname &path, bool create,
- const std::string *append) = 0;
-
- virtual std::string TempFilenameI(const Pathname &dir, const std::string &prefix) = 0;
+ // automatically deleted when the program exits)
+ virtual bool GetTemporaryFolder(Pathname &path, bool create,
+ const std::string *append) = 0;
- virtual bool GetFileSizeI(const Pathname &dir, size_t *size) = 0;
-
- static Filesystem *default_filesystem(void) { ASSERT(default_filesystem_!=NULL); return default_filesystem_; }
- static void set_default_filesystem(Filesystem *filesystem) {default_filesystem_ = filesystem; }
-
-
- static bool CreateFolder(const Pathname &pathname);
-
- static FileStream *OpenFile(const Pathname &filename,
- const std::string &mode);
- static bool DeleteFile(const Pathname &filename);
- static bool MoveFile(const Pathname &old_path, const Pathname &new_path);
- static bool CopyFile(const Pathname &old_path, const Pathname &new_path);
- static bool IsFolder(const Pathname& pathname);
- static bool FileExists(const Pathname &pathname);
- static bool IsTemporaryPath(const Pathname& pathname);
- static bool GetTemporaryFolder(Pathname &path, bool create,
- const std::string *append);
- static std::string TempFilename(const Pathname &dir, const std::string &prefix);
- static bool GetFileSize(const Pathname &dir, size_t *size);
-
- private:
- static Filesystem *default_filesystem_;
- static Filesystem *EnsureDefaultFilesystem();
+ virtual std::string TempFilename(const Pathname &dir,
+ const std::string &prefix) = 0;
+ // Determines the size of the file indicated by path.
+ virtual bool GetFileSize(const Pathname& path, size_t* size) = 0;
+
+ // Determines a timestamp associated with the file indicated by path.
+ virtual bool GetFileTime(const Pathname& path, FileTimeType which,
+ time_t* time) = 0;
+
+ // Returns the path to the running application.
+ // Note: This is not guaranteed to work on all platforms. Be aware of the
+ // limitations before using it, and robustly handle failure.
+ virtual bool GetAppPathname(Pathname* path) = 0;
+
+ // Get a folder that is unique to the current application, which is suitable
+ // for sharing data between executions of the app. If the per_user arg is
+ // true, the folder is also specific to the current user.
+ virtual bool GetAppDataFolder(Pathname* path, bool per_user) = 0;
+
+ // Get a temporary folder that is unique to the current user and application.
+ // TODO: Re-evaluate the goals of this function. We probably just need any
+ // directory that won't collide with another existing directory, and which
+ // will be cleaned up when the program exits.
+ virtual bool GetAppTempFolder(Pathname* path) = 0;
+
+ // Delete the contents of the folder returned by GetAppTempFolder
+ bool CleanAppTempFolder();
+
+ virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) = 0;
+
+ // Returns the absolute path of the current directory.
+ virtual Pathname GetCurrentDirectory() = 0;
+
+ // Note: These might go into some shared config section later, but they're
+ // used by some methods in this interface, so we're leaving them here for now.
+ void SetOrganizationName(const std::string& organization) {
+ organization_name_ = organization;
+ }
+ void GetOrganizationName(std::string* organization) {
+ ASSERT(NULL != organization);
+ *organization = organization_name_;
+ }
+ void SetApplicationName(const std::string& application) {
+ application_name_ = application;
+ }
+ void GetApplicationName(std::string* application) {
+ ASSERT(NULL != application);
+ *application = application_name_;
+ }
+
+ protected:
+ std::string organization_name_;
+ std::string application_name_;
};
-// Generates a unique temporary filename in 'directory' with the given 'prefix'
- std::string TempFilename(const Pathname &dir, const std::string &prefix);
+class Filesystem {
+ public:
+ static FilesystemInterface *default_filesystem() {
+ ASSERT(default_filesystem_.get() != NULL);
+ return default_filesystem_.get();
+ }
- // Generates a unique filename based on the input path. If no path component
- // is specified, it uses the temporary directory. If a filename is provided,
- // up to 100 variations of form basename-N.extension are tried. When
- // create_empty is true, an empty file of this name is created (which
- // decreases the chance of a temporary filename collision with another
- // process).
- bool CreateUniqueFile(talk_base::Pathname& path, bool create_empty);
+ static void set_default_filesystem(FilesystemInterface *filesystem) {
+ default_filesystem_.reset(filesystem);
+ }
-}
+ static FilesystemInterface *swap_default_filesystem(
+ FilesystemInterface *filesystem) {
+ FilesystemInterface *cur = default_filesystem_.release();
+ default_filesystem_.reset(filesystem);
+ return cur;
+ }
-#endif // TALK_BASE_FILEUTILS_H__
+ static DirectoryIterator *IterateDirectory() {
+ return EnsureDefaultFilesystem()->IterateDirectory();
+ }
+
+ static bool CreateFolder(const Pathname &pathname) {
+ return EnsureDefaultFilesystem()->CreateFolder(pathname);
+ }
+
+ static FileStream *OpenFile(const Pathname &filename,
+ const std::string &mode) {
+ return EnsureDefaultFilesystem()->OpenFile(filename, mode);
+ }
+
+ static bool CreatePrivateFile(const Pathname &filename) {
+ return EnsureDefaultFilesystem()->CreatePrivateFile(filename);
+ }
+
+ static bool DeleteFile(const Pathname &filename) {
+ return EnsureDefaultFilesystem()->DeleteFile(filename);
+ }
+
+ static bool DeleteEmptyFolder(const Pathname &folder) {
+ return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder);
+ }
+
+ static bool DeleteFolderContents(const Pathname &folder) {
+ return EnsureDefaultFilesystem()->DeleteFolderContents(folder);
+ }
+
+ static bool DeleteFolderAndContents(const Pathname &folder) {
+ return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder);
+ }
+
+ static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
+ return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path);
+ }
+
+ static bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
+ return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
+ }
+
+ static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
+ return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
+ }
+
+ static bool IsFolder(const Pathname& pathname) {
+ return EnsureDefaultFilesystem()->IsFolder(pathname);
+ }
+
+ static bool IsFile(const Pathname &pathname) {
+ return EnsureDefaultFilesystem()->IsFile(pathname);
+ }
+
+ static bool IsAbsent(const Pathname &pathname) {
+ return EnsureDefaultFilesystem()->IsAbsent(pathname);
+ }
+
+ static bool IsTemporaryPath(const Pathname& pathname) {
+ return EnsureDefaultFilesystem()->IsTemporaryPath(pathname);
+ }
+
+ static bool GetTemporaryFolder(Pathname &path, bool create,
+ const std::string *append) {
+ return EnsureDefaultFilesystem()->GetTemporaryFolder(path, create, append);
+ }
+
+ static std::string TempFilename(const Pathname &dir,
+ const std::string &prefix) {
+ return EnsureDefaultFilesystem()->TempFilename(dir, prefix);
+ }
+
+ static bool GetFileSize(const Pathname& path, size_t* size) {
+ return EnsureDefaultFilesystem()->GetFileSize(path, size);
+ }
+
+ static bool GetFileTime(const Pathname& path, FileTimeType which,
+ time_t* time) {
+ return EnsureDefaultFilesystem()->GetFileTime(path, which, time);
+ }
+
+ static bool GetAppPathname(Pathname* path) {
+ return EnsureDefaultFilesystem()->GetAppPathname(path);
+ }
+
+ static bool GetAppDataFolder(Pathname* path, bool per_user) {
+ return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user);
+ }
+
+ static bool GetAppTempFolder(Pathname* path) {
+ return EnsureDefaultFilesystem()->GetAppTempFolder(path);
+ }
+
+ static bool CleanAppTempFolder() {
+ return EnsureDefaultFilesystem()->CleanAppTempFolder();
+ }
+
+ static bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
+ return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes);
+ }
+
+ // Definition has to be in the .cc file due to returning forward-declared
+ // Pathname by value.
+ static Pathname GetCurrentDirectory();
+
+ static void SetOrganizationName(const std::string& organization) {
+ EnsureDefaultFilesystem()->SetOrganizationName(organization);
+ }
+
+ static void GetOrganizationName(std::string* organization) {
+ EnsureDefaultFilesystem()->GetOrganizationName(organization);
+ }
+
+ static void SetApplicationName(const std::string& application) {
+ EnsureDefaultFilesystem()->SetApplicationName(application);
+ }
+
+ static void GetApplicationName(std::string* application) {
+ EnsureDefaultFilesystem()->GetApplicationName(application);
+ }
+
+ private:
+ static scoped_ptr<FilesystemInterface> default_filesystem_;
+
+ static FilesystemInterface *EnsureDefaultFilesystem();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Filesystem);
+};
+
+class FilesystemScope{
+ public:
+ explicit FilesystemScope(FilesystemInterface *new_fs) {
+ old_fs_ = Filesystem::swap_default_filesystem(new_fs);
+ }
+ ~FilesystemScope() {
+ Filesystem::set_default_filesystem(old_fs_);
+ }
+ private:
+ FilesystemInterface* old_fs_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope);
+};
+
+// Generates a unique filename based on the input path. If no path component
+// is specified, it uses the temporary directory. If a filename is provided,
+// up to 100 variations of form basename-N.extension are tried. When
+// create_empty is true, an empty file of this name is created (which
+// decreases the chance of a temporary filename collision with another
+// process).
+bool CreateUniqueFile(Pathname& path, bool create_empty);
+
+} // namespace talk_base
+
+#endif // TALK_BASE_FILEUTILS_H_
+
diff --git a/talk/base/firewallsocketserver.cc b/talk/base/firewallsocketserver.cc
old mode 100755
new mode 100644
index 49db8a8..a99c72e
--- a/talk/base/firewallsocketserver.cc
+++ b/talk/base/firewallsocketserver.cc
@@ -2,122 +2,129 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "talk/base/firewallsocketserver.h"
+
#include <cassert>
#include <algorithm>
-#ifdef OSX
-#include <errno.h>
-#endif
-#include "talk/base/firewallsocketserver.h"
#include "talk/base/asyncsocket.h"
#include "talk/base/logging.h"
namespace talk_base {
class FirewallSocket : public AsyncSocketAdapter {
-public:
- FirewallSocket(FirewallSocketServer * server, AsyncSocket * socket, int type)
- : AsyncSocketAdapter(socket), server_(server), type_(type) {
- }
- FirewallSocket(FirewallSocketServer * server, Socket * socket, int type)
+ public:
+ FirewallSocket(FirewallSocketServer* server, AsyncSocket* socket, int type)
: AsyncSocketAdapter(socket), server_(server), type_(type) {
}
virtual int Connect(const SocketAddress& addr) {
if (type_ == SOCK_STREAM) {
- if (!server_->Check(FP_TCP, FD_OUT, addr)) {
- //LOG(INFO) << "FirewallSocket::Connect - Outbound TCP connection denied";
- // Note: handle this asynchronously?
+ if (!server_->Check(FP_TCP, GetLocalAddress(), addr)) {
+ LOG(LS_VERBOSE) << "FirewallSocket outbound TCP connection from "
+ << GetLocalAddress().ToString() << " to "
+ << addr.ToString() << " denied";
+ // TODO: Handle this asynchronously.
SetError(EHOSTUNREACH);
return SOCKET_ERROR;
}
}
return AsyncSocketAdapter::Connect(addr);
}
- virtual int Send(const void * pv, size_t cb) {
- if (type_ == SOCK_DGRAM) {
- if (!server_->Check(FP_UDP, FD_OUT, GetRemoteAddress())) {
- //LOG(INFO) << "FirewallSocket::Send - Outbound UDP packet dropped";
- return static_cast<int>(cb);
- }
- }
- return AsyncSocketAdapter::Send(pv, cb);
+ virtual int Send(const void* pv, size_t cb) {
+ return SendTo(pv, cb, GetRemoteAddress());
}
- virtual int SendTo(const void * pv, size_t cb, const SocketAddress& addr) {
+ virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
if (type_ == SOCK_DGRAM) {
- if (!server_->Check(FP_UDP, FD_OUT, addr)) {
- //LOG(INFO) << "FirewallSocket::SendTo - Outbound UDP packet dropped";
+ if (!server_->Check(FP_UDP, GetLocalAddress(), addr)) {
+ LOG(LS_VERBOSE) << "FirewallSocket outbound UDP packet from "
+ << GetLocalAddress().ToString() << " to "
+ << addr.ToString() << " dropped";
return static_cast<int>(cb);
}
}
return AsyncSocketAdapter::SendTo(pv, cb, addr);
}
- virtual int Recv(void * pv, size_t cb) {
- if (type_ == SOCK_DGRAM) {
- if (!server_->Check(FP_UDP, FD_IN, GetRemoteAddress())) {
- while (true) {
- int res = AsyncSocketAdapter::Recv(pv, cb);
- if (res <= 0)
- return res;
- //LOG(INFO) << "FirewallSocket::Recv - Inbound UDP packet dropped";
- }
- }
- }
- return AsyncSocketAdapter::Recv(pv, cb);
+ virtual int Recv(void* pv, size_t cb) {
+ SocketAddress addr;
+ return RecvFrom(pv, cb, &addr);
}
- virtual int RecvFrom(void * pv, size_t cb, SocketAddress * paddr) {
+ virtual int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
if (type_ == SOCK_DGRAM) {
while (true) {
int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
if (res <= 0)
return res;
- if (server_->Check(FP_UDP, FD_IN, *paddr))
+ if (server_->Check(FP_UDP, *paddr, GetLocalAddress()))
return res;
- //LOG(INFO) << "FirewallSocket::RecvFrom - Inbound UDP packet dropped";
+ LOG(LS_VERBOSE) << "FirewallSocket inbound UDP packet from "
+ << paddr->ToString() << " to "
+ << GetLocalAddress().ToString() << " dropped";
}
}
return AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
}
- virtual Socket * Accept(SocketAddress *paddr) {
- while (Socket * sock = AsyncSocketAdapter::Accept(paddr)) {
- if (server_->Check(FP_TCP, FD_IN, *paddr))
+
+ virtual int Listen(int backlog) {
+ if (!server_->tcp_listen_enabled()) {
+ LOG(LS_VERBOSE) << "FirewallSocket listen attempt denied";
+ return -1;
+ }
+
+ return AsyncSocketAdapter::Listen(backlog);
+ }
+ virtual AsyncSocket* Accept(SocketAddress* paddr) {
+ SocketAddress addr;
+ while (AsyncSocket* sock = AsyncSocketAdapter::Accept(&addr)) {
+ if (server_->Check(FP_TCP, addr, GetLocalAddress())) {
+ if (paddr)
+ *paddr = addr;
return sock;
+ }
sock->Close();
delete sock;
- //LOG(INFO) << "FirewallSocket::Accept - Inbound TCP connection denied";
+ LOG(LS_VERBOSE) << "FirewallSocket inbound TCP connection from "
+ << addr.ToString() << " to "
+ << GetLocalAddress().ToString() << " denied";
}
return 0;
}
-private:
- FirewallSocketServer * server_;
+ private:
+ FirewallSocketServer* server_;
int type_;
};
-FirewallSocketServer::FirewallSocketServer(SocketServer * server, FirewallManager * manager) : server_(server), manager_(manager) {
+FirewallSocketServer::FirewallSocketServer(SocketServer* server,
+ FirewallManager* manager,
+ bool should_delete_server)
+ : server_(server), manager_(manager),
+ should_delete_server_(should_delete_server),
+ udp_sockets_enabled_(true), tcp_sockets_enabled_(true),
+ tcp_listen_enabled_(true) {
if (manager_)
manager_->AddServer(this);
}
@@ -125,14 +132,34 @@
FirewallSocketServer::~FirewallSocketServer() {
if (manager_)
manager_->RemoveServer(this);
+
+ if (server_ && should_delete_server_) {
+ delete server_;
+ server_ = NULL;
+ }
}
-void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p, FirewallDirection d, const SocketAddress& addr) {
+void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
+ FirewallDirection d,
+ const SocketAddress& addr) {
+ SocketAddress src, dst;
+ if (d == FD_IN) {
+ dst = addr;
+ } else {
+ src = addr;
+ }
+ AddRule(allow, p, src, dst);
+}
+
+
+void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
+ const SocketAddress& src,
+ const SocketAddress& dst) {
Rule r;
r.allow = allow;
r.p = p;
- r.d = d;
- r.addr = addr;
+ r.src = src;
+ r.dst = dst;
CritScope scope(&crit_);
rules_.push_back(r);
}
@@ -142,17 +169,21 @@
rules_.clear();
}
-bool FirewallSocketServer::Check(FirewallProtocol p, FirewallDirection d, const SocketAddress& addr) {
+bool FirewallSocketServer::Check(FirewallProtocol p,
+ const SocketAddress& src,
+ const SocketAddress& dst) {
CritScope scope(&crit_);
- for (size_t i=0; i<rules_.size(); ++i) {
+ for (size_t i = 0; i < rules_.size(); ++i) {
const Rule& r = rules_[i];
if ((r.p != p) && (r.p != FP_ANY))
continue;
- if ((r.d != d) && (r.d != FD_ANY))
+ if ((r.src.ip() != src.ip()) && !r.src.IsAny())
continue;
- if ((r.addr.ip() != addr.ip()) && !r.addr.IsAny())
+ if ((r.src.port() != src.port()) && (r.src.port() != 0))
continue;
- if ((r.addr.port() != addr.port()) && (r.addr.port() != 0))
+ if ((r.dst.ip() != dst.ip()) && !r.dst.IsAny())
+ continue;
+ if ((r.dst.port() != dst.port()) && (r.dst.port() != 0))
continue;
return r.allow;
}
@@ -160,22 +191,20 @@
}
Socket* FirewallSocketServer::CreateSocket(int type) {
- return WrapSocket(server_->CreateSocket(type), type);
+ return WrapSocket(server_->CreateAsyncSocket(type), type);
}
AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int type) {
return WrapSocket(server_->CreateAsyncSocket(type), type);
}
-Socket * FirewallSocketServer::WrapSocket(Socket * sock, int type) {
- if (!sock)
+AsyncSocket* FirewallSocketServer::WrapSocket(AsyncSocket* sock, int type) {
+ if (!sock ||
+ (type == SOCK_STREAM && !tcp_sockets_enabled_) ||
+ (type == SOCK_DGRAM && !udp_sockets_enabled_)) {
+ LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied";
return NULL;
- return new FirewallSocket(this, sock, type);
-}
-
-AsyncSocket * FirewallSocketServer::WrapSocket(AsyncSocket * sock, int type) {
- if (!sock)
- return NULL;
+ }
return new FirewallSocket(this, sock, type);
}
@@ -186,28 +215,32 @@
assert(servers_.empty());
}
-void FirewallManager::AddServer(FirewallSocketServer * server) {
+void FirewallManager::AddServer(FirewallSocketServer* server) {
CritScope scope(&crit_);
servers_.push_back(server);
}
-void FirewallManager::RemoveServer(FirewallSocketServer * server) {
+void FirewallManager::RemoveServer(FirewallSocketServer* server) {
CritScope scope(&crit_);
- servers_.erase(std::remove(servers_.begin(), servers_.end(), server), servers_.end());
+ servers_.erase(std::remove(servers_.begin(), servers_.end(), server),
+ servers_.end());
}
-void FirewallManager::AddRule(bool allow, FirewallProtocol p, FirewallDirection d, const SocketAddress& addr) {
+void FirewallManager::AddRule(bool allow, FirewallProtocol p,
+ FirewallDirection d, const SocketAddress& addr) {
CritScope scope(&crit_);
- for (std::vector<FirewallSocketServer *>::const_iterator it = servers_.begin(); it != servers_.end(); ++it) {
+ for (std::vector<FirewallSocketServer*>::const_iterator it =
+ servers_.begin(); it != servers_.end(); ++it) {
(*it)->AddRule(allow, p, d, addr);
}
}
void FirewallManager::ClearRules() {
CritScope scope(&crit_);
- for (std::vector<FirewallSocketServer *>::const_iterator it = servers_.begin(); it != servers_.end(); ++it) {
+ for (std::vector<FirewallSocketServer*>::const_iterator it =
+ servers_.begin(); it != servers_.end(); ++it) {
(*it)->ClearRules();
}
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/firewallsocketserver.h b/talk/base/firewallsocketserver.h
old mode 100755
new mode 100644
index 10c07e6..94ba2d2
--- a/talk/base/firewallsocketserver.h
+++ b/talk/base/firewallsocketserver.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_FIREWALLSOCKETSERVER_H__
-#define TALK_BASE_FIREWALLSOCKETSERVER_H__
+#ifndef TALK_BASE_FIREWALLSOCKETSERVER_H_
+#define TALK_BASE_FIREWALLSOCKETSERVER_H_
#include <vector>
#include "talk/base/socketserver.h"
@@ -36,30 +36,61 @@
class FirewallManager;
-// This SocketServer shim simulates a rule-based firewall server
+// This SocketServer shim simulates a rule-based firewall server.
enum FirewallProtocol { FP_UDP, FP_TCP, FP_ANY };
enum FirewallDirection { FD_IN, FD_OUT, FD_ANY };
class FirewallSocketServer : public SocketServer {
-public:
- FirewallSocketServer(SocketServer * server, FirewallManager * manager = 0);
+ public:
+ FirewallSocketServer(SocketServer * server,
+ FirewallManager * manager = NULL,
+ bool should_delete_server = false);
virtual ~FirewallSocketServer();
- void AddRule(bool allow, FirewallProtocol p = FP_ANY, FirewallDirection d = FD_ANY, const SocketAddress& addr = SocketAddress());
+ SocketServer* socketserver() const { return server_; }
+ void set_socketserver(SocketServer* server) {
+ if (server_ && should_delete_server_) {
+ delete server_;
+ server_ = NULL;
+ should_delete_server_ = false;
+ }
+ server_ = server;
+ }
+
+ // Settings to control whether CreateSocket or Socket::Listen succeed.
+ void set_udp_sockets_enabled(bool enabled) { udp_sockets_enabled_ = enabled; }
+ void set_tcp_sockets_enabled(bool enabled) { tcp_sockets_enabled_ = enabled; }
+ bool tcp_listen_enabled() const { return tcp_listen_enabled_; }
+ void set_tcp_listen_enabled(bool enabled) { tcp_listen_enabled_ = enabled; }
+
+ // Rules govern the behavior of Connect/Accept/Send/Recv attempts.
+ void AddRule(bool allow, FirewallProtocol p = FP_ANY,
+ FirewallDirection d = FD_ANY,
+ const SocketAddress& addr = SocketAddress());
+ void AddRule(bool allow, FirewallProtocol p,
+ const SocketAddress& src, const SocketAddress& dst);
void ClearRules();
- bool Check(FirewallProtocol p, FirewallDirection d, const SocketAddress& addr);
+ bool Check(FirewallProtocol p,
+ const SocketAddress& src, const SocketAddress& dst);
virtual Socket* CreateSocket(int type);
virtual AsyncSocket* CreateAsyncSocket(int type);
- virtual bool Wait(int cms, bool process_io) { return server_->Wait(cms, process_io); }
- virtual void WakeUp() { return server_->WakeUp(); }
+ virtual void SetMessageQueue(MessageQueue* queue) {
+ server_->SetMessageQueue(queue);
+ }
+ virtual bool Wait(int cms, bool process_io) {
+ return server_->Wait(cms, process_io);
+ }
+ virtual void WakeUp() {
+ return server_->WakeUp();
+ }
Socket * WrapSocket(Socket * sock, int type);
AsyncSocket * WrapSocket(AsyncSocket * sock, int type);
-private:
+ private:
SocketServer * server_;
FirewallManager * manager_;
CriticalSection crit_;
@@ -67,29 +98,36 @@
bool allow;
FirewallProtocol p;
FirewallDirection d;
- SocketAddress addr;
+ SocketAddress src;
+ SocketAddress dst;
};
std::vector<Rule> rules_;
+ bool should_delete_server_;
+ bool udp_sockets_enabled_;
+ bool tcp_sockets_enabled_;
+ bool tcp_listen_enabled_;
};
// FirewallManager allows you to manage firewalls in multiple threads together
class FirewallManager {
-public:
+ public:
FirewallManager();
~FirewallManager();
void AddServer(FirewallSocketServer * server);
void RemoveServer(FirewallSocketServer * server);
- void AddRule(bool allow, FirewallProtocol p = FP_ANY, FirewallDirection d = FD_ANY, const SocketAddress& addr = SocketAddress());
+ void AddRule(bool allow, FirewallProtocol p = FP_ANY,
+ FirewallDirection d = FD_ANY,
+ const SocketAddress& addr = SocketAddress());
void ClearRules();
-private:
+ private:
CriticalSection crit_;
std::vector<FirewallSocketServer *> servers_;
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_FIREWALLSOCKETSERVER_H__
+#endif // TALK_BASE_FIREWALLSOCKETSERVER_H_
diff --git a/talk/base/flags.cc b/talk/base/flags.cc
new file mode 100644
index 0000000..09a8edf
--- /dev/null
+++ b/talk/base/flags.cc
@@ -0,0 +1,324 @@
+/*
+ * libjingle
+ * Copyright 2006, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#ifdef WIN32
+#include "talk/base/win32.h"
+#include <shellapi.h>
+#endif
+
+#include "talk/base/flags.h"
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Flag
+
+Flag::Flag(const char* file, const char* name, const char* comment,
+ Type type, void* variable, FlagValue default__)
+ : file_(file),
+ name_(name),
+ comment_(comment),
+ type_(type),
+ variable_(reinterpret_cast<FlagValue*>(variable)),
+ default_(default__) {
+ FlagList::Register(this);
+}
+
+
+void Flag::SetToDefault() {
+ // Note that we cannot simply do '*variable_ = default_;' since
+ // flag variables are not really of type FlagValue and thus may
+ // be smaller! The FlagValue union is simply 'overlayed' on top
+ // of a flag variable for convenient access. Since union members
+ // are guarantee to be aligned at the beginning, this works.
+ switch (type_) {
+ case Flag::BOOL:
+ variable_->b = default_.b;
+ return;
+ case Flag::INT:
+ variable_->i = default_.i;
+ return;
+ case Flag::FLOAT:
+ variable_->f = default_.f;
+ return;
+ case Flag::STRING:
+ variable_->s = default_.s;
+ return;
+ }
+ UNREACHABLE();
+}
+
+
+static const char* Type2String(Flag::Type type) {
+ switch (type) {
+ case Flag::BOOL: return "bool";
+ case Flag::INT: return "int";
+ case Flag::FLOAT: return "float";
+ case Flag::STRING: return "string";
+ }
+ UNREACHABLE();
+ return NULL;
+}
+
+
+static void PrintFlagValue(Flag::Type type, FlagValue* p) {
+ switch (type) {
+ case Flag::BOOL:
+ printf("%s", (p->b ? "true" : "false"));
+ return;
+ case Flag::INT:
+ printf("%d", p->i);
+ return;
+ case Flag::FLOAT:
+ printf("%f", p->f);
+ return;
+ case Flag::STRING:
+ printf("%s", p->s);
+ return;
+ }
+ UNREACHABLE();
+}
+
+
+void Flag::Print(bool print_current_value) {
+ printf(" --%s (%s) type: %s default: ", name_, comment_,
+ Type2String(type_));
+ PrintFlagValue(type_, &default_);
+ if (print_current_value) {
+ printf(" current value: ");
+ PrintFlagValue(type_, variable_);
+ }
+ printf("\n");
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of FlagList
+
+Flag* FlagList::list_ = NULL;
+
+
+FlagList::FlagList() {
+ list_ = NULL;
+}
+
+void FlagList::Print(const char* file, bool print_current_value) {
+ // Since flag registration is likely by file (= C++ file),
+ // we don't need to sort by file and still get grouped output.
+ const char* current = NULL;
+ for (Flag* f = list_; f != NULL; f = f->next()) {
+ if (file == NULL || file == f->file()) {
+ if (current != f->file()) {
+ printf("Flags from %s:\n", f->file());
+ current = f->file();
+ }
+ f->Print(print_current_value);
+ }
+ }
+}
+
+
+Flag* FlagList::Lookup(const char* name) {
+ Flag* f = list_;
+ while (f != NULL && strcmp(name, f->name()) != 0)
+ f = f->next();
+ return f;
+}
+
+
+void FlagList::SplitArgument(const char* arg,
+ char* buffer, int buffer_size,
+ const char** name, const char** value,
+ bool* is_bool) {
+ *name = NULL;
+ *value = NULL;
+ *is_bool = false;
+
+ if (*arg == '-') {
+ // find the begin of the flag name
+ arg++; // remove 1st '-'
+ if (*arg == '-')
+ arg++; // remove 2nd '-'
+ if (arg[0] == 'n' && arg[1] == 'o') {
+ arg += 2; // remove "no"
+ *is_bool = true;
+ }
+ *name = arg;
+
+ // find the end of the flag name
+ while (*arg != '\0' && *arg != '=')
+ arg++;
+
+ // get the value if any
+ if (*arg == '=') {
+ // make a copy so we can NUL-terminate flag name
+ int n = arg - *name;
+ if (n >= buffer_size)
+ Fatal(__FILE__, __LINE__, "CHECK(%s) failed", "n < buffer_size");
+ memcpy(buffer, *name, n * sizeof(char));
+ buffer[n] = '\0';
+ *name = buffer;
+ // get the value
+ *value = arg + 1;
+ }
+ }
+}
+
+
+int FlagList::SetFlagsFromCommandLine(int* argc, const char** argv,
+ bool remove_flags) {
+ // parse arguments
+ for (int i = 1; i < *argc; /* see below */) {
+ int j = i; // j > 0
+ const char* arg = argv[i++];
+
+ // split arg into flag components
+ char buffer[1024];
+ const char* name;
+ const char* value;
+ bool is_bool;
+ SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
+
+ if (name != NULL) {
+ // lookup the flag
+ Flag* flag = Lookup(name);
+ if (flag == NULL) {
+ fprintf(stderr, "Error: unrecognized flag %s\n", arg);
+ return j;
+ }
+
+ // if we still need a flag value, use the next argument if available
+ if (flag->type() != Flag::BOOL && value == NULL) {
+ if (i < *argc) {
+ value = argv[i++];
+ } else {
+ fprintf(stderr, "Error: missing value for flag %s of type %s\n",
+ arg, Type2String(flag->type()));
+ return j;
+ }
+ }
+
+ // set the flag
+ char empty[] = { '\0' };
+ char* endp = empty;
+ switch (flag->type()) {
+ case Flag::BOOL:
+ *flag->bool_variable() = !is_bool;
+ break;
+ case Flag::INT:
+ *flag->int_variable() = strtol(value, &endp, 10);
+ break;
+ case Flag::FLOAT:
+ *flag->float_variable() = strtod(value, &endp);
+ break;
+ case Flag::STRING:
+ *flag->string_variable() = value;
+ break;
+ }
+
+ // handle errors
+ if ((flag->type() == Flag::BOOL && value != NULL) ||
+ (flag->type() != Flag::BOOL && is_bool) ||
+ *endp != '\0') {
+ fprintf(stderr, "Error: illegal value for flag %s of type %s\n",
+ arg, Type2String(flag->type()));
+ return j;
+ }
+
+ // remove the flag & value from the command
+ if (remove_flags)
+ while (j < i)
+ argv[j++] = NULL;
+ }
+ }
+
+ // shrink the argument list
+ if (remove_flags) {
+ int j = 1;
+ for (int i = 1; i < *argc; i++) {
+ if (argv[i] != NULL)
+ argv[j++] = argv[i];
+ }
+ *argc = j;
+ }
+
+ // parsed all flags successfully
+ return 0;
+}
+
+void FlagList::Register(Flag* flag) {
+ assert(flag != NULL && strlen(flag->name()) > 0);
+ if (Lookup(flag->name()) != NULL)
+ Fatal(flag->file(), 0, "flag %s declared twice", flag->name());
+ flag->next_ = list_;
+ list_ = flag;
+}
+
+#ifdef WIN32
+WindowsCommandLineArguments::WindowsCommandLineArguments() {
+ // start by getting the command line.
+ LPTSTR command_line = ::GetCommandLine();
+ // now, convert it to a list of wide char strings.
+ LPWSTR *wide_argv = ::CommandLineToArgvW(command_line, &argc_);
+ // now allocate an array big enough to hold that many string pointers.
+ argv_ = new char*[argc_];
+
+ // iterate over the returned wide strings;
+ for(int i = 0; i < argc_; ++i) {
+ // for each, create a char buffer big enough to hold it; so, find out
+ // how much space we need.
+ int len8 = WideCharToMultiByte(CP_UTF8, 0, wide_argv[i],
+ wcslen(wide_argv[i]), NULL, 0,
+ NULL, NULL);
+ // then allocate the buffer...
+ char *buffer = new char[1 + len8]; // +1 for trailing \0
+ // and do the conversion.
+ WideCharToMultiByte(CP_UTF8, 0, wide_argv[i],
+ wcslen(wide_argv[i]), buffer, len8,
+ NULL, NULL);
+ // WideCharToMultibyte doesn't give us a trailing \0, so we add it.
+ buffer[len8] = '\0';
+ // make sure the argv array has the right string at this point.
+ argv_[i] = buffer;
+ }
+ LocalFree(wide_argv);
+}
+
+WindowsCommandLineArguments::~WindowsCommandLineArguments() {
+ // need to free each string in the array, and then the array.
+ for(int i = 0; i < argc_; i++) {
+ delete[] argv_[i];
+ }
+
+ delete[] argv_;
+}
+#endif // WIN32
+
diff --git a/talk/base/flags.h b/talk/base/flags.h
new file mode 100644
index 0000000..a6eee00
--- /dev/null
+++ b/talk/base/flags.h
@@ -0,0 +1,281 @@
+/*
+ * libjingle
+ * Copyright 2006, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Flags are defined and declared using DEFINE_xxx and DECLARE_xxx macros,
+// where xxx is the flag type. Flags are referred to via FLAG_yyy,
+// where yyy is the flag name. For intialization and iteration of flags,
+// see the FlagList class. For full programmatic access to any
+// flag, see the Flag class.
+//
+// The implementation only relies and basic C++ functionality
+// and needs no special library or STL support.
+
+#ifndef TALK_BASE_FLAGS_H__
+#define TALK_BASE_FLAGS_H__
+
+#include <assert.h>
+
+#include "talk/base/checks.h"
+#include "talk/base/common.h"
+
+// Internal use only.
+union FlagValue {
+ // Note: Because in C++ non-bool values are silently converted into
+ // bool values ('bool b = "false";' results in b == true!), we pass
+ // and int argument to New_BOOL as this appears to be safer - sigh.
+ // In particular, it prevents the (not uncommon!) bug where a bool
+ // flag is defined via: DEFINE_bool(flag, "false", "some comment");.
+ static FlagValue New_BOOL(int b) {
+ FlagValue v;
+ v.b = (b != 0);
+ return v;
+ }
+
+ static FlagValue New_INT(int i) {
+ FlagValue v;
+ v.i = i;
+ return v;
+ }
+
+ static FlagValue New_FLOAT(float f) {
+ FlagValue v;
+ v.f = f;
+ return v;
+ }
+
+ static FlagValue New_STRING(const char* s) {
+ FlagValue v;
+ v.s = s;
+ return v;
+ }
+
+ bool b;
+ int i;
+ double f;
+ const char* s;
+};
+
+
+// Each flag can be accessed programmatically via a Flag object.
+class Flag {
+ public:
+ enum Type { BOOL, INT, FLOAT, STRING };
+
+ // Internal use only.
+ Flag(const char* file, const char* name, const char* comment,
+ Type type, void* variable, FlagValue default_);
+
+ // General flag information
+ const char* file() const { return file_; }
+ const char* name() const { return name_; }
+ const char* comment() const { return comment_; }
+
+ // Flag type
+ Type type() const { return type_; }
+
+ // Flag variables
+ bool* bool_variable() const {
+ assert(type_ == BOOL);
+ return &variable_->b;
+ }
+
+ int* int_variable() const {
+ assert(type_ == INT);
+ return &variable_->i;
+ }
+
+ double* float_variable() const {
+ assert(type_ == FLOAT);
+ return &variable_->f;
+ }
+
+ const char** string_variable() const {
+ assert(type_ == STRING);
+ return &variable_->s;
+ }
+
+ // Default values
+ bool bool_default() const {
+ assert(type_ == BOOL);
+ return default_.b;
+ }
+
+ int int_default() const {
+ assert(type_ == INT);
+ return default_.i;
+ }
+
+ double float_default() const {
+ assert(type_ == FLOAT);
+ return default_.f;
+ }
+
+ const char* string_default() const {
+ assert(type_ == STRING);
+ return default_.s;
+ }
+
+ // Resets a flag to its default value
+ void SetToDefault();
+
+ // Iteration support
+ Flag* next() const { return next_; }
+
+ // Prints flag information. The current flag value is only printed
+ // if print_current_value is set.
+ void Print(bool print_current_value);
+
+ private:
+ const char* file_;
+ const char* name_;
+ const char* comment_;
+
+ Type type_;
+ FlagValue* variable_;
+ FlagValue default_;
+
+ Flag* next_;
+
+ friend class FlagList; // accesses next_
+};
+
+
+// Internal use only.
+#define DEFINE_FLAG(type, c_type, name, default, comment) \
+ /* define and initialize the flag */ \
+ c_type FLAG_##name = (default); \
+ /* register the flag */ \
+ static Flag Flag_##name(__FILE__, #name, (comment), \
+ Flag::type, &FLAG_##name, \
+ FlagValue::New_##type(default))
+
+
+// Internal use only.
+#define DECLARE_FLAG(c_type, name) \
+ /* declare the external flag */ \
+ extern c_type FLAG_##name
+
+
+// Use the following macros to define a new flag:
+#define DEFINE_bool(name, default, comment) \
+ DEFINE_FLAG(BOOL, bool, name, default, comment)
+#define DEFINE_int(name, default, comment) \
+ DEFINE_FLAG(INT, int, name, default, comment)
+#define DEFINE_float(name, default, comment) \
+ DEFINE_FLAG(FLOAT, double, name, default, comment)
+#define DEFINE_string(name, default, comment) \
+ DEFINE_FLAG(STRING, const char*, name, default, comment)
+
+
+// Use the following macros to declare a flag defined elsewhere:
+#define DECLARE_bool(name) DECLARE_FLAG(bool, name)
+#define DECLARE_int(name) DECLARE_FLAG(int, name)
+#define DECLARE_float(name) DECLARE_FLAG(double, name)
+#define DECLARE_string(name) DECLARE_FLAG(const char*, name)
+
+
+// The global list of all flags.
+class FlagList {
+ public:
+ FlagList();
+
+ // The NULL-terminated list of all flags. Traverse with Flag::next().
+ static Flag* list() { return list_; }
+
+ // If file != NULL, prints information for all flags defined in file;
+ // otherwise prints information for all flags in all files. The current
+ // flag value is only printed if print_current_value is set.
+ static void Print(const char* file, bool print_current_value);
+
+ // Lookup a flag by name. Returns the matching flag or NULL.
+ static Flag* Lookup(const char* name);
+
+ // Helper function to parse flags: Takes an argument arg and splits it into
+ // a flag name and flag value (or NULL if they are missing). is_bool is set
+ // if the arg started with "-no" or "--no". The buffer may be used to NUL-
+ // terminate the name, it must be large enough to hold any possible name.
+ static void SplitArgument(const char* arg,
+ char* buffer, int buffer_size,
+ const char** name, const char** value,
+ bool* is_bool);
+
+ // Set the flag values by parsing the command line. If remove_flags
+ // is set, the flags and associated values are removed from (argc,
+ // argv). Returns 0 if no error occurred. Otherwise, returns the
+ // argv index > 0 for the argument where an error occurred. In that
+ // case, (argc, argv) will remain unchanged indepdendent of the
+ // remove_flags value, and no assumptions about flag settings should
+ // be made.
+ //
+ // The following syntax for flags is accepted (both '-' and '--' are ok):
+ //
+ // --flag (bool flags only)
+ // --noflag (bool flags only)
+ // --flag=value (non-bool flags only, no spaces around '=')
+ // --flag value (non-bool flags only)
+ static int SetFlagsFromCommandLine(int* argc,
+ const char** argv,
+ bool remove_flags);
+ static inline int SetFlagsFromCommandLine(int* argc,
+ char** argv,
+ bool remove_flags) {
+ return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv),
+ remove_flags);
+ }
+
+ // Registers a new flag. Called during program initialization. Not
+ // thread-safe.
+ static void Register(Flag* flag);
+
+ private:
+ static Flag* list_;
+};
+
+#ifdef WIN32
+// A helper class to translate Windows command line arguments into UTF8,
+// which then allows us to just pass them to the flags system.
+// This encapsulates all the work of getting the command line and translating
+// it to an array of 8-bit strings; all you have to do is create one of these,
+// and then call argc() and argv().
+class WindowsCommandLineArguments {
+ public:
+ WindowsCommandLineArguments();
+ ~WindowsCommandLineArguments();
+
+ int argc() { return argc_; }
+ char **argv() { return argv_; }
+ private:
+ int argc_;
+ char **argv_;
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(WindowsCommandLineArguments);
+};
+#endif // WIN32
+
+
+#endif // SHARED_COMMANDLINEFLAGS_FLAGS_H__
diff --git a/talk/base/helpers.cc b/talk/base/helpers.cc
old mode 100755
new mode 100644
index 627edce..94ca57e
--- a/talk/base/helpers.cc
+++ b/talk/base/helpers.cc
@@ -2,100 +2,193 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/base/helpers.h"
-#include "talk/base/time.h"
-#include <cstdlib>
-#include <cassert>
-
-// TODO: Change this implementation to use OpenSSL's RAND_bytes. That will
-// give cryptographically random values on all platforms.
#ifdef WIN32
-#include <time.h>
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#endif
-
-namespace cricket {
-
-static long g_seed = 1L;
-
-int GetRandom() {
- return ((g_seed = g_seed * 214013L + 2531011L) >> 16) & 0x7fff;
-}
-
-static bool s_initrandom;
-
-long GetRandomSeed() {
- return g_seed;
-}
-
-void SetRandomSeed(unsigned long seed)
-{
- s_initrandom = true;
- g_seed = (long)seed;
-}
-
-void InitRandom(const char *client_unique, size_t len) {
- // Hash this string - unique per client
-
- uint32 hash = 0;
- if (client_unique != NULL) {
- for (int i = 0; i < (int)len; i++)
- hash = ((hash << 2) + hash) + client_unique[i];
- }
-
- // Now initialize the seed against a high resolution
- // counter
-
- unsigned long seed = GetRandomSeed();
-
-#ifdef WIN32
- bool success = false;
- HCRYPTPROV hProv = NULL;
- if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
- success = (FALSE != CryptGenRandom(hProv,
- sizeof(seed),
- reinterpret_cast<BYTE*>(&seed)));
- CryptReleaseContext(hProv, 0);
- }
-
- if (!success) {
- LARGE_INTEGER big;
- QueryPerformanceCounter(&big);
- seed = big.LowPart;
- }
+#include <ntsecapi.h>
#else
- seed = talk_base::Time();
+#ifdef USE_OPENSSL
+#include <openssl/rand.h>
+#endif
#endif
- SetRandomSeed(seed ^ hash);
-}
+#include "talk/base/base64.h"
+#include "talk/base/logging.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/time.h"
-const char BASE64[64] = {
+namespace talk_base {
+
+// Base class for RNG implementations.
+class RandomGenerator {
+ public:
+ virtual ~RandomGenerator() {}
+ virtual bool Init(const void* seed, size_t len) = 0;
+ virtual bool Generate(void* buf, size_t len) = 0;
+};
+
+// The real random generators, using either CryptoAPI or OpenSSL.
+// We also support the 'old' generator on Mac/Linux until we have time to
+// fully test the OpenSSL one.
+#ifdef WIN32
+class SecureRandomGenerator : public RandomGenerator {
+ public:
+ SecureRandomGenerator() : advapi32_(NULL), rtl_gen_random_(NULL) {}
+ ~SecureRandomGenerator() {
+ FreeLibrary(advapi32_);
+ }
+
+ virtual bool Init(const void* seed, size_t seed_len) {
+ // We don't do any additional seeding on Win32, we just use the CryptoAPI
+ // RNG (which is exposed as a hidden function off of ADVAPI32 so that we
+ // don't need to drag in all of CryptoAPI)
+ if (rtl_gen_random_) {
+ return true;
+ }
+
+ advapi32_ = LoadLibrary(L"advapi32.dll");
+ if (!advapi32_) {
+ return false;
+ }
+
+ rtl_gen_random_ = reinterpret_cast<RtlGenRandomProc>(
+ GetProcAddress(advapi32_, "SystemFunction036"));
+ if (!rtl_gen_random_) {
+ FreeLibrary(advapi32_);
+ return false;
+ }
+
+ return true;
+ }
+ virtual bool Generate(void* buf, size_t len) {
+ if (!rtl_gen_random_ && !Init(NULL, 0)) {
+ return false;
+ }
+ return (rtl_gen_random_(buf, len) != FALSE);
+ }
+
+ private:
+ typedef BOOL (WINAPI *RtlGenRandomProc)(PVOID, ULONG);
+ HINSTANCE advapi32_;
+ RtlGenRandomProc rtl_gen_random_;
+};
+#else
+#ifndef USE_OPENSSL
+// The old RNG.
+class SecureRandomGenerator : public RandomGenerator {
+ public:
+ SecureRandomGenerator() : seed_(1) {
+ }
+ ~SecureRandomGenerator() {
+ }
+ virtual bool Init(const void* seed, size_t len) {
+ uint32 hash = 0;
+ for (size_t i = 0; i < len; ++i) {
+ hash = ((hash << 2) + hash) + static_cast<const char*>(seed)[i];
+ }
+
+ seed_ = Time() ^ hash;
+ return true;
+ }
+ virtual bool Generate(void* buf, size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ static_cast<uint8*>(buf)[i] = static_cast<uint8>(GetRandom());
+ }
+ return true;
+ }
+
+ private:
+ int GetRandom() {
+ return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
+ }
+ int seed_;
+};
+#else
+// The OpenSSL RNG. Need to make sure it doesn't run out of entropy.
+class SecureRandomGenerator : public RandomGenerator {
+ public:
+ SecureRandomGenerator() : inited_(false) {
+ }
+ ~SecureRandomGenerator() {
+ }
+ virtual bool Init(const void* seed, size_t len) {
+ // By default, seed from the system state.
+ if (!inited_) {
+ if (RAND_poll() != 0) {
+ return false;
+ }
+ inited_ = true;
+ }
+ // Allow app data to be mixed in, if provided.
+ if (seed) {
+ RAND_add(seed, len);
+ }
+ return true;
+ }
+ virtual bool Generate(void* buf, size_t len) {
+ if (!inited_ && !Init(NULL, 0)) {
+ return false;
+ }
+ return (RAND_bytes(buf, len) == 0);
+ }
+
+ private:
+ bool inited_;
+};
+#endif // USE_OPENSSL
+#endif // WIN32
+
+// A test random generator, for predictable output.
+class TestRandomGenerator : public RandomGenerator {
+ public:
+ TestRandomGenerator() : seed_(7) {
+ }
+ ~TestRandomGenerator() {
+ }
+ virtual bool Init(const void* seed, size_t len) {
+ return true;
+ }
+ virtual bool Generate(void* buf, size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ static_cast<uint8*>(buf)[i] = static_cast<uint8>(GetRandom());
+ }
+ return true;
+ }
+
+ private:
+ int GetRandom() {
+ return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
+ }
+ int seed_;
+};
+
+// TODO: Use Base64::Base64Table instead.
+static const char BASE64[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
@@ -103,46 +196,54 @@
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
-// Generates a random string of the given length. We generate base64 values so
-// that they will be printable, though that's not necessary.
+static scoped_ptr<RandomGenerator> g_rng(new SecureRandomGenerator());
-std::string CreateRandomString(int len) {
- // Random number generator should of been initialized!
- assert(s_initrandom);
- if (!s_initrandom)
- InitRandom(0, 0);
-
- std::string str;
- for (int i = 0; i < len; i++)
-#if defined(_MSC_VER) && _MSC_VER < 1300
- str.insert(str.end(), BASE64[GetRandom() & 63]);
-#else
- str.push_back(BASE64[GetRandom() & 63]);
-#endif
- return str;
+void SetRandomTestMode(bool test) {
+ if (!test) {
+ g_rng.reset(new SecureRandomGenerator());
+ } else {
+ g_rng.reset(new TestRandomGenerator());
+ }
}
-uint32 CreateRandomId() {
- uint8 b1 = (uint8)(GetRandom() & 255);
- uint8 b2 = (uint8)(GetRandom() & 255);
- uint8 b3 = (uint8)(GetRandom() & 255);
- uint8 b4 = (uint8)(GetRandom() & 255);
- return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
+bool InitRandom(int seed) {
+ return InitRandom(reinterpret_cast<const char*>(&seed), sizeof(seed));
}
-bool IsBase64Char(char ch) {
- return (('A' <= ch) && (ch <= 'Z')) ||
- (('a' <= ch) && (ch <= 'z')) ||
- (('0' <= ch) && (ch <= '9')) ||
- (ch == '+') || (ch == '/');
-}
-
-bool IsBase64Encoded(const std::string& str) {
- for (size_t i = 0; i < str.size(); ++i) {
- if (!IsBase64Char(str.at(i)))
- return false;
+bool InitRandom(const char* seed, size_t len) {
+ if (!g_rng->Init(seed, len)) {
+ LOG(LS_ERROR) << "Failed to init random generator!";
+ return false;
}
return true;
}
-} // namespace cricket
+std::string CreateRandomString(size_t len) {
+ std::string str;
+ scoped_array<uint8> bytes(new uint8[len]);
+ if (!g_rng->Generate(bytes.get(), len)) {
+ LOG(LS_ERROR) << "Failed to generate random string!";
+ }
+ for (size_t i = 0; i < len; i++) {
+ str.push_back(BASE64[bytes[i] & 63]);
+ }
+ return str;
+}
+
+uint32 CreateRandomId() {
+ uint32 id;
+ if (!g_rng->Generate(&id, sizeof(id))) {
+ LOG(LS_ERROR) << "Failed to generate random id!";
+ }
+ return id;
+}
+
+uint32 CreateRandomNonZeroId() {
+ uint32 id;
+ do {
+ id = CreateRandomId();
+ } while (id == 0);
+ return id;
+}
+
+} // namespace talk_base
diff --git a/talk/base/helpers.h b/talk/base/helpers.h
old mode 100755
new mode 100644
index 696edbe..878efc1
--- a/talk/base/helpers.h
+++ b/talk/base/helpers.h
@@ -2,54 +2,54 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __HELPERS_H__
-#define __HELPERS_H__
+#ifndef TALK_BASE_HELPERS_H_
+#define TALK_BASE_HELPERS_H_
-#include "talk/base/basictypes.h"
#include <string>
+#include "talk/base/basictypes.h"
-namespace cricket {
+namespace talk_base {
-// srand initializer
-void InitRandom(const char *client_unique, size_t len);
+// For testing, we can return predictable data.
+void SetRandomTestMode(bool test);
-// For testing, the random seed can be directly accessed.
-long GetRandomSeed();
-void SetRandomSeed(unsigned long seed);
+// Initializes the RNG, and seeds it with the specified entropy.
+bool InitRandom(int seed);
+bool InitRandom(const char* seed, size_t len);
// Generates a (cryptographically) random string of the given length.
-std::string CreateRandomString(int length);
+// We generate base64 values so that they will be printable.
+std::string CreateRandomString(size_t length);
-// Generates a random id
+// Generates a random id.
uint32 CreateRandomId();
-// Determines whether the given string consists entirely of valid base64
-// encoded characters.
-bool IsBase64Encoded(const std::string& str);
+// Generates a random id > 0.
+uint32 CreateRandomNonZeroId();
-} // namespace cricket
+} // namespace talk_base
-#endif // __HELPERS_H__
+#endif // TALK_BASE_HELPERS_H_
diff --git a/talk/base/host.cc b/talk/base/host.cc
old mode 100755
new mode 100644
index df5f7f7..7decc49
--- a/talk/base/host.cc
+++ b/talk/base/host.cc
@@ -2,99 +2,48 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <string>
-#include <iostream>
-#include <cassert>
-#include <errno.h>
+#include "talk/base/host.h"
#ifdef POSIX
-extern "C" {
#include <sys/utsname.h>
-}
-#endif // POSIX
+#endif // POSIX
-#include "talk/base/host.h"
-#include "talk/base/logging.h"
-#include "talk/base/network.h"
-#include "talk/base/socket.h"
-
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::strerror;
- using ::exit;
-}
-#endif
+#include <string>
namespace talk_base {
-namespace {
-
-void FatalError(const std::string& name, int err) {
- PLOG(LERROR, err) << name;
- std::exit(1);
-}
-
-}
-
-#ifdef POSIX
std::string GetHostName() {
+ // TODO: fix or get rid of this
+#if 0
struct utsname nm;
if (uname(&nm) < 0)
- FatalError("uname", errno);
+ FatalError("uname", LAST_SYSTEM_ERROR);
return std::string(nm.nodename);
-}
#endif
-
-#ifdef WIN32
-std::string GetHostName() {
- // TODO: fix this
return "cricket";
}
-#endif
-// Records information about the local host.
-Host* gLocalHost = 0;
-
-const Host& LocalHost() {
- if (!gLocalHost) {
- std::vector<Network*>* networks = new std::vector<Network*>;
- NetworkManager::CreateNetworks(*networks);
-#ifdef WIN32
- // This is sort of problematic... one part of the code (the unittests) wants
- // 127.0.0.1 to be present and another part (port allocators) don't. Right
- // now, they use different APIs, so we can have different behavior. But
- // there is something wrong with this.
- networks->push_back(new Network("localhost",
- SocketAddress::StringToIP("127.0.0.1")));
-#endif
- gLocalHost = new Host(GetHostName(), networks);
- assert(gLocalHost->networks().size() > 0);
- }
-
- return *gLocalHost;
-}
-
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/host.h b/talk/base/host.h
old mode 100755
new mode 100644
index 7ee603d..8528240
--- a/talk/base/host.h
+++ b/talk/base/host.h
@@ -25,35 +25,16 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_HOST_H__
-#define TALK_BASE_HOST_H__
+#ifndef TALK_BASE_HOST_H_
+#define TALK_BASE_HOST_H_
#include <string>
-#include <vector>
-#include "talk/base/network.h"
namespace talk_base {
-// Provides information about a host in the network.
-class Host {
-public:
- Host(const std::string& name, std::vector<Network*>* networks)
- : name_(name), networks_(networks) { }
-
- const std::string& name() const { return name_; }
- const std::vector<Network*>& networks() const { return *networks_; }
-
-private:
- std::string name_;
- std::vector<Network*>* networks_;
-};
-
-// Returns a reference to the description of the local host.
-const Host& LocalHost();
-
// Returns the name of the local host.
std::string GetHostName();
} // namespace talk_base
-#endif // TALK_BASE_HOST_H__
+#endif // TALK_BASE_HOST_H_
diff --git a/talk/base/httpbase.cc b/talk/base/httpbase.cc
old mode 100755
new mode 100644
index 06b7378..f5dc60e
--- a/talk/base/httpbase.cc
+++ b/talk/base/httpbase.cc
@@ -2,32 +2,32 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef OSX
-#include <errno.h>
-#endif
+// Copyright 2005 Google Inc. All Rights Reserved.
+//
+
#ifdef WIN32
#include "talk/base/win32.h"
@@ -40,6 +40,7 @@
#include "talk/base/logging.h"
#include "talk/base/socket.h"
#include "talk/base/stringutils.h"
+#include "talk/base/thread.h"
namespace talk_base {
@@ -53,6 +54,10 @@
return (len == header_len) && (_strnicmp(str, header_str, header_len) == 0);
}
+enum {
+ MSG_READ
+};
+
//////////////////////////////////////////////////////////////////////
// HttpParser
//////////////////////////////////////////////////////////////////////
@@ -64,50 +69,53 @@
HttpParser::~HttpParser() {
}
-void
+void
HttpParser::reset() {
state_ = ST_LEADER;
chunked_ = false;
data_size_ = SIZE_UNKNOWN;
}
-bool
-HttpParser::process(const char* buffer, size_t len, size_t& processed,
- HttpError& err) {
- processed = 0;
- err = HE_NONE;
+HttpParser::ProcessResult
+HttpParser::Process(const char* buffer, size_t len, size_t* processed,
+ HttpError* error) {
+ *processed = 0;
+ *error = HE_NONE;
if (state_ >= ST_COMPLETE) {
ASSERT(false);
- return false;
+ return PR_COMPLETE;
}
while (true) {
if (state_ < ST_DATA) {
- size_t pos = processed;
+ size_t pos = *processed;
while ((pos < len) && (buffer[pos] != '\n')) {
pos += 1;
}
if (pos >= len) {
- break; // don't have a full header
+ break; // don't have a full header
}
- const char* line = buffer + processed;
- size_t len = (pos - processed);
- processed = pos + 1;
+ const char* line = buffer + *processed;
+ size_t len = (pos - *processed);
+ *processed = pos + 1;
while ((len > 0) && isspace(static_cast<unsigned char>(line[len-1]))) {
len -= 1;
}
- if (!process_line(line, len, err)) {
- return false; // no more processing
+ ProcessResult result = ProcessLine(line, len, error);
+ LOG(LS_VERBOSE) << "Processed line, result=" << result;
+
+ if (PR_CONTINUE != result) {
+ return result;
}
} else if (data_size_ == 0) {
if (chunked_) {
state_ = ST_CHUNKTERM;
} else {
- return false;
+ return PR_COMPLETE;
}
} else {
- size_t available = len - processed;
+ size_t available = len - *processed;
if (available <= 0) {
break; // no more data
}
@@ -115,34 +123,41 @@
available = data_size_;
}
size_t read = 0;
- err = onHttpRecvData(buffer + processed, available, read);
- if (err != HE_NONE) {
- return false; // error occurred
+ ProcessResult result = ProcessData(buffer + *processed, available, read,
+ error);
+ LOG(LS_VERBOSE) << "Processed data, result: " << result << " read: "
+ << read << " err: " << error;
+
+ if (PR_CONTINUE != result) {
+ return result;
}
- processed += read;
+ *processed += read;
if (data_size_ != SIZE_UNKNOWN) {
data_size_ -= read;
}
}
}
- return true;
+ return PR_CONTINUE;
}
-bool
-HttpParser::process_line(const char* line, size_t len, HttpError& err) {
+HttpParser::ProcessResult
+HttpParser::ProcessLine(const char* line, size_t len, HttpError* error) {
+ LOG_F(LS_VERBOSE) << " state: " << state_ << " line: "
+ << std::string(line, len) << " len: " << len << " err: "
+ << error;
+
switch (state_) {
case ST_LEADER:
state_ = ST_HEADERS;
- err = onHttpRecvLeader(line, len);
- break;
+ return ProcessLeader(line, len, error);
case ST_HEADERS:
if (len > 0) {
const char* value = strchrn(line, len, ':');
if (!value) {
- err = HE_PROTOCOL;
- break;
+ *error = HE_PROTOCOL;
+ return PR_COMPLETE;
}
size_t nlen = (value - line);
const char* eol = line + len;
@@ -151,24 +166,26 @@
} while ((value < eol) && isspace(static_cast<unsigned char>(*value)));
size_t vlen = eol - value;
if (MatchHeader(line, nlen, HH_CONTENT_LENGTH)) {
- if (sscanf(value, "%d", &data_size_) != 1) {
- err = HE_PROTOCOL;
- break;
+ unsigned int temp_size;
+ if (sscanf(value, "%u", &temp_size) != 1) {
+ *error = HE_PROTOCOL;
+ return PR_COMPLETE;
}
+ data_size_ = static_cast<size_t>(temp_size);
} else if (MatchHeader(line, nlen, HH_TRANSFER_ENCODING)) {
if ((vlen == 7) && (_strnicmp(value, "chunked", 7) == 0)) {
chunked_ = true;
} else if ((vlen == 8) && (_strnicmp(value, "identity", 8) == 0)) {
chunked_ = false;
} else {
- err = HE_PROTOCOL;
- break;
+ *error = HE_PROTOCOL;
+ return PR_COMPLETE;
}
}
- err = onHttpRecvHeader(line, nlen, value, vlen);
+ return ProcessHeader(line, nlen, value, vlen, error);
} else {
state_ = chunked_ ? ST_CHUNKSIZE : ST_DATA;
- err = onHttpRecvHeaderComplete(chunked_, data_size_);
+ return ProcessHeaderComplete(chunked_, data_size_, error);
}
break;
@@ -177,18 +194,20 @@
char* ptr = NULL;
data_size_ = strtoul(line, &ptr, 16);
if (ptr != line + len) {
- err = HE_PROTOCOL;
- break;
+ *error = HE_PROTOCOL;
+ return PR_COMPLETE;
}
state_ = (data_size_ == 0) ? ST_TRAILERS : ST_DATA;
} else {
- err = HE_PROTOCOL;
+ *error = HE_PROTOCOL;
+ return PR_COMPLETE;
}
break;
case ST_CHUNKTERM:
if (len > 0) {
- err = HE_PROTOCOL;
+ *error = HE_PROTOCOL;
+ return PR_COMPLETE;
} else {
state_ = chunked_ ? ST_CHUNKSIZE : ST_DATA;
}
@@ -196,239 +215,510 @@
case ST_TRAILERS:
if (len == 0) {
- return false;
+ return PR_COMPLETE;
}
- // err = onHttpRecvTrailer();
+ // *error = onHttpRecvTrailer();
break;
default:
+ ASSERT(false);
break;
}
- return (err == HE_NONE);
+ return PR_CONTINUE;
}
-
-void
-HttpParser::end_of_input() {
- if ((state_ == ST_DATA) && (data_size_ == SIZE_UNKNOWN)) {
- complete(HE_NONE);
- } else {
- complete(HE_DISCONNECTED);
+
+bool
+HttpParser::is_valid_end_of_input() const {
+ return (state_ == ST_DATA) && (data_size_ == SIZE_UNKNOWN);
+}
+
+void
+HttpParser::complete(HttpError error) {
+ if (state_ < ST_COMPLETE) {
+ state_ = ST_COMPLETE;
+ OnComplete(error);
}
}
-void
-HttpParser::complete(HttpError err) {
- if (state_ < ST_COMPLETE) {
- state_ = ST_COMPLETE;
- onHttpRecvComplete(err);
+//////////////////////////////////////////////////////////////////////
+// HttpBase::DocumentStream
+//////////////////////////////////////////////////////////////////////
+
+class BlockingMemoryStream : public ExternalMemoryStream {
+public:
+ BlockingMemoryStream(char* buffer, size_t size)
+ : ExternalMemoryStream(buffer, size) { }
+
+ virtual StreamResult DoReserve(size_t size, int* error) {
+ return (buffer_length_ >= size) ? SR_SUCCESS : SR_BLOCK;
}
-}
+};
+
+class HttpBase::DocumentStream : public StreamInterface {
+public:
+ DocumentStream(HttpBase* base) : base_(base), error_(HE_DEFAULT) { }
+
+ virtual StreamState GetState() const {
+ if (NULL == base_)
+ return SS_CLOSED;
+ if (HM_RECV == base_->mode_)
+ return SS_OPEN;
+ return SS_OPENING;
+ }
+
+ virtual StreamResult Read(void* buffer, size_t buffer_len,
+ size_t* read, int* error) {
+ if (!base_) {
+ if (error) *error = error_;
+ return (HE_NONE == error_) ? SR_EOS : SR_ERROR;
+ }
+
+ if (HM_RECV != base_->mode_) {
+ return SR_BLOCK;
+ }
+
+ // DoReceiveLoop writes http document data to the StreamInterface* document
+ // member of HttpData. In this case, we want this data to be written
+ // directly to our buffer. To accomplish this, we wrap our buffer with a
+ // StreamInterface, and replace the existing document with our wrapper.
+ // When the method returns, we restore the old document. Ideally, we would
+ // pass our StreamInterface* to DoReceiveLoop, but due to the callbacks
+ // of HttpParser, we would still need to store the pointer temporarily.
+ scoped_ptr<StreamInterface>
+ stream(new BlockingMemoryStream(reinterpret_cast<char*>(buffer),
+ buffer_len));
+
+ // Replace the existing document with our wrapped buffer.
+ base_->data_->document.swap(stream);
+
+ // Pump the I/O loop. DoReceiveLoop is guaranteed not to attempt to
+ // complete the I/O process, which means that our wrapper is not in danger
+ // of being deleted. To ensure this, DoReceiveLoop returns true when it
+ // wants complete to be called. We make sure to uninstall our wrapper
+ // before calling complete().
+ HttpError http_error;
+ bool complete = base_->DoReceiveLoop(&http_error);
+
+ // Reinstall the original output document.
+ base_->data_->document.swap(stream);
+
+ // If we reach the end of the receive stream, we disconnect our stream
+ // adapter from the HttpBase, and further calls to read will either return
+ // EOS or ERROR, appropriately. Finally, we call complete().
+ StreamResult result = SR_BLOCK;
+ if (complete) {
+ HttpBase* base = Disconnect(http_error);
+ if (error) *error = error_;
+ result = (HE_NONE == error_) ? SR_EOS : SR_ERROR;
+ base->complete(http_error);
+ }
+
+ // Even if we are complete, if some data was read we must return SUCCESS.
+ // Future Reads will return EOS or ERROR based on the error_ variable.
+ size_t position;
+ stream->GetPosition(&position);
+ if (position > 0) {
+ if (read) *read = position;
+ result = SR_SUCCESS;
+ }
+ return result;
+ }
+
+ virtual StreamResult Write(const void* data, size_t data_len,
+ size_t* written, int* error) {
+ if (error) *error = -1;
+ return SR_ERROR;
+ }
+
+ virtual void Close() {
+ if (base_) {
+ HttpBase* base = Disconnect(HE_NONE);
+ if (HM_RECV == base->mode_ && base->http_stream_) {
+ // Read I/O could have been stalled on the user of this DocumentStream,
+ // so restart the I/O process now that we've removed ourselves.
+ base->http_stream_->PostEvent(SE_READ, 0);
+ }
+ }
+ }
+
+ virtual bool GetAvailable(size_t* size) const {
+ if (!base_ || HM_RECV != base_->mode_)
+ return false;
+ size_t data_size = base_->GetDataRemaining();
+ if (SIZE_UNKNOWN == data_size)
+ return false;
+ if (size)
+ *size = data_size;
+ return true;
+ }
+
+ HttpBase* Disconnect(HttpError error) {
+ ASSERT(NULL != base_);
+ ASSERT(NULL != base_->doc_stream_);
+ HttpBase* base = base_;
+ base_->doc_stream_ = NULL;
+ base_ = NULL;
+ error_ = error;
+ return base;
+ }
+
+private:
+ HttpBase* base_;
+ HttpError error_;
+};
//////////////////////////////////////////////////////////////////////
// HttpBase
//////////////////////////////////////////////////////////////////////
HttpBase::HttpBase() : mode_(HM_NONE), data_(NULL), notify_(NULL),
- stream_(NULL) {
+ http_stream_(NULL), doc_stream_(NULL) {
}
HttpBase::~HttpBase() {
+ ASSERT(HM_NONE == mode_);
}
bool
HttpBase::isConnected() const {
- return (stream_ != NULL) && (stream_->GetState() == SS_OPEN);
+ return (http_stream_ != NULL) && (http_stream_->GetState() == SS_OPEN);
}
bool
HttpBase::attach(StreamInterface* stream) {
- if ((mode_ != HM_NONE) || (stream_ != NULL) || (stream == NULL)) {
+ if ((mode_ != HM_NONE) || (http_stream_ != NULL) || (stream == NULL)) {
ASSERT(false);
return false;
}
- stream_ = stream;
- stream_->SignalEvent.connect(this, &HttpBase::OnEvent);
- mode_ = (stream_->GetState() == SS_OPENING) ? HM_CONNECT : HM_NONE;
+ http_stream_ = stream;
+ http_stream_->SignalEvent.connect(this, &HttpBase::OnHttpStreamEvent);
+ mode_ = (http_stream_->GetState() == SS_OPENING) ? HM_CONNECT : HM_NONE;
return true;
}
StreamInterface*
HttpBase::detach() {
+ ASSERT(HM_NONE == mode_);
if (mode_ != HM_NONE) {
- ASSERT(false);
return NULL;
}
- StreamInterface* stream = stream_;
- stream_ = NULL;
+ StreamInterface* stream = http_stream_;
+ http_stream_ = NULL;
if (stream) {
stream->SignalEvent.disconnect(this);
}
return stream;
}
-/*
-bool
-HttpBase::accept(PNSocket& socket) {
- if (mode_ != HM_NONE) {
- ASSERT(false);
- return false;
- }
-
- return socket.accept(stream_);
-}
-
-void
-HttpBase::connect(const SocketAddress& addr) {
- if (mode_ != HM_NONE) {
- ASSERT(false);
- return;
- }
-
- mode_ = HM_CONNECT;
-
- SocketAddress local;
- if (!stream_.connect(local, addr) && !stream_.isBlocking()) {
- onSocketConnect(&stream_, stream_.getError());
- }
-}
-*/
void
HttpBase::send(HttpData* data) {
+ ASSERT(HM_NONE == mode_);
if (mode_ != HM_NONE) {
- ASSERT(false);
return;
} else if (!isConnected()) {
- OnEvent(stream_, SE_CLOSE, HE_DISCONNECTED);
+ OnHttpStreamEvent(http_stream_, SE_CLOSE, HE_DISCONNECTED);
return;
}
-
+
mode_ = HM_SEND;
data_ = data;
len_ = 0;
ignore_data_ = chunk_data_ = false;
+ if (data_->document.get()) {
+ data_->document->SignalEvent.connect(this, &HttpBase::OnDocumentEvent);
+ }
+
std::string encoding;
if (data_->hasHeader(HH_TRANSFER_ENCODING, &encoding)
&& (encoding == "chunked")) {
chunk_data_ = true;
}
-
+
len_ = data_->formatLeader(buffer_, sizeof(buffer_));
len_ += strcpyn(buffer_ + len_, sizeof(buffer_) - len_, "\r\n");
- header_ = data_->begin();
- queue_headers();
- OnEvent(stream_, SE_WRITE, 0);
+ header_ = data_->begin();
+ if (header_ == data_->end()) {
+ // We must call this at least once, in the case where there are no headers.
+ queue_headers();
+ }
+
+ flush_data();
}
void
HttpBase::recv(HttpData* data) {
+ ASSERT(HM_NONE == mode_);
if (mode_ != HM_NONE) {
- ASSERT(false);
return;
} else if (!isConnected()) {
- OnEvent(stream_, SE_CLOSE, HE_DISCONNECTED);
+ OnHttpStreamEvent(http_stream_, SE_CLOSE, HE_DISCONNECTED);
return;
}
-
+
mode_ = HM_RECV;
data_ = data;
len_ = 0;
ignore_data_ = chunk_data_ = false;
-
+
reset();
- OnEvent(stream_, SE_READ, 0);
+ if (doc_stream_) {
+ doc_stream_->SignalEvent(doc_stream_, SE_OPEN | SE_READ, 0);
+ } else {
+ read_and_process_data();
+ }
}
void
HttpBase::abort(HttpError err) {
if (mode_ != HM_NONE) {
- if (stream_ != NULL) {
- stream_->Close();
+ if (http_stream_ != NULL) {
+ http_stream_->Close();
}
do_complete(err);
}
}
+StreamInterface* HttpBase::GetDocumentStream() {
+ if (doc_stream_)
+ return NULL;
+ doc_stream_ = new DocumentStream(this);
+ return doc_stream_;
+}
+
+HttpError HttpBase::HandleStreamClose(int error) {
+ if (http_stream_ != NULL) {
+ http_stream_->Close();
+ }
+ if (error == 0) {
+ if ((mode_ == HM_RECV) && is_valid_end_of_input()) {
+ return HE_NONE;
+ } else {
+ return HE_DISCONNECTED;
+ }
+ } else if (error == SOCKET_EACCES) {
+ return HE_AUTH;
+ } else if (error == SEC_E_CERT_EXPIRED) {
+ return HE_CERTIFICATE_EXPIRED;
+ }
+ LOG_F(LS_ERROR) << "(" << error << ")";
+ return (HM_CONNECT == mode_) ? HE_CONNECT_FAILED : HE_SOCKET_ERROR;
+}
+
+bool HttpBase::DoReceiveLoop(HttpError* error) {
+ ASSERT(HM_RECV == mode_);
+ ASSERT(NULL != error);
+
+ // Do to the latency between receiving read notifications from
+ // pseudotcpchannel, we rely on repeated calls to read in order to acheive
+ // ideal throughput. The number of reads is limited to prevent starving
+ // the caller.
+
+ size_t loop_count = 0;
+ const size_t kMaxReadCount = 20;
+ bool process_requires_more_data = false;
+ do {
+ // The most frequent use of this function is response to new data available
+ // on http_stream_. Therefore, we optimize by attempting to read from the
+ // network first (as opposed to processing existing data first).
+
+ if (len_ < sizeof(buffer_)) {
+ // Attempt to buffer more data.
+ size_t read;
+ int read_error;
+ StreamResult read_result = http_stream_->Read(buffer_ + len_,
+ sizeof(buffer_) - len_,
+ &read, &read_error);
+ switch (read_result) {
+ case SR_SUCCESS:
+ ASSERT(len_ + read <= sizeof(buffer_));
+ len_ += read;
+ break;
+ case SR_BLOCK:
+ if (process_requires_more_data) {
+ // We're can't make progress until more data is available.
+ return false;
+ }
+ // Attempt to process the data already in our buffer.
+ break;
+ case SR_EOS:
+ // Clean close, with no error. Fall through to HandleStreamClose.
+ read_error = 0;
+ case SR_ERROR:
+ *error = HandleStreamClose(read_error);
+ return true;
+ }
+ } else if (process_requires_more_data) {
+ // We have too much unprocessed data in our buffer. This should only
+ // occur when a single HTTP header is longer than the buffer size (32K).
+ // Anything longer than that is almost certainly an error.
+ *error = HE_OVERFLOW;
+ return true;
+ }
+
+ // Process data in our buffer. Process is not guaranteed to process all
+ // the buffered data. In particular, it will wait until a complete
+ // protocol element (such as http header, or chunk size) is available,
+ // before processing it in its entirety. Also, it is valid and sometimes
+ // necessary to call Process with an empty buffer, since the state machine
+ // may have interrupted state transitions to complete.
+ size_t processed;
+ ProcessResult process_result = Process(buffer_, len_, &processed,
+ error);
+ ASSERT(processed <= len_);
+ len_ -= processed;
+ memmove(buffer_, buffer_ + processed, len_);
+ switch (process_result) {
+ case PR_CONTINUE:
+ // We need more data to make progress.
+ process_requires_more_data = true;
+ break;
+ case PR_BLOCK:
+ // We're stalled on writing the processed data.
+ return false;
+ case PR_COMPLETE:
+ // *error already contains the correct code.
+ return true;
+ }
+ } while (++loop_count <= kMaxReadCount);
+
+ LOG_F(LS_WARNING) << "danger of starvation";
+ return false;
+}
+
+void
+HttpBase::read_and_process_data() {
+ HttpError error;
+ if (DoReceiveLoop(&error)) {
+ complete(error);
+ }
+}
+
void
HttpBase::flush_data() {
+ ASSERT(HM_SEND == mode_);
+
+ // When send_required is true, no more buffering can occur without a network
+ // write.
+ bool send_required = (len_ >= sizeof(buffer_));
+
while (true) {
- for (size_t start = 0; start < len_; ) {
- size_t written;
- int error;
- StreamResult result = stream_->Write(buffer_ + start, len_ - start,
- &written, &error);
- if (result == SR_SUCCESS) {
- //LOG_F(LS_INFO) << "wrote " << res << " bytes";
- start += written;
- continue;
- } else if (result == SR_BLOCK) {
- //LOG_F(LS_INFO) << "blocking";
- len_ -= start;
- memmove(buffer_, buffer_ + start, len_);
- return;
+ ASSERT(len_ <= sizeof(buffer_));
+
+ // HTTP is inherently sensitive to round trip latency, since a frequent use
+ // case is for small requests and responses to be sent back and forth, and
+ // the lack of pipelining forces a single request to take a minimum of the
+ // round trip time. As a result, it is to our benefit to pack as much data
+ // into each packet as possible. Thus, we defer network writes until we've
+ // buffered as much data as possible.
+
+ if (!send_required && (header_ != data_->end())) {
+ // First, attempt to queue more header data.
+ send_required = queue_headers();
+ }
+
+ if (!send_required && (NULL != data_->document.get())) {
+ // Next, attempt to queue document data.
+
+ const size_t kChunkDigits = 8;
+ size_t offset, reserve;
+ if (chunk_data_) {
+ // Reserve characters at the start for X-byte hex value and \r\n
+ offset = len_ + kChunkDigits + 2;
+ // ... and 2 characters at the end for \r\n
+ reserve = offset + 2;
} else {
- ASSERT(result == SR_ERROR);
- LOG_F(LS_ERROR) << "error";
- OnEvent(stream_, SE_CLOSE, error);
- return;
+ offset = len_;
+ reserve = offset;
+ }
+
+ if (reserve >= sizeof(buffer_)) {
+ send_required = true;
+ } else {
+ size_t read;
+ int error;
+ StreamResult result = data_->document->Read(buffer_ + offset,
+ sizeof(buffer_) - reserve,
+ &read, &error);
+ if (result == SR_SUCCESS) {
+ ASSERT(reserve + read <= sizeof(buffer_));
+ if (chunk_data_) {
+ // Prepend the chunk length in hex.
+ // Note: sprintfn appends a null terminator, which is why we can't
+ // combine it with the line terminator.
+ sprintfn(buffer_ + len_, kChunkDigits + 1, "%.*x",
+ kChunkDigits, read);
+ // Add line terminator to the chunk length.
+ memcpy(buffer_ + len_ + kChunkDigits, "\r\n", 2);
+ // Add line terminator to the end of the chunk.
+ memcpy(buffer_ + offset + read, "\r\n", 2);
+ }
+ len_ = reserve + read;
+ } else if (result == SR_BLOCK) {
+ // Nothing to do but flush data to the network.
+ send_required = true;
+ } else if (result == SR_EOS) {
+ if (chunk_data_) {
+ // Append the empty chunk and empty trailers, then turn off
+ // chunking.
+ ASSERT(len_ + 5 <= sizeof(buffer_));
+ memcpy(buffer_ + len_, "0\r\n\r\n", 5);
+ len_ += 5;
+ chunk_data_ = false;
+ } else if (0 == len_) {
+ // No more data to read, and no more data to write.
+ do_complete();
+ return;
+ }
+ // Although we are done reading data, there is still data which needs
+ // to be flushed to the network.
+ send_required = true;
+ } else {
+ LOG_F(LS_ERROR) << "Read error: " << error;
+ do_complete(HE_STREAM);
+ return;
+ }
}
}
- len_ = 0;
- // Check for more headers
- if (header_ != data_->end()) {
- queue_headers();
- continue;
+ if (0 == len_) {
+ // No data currently available to send.
+ if (NULL == data_->document.get()) {
+ // If there is no source document, that means we're done.
+ do_complete();
+ }
+ return;
}
- // Check for document data
- if (!data_->document.get())
- break;
-
- size_t offset = 0, reserve = 0;
- if (chunk_data_) {
- // Reserve 10 characters at the start for 8-byte hex value and \r\n
- offset = 10;
- // ... and 2 characters at the end for \r\n
- reserve = offset + 2;
- ASSERT(reserve < sizeof(buffer_));
- }
-
- int error = 0;
- StreamResult result = data_->document->Read(buffer_ + offset,
- sizeof(buffer_) - reserve,
- &len_, &error);
+ size_t written;
+ int error;
+ StreamResult result = http_stream_->Write(buffer_, len_, &written, &error);
if (result == SR_SUCCESS) {
- if (!chunk_data_)
- continue;
-
- // Prepend the length and append \r\n
- sprintfn(buffer_, offset, "%.*x", (offset - 2), len_);
- memcpy(buffer_ + offset - 2, "\r\n", 2);
- memcpy(buffer_ + offset + len_, "\r\n", 2);
- ASSERT(len_ + reserve <= sizeof(buffer_));
- len_ += reserve;
- } else if (result == SR_EOS) {
- if (!chunk_data_)
- break;
-
- // Append the empty chunk and empty trailers, then turn off chunking.
- len_ = sprintfn(buffer_, sizeof(buffer_), "0\r\n\r\n");
- chunk_data_ = false;
+ ASSERT(written <= len_);
+ len_ -= written;
+ memmove(buffer_, buffer_ + written, len_);
+ send_required = false;
+ } else if (result == SR_BLOCK) {
+ if (send_required) {
+ // Nothing more we can do until network is writeable.
+ return;
+ }
} else {
- LOG_F(LS_ERROR) << "Read error: " << error;
- do_complete(HE_STREAM);
+ ASSERT(result == SR_ERROR);
+ LOG_F(LS_ERROR) << "error";
+ OnHttpStreamEvent(http_stream_, SE_CLOSE, error);
return;
}
}
- do_complete();
+ ASSERT(false);
}
-void
+bool
HttpBase::queue_headers() {
+ ASSERT(HM_SEND == mode_);
while (header_ != data_->end()) {
size_t len = sprintfn(buffer_ + len_, sizeof(buffer_) - len_,
"%.*s: %.*s\r\n",
@@ -441,12 +731,13 @@
LOG(WARNING) << "discarding header that is too long: " << header_->first;
++header_;
} else {
- break;
+ // Not enough room for the next header, write to network first.
+ return true;
}
}
- if (header_ == data_->end()) {
- len_ += strcpyn(buffer_ + len_, sizeof(buffer_) - len_, "\r\n");
- }
+ // End of headers
+ len_ += strcpyn(buffer_ + len_, sizeof(buffer_) - len_, "\r\n");
+ return false;
}
void
@@ -454,14 +745,28 @@
ASSERT(mode_ != HM_NONE);
HttpMode mode = mode_;
mode_ = HM_NONE;
+ if (data_ && data_->document.get()) {
+ data_->document->SignalEvent.disconnect(this);
+ }
data_ = NULL;
+ if ((HM_RECV == mode) && doc_stream_) {
+ ASSERT(HE_NONE != err); // We should have Disconnected doc_stream_ already.
+ DocumentStream* ds = doc_stream_;
+ ds->Disconnect(err);
+ ds->SignalEvent(ds, SE_CLOSE, err);
+ }
if (notify_) {
- notify_->onHttpComplete(mode, err);
+ notify_->onHttpComplete(mode, err);
}
}
+//
+// Stream Signals
+//
+
void
-HttpBase::OnEvent(StreamInterface* stream, int events, int error) {
+HttpBase::OnHttpStreamEvent(StreamInterface* stream, int events, int error) {
+ ASSERT(stream == http_stream_);
if ((events & SE_OPEN) && (mode_ == HM_CONNECT)) {
do_complete();
return;
@@ -473,43 +778,10 @@
}
if ((events & SE_READ) && (mode_ == HM_RECV)) {
- // Do to the latency between receiving read notifications from
- // pseudotcpchannel, we rely on repeated calls to read in order to acheive
- // ideal throughput. The number of reads is limited to prevent starving
- // the caller.
- size_t loop_count = 0;
- const size_t kMaxReadCount = 20;
- while (true) {
- if (len_ >= sizeof(buffer_)) {
- do_complete(HE_OVERFLOW);
- return;
- }
- size_t read;
- int error;
- StreamResult result = stream_->Read(buffer_ + len_,
- sizeof(buffer_) - len_,
- &read, &error);
- if ((result == SR_BLOCK) || (result == SR_EOS))
- return;
- if (result == SR_ERROR) {
- OnEvent(stream_, SE_CLOSE, error);
- return;
- }
- ASSERT(result == SR_SUCCESS);
- //LOG(INFO) << "HttpBase << " << std::string(buffer_ + len_, res);
- len_ += read;
- HttpError herr;
- bool more = process(buffer_, len_, read, herr);
- len_ -= read;
- memcpy(buffer_, buffer_ + read, len_);
- if (!more) {
- complete(herr);
- return;
- }
- if (++loop_count > kMaxReadCount) {
- LOG_F(LS_WARNING) << "danger of starvation";
- break;
- }
+ if (doc_stream_) {
+ doc_stream_->SignalEvent(doc_stream_, SE_READ, 0);
+ } else {
+ read_and_process_data();
}
return;
}
@@ -517,27 +789,33 @@
if ((events & SE_CLOSE) == 0)
return;
- if (stream_ != NULL) {
- stream_->Close();
- }
- HttpError herr;
- // TODO: Pass through errors instead of translating them?
- if (error == 0) {
- herr = HE_DISCONNECTED;
- } else if (error == SOCKET_EACCES) {
- herr = HE_AUTH;
- } else if (error == SEC_E_CERT_EXPIRED) {
- herr = HE_CERTIFICATE_EXPIRED;
- } else {
- LOG_F(LS_ERROR) << "SE_CLOSE error: " << error;
- herr = HE_SOCKET;
- }
- if ((mode_ == HM_RECV) && (error == HE_NONE)) {
- end_of_input();
+ HttpError http_error = HandleStreamClose(error);
+ if (mode_ == HM_RECV) {
+ complete(http_error);
} else if (mode_ != HM_NONE) {
- do_complete(mkerr(herr, HE_DISCONNECTED));
+ do_complete(http_error);
} else if (notify_) {
- notify_->onHttpClosed(mkerr(herr, HE_DISCONNECTED));
+ notify_->onHttpClosed(http_error);
+ }
+}
+
+void
+HttpBase::OnDocumentEvent(StreamInterface* stream, int events, int error) {
+ ASSERT(stream == data_->document.get());
+ if ((events & SE_WRITE) && (mode_ == HM_RECV)) {
+ read_and_process_data();
+ return;
+ }
+
+ if ((events & SE_READ) && (mode_ == HM_SEND)) {
+ flush_data();
+ return;
+ }
+
+ if (events & SE_CLOSE) {
+ LOG_F(LS_ERROR) << "Read error: " << error;
+ do_complete(HE_STREAM);
+ return;
}
}
@@ -545,46 +823,71 @@
// HttpParser Implementation
//
-HttpError
-HttpBase::onHttpRecvLeader(const char* line, size_t len) {
- return data_->parseLeader(line, len);
+HttpParser::ProcessResult
+HttpBase::ProcessLeader(const char* line, size_t len, HttpError* error) {
+ *error = data_->parseLeader(line, len);
+ return (HE_NONE == *error) ? PR_CONTINUE : PR_COMPLETE;
}
-HttpError
-HttpBase::onHttpRecvHeader(const char* name, size_t nlen, const char* value,
- size_t vlen) {
+HttpParser::ProcessResult
+HttpBase::ProcessHeader(const char* name, size_t nlen, const char* value,
+ size_t vlen, HttpError* error) {
std::string sname(name, nlen), svalue(value, vlen);
data_->addHeader(sname, svalue);
- //LOG(INFO) << sname << ": " << svalue;
- return HE_NONE;
-}
-
-HttpError
-HttpBase::onHttpRecvHeaderComplete(bool chunked, size_t& data_size) {
- return notify_ ? notify_->onHttpHeaderComplete(chunked, data_size) : HE_NONE;
+ return PR_CONTINUE;
}
-HttpError
-HttpBase::onHttpRecvData(const char* data, size_t len, size_t& read) {
+HttpParser::ProcessResult
+HttpBase::ProcessHeaderComplete(bool chunked, size_t& data_size,
+ HttpError* error) {
+ StreamInterface* old_docstream = doc_stream_;
+ if (notify_) {
+ *error = notify_->onHttpHeaderComplete(chunked, data_size);
+ // The request must not be aborted as a result of this callback.
+ ASSERT(NULL != data_);
+ }
+ if ((HE_NONE == *error) && (NULL != data_->document.get())) {
+ data_->document->SignalEvent.connect(this, &HttpBase::OnDocumentEvent);
+ }
+ if (HE_NONE != *error) {
+ return PR_COMPLETE;
+ }
+ if (old_docstream != doc_stream_) {
+ // Break out of Process loop, since our I/O model just changed.
+ return PR_BLOCK;
+ }
+ return PR_CONTINUE;
+}
+
+HttpParser::ProcessResult
+HttpBase::ProcessData(const char* data, size_t len, size_t& read,
+ HttpError* error) {
+ LOG_F(LS_VERBOSE) << "data: " << std::string(data, len);
if (ignore_data_ || !data_->document.get()) {
read = len;
- return HE_NONE;
+ return PR_CONTINUE;
}
- int error = 0;
- switch (data_->document->Write(data, len, &read, &error)) {
- case SR_SUCCESS:
- return HE_NONE;
- case SR_EOS:
- case SR_BLOCK:
- LOG_F(LS_ERROR) << "Write EOS or block";
- return HE_STREAM;
+ int write_error = 0;
+ switch (data_->document->Write(data, len, &read, &write_error)) {
+ case SR_SUCCESS:
+ return PR_CONTINUE;
+ case SR_BLOCK:
+ return PR_BLOCK;
+ case SR_EOS:
+ LOG_F(LS_ERROR) << "Unexpected EOS";
+ *error = HE_STREAM;
+ return PR_COMPLETE;
+ case SR_ERROR:
+ default:
+ LOG_F(LS_ERROR) << "Write error: " << write_error;
+ *error = HE_STREAM;
+ return PR_COMPLETE;
}
- LOG_F(LS_ERROR) << "Write error: " << error;
- return HE_STREAM;
}
void
-HttpBase::onHttpRecvComplete(HttpError err) {
+HttpBase::OnComplete(HttpError err) {
+ LOG_F(LS_VERBOSE);
do_complete(err);
}
diff --git a/talk/base/httpbase.h b/talk/base/httpbase.h
old mode 100755
new mode 100644
index 64aefe9..97527eb
--- a/talk/base/httpbase.h
+++ b/talk/base/httpbase.h
@@ -25,6 +25,10 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+// Copyright 2005 Google Inc. All Rights Reserved.
+//
+
+
#ifndef TALK_BASE_HTTPBASE_H__
#define TALK_BASE_HTTPBASE_H__
@@ -34,30 +38,41 @@
class StreamInterface;
-//////////////////////////////////////////////////////////////////////
-// HttpParser
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// HttpParser - Parses an HTTP stream provided via Process and end_of_input, and
+// generates events for:
+// Structural Elements: Leader, Headers, Document Data
+// Events: End of Headers, End of Document, Errors
+///////////////////////////////////////////////////////////////////////////////
class HttpParser {
public:
+ enum ProcessResult { PR_CONTINUE, PR_BLOCK, PR_COMPLETE };
HttpParser();
virtual ~HttpParser();
void reset();
- bool process(const char* buffer, size_t len, size_t& read, HttpError& err);
- void end_of_input();
+ ProcessResult Process(const char* buffer, size_t len, size_t* processed,
+ HttpError* error);
+ bool is_valid_end_of_input() const;
void complete(HttpError err);
+ size_t GetDataRemaining() const { return data_size_; }
+
protected:
- bool process_line(const char* line, size_t len, HttpError& err);
+ ProcessResult ProcessLine(const char* line, size_t len, HttpError* error);
// HttpParser Interface
- virtual HttpError onHttpRecvLeader(const char* line, size_t len) = 0;
- virtual HttpError onHttpRecvHeader(const char* name, size_t nlen,
- const char* value, size_t vlen) = 0;
- virtual HttpError onHttpRecvHeaderComplete(bool chunked, size_t& data_size) = 0;
- virtual HttpError onHttpRecvData(const char* data, size_t len, size_t& read) = 0;
- virtual void onHttpRecvComplete(HttpError err) = 0;
+ virtual ProcessResult ProcessLeader(const char* line, size_t len,
+ HttpError* error) = 0;
+ virtual ProcessResult ProcessHeader(const char* name, size_t nlen,
+ const char* value, size_t vlen,
+ HttpError* error) = 0;
+ virtual ProcessResult ProcessHeaderComplete(bool chunked, size_t& data_size,
+ HttpError* error) = 0;
+ virtual ProcessResult ProcessData(const char* data, size_t len, size_t& read,
+ HttpError* error) = 0;
+ virtual void OnComplete(HttpError err) = 0;
private:
enum State {
@@ -69,31 +84,41 @@
size_t data_size_;
};
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// IHttpNotify
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
enum HttpMode { HM_NONE, HM_CONNECT, HM_RECV, HM_SEND };
class IHttpNotify {
public:
+ virtual ~IHttpNotify() {}
virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size) = 0;
virtual void onHttpComplete(HttpMode mode, HttpError err) = 0;
virtual void onHttpClosed(HttpError err) = 0;
};
-//////////////////////////////////////////////////////////////////////
-// HttpBase
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// HttpBase - Provides a state machine for implementing HTTP-based components.
+// Attach HttpBase to a StreamInterface which represents a bidirectional HTTP
+// stream, and then call send() or recv() to initiate sending or receiving one
+// side of an HTTP transaction. By default, HttpBase operates as an I/O pump,
+// moving data from the HTTP stream to the HttpData object and vice versa.
+// However, it can also operate in stream mode, in which case the user of the
+// stream interface drives I/O via calls to Read().
+///////////////////////////////////////////////////////////////////////////////
-class HttpBase : private HttpParser, public sigslot::has_slots<> {
+class HttpBase
+: private HttpParser,
+ public sigslot::has_slots<>
+{
public:
HttpBase();
virtual ~HttpBase();
void notify(IHttpNotify* notify) { notify_ = notify; }
bool attach(StreamInterface* stream);
- StreamInterface* stream() { return stream_; }
+ StreamInterface* stream() { return http_stream_; }
StreamInterface* detach();
bool isConnected() const;
@@ -106,28 +131,62 @@
void set_ignore_data(bool ignore) { ignore_data_ = ignore; }
bool ignore_data() const { return ignore_data_; }
+ // Obtaining this stream puts HttpBase into stream mode until the stream
+ // is closed. HttpBase can only expose one open stream interface at a time.
+ // Further calls will return NULL.
+ StreamInterface* GetDocumentStream();
+
protected:
+ // Do cleanup when the http stream closes (error may be 0 for a clean
+ // shutdown), and return the error code to signal.
+ HttpError HandleStreamClose(int error);
+
+ // DoReceiveLoop acts as a data pump, pulling data from the http stream,
+ // pushing it through the HttpParser, and then populating the HttpData object
+ // based on the callbacks from the parser. One of the most interesting
+ // callbacks is ProcessData, which provides the actual http document body.
+ // This data is then written to the HttpData::document. As a result, data
+ // flows from the network to the document, with some incidental protocol
+ // parsing in between.
+ // Ideally, we would pass in the document* to DoReceiveLoop, to more easily
+ // support GetDocumentStream(). However, since the HttpParser is callback
+ // driven, we are forced to store the pointer somewhere until the callback
+ // is triggered.
+ // Returns true if the received document has finished, and
+ // HttpParser::complete should be called.
+ bool DoReceiveLoop(HttpError* err);
+
+ void read_and_process_data();
void flush_data();
- void queue_headers();
+ bool queue_headers();
void do_complete(HttpError err = HE_NONE);
- void OnEvent(StreamInterface* stream, int events, int error);
-
+ void OnHttpStreamEvent(StreamInterface* stream, int events, int error);
+ void OnDocumentEvent(StreamInterface* stream, int events, int error);
+
// HttpParser Interface
- virtual HttpError onHttpRecvLeader(const char* line, size_t len);
- virtual HttpError onHttpRecvHeader(const char* name, size_t nlen,
- const char* value, size_t vlen);
- virtual HttpError onHttpRecvHeaderComplete(bool chunked, size_t& data_size);
- virtual HttpError onHttpRecvData(const char* data, size_t len, size_t& read);
- virtual void onHttpRecvComplete(HttpError err);
+ virtual ProcessResult ProcessLeader(const char* line, size_t len,
+ HttpError* error);
+ virtual ProcessResult ProcessHeader(const char* name, size_t nlen,
+ const char* value, size_t vlen,
+ HttpError* error);
+ virtual ProcessResult ProcessHeaderComplete(bool chunked, size_t& data_size,
+ HttpError* error);
+ virtual ProcessResult ProcessData(const char* data, size_t len, size_t& read,
+ HttpError* error);
+ virtual void OnComplete(HttpError err);
private:
+ class DocumentStream;
+ friend class DocumentStream;
+
enum { kBufferSize = 32 * 1024 };
HttpMode mode_;
HttpData* data_;
IHttpNotify* notify_;
- StreamInterface* stream_;
+ StreamInterface* http_stream_;
+ DocumentStream* doc_stream_;
char buffer_[kBufferSize];
size_t len_;
@@ -135,7 +194,7 @@
HttpData::const_iterator header_;
};
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
} // namespace talk_base
diff --git a/talk/base/httpclient.cc b/talk/base/httpclient.cc
old mode 100755
new mode 100644
index 49c5070..3b6e97e
--- a/talk/base/httpclient.cc
+++ b/talk/base/httpclient.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -38,7 +38,7 @@
#include "talk/base/socketstream.h"
#include "talk/base/stringencode.h"
#include "talk/base/stringutils.h"
-#include "talk/base/basicdefs.h"
+#include "talk/base/thread.h"
namespace talk_base {
@@ -51,11 +51,6 @@
const size_t kCacheHeader = 0;
const size_t kCacheBody = 1;
-std::string HttpAddress(const SocketAddress& address) {
- return (address.port() == HTTP_DEFAULT_PORT)
- ? address.hostname() : address.ToString();
-}
-
// Convert decimal string to integer
bool HttpStringToInt(const std::string& str, unsigned long* val) {
ASSERT(NULL != val);
@@ -64,16 +59,15 @@
return (*eos == '\0');
}
-bool HttpShouldCache(const HttpRequestData& request,
- const HttpResponseData& response) {
- bool verb_allows_cache = (request.verb == HV_GET)
- || (request.verb == HV_HEAD);
- bool is_range_response = response.hasHeader(HH_CONTENT_RANGE, NULL);
- bool has_expires = response.hasHeader(HH_EXPIRES, NULL);
+bool HttpShouldCache(const HttpTransaction& t) {
+ bool verb_allows_cache = (t.request.verb == HV_GET)
+ || (t.request.verb == HV_HEAD);
+ bool is_range_response = t.response.hasHeader(HH_CONTENT_RANGE, NULL);
+ bool has_expires = t.response.hasHeader(HH_EXPIRES, NULL);
bool request_allows_cache =
- has_expires || (std::string::npos != request.path.find('?'));
+ has_expires || (std::string::npos != t.request.path.find('?'));
bool response_allows_cache =
- has_expires || HttpCodeIsCacheable(response.scode);
+ has_expires || HttpCodeIsCacheable(t.response.scode);
bool may_cache = verb_allows_cache
&& request_allows_cache
@@ -81,7 +75,7 @@
&& !is_range_response;
std::string value;
- if (response.hasHeader(HH_CACHE_CONTROL, &value)) {
+ if (t.response.hasHeader(HH_CACHE_CONTROL, &value)) {
HttpAttributeList directives;
HttpParseAttributes(value.data(), value.size(), directives);
// Response Directives Summary:
@@ -108,8 +102,7 @@
HCS_NONE // Not in cache
};
-HttpCacheState HttpGetCacheState(const HttpRequestData& request,
- const HttpResponseData& response) {
+HttpCacheState HttpGetCacheState(const HttpTransaction& t) {
// Temporaries
std::string s_temp;
unsigned long i_temp;
@@ -118,13 +111,13 @@
unsigned long now = time(0);
HttpAttributeList cache_control;
- if (response.hasHeader(HH_CACHE_CONTROL, &s_temp)) {
+ if (t.response.hasHeader(HH_CACHE_CONTROL, &s_temp)) {
HttpParseAttributes(s_temp.data(), s_temp.size(), cache_control);
}
// Compute age of cache document
unsigned long date;
- if (!response.hasHeader(HH_DATE, &s_temp)
+ if (!t.response.hasHeader(HH_DATE, &s_temp)
|| !HttpDateToSeconds(s_temp, &date))
return HCS_NONE;
@@ -138,7 +131,7 @@
}
unsigned long corrected_received_age = apparent_age;
- if (response.hasHeader(HH_AGE, &s_temp)
+ if (t.response.hasHeader(HH_AGE, &s_temp)
&& HttpStringToInt(s_temp, &i_temp)) {
corrected_received_age = stdmax(apparent_age, i_temp);
}
@@ -152,10 +145,10 @@
unsigned long lifetime;
if (HttpHasAttribute(cache_control, "max-age", &s_temp)) {
lifetime = atoi(s_temp.c_str());
- } else if (response.hasHeader(HH_EXPIRES, &s_temp)
+ } else if (t.response.hasHeader(HH_EXPIRES, &s_temp)
&& HttpDateToSeconds(s_temp, &i_temp)) {
lifetime = i_temp - date;
- } else if (response.hasHeader(HH_LAST_MODIFIED, &s_temp)
+ } else if (t.response.hasHeader(HH_LAST_MODIFIED, &s_temp)
&& HttpDateToSeconds(s_temp, &i_temp)) {
// TODO: Issue warning 113 if age > 24 hours
lifetime = (now - i_temp) / 10;
@@ -188,7 +181,7 @@
}
if (response.hasHeader(HH_LAST_MODIFIED, &value)) {
unsigned long last_modified, date;
- if (HttpDateToSeconds(value, &last_modified)
+ if (HttpDateToSeconds(value, &last_modified)
&& response.hasHeader(HH_DATE, &value)
&& HttpDateToSeconds(value, &date)
&& (last_modified + 60 < date)) {
@@ -199,46 +192,121 @@
return HVS_NONE;
}
-std::string GetCacheID(const SocketAddress& server,
- const HttpRequestData& request) {
- std::string url;
- url.append(ToString(request.verb));
- url.append("_");
- if ((_strnicmp(request.path.c_str(), "http://", 7) == 0)
- || (_strnicmp(request.path.c_str(), "https://", 8) == 0)) {
- url.append(request.path);
- } else {
- url.append("http://");
- url.append(HttpAddress(server));
- url.append(request.path);
- }
- return url;
+std::string GetCacheID(const HttpRequestData& request) {
+ std::string id, url;
+ id.append(ToString(request.verb));
+ id.append("_");
+ request.getAbsoluteUri(&url);
+ id.append(url);
+ return id;
}
} // anonymous namespace
//////////////////////////////////////////////////////////////////////
+// Public Helpers
+//////////////////////////////////////////////////////////////////////
+
+bool HttpWriteCacheHeaders(const HttpResponseData* response,
+ StreamInterface* output, size_t* size) {
+ size_t length = 0;
+ // Write all unknown and end-to-end headers to a cache file
+ for (HttpData::const_iterator it = response->begin();
+ it != response->end(); ++it) {
+ HttpHeader header;
+ if (FromString(header, it->first) && !HttpHeaderIsEndToEnd(header))
+ continue;
+ length += it->first.length() + 2 + it->second.length() + 2;
+ if (!output)
+ continue;
+ std::string formatted_header(it->first);
+ formatted_header.append(": ");
+ formatted_header.append(it->second);
+ formatted_header.append("\r\n");
+ StreamResult result = output->WriteAll(formatted_header.data(),
+ formatted_header.length(),
+ NULL, NULL);
+ if (SR_SUCCESS != result) {
+ return false;
+ }
+ }
+ if (output && (SR_SUCCESS != output->WriteAll("\r\n", 2, NULL, NULL))) {
+ return false;
+ }
+ length += 2;
+ if (size)
+ *size = length;
+ return true;
+}
+
+bool HttpReadCacheHeaders(StreamInterface* input, HttpResponseData* response,
+ HttpData::HeaderCombine combine) {
+ while (true) {
+ std::string formatted_header;
+ StreamResult result = input->ReadLine(&formatted_header);
+ if ((SR_EOS == result) || (1 == formatted_header.size())) {
+ break;
+ }
+ if (SR_SUCCESS != result) {
+ return false;
+ }
+ size_t end_of_name = formatted_header.find(':');
+ if (std::string::npos == end_of_name) {
+ LOG_F(LS_WARNING) << "Malformed cache header";
+ continue;
+ }
+ size_t start_of_value = end_of_name + 1;
+ size_t end_of_value = formatted_header.length();
+ while ((start_of_value < end_of_value)
+ && isspace(formatted_header[start_of_value]))
+ ++start_of_value;
+ while ((start_of_value < end_of_value)
+ && isspace(formatted_header[end_of_value-1]))
+ --end_of_value;
+ size_t value_length = end_of_value - start_of_value;
+
+ std::string name(formatted_header.substr(0, end_of_name));
+ std::string value(formatted_header.substr(start_of_value, value_length));
+ response->changeHeader(name, value, combine);
+ }
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////
// HttpClient
//////////////////////////////////////////////////////////////////////
-HttpClient::HttpClient(const std::string& agent, StreamPool* pool)
-: agent_(agent), pool_(pool), fail_redirect_(false), absolute_uri_(false),
- cache_(NULL), cache_state_(CS_READY)
-{
+const size_t kDefaultRetries = 1;
+const size_t kMaxRedirects = 5;
+
+HttpClient::HttpClient(const std::string& agent, StreamPool* pool,
+ HttpTransaction* transaction)
+ : agent_(agent), pool_(pool),
+ transaction_(transaction), free_transaction_(false),
+ retries_(kDefaultRetries), attempt_(0), redirects_(0),
+ redirect_action_(REDIRECT_DEFAULT),
+ uri_form_(URI_DEFAULT), cache_(NULL), cache_state_(CS_READY) {
base_.notify(this);
+ if (NULL == transaction_) {
+ free_transaction_ = true;
+ transaction_ = new HttpTransaction;
+ }
}
HttpClient::~HttpClient() {
base_.notify(NULL);
base_.abort(HE_SHUTDOWN);
release();
+ if (free_transaction_)
+ delete transaction_;
}
void HttpClient::reset() {
server_.Clear();
- request_.clear(true);
- response_.clear(true);
+ request().clear(true);
+ response().clear(true);
context_.reset();
+ redirects_ = 0;
base_.abort(HE_OPERATION_CANCELLED);
}
@@ -246,7 +314,11 @@
server_ = address;
// Setting 'Host' here allows it to be overridden before starting the request,
// if necessary.
- request_.setHeader(HH_HOST, HttpAddress(server_), true);
+ request().setHeader(HH_HOST, HttpAddress(server_, false), true);
+}
+
+StreamInterface* HttpClient::GetDocumentStream() {
+ return base_.GetDocumentStream();
}
void HttpClient::start() {
@@ -258,51 +330,69 @@
ASSERT(!IsCacheActive());
- if (request_.hasHeader(HH_TRANSFER_ENCODING, NULL)) {
+ if (request().hasHeader(HH_TRANSFER_ENCODING, NULL)) {
// Exact size must be known on the client. Instead of using chunked
// encoding, wrap data with auto-caching file or memory stream.
ASSERT(false);
return;
}
+ attempt_ = 0;
+
// If no content has been specified, using length of 0.
- request_.setHeader(HH_CONTENT_LENGTH, "0", false);
+ request().setHeader(HH_CONTENT_LENGTH, "0", false);
- request_.setHeader(HH_USER_AGENT, agent_, false);
- request_.setHeader(HH_CONNECTION, "Keep-Alive", false);
- if (_strnicmp(request_.path.c_str(), "http", 4) == 0) {
- request_.setHeader(HH_PROXY_CONNECTION, "Keep-Alive", false);
+ if (!agent_.empty()) {
+ request().setHeader(HH_USER_AGENT, agent_, false);
}
- bool absolute_uri = absolute_uri_;
+ UriForm uri_form = uri_form_;
if (PROXY_HTTPS == proxy_.type) {
+ // Proxies require absolute form
+ uri_form = URI_ABSOLUTE;
request().version = HVER_1_0;
- // Proxies require canonical form
- absolute_uri = true;
+ request().setHeader(HH_PROXY_CONNECTION, "Keep-Alive", false);
+ } else {
+ request().setHeader(HH_CONNECTION, "Keep-Alive", false);
}
- // Convert to canonical form (if not already)
- if (absolute_uri && (_strnicmp(request().path.c_str(), "http://", 7) != 0)) {
- std::string canonical_path("http://");
- canonical_path.append(HttpAddress(server_));
- canonical_path.append(request().path);
- request().path = canonical_path;
+ if (URI_ABSOLUTE == uri_form) {
+ // Convert to absolute uri form
+ std::string url;
+ if (request().getAbsoluteUri(&url)) {
+ request().path = url;
+ } else {
+ LOG(LS_WARNING) << "Couldn't obtain absolute uri";
+ }
+ } else if (URI_RELATIVE == uri_form) {
+ // Convert to relative uri form
+ std::string host, path;
+ if (request().getRelativeUri(&host, &path)) {
+ request().setHeader(HH_HOST, host);
+ request().path = path;
+ } else {
+ LOG(LS_WARNING) << "Couldn't obtain relative uri";
+ }
}
if ((NULL != cache_) && CheckCache()) {
return;
}
+ connect();
+}
+
+void HttpClient::connect() {
int stream_err;
StreamInterface* stream = pool_->RequestConnectedStream(server_, &stream_err);
if (stream == NULL) {
- if (stream_err)
- LOG(LS_ERROR) << "RequestConnectedStream returned: " << stream_err;
- onHttpComplete(HM_CONNECT, (stream_err == 0) ? HE_NONE : HE_SOCKET);
+ ASSERT(0 != stream_err);
+ LOG(LS_ERROR) << "RequestConnectedStream error: " << stream_err;
+ onHttpComplete(HM_CONNECT, HE_CONNECT_FAILED);
} else {
base_.attach(stream);
if (stream->GetState() == SS_OPEN) {
- base_.send(&request_);
+ base_.send(&transaction_->request);
}
}
}
@@ -310,7 +400,7 @@
void HttpClient::prepare_get(const std::string& url) {
reset();
Url<char> purl(url);
- set_server(SocketAddress(purl.server(), purl.port(), false));
+ set_server(SocketAddress(purl.host(), purl.port()));
request().verb = HV_GET;
request().path = purl.full_path();
}
@@ -320,7 +410,7 @@
StreamInterface* request_doc) {
reset();
Url<char> purl(url);
- set_server(SocketAddress(purl.server(), purl.port(), false));
+ set_server(SocketAddress(purl.host(), purl.port()));
request().verb = HV_POST;
request().path = purl.full_path();
request().setContent(content_type, request_doc);
@@ -332,11 +422,24 @@
}
}
+bool HttpClient::ShouldRedirect(std::string* location) const {
+ // TODO: Unittest redirection.
+ if ((REDIRECT_NEVER == redirect_action_)
+ || !HttpCodeIsRedirection(response().scode)
+ || !response().hasHeader(HH_LOCATION, location)
+ || (redirects_ >= kMaxRedirects))
+ return false;
+ return (REDIRECT_ALWAYS == redirect_action_)
+ || (HC_SEE_OTHER == response().scode)
+ || (HV_HEAD == request().verb)
+ || (HV_GET == request().verb);
+}
+
bool HttpClient::BeginCacheFile() {
ASSERT(NULL != cache_);
ASSERT(CS_READY == cache_state_);
- std::string id = GetCacheID(server_, request_);
+ std::string id = GetCacheID(request());
CacheLock lock(cache_, id, true);
if (!lock.IsLocked()) {
LOG_F(LS_WARNING) << "Couldn't lock cache";
@@ -356,12 +459,12 @@
// Let's secretly replace the response document with Folgers Crystals,
// er, StreamTap, so that we can mirror the data to our cache.
- StreamInterface* output = response_.document.release();
+ StreamInterface* output = response().document.release();
if (!output) {
output = new NullStream;
}
StreamTap* tap = new StreamTap(output, stream.release());
- response_.document.reset(tap);
+ response().document.reset(tap);
return true;
}
@@ -372,23 +475,9 @@
return HE_CACHE;
}
- // Write all unknown and end-to-end headers to a cache file
- for (HttpData::const_iterator it = response_.begin();
- it != response_.end(); ++it) {
- HttpHeader header;
- if (FromString(header, it->first) && !HttpHeaderIsEndToEnd(header))
- continue;
- std::string formatted_header(it->first);
- formatted_header.append(": ");
- formatted_header.append(it->second);
- formatted_header.append("\r\n");
- StreamResult result = stream->WriteAll(formatted_header.data(),
- formatted_header.length(),
- NULL, NULL);
- if (SR_SUCCESS != result) {
- LOG_F(LS_ERROR) << "Couldn't write header cache";
- return HE_CACHE;
- }
+ if (!HttpWriteCacheHeaders(&transaction_->response, stream.get(), NULL)) {
+ LOG_F(LS_ERROR) << "Couldn't write header cache";
+ return HE_CACHE;
}
return HE_NONE;
@@ -396,8 +485,8 @@
void HttpClient::CompleteCacheFile() {
// Restore previous response document
- StreamTap* tap = static_cast<StreamTap*>(response_.document.release());
- response_.document.reset(tap->Detach());
+ StreamTap* tap = static_cast<StreamTap*>(response().document.release());
+ response().document.reset(tap->Detach());
int error;
StreamResult result = tap->GetTapResult(&error);
@@ -407,7 +496,7 @@
if (SR_SUCCESS != result) {
LOG(LS_ERROR) << "Cache file error: " << error;
- cache_->DeleteResource(GetCacheID(server_, request_));
+ cache_->DeleteResource(GetCacheID(request()));
}
}
@@ -415,7 +504,7 @@
ASSERT(NULL != cache_);
ASSERT(CS_READY == cache_state_);
- std::string id = GetCacheID(server_, request_);
+ std::string id = GetCacheID(request());
if (!cache_->HasResource(id)) {
// No cache file available
return false;
@@ -424,7 +513,7 @@
HttpError error = ReadCacheHeaders(id, true);
if (HE_NONE == error) {
- switch (HttpGetCacheState(request_, response_)) {
+ switch (HttpGetCacheState(*transaction_)) {
case HCS_FRESH:
// Cache content is good, read from cache
break;
@@ -436,7 +525,7 @@
// Couldn't validate, fall through.
case HCS_NONE:
// Cache content is not useable. Issue a regular request.
- response_.clear(false);
+ response().clear(false);
return false;
}
}
@@ -448,7 +537,7 @@
if (HE_CACHE == error) {
LOG_F(LS_WARNING) << "Cache failure, continuing with normal request";
- response_.clear(false);
+ response().clear(false);
return false;
}
@@ -465,37 +554,12 @@
HttpData::HeaderCombine combine =
override ? HttpData::HC_REPLACE : HttpData::HC_AUTO;
- while (true) {
- std::string formatted_header;
- StreamResult result = stream->ReadLine(&formatted_header);
- if (SR_EOS == result)
- break;
-
- if (SR_SUCCESS != result) {
- LOG_F(LS_ERROR) << "ReadLine error in cache headers";
- return HE_CACHE;
- }
- size_t end_of_name = formatted_header.find(':');
- if (std::string::npos == end_of_name) {
- LOG_F(LS_WARNING) << "Malformed cache header";
- continue;
- }
- size_t start_of_value = end_of_name + 1;
- size_t end_of_value = formatted_header.length();
- while ((start_of_value < end_of_value)
- && isspace(formatted_header[start_of_value]))
- ++start_of_value;
- while ((start_of_value < end_of_value)
- && isspace(formatted_header[end_of_value-1]))
- --end_of_value;
- size_t value_length = end_of_value - start_of_value;
-
- std::string name(formatted_header.substr(0, end_of_name));
- std::string value(formatted_header.substr(start_of_value, value_length));
- response_.changeHeader(name, value, combine);
+ if (!HttpReadCacheHeaders(stream.get(), &transaction_->response, combine)) {
+ LOG_F(LS_ERROR) << "Error reading cache headers";
+ return HE_CACHE;
}
- response_.scode = HC_OK;
+ response().scode = HC_OK;
return HE_NONE;
}
@@ -506,7 +570,7 @@
size_t data_size;
scoped_ptr<StreamInterface> stream(cache_->ReadResource(id, kCacheBody));
- if (!stream.get() || !stream->GetSize(&data_size)) {
+ if (!stream.get() || !stream->GetAvailable(&data_size)) {
LOG_F(LS_ERROR) << "Unavailable cache body";
error = HE_CACHE;
} else {
@@ -514,11 +578,11 @@
}
if ((HE_NONE == error)
- && (HV_HEAD != request_.verb)
- && (NULL != response_.document.get())) {
+ && (HV_HEAD != request().verb)
+ && (NULL != response().document.get())) {
char buffer[1024 * 64];
StreamResult result = Flow(stream.get(), buffer, ARRAY_SIZE(buffer),
- response_.document.get());
+ response().document.get());
if (SR_SUCCESS != result) {
error = HE_STREAM;
}
@@ -529,22 +593,22 @@
bool HttpClient::PrepareValidate() {
ASSERT(CS_READY == cache_state_);
- // At this point, request_ contains the pending request, and response_
+ // At this point, request() contains the pending request, and response()
// contains the cached response headers. Reformat the request to validate
// the cached content.
- HttpValidatorStrength vs_required = HttpRequestValidatorLevel(request_);
- HttpValidatorStrength vs_available = HttpResponseValidatorLevel(response_);
+ HttpValidatorStrength vs_required = HttpRequestValidatorLevel(request());
+ HttpValidatorStrength vs_available = HttpResponseValidatorLevel(response());
if (vs_available < vs_required) {
return false;
}
std::string value;
- if (response_.hasHeader(HH_ETAG, &value)) {
- request_.addHeader(HH_IF_NONE_MATCH, value);
+ if (response().hasHeader(HH_ETAG, &value)) {
+ request().addHeader(HH_IF_NONE_MATCH, value);
}
- if (response_.hasHeader(HH_LAST_MODIFIED, &value)) {
- request_.addHeader(HH_IF_MODIFIED_SINCE, value);
+ if (response().hasHeader(HH_LAST_MODIFIED, &value)) {
+ request().addHeader(HH_IF_MODIFIED_SINCE, value);
}
- response_.clear(false);
+ response().clear(false);
cache_state_ = CS_VALIDATING;
return true;
}
@@ -552,7 +616,7 @@
HttpError HttpClient::CompleteValidate() {
ASSERT(CS_VALIDATING == cache_state_);
- std::string id = GetCacheID(server_, request_);
+ std::string id = GetCacheID(request());
// Merge cached headers with new headers
HttpError error = ReadCacheHeaders(id, false);
@@ -569,13 +633,18 @@
HttpError HttpClient::OnHeaderAvailable(bool ignore_data, bool chunked,
size_t data_size) {
- if (!ignore_data && !chunked && response_.document.get()) {
+ // If we are ignoring the data, this is an intermediate header.
+ // TODO: don't signal intermediate headers. Instead, do all header-dependent
+ // processing now, and either set up the next request, or fail outright.
+ // TODO: by default, only write response documents with a success code.
+ SignalHeaderAvailable(this, !ignore_data, ignore_data ? 0 : data_size);
+ if (!ignore_data && !chunked && (data_size != SIZE_UNKNOWN)
+ && response().document.get()) {
// Attempt to pre-allocate space for the downloaded data.
- if (!response_.document->ReserveSize(data_size)) {
+ if (!response().document->ReserveSize(data_size)) {
return HE_OVERFLOW;
}
}
- SignalHeaderAvailable(this, chunked, data_size);
return HE_NONE;
}
@@ -585,22 +654,22 @@
HttpError HttpClient::onHttpHeaderComplete(bool chunked, size_t& data_size) {
if (CS_VALIDATING == cache_state_) {
- if (HC_NOT_MODIFIED == response_.scode) {
+ if (HC_NOT_MODIFIED == response().scode) {
return CompleteValidate();
}
// Should we remove conditional headers from request?
cache_state_ = CS_READY;
- cache_->DeleteResource(GetCacheID(server_, request_));
+ cache_->DeleteResource(GetCacheID(request()));
// Continue processing response as normal
}
ASSERT(!IsCacheActive());
- if ((request_.verb == HV_HEAD) || !HttpCodeHasBody(response_.scode)) {
+ if ((request().verb == HV_HEAD) || !HttpCodeHasBody(response().scode)) {
// HEAD requests and certain response codes contain no body
data_size = 0;
}
- if ((HttpCodeIsRedirection(response_.scode) && !fail_redirect_)
- || ((HC_PROXY_AUTHENTICATION_REQUIRED == response_.scode)
+ if (ShouldRedirect(NULL)
+ || ((HC_PROXY_AUTHENTICATION_REQUIRED == response().scode)
&& (PROXY_HTTPS == proxy_.type))) {
// We're going to issue another request, so ignore the incoming data.
base_.set_ignore_data(true);
@@ -613,7 +682,7 @@
if ((NULL != cache_)
&& !base_.ignore_data()
- && HttpShouldCache(request_, response_)) {
+ && HttpShouldCache(*transaction_)) {
if (BeginCacheFile()) {
cache_state_ = CS_WRITING;
}
@@ -622,65 +691,81 @@
}
void HttpClient::onHttpComplete(HttpMode mode, HttpError err) {
- if (err != HE_NONE) {
+ if (((HE_DISCONNECTED == err) || (HE_CONNECT_FAILED == err)
+ || (HE_SOCKET_ERROR == err))
+ && (HC_INTERNAL_SERVER_ERROR == response().scode)
+ && (attempt_ < retries_)) {
+ // If the response code has not changed from the default, then we haven't
+ // received anything meaningful from the server, so we are eligible for a
+ // retry.
+ ++attempt_;
+ if (request().document.get() && !request().document->Rewind()) {
+ // Unable to replay the request document.
+ err = HE_STREAM;
+ } else {
+ release();
+ connect();
+ return;
+ }
+ } else if (err != HE_NONE) {
// fall through
} else if (mode == HM_CONNECT) {
- base_.send(&request_);
+ base_.send(&transaction_->request);
return;
- } else if ((mode == HM_SEND) || HttpCodeIsInformational(response_.scode)) {
+ } else if ((mode == HM_SEND) || HttpCodeIsInformational(response().scode)) {
// If you're interested in informational headers, catch
// SignalHeaderAvailable.
- base_.recv(&response_);
+ base_.recv(&transaction_->response);
return;
} else {
- if (!HttpShouldKeepAlive(response_)) {
- LOG(INFO) << "HttpClient: closing socket";
+ if (!HttpShouldKeepAlive(response())) {
+ LOG(LS_VERBOSE) << "HttpClient: closing socket";
base_.stream()->Close();
}
- if (HttpCodeIsRedirection(response_.scode) && !fail_redirect_) {
- std::string value;
- if (!response_.hasHeader(HH_LOCATION, &value)) {
- err = HE_PROTOCOL;
- } else {
- Url<char> purl(value);
- set_server(SocketAddress(purl.server(), purl.port(), false));
- request_.path = purl.full_path();
- if (response_.scode == HC_SEE_OTHER) {
- request_.verb = HV_GET;
- request_.clearHeader(HH_CONTENT_TYPE);
- request_.clearHeader(HH_CONTENT_LENGTH);
- request_.document.reset();
- } else if (request_.document.get() && !request_.document->Rewind()) {
- // Unable to replay the request document.
- err = HE_STREAM;
- }
+ std::string location;
+ if (ShouldRedirect(&location)) {
+ Url<char> purl(location);
+ set_server(SocketAddress(purl.host(), purl.port()));
+ request().path = purl.full_path();
+ if (response().scode == HC_SEE_OTHER) {
+ request().verb = HV_GET;
+ request().clearHeader(HH_CONTENT_TYPE);
+ request().clearHeader(HH_CONTENT_LENGTH);
+ request().document.reset();
+ } else if (request().document.get() && !request().document->Rewind()) {
+ // Unable to replay the request document.
+ ASSERT(REDIRECT_ALWAYS == redirect_action_);
+ err = HE_STREAM;
}
if (err == HE_NONE) {
+ ++redirects_;
context_.reset();
- response_.clear(false);
+ response().clear(false);
release();
start();
return;
}
- } else if ((HC_PROXY_AUTHENTICATION_REQUIRED == response_.scode)
+ } else if ((HC_PROXY_AUTHENTICATION_REQUIRED == response().scode)
&& (PROXY_HTTPS == proxy_.type)) {
- std::string response, auth_method;
- HttpData::const_iterator begin = response_.begin(HH_PROXY_AUTHENTICATE);
- HttpData::const_iterator end = response_.end(HH_PROXY_AUTHENTICATE);
+ std::string authorization, auth_method;
+ HttpData::const_iterator begin = response().begin(HH_PROXY_AUTHENTICATE);
+ HttpData::const_iterator end = response().end(HH_PROXY_AUTHENTICATE);
for (HttpData::const_iterator it = begin; it != end; ++it) {
+ HttpAuthContext *context = context_.get();
HttpAuthResult res = HttpAuthenticate(
it->second.data(), it->second.size(),
proxy_.address,
- ToString(request_.verb), request_.path,
+ ToString(request().verb), request().path,
proxy_.username, proxy_.password,
- *context_.use(), response, auth_method);
+ context, authorization, auth_method);
+ context_.reset(context);
if (res == HAR_RESPONSE) {
- request_.setHeader(HH_PROXY_AUTHORIZATION, response);
- if (request_.document.get() && !request_.document->Rewind()) {
+ request().setHeader(HH_PROXY_AUTHORIZATION, authorization);
+ if (request().document.get() && !request().document->Rewind()) {
err = HE_STREAM;
} else {
// Explicitly do not reset the HttpAuthContext
- response_.clear(false);
+ response().clear(false);
// TODO: Reuse socket when authenticating?
release();
start();
@@ -706,9 +791,23 @@
}
void HttpClient::onHttpClosed(HttpError err) {
- SignalHttpClientClosed(this, err);
+ // This shouldn't occur, since we return the stream to the pool upon command
+ // completion.
+ ASSERT(false);
+}
+
+//////////////////////////////////////////////////////////////////////
+// HttpClientDefault
+//////////////////////////////////////////////////////////////////////
+
+HttpClientDefault::HttpClientDefault(SocketFactory* factory,
+ const std::string& agent,
+ HttpTransaction* transaction)
+ : ReuseSocketPool(factory ? factory : Thread::Current()->socketserver()),
+ HttpClient(agent, NULL, transaction) {
+ set_pool(this);
}
//////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/httpclient.h b/talk/base/httpclient.h
old mode 100755
new mode 100644
index 789cb59..b64e55f
--- a/talk/base/httpclient.h
+++ b/talk/base/httpclient.h
@@ -39,30 +39,74 @@
namespace talk_base {
//////////////////////////////////////////////////////////////////////
+// Client-specific http utilities
+//////////////////////////////////////////////////////////////////////
+
+// Write cache-relevant response headers to output stream. If size is non-null,
+// it contains the length of the output in bytes. output may be null if only
+// the length is desired.
+bool HttpWriteCacheHeaders(const HttpResponseData* response,
+ StreamInterface* output, size_t* size);
+// Read cached headers from a stream, and them merge them into the response
+// object using the specified combine operation.
+bool HttpReadCacheHeaders(StreamInterface* input,
+ HttpResponseData* response,
+ HttpData::HeaderCombine combine);
+
+//////////////////////////////////////////////////////////////////////
// HttpClient
+// Implements an HTTP 1.1 client.
//////////////////////////////////////////////////////////////////////
class DiskCache;
class HttpClient;
class IPNetPool;
+// What to do: Define STRICT_HTTP_ERROR=1 in your makefile. Use HttpError in
+// your code (HttpErrorType should only be used for code that is shared
+// with groups which have not yet migrated).
+#if STRICT_HTTP_ERROR
+typedef HttpError HttpErrorType;
+#else // !STRICT_HTTP_ERROR
+typedef int HttpErrorType;
+#endif // !STRICT_HTTP_ERROR
+
class HttpClient : private IHttpNotify {
public:
- HttpClient(const std::string& agent, StreamPool* pool);
+ // If HttpRequestData and HttpResponseData objects are provided, they must
+ // be freed by the caller. Otherwise, an internal object is allocated.
+ HttpClient(const std::string& agent, StreamPool* pool,
+ HttpTransaction* transaction = NULL);
virtual ~HttpClient();
void set_pool(StreamPool* pool) { pool_ = pool; }
+ void set_agent(const std::string& agent) { agent_ = agent; }
const std::string& agent() const { return agent_; }
void set_proxy(const ProxyInfo& proxy) { proxy_ = proxy; }
const ProxyInfo& proxy() const { return proxy_; }
- void set_fail_redirect(bool fail_redirect) { fail_redirect_ = fail_redirect; }
- bool fail_redirect() const { return fail_redirect_; }
+ // Request retries occur when the connection closes before the beginning of
+ // an http response is received. In these cases, the http server may have
+ // timed out the keepalive connection before it received our request. Note
+ // that if a request document cannot be rewound, no retry is made. The
+ // default is 1.
+ void set_request_retries(size_t retries) { retries_ = retries; }
+ size_t request_retries() const { return retries_; }
- void use_absolute_uri(bool absolute_uri) { absolute_uri_ = absolute_uri; }
- bool absolute_uri() const { return absolute_uri_; }
+ enum RedirectAction { REDIRECT_DEFAULT, REDIRECT_ALWAYS, REDIRECT_NEVER };
+ void set_redirect_action(RedirectAction action) { redirect_action_ = action; }
+ RedirectAction redirect_action() const { return redirect_action_; }
+ // Deprecated
+ void set_fail_redirect(bool fail_redirect) {
+ redirect_action_ = REDIRECT_NEVER;
+ }
+ bool fail_redirect() const { return (REDIRECT_NEVER == redirect_action_); }
+
+ enum UriForm { URI_DEFAULT, URI_ABSOLUTE, URI_RELATIVE };
+ void set_uri_form(UriForm form) { uri_form_ = form; }
+ UriForm uri_form() const { return uri_form_; }
void set_cache(DiskCache* cache) { ASSERT(!IsCacheActive()); cache_ = cache; }
bool cache_enabled() const { return (NULL != cache_); }
@@ -74,32 +118,47 @@
void set_server(const SocketAddress& address);
const SocketAddress& server() const { return server_; }
- HttpRequestData& request() { return request_; }
- const HttpRequestData& request() const { return request_; }
- HttpResponseData& response() { return response_; }
- const HttpResponseData& response() const { return response_; }
+ // Note: in order for HttpClient to retry a POST in response to
+ // an authentication challenge, a redirect response, or socket disconnection,
+ // the request document must support 'replaying' by calling Rewind() on it.
+ // In the case where just a subset of a stream should be used as the request
+ // document, the stream may be wrapped with the StreamSegment adapter.
+ HttpTransaction* transaction() { return transaction_; }
+ const HttpTransaction* transaction() const { return transaction_; }
+ HttpRequestData& request() { return transaction_->request; }
+ const HttpRequestData& request() const { return transaction_->request; }
+ HttpResponseData& response() { return transaction_->response; }
+ const HttpResponseData& response() const { return transaction_->response; }
// convenience methods
void prepare_get(const std::string& url);
void prepare_post(const std::string& url, const std::string& content_type,
StreamInterface* request_doc);
+ // Convert HttpClient to a pull-based I/O model.
+ StreamInterface* GetDocumentStream();
+
// After you finish setting up your request, call start.
void start();
// Signalled when the header has finished downloading, before the document
- // content is processed. This notification is for informational purposes
- // only. Do not modify the client in response to this.
- sigslot::signal3<const HttpClient*,bool,size_t> SignalHeaderAvailable;
- // Signalled when the current 'call' finishes. On success, err is 0.
- sigslot::signal2<HttpClient*,int> SignalHttpClientComplete;
- // Signalled when the network connection goes down while a call is not
- // in progress.
- sigslot::signal2<HttpClient*,int> SignalHttpClientClosed;
+ // content is processed. You may change the response document in response
+ // to this signal. The second parameter indicates whether this is an
+ // intermediate (false) or final (true) header. An intermediate header is
+ // one that generates another request, such as a redirect or authentication
+ // challenge. The third parameter indicates the length of the response
+ // document, or else SIZE_UNKNOWN. Note: Do NOT abort the request in response
+ // to this signal.
+ sigslot::signal3<HttpClient*,bool,size_t> SignalHeaderAvailable;
+ // Signalled when the current request finishes. On success, err is 0.
+ sigslot::signal2<HttpClient*,HttpErrorType> SignalHttpClientComplete;
protected:
+ void connect();
void release();
+ bool ShouldRedirect(std::string* location) const;
+
bool BeginCacheFile();
HttpError WriteCacheHeaders(const std::string& id);
void CompleteCacheFile();
@@ -127,25 +186,24 @@
HttpBase base_;
SocketAddress server_;
ProxyInfo proxy_;
- HttpRequestData request_;
- HttpResponseData response_;
- bool fail_redirect_, absolute_uri_;
+ HttpTransaction* transaction_;
+ bool free_transaction_;
+ size_t retries_, attempt_, redirects_;
+ RedirectAction redirect_action_;
+ UriForm uri_form_;
scoped_ptr<HttpAuthContext> context_;
DiskCache* cache_;
CacheState cache_state_;
};
//////////////////////////////////////////////////////////////////////
-// Default implementation of HttpClient
+// HttpClientDefault - Default implementation of HttpClient
//////////////////////////////////////////////////////////////////////
class HttpClientDefault : public ReuseSocketPool, public HttpClient {
public:
- HttpClientDefault(SocketFactory* factory, const std::string& agent)
- : ReuseSocketPool(factory), HttpClient(agent, NULL)
- {
- set_pool(this);
- }
+ HttpClientDefault(SocketFactory* factory, const std::string& agent,
+ HttpTransaction* transaction = NULL);
};
//////////////////////////////////////////////////////////////////////
diff --git a/talk/base/httpcommon-inl.h b/talk/base/httpcommon-inl.h
old mode 100755
new mode 100644
index 5235b89..a33a643
--- a/talk/base/httpcommon-inl.h
+++ b/talk/base/httpcommon-inl.h
@@ -38,73 +38,102 @@
///////////////////////////////////////////////////////////////////////////////
template<class CTYPE>
-Url<CTYPE>::Url(const string& url) {
- const CTYPE* raw_url = url.c_str();
- if (ascnicmp(raw_url, "http://", 7) == 0) {
- raw_url += 7;
- m_secure = false;
- } else if (ascnicmp(raw_url, "https://", 8) == 0) {
- raw_url += 8;
- m_secure = true;
+void Url<CTYPE>::do_set_url(const CTYPE* val, size_t len) {
+ if (ascnicmp(val, "http://", 7) == 0) {
+ val += 7; len -= 7;
+ secure_ = false;
+ } else if (ascnicmp(val, "https://", 8) == 0) {
+ val += 8; len -= 8;
+ secure_ = true;
} else {
+ clear();
return;
}
- m_port = UrlDefaultPort(m_secure);
- const CTYPE* colon = ::strchr(raw_url, static_cast<CTYPE>(':'));
- const CTYPE* slash = ::strchr(raw_url, static_cast<CTYPE>('/'));
- if (!colon && !slash) {
- m_server = url;
- // TODO: rethink this slash
- m_path.append(1, static_cast<CTYPE>('/'));
- } else {
- const CTYPE* ptr;
- if (colon == 0) {
- ptr = slash;
- } else if (slash == 0) {
- ptr = colon;
- } else {
- ptr = _min(colon, slash);
- }
- m_server.assign(raw_url, ptr - raw_url);
- if (ptr == colon) {
- CTYPE* tmp = 0;
- m_port = static_cast<uint16>(::strtoul(ptr + 1, &tmp, 10));
- ptr = tmp;
- }
- const CTYPE* query = ::strchr(ptr, static_cast<CTYPE>('?'));
- if (!query) {
- m_path.assign(ptr);
- } else {
- m_path.assign(ptr, query - ptr);
- m_query.assign(query);
- }
+ const CTYPE* path = strchrn(val, len, static_cast<CTYPE>('/'));
+ if (!path) {
+ path = val + len;
}
- ASSERT(m_path.empty() || (m_path[0] == static_cast<CTYPE>('/')));
- ASSERT(m_query.empty() || (m_query[0] == static_cast<CTYPE>('?')));
+ size_t address_length = (path - val);
+ do_set_address(val, address_length);
+ do_set_full_path(path, len - address_length);
}
template<class CTYPE>
-typename Traits<CTYPE>::string Url<CTYPE>::full_path() {
- string full_path(m_path);
- full_path.append(m_query);
- return full_path;
+void Url<CTYPE>::do_set_address(const CTYPE* val, size_t len) {
+ if (const CTYPE* colon = strchrn(val, len, static_cast<CTYPE>(':'))) {
+ host_.assign(val, colon - val);
+ // Note: In every case, we're guaranteed that colon is followed by a null,
+ // or non-numeric character.
+ port_ = static_cast<uint16>(::strtoul(colon + 1, NULL, 10));
+ // TODO: Consider checking for invalid data following port number.
+ } else {
+ host_.assign(val, len);
+ port_ = HttpDefaultPort(secure_);
+ }
}
template<class CTYPE>
-typename Traits<CTYPE>::string Url<CTYPE>::url() {
+void Url<CTYPE>::do_set_full_path(const CTYPE* val, size_t len) {
+ const CTYPE* query = strchrn(val, len, static_cast<CTYPE>('?'));
+ if (!query) {
+ query = val + len;
+ }
+ size_t path_length = (query - val);
+ if (0 == path_length) {
+ // TODO: consider failing in this case.
+ path_.assign(1, static_cast<CTYPE>('/'));
+ } else {
+ ASSERT(val[0] == static_cast<CTYPE>('/'));
+ path_.assign(val, path_length);
+ }
+ query_.assign(query, len - path_length);
+}
+
+template<class CTYPE>
+void Url<CTYPE>::do_get_url(string* val) const {
CTYPE protocol[9];
- asccpyn(protocol, ARRAY_SIZE(protocol), m_secure ? "https://" : "http://");
- string url(protocol);
- url.append(m_server);
- if (m_port != UrlDefaultPort(m_secure)) {
+ asccpyn(protocol, ARRAY_SIZE(protocol), secure_ ? "https://" : "http://");
+ val->append(protocol);
+ do_get_address(val);
+ do_get_full_path(val);
+}
+
+template<class CTYPE>
+void Url<CTYPE>::do_get_address(string* val) const {
+ val->append(host_);
+ if (port_ != HttpDefaultPort(secure_)) {
CTYPE format[5], port[32];
asccpyn(format, ARRAY_SIZE(format), ":%hu");
- sprintfn(port, ARRAY_SIZE(port), format, m_port);
- url.append(port);
+ sprintfn(port, ARRAY_SIZE(port), format, port_);
+ val->append(port);
}
- url.append(m_path);
- url.append(m_query);
- return url;
+}
+
+template<class CTYPE>
+void Url<CTYPE>::do_get_full_path(string* val) const {
+ val->append(path_);
+ val->append(query_);
+}
+
+template<class CTYPE>
+bool Url<CTYPE>::get_attribute(const string& name, string* value) const {
+ if (query_.empty())
+ return false;
+
+ std::string::size_type pos = query_.find(name, 1);
+ if (std::string::npos == pos)
+ return false;
+
+ pos += name.length() + 1;
+ if ((pos > query_.length()) || (static_cast<CTYPE>('=') != query_[pos-1]))
+ return false;
+
+ std::string::size_type end = query_.find(static_cast<CTYPE>('&'), pos);
+ if (std::string::npos == end) {
+ end = query_.length();
+ }
+ value->assign(query_.substr(pos, end - pos));
+ return true;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/talk/base/httpcommon.cc b/talk/base/httpcommon.cc
old mode 100755
new mode 100644
index 0358121..f7553b2
--- a/talk/base/httpcommon.cc
+++ b/talk/base/httpcommon.cc
@@ -2,46 +2,49 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <time.h>
#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
-#define _WINSOCKAPI_
-#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
#endif
+#include "talk/base/httpcommon-inl.h"
+
#include "talk/base/base64.h"
#include "talk/base/common.h"
#include "talk/base/cryptstring.h"
#include "talk/base/httpcommon.h"
#include "talk/base/socketaddress.h"
#include "talk/base/stringdigest.h"
+#include "talk/base/stringencode.h"
#include "talk/base/stringutils.h"
namespace talk_base {
@@ -70,7 +73,7 @@
static size_t Size;
static inline const char* Name(E val) { return Names[val]; }
- static inline bool Parse(E& val, const std::string& name) {
+ static inline bool Parse(E& val, const std::string& name) {
size_t index;
if (!find_string(index, name, Names, Size))
return false;
@@ -97,7 +100,7 @@
//////////////////////////////////////////////////////////////////////
static const char* kHttpVersions[HVER_LAST+1] = {
- "1.0", "1.1"
+ "1.0", "1.1", "Unknown"
};
ENUM(HttpVersion, kHttpVersions);
@@ -110,6 +113,7 @@
"Age",
"Cache-Control",
"Connection",
+ "Content-Disposition",
"Content-Length",
"Content-Range",
"Content-Type",
@@ -163,7 +167,7 @@
bool HttpCodeHasBody(uint32 code) {
return !HttpCodeIsInformational(code)
- && (code != HC_NO_CONTENT) || (code != HC_NOT_MODIFIED);
+ && (code != HC_NO_CONTENT) && (code != HC_NOT_MODIFIED);
}
bool HttpCodeIsCacheable(uint32 code) {
@@ -186,7 +190,7 @@
case HH_KEEP_ALIVE:
case HH_PROXY_AUTHENTICATE:
case HH_PROXY_AUTHORIZATION:
- //case HH_PROXY_CONNECTION:??
+ case HH_PROXY_CONNECTION: // Note part of RFC... this is non-standard header
case HH_TE:
case HH_TRAILERS:
case HH_TRANSFER_ENCODING:
@@ -234,9 +238,34 @@
return false;
}
+// TODO: unittest for EscapeAttribute and HttpComposeAttributes.
+
+std::string EscapeAttribute(const std::string& attribute) {
+ const size_t kMaxLength = attribute.length() * 2 + 1;
+ char* buffer = STACK_ARRAY(char, kMaxLength);
+ size_t len = escape(buffer, kMaxLength, attribute.data(), attribute.length(),
+ "\"", '\\');
+ return std::string(buffer, len);
+}
+
} // anonymous namespace
-void HttpParseAttributes(const char * data, size_t len,
+void HttpComposeAttributes(const HttpAttributeList& attributes, char separator,
+ std::string* composed) {
+ std::stringstream ss;
+ for (size_t i=0; i<attributes.size(); ++i) {
+ if (i > 0) {
+ ss << separator << " ";
+ }
+ ss << attributes[i].first;
+ if (!attributes[i].second.empty()) {
+ ss << "=\"" << EscapeAttribute(attributes[i].second) << "\"";
+ }
+ }
+ *composed = ss.str();
+}
+
+void HttpParseAttributes(const char * data, size_t len,
HttpAttributeList& attributes) {
size_t pos = 0;
while (true) {
@@ -302,7 +331,7 @@
}
bool HttpHasNthAttribute(HttpAttributeList& attributes,
- size_t index,
+ size_t index,
std::string* name,
std::string* value) {
if (index >= attributes.size())
@@ -336,7 +365,7 @@
if (7 != sscanf(date.c_str(), "%*3s, %d %3s %d %d:%d:%d %5c",
&tval.tm_mday, month, &tval.tm_year,
- &tval.tm_hour, &tval.tm_min, &tval.tm_sec, &zone)) {
+ &tval.tm_hour, &tval.tm_min, &tval.tm_sec, zone)) {
return false;
}
switch (toupper(month[2])) {
@@ -369,7 +398,8 @@
}
gmt = non_gmt + kTimeZoneOffsets[zindex] * 60 * 60;
}
-#ifdef OSX
+ // TODO: Android should support timezone, see b/2441195
+#if defined(OSX) || defined(ANDROID) || defined(BSD)
tm *tm_for_timezone = localtime((time_t *)&gmt);
*seconds = gmt + tm_for_timezone->tm_gmtoff;
#else
@@ -378,16 +408,28 @@
return true;
}
+std::string HttpAddress(const SocketAddress& address, bool secure) {
+ return (address.port() == HttpDefaultPort(secure))
+ ? address.hostname() : address.ToString();
+}
+
//////////////////////////////////////////////////////////////////////
// HttpData
//////////////////////////////////////////////////////////////////////
void
HttpData::clear(bool release_document) {
+ // Clear headers first, since releasing a document may have far-reaching
+ // effects.
+ headers_.clear();
if (release_document) {
document.reset();
}
- m_headers.clear();
+}
+
+void
+HttpData::copy(const HttpData& src) {
+ headers_ = src.headers_;
}
void
@@ -399,13 +441,13 @@
combine = !FromString(header, name) || HttpHeaderIsCollapsible(header)
? HC_YES : HC_NO;
} else if (combine == HC_REPLACE) {
- m_headers.erase(name);
+ headers_.erase(name);
combine = HC_NO;
}
// At this point, combine is one of (YES, NO, NEW)
if (combine != HC_NO) {
- HeaderMap::iterator it = m_headers.find(name);
- if (it != m_headers.end()) {
+ HeaderMap::iterator it = headers_.find(name);
+ if (it != headers_.end()) {
if (combine == HC_YES) {
it->second.append(",");
it->second.append(value);
@@ -413,18 +455,23 @@
return;
}
}
- m_headers.insert(HeaderMap::value_type(name, value));
+ headers_.insert(HeaderMap::value_type(name, value));
}
-void
-HttpData::clearHeader(const std::string& name) {
- m_headers.erase(name);
+size_t HttpData::clearHeader(const std::string& name) {
+ return headers_.erase(name);
+}
+
+HttpData::iterator HttpData::clearHeader(iterator header) {
+ iterator deprecated = header++;
+ headers_.erase(deprecated);
+ return header;
}
bool
HttpData::hasHeader(const std::string& name, std::string* value) const {
- HeaderMap::const_iterator it = m_headers.find(name);
- if (it == m_headers.end()) {
+ HeaderMap::const_iterator it = headers_.find(name);
+ if (it == headers_.end()) {
return false;
} else if (value) {
*value = it->second;
@@ -432,14 +479,20 @@
return true;
}
-void
-HttpData::setContent(const std::string& content_type,
- StreamInterface* document) {
+void HttpData::setContent(const std::string& content_type,
+ StreamInterface* document) {
+ setHeader(HH_CONTENT_TYPE, content_type);
+ setDocumentAndLength(document);
+}
+
+void HttpData::setDocumentAndLength(StreamInterface* document) {
+ // TODO: Consider calling Rewind() here?
+ ASSERT(!hasHeader(HH_CONTENT_LENGTH, NULL));
+ ASSERT(!hasHeader(HH_TRANSFER_ENCODING, NULL));
ASSERT(document != NULL);
this->document.reset(document);
- setHeader(HH_CONTENT_TYPE, content_type);
size_t content_length = 0;
- if (this->document->GetSize(&content_length)) {
+ if (this->document->GetAvailable(&content_length)) {
char buffer[32];
sprintfn(buffer, sizeof(buffer), "%d", content_length);
setHeader(HH_CONTENT_LENGTH, buffer);
@@ -454,13 +507,20 @@
void
HttpRequestData::clear(bool release_document) {
- HttpData::clear(release_document);
verb = HV_GET;
path.clear();
+ HttpData::clear(release_document);
+}
+
+void
+HttpRequestData::copy(const HttpRequestData& src) {
+ verb = src.verb;
+ path = src.path;
+ HttpData::copy(src);
}
size_t
-HttpRequestData::formatLeader(char* buffer, size_t size) {
+HttpRequestData::formatLeader(char* buffer, size_t size) const {
ASSERT(path.find(' ') == std::string::npos);
return sprintfn(buffer, size, "%s %.*s HTTP/%s", ToString(verb), path.size(),
path.data(), ToString(version));
@@ -469,9 +529,9 @@
HttpError
HttpRequestData::parseLeader(const char* line, size_t len) {
UNUSED(len);
- uint32 vmajor, vminor;
+ unsigned int vmajor, vminor;
int vend, dstart, dend;
- if ((sscanf(line, "%*s%n %n%*s%n HTTP/%lu.%lu", &vend, &dstart, &dend,
+ if ((sscanf(line, "%*s%n %n%*s%n HTTP/%u.%u", &vend, &dstart, &dend,
&vmajor, &vminor) != 2)
|| (vmajor != 1)) {
return HE_PROTOCOL;
@@ -491,22 +551,63 @@
return HE_NONE;
}
+bool HttpRequestData::getAbsoluteUri(std::string* uri) const {
+ if (HV_CONNECT == verb)
+ return false;
+ Url<char> url(path);
+ if (url.valid()) {
+ uri->assign(path);
+ return true;
+ }
+ std::string host;
+ if (!hasHeader(HH_HOST, &host))
+ return false;
+ url.set_address(host);
+ url.set_full_path(path);
+ uri->assign(url.url());
+ return url.valid();
+}
+
+bool HttpRequestData::getRelativeUri(std::string* host,
+ std::string* path) const
+{
+ if (HV_CONNECT == verb)
+ return false;
+ Url<char> url(this->path);
+ if (url.valid()) {
+ host->assign(url.address());
+ path->assign(url.full_path());
+ return true;
+ }
+ if (!hasHeader(HH_HOST, host))
+ return false;
+ path->assign(this->path);
+ return true;
+}
+
//
// HttpResponseData
//
void
HttpResponseData::clear(bool release_document) {
- HttpData::clear(release_document);
scode = HC_INTERNAL_SERVER_ERROR;
message.clear();
+ HttpData::clear(release_document);
+}
+
+void
+HttpResponseData::copy(const HttpResponseData& src) {
+ scode = src.scode;
+ message = src.message;
+ HttpData::copy(src);
}
void
HttpResponseData::set_success(uint32 scode) {
this->scode = scode;
message.clear();
- setHeader(HH_CONTENT_LENGTH, "0");
+ setHeader(HH_CONTENT_LENGTH, "0", false);
}
void
@@ -523,18 +624,18 @@
this->scode = scode;
message.clear();
setHeader(HH_LOCATION, location);
- setHeader(HH_CONTENT_LENGTH, "0");
+ setHeader(HH_CONTENT_LENGTH, "0", false);
}
void
HttpResponseData::set_error(uint32 scode) {
this->scode = scode;
message.clear();
- setHeader(HH_CONTENT_LENGTH, "0");
+ setHeader(HH_CONTENT_LENGTH, "0", false);
}
size_t
-HttpResponseData::formatLeader(char* buffer, size_t size) {
+HttpResponseData::formatLeader(char* buffer, size_t size) const {
size_t len = sprintfn(buffer, size, "HTTP/%s %lu", ToString(version), scode);
if (!message.empty()) {
len += sprintfn(buffer + len, size - len, " %.*s",
@@ -546,18 +647,31 @@
HttpError
HttpResponseData::parseLeader(const char* line, size_t len) {
size_t pos = 0;
- uint32 vmajor, vminor;
- if ((sscanf(line, "HTTP/%lu.%lu %lu%n", &vmajor, &vminor, &scode, &pos) != 3)
- || (vmajor != 1)) {
- return HE_PROTOCOL;
- }
- if (vminor == 0) {
- version = HVER_1_0;
- } else if (vminor == 1) {
- version = HVER_1_1;
+ unsigned int vmajor, vminor, temp_scode;
+ int temp_pos;
+ if (sscanf(line, "HTTP %u%n",
+ &temp_scode, &temp_pos) == 1) {
+ // This server's response has no version. :( NOTE: This happens for every
+ // response to requests made from Chrome plugins, regardless of the server's
+ // behaviour.
+ LOG(LS_VERBOSE) << "HTTP version missing from response";
+ version = HVER_UNKNOWN;
+ } else if ((sscanf(line, "HTTP/%u.%u %u%n",
+ &vmajor, &vminor, &temp_scode, &temp_pos) == 3)
+ && (vmajor == 1)) {
+ // This server's response does have a version.
+ if (vminor == 0) {
+ version = HVER_1_0;
+ } else if (vminor == 1) {
+ version = HVER_1_1;
+ } else {
+ return HE_PROTOCOL;
+ }
} else {
return HE_PROTOCOL;
}
+ scode = temp_scode;
+ pos = static_cast<size_t>(temp_pos);
while ((pos < len) && isspace(static_cast<unsigned char>(line[pos]))) ++pos;
message.assign(line + pos, len - pos);
return HE_NONE;
@@ -598,7 +712,7 @@
"edffcb0829e755838b073a4a42de06bc";
#endif
-static std::string quote(const std::string& str) {
+std::string quote(const std::string& str) {
std::string result;
result.push_back('"');
for (size_t i=0; i<str.size(); ++i) {
@@ -668,7 +782,7 @@
response = auth_method;
response.append(" ");
// TODO: create a sensitive-source version of Base64::encode
- response.append(Base64::encode(sensitive));
+ response.append(Base64::Encode(sensitive));
memset(sensitive, 0, len);
delete [] sensitive;
return HAR_RESPONSE;
@@ -690,7 +804,7 @@
cnonce = DIGEST_CNONCE;
#else
char buffer[256];
- sprintf(buffer, "%d", time(0));
+ sprintf(buffer, "%d", static_cast<int>(time(0)));
cnonce = MD5(buffer);
#endif
ncount = "00000001";
@@ -726,7 +840,7 @@
std::string dig_response = MD5(HA1 + ":" + middle + ":" + HA2);
#if TEST_DIGEST
- assert(strcmp(dig_response.c_str(), DIGEST_RESPONSE) == 0);
+ ASSERT(strcmp(dig_response.c_str(), DIGEST_RESPONSE) == 0);
#endif
std::stringstream ss;
@@ -789,7 +903,7 @@
//| ISC_REQ_USE_SUPPLIED_CREDS
;
- TimeStamp lifetime;
+ ::TimeStamp lifetime;
SECURITY_STATUS ret = S_OK;
ULONG ret_flags = 0, flags = NEG_FLAGS_DEFAULT;
@@ -807,10 +921,10 @@
}
steps = neg->steps;
- std::string decoded_challenge;
- HttpHasNthAttribute(args, 1, &decoded_challenge, NULL);
- decoded_challenge = Base64::decode(decoded_challenge);
- if (!decoded_challenge.empty()) {
+ std::string challenge, decoded_challenge;
+ if (HttpHasNthAttribute(args, 1, &challenge, NULL)
+ && Base64::Decode(challenge, Base64::DO_STRICT,
+ &decoded_challenge, NULL)) {
SecBuffer in_sec;
in_sec.pvBuffer = const_cast<char *>(decoded_challenge.data());
in_sec.cbBuffer = static_cast<unsigned long>(decoded_challenge.size());
@@ -822,7 +936,7 @@
in_buf_desc.pBuffers = &in_sec;
ret = InitializeSecurityContextA(&neg->cred, &neg->ctx, spn, flags, 0, SECURITY_NATIVE_DREP, &in_buf_desc, 0, &neg->ctx, &out_buf_desc, &ret_flags, &lifetime);
- //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeDiff(talk_base::Time(), now);
+ //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeSince(now);
if (FAILED(ret)) {
LOG(LS_ERROR) << "InitializeSecurityContext returned: "
<< ErrorName(ret, SECURITY_ERRORS);
@@ -886,7 +1000,7 @@
CredHandle cred;
ret = AcquireCredentialsHandleA(0, want_negotiate ? NEGOSSP_NAME_A : NTLMSP_NAME_A, SECPKG_CRED_OUTBOUND, 0, pauth_id, 0, 0, &cred, &lifetime);
- //LOG(INFO) << "$$$ AcquireCredentialsHandle @ " << TimeDiff(talk_base::Time(), now);
+ //LOG(INFO) << "$$$ AcquireCredentialsHandle @ " << TimeSince(now);
if (ret != SEC_E_OK) {
LOG(LS_ERROR) << "AcquireCredentialsHandle error: "
<< ErrorName(ret, SECURITY_ERRORS);
@@ -897,7 +1011,7 @@
CtxtHandle ctx;
ret = InitializeSecurityContextA(&cred, 0, spn, flags, 0, SECURITY_NATIVE_DREP, 0, 0, &ctx, &out_buf_desc, &ret_flags, &lifetime);
- //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeDiff(talk_base::Time(), now);
+ //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeSince(now);
if (FAILED(ret)) {
LOG(LS_ERROR) << "InitializeSecurityContext returned: "
<< ErrorName(ret, SECURITY_ERRORS);
@@ -905,7 +1019,7 @@
return HAR_IGNORE;
}
- assert(!context);
+ ASSERT(!context);
context = neg = new NegotiateAuthContext(auth_method, cred, ctx);
neg->specified_credentials = specify_credentials;
neg->steps = steps;
@@ -913,7 +1027,7 @@
if ((ret == SEC_I_COMPLETE_NEEDED) || (ret == SEC_I_COMPLETE_AND_CONTINUE)) {
ret = CompleteAuthToken(&neg->ctx, &out_buf_desc);
- //LOG(INFO) << "$$$ CompleteAuthToken @ " << TimeDiff(talk_base::Time(), now);
+ //LOG(INFO) << "$$$ CompleteAuthToken @ " << TimeSince(now);
LOG(LS_VERBOSE) << "CompleteAuthToken returned: "
<< ErrorName(ret, SECURITY_ERRORS);
if (FAILED(ret)) {
@@ -921,12 +1035,12 @@
}
}
- //LOG(INFO) << "$$$ NEGOTIATE took " << TimeDiff(talk_base::Time(), now) << "ms";
+ //LOG(INFO) << "$$$ NEGOTIATE took " << TimeSince(now) << "ms";
std::string decoded(out_buf, out_buf + out_sec.cbBuffer);
response = auth_method;
response.append(" ");
- response.append(Base64::encode(decoded));
+ response.append(Base64::Encode(decoded));
return HAR_RESPONSE;
}
#endif
diff --git a/talk/base/httpcommon.h b/talk/base/httpcommon.h
old mode 100755
new mode 100644
index 2893933..7e0b9cf
--- a/talk/base/httpcommon.h
+++ b/talk/base/httpcommon.h
@@ -32,6 +32,7 @@
#include <string>
#include <vector>
#include "talk/base/basictypes.h"
+#include "talk/base/common.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/stringutils.h"
#include "talk/base/stream.h"
@@ -65,12 +66,14 @@
HC_PROXY_AUTHENTICATION_REQUIRED = 407,
HC_GONE = 410,
- HC_INTERNAL_SERVER_ERROR = 500
+ HC_INTERNAL_SERVER_ERROR = 500,
+ HC_NOT_IMPLEMENTED = 501,
+ HC_SERVICE_UNAVAILABLE = 503,
};
enum HttpVersion {
- HVER_1_0, HVER_1_1,
- HVER_LAST = HVER_1_1
+ HVER_1_0, HVER_1_1, HVER_UNKNOWN,
+ HVER_LAST = HVER_UNKNOWN
};
enum HttpVerb {
@@ -80,8 +83,13 @@
enum HttpError {
HE_NONE,
- HE_PROTOCOL, HE_DISCONNECTED, HE_OVERFLOW,
- HE_SOCKET, HE_SHUTDOWN, HE_OPERATION_CANCELLED,
+ HE_PROTOCOL, // Received non-valid HTTP data
+ HE_DISCONNECTED, // Connection closed unexpectedly
+ HE_OVERFLOW, // Received too much data for internal buffers
+ HE_CONNECT_FAILED, // The socket failed to connect.
+ HE_SOCKET_ERROR, // An error occurred on a connected socket
+ HE_SHUTDOWN, // Http object is being destroyed
+ HE_OPERATION_CANCELLED, // Connection aborted locally
HE_AUTH, // Proxy Authentication Required
HE_CERTIFICATE_EXPIRED, // During SSL negotiation
HE_STREAM, // Problem reading or writing to the document
@@ -93,6 +101,7 @@
HH_AGE,
HH_CACHE_CONTROL,
HH_CONNECTION,
+ HH_CONTENT_DISPOSITION,
HH_CONTENT_LENGTH,
HH_CONTENT_RANGE,
HH_CONTENT_TYPE,
@@ -156,6 +165,8 @@
typedef std::pair<std::string, std::string> HttpAttribute;
typedef std::vector<HttpAttribute> HttpAttributeList;
+void HttpComposeAttributes(const HttpAttributeList& attributes, char separator,
+ std::string* composed);
void HttpParseAttributes(const char * data, size_t len,
HttpAttributeList& attributes);
bool HttpHasAttribute(const HttpAttributeList& attributes,
@@ -169,10 +180,13 @@
// Convert RFC1123 date (DoW, DD Mon YYYY HH:MM:SS TZ) to unix timestamp
bool HttpDateToSeconds(const std::string& date, unsigned long* seconds);
-inline const uint16 UrlDefaultPort(bool secure) {
+inline uint16 HttpDefaultPort(bool secure) {
return secure ? HTTP_SECURE_PORT : HTTP_DEFAULT_PORT;
}
+// Returns the http server notation for a given address
+std::string HttpAddress(const SocketAddress& address, bool secure);
+
// functional for insensitive std::string compare
struct iless {
bool operator()(const std::string& lhs, const std::string& rhs) const {
@@ -180,6 +194,9 @@
}
};
+// put quotes around a string and escape any quotes inside it
+std::string quote(const std::string& str);
+
//////////////////////////////////////////////////////////////////////
// Url
//////////////////////////////////////////////////////////////////////
@@ -195,41 +212,80 @@
static int Decode(const CTYPE* source, CTYPE* destination, size_t len);
static int Decode(const string& source, string& destination);
- Url(const string& url);
- Url(const string& path, const string& server, uint16 port = HTTP_DEFAULT_PORT)
- : m_server(server), m_path(path), m_port(port),
- m_secure(HTTP_SECURE_PORT == port)
- {
- ASSERT(m_path.empty() || (m_path[0] == static_cast<CTYPE>('/')));
- }
-
- bool valid() const { return !m_server.empty(); }
- const string& server() const { return m_server; }
- // Note: path() was renamed to path_, because it now uses the stricter sense
- // of not including a query string. I'm trying to think of a clearer name.
- const string& path_() const { return m_path; }
- const string& query() const { return m_query; }
- string full_path();
- string url();
- uint16 port() const { return m_port; }
- bool secure() const { return m_secure; }
+ Url(const string& url) { do_set_url(url.c_str(), url.size()); }
+ Url(const string& path, const string& host, uint16 port = HTTP_DEFAULT_PORT)
+ : host_(host), port_(port), secure_(HTTP_SECURE_PORT == port)
+ { set_full_path(path); }
- void set_server(const string& val) { m_server = val; }
- void set_path(const string& val) {
- ASSERT(val.empty() || (val[0] == static_cast<CTYPE>('/')));
- m_path = val;
+ bool valid() const { return !host_.empty(); }
+ void clear() {
+ host_.clear();
+ port_ = HTTP_DEFAULT_PORT;
+ secure_ = false;
+ path_.assign(1, static_cast<CTYPE>('/'));
+ query_.clear();
}
+
+ void set_url(const string& val) {
+ do_set_url(val.c_str(), val.size());
+ }
+ string url() const {
+ string val; do_get_url(&val); return val;
+ }
+
+ void set_address(const string& val) {
+ do_set_address(val.c_str(), val.size());
+ }
+ string address() const {
+ string val; do_get_address(&val); return val;
+ }
+
+ void set_full_path(const string& val) {
+ do_set_full_path(val.c_str(), val.size());
+ }
+ string full_path() const {
+ string val; do_get_full_path(&val); return val;
+ }
+
+ void set_host(const string& val) { host_ = val; }
+ const string& host() const { return host_; }
+
+ void set_port(uint16 val) { port_ = val; }
+ uint16 port() const { return port_; }
+
+ void set_secure(bool val) { secure_ = val; }
+ bool secure() const { return secure_; }
+
+ void set_path(const string& val) {
+ if (val.empty()) {
+ path_.assign(1, static_cast<CTYPE>('/'));
+ } else {
+ ASSERT(val[0] == static_cast<CTYPE>('/'));
+ path_ = val;
+ }
+ }
+ const string& path() const { return path_; }
+
void set_query(const string& val) {
ASSERT(val.empty() || (val[0] == static_cast<CTYPE>('?')));
- m_query = val;
+ query_ = val;
}
- void set_port(uint16 val) { m_port = val; }
- void set_secure(bool val) { m_secure = val; }
+ const string& query() const { return query_; }
+
+ bool get_attribute(const string& name, string* value) const;
private:
- string m_server, m_path, m_query;
- uint16 m_port;
- bool m_secure;
+ void do_set_url(const CTYPE* val, size_t len);
+ void do_set_address(const CTYPE* val, size_t len);
+ void do_set_full_path(const CTYPE* val, size_t len);
+
+ void do_get_url(string* val) const;
+ void do_get_address(string* val) const;
+ void do_get_full_path(string* val) const;
+
+ string host_, path_, query_;
+ uint16 port_;
+ bool secure_;
};
//////////////////////////////////////////////////////////////////////
@@ -239,7 +295,8 @@
struct HttpData {
typedef std::multimap<std::string, std::string, iless> HeaderMap;
typedef HeaderMap::const_iterator const_iterator;
-
+ typedef HeaderMap::iterator iterator;
+
HttpVersion version;
scoped_ptr<StreamInterface> document;
@@ -256,24 +313,39 @@
bool overwrite = true) {
changeHeader(name, value, overwrite ? HC_REPLACE : HC_NEW);
}
- void clearHeader(const std::string& name);
+ // Returns count of erased headers
+ size_t clearHeader(const std::string& name);
+ // Returns iterator to next header
+ iterator clearHeader(iterator header);
// keep in mind, this may not do what you want in the face of multiple headers
bool hasHeader(const std::string& name, std::string* value) const;
inline const_iterator begin() const {
- return m_headers.begin();
+ return headers_.begin();
}
inline const_iterator end() const {
- return m_headers.end();
+ return headers_.end();
+ }
+ inline iterator begin() {
+ return headers_.begin();
+ }
+ inline iterator end() {
+ return headers_.end();
}
inline const_iterator begin(const std::string& name) const {
- return m_headers.lower_bound(name);
+ return headers_.lower_bound(name);
}
inline const_iterator end(const std::string& name) const {
- return m_headers.upper_bound(name);
+ return headers_.upper_bound(name);
}
-
+ inline iterator begin(const std::string& name) {
+ return headers_.lower_bound(name);
+ }
+ inline iterator end(const std::string& name) {
+ return headers_.upper_bound(name);
+ }
+
// Convenience methods using HttpHeader
inline void changeHeader(HttpHeader header, const std::string& value,
HeaderCombine combine) {
@@ -294,23 +366,31 @@
return hasHeader(ToString(header), value);
}
inline const_iterator begin(HttpHeader header) const {
- return m_headers.lower_bound(ToString(header));
+ return headers_.lower_bound(ToString(header));
}
inline const_iterator end(HttpHeader header) const {
- return m_headers.upper_bound(ToString(header));
+ return headers_.upper_bound(ToString(header));
+ }
+ inline iterator begin(HttpHeader header) {
+ return headers_.lower_bound(ToString(header));
+ }
+ inline iterator end(HttpHeader header) {
+ return headers_.upper_bound(ToString(header));
}
void setContent(const std::string& content_type, StreamInterface* document);
+ void setDocumentAndLength(StreamInterface* document);
- virtual size_t formatLeader(char* buffer, size_t size) = 0;
+ virtual size_t formatLeader(char* buffer, size_t size) const = 0;
virtual HttpError parseLeader(const char* line, size_t len) = 0;
-
+
protected:
virtual ~HttpData() { }
void clear(bool release_document);
+ void copy(const HttpData& src);
private:
- HeaderMap m_headers;
+ HeaderMap headers_;
};
struct HttpRequestData : public HttpData {
@@ -320,9 +400,13 @@
HttpRequestData() : verb(HV_GET) { }
void clear(bool release_document);
+ void copy(const HttpRequestData& src);
- virtual size_t formatLeader(char* buffer, size_t size);
+ virtual size_t formatLeader(char* buffer, size_t size) const;
virtual HttpError parseLeader(const char* line, size_t len);
+
+ bool getAbsoluteUri(std::string* uri) const;
+ bool getRelativeUri(std::string* host, std::string* path) const;
};
struct HttpResponseData : public HttpData {
@@ -331,6 +415,7 @@
HttpResponseData() : scode(HC_INTERNAL_SERVER_ERROR) { }
void clear(bool release_document);
+ void copy(const HttpResponseData& src);
// Convenience methods
void set_success(uint32 scode = HC_OK);
@@ -340,10 +425,15 @@
uint32 scode = HC_MOVED_TEMPORARILY);
void set_error(uint32 scode);
- virtual size_t formatLeader(char* buffer, size_t size);
+ virtual size_t formatLeader(char* buffer, size_t size) const;
virtual HttpError parseLeader(const char* line, size_t len);
};
+struct HttpTransaction {
+ HttpRequestData request;
+ HttpResponseData response;
+};
+
//////////////////////////////////////////////////////////////////////
// Http Authentication
//////////////////////////////////////////////////////////////////////
diff --git a/talk/base/httprequest.cc b/talk/base/httprequest.cc
new file mode 100644
index 0000000..48c924e
--- /dev/null
+++ b/talk/base/httprequest.cc
@@ -0,0 +1,127 @@
+/*
+ * libjingle
+ * Copyright 2006, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/httprequest.h"
+
+#include "talk/base/common.h"
+#include "talk/base/firewallsocketserver.h"
+#include "talk/base/httpclient.h"
+#include "talk/base/logging.h"
+#include "talk/base/physicalsocketserver.h"
+#include "talk/base/socketadapters.h"
+#include "talk/base/socketpool.h"
+#include "talk/base/ssladapter.h"
+
+using namespace talk_base;
+
+///////////////////////////////////////////////////////////////////////////////
+// HttpMonitor
+///////////////////////////////////////////////////////////////////////////////
+
+HttpMonitor::HttpMonitor(SocketServer *ss) {
+ ASSERT(Thread::Current() != NULL);
+ ss_ = ss;
+ reset();
+}
+
+void HttpMonitor::Connect(HttpClient *http) {
+ http->SignalHttpClientComplete.connect(this,
+ &HttpMonitor::OnHttpClientComplete);
+}
+
+void HttpMonitor::OnHttpClientComplete(HttpClient * http, HttpErrorType error) {
+ complete_ = true;
+ error_ = error;
+ ss_->WakeUp();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// HttpRequest
+///////////////////////////////////////////////////////////////////////////////
+
+const int kDefaultHTTPTimeout = 30 * 1000; // 30 sec
+
+HttpRequest::HttpRequest(const std::string &user_agent)
+ : firewall_(0), port_(80), secure_(false),
+ timeout_(kDefaultHTTPTimeout), fail_redirect_(false),
+ client_(user_agent.c_str(), NULL), error_(HE_NONE) {
+}
+
+void HttpRequest::Send() {
+ // TODO: Rewrite this to use the thread's native socket server, and a more
+ // natural flow?
+
+ PhysicalSocketServer physical;
+ SocketServer * ss = &physical;
+ if (firewall_) {
+ ss = new FirewallSocketServer(ss, firewall_);
+ }
+
+ SslSocketFactory factory(ss, client_.agent());
+ factory.SetProxy(proxy_);
+ if (secure_)
+ factory.UseSSL(host_.c_str());
+
+ //factory.SetLogging("HttpRequest");
+
+ ReuseSocketPool pool(&factory);
+ client_.set_pool(&pool);
+
+ bool transparent_proxy = (port_ == 80) && ((proxy_.type == PROXY_HTTPS) ||
+ (proxy_.type == PROXY_UNKNOWN));
+
+ if (transparent_proxy) {
+ client_.set_proxy(proxy_);
+ }
+ client_.set_fail_redirect(fail_redirect_);
+
+ SocketAddress server(host_, port_);
+ client_.set_server(server);
+
+ LOG(LS_INFO) << "HttpRequest start: " << host_ + client_.request().path;
+
+ HttpMonitor monitor(ss);
+ monitor.Connect(&client_);
+ client_.start();
+ ss->Wait(timeout_, true);
+ if (!monitor.done()) {
+ LOG(LS_INFO) << "HttpRequest request timed out";
+ client_.reset();
+ return;
+ }
+
+ set_error(monitor.error());
+ if (error_) {
+ LOG(LS_INFO) << "HttpRequest request error: " << error_;
+ return;
+ }
+
+ std::string value;
+ if (client_.response().hasHeader(HH_LOCATION, &value)) {
+ response_redirect_ = value.c_str();
+ }
+}
diff --git a/talk/base/httprequest.h b/talk/base/httprequest.h
new file mode 100644
index 0000000..2e13c32
--- /dev/null
+++ b/talk/base/httprequest.h
@@ -0,0 +1,132 @@
+/*
+ * libjingle
+ * Copyright 2006, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _HTTPREQUEST_H_
+#define _HTTPREQUEST_H_
+
+#include "talk/base/httpclient.h"
+#include "talk/base/logging.h"
+#include "talk/base/proxyinfo.h"
+#include "talk/base/socketserver.h"
+#include "talk/base/thread.h"
+#include "talk/base/sslsocketfactory.h" // Deprecated include
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// HttpRequest
+///////////////////////////////////////////////////////////////////////////////
+
+class FirewallManager;
+class MemoryStream;
+
+class HttpRequest {
+public:
+ HttpRequest(const std::string &user_agent);
+
+ void Send();
+
+ void set_proxy(const ProxyInfo& proxy) {
+ proxy_ = proxy;
+ }
+ void set_firewall(FirewallManager * firewall) {
+ firewall_ = firewall;
+ }
+
+ // The DNS name of the host to connect to.
+ const std::string& host() { return host_; }
+ void set_host(const std::string& host) { host_ = host; }
+
+ // The port to connect to on the target host.
+ int port() { return port_; }
+ void set_port(int port) { port_ = port; }
+
+ // Whether the request should use SSL.
+ bool secure() { return secure_; }
+ void set_secure(bool secure) { secure_ = secure; }
+
+ // Returns the redirect when redirection occurs
+ const std::string& response_redirect() { return response_redirect_; }
+
+ // Time to wait on the download, in ms. Default is 5000 (5s)
+ int timeout() { return timeout_; }
+ void set_timeout(int timeout) { timeout_ = timeout; }
+
+ // Fail redirects to allow analysis of redirect urls, etc.
+ bool fail_redirect() const { return fail_redirect_; }
+ void set_fail_redirect(bool fail_redirect) { fail_redirect_ = fail_redirect; }
+
+ HttpRequestData& request() { return client_.request(); }
+ HttpResponseData& response() { return client_.response(); }
+ HttpErrorType error() { return error_; }
+
+protected:
+ void set_error(HttpErrorType error) { error_ = error; }
+
+private:
+ ProxyInfo proxy_;
+ FirewallManager * firewall_;
+ std::string host_;
+ int port_;
+ bool secure_;
+ int timeout_;
+ bool fail_redirect_;
+ HttpClient client_;
+ HttpErrorType error_;
+ std::string response_redirect_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// HttpMonitor
+///////////////////////////////////////////////////////////////////////////////
+
+class HttpMonitor : public sigslot::has_slots<> {
+public:
+ HttpMonitor(SocketServer *ss);
+
+ void reset() {
+ complete_ = false;
+ error_ = HE_DEFAULT;
+ }
+
+ bool done() const { return complete_; }
+ HttpErrorType error() const { return error_; }
+
+ void Connect(HttpClient* http);
+ void OnHttpClientComplete(HttpClient * http, HttpErrorType error);
+
+private:
+ bool complete_;
+ HttpErrorType error_;
+ SocketServer *ss_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base_
+
+#endif // _HTTPREQUEST_H_
diff --git a/talk/base/httpserver.cc b/talk/base/httpserver.cc
deleted file mode 100755
index 9c27b5c..0000000
--- a/talk/base/httpserver.cc
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <algorithm>
-
-#include "talk/base/httpcommon-inl.h"
-
-#include "talk/base/asyncsocket.h"
-#include "talk/base/common.h"
-#include "talk/base/httpserver.h"
-#include "talk/base/logging.h"
-#include "talk/base/socketstream.h"
-
-namespace talk_base {
-
-///////////////////////////////////////////////////////////////////////////////
-// HttpServer
-///////////////////////////////////////////////////////////////////////////////
-
-HttpServer::HttpServer() : next_connection_id_(1) {
-}
-
-HttpServer::~HttpServer() {
- for (ConnectionMap::iterator it = connections_.begin();
- it != connections_.end();
- ++it) {
- StreamInterface* stream = it->second->EndProcess();
- delete stream;
- delete it->second;
- }
-}
-
-int
-HttpServer::HandleConnection(StreamInterface* stream) {
- int connection_id = next_connection_id_++;
- ASSERT(connection_id != HTTP_INVALID_CONNECTION_ID);
- Connection* connection = new Connection(connection_id, this);
- connections_.insert(ConnectionMap::value_type(connection_id, connection));
- connection->BeginProcess(stream);
- return connection_id;
-}
-
-void
-HttpServer::Respond(HttpTransaction* transaction) {
- int connection_id = transaction->connection_id();
- if (Connection* connection = Find(connection_id)) {
- connection->Respond(transaction);
- } else {
- delete transaction;
- // We may be tempted to SignalHttpComplete, but that implies that a
- // connection still exists.
- }
-}
-
-void
-HttpServer::Close(int connection_id, bool force) {
- if (Connection* connection = Find(connection_id)) {
- connection->InitiateClose(force);
- }
-}
-
-void
-HttpServer::CloseAll(bool force) {
- std::list<Connection*> connections;
- for (ConnectionMap::const_iterator it = connections_.begin();
- it != connections_.end(); ++it) {
- connections.push_back(it->second);
- }
- for (std::list<Connection*>::const_iterator it = connections.begin();
- it != connections.end(); ++it) {
- (*it)->InitiateClose(force);
- }
-}
-
-HttpServer::Connection*
-HttpServer::Find(int connection_id) {
- ConnectionMap::iterator it = connections_.find(connection_id);
- if (it == connections_.end())
- return NULL;
- return it->second;
-}
-
-void
-HttpServer::Remove(int connection_id) {
- ConnectionMap::iterator it = connections_.find(connection_id);
- if (it == connections_.end()) {
- ASSERT(false);
- return;
- }
- Connection* connection = it->second;
- connections_.erase(it);
- SignalConnectionClosed(this, connection_id, connection->EndProcess());
- delete connection;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// HttpServer::Connection
-///////////////////////////////////////////////////////////////////////////////
-
-HttpServer::Connection::Connection(int connection_id, HttpServer* server)
- : connection_id_(connection_id), server_(server),
- current_(NULL), signalling_(false), close_(false) {
-}
-
-HttpServer::Connection::~Connection() {
- delete current_;
-}
-
-void
-HttpServer::Connection::BeginProcess(StreamInterface* stream) {
- base_.notify(this);
- base_.attach(stream);
- current_ = new HttpTransaction(connection_id_);
- current_->request()->document.reset(new MemoryStream);
- if (base_.mode() != HM_CONNECT)
- base_.recv(current_->request());
-}
-
-StreamInterface*
-HttpServer::Connection::EndProcess() {
- base_.notify(NULL);
- base_.abort(HE_DISCONNECTED);
- return base_.detach();
-}
-
-void
-HttpServer::Connection::Respond(HttpTransaction* transaction) {
- ASSERT(current_ == NULL);
- current_ = transaction;
- if (current_->response()->begin() == current_->response()->end()) {
- current_->response()->set_error(HC_INTERNAL_SERVER_ERROR);
- }
- bool keep_alive = HttpShouldKeepAlive(*transaction->request());
- current_->response()->setHeader(HH_CONNECTION,
- keep_alive ? "Keep-Alive" : "Close",
- false);
- close_ = !HttpShouldKeepAlive(*transaction->response());
- base_.send(current_->response());
-}
-
-void
-HttpServer::Connection::InitiateClose(bool force) {
- if (!signalling_ && (force || (base_.mode() != HM_SEND))) {
- server_->Remove(connection_id_);
- } else {
- close_ = true;
- }
-}
-
-//
-// IHttpNotify Implementation
-//
-
-HttpError
-HttpServer::Connection::onHttpHeaderComplete(bool chunked, size_t& data_size) {
- if (data_size == SIZE_UNKNOWN) {
- data_size = 0;
- }
- return HE_NONE;
-}
-
-void
-HttpServer::Connection::onHttpComplete(HttpMode mode, HttpError err) {
- if (mode == HM_SEND) {
- ASSERT(current_ != NULL);
- signalling_ = true;
- server_->SignalHttpRequestComplete(server_, current_, err);
- signalling_ = false;
- if (close_) {
- // Force a close
- err = HE_DISCONNECTED;
- }
- }
- if (err != HE_NONE) {
- server_->Remove(connection_id_);
- } else if (mode == HM_CONNECT) {
- base_.recv(current_->request());
- } else if (mode == HM_RECV) {
- ASSERT(current_ != NULL);
- // TODO: do we need this?
- //request_.document_->rewind();
- HttpTransaction* transaction = current_;
- current_ = NULL;
- server_->SignalHttpRequest(server_, transaction);
- } else if (mode == HM_SEND) {
- current_->request()->clear(true);
- current_->request()->document.reset(new MemoryStream);
- current_->response()->clear(true);
- base_.recv(current_->request());
- } else {
- ASSERT(false);
- }
-}
-
-void
-HttpServer::Connection::onHttpClosed(HttpError err) {
- UNUSED(err);
- server_->Remove(connection_id_);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// HttpListenServer
-///////////////////////////////////////////////////////////////////////////////
-
-HttpListenServer::HttpListenServer(AsyncSocket* listener)
- : listener_(listener) {
- listener_->SignalReadEvent.connect(this, &HttpListenServer::OnReadEvent);
-}
-
-HttpListenServer::~HttpListenServer() {
-}
-
-int
-HttpListenServer::Listen(const SocketAddress& address) {
- if ((listener_->Bind(address) != SOCKET_ERROR) &&
- (listener_->Listen(5) != SOCKET_ERROR))
- return 0;
- return listener_->GetError();
-}
-
-bool
-HttpListenServer::GetAddress(SocketAddress& address) {
- address = listener_->GetLocalAddress();
- return !address.IsNil();
-}
-
-void
-HttpListenServer::OnReadEvent(AsyncSocket* socket) {
- ASSERT(socket == listener_);
- AsyncSocket* incoming = static_cast<AsyncSocket*>(listener_->Accept(NULL));
- if (incoming)
- HandleConnection(new SocketStream(incoming));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-} // namespace talk_base
diff --git a/talk/base/httpserver.h b/talk/base/httpserver.h
deleted file mode 100755
index a09218c..0000000
--- a/talk/base/httpserver.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_BASE_HTTPSERVER_H__
-#define TALK_BASE_HTTPSERVER_H__
-
-#include <map>
-#include "talk/base/httpbase.h"
-
-namespace talk_base {
-
-class AsyncSocket;
-class HttpServer;
-class SocketAddress;
-
-//////////////////////////////////////////////////////////////////////
-// HttpServer
-//////////////////////////////////////////////////////////////////////
-
-const int HTTP_INVALID_CONNECTION_ID = 0;
-
-class HttpTransaction {
-public:
- HttpTransaction(int connection_id) : connection_id_(connection_id) { }
- ~HttpTransaction() { }
-
- int connection_id() const { return connection_id_; }
-
- HttpRequestData* request() { return &request_; }
- HttpResponseData* response() { return &response_; }
-
-private:
- int connection_id_;
- HttpRequestData request_;
- HttpResponseData response_;
-};
-
-class HttpServer {
-public:
- HttpServer();
- virtual ~HttpServer();
-
- int HandleConnection(StreamInterface* stream);
- // Due to sigslot issues, we can't destroy some streams at an arbitrary time.
- sigslot::signal3<HttpServer*, int, StreamInterface*> SignalConnectionClosed;
-
- // An HTTP request has been made, and is available in the transaction object.
- // Populate the transaction's response, and then return the object via the
- // Respond method. Note that during this time, ownership of the transaction
- // object is transferred, so it may be passed between threads, although
- // respond must be called on the server's active thread.
- sigslot::signal2<HttpServer*, HttpTransaction*> SignalHttpRequest;
- void Respond(HttpTransaction* transaction);
-
- // If you want to know when a request completes, listen to this event.
- sigslot::signal3<HttpServer*, HttpTransaction*, int>
- SignalHttpRequestComplete;
-
- // Stop processing the connection indicated by connection_id.
- // Unless force is true, the server will complete sending a response that is
- // in progress.
- void Close(int connection_id, bool force);
- void CloseAll(bool force);
-
-private:
- class Connection : private IHttpNotify {
- public:
- Connection(int connection_id, HttpServer* server);
- virtual ~Connection();
-
- void BeginProcess(StreamInterface* stream);
- StreamInterface* EndProcess();
-
- void Respond(HttpTransaction* transaction);
- void InitiateClose(bool force);
-
- // IHttpNotify Interface
- virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size);
- virtual void onHttpComplete(HttpMode mode, HttpError err);
- virtual void onHttpClosed(HttpError err);
-
- int connection_id_;
- HttpServer* server_;
- HttpBase base_;
- HttpTransaction* current_;
- bool signalling_, close_;
- };
-
- Connection* Find(int connection_id);
- void Remove(int connection_id);
-
- friend class Connection;
- typedef std::map<int,Connection*> ConnectionMap;
-
- ConnectionMap connections_;
- int next_connection_id_;
-};
-
-//////////////////////////////////////////////////////////////////////
-
-class HttpListenServer : public HttpServer, public sigslot::has_slots<> {
-public:
- HttpListenServer(AsyncSocket* listener);
- virtual ~HttpListenServer();
-
- int Listen(const SocketAddress& address);
- bool GetAddress(SocketAddress& address);
-
-private:
- void OnReadEvent(AsyncSocket* socket);
-
- AsyncSocket* listener_;
-};
-
-//////////////////////////////////////////////////////////////////////
-
-} // namespace talk_base
-
-#endif // TALK_BASE_HTTPSERVER_H__
diff --git a/talk/base/linked_ptr.h b/talk/base/linked_ptr.h
old mode 100755
new mode 100644
index 8d5ce49..a98a367
--- a/talk/base/linked_ptr.h
+++ b/talk/base/linked_ptr.h
@@ -1,4 +1,31 @@
/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
* linked_ptr - simple reference linked pointer
* (like reference counting, just using a linked list of the references
* instead of their count.)
diff --git a/talk/base/linux.cc b/talk/base/linux.cc
new file mode 100644
index 0000000..2061d73
--- /dev/null
+++ b/talk/base/linux.cc
@@ -0,0 +1,219 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+//
+
+#ifdef LINUX
+#include "talk/base/linux.h"
+
+#include <errno.h>
+#include <sys/utsname.h>
+
+#include <cstdio>
+
+#include "talk/base/stringencode.h"
+
+namespace talk_base {
+
+ProcCpuInfo::ProcCpuInfo() {
+}
+
+ProcCpuInfo::~ProcCpuInfo() {
+}
+
+bool ProcCpuInfo::LoadFromSystem() {
+ ConfigParser procfs;
+ if (!procfs.Open("/proc/cpuinfo"))
+ return false;
+ return procfs.Parse(&cpu_info_);
+};
+
+bool ProcCpuInfo::GetNumCpus(int *num) {
+ if (cpu_info_.size() == 0)
+ return false;
+ *num = cpu_info_.size();
+ return true;
+}
+
+bool ProcCpuInfo::GetCpuStringValue(int cpu_id, const std::string& key,
+ std::string *result) {
+ if (cpu_id >= static_cast<int>(cpu_info_.size()))
+ return false;
+ ConfigParser::SimpleMap::iterator iter = cpu_info_[cpu_id].find(key);
+ if (iter == cpu_info_[cpu_id].end())
+ return false;
+ *result = iter->second;
+ return true;
+}
+
+bool ProcCpuInfo::GetCpuIntValue(int cpu_id, const std::string& key,
+ int *result) {
+ if (cpu_id >= static_cast<int>(cpu_info_.size())) {
+ return false;
+ }
+ ConfigParser::SimpleMap::iterator iter = cpu_info_[cpu_id].find(key);
+ if (iter == cpu_info_[cpu_id].end()) {
+ return false;
+ }
+ *result = atoi((iter->second).c_str());
+ return true;
+}
+
+ConfigParser::ConfigParser() {}
+
+ConfigParser::~ConfigParser() {}
+
+bool ConfigParser::Open(const std::string& filename) {
+ FileStream *fs = new FileStream();
+ if (!fs->Open(filename, "r"))
+ return false;
+ instream_.reset(fs);
+ return true;
+}
+
+void ConfigParser::Attach(StreamInterface* stream) {
+ instream_.reset(stream);
+}
+
+bool ConfigParser::Parse(MapVector *key_val_pairs) {
+ // Parses the file and places the found key-value pairs into key_val_pairs.
+ SimpleMap section;
+ while (ParseSection(§ion)) {
+ key_val_pairs->push_back(section);
+ section.clear();
+ }
+ return (!key_val_pairs->empty());
+}
+
+bool ConfigParser::ParseSection(SimpleMap *key_val_pair) {
+ // Parses the next section in the filestream and places the found key-value
+ // pairs into key_val_pair.
+ std::string key, value;
+ while (ParseLine(&key, &value)) {
+ (*key_val_pair)[key] = value;
+ }
+ return (!key_val_pair->empty());
+}
+
+bool ConfigParser::ParseLine(std::string *key, std::string *value) {
+ // Parses the next line in the filestream and places the found key-value
+ // pair into key and val.
+ std::string line;
+ if ((instream_->ReadLine(&line)) == EOF)
+ return false;
+ std::vector<std::string> tokens;
+ if (2 != split(line, ':', &tokens))
+ return false;
+ // Removes whitespace at the end of Key name
+ size_t pos = tokens[0].length() - 1;
+ while ((pos > 0) && isspace(tokens[0][pos]))
+ pos--;
+ tokens[0].erase(pos + 1);
+ // Removes whitespace at the start of value
+ pos = 0;
+ while (pos < tokens[1].length() && isspace(tokens[1][pos]))
+ pos++;
+ tokens[1].erase(0, pos);
+ *key = tokens[0];
+ *value = tokens[1];
+ return true;
+}
+
+static bool ExpectLineFromStream(FileStream *stream,
+ std::string *out) {
+ StreamResult res = stream->ReadLine(out);
+ if (res != SR_SUCCESS) {
+ if (res != SR_EOS) {
+ LOG(LS_ERROR) << "Error when reading from stream";
+ } else {
+ LOG(LS_ERROR) << "Incorrect number of lines in stream";
+ }
+ return false;
+ }
+ return true;
+}
+
+static void ExpectEofFromStream(FileStream *stream) {
+ std::string unused;
+ StreamResult res = stream->ReadLine(&unused);
+ if (res == SR_SUCCESS) {
+ LOG(LS_WARNING) << "Ignoring unexpected extra lines from stream";
+ } else if (res != SR_EOS) {
+ LOG(LS_WARNING) << "Error when checking for extra lines from stream";
+ }
+}
+
+// For caching the lsb_release output (reading it invokes a sub-process and
+// hence is somewhat expensive).
+static std::string lsb_release_string;
+static CriticalSection lsb_release_string_critsec;
+
+std::string ReadLinuxLsbRelease() {
+ CritScope cs(&lsb_release_string_critsec);
+ if (!lsb_release_string.empty()) {
+ // Have cached result from previous call.
+ return lsb_release_string;
+ }
+ // No cached result. Run lsb_release and parse output.
+ POpenStream lsb_release_output;
+ if (!lsb_release_output.Open("lsb_release -idrcs", "r")) {
+ LOG_ERR(LS_ERROR) << "Can't run lsb_release";
+ return lsb_release_string; // empty
+ }
+ // Read in the command's output and build the string.
+ std::ostringstream sstr;
+ std::string line;
+ int wait_status;
+
+ if (!ExpectLineFromStream(&lsb_release_output, &line)) {
+ return lsb_release_string; // empty
+ }
+ sstr << "DISTRIB_ID=" << line;
+
+ if (!ExpectLineFromStream(&lsb_release_output, &line)) {
+ return lsb_release_string; // empty
+ }
+ sstr << " DISTRIB_DESCRIPTION=\"" << line << '"';
+
+ if (!ExpectLineFromStream(&lsb_release_output, &line)) {
+ return lsb_release_string; // empty
+ }
+ sstr << " DISTRIB_RELEASE=" << line;
+
+ if (!ExpectLineFromStream(&lsb_release_output, &line)) {
+ return lsb_release_string; // empty
+ }
+ sstr << " DISTRIB_CODENAME=" << line;
+
+ // Should not be anything left.
+ ExpectEofFromStream(&lsb_release_output);
+
+ lsb_release_output.Close();
+ wait_status = lsb_release_output.GetWaitStatus();
+ if (wait_status == -1 ||
+ !WIFEXITED(wait_status) ||
+ WEXITSTATUS(wait_status) != 0) {
+ LOG(LS_WARNING) << "Unexpected exit status from lsb_release";
+ }
+
+ lsb_release_string = sstr.str();
+
+ return lsb_release_string;
+}
+
+std::string ReadLinuxUname() {
+ struct utsname buf;
+ if (uname(&buf) < 0) {
+ LOG_ERR(LS_ERROR) << "Can't call uname()";
+ return std::string();
+ }
+ std::ostringstream sstr;
+ sstr << buf.sysname << " "
+ << buf.release << " "
+ << buf.version << " "
+ << buf.machine;
+ return sstr.str();
+}
+
+} // namespace talk_base
+
+#endif // LINUX
diff --git a/talk/base/linux.h b/talk/base/linux.h
new file mode 100644
index 0000000..808dc0e
--- /dev/null
+++ b/talk/base/linux.h
@@ -0,0 +1,97 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+
+#ifndef TALK_BASE_LINUX_H_
+#define TALK_BASE_LINUX_H_
+
+#ifdef LINUX
+#include <string>
+#include <map>
+#include <vector>
+#include "talk/base/stream.h"
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////////////
+// ConfigParser parses a FileStream of an ".ini."-type format into a map.
+//////////////////////////////////////////////////////////////////////////////
+
+// Sample Usage:
+// ConfigParser parser;
+// ConfigParser::MapVector key_val_pairs;
+// if (parser.Open(inifile) && parser.Parse(&key_val_pairs)) {
+// for (int section_num=0; i < key_val_pairs.size(); ++section_num) {
+// std::string val1 = key_val_pairs[section_num][key1];
+// std::string val2 = key_val_pairs[section_num][key2];
+// // Do something with valn;
+// }
+// }
+
+class ConfigParser {
+ public:
+ typedef std::map<std::string, std::string> SimpleMap;
+ typedef std::vector<SimpleMap> MapVector;
+
+ ConfigParser();
+ virtual ~ConfigParser();
+
+ virtual bool Open(const std::string& filename);
+ virtual void Attach(StreamInterface* stream);
+ virtual bool Parse(MapVector *key_val_pairs);
+ virtual bool ParseSection(SimpleMap *key_val_pair);
+ virtual bool ParseLine(std::string *key, std::string *value);
+
+ private:
+ scoped_ptr<StreamInterface> instream_;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// ProcCpuInfo reads CPU info from the /proc subsystem on any *NIX platform.
+//////////////////////////////////////////////////////////////////////////////
+
+// Sample Usage:
+// ProcCpuInfo proc_info;
+// int no_of_cpu;
+// if (proc_info.LoadFromSystem()) {
+// std::string out_str;
+// proc_info.GetNumCpus(&no_of_cpu);
+// proc_info.GetCpuStringValue(0, "vendor_id", &out_str);
+// }
+// }
+
+class ProcCpuInfo {
+ public:
+ ProcCpuInfo();
+ virtual ~ProcCpuInfo();
+
+ // Reads the proc subsystem's cpu info into memory. If this fails, this
+ // returns false; if it succeeds, it returns true.
+ virtual bool LoadFromSystem();
+
+ // Obtains the number of CPUs and places the value num.
+ virtual bool GetNumCpus(int *num);
+
+ // Looks for the CPU proc item with the given name for the given CPU number
+ // and places the string value in result.
+ virtual bool GetCpuStringValue(int cpu_id, const std::string& key,
+ std::string *result);
+
+ // Looks for the CPU proc item with the given name for the given CPU number
+ // and places the int value in result.
+ virtual bool GetCpuIntValue(int cpu_id, const std::string& key,
+ int *result);
+
+ private:
+ ConfigParser::MapVector cpu_info_;
+};
+
+// Builds a string containing the info from lsb_release on a single line.
+std::string ReadLinuxLsbRelease();
+
+// Returns the output of "uname".
+std::string ReadLinuxUname();
+
+} // namespace talk_base
+
+#endif // LINUX
+#endif // TALK_BASE_LINUX_H_
diff --git a/talk/base/logging.cc b/talk/base/logging.cc
old mode 100755
new mode 100644
index 2a7fbe3..d632a2c
--- a/talk/base/logging.cc
+++ b/talk/base/logging.cc
@@ -2,41 +2,51 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define snprintf _snprintf
#undef ERROR // wingdi.h
#endif
+#ifdef OSX
+#include <CoreServices/CoreServices.h>
+#elif defined(ANDROID)
+#include <android/log.h>
+static const char kLibjingle[] = "libjingle";
+#endif // OSX || ANDROID
+
#include <iostream>
#include <iomanip>
+#include <vector>
#include "talk/base/logging.h"
#include "talk/base/stream.h"
#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
#include "talk/base/time.h"
namespace talk_base {
@@ -45,8 +55,8 @@
// Constant Labels
/////////////////////////////////////////////////////////////////////////////
-const char * FindLabel(int value, const talk_base::ConstantLabel entries[]) {
- for (int i=0; entries[i].label; ++i) {
+const char * FindLabel(int value, const ConstantLabel entries[]) {
+ for (int i = 0; entries[i].label; ++i) {
if (value == entries[i].value) {
return entries[i].label;
}
@@ -54,18 +64,17 @@
return 0;
}
-std::string ErrorName(int err, const talk_base::ConstantLabel * err_table) {
- const char * value = 0;
- if (err == 0)
- return "No error";
+std::string ErrorName(int err, const ConstantLabel * err_table) {
+ if (err == 0)
+ return "No error";
if (err_table != 0) {
if (const char * value = FindLabel(err, err_table))
return value;
}
-
+
char buffer[16];
- snprintf(buffer, sizeof(buffer), "0x%08lx", err);
+ snprintf(buffer, sizeof(buffer), "0x%08x", err);
return buffer;
}
@@ -73,27 +82,29 @@
// LogMessage
/////////////////////////////////////////////////////////////////////////////
+const int LogMessage::NO_LOGGING = LS_ERROR + 1;
+
#if _DEBUG
static const int LOG_DEFAULT = LS_INFO;
#else // !_DEBUG
static const int LOG_DEFAULT = LogMessage::NO_LOGGING;
#endif // !_DEBUG
+// Global lock for log subsystem, only needed to serialize access to streams_.
+CriticalSection LogMessage::crit_;
+
// By default, release builds don't log, debug builds at info level
int LogMessage::min_sev_ = LOG_DEFAULT;
int LogMessage::dbg_sev_ = LOG_DEFAULT;
-// No file logging by default
-int LogMessage::stream_sev_ = NO_LOGGING;
-
// Don't bother printing context for the ubiquitous INFO log messages
int LogMessage::ctx_sev_ = LS_WARNING;
-// stream_ defaults to NULL
+// The list of logging streams currently configured.
// Note: we explicitly do not clean this up, because of the uncertain ordering
// of destructors at program exit. Let the person who sets the stream trigger
// cleanup by setting to NULL, or let it leak (safe at program exit).
-StreamInterface* LogMessage::stream_;
+LogMessage::StreamList LogMessage::streams_;
// Boolean options default to false (0)
bool LogMessage::thread_, LogMessage::timestamp_;
@@ -101,14 +112,16 @@
// Program start time
uint32 LogMessage::start_ = StartTime();
-// if we're in diagnostic mode, we'll be explicitly set that way. default to false
+// If we're in diagnostic mode, we'll be explicitly set that way; default=false.
bool LogMessage::is_diagnostic_mode_ = false;
LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev,
LogErrorContext err_ctx, int err, const char* module)
: severity_(sev) {
+ // Android's logging facility keeps track of timestamp and thread.
+#ifndef ANDROID
if (timestamp_) {
- uint32 time = TimeDiff(Time(), start_);
+ uint32 time = TimeSince(start_);
print_stream_ << "[" << std::setfill('0') << std::setw(3) << (time / 1000)
<< ":" << std::setw(3) << (time % 1000) << std::setfill(' ')
<< "] ";
@@ -120,6 +133,7 @@
print_stream_ << "[" << std::hex << id << std::dec << "] ";
#endif // WIN32
}
+#endif // !ANDROID
if (severity_ >= ctx_sev_) {
print_stream_ << Describe(sev) << "(" << DescribeFile(file)
@@ -133,7 +147,7 @@
case ERRCTX_ERRNO:
tmp << " " << strerror(err);
break;
- #ifdef WIN32
+#if WIN32
case ERRCTX_HRESULT: {
char msgbuf[256];
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM;
@@ -150,8 +164,18 @@
}
tmp << " " << msgbuf;
}
- break; }
- #endif // WIN32
+ break;
+ }
+#endif // WIN32
+#if OSX
+ case ERRCTX_OSSTATUS: {
+ tmp << " " << nonnull(GetMacOSStatusErrorString(err), "Unknown error");
+ if (const char* desc = GetMacOSStatusCommentString(err)) {
+ tmp << ": " << desc;
+ }
+ break;
+ }
+#endif // OSX
default:
break;
}
@@ -163,34 +187,18 @@
if (!extra_.empty())
print_stream_ << " : " << extra_;
print_stream_ << std::endl;
- const std::string& str = print_stream_.str();
+ const std::string& str = print_stream_.str();
if (severity_ >= dbg_sev_) {
- bool log_to_stderr = true;
-#ifdef WIN32
- static bool debugger_present = (IsDebuggerPresent() != FALSE);
- if (debugger_present) {
- log_to_stderr = false;
- OutputDebugStringA(str.c_str());
- }
- if (log_to_stderr) {
- // This handles dynamically allocated consoles, too.
- if (HANDLE error_handle = ::GetStdHandle(STD_ERROR_HANDLE)) {
- log_to_stderr = false;
- unsigned long written;
- ::WriteFile(error_handle, str.data(), str.size(), &written, 0);
- }
- }
-#endif // WIN32
- if (log_to_stderr) {
- std::cerr << str;
- std::cerr.flush();
- }
+ OutputToDebug(str, severity_);
}
- if (severity_ >= stream_sev_) {
- // If write isn't fully successful, what are we going to do, log it? :)
- stream_->WriteAll(str.data(), str.size(), NULL, NULL);
+ // Must lock streams_ before accessing
+ CritScope cs(&crit_);
+ for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
+ if (severity_ >= it->second) {
+ OutputToStream(it->first, str);
+ }
}
}
@@ -212,14 +220,148 @@
void LogMessage::LogToDebug(int min_sev) {
dbg_sev_ = min_sev;
- min_sev_ = _min(dbg_sev_, stream_sev_);
+ UpdateMinLogSeverity();
}
void LogMessage::LogToStream(StreamInterface* stream, int min_sev) {
- delete stream_;
- stream_ = stream;
- stream_sev_ = (stream_ == 0) ? NO_LOGGING : min_sev;
- min_sev_ = _min(dbg_sev_, stream_sev_);
+ CritScope cs(&crit_);
+ // Discard and delete all previously installed streams
+ for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
+ delete it->first;
+ }
+ streams_.clear();
+ // Install the new stream, if specified
+ if (stream) {
+ AddLogToStream(stream, min_sev);
+ }
+}
+
+int LogMessage::GetLogToStream(StreamInterface* stream) {
+ CritScope cs(&crit_);
+ int sev = NO_LOGGING;
+ for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
+ if (!stream || stream == it->first) {
+ sev = _min(sev, it->second);
+ }
+ }
+ return sev;
+}
+
+void LogMessage::AddLogToStream(StreamInterface* stream, int min_sev) {
+ CritScope cs(&crit_);
+ streams_.push_back(std::make_pair(stream, min_sev));
+ UpdateMinLogSeverity();
+}
+
+void LogMessage::RemoveLogToStream(StreamInterface* stream) {
+ CritScope cs(&crit_);
+ for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
+ if (stream == it->first) {
+ streams_.erase(it);
+ break;
+ }
+ }
+ UpdateMinLogSeverity();
+}
+
+void LogMessage::ConfigureLogging(const char* params, const char* filename) {
+ int current_level = LS_VERBOSE;
+ int debug_level = GetLogToDebug();
+ int file_level = GetLogToStream();
+
+ std::vector<std::string> tokens;
+ split(params, ' ', &tokens);
+
+ for (size_t i = 0; i < tokens.size(); ++i) {
+ if (tokens[i].empty())
+ continue;
+
+ // Logging features
+ if (tokens[i] == "tstamp") {
+ LogTimestamps();
+ } else if (tokens[i] == "thread") {
+ LogThreads();
+
+ // Logging levels
+ } else if (tokens[i] == "sensitive") {
+ current_level = LS_SENSITIVE;
+ } else if (tokens[i] == "verbose") {
+ current_level = LS_VERBOSE;
+ } else if (tokens[i] == "info") {
+ current_level = LS_INFO;
+ } else if (tokens[i] == "warning") {
+ current_level = LS_WARNING;
+ } else if (tokens[i] == "error") {
+ current_level = LS_ERROR;
+ } else if (tokens[i] == "none") {
+ current_level = NO_LOGGING;
+
+ // Logging targets
+ } else if (tokens[i] == "file") {
+ file_level = current_level;
+ } else if (tokens[i] == "debug") {
+ debug_level = current_level;
+ }
+ }
+
+#ifdef WIN32
+ if ((NO_LOGGING != debug_level) && !::IsDebuggerPresent()) {
+ // First, attempt to attach to our parent's console... so if you invoke
+ // from the command line, we'll see the output there. Otherwise, create
+ // our own console window.
+ // Note: These methods fail if a console already exists, which is fine.
+ bool success = false;
+ typedef BOOL (WINAPI* PFN_AttachConsole)(DWORD);
+ if (HINSTANCE kernel32 = ::LoadLibrary(L"kernel32.dll")) {
+ // AttachConsole is defined on WinXP+.
+ if (PFN_AttachConsole attach_console = reinterpret_cast<PFN_AttachConsole>
+ (::GetProcAddress(kernel32, "AttachConsole"))) {
+ success = (FALSE != attach_console(ATTACH_PARENT_PROCESS));
+ }
+ ::FreeLibrary(kernel32);
+ }
+ if (!success) {
+ ::AllocConsole();
+ }
+ }
+#endif // WIN32
+
+ scoped_ptr<FileStream> stream;
+ if (NO_LOGGING != file_level) {
+ stream.reset(new FileStream);
+ if (!stream->Open(filename, "wb") || !stream->DisableBuffering()) {
+ stream.reset();
+ }
+ }
+
+ LogToDebug(debug_level);
+ LogToStream(stream.release(), file_level);
+}
+
+int LogMessage::ParseLogSeverity(const std::string& value) {
+ int level = NO_LOGGING;
+ if (value == "LS_SENSITIVE") {
+ level = LS_SENSITIVE;
+ } else if (value == "LS_VERBOSE") {
+ level = LS_VERBOSE;
+ } else if (value == "LS_INFO") {
+ level = LS_INFO;
+ } else if (value == "LS_WARNING") {
+ level = LS_WARNING;
+ } else if (value == "LS_ERROR") {
+ level = LS_ERROR;
+ } else if (isdigit(value[0])) {
+ level = atoi(value.c_str()); // NOLINT
+ }
+ return level;
+}
+
+void LogMessage::UpdateMinLogSeverity() {
+ int min_sev = dbg_sev_;
+ for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
+ min_sev = _min(dbg_sev_, it->second);
+ }
+ min_sev_ = min_sev;
}
const char* LogMessage::Describe(LoggingSeverity sev) {
@@ -242,17 +384,108 @@
return (end1 > end2) ? end1 + 1 : end2 + 1;
}
+void LogMessage::OutputToDebug(const std::string& str,
+ LoggingSeverity severity) {
+ bool log_to_stderr = true;
+#if defined(OSX) && (!defined(DEBUG) || defined(NDEBUG))
+ // On the Mac, all stderr output goes to the Console log and causes clutter.
+ // So in opt builds, don't log to stderr unless the user specifically sets
+ // a preference to do so.
+ CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault,
+ "logToStdErr",
+ kCFStringEncodingUTF8);
+ CFStringRef domain = CFBundleGetIdentifier(CFBundleGetMainBundle());
+ if (key != NULL && domain != NULL) {
+ Boolean exists_and_is_valid;
+ Boolean should_log =
+ CFPreferencesGetAppBooleanValue(key, domain, &exists_and_is_valid);
+ // If the key doesn't exist or is invalid or is false, we will not log to
+ // stderr.
+ log_to_stderr = exists_and_is_valid && should_log;
+ }
+ if (key != NULL) {
+ CFRelease(key);
+ }
+#endif
+#ifdef WIN32
+ // Always log to the debugger.
+ // Perhaps stderr should be controlled by a preference, as on Mac?
+ OutputDebugStringA(str.c_str());
+ if (log_to_stderr) {
+ // This handles dynamically allocated consoles, too.
+ if (HANDLE error_handle = ::GetStdHandle(STD_ERROR_HANDLE)) {
+ log_to_stderr = false;
+ unsigned long written; // NOLINT
+ ::WriteFile(error_handle, str.data(), str.size(), &written, 0);
+ }
+ }
+#endif // WIN32
+#ifdef ANDROID
+ // Android's logging facility uses severity to log messages but we
+ // need to map libjingle's severity levels to Android ones first.
+ // Also write to stderr which maybe available to executable started
+ // from the shell.
+ int prio;
+ switch (severity) {
+ case LS_SENSITIVE:
+ __android_log_write(ANDROID_LOG_INFO, kLibjingle, "SENSITIVE");
+ return;
+ case LS_VERBOSE:
+ prio = ANDROID_LOG_VERBOSE;
+ break;
+ case LS_INFO:
+ prio = ANDROID_LOG_INFO;
+ break;
+ case LS_WARNING:
+ prio = ANDROID_LOG_WARN;
+ break;
+ case LS_ERROR:
+ prio = ANDROID_LOG_ERROR;
+ break;
+ default:
+ prio = ANDROID_LOG_UNKNOWN;
+ }
+ // Use the size of the string in the format (str may have \0 in the middle).
+ __android_log_print(prio, kLibjingle, "%.*s", str.size(), str.c_str());
+#endif // ANDROID
+ if (log_to_stderr) {
+ std::cerr << str;
+ std::cerr.flush();
+ }
+}
+
+void LogMessage::OutputToStream(StreamInterface* stream,
+ const std::string& str) {
+ // If write isn't fully successful, what are we going to do, log it? :)
+ stream->WriteAll(str.data(), str.size(), NULL, NULL);
+}
+
//////////////////////////////////////////////////////////////////////
// Logging Helpers
//////////////////////////////////////////////////////////////////////
void LogMultiline(LoggingSeverity level, const char* label, bool input,
- const char * data, size_t len, bool hex_mode,
+ const void* data, size_t len, bool hex_mode,
LogMultilineState* state) {
if (!LOG_CHECK_LEVEL_V(level))
return;
const char * direction = (input ? " << " : " >> ");
+
+ // NULL data means to flush our count of unprintable characters.
+ if (!data) {
+ if (state && state->unprintable_count_[input]) {
+ LOG_V(level) << label << direction << "## "
+ << state->unprintable_count_[input]
+ << " consecutive unprintable ##";
+ state->unprintable_count_[input] = 0;
+ }
+ return;
+ }
+
+ // The ctype classification functions want unsigned chars.
+ const unsigned char* udata = static_cast<const unsigned char*>(data);
+
if (hex_mode) {
const size_t LINE_SIZE = 24;
char hex_line[LINE_SIZE * 9 / 4 + 2], asc_line[LINE_SIZE + 1];
@@ -260,74 +493,78 @@
memset(asc_line, ' ', sizeof(asc_line));
memset(hex_line, ' ', sizeof(hex_line));
size_t line_len = _min(len, LINE_SIZE);
- for (size_t i=0; i<line_len; ++i) {
- unsigned char ch = static_cast<unsigned char>(data[i]);
- asc_line[i] = isprint(ch) ? data[i] : '.';
+ for (size_t i = 0; i < line_len; ++i) {
+ unsigned char ch = udata[i];
+ asc_line[i] = isprint(ch) ? ch : '.';
hex_line[i*2 + i/4] = hex_encode(ch >> 4);
hex_line[i*2 + i/4 + 1] = hex_encode(ch & 0xf);
}
asc_line[sizeof(asc_line)-1] = 0;
hex_line[sizeof(hex_line)-1] = 0;
- LOG_V(level) << label << direction
+ LOG_V(level) << label << direction
<< asc_line << " " << hex_line << " ";
- data += line_len;
+ udata += line_len;
len -= line_len;
}
return;
}
- size_t consecutive_unprintable = state ? state->unprintable_count_ : 0;
+ size_t consecutive_unprintable = state ? state->unprintable_count_[input] : 0;
- std::string str(data, len);
- while (!str.empty()) {
- size_t line_end_length = 0;
- std::string::size_type pos = str.find('\n');
- std::string substr = str;
- if (pos == std::string::npos) {
- substr = str;
- str.clear();
- } else if ((pos > 0) && (str[pos-1] == '\r')) {
- line_end_length = 2;
- substr = str.substr(0, pos - 1);
- str = str.substr(pos + 1);
+ const unsigned char* end = udata + len;
+ while (udata < end) {
+ const unsigned char* line = udata;
+ const unsigned char* end_of_line = strchrn<unsigned char>(udata,
+ end - udata,
+ '\n');
+ if (!end_of_line) {
+ udata = end_of_line = end;
} else {
- line_end_length = 1;
- substr = str.substr(0, pos);
- str = str.substr(pos + 1);
+ udata = end_of_line + 1;
}
- // Any lines which consist entirely of ascii characters are printed. Other
- // lines are considered binary, and we just count the number of bytes.
- // This algorithm should be very compatible with HTTP transfers of binary
- // data.
- bool is_ascii = true, is_whitespace = true;
- for (size_t i=0; i<substr.size(); ++i) {
- unsigned char ch = static_cast<unsigned char>(substr[i]);
- if (!isprint(ch)) {
- is_ascii = false;
- break;
- } else if (!isspace(static_cast<unsigned char>(ch))) {
- is_whitespace = false;
+ bool is_printable = true;
+
+ // If we are in unprintable mode, we need to see a line of at least
+ // kMinPrintableLine characters before we'll switch back.
+ const ptrdiff_t kMinPrintableLine = 4;
+ if (consecutive_unprintable && ((end_of_line - line) < kMinPrintableLine)) {
+ is_printable = false;
+ } else {
+ // Determine if the line contains only whitespace and printable
+ // characters.
+ bool is_entirely_whitespace = true;
+ for (const unsigned char* pos = line; pos < end_of_line; ++pos) {
+ if (isspace(*pos))
+ continue;
+ is_entirely_whitespace = false;
+ if (!isprint(*pos)) {
+ is_printable = false;
+ break;
+ }
+ }
+ // Treat an empty line following unprintable data as unprintable.
+ if (consecutive_unprintable && is_entirely_whitespace) {
+ is_printable = false;
}
}
- // Treat an empty line following binary data as binary.
- if (is_whitespace && consecutive_unprintable) {
- is_ascii = false;
- }
- if (!is_ascii) {
- consecutive_unprintable += substr.size() + line_end_length;
- }
- if (consecutive_unprintable && (is_ascii || str.empty())) {
- LOG_V(level) << label << direction << "## " << consecutive_unprintable
- << " consecutive unprintable ##";
- }
- if (is_ascii) {
- consecutive_unprintable = 0;
- } else {
+ if (!is_printable) {
+ consecutive_unprintable += (udata - line);
continue;
}
-
+ // Print out the current line, but prefix with a count of prior unprintable
+ // characters.
+ if (consecutive_unprintable) {
+ LOG_V(level) << label << direction << "## " << consecutive_unprintable
+ << " consecutive unprintable ##";
+ consecutive_unprintable = 0;
+ }
+ // Strip off trailing whitespace.
+ while ((end_of_line > line) && isspace(*(end_of_line-1))) {
+ --end_of_line;
+ }
// Filter out any private data
+ std::string substr(reinterpret_cast<const char*>(line), end_of_line - line);
std::string::size_type pos_private = substr.find("Email");
if (pos_private == std::string::npos) {
pos_private = substr.find("Passwd");
@@ -340,10 +577,10 @@
}
if (state) {
- state->unprintable_count_ = consecutive_unprintable;
+ state->unprintable_count_[input] = consecutive_unprintable;
}
}
//////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/logging.h b/talk/base/logging.h
old mode 100755
new mode 100644
index a4686b7..ac69b7b
--- a/talk/base/logging.h
+++ b/talk/base/logging.h
@@ -2,48 +2,75 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// LOG(...) an ostream target that can be used to send formatted
// output to a variety of logging targets, such as debugger console, stderr,
// file, or any StreamInterface.
-// The severity level passed as the first argument to the the LOGging
+// The severity level passed as the first argument to the LOGging
// functions is used as a filter, to limit the verbosity of the logging.
// Static members of LogMessage documented below are used to control the
// verbosity and target of the output.
// There are several variations on the LOG macro which facilitate logging
// of common error conditions, detailed below.
-#ifndef TALK_BASE_LOGGING_H__
-#define TALK_BASE_LOGGING_H__
+// LOG(sev) logs the given stream at severity "sev", which must be a
+// compile-time constant of the LoggingSeverity type, without the namespace
+// prefix.
+// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity
+// type (basically, it just doesn't prepend the namespace).
+// LOG_F(sev) Like LOG(), but includes the name of the current function.
+// LOG_GLE(M)(sev [, mod]) attempt to add a string description of the
+// HRESULT returned by GetLastError. The "M" variant allows searching of a
+// DLL's string table for the error description.
+// LOG_ERRNO(sev) attempts to add a string description of an errno-derived
+// error. errno and associated facilities exist on both Windows and POSIX,
+// but on Windows they only apply to the C/C++ runtime.
+// LOG_ERR(sev) is an alias for the platform's normal error system, i.e. _GLE on
+// Windows and _ERRNO on POSIX.
+// (The above three also all have _EX versions that let you specify the error
+// code, rather than using the last one.)
+// LOG_E(sev, ctx, err, ...) logs a detailed error interpreted using the
+// specified context.
+// LOG_CHECK_LEVEL(sev) (and LOG_CHECK_LEVEL_V(sev)) can be used as a test
+// before performing expensive or sensitive operations whose sole purpose is
+// to output logging data at the desired level.
+// Lastly, PLOG(sev, err) is an alias for LOG_ERR_EX.
+
+#ifndef TALK_BASE_LOGGING_H_
+#define TALK_BASE_LOGGING_H_
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h" // NOLINT
#endif
+#include <list>
#include <sstream>
+#include <string>
+#include <utility>
#include "talk/base/basictypes.h"
+#include "talk/base/criticalsection.h"
namespace talk_base {
@@ -66,7 +93,7 @@
struct ConstantLabel { int value; const char * label; };
#define KLABEL(x) { x, #x }
-#define TLABEL(x,y) { x, y }
+#define TLABEL(x, y) { x, y }
#define LASTLABEL { 0, 0 }
const char * FindLabel(int value, const ConstantLabel entries[]);
@@ -90,12 +117,22 @@
LERROR = LS_ERROR };
// LogErrorContext assists in interpreting the meaning of an error value.
-// ERRCTX_ERRNO: the value was read from global 'errno'
-// ERRCTX_HRESULT: the value is a Windows HRESULT
-enum LogErrorContext { ERRCTX_NONE, ERRCTX_ERRNO, ERRCTX_HRESULT };
+enum LogErrorContext {
+ ERRCTX_NONE,
+ ERRCTX_ERRNO, // System-local errno
+ ERRCTX_HRESULT, // Windows HRESULT
+ ERRCTX_OSSTATUS, // MacOS OSStatus
+
+ // Abbreviations for LOG_E macro
+ ERRCTX_EN = ERRCTX_ERRNO, // LOG_E(sev, EN, x)
+ ERRCTX_HR = ERRCTX_HRESULT, // LOG_E(sev, HR, x)
+ ERRCTX_OS = ERRCTX_OSSTATUS, // LOG_E(sev, OS, x)
+};
class LogMessage {
public:
+ static const int NO_LOGGING;
+
LogMessage(const char* file, int line, LoggingSeverity sev,
LogErrorContext err_ctx = ERRCTX_NONE, int err = 0,
const char* module = NULL);
@@ -104,8 +141,6 @@
static inline bool Loggable(LoggingSeverity sev) { return (sev >= min_sev_); }
std::ostream& stream() { return print_stream_; }
- enum { NO_LOGGING = LS_ERROR + 1 };
-
// These are attributes which apply to all logging channels
// LogContext: Display the file and line number of the message
static void LogContext(int min_sev);
@@ -123,10 +158,18 @@
// Debug: Debug console on Windows, otherwise stderr
static void LogToDebug(int min_sev);
static int GetLogToDebug() { return dbg_sev_; }
+
// Stream: Any non-blocking stream interface. LogMessage takes ownership of
- // the stream.
+ // the stream. Multiple streams may be specified by using AddLogToStream.
+ // LogToStream is retained for backwards compatibility; when invoked, it
+ // will discard any previously set streams and install the specified stream.
+ // GetLogToStream gets the severity for the specified stream, of if none
+ // is specified, the minimum stream severity.
+ // RemoveLogToStream removes the specified stream, without destroying it.
static void LogToStream(StreamInterface* stream, int min_sev);
- static int GetLogToStream() { return stream_sev_; }
+ static int GetLogToStream(StreamInterface* stream = NULL);
+ static void AddLogToStream(StreamInterface* stream, int min_sev);
+ static void RemoveLogToStream(StreamInterface* stream);
// Testing against MinLogSeverity allows code to avoid potentially expensive
// logging operations by pre-checking the logging level.
@@ -135,11 +178,28 @@
static void SetDiagnosticMode(bool f) { is_diagnostic_mode_ = f; }
static bool IsDiagnosticMode() { return is_diagnostic_mode_; }
+ // Parses the provided parameter stream to configure the options above.
+ // Useful for configuring logging from the command line. If file logging
+ // is enabled, it is output to the specified filename.
+ static void ConfigureLogging(const char* params, const char* filename);
+
+ // Convert the string to a LS_ value; also accept numeric values.
+ static int ParseLogSeverity(const std::string& value);
+
private:
+ typedef std::list<std::pair<StreamInterface*, int> > StreamList;
+
+ // Updates min_sev_ appropriately when debug sinks change.
+ static void UpdateMinLogSeverity();
+
// These assist in formatting some parts of the debug output.
static const char* Describe(LoggingSeverity sev);
static const char* DescribeFile(const char* file);
+ // These write out the actual log messages.
+ static void OutputToDebug(const std::string& msg, LoggingSeverity severity_);
+ static void OutputToStream(StreamInterface* stream, const std::string& msg);
+
// The ostream that buffers the formatted message before output
std::ostringstream print_stream_;
@@ -150,15 +210,18 @@
// the message before output.
std::string extra_;
- // dbg_sev_ and stream_sev_ are the thresholds for those output targets
+ // Global lock for the logging subsystem
+ static CriticalSection crit_;
+
+ // dbg_sev_ is the thresholds for those output targets
// min_sev_ is the minimum (most verbose) of those levels, and is used
// as a short-circuit in the logging macros to identify messages that won't
// be logged.
// ctx_sev_ is the minimum level at which file context is displayed
- static int min_sev_, dbg_sev_, stream_sev_, ctx_sev_;
+ static int min_sev_, dbg_sev_, ctx_sev_;
- // The output stream, if any
- static StreamInterface * stream_;
+ // The output streams and their associated severities
+ static StreamList streams_;
// Flags for formatting options
static bool thread_, timestamp_;
@@ -177,15 +240,17 @@
//////////////////////////////////////////////////////////////////////
class LogMultilineState {
-public:
- size_t unprintable_count_;
- LogMultilineState() : unprintable_count_(0) { }
+ public:
+ size_t unprintable_count_[2];
+ LogMultilineState() {
+ unprintable_count_[0] = unprintable_count_[1] = 0;
+ }
};
// When possible, pass optional state variable to track various data across
// multiple calls to LogMultiline. Otherwise, pass NULL.
void LogMultiline(LoggingSeverity level, const char* label, bool input,
- const char * data, size_t len, bool hex_mode,
+ const void* data, size_t len, bool hex_mode,
LogMultilineState* state);
//////////////////////////////////////////////////////////////////////
@@ -204,22 +269,43 @@
#ifndef LOG
#if LOGGING
+// The following non-obvious technique for implementation of a
+// conditional log stream was stolen from google3/base/logging.h.
+
+// This class is used to explicitly ignore values in the conditional
+// logging macros. This avoids compiler warnings like "value computed
+// is not used" and "statement has no effect".
+
+class LogMessageVoidify {
+ public:
+ LogMessageVoidify() { }
+ // This has to be an operator with a precedence lower than << but
+ // higher than ?:
+ void operator&(std::ostream&) { }
+};
+
+#define LOG_SEVERITY_PRECONDITION(sev) \
+ !(talk_base::LogMessage::Loggable(sev)) \
+ ? (void) 0 \
+ : talk_base::LogMessageVoidify() &
+
#define LOG(sev) \
- if (talk_base::LogMessage::Loggable(talk_base::sev)) \
+ LOG_SEVERITY_PRECONDITION(talk_base::sev) \
talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev).stream()
// The _V version is for when a variable is passed in. It doesn't do the
// namespace concatination.
#define LOG_V(sev) \
- if (talk_base::LogMessage::Loggable(sev)) \
+ LOG_SEVERITY_PRECONDITION(sev) \
talk_base::LogMessage(__FILE__, __LINE__, sev).stream()
// The _F version prefixes the message with the current function name.
+#if defined(__GNUC__) && defined(_DEBUG)
+#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
+#else
#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
+#endif
-// LOG_CHECK_LEVEL can be used as a test before performing expensive or
-// sensitive operations whose sole purpose is to output logging data at the
-// desired level.
#define LOG_CHECK_LEVEL(sev) \
talk_base::LogCheckLevel(talk_base::sev)
#define LOG_CHECK_LEVEL_V(sev) \
@@ -228,34 +314,11 @@
return (LogMessage::GetMinLogSeverity() <= sev);
}
-// PLOG and LOG_ERR attempt to provide a string description of an errno derived
-// error. LOG_ERR reads errno directly, so care must be taken to call it before
-// errno is reset.
-#define PLOG(sev, err) \
- if (talk_base::LogMessage::Loggable(talk_base::sev)) \
+#define LOG_E(sev, ctx, err, ...) \
+ LOG_SEVERITY_PRECONDITION(talk_base::sev) \
talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \
- talk_base::ERRCTX_ERRNO, err).stream()
-#define LOG_ERR(sev) \
- if (talk_base::LogMessage::Loggable(sev)) \
- talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \
- talk_base::ERRCTX_ERRNO, errno).stream()
-
-// LOG_GLE(M) attempt to provide a string description of the HRESULT returned
-// by GetLastError. The second variant allows searching of a dll's string
-// table for the error description.
-#ifdef WIN32
-#define LOG_GLE(sev) \
- if (talk_base::LogMessage::Loggable(talk_base::sev)) \
- talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \
- talk_base::ERRCTX_HRESULT, GetLastError()).stream()
-#define LOG_GLEM(sev, mod) \
- if (talk_base::LogMessage::Loggable(talk_base::sev)) \
- talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \
- talk_base::ERRCTX_HRESULT, GetLastError(), mod) \
- .stream()
-#endif // WIN32
-
-// TODO: Add an "assert" wrapper that logs in the same manner.
+ talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \
+ .stream()
#else // !LOGGING
@@ -271,26 +334,48 @@
false
#define LOG_CHECK_LEVEL_V(sev) \
false
-#define PLOG(sev, err) \
- while (false) talk_base::LogMessage(NULL, 0, talk_base::sev, \
- talk_base::ERRCTX_ERRNO, 0).stream()
-#define LOG_ERR(sev) \
- while (false) talk_base::LogMessage(NULL, 0, talk_base::sev, \
- talk_base::ERRCTX_ERRNO, 0).stream()
-#ifdef WIN32
-#define LOG_GLE(sev) \
- while (false) talk_base::LogMessage(NULL, 0, talk_base::sev, \
- talk_base::ERRCTX_HRESULT, 0).stream()
-#define LOG_GLEM(sev, mod) \
- while (false) talk_base::LogMessage(NULL, 0, talk_base::sev, \
- talk_base::ERRCTX_HRESULT, 0).stream()
-#endif // WIN32
+
+#define LOG_E(sev, ctx, err, ...) \
+ while (false) talk_base::LogMessage(__FILE__, __LINE__, talk_base::sev, \
+ talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \
+ .stream()
#endif // !LOGGING
+
+#define LOG_ERRNO_EX(sev, err) \
+ LOG_E(sev, ERRNO, err)
+#define LOG_ERRNO(sev) \
+ LOG_ERRNO_EX(sev, errno)
+
+#ifdef WIN32
+#define LOG_GLE_EX(sev, err) \
+ LOG_E(sev, HRESULT, err)
+#define LOG_GLE(sev) \
+ LOG_GLE_EX(sev, GetLastError())
+#define LOG_GLEM(sev, mod) \
+ LOG_E(sev, HRESULT, GetLastError(), mod)
+#define LOG_ERR_EX(sev, err) \
+ LOG_GLE_EX(sev, err)
+#define LOG_ERR(sev) \
+ LOG_GLE(sev)
+#define LAST_SYSTEM_ERROR \
+ (::GetLastError())
+#elif POSIX
+#define LOG_ERR_EX(sev, err) \
+ LOG_ERRNO_EX(sev, err)
+#define LOG_ERR(sev) \
+ LOG_ERRNO(sev)
+#define LAST_SYSTEM_ERROR \
+ (errno)
+#endif // WIN32
+
+#define PLOG(sev, err) \
+ LOG_ERR_EX(sev, err)
+
+// TODO(?): Add an "assert" wrapper that logs in the same manner.
+
#endif // LOG
-//////////////////////////////////////////////////////////////////////
+} // namespace talk_base
-} // talk_base
-
-#endif // TALK_BASE_LOGGING_H__
+#endif // TALK_BASE_LOGGING_H_
diff --git a/talk/base/macconversion.cc b/talk/base/macconversion.cc
new file mode 100644
index 0000000..4654e53
--- /dev/null
+++ b/talk/base/macconversion.cc
@@ -0,0 +1,176 @@
+/*
+ * libjingle
+ * Copyright 2004--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef OSX
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "talk/base/logging.h"
+#include "talk/base/macconversion.h"
+
+bool p_convertHostCFStringRefToCPPString(
+ const CFStringRef cfstr, std::string& cppstr) {
+ bool result = false;
+
+ // First this must be non-null,
+ if (NULL != cfstr) {
+ // it must actually *be* a CFString, and not something just masquerading
+ // as one,
+ if (CFGetTypeID(cfstr) == CFStringGetTypeID()) {
+ // and we must be able to get the characters out of it.
+ // (The cfstr owns this buffer; it came from somewhere else,
+ // so someone else gets to take care of getting rid of the cfstr,
+ // and then this buffer will go away automatically.)
+ unsigned length = CFStringGetLength(cfstr);
+ char* buf = new char[1 + length];
+ if (CFStringGetCString(cfstr, buf, 1 + length, kCFStringEncodingASCII)) {
+ if (strlen(buf) == length) {
+ cppstr.assign(buf);
+ result = true;
+ }
+ }
+ delete [] buf;
+ }
+ }
+
+ return result;
+}
+
+bool p_convertCFNumberToInt(CFNumberRef cfn, int* i) {
+ bool converted = false;
+
+ // It must not be null.
+ if (NULL != cfn) {
+ // It must actually *be* a CFNumber and not something just masquerading
+ // as one.
+ if (CFGetTypeID(cfn) == CFNumberGetTypeID()) {
+ CFNumberType ntype = CFNumberGetType(cfn);
+ switch (ntype) {
+ case kCFNumberSInt8Type:
+ SInt8 sint8;
+ converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint8));
+ if (converted) *i = static_cast<int>(sint8);
+ break;
+ case kCFNumberSInt16Type:
+ SInt16 sint16;
+ converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint16));
+ if (converted) *i = static_cast<int>(sint16);
+ break;
+ case kCFNumberSInt32Type:
+ SInt32 sint32;
+ converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint32));
+ if (converted) *i = static_cast<int>(sint32);
+ break;
+ case kCFNumberSInt64Type:
+ SInt64 sint64;
+ converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint64));
+ if (converted) *i = static_cast<int>(sint64);
+ break;
+ case kCFNumberFloat32Type:
+ Float32 float32;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&float32));
+ if (converted) *i = static_cast<int>(float32);
+ break;
+ case kCFNumberFloat64Type:
+ Float64 float64;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&float64));
+ if (converted) *i = static_cast<int>(float64);
+ break;
+ case kCFNumberCharType:
+ char charvalue;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&charvalue));
+ if (converted) *i = static_cast<int>(charvalue);
+ break;
+ case kCFNumberShortType:
+ short shortvalue;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&shortvalue));
+ if (converted) *i = static_cast<int>(shortvalue);
+ break;
+ case kCFNumberIntType:
+ int intvalue;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&intvalue));
+ if (converted) *i = static_cast<int>(intvalue);
+ break;
+ case kCFNumberLongType:
+ long longvalue;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&longvalue));
+ if (converted) *i = static_cast<int>(longvalue);
+ break;
+ case kCFNumberLongLongType:
+ long long llvalue;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&llvalue));
+ if (converted) *i = static_cast<int>(llvalue);
+ break;
+ case kCFNumberFloatType:
+ float floatvalue;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&floatvalue));
+ if (converted) *i = static_cast<int>(floatvalue);
+ break;
+ case kCFNumberDoubleType:
+ double doublevalue;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&doublevalue));
+ if (converted) *i = static_cast<int>(doublevalue);
+ break;
+ case kCFNumberCFIndexType:
+ CFIndex cfindex;
+ converted = CFNumberGetValue(cfn, ntype,
+ static_cast<void*>(&cfindex));
+ if (converted) *i = static_cast<int>(cfindex);
+ break;
+ default:
+ LOG(LS_ERROR) << "got unknown type.";
+ break;
+ }
+ }
+ }
+
+ return converted;
+}
+
+bool p_isCFNumberTrue(CFNumberRef cfn) {
+ // We assume it's false until proven otherwise.
+ bool result = false;
+ int asInt;
+ bool converted = p_convertCFNumberToInt(cfn, &asInt);
+
+ if (converted && (0 != asInt)) {
+ result = true;
+ }
+
+ return result;
+}
+
+#endif // OSX
diff --git a/talk/base/macconversion.h b/talk/base/macconversion.h
new file mode 100644
index 0000000..a401cab
--- /dev/null
+++ b/talk/base/macconversion.h
@@ -0,0 +1,56 @@
+/*
+ * libjingle
+ * Copyright 2004--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_MACCONVERSION_H_
+#define TALK_BASE_MACCONVERSION_H_
+
+#ifdef OSX
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <string>
+
+// given a CFStringRef, attempt to convert it to a C++ string.
+// returns true if it succeeds, false otherwise.
+// We can safely assume, given our context, that the string is
+// going to be in ASCII, because it will either be an IP address,
+// or a domain name, which is guaranteed to be ASCII-representable.
+bool p_convertHostCFStringRefToCPPString(const CFStringRef cfstr,
+ std::string& cppstr);
+
+// Convert the CFNumber to an integer, putting the integer in the location
+// given, and returhing true, if the conversion succeeds.
+// If given a NULL or a non-CFNumber, returns false.
+// This is pretty aggresive about trying to convert to int.
+bool p_convertCFNumberToInt(CFNumberRef cfn, int* i);
+
+// given a CFNumberRef, determine if it represents a true value.
+bool p_isCFNumberTrue(CFNumberRef cfn);
+
+#endif // OSX
+
+#endif // TALK_BASE_MACCONVERSION_H_
diff --git a/talk/base/macutils.cc b/talk/base/macutils.cc
new file mode 100644
index 0000000..69a2f5d
--- /dev/null
+++ b/talk/base/macutils.cc
@@ -0,0 +1,156 @@
+/*
+ * libjingle
+ * Copyright 2007--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sstream>
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/macutils.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/stringutils.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ToUtf8(const CFStringRef str16, std::string* str8) {
+ if ((NULL == str16) || (NULL == str8))
+ return false;
+ size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
+ kCFStringEncodingUTF8)
+ + 1;
+ scoped_array<char> buffer(new char[maxlen]);
+ if (!buffer.get()
+ || !CFStringGetCString(str16, buffer.get(), maxlen,
+ kCFStringEncodingUTF8))
+ return false;
+ str8->assign(buffer.get());
+ return true;
+}
+
+bool ToUtf16(const std::string& str8, CFStringRef* str16) {
+ if (NULL == str16)
+ return false;
+ *str16 = CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8*>(str8.data()),
+ str8.length(), kCFStringEncodingUTF8,
+ false);
+ return (NULL != *str16);
+}
+
+void DecodeFourChar(UInt32 fc, std::string* out) {
+ std::stringstream ss;
+ ss << '\'';
+ bool printable = true;
+ for (int i = 3; i >= 0; --i) {
+ char ch = (fc >> (8 * i)) & 0xFF;
+ if (isprint(static_cast<unsigned char>(ch))) {
+ ss << ch;
+ } else {
+ printable = false;
+ break;
+ }
+ }
+ if (printable) {
+ ss << '\'';
+ } else {
+ ss.str("");
+ ss << "0x" << std::hex << fc;
+ }
+ out->append(ss.str());
+}
+
+std::string DecodeEvent(EventRef event) {
+ std::string str;
+ DecodeFourChar(::GetEventClass(event), &str);
+ str.push_back(':');
+ DecodeFourChar(::GetEventKind(event), &str);
+ return str;
+}
+
+static bool GetGestalt(OSType ostype, int* value) {
+ ASSERT(NULL != value);
+ SInt32 native_value;
+ OSStatus result = Gestalt(ostype, &native_value);
+ if (noErr == result) {
+ *value = native_value;
+ return true;
+ }
+ std::string str;
+ DecodeFourChar(ostype, &str);
+ LOG_E(LS_ERROR, OS, result) << "Gestalt(" << str << ")";
+ return false;
+}
+
+bool GetOSVersion(int* major, int* minor, int* bugfix) {
+ ASSERT(major && minor && bugfix);
+ if (!GetGestalt(gestaltSystemVersion, major))
+ return false;
+ if (*major < 0x1040) {
+ *bugfix = *major & 0xF;
+ *minor = (*major >> 4) & 0xF;
+ *major = (*major >> 8);
+ return true;
+ }
+ return GetGestalt(gestaltSystemVersionMajor, major)
+ && GetGestalt(gestaltSystemVersionMinor, minor)
+ && GetGestalt(gestaltSystemVersionBugFix, bugfix);
+}
+
+MacOSVersionName GetOSVersionName() {
+ int major = 0, minor = 0, bugfix = 0;
+ if (!GetOSVersion(&major, &minor, &bugfix))
+ return kMacOSUnknown;
+ if (major > 10)
+ return kMacOSNewer;
+ if ((major < 10) || (minor < 3))
+ return kMacOSOlder;
+ switch (minor) {
+ case 3:
+ return kMacOSPanther;
+ case 4:
+ return kMacOSTiger;
+ case 5:
+ return kMacOSLeopard;
+ }
+ return kMacOSNewer;
+}
+
+bool GetQuickTimeVersion(std::string* out) {
+ int ver;
+ if (!GetGestalt(gestaltQuickTimeVersion, &ver))
+ return false;
+
+ std::stringstream ss;
+ ss << std::hex << ver;
+ *out = ss.str();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/macutils.h b/talk/base/macutils.h
new file mode 100644
index 0000000..1cd64ab
--- /dev/null
+++ b/talk/base/macutils.h
@@ -0,0 +1,62 @@
+/*
+ * libjingle
+ * Copyright 2007--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_MACUTILS_H__
+#define TALK_BASE_MACUTILS_H__
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Carbon/Carbon.h>
+#include <string>
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ToUtf8(const CFStringRef str16, std::string* str8);
+bool ToUtf16(const std::string& str8, CFStringRef* str16);
+
+void DecodeFourChar(UInt32 fc, std::string* out);
+std::string DecodeEvent(EventRef event);
+
+enum MacOSVersionName {
+ kMacOSUnknown, // ???
+ kMacOSOlder, // 10.2-
+ kMacOSPanther, // 10.3
+ kMacOSTiger, // 10.4
+ kMacOSLeopard, // 10.5
+ kMacOSNewer, // 10.6+
+};
+
+bool GetOSVersion(int* major, int* minor, int* bugfix);
+MacOSVersionName GetOSVersionName();
+bool GetQuickTimeVersion(std::string* version);
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_MACUTILS_H__
diff --git a/talk/base/md5.h b/talk/base/md5.h
old mode 100755
new mode 100644
diff --git a/talk/base/md5c.c b/talk/base/md5c.c
old mode 100755
new mode 100644
diff --git a/talk/base/natsocketfactory.h b/talk/base/messagehandler.cc
old mode 100755
new mode 100644
similarity index 71%
copy from talk/base/natsocketfactory.h
copy to talk/base/messagehandler.cc
index a689158..5b3585b
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/messagehandler.cc
@@ -25,27 +25,13 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
-
-#include "talk/base/socketfactory.h"
+#include "talk/base/messagehandler.h"
+#include "talk/base/messagequeue.h"
namespace talk_base {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
-
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
-
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
-};
+MessageHandler::~MessageHandler() {
+ MessageQueueManager::Instance()->Clear(this);
+}
} // namespace talk_base
-
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
diff --git a/talk/base/natsocketfactory.h b/talk/base/messagehandler.h
old mode 100755
new mode 100644
similarity index 72%
rename from talk/base/natsocketfactory.h
rename to talk/base/messagehandler.h
index a689158..eb7db9b
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/messagehandler.h
@@ -25,27 +25,22 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
-
-#include "talk/base/socketfactory.h"
+#ifndef TALK_BASE_MESSAGEHANDLER_H__
+#define TALK_BASE_MESSAGEHANDLER_H__
namespace talk_base {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
+struct Message;
+
+// Messages get dispatched to a MessageHandler
+
+class MessageHandler {
public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+ virtual ~MessageHandler();
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
-
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
+ virtual void OnMessage(Message* msg) = 0;
};
} // namespace talk_base
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif // TALK_BASE_MESSAGEHANDLER_H__
diff --git a/talk/base/messagequeue.cc b/talk/base/messagequeue.cc
old mode 100755
new mode 100644
index 64f57cc..8c3a8ce
--- a/talk/base/messagequeue.cc
+++ b/talk/base/messagequeue.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -30,9 +30,7 @@
#endif
#ifdef POSIX
-extern "C" {
#include <sys/time.h>
-}
#endif
#include "talk/base/common.h"
@@ -66,7 +64,8 @@
void MessageQueueManager::Add(MessageQueue *message_queue) {
// MessageQueueManager methods should be non-reentrant, so we
- // ASSERT that is the case.
+ // ASSERT that is the case. If any of these ASSERT, please
+ // contact bpm or jbeda.
ASSERT(!crit_.CurrentThreadIsOwner());
CritScope cs(&crit_);
message_queues_.push_back(message_queue);
@@ -74,11 +73,25 @@
void MessageQueueManager::Remove(MessageQueue *message_queue) {
ASSERT(!crit_.CurrentThreadIsOwner()); // See note above.
- CritScope cs(&crit_);
- std::vector<MessageQueue *>::iterator iter;
- iter = std::find(message_queues_.begin(), message_queues_.end(), message_queue);
- if (iter != message_queues_.end())
- message_queues_.erase(iter);
+ // If this is the last MessageQueue, destroy the manager as well so that
+ // we don't leak this object at program shutdown. As mentioned above, this is
+ // not thread-safe, but this should only happen at program termination (when
+ // the ThreadManager is destroyed, and threads are no longer active).
+ bool destroy = false;
+ {
+ CritScope cs(&crit_);
+ std::vector<MessageQueue *>::iterator iter;
+ iter = std::find(message_queues_.begin(), message_queues_.end(),
+ message_queue);
+ if (iter != message_queues_.end()) {
+ message_queues_.erase(iter);
+ }
+ destroy = message_queues_.empty();
+ }
+ if (destroy) {
+ instance_ = NULL;
+ delete this;
+ }
}
void MessageQueueManager::Clear(MessageHandler *handler) {
@@ -93,35 +106,45 @@
// MessageQueue
MessageQueue::MessageQueue(SocketServer* ss)
- : ss_(ss), new_ss(false), fStop_(false), fPeekKeep_(false), active_(false) {
+ : ss_(ss), fStop_(false), fPeekKeep_(false), active_(false),
+ dmsgq_next_num_(0) {
if (!ss_) {
- new_ss = true;
- ss_ = new PhysicalSocketServer();
+ // Currently, MessageQueue holds a socket server, and is the base class for
+ // Thread. It seems like it makes more sense for Thread to hold the socket
+ // server, and provide it to the MessageQueue, since the Thread controls
+ // the I/O model, and MQ is agnostic to those details. Anyway, this causes
+ // messagequeue_unittest to depend on network libraries... yuck.
+ default_ss_.reset(new PhysicalSocketServer());
+ ss_ = default_ss_.get();
}
+ ss_->SetMessageQueue(this);
}
MessageQueue::~MessageQueue() {
+ // The signal is done from here to ensure
+ // that it always gets called when the queue
+ // is going away.
+ SignalQueueDestroyed();
if (active_) {
MessageQueueManager::Instance()->Remove(this);
Clear(NULL);
}
- if (new_ss)
- delete ss_;
+ if (ss_) {
+ ss_->SetMessageQueue(NULL);
+ }
}
void MessageQueue::set_socketserver(SocketServer* ss) {
- if (new_ss)
- delete ss_;
- new_ss = false;
- ss_ = ss;
+ ss_ = ss ? ss : default_ss_.get();
+ ss_->SetMessageQueue(this);
}
-void MessageQueue::Stop() {
+void MessageQueue::Quit() {
fStop_ = true;
ss_->WakeUp();
}
-bool MessageQueue::IsStopping() {
+bool MessageQueue::IsQuitting() {
return fStop_;
}
@@ -141,7 +164,7 @@
return true;
}
-bool MessageQueue::Get(Message *pmsg, int cmsWait) {
+bool MessageQueue::Get(Message *pmsg, int cmsWait, bool process_io) {
// Return and clear peek if present
// Always return the peek if it exists so there is Peek/Get symmetry
@@ -172,11 +195,11 @@
// Calc the next trigger too
while (!dmsgq_.empty()) {
- if (msCurrent < dmsgq_.top().msTrigger_) {
- cmsDelayNext = dmsgq_.top().msTrigger_ - msCurrent;
+ if (TimeIsLater(msCurrent, dmsgq_.top().msTrigger_)) {
+ cmsDelayNext = TimeDiff(dmsgq_.top().msTrigger_, msCurrent);
break;
}
- msgq_.push(dmsgq_.top().msg_);
+ msgq_.push_back(dmsgq_.top().msg_);
dmsgq_.pop();
}
@@ -191,7 +214,7 @@
<< (delay + kMaxMsgLatency) << "ms";
}
}
- msgq_.pop();
+ msgq_.pop_front();
if (MQID_DISPOSE == pmsg->message_id) {
ASSERT(NULL == pmsg->phandler);
delete pmsg->pdata;
@@ -210,20 +233,19 @@
if (cmsWait == kForever) {
cmsNext = cmsDelayNext;
} else {
- cmsNext = cmsTotal - cmsElapsed;
- if (cmsNext < 0)
- cmsNext = 0;
+ cmsNext = _max(0, cmsTotal - cmsElapsed);
if ((cmsDelayNext != kForever) && (cmsDelayNext < cmsNext))
cmsNext = cmsDelayNext;
}
// Wait and multiplex in the meantime
- ss_->Wait(cmsNext, true);
+ if (!ss_->Wait(cmsNext, process_io))
+ return false;
// If the specified timeout expired, return
msCurrent = Time();
- cmsElapsed = msCurrent - msStart;
+ cmsElapsed = TimeDiff(msCurrent, msStart);
if (cmsWait != kForever) {
if (cmsElapsed >= cmsWait)
return false;
@@ -253,12 +275,12 @@
if (time_sensitive) {
msg.ts_sensitive = Time() + kMaxMsgLatency;
}
- msgq_.push(msg);
+ msgq_.push_back(msg);
ss_->WakeUp();
}
-void MessageQueue::PostDelayed(int cmsDelay, MessageHandler *phandler,
- uint32 id, MessageData *pdata) {
+void MessageQueue::DoDelayPost(int cmsDelay, uint32 tstamp,
+ MessageHandler *phandler, uint32 id, MessageData* pdata) {
if (fStop_)
return;
@@ -272,7 +294,12 @@
msg.phandler = phandler;
msg.message_id = id;
msg.pdata = pdata;
- dmsgq_.push(DelayedMessage(cmsDelay, &msg));
+ DelayedMessage dmsg(cmsDelay, tstamp, dmsgq_next_num_, msg);
+ dmsgq_.push(dmsg);
+ // If this message queue processes 1 message every millisecond for 50 days,
+ // we will wrap this number. Even then, only messages with identical times
+ // will be misordered, and then only briefly. This is probably ok.
+ VERIFY(0 != ++dmsgq_next_num_);
ss_->WakeUp();
}
@@ -283,7 +310,7 @@
return 0;
if (!dmsgq_.empty()) {
- int delay = dmsgq_.top().msTrigger_ - Time();
+ int delay = TimeUntil(dmsgq_.top().msTrigger_);
if (delay < 0)
delay = 0;
return delay;
@@ -292,57 +319,53 @@
return kForever;
}
-void MessageQueue::Clear(MessageHandler *phandler, uint32 id) {
+void MessageQueue::Clear(MessageHandler *phandler, uint32 id,
+ MessageList* removed) {
CritScope cs(&crit_);
// Remove messages with phandler
- if (fPeekKeep_) {
- if (phandler == NULL || msgPeek_.phandler == phandler) {
- if (id == MQID_ANY || msgPeek_.message_id == id) {
- delete msgPeek_.pdata;
- fPeekKeep_ = false;
- }
+ if (fPeekKeep_ && msgPeek_.Match(phandler, id)) {
+ if (removed) {
+ removed->push_back(msgPeek_);
+ } else {
+ delete msgPeek_.pdata;
}
+ fPeekKeep_ = false;
}
// Remove from ordered message queue
- size_t c = msgq_.size();
- while (c-- != 0) {
- Message msg = msgq_.front();
- msgq_.pop();
- if (phandler != NULL && msg.phandler != phandler) {
- msgq_.push(msg);
- } else {
- if (id == MQID_ANY || msg.message_id == id) {
- delete msg.pdata;
+ for (MessageList::iterator it = msgq_.begin(); it != msgq_.end();) {
+ if (it->Match(phandler, id)) {
+ if (removed) {
+ removed->push_back(*it);
} else {
- msgq_.push(msg);
+ delete it->pdata;
}
+ it = msgq_.erase(it);
+ } else {
+ ++it;
}
}
// Remove from priority queue. Not directly iterable, so use this approach
- std::queue<DelayedMessage> dmsgs;
- while (!dmsgq_.empty()) {
- DelayedMessage dmsg = dmsgq_.top();
- dmsgq_.pop();
- if (phandler != NULL && dmsg.msg_.phandler != phandler) {
- dmsgs.push(dmsg);
- } else {
- if (id == MQID_ANY || dmsg.msg_.message_id == id) {
- delete dmsg.msg_.pdata;
+ PriorityQueue::container_type::iterator new_end = dmsgq_.container().begin();
+ for (PriorityQueue::container_type::iterator it = new_end;
+ it != dmsgq_.container().end(); ++it) {
+ if (it->msg_.Match(phandler, id)) {
+ if (removed) {
+ removed->push_back(it->msg_);
} else {
- dmsgs.push(dmsg);
+ delete it->msg_.pdata;
}
+ } else {
+ *new_end++ = *it;
}
}
- while (!dmsgs.empty()) {
- dmsgq_.push(dmsgs.front());
- dmsgs.pop();
- }
+ dmsgq_.container().erase(new_end, dmsgq_.container().end());
+ dmsgq_.reheap();
}
void MessageQueue::Dispatch(Message *pmsg) {
@@ -357,4 +380,4 @@
}
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/messagequeue.h b/talk/base/messagequeue.h
old mode 100755
new mode 100644
index ce79700..4d470df
--- a/talk/base/messagequeue.h
+++ b/talk/base/messagequeue.h
@@ -2,37 +2,43 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_MESSAGEQUEUE_H__
-#define TALK_BASE_MESSAGEQUEUE_H__
+#ifndef TALK_BASE_MESSAGEQUEUE_H_
+#define TALK_BASE_MESSAGEQUEUE_H_
-#include <vector>
-#include <queue>
#include <algorithm>
+#include <cstring>
+#include <list>
+#include <queue>
+#include <vector>
+
#include "talk/base/basictypes.h"
#include "talk/base/criticalsection.h"
+#include "talk/base/messagehandler.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/sigslot.h"
#include "talk/base/socketserver.h"
#include "talk/base/time.h"
@@ -40,19 +46,18 @@
struct Message;
class MessageQueue;
-class MessageHandler;
// MessageQueueManager does cleanup of of message queues
class MessageQueueManager {
-public:
+ public:
static MessageQueueManager* Instance();
void Add(MessageQueue *message_queue);
void Remove(MessageQueue *message_queue);
void Clear(MessageHandler *handler);
-private:
+ private:
MessageQueueManager();
~MessageQueueManager();
@@ -62,36 +67,36 @@
CriticalSection crit_;
};
-// Messages get dispatched to a MessageHandler
-
-class MessageHandler {
-public:
- virtual ~MessageHandler() {
- MessageQueueManager::Instance()->Clear(this);
- }
-
- virtual void OnMessage(Message *pmsg) = 0;
-};
-
// Derive from this for specialized data
// App manages lifetime, except when messages are purged
class MessageData {
-public:
+ public:
MessageData() {}
virtual ~MessageData() {}
};
template <class T>
class TypedMessageData : public MessageData {
-public:
- TypedMessageData(const T& data) : data_(data) { }
+ public:
+ explicit TypedMessageData(const T& data) : data_(data) { }
const T& data() const { return data_; }
T& data() { return data_; }
-private:
+ private:
T data_;
};
+// Like TypedMessageData, but for pointers that require a delete.
+template <class T>
+class ScopedMessageData : public MessageData {
+ public:
+ explicit ScopedMessageData(T* data) : data_(data) { }
+ const scoped_ptr<T>& data() const { return data_; }
+ scoped_ptr<T>& data() { return data_; }
+ private:
+ scoped_ptr<T> data_;
+};
+
template<class T>
inline MessageData* WrapMessageData(const T& data) {
return new TypedMessageData<T>(data);
@@ -104,10 +109,10 @@
template<class T>
class DisposeData : public MessageData {
-public:
- DisposeData(T* data) : data_(data) { }
+ public:
+ explicit DisposeData(T* data) : data_(data) { }
virtual ~DisposeData() { delete data_; }
-private:
+ private:
T* data_;
};
@@ -120,34 +125,40 @@
Message() {
memset(this, 0, sizeof(*this));
}
+ inline bool Match(MessageHandler* handler, uint32 id) const {
+ return (handler == NULL || handler == phandler)
+ && (id == MQID_ANY || id == message_id);
+ }
MessageHandler *phandler;
uint32 message_id;
MessageData *pdata;
uint32 ts_sensitive;
};
-// DelayedMessage goes into a priority queue, sorted by trigger time
+typedef std::list<Message> MessageList;
+
+// DelayedMessage goes into a priority queue, sorted by trigger time. Messages
+// with the same trigger time are processed in num_ (FIFO) order.
class DelayedMessage {
-public:
- DelayedMessage(int cmsDelay, Message *pmsg) {
- cmsDelay_ = cmsDelay;
- msTrigger_ = GetMillisecondCount() + cmsDelay;
- msg_ = *pmsg;
- }
+ public:
+ DelayedMessage(int delay, uint32 trigger, uint32 num, const Message& msg)
+ : cmsDelay_(delay), msTrigger_(trigger), num_(num), msg_(msg) { }
bool operator< (const DelayedMessage& dmsg) const {
- return dmsg.msTrigger_ < msTrigger_;
+ return (dmsg.msTrigger_ < msTrigger_)
+ || ((dmsg.msTrigger_ == msTrigger_) && (dmsg.num_ < num_));
}
- int cmsDelay_; // for debugging
+ int cmsDelay_; // for debugging
uint32 msTrigger_;
+ uint32 num_;
Message msg_;
};
class MessageQueue {
-public:
- MessageQueue(SocketServer* ss = 0);
+ public:
+ explicit MessageQueue(SocketServer* ss = NULL);
virtual ~MessageQueue();
SocketServer* socketserver() { return ss_; }
@@ -159,49 +170,76 @@
// Get (or Peek) returns false. By guaranteeing delivery of those messages,
// we eliminate the race condition when an MessageHandler and MessageQueue
// may be destroyed independently of each other.
-
- virtual void Stop();
- virtual bool IsStopping();
+ virtual void Quit();
+ virtual bool IsQuitting();
virtual void Restart();
// Get() will process I/O until:
// 1) A message is available (returns true)
// 2) cmsWait seconds have elapsed (returns false)
// 3) Stop() is called (returns false)
- virtual bool Get(Message *pmsg, int cmsWait = kForever);
+ virtual bool Get(Message *pmsg, int cmsWait = kForever,
+ bool process_io = true);
virtual bool Peek(Message *pmsg, int cmsWait = 0);
virtual void Post(MessageHandler *phandler, uint32 id = 0,
- MessageData *pdata = NULL, bool time_sensitive = false);
+ MessageData *pdata = NULL, bool time_sensitive = false);
virtual void PostDelayed(int cmsDelay, MessageHandler *phandler,
- uint32 id = 0, MessageData *pdata = NULL);
- virtual void Clear(MessageHandler *phandler, uint32 id = MQID_ANY);
+ uint32 id = 0, MessageData *pdata = NULL) {
+ return DoDelayPost(cmsDelay, TimeAfter(cmsDelay), phandler, id, pdata);
+ }
+ virtual void PostAt(uint32 tstamp, MessageHandler *phandler,
+ uint32 id = 0, MessageData *pdata = NULL) {
+ return DoDelayPost(TimeUntil(tstamp), tstamp, phandler, id, pdata);
+ }
+ virtual void Clear(MessageHandler *phandler, uint32 id = MQID_ANY,
+ MessageList* removed = NULL);
virtual void Dispatch(Message *pmsg);
virtual void ReceiveSends();
+
+ // Amount of time until the next message can be retrieved
virtual int GetDelay();
+ bool empty() const { return msgq_.empty() && dmsgq_.empty() && !fPeekKeep_; }
+ size_t size() const { return msgq_.size() + dmsgq_.size() + fPeekKeep_; }
+
// Internally posts a message which causes the doomed object to be deleted
template<class T> void Dispose(T* doomed) {
if (doomed) {
- Post(NULL, MQID_DISPOSE, new talk_base::DisposeData<T>(doomed));
+ Post(NULL, MQID_DISPOSE, new DisposeData<T>(doomed));
}
}
-protected:
- void EnsureActive();
+ // When this signal is sent out, any references to this queue should
+ // no longer be used.
+ sigslot::signal0<> SignalQueueDestroyed;
+ protected:
+ class PriorityQueue : public std::priority_queue<DelayedMessage> {
+ public:
+ container_type& container() { return c; }
+ void reheap() { make_heap(c.begin(), c.end(), comp); }
+ };
+
+ void EnsureActive();
+ void DoDelayPost(int cmsDelay, uint32 tstamp, MessageHandler *phandler,
+ uint32 id, MessageData* pdata);
+
+ // The SocketServer is not owned by MessageQueue.
SocketServer* ss_;
- bool new_ss;
+ // If a server isn't supplied in the constructor, use this one.
+ scoped_ptr<SocketServer> default_ss_;
bool fStop_;
bool fPeekKeep_;
Message msgPeek_;
// A message queue is active if it has ever had a message posted to it.
// This also corresponds to being in MessageQueueManager's global list.
bool active_;
- std::queue<Message> msgq_;
- std::priority_queue<DelayedMessage> dmsgq_;
+ MessageList msgq_;
+ PriorityQueue dmsgq_;
+ uint32 dmsgq_next_num_;
CriticalSection crit_;
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_MESSAGEQUEUE_H__
+#endif // TALK_BASE_MESSAGEQUEUE_H_
diff --git a/talk/base/nat_unittest.cc b/talk/base/nat_unittest.cc
deleted file mode 100755
index 23c122b..0000000
--- a/talk/base/nat_unittest.cc
+++ /dev/null
@@ -1,223 +0,0 @@
-#include <string>
-#include <cstring>
-#include <iostream>
-#include <cassert>
-
-#include "talk/base/natserver.h"
-#include "talk/base/testclient.h"
-#include "talk/base/physicalsocketserver.h"
-#include "talk/base/virtualsocketserver.h"
-#include "talk/base/natsocketfactory.h"
-#include "talk/base/host.h"
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-using namespace talk_base;
-
-#define CHECK(arg) Check(arg, #arg)
-
-void Check(int result, const char* desc) {
- if (result < 0) {
- std::cerr << desc << ": " << std::strerror(errno) << std::endl;
- exit(1);
- }
-}
-
-void CheckTest(bool act_val, bool exp_val, std::string desc) {
- if (act_val && !exp_val) {
- std::cerr << "error: " << desc << " was true, expected false" << std::endl;
- exit(1);
- } else if (!act_val && exp_val) {
- std::cerr << "error: " << desc << " was false, expected true" << std::endl;
- exit(1);
- }
-}
-
-void CheckReceive(
- TestClient* client, bool should_receive, const char* buf, size_t size) {
- if (should_receive)
- client->CheckNextPacket(buf, size, 0);
- else
- client->CheckNoPacket();
-}
-
-TestClient* CreateTestClient(
- SocketFactory* factory, const SocketAddress& local_addr) {
- AsyncUDPSocket* socket = CreateAsyncUDPSocket(factory);
- CHECK(socket->Bind(local_addr));
- return new TestClient(socket);
-}
-
-void TestNATPorts(
- SocketServer* internal, const SocketAddress& internal_addr,
- SocketServer* external, const SocketAddress external_addrs[4],
- NATType nat_type, bool exp_same) {
-
- Thread th_int(internal);
- Thread th_ext(external);
-
- SocketAddress server_addr = internal_addr;
- server_addr.SetPort(NAT_SERVER_PORT);
- NATServer* nat = new NATServer(
- nat_type, internal, server_addr, external, external_addrs[0]);
- NATSocketFactory* natsf = new NATSocketFactory(internal, server_addr);
-
- TestClient* in = CreateTestClient(natsf, internal_addr);
- TestClient* out[4];
- for (int i = 0; i < 4; i++)
- out[i] = CreateTestClient(external, external_addrs[i]);
-
- th_int.Start();
- th_ext.Start();
-
- const char* buf = "filter_test";
- size_t len = strlen(buf);
-
- in->SendTo(buf, len, external_addrs[0]);
- SocketAddress trans_addr;
- out[0]->CheckNextPacket(buf, len, &trans_addr);
-
- for (int i = 1; i < 4; i++) {
- in->SendTo(buf, len, external_addrs[i]);
- SocketAddress trans_addr2;
- out[i]->CheckNextPacket(buf, len, &trans_addr2);
- bool are_same = (trans_addr == trans_addr2);
- CheckTest(are_same, exp_same, "same translated address");
- }
-
- th_int.Stop();
- th_ext.Stop();
-
- delete nat;
- delete natsf;
- delete in;
- for (int i = 0; i < 4; i++)
- delete out[i];
-}
-
-void TestPorts(
- SocketServer* internal, const SocketAddress& internal_addr,
- SocketServer* external, const SocketAddress external_addrs[4]) {
- TestNATPorts(internal, internal_addr, external, external_addrs,
- NAT_OPEN_CONE, true);
- TestNATPorts(internal, internal_addr, external, external_addrs,
- NAT_ADDR_RESTRICTED, true);
- TestNATPorts(internal, internal_addr, external, external_addrs,
- NAT_PORT_RESTRICTED, true);
- TestNATPorts(internal, internal_addr, external, external_addrs,
- NAT_SYMMETRIC, false);
-}
-
-void TestNATFilters(
- SocketServer* internal, const SocketAddress& internal_addr,
- SocketServer* external, const SocketAddress external_addrs[4],
- NATType nat_type, bool filter_ip, bool filter_port) {
-
- Thread th_int(internal);
- Thread th_ext(external);
-
- SocketAddress server_addr = internal_addr;
- server_addr.SetPort(NAT_SERVER_PORT);
- NATServer* nat = new NATServer(
- nat_type, internal, server_addr, external, external_addrs[0]);
- NATSocketFactory* natsf = new NATSocketFactory(internal, server_addr);
-
- TestClient* in = CreateTestClient(natsf, internal_addr);
- TestClient* out[4];
- for (int i = 0; i < 4; i++)
- out[i] = CreateTestClient(external, external_addrs[i]);
-
- th_int.Start();
- th_ext.Start();
-
- const char* buf = "filter_test";
- size_t len = strlen(buf);
-
- in->SendTo(buf, len, external_addrs[0]);
- SocketAddress trans_addr;
- out[0]->CheckNextPacket(buf, len, &trans_addr);
-
- out[1]->SendTo(buf, len, trans_addr);
- CheckReceive(in, !filter_ip, buf, len);
-
- out[2]->SendTo(buf, len, trans_addr);
- CheckReceive(in, !filter_port, buf, len);
-
- out[3]->SendTo(buf, len, trans_addr);
- CheckReceive(in, !filter_ip && !filter_port, buf, len);
-
- th_int.Stop();
- th_ext.Stop();
-
- delete nat;
- delete natsf;
- delete in;
- for (int i = 0; i < 4; i++)
- delete out[i];
-}
-
-void TestFilters(
- SocketServer* internal, const SocketAddress& internal_addr,
- SocketServer* external, const SocketAddress external_addrs[4]) {
- TestNATFilters(internal, internal_addr, external, external_addrs,
- NAT_OPEN_CONE, false, false);
- TestNATFilters(internal, internal_addr, external, external_addrs,
- NAT_ADDR_RESTRICTED, true, false);
- TestNATFilters(internal, internal_addr, external, external_addrs,
- NAT_PORT_RESTRICTED, true, true);
- TestNATFilters(internal, internal_addr, external, external_addrs,
- NAT_SYMMETRIC, true, true);
-}
-
-const int PORT0 = 7405;
-const int PORT1 = 7450;
-const int PORT2 = 7505;
-
-int main(int argc, char* argv[]) {
- assert(LocalHost().networks().size() >= 2);
- SocketAddress int_addr(LocalHost().networks()[1]->ip(), PORT0);
-
- std::string ext_ip1 =
- SocketAddress::IPToString(LocalHost().networks()[0]->ip()); // 127.0.0.1
- std::string ext_ip2 =
- SocketAddress::IPToString(LocalHost().networks()[1]->ip()); // 127.0.0.2
- assert(int_addr.IPAsString() != ext_ip1);
- //assert(int_addr.IPAsString() != ext_ip2); // uncomment
-
- SocketAddress ext_addrs[4] = {
- SocketAddress(ext_ip1, PORT1),
- SocketAddress(ext_ip2, PORT1),
- SocketAddress(ext_ip1, PORT2),
- SocketAddress(ext_ip2, PORT2)
- };
-
- PhysicalSocketServer* int_pss = new PhysicalSocketServer();
- PhysicalSocketServer* ext_pss = new PhysicalSocketServer();
-
- std::cout << "Testing on physical network:" << std::endl;
- TestPorts(int_pss, int_addr, ext_pss, ext_addrs);
- std::cout << "ports: PASS" << std::endl;
- TestFilters(int_pss, int_addr, ext_pss, ext_addrs);
- std::cout << "filters: PASS" << std::endl;
-
- VirtualSocketServer* int_vss = new VirtualSocketServer();
- VirtualSocketServer* ext_vss = new VirtualSocketServer();
-
- int_addr.SetIP(int_vss->GetNextIP());
- ext_addrs[0].SetIP(ext_vss->GetNextIP());
- ext_addrs[1].SetIP(ext_vss->GetNextIP());
- ext_addrs[2].SetIP(ext_addrs[0].ip());
- ext_addrs[3].SetIP(ext_addrs[1].ip());
-
- std::cout << "Testing on virtual network:" << std::endl;
- TestPorts(int_vss, int_addr, ext_vss, ext_addrs);
- std::cout << "ports: PASS" << std::endl;
- TestFilters(int_vss, int_addr, ext_vss, ext_addrs);
- std::cout << "filters: PASS" << std::endl;
-
- return 0;
-}
diff --git a/talk/base/natserver.cc b/talk/base/natserver.cc
deleted file mode 100755
index 336cf64..0000000
--- a/talk/base/natserver.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <cassert>
-#include <iostream>
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-#include "talk/base/natserver.h"
-
-namespace talk_base {
-
-RouteCmp::RouteCmp(NAT* nat) : symmetric(nat->IsSymmetric()) {
-}
-
-size_t RouteCmp::operator()(const SocketAddressPair& r) const {
- size_t h = r.source().Hash();
- if (symmetric)
- h ^= r.destination().Hash();
- return h;
-}
-
-bool RouteCmp::operator()(
- const SocketAddressPair& r1, const SocketAddressPair& r2) const {
- if (r1.source() < r2.source())
- return true;
- if (r2.source() < r1.source())
- return false;
- if (symmetric && (r1.destination() < r2.destination()))
- return true;
- if (symmetric && (r2.destination() < r1.destination()))
- return false;
- return false;
-}
-
-AddrCmp::AddrCmp(NAT* nat)
- : use_ip(nat->FiltersIP()), use_port(nat->FiltersPort()) {
-}
-
-size_t AddrCmp::operator()(const SocketAddress& a) const {
- size_t h = 0;
- if (use_ip)
- h ^= a.ip();
- if (use_port)
- h ^= a.port() | (a.port() << 16);
- return h;
-}
-
-bool AddrCmp::operator()(
- const SocketAddress& a1, const SocketAddress& a2) const {
- if (use_ip && (a1.ip() < a2.ip()))
- return true;
- if (use_ip && (a2.ip() < a1.ip()))
- return false;
- if (use_port && (a1.port() < a2.port()))
- return true;
- if (use_port && (a2.port() < a1.port()))
- return false;
- return false;
-}
-
-NATServer::NATServer(
- NATType type, SocketFactory* internal, const SocketAddress& internal_addr,
- SocketFactory* external, const SocketAddress& external_ip)
- : external_(external), external_ip_(external_ip) {
- nat_ = NAT::Create(type);
-
- server_socket_ = CreateAsyncUDPSocket(internal);
- server_socket_->Bind(internal_addr);
- server_socket_->SignalReadPacket.connect(this, &NATServer::OnInternalPacket);
-
- int_map_ = new InternalMap(RouteCmp(nat_));
- ext_map_ = new ExternalMap();
-}
-
-NATServer::~NATServer() {
- for (InternalMap::iterator iter = int_map_->begin();
- iter != int_map_->end();
- iter++)
- delete iter->second;
-
- delete nat_;
- delete server_socket_;
- delete int_map_;
- delete ext_map_;
-}
-
-void NATServer::OnInternalPacket(
- const char* buf, size_t size, const SocketAddress& addr,
- AsyncPacketSocket* socket) {
-
- // Read the intended destination from the wire.
- SocketAddress dest_addr;
- dest_addr.Read_(buf, size);
-
- // Find the translation for these addresses (allocating one if necessary).
- SocketAddressPair route(addr, dest_addr);
- InternalMap::iterator iter = int_map_->find(route);
- if (iter == int_map_->end()) {
- Translate(route);
- iter = int_map_->find(route);
- }
- assert(iter != int_map_->end());
-
- // Allow the destination to send packets back to the source.
- iter->second->whitelist->insert(dest_addr);
-
- // Send the packet to its intended destination.
- iter->second->socket->SendTo(
- buf + dest_addr.Size_(), size - dest_addr.Size_(), dest_addr);
-}
-
-void NATServer::OnExternalPacket(
- const char* buf, size_t size, const SocketAddress& remote_addr,
- AsyncPacketSocket* socket) {
-
- SocketAddress local_addr = socket->GetLocalAddress();
-
- // Find the translation for this addresses.
- ExternalMap::iterator iter = ext_map_->find(local_addr);
- assert(iter != ext_map_->end());
-
- // Allow the NAT to reject this packet.
- if (Filter(iter->second, remote_addr)) {
- std::cerr << "Packet from " << remote_addr.ToString()
- << " was filtered out by the NAT." << std::endl;
- return;
- }
-
- // Forward this packet to the internal address.
-
- size_t real_size = size + remote_addr.Size_();
- char* real_buf = new char[real_size];
-
- remote_addr.Write_(real_buf, real_size);
- std::memcpy(real_buf + remote_addr.Size_(), buf, size);
-
- server_socket_->SendTo(real_buf, real_size, iter->second->route.source());
-
- delete[] real_buf;
-}
-
-void NATServer::Translate(const SocketAddressPair& route) {
- AsyncUDPSocket* socket = CreateAsyncUDPSocket(external_);
-
- SocketAddress ext_addr = external_ip_;
- for (int i = 0; i < 65536; i++) {
- ext_addr.SetPort((route.source().port() + i) % 65536);
- if (ext_map_->find(ext_addr) == ext_map_->end()) {
- int result = socket->Bind(ext_addr);
- if ((result < 0) && (socket->GetError() == EADDRINUSE))
- continue;
- assert(result >= 0); // TODO: do something better
-
- TransEntry* entry = new TransEntry(route, socket, nat_);
- (*int_map_)[route] = entry;
- (*ext_map_)[ext_addr] = entry;
- socket->SignalReadPacket.connect(this, &NATServer::OnExternalPacket);
- return;
- }
- }
-
- std::cerr << "Couldn't find a free port!" << std::endl;
- delete socket;
- exit(1);
-}
-
-bool NATServer::Filter(TransEntry* entry, const SocketAddress& ext_addr) {
- return entry->whitelist->find(ext_addr) == entry->whitelist->end();
-}
-
-NATServer::TransEntry::TransEntry(
- const SocketAddressPair& r, AsyncUDPSocket* s, NAT* nat)
- : route(r), socket(s) {
- whitelist = new AddressSet(AddrCmp(nat));
-}
-
-NATServer::TransEntry::~TransEntry() {
- delete socket;
-}
-
-} // namespace talk_base
diff --git a/talk/base/natserver.h b/talk/base/natserver.h
deleted file mode 100755
index 61c1dd3..0000000
--- a/talk/base/natserver.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_BASE_NATSERVER_H__
-#define TALK_BASE_NATSERVER_H__
-
-#include "talk/base/asyncudpsocket.h"
-#include "talk/base/socketaddresspair.h"
-#include "talk/base/thread.h"
-#include "talk/base/socketfactory.h"
-#include "talk/base/nattypes.h"
-#include <map>
-
-namespace talk_base {
-
-// Change how routes (socketaddress pairs) are compared based on the type of
-// NAT. The NAT server maintains a hashtable of the routes that it knows
-// about. So these affect which routes are treated the same.
-struct RouteCmp {
- RouteCmp(NAT* nat);
- size_t operator()(const SocketAddressPair& r) const;
- bool operator()(
- const SocketAddressPair& r1, const SocketAddressPair& r2) const;
-
- bool symmetric;
-};
-
-// Changes how addresses are compared based on the filtering rules of the NAT.
-struct AddrCmp {
- AddrCmp(NAT* nat);
- size_t operator()(const SocketAddress& r) const;
- bool operator()(const SocketAddress& r1, const SocketAddress& r2) const;
-
- bool use_ip;
- bool use_port;
-};
-
-// Implements the NAT device. It listens for packets on the internal network,
-// translates them, and sends them out over the external network.
-
-const int NAT_SERVER_PORT = 4237;
-
-class NATServer : public sigslot::has_slots<> {
-public:
- NATServer(
- NATType type, SocketFactory* internal, const SocketAddress& internal_addr,
- SocketFactory* external, const SocketAddress& external_ip);
- ~NATServer();
-
- // Packets received on one of the networks.
- void OnInternalPacket(
- const char* buf, size_t size, const SocketAddress& addr,
- AsyncPacketSocket* socket);
- void OnExternalPacket(
- const char* buf, size_t size, const SocketAddress& remote_addr,
- AsyncPacketSocket* socket);
-
-private:
- typedef std::set<SocketAddress,AddrCmp> AddressSet;
-
- /* Records a translation and the associated external socket. */
- struct TransEntry {
- TransEntry(const SocketAddressPair& r, AsyncUDPSocket* s, NAT* nat);
- ~TransEntry();
-
- SocketAddressPair route;
- AsyncUDPSocket* socket;
- AddressSet* whitelist;
- };
-
- typedef std::map<SocketAddressPair,TransEntry*,RouteCmp> InternalMap;
- typedef std::map<SocketAddress,TransEntry*> ExternalMap;
-
- NAT* nat_;
- AsyncUDPSocket* server_socket_;
- SocketFactory* external_;
- SocketAddress external_ip_;
- InternalMap* int_map_;
- ExternalMap* ext_map_;
-
- /* Creates a new entry that translates the given route. */
- void Translate(const SocketAddressPair& route);
-
- /* Determines whether the NAT would filter out a packet from this address. */
- bool Filter(TransEntry* entry, const SocketAddress& ext_addr);
-};
-
-} // namespace talk_base
-
-#endif // TALK_BASE_NATSERVER_H__
diff --git a/talk/base/natserver_main.cc b/talk/base/natserver_main.cc
deleted file mode 100755
index a748108..0000000
--- a/talk/base/natserver_main.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-
-#include "talk/base/natserver.h"
-#include "talk/base/host.h"
-#include "talk/base/physicalsocketserver.h"
-
-using namespace talk_base;
-
-int main(int argc, char* argv[]) {
- if (argc != 3) {
- std::cerr << "usage: natserver <internal-ip> <external-ip>" << std::endl;
- exit(1);
- }
-
- SocketAddress internal = SocketAddress(argv[1]);
- SocketAddress external = SocketAddress(argv[2]);
- if (internal.EqualIPs(external)) {
- std::cerr << "internal and external IPs must differ" << std::endl;
- exit(1);
- }
-
- Thread* pthMain = Thread::Current();
- PhysicalSocketServer* ss = new PhysicalSocketServer();
- pthMain->set_socketserver(ss);
- NATServer* server = new NATServer(NAT_OPEN_CONE, ss, internal, ss, external);
- server = server;
-
- pthMain->Run();
- return 0;
-}
diff --git a/talk/base/natsocketfactory.cc b/talk/base/natsocketfactory.cc
deleted file mode 100755
index 2b0309e..0000000
--- a/talk/base/natsocketfactory.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-#include <cassert>
-#include "talk/base/natsocketfactory.h"
-
-namespace talk_base {
-
-class NATSocket : public AsyncSocket {
-public:
- NATSocket(Socket* socket, const SocketAddress& server_addr)
- : async_(false), connected_(false), server_addr_(server_addr),
- socket_(socket), buf_(0), size_(0) {
- }
-
- NATSocket(AsyncSocket* socket, const SocketAddress& server_addr)
- : async_(true), connected_(false), server_addr_(server_addr),
- socket_(socket), buf_(0), size_(0) {
- socket->SignalReadEvent.connect(this, &NATSocket::OnReadEvent);
- socket->SignalWriteEvent.connect(this, &NATSocket::OnWriteEvent);
- }
-
- virtual ~NATSocket() {
- delete socket_;
- delete buf_;
- }
-
- SocketAddress GetLocalAddress() const {
- return socket_->GetLocalAddress();
- }
-
- SocketAddress GetRemoteAddress() const {
- return remote_addr_; // will be ANY if not connected
- }
-
- int Bind(const SocketAddress& addr) {
- return socket_->Bind(addr);
- }
-
- int Connect(const SocketAddress& addr) {
- connected_ = true;
- remote_addr_ = addr;
- return 0;
- }
-
- int Send(const void *pv, size_t cb) {
- assert(connected_);
- return SendInternal(pv, cb, remote_addr_);
- }
-
- int SendTo(const void *pv, size_t cb, const SocketAddress& addr) {
- assert(!connected_);
- return SendInternal(pv, cb, addr);
- }
-
- int SendInternal(const void *pv, size_t cb, const SocketAddress& addr) {
- size_t size = cb + addr.Size_();
- char* buf = new char[size];
- Encode(static_cast<const char*>(pv), cb, buf, size, addr);
-
- int result = socket_->SendTo(buf, size, server_addr_);
- delete buf;
- if (result < 0) {
- return result;
- } else {
- assert(result == static_cast<int>(size)); // TODO: This isn't fair.
- return (int)((size_t)result - addr.Size_());
- }
- }
-
- int Recv(void *pv, size_t cb) {
- SocketAddress addr;
- return RecvFrom(pv, cb, &addr);
- }
-
- int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
- // Make sure we have enough room to read the requested amount plus the
- // header address.
- SocketAddress remote_addr;
- Grow(cb + remote_addr.Size_());
-
- // Read the packet from the socket.
- int result = socket_->RecvFrom(buf_, size_, &remote_addr);
- if (result < 0)
- return result;
- assert(remote_addr == server_addr_);
-
- // TODO: we need better framing so that we know how many bytes we can
- // return before we need to read the next address. For UDP, this will be
- // fine as long as the reader always reads everything in the packet.
- assert((size_t)result < size_);
-
- // Decode the wire packet into the actual results.
- SocketAddress real_remote_addr;
- size_t real_size = cb;
- Decode(buf_, result, pv, &real_size, &real_remote_addr);
-
- // Make sure this packet should be delivered before returning it.
- if (!connected_ || (real_remote_addr == remote_addr_)) {
- if (paddr)
- *paddr = real_remote_addr;
- return (int)real_size;
- } else {
- std::cerr << "Dropping packet from unknown remote address: "
- << real_remote_addr.ToString() << std::endl;
- return 0; // Tell the caller we didn't read anything
- }
- }
-
- int Close() {
- connected_ = false;
- remote_addr_ = SocketAddress();
- return socket_->Close();
- }
-
- int Listen(int backlog) {
- assert(false); // not yet implemented
- return 0;
- }
-
- Socket* Accept(SocketAddress *paddr) {
- assert(false); // not yet implemented
- return 0;
- }
-
- AsyncSocket* asyncsocket() {
- assert(async_);
- return static_cast<AsyncSocket*>(socket_);
- }
-
- int GetError() const { return socket_->GetError(); }
- void SetError(int error) { socket_->SetError(error); }
-
- ConnState GetState() const { return connected_ ? CS_CONNECTED : CS_CLOSED; }
-
- virtual int EstimateMTU(uint16* mtu) { return socket_->EstimateMTU(mtu); }
- virtual int SetOption(Option opt, int value) { return socket_->SetOption(opt, value); }
-
- void OnReadEvent(AsyncSocket* socket) {
- assert(socket == socket_);
- SignalReadEvent(this);
- }
-
- void OnWriteEvent(AsyncSocket* socket) {
- assert(socket == socket_);
- SignalWriteEvent(this);
- }
-
-private:
- // Makes sure the buffer is at least the given size.
- void Grow(size_t new_size) {
- if (size_ < new_size) {
- delete buf_;
- size_ = new_size;
- buf_ = new char[size_];
- }
- }
-
- // Encodes the given data and intended remote address into a packet to send
- // to the NAT server.
- void Encode(const char* data, size_t data_size, char* buf, size_t buf_size,
- const SocketAddress& remote_addr) {
- assert(buf_size == data_size + remote_addr.Size_());
- remote_addr.Write_(buf, (int)buf_size);
- std::memcpy(buf + remote_addr.Size_(), data, data_size);
- }
-
- // Decodes the given packet from the NAT server into the actual remote
- // address and data.
- void Decode(const char* data, size_t data_size, void* buf, size_t* buf_size,
- SocketAddress* remote_addr) {
- assert(data_size >= remote_addr->Size_());
- assert(data_size <= *buf_size + remote_addr->Size_());
- remote_addr->Read_(data, (int)data_size);
- *buf_size = data_size - remote_addr->Size_();
- std::memcpy(buf, data + remote_addr->Size_(), *buf_size);
- }
-
- bool async_;
- bool connected_;
- SocketAddress remote_addr_;
- SocketAddress server_addr_; // address of the NAT server
- Socket* socket_;
- char* buf_;
- size_t size_;
-};
-
-NATSocketFactory::NATSocketFactory(
- SocketFactory* factory, const SocketAddress& nat_addr)
- : factory_(factory), nat_addr_(nat_addr) {
-}
-
-Socket* NATSocketFactory::CreateSocket(int type) {
- assert(type == SOCK_DGRAM); // TCP is not yet suported
- return new NATSocket(factory_->CreateSocket(type), nat_addr_);
-}
-
-AsyncSocket* NATSocketFactory::CreateAsyncSocket(int type) {
- assert(type == SOCK_DGRAM); // TCP is not yet suported
- return new NATSocket(factory_->CreateAsyncSocket(type), nat_addr_);
-}
-
-} // namespace talk_base
diff --git a/talk/base/nattypes.cc b/talk/base/nattypes.cc
deleted file mode 100755
index 290c3ad..0000000
--- a/talk/base/nattypes.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <cassert>
-
-#include "talk/base/nattypes.h"
-
-namespace talk_base {
-
-class SymmetricNAT : public NAT {
-public:
- bool IsSymmetric() { return true; }
- bool FiltersIP() { return true; }
- bool FiltersPort() { return true; }
-};
-
-class OpenConeNAT : public NAT {
-public:
- bool IsSymmetric() { return false; }
- bool FiltersIP() { return false; }
- bool FiltersPort() { return false; }
-};
-
-class AddressRestrictedNAT : public NAT {
-public:
- bool IsSymmetric() { return false; }
- bool FiltersIP() { return true; }
- bool FiltersPort() { return false; }
-};
-
-class PortRestrictedNAT : public NAT {
-public:
- bool IsSymmetric() { return false; }
- bool FiltersIP() { return true; }
- bool FiltersPort() { return true; }
-};
-
-NAT* NAT::Create(NATType type) {
- switch (type) {
- case NAT_OPEN_CONE: return new OpenConeNAT();
- case NAT_ADDR_RESTRICTED: return new AddressRestrictedNAT();
- case NAT_PORT_RESTRICTED: return new PortRestrictedNAT();
- case NAT_SYMMETRIC: return new SymmetricNAT();
- default: assert(0); return 0;
- }
-}
-
-} // namespace talk_base
diff --git a/talk/base/nattypes.h b/talk/base/nattypes.h
deleted file mode 100755
index aad11bb..0000000
--- a/talk/base/nattypes.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_BASE_NATTYPE_H__
-#define TALK_BASE_NATTYPE_H__
-
-namespace talk_base {
-
-/* Identifies each type of NAT that can be simulated. */
-enum NATType {
- NAT_OPEN_CONE,
- NAT_ADDR_RESTRICTED,
- NAT_PORT_RESTRICTED,
- NAT_SYMMETRIC
-};
-
-// Implements the rules for each specific type of NAT.
-class NAT {
-public:
- // Determines whether this NAT uses both source and destination address when
- // checking whether a mapping already exists.
- virtual bool IsSymmetric() = 0;
-
- // Determines whether this NAT drops packets received from a different IP
- // the one last sent to.
- virtual bool FiltersIP() = 0;
-
- // Determines whether this NAT drops packets received from a different port
- // the one last sent to.
- virtual bool FiltersPort() = 0;
-
- // Returns an implementation of the given type of NAT.
- static NAT* Create(NATType type);
-};
-
-} // namespace talk_base
-
-#endif // TALK_BASE_NATTYPE_H__
diff --git a/talk/base/nethelpers.cc b/talk/base/nethelpers.cc
new file mode 100644
index 0000000..5740dc3
--- /dev/null
+++ b/talk/base/nethelpers.cc
@@ -0,0 +1,138 @@
+/*
+ * libjingle
+ * Copyright 2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/nethelpers.h"
+
+#include "talk/base/byteorder.h"
+#include "talk/base/signalthread.h"
+
+namespace talk_base {
+
+// AsyncResolver
+
+AsyncResolver::AsyncResolver() : result_(NULL), error_(0) {
+}
+
+AsyncResolver::~AsyncResolver() {
+ FreeHostEnt(result_);
+}
+
+void AsyncResolver::DoWork() {
+ result_ = SafeGetHostByName(addr_.hostname().c_str(), &error_);
+}
+
+void AsyncResolver::OnWorkDone() {
+ if (result_) {
+ addr_.SetIP(NetworkToHost32(
+ *reinterpret_cast<uint32*>(result_->h_addr_list[0])));
+ }
+}
+
+// The functions below are used to do gethostbyname, but with an allocated
+// instead of a static buffer.
+hostent* SafeGetHostByName(const char* hostname, int* herrno) {
+ hostent* result = NULL;
+#if defined(WIN32) || (defined(POSIX) && !defined(OSX))
+ // On Windows we have to allocate a buffer, and manually copy the hostent,
+ // along with its embedded pointers.
+ hostent* ent = gethostbyname(hostname);
+ if (!ent) {
+#ifdef WIN32
+ *herrno = WSAGetLastError();
+#else // POSIX
+ *herrno = h_errno;
+#endif
+ return NULL;
+ }
+
+ // Get the total number of bytes we need to copy, and allocate our buffer.
+ int num_aliases = 0, num_addrs = 0;
+ int total_len = sizeof(hostent);
+ total_len += strlen(ent->h_name) + 1;
+ while (ent->h_aliases[num_aliases]) {
+ total_len += sizeof(char*) + strlen(ent->h_aliases[num_aliases]) + 1;
+ ++num_aliases;
+ }
+ total_len += sizeof(char*);
+ while (ent->h_addr_list[num_addrs]) {
+ total_len += sizeof(char*) + ent->h_length;
+ ++num_addrs;
+ }
+ total_len += sizeof(char*);
+
+ result = static_cast<hostent*>(malloc(total_len));
+ char* p = reinterpret_cast<char*>(result) + sizeof(hostent);
+
+ // Copy the hostent into it, along with its embedded pointers.
+ result->h_name = p;
+ memcpy(p, ent->h_name, strlen(ent->h_name) + 1);
+ p += strlen(ent->h_name) + 1;
+
+ result->h_aliases = reinterpret_cast<char**>(p);
+ p += (num_aliases + 1) * sizeof(char*);
+ for (int i = 0; i < num_aliases; ++i) {
+ result->h_aliases[i] = p;
+ memcpy(p, ent->h_aliases[i], strlen(ent->h_aliases[i]) + 1);
+ p += strlen(ent->h_aliases[i]) + 1;
+ }
+ result->h_aliases[num_aliases] = NULL;
+
+ result->h_addrtype = ent->h_addrtype;
+ result->h_length = ent->h_length;
+
+ result->h_addr_list = reinterpret_cast<char**>(p);
+ p += (num_addrs + 1) * sizeof(char*);
+ for (int i = 0; i < num_addrs; ++i) {
+ result->h_addr_list[i] = p;
+ memcpy(p, ent->h_addr_list[i], ent->h_length);
+ p += ent->h_length;
+ }
+ result->h_addr_list[num_addrs] = NULL;
+
+ *herrno = 0;
+#elif defined(OSX)
+ // Mac OS returns an object with everything allocated.
+ result = getipnodebyname(hostname, AF_INET, AI_DEFAULT, herrno);
+#else
+#error "I don't know how to do gethostbyname safely on your system."
+#endif
+ return result;
+}
+
+// This function should mirror the above function, and free any resources
+// allocated by the above.
+void FreeHostEnt(hostent* host) {
+#if defined(WIN32) || (defined(POSIX) && !defined(OSX))
+ free(host);
+#elif defined(OSX)
+ freehostent(host);
+#else
+#error "I don't know how to free a hostent on your system."
+#endif
+}
+
+} // namespace talk_base
diff --git a/talk/base/nethelpers.h b/talk/base/nethelpers.h
new file mode 100644
index 0000000..4cba9a9
--- /dev/null
+++ b/talk/base/nethelpers.h
@@ -0,0 +1,76 @@
+/*
+ * libjingle
+ * Copyright 2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_NETHELPERS_H_
+#define TALK_BASE_NETHELPERS_H_
+
+#ifdef POSIX
+#include <netdb.h>
+#include <cstddef>
+#elif WIN32
+#include <winsock2.h> // NOLINT
+#endif
+
+#include <list>
+
+#include "talk/base/signalthread.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/socketaddress.h"
+
+namespace talk_base {
+
+// AsyncResolver will perform async DNS resolution, signaling the result on
+// the inherited SignalWorkDone when the operation completes.
+class AsyncResolver : public SignalThread {
+ public:
+ AsyncResolver();
+
+ const SocketAddress& address() const { return addr_; }
+ void set_address(const SocketAddress& addr) { addr_ = addr; }
+ int error() const { return error_; }
+ void set_error(int error) { error_ = error; }
+
+ protected:
+ ~AsyncResolver();
+ virtual void DoWork();
+ virtual void OnWorkDone();
+
+ private:
+ SocketAddress addr_;
+ hostent* result_;
+ int error_;
+};
+
+// SafeGetHostByName functions allocate and return their result, instead of
+// using a static variable like the normal gethostbyname.
+// FreeHostEnt frees the memory allocated by SafeGetHostByName.
+hostent* SafeGetHostByName(const char* hostname, int* herrno);
+void FreeHostEnt(hostent* host);
+
+} // namespace talk_base
+
+#endif // TALK_BASE_NETHELPERS_H_
diff --git a/talk/base/network.cc b/talk/base/network.cc
old mode 100755
new mode 100644
index d5a7d24..8a56d0a
--- a/talk/base/network.cc
+++ b/talk/base/network.cc
@@ -2,70 +2,76 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <algorithm>
-#include <cassert>
-#include <cfloat>
-#include <cmath>
-#include <sstream>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "talk/base/network.h"
+#include "talk/base/stream.h"
#ifdef POSIX
-extern "C" {
#include <sys/socket.h>
#include <sys/utsname.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <errno.h>
-}
-#endif // POSIX
+#endif // POSIX
#ifdef WIN32
#include "talk/base/win32.h"
#include <Iphlpapi.h>
#endif
+#include <algorithm>
+#include <cassert>
+#include <cfloat>
+#include <cmath>
+#include <cstdio>
+#include <cstring>
+#include <sstream>
+
#include "talk/base/host.h"
#include "talk/base/logging.h"
-#include "talk/base/network.h"
-#include "talk/base/socket.h" // this includes something that makes windows happy
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/socket.h" // includes something that makes windows happy
#include "talk/base/stringencode.h"
#include "talk/base/time.h"
-#include "talk/base/basicdefs.h"
namespace {
-const double kAlpha = 0.5; // weight for data infinitely far in the past
-const double kHalfLife = 2000; // half life of exponential decay (in ms)
+const double kAlpha = 0.5; // weight for data infinitely far in the past
+const double kHalfLife = 2000; // half life of exponential decay (in ms)
const double kLog2 = 0.693147180559945309417;
const double kLambda = kLog2 / kHalfLife;
// assume so-so quality unless data says otherwise
const double kDefaultQuality = talk_base::QUALITY_FAIR;
-typedef std::map<std::string,std::string> StrMap;
+typedef std::map<std::string, std::string> StrMap;
void BuildMap(const StrMap& map, std::string& str) {
str.append("{");
@@ -124,131 +130,20 @@
LOG(LERROR) << "Unexpected characters at end";
}
-#if 0
-const std::string TEST_MAP0_IN = "";
-const std::string TEST_MAP0_OUT = "{}";
-const std::string TEST_MAP1 = "{a=12345}";
-const std::string TEST_MAP2 = "{a=12345,b=67890}";
-const std::string TEST_MAP3 = "{a=12345,b=67890,c=13579}";
-const std::string TEST_MAP4 = "{a={d=12345,e=67890}}";
-const std::string TEST_MAP5 = "{a={d=12345,e=67890},b=67890}";
-const std::string TEST_MAP6 = "{a=12345,b={d=12345,e=67890}}";
-const std::string TEST_MAP7 = "{a=12345,b={d=12345,e=67890},c=13579}";
-
-class MyTest {
-public:
- MyTest() {
- test(TEST_MAP0_IN, TEST_MAP0_OUT);
- test(TEST_MAP1, TEST_MAP1);
- test(TEST_MAP2, TEST_MAP2);
- test(TEST_MAP3, TEST_MAP3);
- test(TEST_MAP4, TEST_MAP4);
- test(TEST_MAP5, TEST_MAP5);
- test(TEST_MAP6, TEST_MAP6);
- test(TEST_MAP7, TEST_MAP7);
- }
- void test(const std::string& input, const std::string& exp_output) {
- StrMap map;
- ParseMap(input, map);
- std::string output;
- BuildMap(map, output);
- LOG(INFO) << " ******** " << (output == exp_output);
- }
-};
-
-static MyTest myTest;
-#endif
-
-} // namespace
+} // namespace
namespace talk_base {
-#ifdef POSIX
-void NetworkManager::CreateNetworks(std::vector<Network*>& networks) {
- int fd;
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- PLOG(LERROR, errno) << "socket";
- return;
- }
-
- struct ifconf ifc;
- ifc.ifc_len = 64 * sizeof(struct ifreq);
- ifc.ifc_buf = new char[ifc.ifc_len];
-
- if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
- PLOG(LERROR, errno) << "ioctl";
- return;
- }
- assert(ifc.ifc_len < static_cast<int>(64 * sizeof(struct ifreq)));
-
- struct ifreq* ptr = reinterpret_cast<struct ifreq*>(ifc.ifc_buf);
- struct ifreq* end =
- reinterpret_cast<struct ifreq*>(ifc.ifc_buf + ifc.ifc_len);
-
- while (ptr < end) {
- if (strcmp(ptr->ifr_name, "lo")) { // Ignore the loopback device
- struct sockaddr_in* inaddr =
- reinterpret_cast<struct sockaddr_in*>(&ptr->ifr_ifru.ifru_addr);
- if (inaddr->sin_family == AF_INET) {
- uint32 ip = ntohl(inaddr->sin_addr.s_addr);
- networks.push_back(new Network(std::string(ptr->ifr_name), ip));
- }
- }
-#ifdef _SIZEOF_ADDR_IFREQ
- ptr = reinterpret_cast<struct ifreq*>(
- reinterpret_cast<char*>(ptr) + _SIZEOF_ADDR_IFREQ(*ptr));
-#else
- ptr++;
-#endif
- }
-
- delete [] ifc.ifc_buf;
- close(fd);
+NetworkManager::~NetworkManager() {
+ for (NetworkMap::iterator i = networks_.begin(); i != networks_.end(); ++i)
+ delete i->second;
}
-#endif
-#ifdef WIN32
-void NetworkManager::CreateNetworks(std::vector<Network*>& networks) {
- IP_ADAPTER_INFO info_temp;
- ULONG len = 0;
-
- if (GetAdaptersInfo(&info_temp, &len) != ERROR_BUFFER_OVERFLOW)
- return;
- IP_ADAPTER_INFO *infos = new IP_ADAPTER_INFO[len];
- if (GetAdaptersInfo(infos, &len) != NO_ERROR)
- return;
-
- int count = 0;
- for (IP_ADAPTER_INFO *info = infos; info != NULL; info = info->Next) {
- if (info->Type == MIB_IF_TYPE_LOOPBACK)
- continue;
- if (strcmp(info->IpAddressList.IpAddress.String, "0.0.0.0") == 0)
- continue;
-
- // In production, don't transmit the network name because of
- // privacy concerns. Transmit a number instead.
-
- std::string name;
-#if defined(PRODUCTION)
- std::ostringstream ost;
- ost << count;
- name = ost.str();
- count++;
-#else
- name = info->Description;
-#endif
-
- networks.push_back(new Network(name,
- SocketAddress::StringToIP(info->IpAddressList.IpAddress.String)));
- }
-
- delete infos;
-}
-#endif
-
-void NetworkManager::GetNetworks(std::vector<Network*>& result) {
+bool NetworkManager::GetNetworks(std::vector<Network*>* result) {
std::vector<Network*> list;
- CreateNetworks(list);
+ if (!EnumNetworks(false, &list)) {
+ return false;
+ }
for (uint32 i = 0; i < list.size(); ++i) {
NetworkMap::iterator iter = networks_.find(list[i]->name());
@@ -259,17 +154,35 @@
} else {
network = iter->second;
network->set_ip(list[i]->ip());
+ network->set_gateway_ip(list[i]->gateway_ip());
delete list[i];
}
networks_[network->name()] = network;
- result.push_back(network);
+ result->push_back(network);
+ }
+ return true;
+}
+
+void NetworkManager::DumpNetworks(bool include_ignored) {
+ std::vector<Network*> list;
+ EnumNetworks(include_ignored, &list);
+ LOG(LS_INFO) << "NetworkManager detected " << list.size() << " networks:";
+ for (size_t i = 0; i < list.size(); ++i) {
+ const Network* network = list[i];
+ if (!network->ignored() || include_ignored) {
+ LOG(LS_INFO) << network->ToString() << ": " << network->description()
+ << ", Gateway="
+ << SocketAddress::IPToString(network->gateway_ip())
+ << ((network->ignored()) ? ", Ignored" : "");
+ }
}
}
-std::string NetworkManager::GetState() {
+std::string NetworkManager::GetState() const {
StrMap map;
- for (NetworkMap::iterator i = networks_.begin(); i != networks_.end(); ++i)
+ for (NetworkMap::const_iterator i = networks_.begin();
+ i != networks_.end(); ++i)
map[i->first] = i->second->GetState();
std::string str;
@@ -277,7 +190,7 @@
return str;
}
-void NetworkManager::SetState(std::string str) {
+void NetworkManager::SetState(const std::string& str) {
StrMap map;
ParseMap(str, map);
@@ -285,30 +198,189 @@
std::string name = i->first;
std::string state = i->second;
- Network* network = new Network(name, 0);
+ Network* network = new Network(name, "", 0, 0);
network->SetState(state);
networks_[name] = network;
}
}
-Network::Network(const std::string& name, uint32 ip)
- : name_(name), ip_(ip), uniform_numerator_(0), uniform_denominator_(0),
- exponential_numerator_(0), exponential_denominator_(0),
- quality_(kDefaultQuality) {
+#ifdef POSIX
+// Gets the default gateway for the specified interface.
+uint32 GetDefaultGateway(const std::string& name) {
+#ifdef OSX
+ // TODO: /proc/net/route doesn't exist,
+ // Use ioctl to get the routing table
+ return 0xFFFFFFFF;
+#endif
+ uint32 gateway_ip = 0;
+
+ FileStream fs;
+ if (fs.Open("/proc/net/route", "r")) {
+ std::string line;
+ while (fs.ReadLine(&line) == SR_SUCCESS && gateway_ip == 0) {
+ char iface[16];
+ unsigned int ip, gw;
+ if (sscanf(line.c_str(), "%7s %8X %8X", iface, &ip, &gw) == 3 &&
+ name == iface && ip == 0) {
+ gateway_ip = ntohl(gw);
+ }
+ }
+ }
+
+ return gateway_ip;
+}
+
+
+bool NetworkManager::CreateNetworks(bool include_ignored,
+ std::vector<Network*>* networks) {
+ int fd;
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ LOG_ERR(LERROR) << "socket";
+ return false;
+ }
+
+ struct ifconf ifc;
+ ifc.ifc_len = 64 * sizeof(struct ifreq);
+ ifc.ifc_buf = new char[ifc.ifc_len];
+
+ if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
+ LOG_ERR(LERROR) << "ioctl";
+ return false;
+ }
+ assert(ifc.ifc_len < static_cast<int>(64 * sizeof(struct ifreq)));
+
+ struct ifreq* ptr = reinterpret_cast<struct ifreq*>(ifc.ifc_buf);
+ struct ifreq* end =
+ reinterpret_cast<struct ifreq*>(ifc.ifc_buf + ifc.ifc_len);
+
+ while (ptr < end) {
+ struct sockaddr_in* inaddr =
+ reinterpret_cast<struct sockaddr_in*>(&ptr->ifr_ifru.ifru_addr);
+ if (inaddr->sin_family == AF_INET) {
+ uint32 ip = ntohl(inaddr->sin_addr.s_addr);
+ scoped_ptr<Network> network(
+ new Network(ptr->ifr_name, ptr->ifr_name, ip,
+ GetDefaultGateway(ptr->ifr_name)));
+ network->set_ignored(IsIgnoredNetwork(*network));
+ if (include_ignored || !network->ignored()) {
+ networks->push_back(network.release());
+ }
+ }
+
+#ifdef _SIZEOF_ADDR_IFREQ
+ ptr = reinterpret_cast<struct ifreq*>(
+ reinterpret_cast<char*>(ptr) + _SIZEOF_ADDR_IFREQ(*ptr));
+#else
+ ptr++;
+#endif
+ }
+
+ delete [] ifc.ifc_buf;
+ close(fd);
+ return true;
+}
+#endif // POSIX
+
+#ifdef WIN32
+bool NetworkManager::CreateNetworks(bool include_ignored,
+ std::vector<Network*>* networks) {
+ IP_ADAPTER_INFO info_temp;
+ ULONG len = 0;
+
+ if (GetAdaptersInfo(&info_temp, &len) != ERROR_BUFFER_OVERFLOW)
+ // This just means there's zero networks, which is not an error.
+ return true;
+
+ scoped_array<char> buf(new char[len]);
+ IP_ADAPTER_INFO *infos = reinterpret_cast<IP_ADAPTER_INFO *>(buf.get());
+ DWORD ret = GetAdaptersInfo(infos, &len);
+ if (ret != NO_ERROR) {
+ LOG_ERR_EX(LS_ERROR, ret) << "GetAdaptersInfo failed";
+ return false;
+ }
+
+ int count = 0;
+ for (IP_ADAPTER_INFO *info = infos; info != NULL; info = info->Next) {
+ // Ignore the loopback device.
+ if (info->Type == MIB_IF_TYPE_LOOPBACK) {
+ continue;
+ }
+
+ // In non-debug builds, don't transmit the network name because of
+ // privacy concerns. Transmit a number instead.
+ std::string name;
+#ifdef _DEBUG
+ name = info->Description;
+#else // !_DEBUG
+ std::ostringstream ost;
+ ost << count;
+ name = ost.str();
+ count++;
+#endif // !_DEBUG
+
+ scoped_ptr<Network> network(new Network(name, info->Description,
+ SocketAddress::StringToIP(info->IpAddressList.IpAddress.String),
+ SocketAddress::StringToIP(info->GatewayList.IpAddress.String)));
+ network->set_ignored(IsIgnoredNetwork(*network));
+ if (include_ignored || !network->ignored()) {
+ networks->push_back(network.release());
+ }
+ }
+
+ return true;
+}
+#endif // WIN32
+
+bool NetworkManager::IsIgnoredNetwork(const Network& network) {
+#ifdef POSIX
+ // Ignore local networks (lo, lo0, etc)
+ // Also filter out VMware interfaces, typically named vmnet1 and vmnet8
+ if (strncmp(network.name().c_str(), "lo", 2) == 0 ||
+ strncmp(network.name().c_str(), "vmnet", 5) == 0) {
+ return true;
+ }
+#elif defined(WIN32)
+ // Ignore any HOST side vmware adapters with a description like:
+ // VMware Virtual Ethernet Adapter for VMnet1
+ // but don't ignore any GUEST side adapters with a description like:
+ // VMware Accelerated AMD PCNet Adapter #2
+ if (strstr(network.description().c_str(), "VMnet") != NULL) {
+ return true;
+ }
+#endif
+
+ // Ignore any networks with a 0.x.y.z IP
+ return (network.ip() < 0x01000000);
+}
+
+bool NetworkManager::EnumNetworks(bool include_ignored,
+ std::vector<Network*>* result) {
+ return CreateNetworks(include_ignored, result);
+}
+
+
+Network::Network(const std::string& name, const std::string& desc,
+ uint32 ip, uint32 gateway_ip)
+ : name_(name), description_(desc), ip_(ip), gateway_ip_(gateway_ip),
+ ignored_(false), uniform_numerator_(0), uniform_denominator_(0),
+ exponential_numerator_(0), exponential_denominator_(0),
+ quality_(kDefaultQuality) {
last_data_time_ = Time();
- // TODO: seed the historical data with one data point based on the link speed
- // metric from XP (4.0 if < 50, 3.0 otherwise).
+ // TODO: seed the historical data with one data point based
+ // on the link speed metric from XP (4.0 if < 50, 3.0 otherwise).
}
void Network::StartSession(NetworkSession* session) {
- assert(std::find(sessions_.begin(), sessions_.end(), session) == sessions_.end());
+ assert(std::find(sessions_.begin(), sessions_.end(), session) ==
+ sessions_.end());
sessions_.push_back(session);
}
void Network::StopSession(NetworkSession* session) {
- SessionList::iterator iter = std::find(sessions_.begin(), sessions_.end(), session);
+ SessionList::iterator iter =
+ std::find(sessions_.begin(), sessions_.end(), session);
if (iter != sessions_.end())
sessions_.erase(iter);
}
@@ -326,7 +398,8 @@
double exp_shift = exp(-kLambda * (now - last_data_time_));
double numerator = uniform_numerator_ + exp_shift * exponential_numerator_;
- double denominator = uniform_denominator_ + exp_shift * exponential_denominator_;
+ double denominator = uniform_denominator_ + exp_shift *
+ exponential_denominator_;
if (denominator < DBL_EPSILON)
quality_ = kDefaultQuality;
@@ -336,9 +409,9 @@
std::string Network::ToString() const {
std::stringstream ss;
- // Print out the first space-terminated token of the network name, plus
+ // Print out the first space-terminated token of the network desc, plus
// the IP address.
- ss << "Net[" << name_.substr(0, name_.find(' '))
+ ss << "Net[" << description_.substr(0, description_.find(' '))
<< ":" << SocketAddress::IPToString(ip_) << "]";
return ss.str();
}
@@ -348,13 +421,15 @@
uniform_denominator_ += kAlpha;
double exp_shift = exp(-kLambda * (time - last_data_time_));
- exponential_numerator_ = (1 - kAlpha) * quality + exp_shift * exponential_numerator_;
- exponential_denominator_ = (1 - kAlpha) + exp_shift * exponential_denominator_;
+ exponential_numerator_ = (1 - kAlpha) * quality + exp_shift *
+ exponential_numerator_;
+ exponential_denominator_ = (1 - kAlpha) + exp_shift *
+ exponential_denominator_;
last_data_time_ = time;
}
-std::string Network::GetState() {
+std::string Network::GetState() const {
StrMap map;
map["lt"] = talk_base::ToString<uint32>(last_data_time_);
map["un"] = talk_base::ToString<double>(uniform_numerator_);
@@ -367,7 +442,7 @@
return str;
}
-void Network::SetState(std::string str) {
+void Network::SetState(const std::string& str) {
StrMap map;
ParseMap(str, map);
@@ -378,4 +453,4 @@
exponential_denominator_ = FromString<double>(map["ed"]);
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/network.h b/talk/base/network.h
old mode 100755
new mode 100644
index 52785ba..8153e54
--- a/talk/base/network.h
+++ b/talk/base/network.h
@@ -2,31 +2,31 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NETWORK_H__
-#define TALK_BASE_NETWORK_H__
+#ifndef TALK_BASE_NETWORK_H_
+#define TALK_BASE_NETWORK_H_
#include <deque>
#include <map>
@@ -43,22 +43,35 @@
// Keeps track of the available network interfaces over time so that quality
// information can be aggregated and recorded.
class NetworkManager {
-public:
+ public:
+ virtual ~NetworkManager();
// Updates and returns the current list of networks available on this machine.
// This version will make sure that repeated calls return the same object for
// a given network, so that quality is tracked appropriately.
- void GetNetworks(std::vector<Network*>& networks);
+ // Does not include ignored networks.
+ bool GetNetworks(std::vector<Network*>* networks);
+
+ // Logs the available networks.
+ void DumpNetworks(bool include_ignored);
// Reads and writes the state of the quality database in a string format.
- std::string GetState();
- void SetState(std::string str);
+ std::string GetState() const;
+ void SetState(const std::string& str);
// Creates a network object for each network available on the machine.
- static void CreateNetworks(std::vector<Network*>& networks);
+ static bool CreateNetworks(bool include_ignored,
+ std::vector<Network*>* networks);
+ // Determines if a network should be ignored.
+ static bool IsIgnoredNetwork(const Network& network);
-private:
- typedef std::map<std::string,Network*> NetworkMap;
+ protected:
+ // Fills the supplied list with all usable networks. Overrideable.
+ virtual bool EnumNetworks(bool include_ignored,
+ std::vector<Network*>* networks);
+
+ private:
+ typedef std::map<std::string, Network*> NetworkMap;
NetworkMap networks_;
};
@@ -66,17 +79,31 @@
// Represents a Unix-type network interface, with a name and single address.
// It also includes the ability to track and estimate quality.
class Network {
-public:
- Network(const std::string& name, uint32 ip);
+ public:
+ Network(const std::string& name, const std::string& description,
+ uint32 ip, uint32 gateway_ip);
- // Returns the OS name of this network. This is considered the primary key
+ // Returns the index of this network. This is considered the primary key
// that identifies each network.
const std::string& name() const { return name_; }
+ // Returns the OS-assigned name for this network. This is useful for
+ // debugging but should not be sent over the wire (for privacy reasons).
+ const std::string& description() const { return description_; }
+
// Identifies the current IP address used by this network.
uint32 ip() const { return ip_; }
void set_ip(uint32 ip) { ip_ = ip; }
+ // Identifies the current gateway IP address used by this network.
+ uint32 gateway_ip() const { return gateway_ip_; }
+ void set_gateway_ip(uint32 ip) { gateway_ip_ = ip; }
+
+ // Indicates whether this network should be ignored, perhaps because the
+ // IP/gateway is 0, or the interface is one we know is invalid.
+ bool ignored() const { return ignored_; }
+ void set_ignored(bool ignored) { ignored_ = ignored; }
+
// Updates the list of sessions that are ongoing.
void StartSession(NetworkSession* session);
void StopSession(NetworkSession* session);
@@ -92,11 +119,14 @@
// Debugging description of this network
std::string ToString() const;
-private:
+ private:
typedef std::vector<NetworkSession*> SessionList;
std::string name_;
+ std::string description_;
uint32 ip_;
+ uint32 gateway_ip_;
+ bool ignored_;
SessionList sessions_;
double uniform_numerator_;
double uniform_denominator_;
@@ -110,8 +140,8 @@
// Converts the internal state to and from a string. This is used to record
// quality information into a permanent store.
- void SetState(std::string str);
- std::string GetState();
+ void SetState(const std::string& str);
+ std::string GetState() const;
friend class NetworkManager;
};
@@ -119,7 +149,9 @@
// Represents a session that is in progress using a particular network and can
// provide data about the quality of the network at any given moment.
class NetworkSession {
-public:
+ public:
+ virtual ~NetworkSession() { }
+
// Determines whether this session has an estimate at this moment. We will
// only call GetCurrentQuality when this returns true.
virtual bool HasQuality() = 0;
@@ -127,13 +159,12 @@
// Returns an estimate of the quality at this exact moment. The result should
// be a MOS (mean opinion score) value.
virtual float GetCurrentQuality() = 0;
-
};
const double QUALITY_BAD = 3.0;
const double QUALITY_FAIR = 3.35;
const double QUALITY_GOOD = 3.7;
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_NETWORK_H__
+#endif // TALK_BASE_NETWORK_H_
diff --git a/talk/base/openssladapter.cc b/talk/base/openssladapter.cc
old mode 100755
new mode 100644
index 1d4f02c..2aacecc
--- a/talk/base/openssladapter.cc
+++ b/talk/base/openssladapter.cc
@@ -1,6 +1,15 @@
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#if HAVE_OPENSSL_SSL_H
+
#include <openssl/bio.h>
-#include <openssl/ssl.h>
+#include <openssl/crypto.h>
#include <openssl/err.h>
+#include <openssl/opensslv.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#include "talk/base/common.h"
@@ -9,113 +18,32 @@
#include "talk/base/stringutils.h"
#include "talk/base/Equifax_Secure_Global_eBusiness_CA-1.h"
-//////////////////////////////////////////////////////////////////////
-// StreamBIO
-//////////////////////////////////////////////////////////////////////
+// TODO: Use a nicer abstraction for mutex.
-#if 0
-static int stream_write(BIO* h, const char* buf, int num);
-static int stream_read(BIO* h, char* buf, int size);
-static int stream_puts(BIO* h, const char* str);
-static long stream_ctrl(BIO* h, int cmd, long arg1, void* arg2);
-static int stream_new(BIO* h);
-static int stream_free(BIO* data);
-
-static BIO_METHOD methods_stream = {
- BIO_TYPE_BIO,
- "stream",
- stream_write,
- stream_read,
- stream_puts,
- 0,
- stream_ctrl,
- stream_new,
- stream_free,
- NULL,
-};
-
-BIO_METHOD* BIO_s_stream() { return(&methods_stream); }
-
-BIO* BIO_new_stream(StreamInterface* stream) {
- BIO* ret = BIO_new(BIO_s_stream());
- if (ret == NULL)
- return NULL;
- ret->ptr = stream;
- return ret;
-}
-
-static int stream_new(BIO* b) {
- b->shutdown = 0;
- b->init = 1;
- b->num = 0; // 1 means end-of-stream
- b->ptr = 0;
- return 1;
-}
-
-static int stream_free(BIO* b) {
- if (b == NULL)
- return 0;
- return 1;
-}
-
-static int stream_read(BIO* b, char* out, int outl) {
- if (!out)
- return -1;
- StreamInterface* stream = static_cast<StreamInterface*>(b->ptr);
- BIO_clear_retry_flags(b);
- size_t read;
- int error;
- StreamResult result = stream->Read(out, outl, &read, &error);
- if (result == SR_SUCCESS) {
- return read;
- } else if (result == SR_EOS) {
- b->num = 1;
- } else if (result == SR_BLOCK) {
- BIO_set_retry_read(b);
- }
- return -1;
-}
-
-static int stream_write(BIO* b, const char* in, int inl) {
- if (!in)
- return -1;
- StreamInterface* stream = static_cast<StreamInterface*>(b->ptr);
- BIO_clear_retry_flags(b);
- size_t written;
- int error;
- StreamResult result = stream->Write(in, inl, &written, &error);
- if (result == SR_SUCCESS) {
- return written;
- } else if (result == SR_BLOCK) {
- BIO_set_retry_write(b);
- }
- return -1;
-}
-
-static int stream_puts(BIO* b, const char* str) {
- return stream_write(b, str, strlen(str));
-}
-
-static long stream_ctrl(BIO* b, int cmd, long num, void* ptr) {
- UNUSED(num);
- UNUSED(ptr);
-
- switch (cmd) {
- case BIO_CTRL_RESET:
- return 0;
- case BIO_CTRL_EOF:
- return b->num;
- case BIO_CTRL_WPENDING:
- case BIO_CTRL_PENDING:
- return 0;
- case BIO_CTRL_FLUSH:
- return 1;
- default:
- return 0;
- }
-}
+#if defined(WIN32)
+ #define MUTEX_TYPE HANDLE
+ #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
+ #define MUTEX_CLEANUP(x) CloseHandle(x)
+ #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
+ #define MUTEX_UNLOCK(x) ReleaseMutex(x)
+ #define THREAD_ID GetCurrentThreadId()
+#elif defined(_POSIX_THREADS)
+ // _POSIX_THREADS is normally defined in unistd.h if pthreads are available
+ // on your platform.
+ #define MUTEX_TYPE pthread_mutex_t
+ #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
+ #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
+ #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
+ #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
+ #define THREAD_ID pthread_self()
+#else
+ #error You must define mutex operations appropriate for your platform!
#endif
+struct CRYPTO_dynlock_value {
+ MUTEX_TYPE mutex;
+};
+
//////////////////////////////////////////////////////////////////////
// SocketBIO
//////////////////////////////////////////////////////////////////////
@@ -224,13 +152,96 @@
namespace talk_base {
+// This array will store all of the mutexes available to OpenSSL.
+static MUTEX_TYPE* mutex_buf = NULL;
+
+static void locking_function(int mode, int n, const char * file, int line) {
+ if (mode & CRYPTO_LOCK) {
+ MUTEX_LOCK(mutex_buf[n]);
+ } else {
+ MUTEX_UNLOCK(mutex_buf[n]);
+ }
+}
+
+static pthread_t id_function() {
+ return THREAD_ID;
+}
+
+static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
+ CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
+ if (!value)
+ return NULL;
+ MUTEX_SETUP(value->mutex);
+ return value;
+}
+
+static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
+ const char* file, int line) {
+ if (mode & CRYPTO_LOCK) {
+ MUTEX_LOCK(l->mutex);
+ } else {
+ MUTEX_UNLOCK(l->mutex);
+ }
+}
+
+static void dyn_destroy_function(CRYPTO_dynlock_value* l,
+ const char* file, int line) {
+ MUTEX_CLEANUP(l->mutex);
+ delete l;
+}
+
+VerificationCallback OpenSSLAdapter::custom_verify_callback_ = NULL;
+
+bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
+ if (!InitializeSSLThread() || !SSL_library_init())
+ return false;
+ SSL_load_error_strings();
+ ERR_load_BIO_strings();
+ OpenSSL_add_all_algorithms();
+ RAND_poll();
+ custom_verify_callback_ = callback;
+ return true;
+}
+
+bool OpenSSLAdapter::InitializeSSLThread() {
+ mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
+ if (!mutex_buf)
+ return false;
+ for (int i = 0; i < CRYPTO_num_locks(); ++i)
+ MUTEX_SETUP(mutex_buf[i]);
+
+ // we need to cast our id_function to return an unsigned long -- pthread_t is a pointer
+ CRYPTO_set_id_callback((unsigned long (*)())id_function);
+ CRYPTO_set_locking_callback(locking_function);
+ CRYPTO_set_dynlock_create_callback(dyn_create_function);
+ CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
+ CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
+ return true;
+}
+
+bool OpenSSLAdapter::CleanupSSL() {
+ if (!mutex_buf)
+ return false;
+ CRYPTO_set_id_callback(NULL);
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_dynlock_create_callback(NULL);
+ CRYPTO_set_dynlock_lock_callback(NULL);
+ CRYPTO_set_dynlock_destroy_callback(NULL);
+ for (int i = 0; i < CRYPTO_num_locks(); ++i)
+ MUTEX_CLEANUP(mutex_buf[i]);
+ delete [] mutex_buf;
+ mutex_buf = NULL;
+ return true;
+}
+
OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
: SSLAdapter(socket),
state_(SSL_NONE),
ssl_read_needs_write_(false),
ssl_write_needs_read_(false),
restartable_(false),
- ssl_(NULL), ssl_ctx_(NULL) {
+ ssl_(NULL), ssl_ctx_(NULL),
+ custom_verification_succeeded_(false) {
}
OpenSSLAdapter::~OpenSSLAdapter() {
@@ -240,7 +251,7 @@
int
OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
if (state_ != SSL_NONE)
- return -1;
+ return -1;
ssl_host_name_ = hostname;
restartable_ = restartable;
@@ -276,7 +287,7 @@
goto ssl_error;
}
- bio = BIO_new_socket(static_cast<talk_base::AsyncSocketAdapter*>(socket_));
+ bio = BIO_new_socket(static_cast<AsyncSocketAdapter*>(socket_));
if (!bio) {
err = -1;
goto ssl_error;
@@ -376,6 +387,7 @@
state_ = SSL_NONE;
ssl_read_needs_write_ = false;
ssl_write_needs_read_ = false;
+ custom_verification_succeeded_ = false;
if (ssl_) {
SSL_free(ssl_);
@@ -604,8 +616,9 @@
// This code is taken from the "Network Security with OpenSSL"
// sample in chapter 5
-bool
-OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
+
+bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
+ bool ignore_bad_cert) {
if (!host)
return false;
@@ -641,34 +654,54 @@
int extension_nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
if (extension_nid == NID_subject_alt_name) {
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ const X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
+#else
X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
+#endif
if (!meth)
break;
void* ext_str = NULL;
+ // We assign this to a local variable, instead of passing the address
+ // directly to ASN1_item_d2i.
+ // See http://readlist.com/lists/openssl.org/openssl-users/0/4761.html.
+ unsigned char* ext_value_data = extension->value->data;
+
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
- const unsigned char **ext_value_data = (const_cast<const unsigned char **>
- (&extension->value->data));
+ const unsigned char **ext_value_data_ptr =
+ (const_cast<const unsigned char **>(&ext_value_data));
#else
- unsigned char **ext_value_data = &extension->value->data;
+ unsigned char **ext_value_data_ptr = &ext_value_data;
#endif
if (meth->it) {
- ext_str = ASN1_item_d2i(NULL, ext_value_data, extension->value->length,
+ ext_str = ASN1_item_d2i(NULL, ext_value_data_ptr,
+ extension->value->length,
ASN1_ITEM_ptr(meth->it));
} else {
- ext_str = meth->d2i(NULL, ext_value_data, extension->value->length);
+ ext_str = meth->d2i(NULL, ext_value_data_ptr, extension->value->length);
}
STACK_OF(CONF_VALUE)* value = meth->i2v(meth, ext_str, NULL);
for (int j = 0; j < sk_CONF_VALUE_num(value); ++j) {
CONF_VALUE* nval = sk_CONF_VALUE_value(value, j);
- if (!strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) {
+ // The value for nval can contain wildcards
+ if (!strcmp(nval->name, "DNS") && string_match(host, nval->value)) {
ok = true;
break;
}
}
+ sk_CONF_VALUE_pop_free(value, X509V3_conf_free);
+ value = NULL;
+
+ if (meth->it) {
+ ASN1_item_free(reinterpret_cast<ASN1_VALUE*>(ext_str), meth->it);
+ } else {
+ meth->ext_free(ext_str);
+ }
+ ext_str = NULL;
}
if (ok)
break;
@@ -687,14 +720,22 @@
X509_free(certificate);
- if (!ok && ignore_bad_cert()) {
+ if (!ok && ignore_bad_cert) {
LOG(LS_WARNING) << "TLS certificate check FAILED. "
<< "Allowing connection anyway.";
ok = true;
}
- if (ok)
- ok = (SSL_get_verify_result(ssl) == X509_V_OK);
+ return ok;
+}
+
+bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
+ bool ok = VerifyServerName(ssl, host, ignore_bad_cert());
+
+ if (ok) {
+ ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
+ custom_verification_succeeded_);
+ }
if (!ok && ignore_bad_cert()) {
LOG(LS_INFO) << "Other TLS post connection checks failed.";
@@ -762,6 +803,16 @@
OpenSSLAdapter* stream =
reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
+ if (!ok && custom_verify_callback_) {
+ void* cert =
+ reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
+ if (custom_verify_callback_(cert)) {
+ stream->custom_verification_succeeded_ = true;
+ LOG(LS_INFO) << "validated certificate using custom callback";
+ ok = true;
+ }
+ }
+
if (!ok && stream->ignore_bad_cert()) {
LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
ok = 1;
@@ -770,13 +821,9 @@
return ok;
}
-SSL_CTX*
-OpenSSLAdapter::SetupSSLContext() {
- SSL_CTX* ctx = SSL_CTX_new(TLSv1_client_method());
- if (ctx == NULL)
- return NULL;
-
+bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
// Add the root cert to the SSL context
+ // TODO: this cert appears to be the wrong one.
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
const unsigned char* cert_buffer
#else
@@ -785,12 +832,20 @@
= EquifaxSecureGlobalEBusinessCA1_certificate;
size_t cert_buffer_len = sizeof(EquifaxSecureGlobalEBusinessCA1_certificate);
X509* cert = d2i_X509(NULL, &cert_buffer, cert_buffer_len);
- if (cert == NULL) {
- SSL_CTX_free(ctx);
+ if (cert == NULL)
+ return false;
+ bool success = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
+ X509_free(cert);
+ return success;
+}
+
+SSL_CTX*
+OpenSSLAdapter::SetupSSLContext() {
+ SSL_CTX* ctx = SSL_CTX_new(TLSv1_client_method());
+ if (ctx == NULL)
return NULL;
- }
- if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert)) {
- X509_free(cert);
+
+ if (!ConfigureTrustedRootCertificates(ctx)) {
SSL_CTX_free(ctx);
return NULL;
}
@@ -807,3 +862,5 @@
}
} // namespace talk_base
+
+#endif // HAVE_OPENSSL_SSL_H
diff --git a/talk/base/openssladapter.h b/talk/base/openssladapter.h
old mode 100755
new mode 100644
index b794a7b..c89c292
--- a/talk/base/openssladapter.h
+++ b/talk/base/openssladapter.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -41,6 +41,10 @@
class OpenSSLAdapter : public SSLAdapter {
public:
+ static bool InitializeSSL(VerificationCallback callback);
+ static bool InitializeSSLThread();
+ static bool CleanupSSL();
+
OpenSSLAdapter(AsyncSocket* socket);
virtual ~OpenSSLAdapter();
@@ -68,23 +72,30 @@
void Error(const char* context, int err, bool signal = true);
void Cleanup();
+ static bool VerifyServerName(SSL* ssl, const char* host,
+ bool ignore_bad_cert);
bool SSLPostConnectionCheck(SSL* ssl, const char* host);
#if _DEBUG
static void SSLInfoCallback(const SSL* s, int where, int ret);
#endif // !_DEBUG
static int SSLVerifyCallback(int ok, X509_STORE_CTX* store);
+ static VerificationCallback custom_verify_callback_;
+ friend class OpenSSLStreamAdapter; // for custom_verify_callback_;
+ static bool ConfigureTrustedRootCertificates(SSL_CTX* ctx);
static SSL_CTX* SetupSSLContext();
SSLState state_;
bool ssl_read_needs_write_;
bool ssl_write_needs_read_;
// If true, socket will retain SSL configuration after Close.
- bool restartable_;
+ bool restartable_;
SSL* ssl_;
SSL_CTX* ssl_ctx_;
std::string ssl_host_name_;
+
+ bool custom_verification_succeeded_;
};
/////////////////////////////////////////////////////////////////////////////
diff --git a/talk/base/opensslidentity.cc b/talk/base/opensslidentity.cc
new file mode 100644
index 0000000..a9d94b2
--- /dev/null
+++ b/talk/base/opensslidentity.cc
@@ -0,0 +1,274 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/opensslidentity.h"
+
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/crypto.h>
+
+#include "talk/base/logging.h"
+#include "talk/base/helpers.h"
+
+namespace talk_base {
+
+// We could have exposed a myriad of parameters for the crypto stuff,
+// but keeping it simple seems best.
+
+// Strength of generated keys. Those are RSA.
+static const int KEY_LENGTH = 1024;
+
+// Random bits for certificate serial number
+static const int SERIAL_RAND_BITS = 64;
+
+// Certificate validity lifetime
+static const int CERTIFICATE_LIFETIME = 60*60*24*365; // one year, arbitrarily
+
+// Generate a key pair. Caller is responsible for freeing the returned object.
+static EVP_PKEY* MakeKey() {
+ LOG(LS_INFO) << "Making key pair";
+ EVP_PKEY* pkey = EVP_PKEY_new();
+#if OPENSSL_VERSION_NUMBER < 0x00908000l
+ // Only RSA_generate_key is available. Use that.
+ RSA* rsa = RSA_generate_key(KEY_LENGTH, 0x10001, NULL, NULL);
+ if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ return NULL;
+ }
+#else
+ // RSA_generate_key is deprecated. Use _ex version.
+ BIGNUM* exponent = BN_new();
+ RSA* rsa = RSA_new();
+ if (!pkey || !exponent || !rsa ||
+ !BN_set_word(exponent, 0x10001) || // 65537 RSA exponent
+ !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) ||
+ !EVP_PKEY_assign_RSA(pkey, rsa)) {
+ EVP_PKEY_free(pkey);
+ BN_free(exponent);
+ RSA_free(rsa);
+ return NULL;
+ }
+ // ownership of rsa struct was assigned, don't free it.
+ BN_free(exponent);
+#endif
+ LOG(LS_INFO) << "Returning key pair";
+ return pkey;
+}
+
+// Generate a self-signed certificate, with the public key from the
+// given key pair. Caller is responsible for freeing the returned object.
+static X509* MakeCertificate(EVP_PKEY* pkey, const char* common_name) {
+ LOG(LS_INFO) << "Making certificate for " << common_name;
+ X509* x509 = NULL;
+ BIGNUM* serial_number = NULL;
+ X509_NAME* name = NULL;
+
+ if ((x509=X509_new()) == NULL)
+ goto error;
+
+ if (!X509_set_pubkey(x509, pkey))
+ goto error;
+
+ // serial number
+ // temporary reference to serial number inside x509 struct
+ ASN1_INTEGER* asn1_serial_number;
+ if (!(serial_number = BN_new()) ||
+ !BN_pseudo_rand(serial_number, SERIAL_RAND_BITS, 0, 0) ||
+ !(asn1_serial_number = X509_get_serialNumber(x509)) ||
+ !BN_to_ASN1_INTEGER(serial_number, asn1_serial_number))
+ goto error;
+
+ if (!X509_set_version(x509, 0L)) // version 1
+ goto error;
+
+ // There are a lot of possible components for the name entries. In
+ // our P2P SSL mode however, the certificates are pre-exchanged
+ // (through the secure XMPP channel), and so the certificate
+ // identification is arbitrary. It can't be empty, so we set some
+ // arbitrary common_name. Note that this certificate goes out in
+ // clear during SSL negotiation, so there may be a privacy issue in
+ // putting anything recognizable here.
+ if (!(name = X509_NAME_new()) ||
+ !X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8,
+ (unsigned char*)common_name, -1, -1, 0) ||
+ !X509_set_subject_name(x509, name) ||
+ !X509_set_issuer_name(x509, name))
+ goto error;
+
+ if (!X509_gmtime_adj(X509_get_notBefore(x509), 0) ||
+ !X509_gmtime_adj(X509_get_notAfter(x509), CERTIFICATE_LIFETIME))
+ goto error;
+
+ if (!X509_sign(x509, pkey, EVP_sha1()))
+ goto error;
+
+ BN_free(serial_number);
+ X509_NAME_free(name);
+ LOG(LS_INFO) << "Returning certificate";
+ return x509;
+
+ error:
+ BN_free(serial_number);
+ X509_NAME_free(name);
+ X509_free(x509);
+ return NULL;
+}
+
+// This dumps the SSL error stack to the log.
+static void LogSSLErrors(const std::string& prefix) {
+ char error_buf[200];
+ unsigned long err;
+ while ((err = ERR_get_error())) {
+ ERR_error_string_n(err, error_buf, sizeof(error_buf));
+ LOG(LS_ERROR) << prefix << ": " << error_buf << "\n";
+ }
+}
+
+OpenSSLKeyPair* OpenSSLKeyPair::Generate() {
+ EVP_PKEY* pkey = MakeKey();
+ if (!pkey) {
+ LogSSLErrors("Generating key pair");
+ return NULL;
+ }
+ return new OpenSSLKeyPair(pkey);
+}
+
+OpenSSLKeyPair::~OpenSSLKeyPair() {
+ EVP_PKEY_free(pkey_);
+}
+
+void OpenSSLKeyPair::AddReference() {
+ CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY);
+}
+
+#ifdef _DEBUG
+// Print a certificate to the log, for debugging.
+static void PrintCert(X509* x509) {
+ BIO* temp_memory_bio = BIO_new(BIO_s_mem());
+ if (!temp_memory_bio) {
+ LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
+ return;
+ }
+ X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0);
+ BIO_write(temp_memory_bio, "\0", 1);
+ char* buffer;
+ BIO_get_mem_data(temp_memory_bio, &buffer);
+ LOG(LS_VERBOSE) << buffer;
+ BIO_free(temp_memory_bio);
+}
+#endif
+
+OpenSSLCertificate* OpenSSLCertificate::Generate(
+ OpenSSLKeyPair* key_pair, const std::string& common_name) {
+ std::string actual_common_name = common_name;
+ if (actual_common_name.empty())
+ // Use a random string, arbitrarily 8chars long.
+ actual_common_name = CreateRandomString(8);
+ X509* x509 = MakeCertificate(key_pair->pkey(), actual_common_name.c_str());
+ if (!x509) {
+ LogSSLErrors("Generating certificate");
+ return NULL;
+ }
+#ifdef _DEBUG
+ PrintCert(x509);
+#endif
+ return new OpenSSLCertificate(x509);
+}
+
+OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
+ const std::string& pem_string, int* pem_length) {
+ BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
+ if (!bio)
+ return NULL;
+ (void)BIO_set_close(bio, BIO_NOCLOSE);
+ BIO_set_mem_eof_return(bio, 0);
+ X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
+ const_cast<char*>("\0"));
+ char *ptr;
+ int remaining_length = BIO_get_mem_data(bio, &ptr);
+ BIO_free(bio);
+ if (pem_length)
+ *pem_length = pem_string.length() - remaining_length;
+ if (x509)
+ return new OpenSSLCertificate(x509);
+ else
+ return NULL;
+}
+
+OpenSSLCertificate::~OpenSSLCertificate() {
+ X509_free(x509_);
+}
+
+std::string OpenSSLCertificate::ToPEMString() const {
+ BIO* bio = BIO_new(BIO_s_mem());
+ if (!bio)
+ return NULL;
+ if (!PEM_write_bio_X509(bio, x509_)) {
+ BIO_free(bio);
+ return NULL;
+ }
+ BIO_write(bio, "\0", 1);
+ char* buffer;
+ BIO_get_mem_data(bio, &buffer);
+ std::string ret(buffer);
+ BIO_free(bio);
+ return ret;
+}
+
+void OpenSSLCertificate::AddReference() {
+ CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
+}
+
+OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) {
+ OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate();
+ if (key_pair) {
+ OpenSSLCertificate *certificate =
+ OpenSSLCertificate::Generate(key_pair, common_name);
+ if (certificate)
+ return new OpenSSLIdentity(key_pair, certificate);
+ delete key_pair;
+ }
+ LOG(LS_INFO) << "Identity generation failed";
+ return NULL;
+}
+
+bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
+ // 1 is the documented success return code.
+ if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 ||
+ SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
+ LogSSLErrors("Configuring key and certificate");
+ return false;
+ }
+ return true;
+}
+
+} // talk_base namespace
diff --git a/talk/base/opensslidentity.h b/talk/base/opensslidentity.h
new file mode 100644
index 0000000..7cac419
--- /dev/null
+++ b/talk/base/opensslidentity.h
@@ -0,0 +1,137 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_OPENSSLIDENTITY_H__
+#define TALK_BASE_OPENSSLIDENTITY_H__
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#include <string>
+
+#include "talk/base/common.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/sslidentity.h"
+
+typedef struct ssl_ctx_st SSL_CTX;
+
+namespace talk_base {
+
+// OpenSSLKeyPair encapsulates an OpenSSL EVP_PKEY* keypair object,
+// which is reference counted inside the OpenSSL library.
+class OpenSSLKeyPair {
+ public:
+ static OpenSSLKeyPair* Generate();
+
+ virtual ~OpenSSLKeyPair();
+
+ virtual OpenSSLKeyPair* GetReference() {
+ AddReference();
+ return new OpenSSLKeyPair(pkey_);
+ }
+
+ EVP_PKEY* pkey() const { return pkey_; }
+
+ private:
+ explicit OpenSSLKeyPair(EVP_PKEY* pkey) : pkey_(pkey) {
+ ASSERT(pkey_ != NULL);
+ }
+ void AddReference();
+
+ EVP_PKEY* pkey_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(OpenSSLKeyPair);
+};
+
+// OpenSSLCertificate encapsulates an OpenSSL X509* certificate object,
+// which is also reference counted inside the OpenSSL library.
+class OpenSSLCertificate : public SSLCertificate {
+ public:
+ static OpenSSLCertificate* Generate(OpenSSLKeyPair* key_pair,
+ const std::string& common_name);
+ static OpenSSLCertificate* FromPEMString(const std::string& pem_string,
+ int* pem_length);
+
+ virtual ~OpenSSLCertificate();
+
+ virtual OpenSSLCertificate* GetReference() {
+ AddReference();
+ return new OpenSSLCertificate(x509_);
+ }
+
+ X509* x509() const { return x509_; }
+
+ virtual std::string ToPEMString() const;
+
+ private:
+ explicit OpenSSLCertificate(X509* x509) : x509_(x509) {
+ ASSERT(x509_ != NULL);
+ }
+ void AddReference();
+
+ X509* x509_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(OpenSSLCertificate);
+};
+
+// Holds a keypair and certificate together, and a method to generate
+// them consistently.
+class OpenSSLIdentity : public SSLIdentity {
+ public:
+ static OpenSSLIdentity* Generate(const std::string& common_name);
+
+ virtual ~OpenSSLIdentity() { }
+
+ virtual OpenSSLCertificate& certificate() const {
+ return *certificate_;
+ }
+
+ virtual OpenSSLIdentity* GetReference() {
+ return new OpenSSLIdentity(key_pair_->GetReference(),
+ certificate_->GetReference());
+ }
+
+ // Configure an SSL context object to use our key and certificate.
+ bool ConfigureIdentity(SSL_CTX* ctx);
+
+ private:
+ OpenSSLIdentity(OpenSSLKeyPair* key_pair,
+ OpenSSLCertificate* certificate)
+ : key_pair_(key_pair), certificate_(certificate) {
+ ASSERT(key_pair != NULL);
+ ASSERT(certificate != NULL);
+ }
+
+ scoped_ptr<OpenSSLKeyPair> key_pair_;
+ scoped_ptr<OpenSSLCertificate> certificate_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(OpenSSLIdentity);
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_OPENSSLIDENTITY_H__
diff --git a/talk/base/opensslstreamadapter.cc b/talk/base/opensslstreamadapter.cc
new file mode 100644
index 0000000..6a34e13
--- /dev/null
+++ b/talk/base/opensslstreamadapter.cc
@@ -0,0 +1,650 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#if HAVE_OPENSSL_SSL_H
+
+#include "talk/base/opensslstreamadapter.h"
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/stream.h"
+#include "talk/base/openssladapter.h"
+#include "talk/base/opensslidentity.h"
+#include "talk/base/stringutils.h"
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// StreamBIO
+//////////////////////////////////////////////////////////////////////
+
+static int stream_write(BIO* h, const char* buf, int num);
+static int stream_read(BIO* h, char* buf, int size);
+static int stream_puts(BIO* h, const char* str);
+static long stream_ctrl(BIO* h, int cmd, long arg1, void* arg2);
+static int stream_new(BIO* h);
+static int stream_free(BIO* data);
+
+static BIO_METHOD methods_stream = {
+ BIO_TYPE_BIO,
+ "stream",
+ stream_write,
+ stream_read,
+ stream_puts,
+ 0,
+ stream_ctrl,
+ stream_new,
+ stream_free,
+ NULL,
+};
+
+static BIO_METHOD* BIO_s_stream() { return(&methods_stream); }
+
+static BIO* BIO_new_stream(StreamInterface* stream) {
+ BIO* ret = BIO_new(BIO_s_stream());
+ if (ret == NULL)
+ return NULL;
+ ret->ptr = stream;
+ return ret;
+}
+
+// bio methods return 1 (or at least non-zero) on success and 0 on failure.
+
+static int stream_new(BIO* b) {
+ b->shutdown = 0;
+ b->init = 1;
+ b->num = 0; // 1 means end-of-stream
+ b->ptr = 0;
+ return 1;
+}
+
+static int stream_free(BIO* b) {
+ if (b == NULL)
+ return 0;
+ return 1;
+}
+
+static int stream_read(BIO* b, char* out, int outl) {
+ if (!out)
+ return -1;
+ StreamInterface* stream = static_cast<StreamInterface*>(b->ptr);
+ BIO_clear_retry_flags(b);
+ size_t read;
+ int error;
+ StreamResult result = stream->Read(out, outl, &read, &error);
+ if (result == SR_SUCCESS) {
+ return read;
+ } else if (result == SR_EOS) {
+ b->num = 1;
+ } else if (result == SR_BLOCK) {
+ BIO_set_retry_read(b);
+ }
+ return -1;
+}
+
+static int stream_write(BIO* b, const char* in, int inl) {
+ if (!in)
+ return -1;
+ StreamInterface* stream = static_cast<StreamInterface*>(b->ptr);
+ BIO_clear_retry_flags(b);
+ size_t written;
+ int error;
+ StreamResult result = stream->Write(in, inl, &written, &error);
+ if (result == SR_SUCCESS) {
+ return written;
+ } else if (result == SR_BLOCK) {
+ BIO_set_retry_write(b);
+ }
+ return -1;
+}
+
+static int stream_puts(BIO* b, const char* str) {
+ return stream_write(b, str, strlen(str));
+}
+
+static long stream_ctrl(BIO* b, int cmd, long num, void* ptr) {
+ UNUSED(num);
+ UNUSED(ptr);
+
+ switch (cmd) {
+ case BIO_CTRL_RESET:
+ return 0;
+ case BIO_CTRL_EOF:
+ return b->num;
+ case BIO_CTRL_WPENDING:
+ case BIO_CTRL_PENDING:
+ return 0;
+ case BIO_CTRL_FLUSH:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// OpenSSLStreamAdapter
+/////////////////////////////////////////////////////////////////////////////
+
+OpenSSLStreamAdapter::OpenSSLStreamAdapter(StreamInterface* stream)
+ : SSLStreamAdapter(stream),
+ state_(SSL_NONE),
+ role_(SSL_CLIENT),
+ ssl_read_needs_write_(false), ssl_write_needs_read_(false),
+ ssl_(NULL), ssl_ctx_(NULL),
+ custom_verification_succeeded_(false) {
+}
+
+OpenSSLStreamAdapter::~OpenSSLStreamAdapter() {
+ Cleanup();
+}
+
+void OpenSSLStreamAdapter::SetIdentity(SSLIdentity* identity) {
+ ASSERT(identity_.get() == NULL);
+ identity_.reset(static_cast<OpenSSLIdentity*>(identity));
+}
+
+void OpenSSLStreamAdapter::SetServerRole() {
+ role_ = SSL_SERVER;
+}
+
+void OpenSSLStreamAdapter::SetPeerCertificate(SSLCertificate* cert) {
+ ASSERT(peer_certificate_.get() == NULL);
+ ASSERT(ssl_server_name_.empty());
+ peer_certificate_.reset(static_cast<OpenSSLCertificate*>(cert));
+}
+
+int OpenSSLStreamAdapter::StartSSLWithServer(const char* server_name) {
+ ASSERT(server_name != NULL && server_name[0] != '\0');
+ ssl_server_name_ = server_name;
+ return StartSSL();
+}
+
+int OpenSSLStreamAdapter::StartSSLWithPeer() {
+ ASSERT(ssl_server_name_.empty());
+ // It is permitted to specify peer_certificate_ only later.
+ return StartSSL();
+}
+
+//
+// StreamInterface Implementation
+//
+
+StreamResult OpenSSLStreamAdapter::Write(const void* data, size_t data_len,
+ size_t* written, int* error) {
+ LOG(LS_INFO) << "OpenSSLStreamAdapter::Write(" << data_len << ")";
+
+ switch (state_) {
+ case SSL_NONE:
+ // pass-through in clear text
+ return StreamAdapterInterface::Write(data, data_len, written, error);
+
+ case SSL_WAIT:
+ case SSL_CONNECTING:
+ return SR_BLOCK;
+
+ case SSL_CONNECTED:
+ break;
+
+ case SSL_ERROR:
+ case SSL_CLOSED:
+ default:
+ if (error)
+ *error = ssl_error_code_;
+ return SR_ERROR;
+ }
+
+ // OpenSSL will return an error if we try to write zero bytes
+ if (data_len == 0) {
+ if (written)
+ *written = 0;
+ return SR_SUCCESS;
+ }
+
+ ssl_write_needs_read_ = false;
+
+ int code = SSL_write(ssl_, data, data_len);
+ switch (SSL_get_error(ssl_, code)) {
+ case SSL_ERROR_NONE:
+ LOG(LS_INFO) << " -- success";
+ ASSERT(0 < code && static_cast<unsigned>(code) <= data_len);
+ if (written)
+ *written = code;
+ return SR_SUCCESS;
+ case SSL_ERROR_WANT_READ:
+ LOG(LS_INFO) << " -- error want read";
+ ssl_write_needs_read_ = true;
+ return SR_BLOCK;
+ case SSL_ERROR_WANT_WRITE:
+ LOG(LS_INFO) << " -- error want write";
+ return SR_BLOCK;
+
+ case SSL_ERROR_ZERO_RETURN:
+ default:
+ Error("SSL_write", (code ? code : -1), false);
+ if (error)
+ *error = ssl_error_code_;
+ return SR_ERROR;
+ }
+ // not reached
+}
+
+StreamResult OpenSSLStreamAdapter::Read(void* data, size_t data_len,
+ size_t* read, int* error) {
+ LOG(LS_INFO) << "OpenSSLStreamAdapter::Read(" << data_len << ")";
+ switch (state_) {
+ case SSL_NONE:
+ // pass-through in clear text
+ return StreamAdapterInterface::Read(data, data_len, read, error);
+
+ case SSL_WAIT:
+ case SSL_CONNECTING:
+ return SR_BLOCK;
+
+ case SSL_CONNECTED:
+ break;
+
+ case SSL_CLOSED:
+ return SR_EOS;
+
+ case SSL_ERROR:
+ default:
+ if (error)
+ *error = ssl_error_code_;
+ return SR_ERROR;
+ }
+
+ // Don't trust OpenSSL with zero byte reads
+ if (data_len == 0) {
+ if (read)
+ *read = 0;
+ return SR_SUCCESS;
+ }
+
+ ssl_read_needs_write_ = false;
+
+ int code = SSL_read(ssl_, data, data_len);
+ switch (SSL_get_error(ssl_, code)) {
+ case SSL_ERROR_NONE:
+ LOG(LS_INFO) << " -- success";
+ ASSERT(0 < code && static_cast<unsigned>(code) <= data_len);
+ if (read)
+ *read = code;
+ return SR_SUCCESS;
+ case SSL_ERROR_WANT_READ:
+ LOG(LS_INFO) << " -- error want read";
+ return SR_BLOCK;
+ case SSL_ERROR_WANT_WRITE:
+ LOG(LS_INFO) << " -- error want write";
+ ssl_read_needs_write_ = true;
+ return SR_BLOCK;
+ case SSL_ERROR_ZERO_RETURN:
+ LOG(LS_INFO) << " -- remote side closed";
+ return SR_EOS;
+ break;
+ default:
+ LOG(LS_INFO) << " -- error " << code;
+ Error("SSL_read", (code ? code : -1), false);
+ if (error)
+ *error = ssl_error_code_;
+ return SR_ERROR;
+ }
+ // not reached
+}
+
+void OpenSSLStreamAdapter::Close() {
+ Cleanup();
+ ASSERT(state_ == SSL_CLOSED || state_ == SSL_ERROR);
+ StreamAdapterInterface::Close();
+}
+
+StreamState OpenSSLStreamAdapter::GetState() const {
+ switch(state_) {
+ case SSL_WAIT:
+ case SSL_CONNECTING:
+ return SS_OPENING;
+ case SSL_CONNECTED:
+ return SS_OPEN;
+ default:
+ return SS_CLOSED;
+ };
+ // not reached
+}
+
+void OpenSSLStreamAdapter::OnEvent(StreamInterface* stream, int events,
+ int err) {
+ int events_to_signal = 0;
+ int signal_error = 0;
+ ASSERT(stream == this->stream());
+ if ((events & SE_OPEN)) {
+ LOG(LS_INFO) << "OpenSSLStreamAdapter::OnEvent SE_OPEN";
+ if (state_ != SSL_WAIT) {
+ ASSERT(state_ == SSL_NONE);
+ events_to_signal |= SE_OPEN;
+ } else {
+ state_ = SSL_CONNECTING;
+ if (int err = BeginSSL()) {
+ Error("BeginSSL", err, true);
+ return;
+ }
+ }
+ }
+ if ((events & (SE_READ|SE_WRITE))) {
+ LOG(LS_INFO) << "OpenSSLStreamAdapter::OnEvent"
+ << ((events & SE_READ) ? " SE_READ" : "")
+ << ((events & SE_WRITE) ? " SE_WRITE" : "");
+ if (state_ == SSL_NONE) {
+ events_to_signal |= events & (SE_READ|SE_WRITE);
+ } else if (state_ == SSL_CONNECTING) {
+ if (int err = ContinueSSL()) {
+ Error("ContinueSSL", err, true);
+ return;
+ }
+ } else if (state_ == SSL_CONNECTED) {
+ if (((events & SE_READ) && ssl_write_needs_read_) ||
+ (events & SE_WRITE)) {
+ LOG(LS_INFO) << " -- onStreamWriteable";
+ events_to_signal |= SE_WRITE;
+ }
+ if (((events & SE_WRITE) && ssl_read_needs_write_) ||
+ (events & SE_READ)) {
+ LOG(LS_INFO) << " -- onStreamReadable";
+ events_to_signal |= SE_READ;
+ }
+ }
+ }
+ if ((events & SE_CLOSE)) {
+ LOG(LS_INFO) << "OpenSSLStreamAdapter::OnEvent(SE_CLOSE, " << err << ")";
+ Cleanup();
+ events_to_signal |= SE_CLOSE;
+ // SE_CLOSE is the only event that uses the final parameter to OnEvent().
+ ASSERT(signal_error == 0);
+ signal_error = err;
+ }
+ if(events_to_signal)
+ StreamAdapterInterface::OnEvent(stream, events_to_signal, signal_error);
+}
+
+int OpenSSLStreamAdapter::StartSSL() {
+ ASSERT(state_ == SSL_NONE);
+
+ if (StreamAdapterInterface::GetState() != SS_OPEN) {
+ state_ = SSL_WAIT;
+ return 0;
+ }
+
+ state_ = SSL_CONNECTING;
+ if (int err = BeginSSL()) {
+ Error("BeginSSL", err, false);
+ return err;
+ }
+
+ return 0;
+}
+
+int OpenSSLStreamAdapter::BeginSSL() {
+ ASSERT(state_ == SSL_CONNECTING);
+ // The underlying stream has open. If we are in peer-to-peer mode
+ // then a peer certificate must have been specified by now.
+ ASSERT(!ssl_server_name_.empty() || peer_certificate_.get() != NULL);
+ LOG(LS_INFO) << "BeginSSL: "
+ << (!ssl_server_name_.empty() ? ssl_server_name_ :
+ "with peer");
+
+ BIO* bio = NULL;
+
+ // First set up the context
+ ASSERT(ssl_ctx_ == NULL);
+ ssl_ctx_ = SetupSSLContext();
+ if (!ssl_ctx_)
+ return -1;
+
+ bio = BIO_new_stream(static_cast<StreamInterface*>(stream()));
+ if (!bio)
+ return -1;
+
+ ssl_ = SSL_new(ssl_ctx_);
+ if (!ssl_) {
+ BIO_free(bio);
+ return -1;
+ }
+
+ SSL_set_app_data(ssl_, this);
+
+ SSL_set_bio(ssl_, bio, bio); // the SSL object owns the bio now.
+
+ SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ // Do the connect
+ return ContinueSSL();
+}
+
+int OpenSSLStreamAdapter::ContinueSSL() {
+ LOG(LS_INFO) << "ContinueSSL";
+ ASSERT(state_ == SSL_CONNECTING);
+
+ int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
+ switch (SSL_get_error(ssl_, code)) {
+ case SSL_ERROR_NONE:
+ LOG(LS_INFO) << " -- success";
+
+ if (!SSLPostConnectionCheck(ssl_, ssl_server_name_.c_str(),
+ peer_certificate_.get() != NULL
+ ? peer_certificate_->x509() : NULL)) {
+ LOG(LS_ERROR) << "TLS post connection check failed";
+ return -1;
+ }
+
+ state_ = SSL_CONNECTED;
+ StreamAdapterInterface::OnEvent(stream(), SE_OPEN|SE_READ|SE_WRITE, 0);
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ LOG(LS_INFO) << " -- error want read";
+ break;
+
+ case SSL_ERROR_WANT_WRITE:
+ LOG(LS_INFO) << " -- error want write";
+ break;
+
+ case SSL_ERROR_ZERO_RETURN:
+ default:
+ LOG(LS_INFO) << " -- error " << code;
+ return (code != 0) ? code : -1;
+ }
+
+ return 0;
+}
+
+void OpenSSLStreamAdapter::Error(const char* context, int err, bool signal) {
+ LOG(LS_WARNING) << "OpenSSLStreamAdapter::Error("
+ << context << ", " << err << ")";
+ state_ = SSL_ERROR;
+ ssl_error_code_ = err;
+ Cleanup();
+ if (signal)
+ StreamAdapterInterface::OnEvent(stream(), SE_CLOSE, err);
+}
+
+void OpenSSLStreamAdapter::Cleanup() {
+ LOG(LS_INFO) << "Cleanup";
+
+ if (state_ != SSL_ERROR) {
+ state_ = SSL_CLOSED;
+ ssl_error_code_ = 0;
+ }
+
+ if (ssl_) {
+ SSL_free(ssl_);
+ ssl_ = NULL;
+ }
+ if (ssl_ctx_) {
+ SSL_CTX_free(ssl_ctx_);
+ ssl_ctx_ = NULL;
+ }
+ identity_.reset();
+ peer_certificate_.reset();
+}
+
+SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
+ SSL_CTX* ctx = SSL_CTX_new(role_ == SSL_CLIENT ? TLSv1_client_method()
+ : TLSv1_server_method());
+ if (ctx == NULL)
+ return NULL;
+
+ if (identity_.get() && !identity_->ConfigureIdentity(ctx)) {
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
+
+ if (peer_certificate_.get() == NULL) { // traditional mode
+ // Add the root cert to the SSL context
+ if(!OpenSSLAdapter::ConfigureTrustedRootCertificates(ctx)) {
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
+ }
+
+ if (peer_certificate_.get() != NULL && role_ == SSL_SERVER)
+ // we must specify which client cert to ask for
+ SSL_CTX_add_client_CA(ctx, peer_certificate_->x509());
+
+#ifdef _DEBUG
+ SSL_CTX_set_info_callback(ctx, OpenSSLAdapter::SSLInfoCallback);
+#endif
+
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ SSLVerifyCallback);
+ SSL_CTX_set_verify_depth(ctx, 4);
+ SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+
+ return ctx;
+}
+
+int OpenSSLStreamAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
+#if _DEBUG
+ if (!ok) {
+ char data[256];
+ X509* cert = X509_STORE_CTX_get_current_cert(store);
+ int depth = X509_STORE_CTX_get_error_depth(store);
+ int err = X509_STORE_CTX_get_error(store);
+
+ LOG(LS_INFO) << "Error with certificate at depth: " << depth;
+ X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
+ LOG(LS_INFO) << " issuer = " << data;
+ X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
+ LOG(LS_INFO) << " subject = " << data;
+ LOG(LS_INFO) << " err = " << err
+ << ":" << X509_verify_cert_error_string(err);
+ }
+#endif
+
+ // Get our SSL structure from the store
+ SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(
+ store,
+ SSL_get_ex_data_X509_STORE_CTX_idx()));
+
+ OpenSSLStreamAdapter* stream =
+ reinterpret_cast<OpenSSLStreamAdapter*>(SSL_get_app_data(ssl));
+
+ // In peer-to-peer mode, no root cert / certificate authority was
+ // specified, so the libraries knows of no certificate to accept,
+ // and therefore it will necessarily call here on the first cert it
+ // tries to verify.
+ if (!ok && stream->peer_certificate_.get() != NULL) {
+ X509* cert = X509_STORE_CTX_get_current_cert(store);
+ int err = X509_STORE_CTX_get_error(store);
+ // peer-to-peer mode: allow the certificate to be self-signed,
+ // assuming it matches the cert that was specified.
+ if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
+ X509_cmp(cert, stream->peer_certificate_->x509()) == 0) {
+ LOG(LS_INFO) << "Accepted self-signed peer certificate authority";
+ ok = 1;
+ }
+ } else if (!ok && OpenSSLAdapter::custom_verify_callback_) {
+ // this applies only in traditional mode
+ void* cert =
+ reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
+ if (OpenSSLAdapter::custom_verify_callback_(cert)) {
+ stream->custom_verification_succeeded_ = true;
+ LOG(LS_INFO) << "validated certificate using custom callback";
+ ok = 1;
+ }
+ }
+
+ if (!ok && stream->ignore_bad_cert()) {
+ LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
+ ok = 1;
+ }
+
+ return ok;
+}
+
+// This code is taken from the "Network Security with OpenSSL"
+// sample in chapter 5
+bool OpenSSLStreamAdapter::SSLPostConnectionCheck(SSL* ssl,
+ const char* server_name,
+ const X509* peer_cert) {
+ ASSERT(server_name != NULL);
+ bool ok;
+ if(server_name[0] != '\0') { // traditional mode
+ ok = OpenSSLAdapter::VerifyServerName(ssl, server_name, ignore_bad_cert());
+
+ if (ok) {
+ ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
+ custom_verification_succeeded_);
+ }
+ } else { // peer-to-peer mode
+ ASSERT(peer_cert != NULL);
+ // no server name validation
+ ok = true;
+ }
+
+ if (!ok && ignore_bad_cert()) {
+ LOG(LS_ERROR) << "SSL_get_verify_result(ssl) = "
+ << SSL_get_verify_result(ssl);
+ LOG(LS_INFO) << "Other TLS post connection checks failed.";
+ ok = true;
+ }
+
+ return ok;
+}
+
+} // namespace talk_base
+
+#endif // HAVE_OPENSSL_SSL_H
diff --git a/talk/base/opensslstreamadapter.h b/talk/base/opensslstreamadapter.h
new file mode 100644
index 0000000..16ec751
--- /dev/null
+++ b/talk/base/opensslstreamadapter.h
@@ -0,0 +1,171 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_OPENSSLSTREAMADAPTER_H__
+#define TALK_BASE_OPENSSLSTREAMADAPTER_H__
+
+#include <string>
+#include "talk/base/sslstreamadapter.h"
+#include "talk/base/opensslidentity.h"
+
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+
+namespace talk_base {
+
+// This class was written with OpenSSLAdapter (a socket adapter) as a
+// starting point. It has similar structure and functionality, with
+// the peer-to-peer mode added.
+//
+// Static methods to initialize and deinit the SSL library are in
+// OpenSSLAdapter. This class also uses
+// OpenSSLAdapter::custom_verify_callback_ (a static field). These
+// should probably be moved out to a neutral class.
+//
+// In a few cases I have factored out some OpenSSLAdapter code into
+// static methods so it can be reused from this class. Eventually that
+// code should probably be moved to a common support
+// class. Unfortunately there remain a few duplicated sections of
+// code. I have not done more restructuring because I did not want to
+// affect existing code that uses OpenSSLAdapter.
+//
+// This class does not support the SSL connection restart feature
+// present in OpenSSLAdapter. I am not entirely sure how the feature
+// is useful and I am not convinced that it works properly.
+//
+// This implementation is careful to disallow data exchange after an
+// SSL error, and it has an explicit SSL_CLOSED state. It should not
+// be possible to send any data in clear after one of the StartSSL
+// methods has been called.
+
+// Look in sslstreamadapter.h for documentation of the methods.
+
+class OpenSSLIdentity;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class OpenSSLStreamAdapter : public SSLStreamAdapter {
+ public:
+ explicit OpenSSLStreamAdapter(StreamInterface* stream);
+ virtual ~OpenSSLStreamAdapter();
+
+ virtual void SetIdentity(SSLIdentity* identity);
+ virtual void SetServerRole();
+ virtual void SetPeerCertificate(SSLCertificate* cert);
+
+ virtual int StartSSLWithServer(const char* server_name);
+ virtual int StartSSLWithPeer();
+
+ virtual StreamResult Read(void* data, size_t data_len,
+ size_t* read, int* error);
+ virtual StreamResult Write(const void* data, size_t data_len,
+ size_t* written, int* error);
+ virtual void Close();
+ virtual StreamState GetState() const;
+
+ protected:
+ virtual void OnEvent(StreamInterface* stream, int events, int err);
+
+ private:
+ enum SSLState {
+ // Before calling one of the StartSSL methods, data flows
+ // in clear text.
+ SSL_NONE,
+ SSL_WAIT, // waiting for the stream to open to start SSL negotiation
+ SSL_CONNECTING, // SSL negotiation in progress
+ SSL_CONNECTED, // SSL stream successfully established
+ SSL_ERROR, // some SSL error occurred, stream is closed
+ SSL_CLOSED // Clean close
+ };
+ enum SSLRole {
+ SSL_CLIENT, SSL_SERVER
+ };
+
+ // The following three methods return 0 on success and a negative
+ // error code on failure. The error code may be from OpenSSL or -1
+ // on some other error cases, so it can't really be interpreted
+ // unfortunately.
+
+ // Go from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT,
+ // depending on whether the underlying stream is already open or
+ // not.
+ int StartSSL();
+ // Prepare SSL library, state is SSL_CONNECTING.
+ int BeginSSL();
+ // Perform SSL negotiation steps.
+ int ContinueSSL();
+
+ // Error handler helper. signal is given as true for errors in
+ // asynchronous contexts (when an error method was not returned
+ // through some other method), and in that case an SE_CLOSE event is
+ // raised on the stream with the specified error.
+ // A 0 error means a graceful close, otherwise there is not really enough
+ // context to interpret the error code.
+ void Error(const char* context, int err, bool signal);
+ void Cleanup();
+
+ // SSL library configuration
+ SSL_CTX* SetupSSLContext();
+ // SSL verification check
+ bool SSLPostConnectionCheck(SSL* ssl, const char* server_name,
+ const X509* peer_cert);
+ // SSL certification verification error handler, called back from
+ // the openssl library. Returns an int interpreted as a boolean in
+ // the C style: zero means verification failure, non-zero means
+ // passed.
+ static int SSLVerifyCallback(int ok, X509_STORE_CTX* store);
+
+
+ SSLState state_;
+ SSLRole role_;
+ int ssl_error_code_; // valid when state_ == SSL_ERROR or SSL_CLOSED
+ // Whether the SSL negotiation is blocked on needing to read or
+ // write to the wrapped stream.
+ bool ssl_read_needs_write_;
+ bool ssl_write_needs_read_;
+
+ SSL* ssl_;
+ SSL_CTX* ssl_ctx_;
+ // in traditional mode, the server name that the server's certificate
+ // must specify. Empty in peer-to-peer mode.
+ // Our key and certificate, mostly useful in peer-to-peer mode.
+ scoped_ptr<OpenSSLIdentity> identity_;
+ std::string ssl_server_name_;
+ // In peer-to-peer mode, the certificate that the peer must
+ // present. Empty in traditional mode.
+ scoped_ptr<OpenSSLCertificate> peer_certificate_;
+
+ // OpenSSLAdapter::custom_verify_callback_ result
+ bool custom_verification_succeeded_;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_OPENSSLSTREAMADAPTER_H__
diff --git a/talk/base/pathutils.cc b/talk/base/pathutils.cc
old mode 100755
new mode 100644
index 4a77879..d56373b
--- a/talk/base/pathutils.cc
+++ b/talk/base/pathutils.cc
@@ -33,6 +33,8 @@
#endif // WIN32
#include "talk/base/common.h"
+#include "talk/base/fileutils.h"
+#include "talk/base/logging.h"
#include "talk/base/pathutils.h"
#include "talk/base/stringutils.h"
#include "talk/base/urlencode.h"
@@ -62,15 +64,24 @@
return (NULL != ::strchr(FOLDER_DELIMS, ch));
}
+char Pathname::DefaultFolderDelimiter() {
+ return DEFAULT_FOLDER_DELIM;
+}
+
Pathname::Pathname()
- : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
+ : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
}
Pathname::Pathname(const std::string& pathname)
- : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
+ : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
SetPathname(pathname);
}
+Pathname::Pathname(const std::string& folder, const std::string& filename)
+ : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
+ SetPathname(folder, filename);
+}
+
void Pathname::SetFolderDelimiter(char delimiter) {
ASSERT(IsFolderDelimiter(delimiter));
folder_delimiter_ = delimiter;
@@ -90,29 +101,36 @@
extension_.clear();
}
+bool Pathname::empty() const {
+ return folder_.empty() && basename_.empty() && extension_.empty();
+}
+
std::string Pathname::pathname() const {
std::string pathname(folder_);
pathname.append(basename_);
pathname.append(extension_);
+ if (pathname.empty()) {
+ // Instead of the empty pathname, return the current working directory.
+ pathname.push_back('.');
+ pathname.push_back(folder_delimiter_);
+ }
return pathname;
}
std::string Pathname::url() const {
- std::string s = "file://";
+ std::string s = "file:///";
for (size_t i=0; i<folder_.length(); ++i) {
- if (i == 1 && folder_[i] == ':') // drive letter
- s += '|';
- else if (IsFolderDelimiter(folder_[i]))
+ if (IsFolderDelimiter(folder_[i]))
s += '/';
else
s += folder_[i];
}
s += basename_;
s += extension_;
- return UrlEncodeString(s);
+ return UrlEncodeStringForOnlyUnsafeChars(s);
}
-void Pathname::SetPathname(const std::string &pathname) {
+void Pathname::SetPathname(const std::string& pathname) {
std::string::size_type pos = pathname.find_last_of(FOLDER_DELIMS);
if (pos != std::string::npos) {
SetFolder(pathname.substr(0, pos + 1));
@@ -123,9 +141,15 @@
}
}
-void Pathname::AppendPathname(const Pathname& pathname) {
+void Pathname::SetPathname(const std::string& folder,
+ const std::string& filename) {
+ SetFolder(folder);
+ SetFilename(filename);
+}
+
+void Pathname::AppendPathname(const std::string& pathname) {
std::string full_pathname(folder_);
- full_pathname.append(pathname.pathname());
+ full_pathname.append(pathname);
SetPathname(full_pathname);
}
@@ -177,23 +201,29 @@
return basename_;
}
-void Pathname::SetBasename(const std::string& basename) {
- ASSERT(basename.find_first_of(FOLDER_DELIMS) == std::string::npos);
+bool Pathname::SetBasename(const std::string& basename) {
+ if(basename.find_first_of(FOLDER_DELIMS) != std::string::npos) {
+ return false;
+ }
basename_.assign(basename);
+ return true;
}
std::string Pathname::extension() const {
return extension_;
}
-void Pathname::SetExtension(const std::string& extension) {
- ASSERT(extension.find_first_of(FOLDER_DELIMS) == std::string::npos);
- ASSERT(extension.find_first_of(EXT_DELIM, 1) == std::string::npos);
+bool Pathname::SetExtension(const std::string& extension) {
+ if (extension.find_first_of(FOLDER_DELIMS) != std::string::npos ||
+ extension.find_first_of(EXT_DELIM, 1) != std::string::npos) {
+ return false;
+ }
extension_.assign(extension);
// Ensure extension begins with the extension delimiter
if (!extension_.empty() && (extension_[0] != EXT_DELIM)) {
extension_.insert(extension_.begin(), EXT_DELIM);
}
+ return true;
}
std::string Pathname::filename() const {
@@ -202,225 +232,37 @@
return filename;
}
-void Pathname::SetFilename(const std::string& filename) {
+bool Pathname::SetFilename(const std::string& filename) {
std::string::size_type pos = filename.rfind(EXT_DELIM);
if ((pos == std::string::npos) || (pos == 0)) {
- SetBasename(filename);
- SetExtension(EMPTY_STR);
+ return SetExtension(EMPTY_STR) && SetBasename(filename);
} else {
- SetBasename(filename.substr(0, pos));
- SetExtension(filename.substr(pos));
+ return SetExtension(filename.substr(pos)) && SetBasename(filename.substr(0, pos));
}
}
-///////////////////////////////////////////////////////////////////////////////
-// CreateUniqueFile
-///////////////////////////////////////////////////////////////////////////////
-
-std::string g_organization_name;
-std::string g_application_name;
-
-void SetOrganizationName(const std::string& organization) {
- g_organization_name = organization;
-}
-
-void SetApplicationName(const std::string& application) {
- g_application_name = application;
-}
-
-bool CreateFolder(const talk_base::Pathname& path) {
#ifdef WIN32
- if (!path.filename().empty())
- return false;
-
- std::wstring pathname16 = ToUtf16(path.pathname());
- if (!pathname16.empty() && (pathname16[0] != '\\')) {
- pathname16 = L"\\\\?\\" + pathname16;
- }
-
- DWORD res = ::GetFileAttributes(pathname16.c_str());
- if (res != INVALID_FILE_ATTRIBUTES) {
- // Something exists at this location, check if it is a directory
- return ((res & FILE_ATTRIBUTE_DIRECTORY) != 0);
- } else if ((GetLastError() != ERROR_FILE_NOT_FOUND)
- && (GetLastError() != ERROR_PATH_NOT_FOUND)) {
- // Unexpected error
- return false;
- }
-
- // Directory doesn't exist, look up one directory level
- if (!path.parent_folder().empty()) {
- talk_base::Pathname parent(path);
- parent.SetFolder(path.parent_folder());
- if (!CreateFolder(parent)) {
- return false;
- }
- }
-
- return (::CreateDirectory(pathname16.c_str(), NULL) != 0);
-#else // !WIN32
- return false;
-#endif // !WIN32
+bool Pathname::GetDrive(char *drive, uint32 bytes) const {
+ return GetDrive(drive, bytes, folder_);
}
-bool FinishPath(talk_base::Pathname& path, bool create,
- const std::string& append) {
- if (!append.empty()) {
- path.AppendFolder(append);
- }
- if (create && !CreateFolder(path))
+// static
+bool Pathname::GetDrive(char *drive, uint32 bytes,
+ const std::string& pathname) {
+ // need at lease 4 bytes to save c:
+ if (bytes < 4 || pathname.size() < 3) {
return false;
- return true;
-}
-
-bool GetTemporaryFolder(talk_base::Pathname& path, bool create,
- const std::string& append) {
- ASSERT(!g_application_name.empty());
-#ifdef WIN32
- TCHAR buffer[MAX_PATH + 1];
- if (!::GetTempPath(ARRAY_SIZE(buffer), buffer))
- return false;
- if (!::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
- return false;
- size_t len = strlen(buffer);
- if ((len > 0) && (buffer[len-1] != __T('\\'))) {
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- __T("\\"));
}
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- ToUtf16(g_application_name).c_str());
- if ((len > 0) && (buffer[len-1] != __T('\\'))) {
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- __T("\\"));
- }
- if (len >= ARRAY_SIZE(buffer) - 1)
- return false;
- path.clear();
- path.SetFolder(ToUtf8(buffer));
- return FinishPath(path, create, append);
-#else // !WIN32
- return false;
-#endif // !WIN32
-}
-
-bool GetAppDataFolder(talk_base::Pathname& path, bool create,
- const std::string& append) {
- ASSERT(!g_organization_name.empty());
- ASSERT(!g_application_name.empty());
-#ifdef WIN32
- TCHAR buffer[MAX_PATH + 1];
- if (!::SHGetSpecialFolderPath(NULL, buffer, CSIDL_LOCAL_APPDATA, TRUE))
- return false;
- if (!::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
- return false;
- size_t len = talk_base::strcatn(buffer, ARRAY_SIZE(buffer), _T("\\"));
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- ToUtf16(g_organization_name).c_str());
- if ((len > 0) && (buffer[len-1] != __T('\\'))) {
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- __T("\\"));
- }
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- ToUtf16(g_application_name).c_str());
- if ((len > 0) && (buffer[len-1] != __T('\\'))) {
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- __T("\\"));
- }
- if (len >= ARRAY_SIZE(buffer) - 1)
- return false;
- path.clear();
- path.SetFolder(ToUtf8(buffer));
- return FinishPath(path, create, append);
-#else // !WIN32
- return false;
-#endif // !WIN32
-}
-
-bool CleanupTemporaryFolder() {
-#ifdef WIN32
- talk_base::Pathname temp_path;
- if (!GetTemporaryFolder(temp_path, false, ""))
- return false;
-
- std::wstring temp_path16 = ToUtf16(temp_path.pathname());
- temp_path16.append(1, '*');
- temp_path16.append(1, '\0');
-
- SHFILEOPSTRUCT file_op = { 0 };
- file_op.wFunc = FO_DELETE;
- file_op.pFrom = temp_path16.c_str();
- file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
- return (0 == SHFileOperation(&file_op));
-#else // !WIN32
- return false;
-#endif // !WIN32
-}
-#if 0
-bool CreateUnijqueFile(talk_base::Pathname& path, bool create_empty) {
-#ifdef WIN32
- // If not folder is supplied, use the temporary folder
- if (path.folder().empty()) {
- talk_base::Pathname temp_path;
- if (!GetTemporaryFolder(temp_path, true, "")) {
-
- return false;
- }
- path.SetFolder(temp_path.folder());
- }
- printf("path: %s\n", path.pathname());
- // If not filename is supplied, use a temporary name
- if (path.filename().empty()) {
- TCHAR filename[MAX_PATH];
- std::wstring folder((ToUtf16)(path.folder()));
- if (!::GetTempFileName(folder.c_str(), __T("gt"), 0, filename))
- return false;
- ASSERT(wcsncmp(folder.c_str(), filename, folder.length()) == 0);
- path.SetFilename(ToUtf8(filename + folder.length()));
- if (!create_empty) {
- VERIFY(::DeleteFile(ToUtf16(path.pathname()).c_str()) != FALSE);
- }
- return true;
- }
- // Otherwise, create a unique name based on the given filename
- // foo.txt -> foo-N.txt
- const std::string basename = path.basename();
- const size_t MAX_VERSION = 100;
- size_t version = 0;
- while (version < MAX_VERSION) {
- std::string pathname = path.pathname();
- std::wstring pathname16 = ToUtf16(pathname).c_str();
-
- if (pathname16[0] != __T('\\'))
- pathname16 = __T("\\\\?\\") + pathname16;
-
- HANDLE hfile = CreateFile(pathname16.c_str(), GENERIC_WRITE, 0,
- NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hfile != INVALID_HANDLE_VALUE) {
- CloseHandle(hfile);
- if (!create_empty) {
- VERIFY(::DeleteFile(pathname16.c_str()) != FALSE);
- }
- return true;
- } else {
- int err = GetLastError();
- if (err != ERROR_FILE_EXISTS && err != ERROR_ACCESS_DENIED) {
- return false;
- }
- }
-
- version += 1;
- char version_base[MAX_PATH];
- talk_base::sprintfn(version_base, ARRAY_SIZE(version_base), "%s-%u",
- basename.c_str(), version);
- path.SetBasename(version_base);
- }
- return false;
-#else // !WIN32
- // TODO: Make this better.
- path.SetBasename("/tmp/temp-1");
-#endif // !WIN32
+
+ memcpy(drive, pathname.c_str(), 3);
+ drive[3] = 0;
+ // sanity checking
+ return (isalpha(drive[0]) &&
+ drive[1] == ':' &&
+ drive[2] == '\\');
}
#endif
+
///////////////////////////////////////////////////////////////////////////////
} // namespace talk_base
diff --git a/talk/base/pathutils.h b/talk/base/pathutils.h
old mode 100755
new mode 100644
index eb33edf..ab2aacd
--- a/talk/base/pathutils.h
+++ b/talk/base/pathutils.h
@@ -29,6 +29,8 @@
#define TALK_BASE_PATHUTILS_H__
#include <string>
+// Temporary, until deprecated helpers are removed.
+#include "talk/base/fileutils.h"
namespace talk_base {
@@ -56,9 +58,11 @@
public:
// Folder delimiters are slash and backslash
static bool IsFolderDelimiter(char ch);
+ static char DefaultFolderDelimiter();
Pathname();
Pathname(const std::string& pathname);
+ Pathname(const std::string& folder, const std::string& filename);
// Set's the default folder delimiter for this Pathname
char folder_delimiter() const { return folder_delimiter_; }
@@ -70,14 +74,22 @@
// Reset to the empty pathname
void clear();
+ // Returns true if the pathname is empty. Note: this->pathname().empty()
+ // is always false.
+ bool empty() const;
+
std::string url() const;
+ // Returns the folder and filename components. If the pathname is empty,
+ // returns a string representing the current directory (as a relative path,
+ // i.e., ".").
std::string pathname() const;
void SetPathname(const std::string& pathname);
+ void SetPathname(const std::string& folder, const std::string& filename);
// Append pathname to the current folder (if any). Any existing filename
// will be discarded.
- void AppendPathname(const Pathname& pathname);
+ void AppendPathname(const std::string& pathname);
std::string folder() const;
std::string folder_name() const;
@@ -87,21 +99,79 @@
void AppendFolder(const std::string& folder);
std::string basename() const;
- void SetBasename(const std::string& basename);
+ bool SetBasename(const std::string& basename);
std::string extension() const;
// SetExtension will prefix a period, if needed.
- void SetExtension(const std::string& extension);
+ bool SetExtension(const std::string& extension);
std::string filename() const;
- void SetFilename(const std::string& filename);
+ bool SetFilename(const std::string& filename);
+
+#ifdef WIN32
+ bool GetDrive(char *drive, uint32 bytes) const;
+ static bool GetDrive(char *drive, uint32 bytes,const std::string& pathname);
+#endif
private:
-
std::string folder_, basename_, extension_;
char folder_delimiter_;
};
+///////////////////////////////////////////////////////////////////////////////
+// Global Helpers (deprecated)
+///////////////////////////////////////////////////////////////////////////////
+
+inline void SetOrganizationName(const std::string& organization) {
+ Filesystem::SetOrganizationName(organization);
+}
+inline void SetApplicationName(const std::string& application) {
+ Filesystem::SetApplicationName(application);
+}
+inline void GetOrganizationName(std::string* organization) {
+ Filesystem::GetOrganizationName(organization);
+}
+inline void GetApplicationName(std::string* application) {
+ Filesystem::GetApplicationName(application);
+}
+inline bool CreateFolder(const Pathname& path) {
+ return Filesystem::CreateFolder(path);
+}
+inline bool FinishPath(Pathname& path, bool create, const std::string& append) {
+ if (!append.empty())
+ path.AppendFolder(append);
+ return !create || CreateFolder(path);
+}
+// Note: this method uses the convention of <temp>/<appname> for the temporary
+// folder. Filesystem uses <temp>/<exename>. We will be migrating exclusively
+// to <temp>/<orgname>/<appname> eventually. Since these are temp folders,
+// it's probably ok to orphan them during the transition.
+inline bool GetTemporaryFolder(Pathname& path, bool create,
+ const std::string& append) {
+ std::string application_name;
+ Filesystem::GetApplicationName(&application_name);
+ ASSERT(!application_name.empty());
+ return Filesystem::GetTemporaryFolder(path, create, &application_name)
+ && FinishPath(path, create, append);
+}
+inline bool GetAppDataFolder(Pathname& path, bool create,
+ const std::string& append) {
+ ASSERT(!create); // TODO: Support create flag on Filesystem::GetAppDataFolder.
+ return Filesystem::GetAppDataFolder(&path, true)
+ && FinishPath(path, create, append);
+}
+inline bool CleanupTemporaryFolder() {
+ Pathname path;
+ if (!GetTemporaryFolder(path, false, ""))
+ return false;
+ if (Filesystem::IsAbsent(path))
+ return true;
+ if (!Filesystem::IsTemporaryPath(path)) {
+ ASSERT(false);
+ return false;
+ }
+ return Filesystem::DeleteFolderContents(path);
+}
///////////////////////////////////////////////////////////////////////////////
diff --git a/talk/base/physicalsocketserver.cc b/talk/base/physicalsocketserver.cc
old mode 100755
new mode 100644
index 9cdacdf..d97cba7
--- a/talk/base/physicalsocketserver.cc
+++ b/talk/base/physicalsocketserver.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -32,66 +32,59 @@
#include <cassert>
#ifdef POSIX
-extern "C" {
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>
-}
+#include <signal.h>
#endif
#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
-#define _WINSOCKAPI_
-#include <windows.h>
#undef SetPort
#endif
#include <algorithm>
-#include <iostream>
+#include <map>
#include "talk/base/basictypes.h"
#include "talk/base/byteorder.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
+#include "talk/base/nethelpers.h"
#include "talk/base/physicalsocketserver.h"
#include "talk/base/time.h"
#include "talk/base/winping.h"
+#include "talk/base/win32socketinit.h"
-#ifdef __linux
+// stm: this will tell us if we are on OSX
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef POSIX
+#include <netinet/tcp.h> // for TCP_NODELAY
#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
-#endif // __linux
+typedef void* SockOptArg;
+#endif // POSIX
#ifdef WIN32
-class WinsockInitializer {
-public:
- WinsockInitializer() {
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD(1, 0);
- err_ = WSAStartup(wVersionRequested, &wsaData);
- }
- ~WinsockInitializer() {
- WSACleanup();
- }
- int error() {
- return err_;
- }
-private:
- int err_;
-};
-WinsockInitializer g_winsockinit;
+typedef char* SockOptArg;
#endif
namespace talk_base {
-const int kfRead = 0x0001;
-const int kfWrite = 0x0002;
+const int kfRead = 0x0001;
+const int kfWrite = 0x0002;
const int kfConnect = 0x0004;
-const int kfClose = 0x0008;
+const int kfClose = 0x0008;
+const int kfAccept = 0x0010;
-// Standard MTUs
+// Standard MTUs, from RFC 1191
const uint16 PACKET_MAXIMUMS[] = {
65535, // Theoretical maximum, Hyperchannel
32000, // Nothing
@@ -117,13 +110,28 @@
const uint32 IP_HEADER_SIZE = 20;
const uint32 ICMP_HEADER_SIZE = 8;
-class PhysicalSocket : public AsyncSocket {
-public:
+class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
+ public:
PhysicalSocket(PhysicalSocketServer* ss, SOCKET s = INVALID_SOCKET)
: ss_(ss), s_(s), enabled_events_(0), error_(0),
- state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED) {
- if (s != INVALID_SOCKET)
+ state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED),
+ resolver_(NULL) {
+#ifdef WIN32
+ // EnsureWinsockInit() ensures that winsock is initialized. The default
+ // version of this function doesn't do anything because winsock is
+ // initialized by constructor of a static object. If neccessary libjingle
+ // users can link it with a different version of this function by replacing
+ // win32socketinit.cc. See win32socketinit.cc for more details.
+ EnsureWinsockInit();
+#endif
+ if (s_ != INVALID_SOCKET) {
enabled_events_ = kfRead | kfWrite;
+
+ int type = SOCK_STREAM;
+ socklen_t len = sizeof(type);
+ VERIFY(0 == getsockopt(s_, SOL_SOCKET, SO_TYPE, (SockOptArg)&type, &len));
+ udp_ = (SOCK_DGRAM == type);
+ }
}
virtual ~PhysicalSocket() {
@@ -134,8 +142,9 @@
virtual bool Create(int type) {
Close();
s_ = ::socket(AF_INET, type, 0);
+ udp_ = (SOCK_DGRAM == type);
UpdateLastError();
- if (type != SOCK_STREAM)
+ if (udp_)
enabled_events_ = kfRead | kfWrite;
return s_ != INVALID_SOCKET;
}
@@ -144,12 +153,13 @@
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
int result = ::getsockname(s_, (sockaddr*)&addr, &addrlen);
- ASSERT(addrlen == sizeof(addr));
- talk_base::SocketAddress address;
+ SocketAddress address;
if (result >= 0) {
+ ASSERT(addrlen == sizeof(addr));
address.FromSockAddr(addr);
} else {
- ASSERT(result >= 0);
+ LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
+ << s_;
}
return address;
}
@@ -158,12 +168,13 @@
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
int result = ::getpeername(s_, (sockaddr*)&addr, &addrlen);
- ASSERT(addrlen == sizeof(addr));
- talk_base::SocketAddress address;
+ SocketAddress address;
if (result >= 0) {
+ ASSERT(addrlen == sizeof(addr));
address.FromSockAddr(addr);
} else {
- ASSERT(errno == ENOTCONN);
+ LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
+ << s_;
}
return address;
}
@@ -173,6 +184,12 @@
addr.ToSockAddr(&saddr);
int err = ::bind(s_, (sockaddr*)&saddr, sizeof(saddr));
UpdateLastError();
+#ifdef _DEBUG
+ if (0 == err) {
+ dbg_addr_ = "Bound @ ";
+ dbg_addr_.append(GetLocalAddress().ToString());
+ }
+#endif // _DEBUG
return err;
}
@@ -181,13 +198,27 @@
// ...but should we make it more explicit?
if ((s_ == INVALID_SOCKET) && !Create(SOCK_STREAM))
return SOCKET_ERROR;
- SocketAddress addr2(addr);
- if (addr2.IsUnresolved()) {
- LOG(INFO) << "Resolving addr in PhysicalSocket::Connect";
- addr2.Resolve(); // TODO: Do this async later?
+ if (addr.IsUnresolved()) {
+ if (state_ != CS_CLOSED) {
+ SetError(EALREADY);
+ return SOCKET_ERROR;
+ }
+
+ LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
+ resolver_ = new AsyncResolver();
+ resolver_->set_address(addr);
+ resolver_->SignalWorkDone.connect(this, &PhysicalSocket::OnResolveResult);
+ resolver_->Start();
+ state_ = CS_CONNECTING;
+ return 0;
}
+
+ return DoConnect(addr);
+ }
+
+ int DoConnect(const SocketAddress& addr) {
sockaddr_in saddr;
- addr2.ToSockAddr(&saddr);
+ addr.ToSockAddr(&saddr);
int err = ::connect(s_, (sockaddr*)&saddr, sizeof(saddr));
UpdateLastError();
//LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] Connect(" << addr2.ToString() << ") Ret: " << err << " Error: " << error_;
@@ -196,9 +227,12 @@
} else if (IsBlockingError(error_)) {
state_ = CS_CONNECTING;
enabled_events_ |= kfConnect;
+ } else {
+ return SOCKET_ERROR;
}
+
enabled_events_ |= kfRead | kfWrite;
- return err;
+ return 0;
}
int GetError() const {
@@ -213,27 +247,47 @@
return state_;
}
+ int GetOption(Option opt, int* value) {
+ int slevel;
+ int sopt;
+ if (TranslateOption(opt, &slevel, &sopt) == -1)
+ return -1;
+ socklen_t optlen = sizeof(*value);
+ int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen);
+ if (ret != -1 && opt == OPT_DONTFRAGMENT) {
+#ifdef LINUX
+ *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0;
+#endif
+ }
+ return ret;
+ }
+
int SetOption(Option opt, int value) {
- assert(opt == OPT_DONTFRAGMENT);
-#ifdef WIN32
- value = (value == 0) ? 0 : 1;
- return ::setsockopt(
- s_, IPPROTO_IP, IP_DONTFRAGMENT, reinterpret_cast<char*>(&value),
- sizeof(value));
+ int slevel;
+ int sopt;
+ if (TranslateOption(opt, &slevel, &sopt) == -1)
+ return -1;
+ if (opt == OPT_DONTFRAGMENT) {
+#ifdef LINUX
+ value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
#endif
-#ifdef __linux
- value = (value == 0) ? IP_PMTUDISC_DONT : IP_PMTUDISC_DO;
- return ::setsockopt(
- s_, IPPROTO_IP, IP_MTU_DISCOVER, &value, sizeof(value));
-#endif
-#ifdef OSX
- // This is not possible on OSX.
- return -1;
-#endif
+ }
+ return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
}
int Send(const void *pv, size_t cb) {
- int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb, 0);
+ int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb,
+#ifdef LINUX
+ // Suppress SIGPIPE. Without this, attempting to send on a socket whose
+ // other end is closed will result in a SIGPIPE signal being raised to
+ // our process, which by default will terminate the process, which we
+ // don't want. By specifying this flag, we'll just get the error EPIPE
+ // instead and can handle the error gracefully.
+ MSG_NOSIGNAL
+#else
+ 0
+#endif
+ );
UpdateLastError();
//LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] Send(" << cb << ") Ret: " << sent << " Error: " << error_;
ASSERT(sent <= static_cast<int>(cb)); // We have seen minidumps where this may be false
@@ -247,13 +301,20 @@
sockaddr_in saddr;
addr.ToSockAddr(&saddr);
int sent = ::sendto(
- s_, (const char *)pv, (int)cb, 0, (sockaddr*)&saddr,
- sizeof(saddr));
+ s_, (const char *)pv, (int)cb,
+#ifdef LINUX
+ // Suppress SIGPIPE. See above for explanation.
+ MSG_NOSIGNAL,
+#else
+ 0,
+#endif
+ (sockaddr*)&saddr, sizeof(saddr));
UpdateLastError();
ASSERT(sent <= static_cast<int>(cb)); // We have seen minidumps where this may be false
if ((sent < 0) && IsBlockingError(error_)) {
enabled_events_ |= kfWrite;
}
+ //LOG_F(LS_INFO) << cb << ":" << addr.ToString() << ":" << sent << ":" << error_;
return sent;
}
@@ -263,13 +324,21 @@
// Note: on graceful shutdown, recv can return 0. In this case, we
// pretend it is blocking, and then signal close, so that simplifying
// assumptions can be made about Recv.
+ LOG(LS_WARNING) << "EOF from socket; deferring close event";
+ // Must turn this back on so that the select() loop will notice the close
+ // event.
+ enabled_events_ |= kfRead;
error_ = EWOULDBLOCK;
return SOCKET_ERROR;
}
UpdateLastError();
- if ((received >= 0) || IsBlockingError(error_)) {
+ bool success = (received >= 0) || IsBlockingError(error_);
+ if (udp_ || success) {
enabled_events_ |= kfRead;
}
+ if (!success) {
+ LOG_F(LS_VERBOSE) << "Error = " << error_;
+ }
return received;
}
@@ -281,32 +350,40 @@
UpdateLastError();
if ((received >= 0) && (paddr != NULL))
paddr->FromSockAddr(saddr);
- if ((received >= 0) || IsBlockingError(error_)) {
+ bool success = (received >= 0) || IsBlockingError(error_);
+ if (udp_ || success) {
enabled_events_ |= kfRead;
}
+ if (!success) {
+ LOG_F(LS_VERBOSE) << "Error = " << error_;
+ }
return received;
}
int Listen(int backlog) {
int err = ::listen(s_, backlog);
UpdateLastError();
- if (err == 0)
+ if (err == 0) {
state_ = CS_CONNECTING;
- enabled_events_ |= kfRead;
-
+ enabled_events_ |= kfAccept;
+#ifdef _DEBUG
+ dbg_addr_ = "Listening @ ";
+ dbg_addr_.append(GetLocalAddress().ToString());
+#endif // _DEBUG
+ }
return err;
}
- Socket* Accept(SocketAddress *paddr) {
+ AsyncSocket* Accept(SocketAddress *paddr) {
sockaddr_in saddr;
socklen_t cbAddr = sizeof(saddr);
SOCKET s = ::accept(s_, (sockaddr*)&saddr, &cbAddr);
UpdateLastError();
if (s == INVALID_SOCKET)
return NULL;
+ enabled_events_ |= kfAccept;
if (paddr != NULL)
paddr->FromSockAddr(saddr);
- enabled_events_ |= kfRead | kfWrite;
return ss_->WrapSocket(s);
}
@@ -319,6 +396,10 @@
s_ = INVALID_SOCKET;
state_ = CS_CLOSED;
enabled_events_ = 0;
+ if (resolver_) {
+ resolver_->Destroy(false);
+ resolver_ = NULL;
+ }
return err;
}
@@ -329,8 +410,8 @@
return -1;
}
-#ifdef WIN32
-
+#if defined(WIN32)
+ // Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
WinPing ping;
if (!ping.IsValid()) {
error_ = EINVAL; // can't think of a better error ID
@@ -343,20 +424,23 @@
if (result == WinPing::PING_FAIL) {
error_ = EINVAL; // can't think of a better error ID
return -1;
- }
- if (result != WinPing::PING_TOO_LARGE) {
+ } else if (result != WinPing::PING_TOO_LARGE) {
*mtu = PACKET_MAXIMUMS[level];
return 0;
}
}
- assert(false);
- return 0;
-
-#endif // WIN32
-
-#ifdef __linux
-
+ ASSERT(false);
+ return -1;
+#elif defined(OSX)
+ // No simple way to do this on Mac OS X.
+ // SIOCGIFMTU would work if we knew which interface would be used, but
+ // figuring that out is pretty complicated. For now we'll return an error
+ // and let the caller pick a default MTU.
+ error_ = EINVAL;
+ return -1;
+#elif defined(LINUX)
+ // Gets the path MTU.
int value;
socklen_t vlen = sizeof(value);
int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
@@ -365,45 +449,97 @@
return err;
}
- assert((0 <= value) && (value <= 65536));
- *mtu = uint16(value);
+ ASSERT((0 <= value) && (value <= 65536));
+ *mtu = value;
return 0;
-
-#endif // __linux
-
- // TODO: OSX support
+#endif
}
SocketServer* socketserver() { return ss_; }
-
-protected:
- PhysicalSocketServer* ss_;
- SOCKET s_;
- uint32 enabled_events_;
- int error_;
- ConnState state_;
+
+ protected:
+ void OnResolveResult(SignalThread* thread) {
+ if (thread != resolver_) {
+ return;
+ }
+
+ int error = resolver_->error();
+ if (error == 0) {
+ error = DoConnect(resolver_->address());
+ } else {
+ Close();
+ }
+
+ if (error) {
+ error_ = error;
+ SignalCloseEvent(this, error_);
+ }
+ }
void UpdateLastError() {
-#ifdef WIN32
- error_ = WSAGetLastError();
-#endif
-#ifdef POSIX
- error_ = errno;
-#endif
+ error_ = LAST_SYSTEM_ERROR;
}
+
+ static int TranslateOption(Option opt, int* slevel, int* sopt) {
+ switch (opt) {
+ case OPT_DONTFRAGMENT:
+#ifdef WIN32
+ *slevel = IPPROTO_IP;
+ *sopt = IP_DONTFRAGMENT;
+ break;
+#elif defined(OSX) || defined(BSD)
+ LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
+ return -1;
+#elif defined(POSIX)
+ *slevel = IPPROTO_IP;
+ *sopt = IP_MTU_DISCOVER;
+ break;
+#endif
+ case OPT_RCVBUF:
+ *slevel = SOL_SOCKET;
+ *sopt = SO_RCVBUF;
+ break;
+ case OPT_SNDBUF:
+ *slevel = SOL_SOCKET;
+ *sopt = SO_SNDBUF;
+ break;
+ case OPT_NODELAY:
+ *slevel = IPPROTO_TCP;
+ *sopt = TCP_NODELAY;
+ break;
+ default:
+ ASSERT(false);
+ return -1;
+ }
+ return 0;
+ }
+
+ PhysicalSocketServer* ss_;
+ SOCKET s_;
+ uint8 enabled_events_;
+ bool udp_;
+ int error_;
+ ConnState state_;
+ AsyncResolver* resolver_;
+
+#ifdef _DEBUG
+ std::string dbg_addr_;
+#endif // _DEBUG;
};
#ifdef POSIX
class Dispatcher {
-public:
+ public:
+ virtual ~Dispatcher() { }
virtual uint32 GetRequestedEvents() = 0;
- virtual void OnPreEvent(uint32 ff) = 0;
+ virtual void OnPreEvent(uint32 ff) = 0;
virtual void OnEvent(uint32 ff, int err) = 0;
virtual int GetDescriptor() = 0;
+ virtual bool IsDescriptorClosed() = 0;
};
class EventDispatcher : public Dispatcher {
-public:
+ public:
EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
if (pipe(afd_) < 0)
LOG(LERROR) << "pipe failed";
@@ -415,17 +551,17 @@
close(afd_[0]);
close(afd_[1]);
}
-
+
virtual void Signal() {
CritScope cs(&crit_);
if (!fSignaled_) {
- uint8 b = 0;
- if (write(afd_[1], &b, sizeof(b)) < 0)
- LOG(LERROR) << "write failed";
- fSignaled_ = true;
+ const uint8 b[1] = { 0 };
+ if (VERIFY(1 == write(afd_[1], b, sizeof(b)))) {
+ fSignaled_ = true;
+ }
}
}
-
+
virtual uint32 GetRequestedEvents() {
return kfRead;
}
@@ -433,37 +569,206 @@
virtual void OnPreEvent(uint32 ff) {
// It is not possible to perfectly emulate an auto-resetting event with
// pipes. This simulates it by resetting before the event is handled.
-
+
CritScope cs(&crit_);
if (fSignaled_) {
- uint8 b;
- read(afd_[0], &b, sizeof(b));
+ uint8 b[4]; // Allow for reading more than 1 byte, but expect 1.
+ VERIFY(1 == read(afd_[0], b, sizeof(b)));
fSignaled_ = false;
}
}
virtual void OnEvent(uint32 ff, int err) {
- assert(false);
+ ASSERT(false);
}
virtual int GetDescriptor() {
return afd_[0];
}
-private:
+ virtual bool IsDescriptorClosed() {
+ return false;
+ }
+
+ private:
PhysicalSocketServer *ss_;
int afd_[2];
bool fSignaled_;
CriticalSection crit_;
};
+// This is a class customized to use the self-pipe trick to deliver POSIX
+// signals. This is the only safe, reliable, cross-platform way to do
+// non-trivial things with a POSIX signal (until proper pselect()
+// implementations become ubiquitous).
+class PosixSignalDeliveryDispatcher : public Dispatcher {
+ public:
+ virtual ~PosixSignalDeliveryDispatcher() {
+ close(afd_[0]);
+ close(afd_[1]);
+ }
+
+ virtual uint32 GetRequestedEvents() {
+ return kfRead;
+ }
+
+ virtual void OnPreEvent(uint32 ff) {
+ // Events might get grouped if signals come very fast, so we read out up to
+ // 16 bytes to make sure we keep the pipe empty.
+ uint8 b[16];
+ ssize_t ret = read(afd_[0], b, sizeof(b));
+ if (ret < 0) {
+ LOG_ERR(LS_WARNING) << "Error in read()";
+ } else if (ret == 0) {
+ LOG(LS_WARNING) << "Should have read at least one byte";
+ }
+ }
+
+ virtual void OnEvent(uint32 ff, int err) {
+ for (int signum = 0; signum < ARRAY_SIZE(received_signal_); ++signum) {
+ if (received_signal_[signum]) {
+ received_signal_[signum] = false;
+ HandlerMap::iterator i = handlers_.find(signum);
+ if (i == handlers_.end()) {
+ // This can happen if a signal is delivered to our process at around
+ // the same time as we unset our handler for it. It is not an error
+ // condidion, but it's unusual enough to be worth logging.
+ LOG(LS_INFO) << "Received signal with no handler: " << signum;
+ } else {
+ // Otherwise, execute the handler.
+ (*i->second)(signum);
+ }
+ }
+ }
+ }
+
+ virtual int GetDescriptor() {
+ return afd_[0];
+ }
+
+ virtual bool IsDescriptorClosed() {
+ return false;
+ }
+
+ void SetHandler(int signum, void (*handler)(int)) {
+ handlers_[signum] = handler;
+ }
+
+ void ClearHandler(int signum) {
+ handlers_.erase(signum);
+ }
+
+ bool HasHandlers() {
+ return !handlers_.empty();
+ }
+
+ // This is called directly from our real signal handler, so it must be
+ // signal-handler-safe. That means it cannot assume anything about the
+ // user-level state of the process, since the handler could be executed at any
+ // time on any thread.
+ void OnPosixSignalReceived(int signum) {
+ if (signum >= ARRAY_SIZE(received_signal_)) {
+ // We don't have space in our array for this.
+ return;
+ }
+ // Set a flag saying we've seen this signal.
+ received_signal_[signum] = true;
+ // Tell the thread running our PhysicalSocketServer that we got a signal.
+ const uint8 b[1] = { 0 };
+ if (-1 == write(afd_[1], b, sizeof(b))) {
+ // Nothing we can do here. If there's an error somehow then there's
+ // nothing we can safely do from a signal handler.
+ // No, we can't even safely log it.
+ // But, we still have to check the return value here. Otherwise,
+ // GCC 4.4.1 complains ignoring return value. Even (void) doesn't help.
+ return;
+ }
+ }
+
+ // Sets a PhysicalSocketServer to own signal delivery, or fails if already
+ // owned.
+ bool SetOwner(PhysicalSocketServer *owner) {
+ CritScope cs(&owner_critsec_);
+ if (owner == owner_) {
+ return true;
+ } else if (owner_) {
+ return false;
+ } else {
+ owner_ = owner;
+ owner_->Add(this);
+ return true;
+ }
+ }
+
+ bool IsOwner(PhysicalSocketServer *ss) {
+ CritScope cs(&owner_critsec_);
+ return owner_ == ss;
+ }
+
+ void ClearOwner(PhysicalSocketServer *ss) {
+ CritScope cs(&owner_critsec_);
+ if (owner_ != ss) {
+ return;
+ }
+ owner_->Remove(this);
+ owner_ = NULL;
+ }
+
+ // There is just a single global instance. (Signal handlers do not get any
+ // sort of user-defined void * parameter, so they can't access anything that
+ // isn't global.)
+ static PosixSignalDeliveryDispatcher instance_;
+
+ private:
+ // POSIX only specifies 32 signals, but in principle the system might have
+ // more and the programmer might choose to use them, so we size our array
+ // for 128.
+ static const int kNumPosixSignals = 128;
+
+ typedef std::map<int, void (*)(int)> HandlerMap;
+
+ PosixSignalDeliveryDispatcher() : owner_(NULL) {
+ if (pipe(afd_) < 0) {
+ LOG_ERR(LS_ERROR) << "pipe failed";
+ return;
+ }
+ if (fcntl(afd_[0], F_SETFL, O_NONBLOCK) < 0) {
+ LOG_ERR(LS_WARNING) << "fcntl #1 failed";
+ }
+ if (fcntl(afd_[1], F_SETFL, O_NONBLOCK) < 0) {
+ LOG_ERR(LS_WARNING) << "fcntl #2 failed";
+ }
+ memset(const_cast<void *>(static_cast<volatile void *>(received_signal_)),
+ 0,
+ sizeof(received_signal_));
+ }
+
+ int afd_[2];
+ HandlerMap handlers_;
+ // These are boolean flags that will be set in our signal handler and read
+ // and cleared from Wait(). There is a race involved in this, but it is
+ // benign. The signal handler sets the flag before signaling the pipe, so
+ // we'll never end up blocking in select() while a flag is still true.
+ // However, if two of the same signal arrive close to each other then it's
+ // possible that the second time the handler may set the flag while it's still
+ // true, meaning that signal will be missed. But the first occurrence of it
+ // will still be handled, so this isn't a problem.
+ // Volatile is not necessary here for correctness, but this data _is_ volatile
+ // so I've marked it as such.
+ volatile uint8 received_signal_[kNumPosixSignals];
+ // Our owner.
+ PhysicalSocketServer *owner_;
+ // To synchronize ownership changes.
+ CriticalSection owner_critsec_;
+};
+
+PosixSignalDeliveryDispatcher PosixSignalDeliveryDispatcher::instance_;
+
class SocketDispatcher : public Dispatcher, public PhysicalSocket {
-public:
- SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) {
- ss_->Add(this);
+ public:
+ explicit SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) {
}
SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) : PhysicalSocket(ss, s) {
- ss_->Add(this);
}
virtual ~SocketDispatcher() {
@@ -483,11 +788,46 @@
return Initialize();
}
-
+
virtual int GetDescriptor() {
return s_;
}
+ virtual bool IsDescriptorClosed() {
+ // We don't have a reliable way of distinguishing end-of-stream
+ // from readability. So test on each readable call. Is this
+ // inefficient? Probably.
+ char ch;
+ ssize_t res = ::recv(s_, &ch, 1, MSG_PEEK);
+ if (res > 0) {
+ // Data available, so not closed.
+ return false;
+ } else if (res == 0) {
+ // EOF, so closed.
+ return true;
+ } else { // error
+ switch (errno) {
+ // Returned if we've already closed s_.
+ case EBADF:
+ // Returned during ungraceful peer shutdown.
+ case ECONNRESET:
+ return true;
+ default:
+ // Assume that all other errors are just blocking errors, meaning the
+ // connection is still good but we just can't read from it right now.
+ // This should only happen when connecting (and at most once), because
+ // in all other cases this function is only called if the file
+ // descriptor is already known to be in the readable state. However,
+ // it's not necessary a problem if we spuriously interpret a
+ // "connection lost"-type error as a blocking error, because typically
+ // the next recv() will get EOF, so we'll still eventually notice that
+ // the socket is closed.
+ LOG_ERR(LS_WARNING) << "Assuming benign blocking error";
+ return false;
+ }
+ }
+ }
+
virtual uint32 GetRequestedEvents() {
return enabled_events_;
}
@@ -495,6 +835,8 @@
virtual void OnPreEvent(uint32 ff) {
if ((ff & kfConnect) != 0)
state_ = CS_CONNECTED;
+ if ((ff & kfClose) != 0)
+ state_ = CS_CLOSED;
}
virtual void OnEvent(uint32 ff, int err) {
@@ -510,8 +852,15 @@
enabled_events_ &= ~kfConnect;
SignalConnectEvent(this);
}
- if ((ff & kfClose) != 0)
+ if ((ff & kfAccept) != 0) {
+ enabled_events_ &= ~kfAccept;
+ SignalReadEvent(this);
+ }
+ if ((ff & kfClose) != 0) {
+ // The socket is now dead to us, so stop checking it.
+ enabled_events_ = 0;
SignalCloseEvent(this, err);
+ }
}
virtual int Close() {
@@ -521,11 +870,10 @@
ss_->Remove(this);
return PhysicalSocket::Close();
}
-
};
class FileDispatcher: public Dispatcher, public AsyncFile {
-public:
+ public:
FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) {
set_readable(true);
@@ -544,6 +892,10 @@
return fd_;
}
+ virtual bool IsDescriptorClosed() {
+ return false;
+ }
+
virtual uint32 GetRequestedEvents() {
return flags_;
}
@@ -576,7 +928,7 @@
flags_ = value ? (flags_ | kfWrite) : (flags_ & ~kfWrite);
}
-private:
+ private:
PhysicalSocketServer* ss_;
int fd_;
int flags_;
@@ -590,30 +942,34 @@
#ifdef WIN32
class Dispatcher {
-public:
+ public:
+ virtual ~Dispatcher() {}
virtual uint32 GetRequestedEvents() = 0;
- virtual void OnPreEvent(uint32 ff) = 0;
+ virtual void OnPreEvent(uint32 ff) = 0;
virtual void OnEvent(uint32 ff, int err) = 0;
virtual WSAEVENT GetWSAEvent() = 0;
virtual SOCKET GetSocket() = 0;
virtual bool CheckSignalClose() = 0;
};
-uint32 FlagsToEvents(uint32 events) {
- uint32 ffFD = FD_CLOSE | FD_ACCEPT;
+static uint32 FlagsToEvents(uint32 events) {
+ uint32 ffFD = FD_CLOSE;
if (events & kfRead)
ffFD |= FD_READ;
if (events & kfWrite)
ffFD |= FD_WRITE;
if (events & kfConnect)
ffFD |= FD_CONNECT;
+ if (events & kfAccept)
+ ffFD |= FD_ACCEPT;
return ffFD;
}
class EventDispatcher : public Dispatcher {
-public:
+ public:
EventDispatcher(PhysicalSocketServer *ss) : ss_(ss) {
- if (hev_ = WSACreateEvent()) {
+ hev_ = WSACreateEvent();
+ if (hev_) {
ss_->Add(this);
}
}
@@ -625,12 +981,12 @@
hev_ = NULL;
}
}
-
+
virtual void Signal() {
if (hev_ != NULL)
WSASetEvent(hev_);
}
-
+
virtual uint32 GetRequestedEvents() {
return 0;
}
@@ -658,7 +1014,7 @@
};
class SocketDispatcher : public Dispatcher, public PhysicalSocket {
-public:
+ public:
static int next_id_;
int id_;
bool signal_close_;
@@ -674,14 +1030,14 @@
}
bool Initialize() {
- assert(s_ != INVALID_SOCKET);
+ ASSERT(s_ != INVALID_SOCKET);
// Must be a non-blocking
u_long argp = 1;
ioctlsocket(s_, FIONBIO, &argp);
ss_->Add(this);
return true;
}
-
+
virtual bool Create(int type) {
// Create socket
if (!PhysicalSocket::Create(type))
@@ -711,6 +1067,7 @@
virtual void OnPreEvent(uint32 ff) {
if ((ff & kfConnect) != 0)
state_ = CS_CONNECTED;
+ // We set CS_CLOSED from CheckSignalClose.
}
virtual void OnEvent(uint32 ff, int err) {
@@ -727,8 +1084,16 @@
if (ff != kfConnect)
LOG(LS_VERBOSE) << "Signalled with kfConnect: " << ff;
enabled_events_ &= ~kfConnect;
+#ifdef _DEBUG
+ dbg_addr_ = "Connected @ ";
+ dbg_addr_.append(GetRemoteAddress().ToString());
+#endif // _DEBUG
SignalConnectEvent(this);
}
+ if (((ff & kfAccept) != 0) && (id_ == cache_id)) {
+ enabled_events_ &= ~kfAccept;
+ SignalReadEvent(this);
+ }
if (((ff & kfClose) != 0) && (id_ == cache_id)) {
//LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] OnClose() Error: " << err;
signal_close_ = true;
@@ -752,6 +1117,7 @@
if (recv(s_, &ch, 1, MSG_PEEK) > 0)
return false;
+ state_ = CS_CLOSED;
signal_close_ = false;
SignalCloseEvent(this, signal_err_);
return true;
@@ -760,11 +1126,11 @@
int SocketDispatcher::next_id_ = 0;
-#endif // WIN32
+#endif // WIN32
// Sets the value of a boolean value to false when signaled.
class Signaler : public EventDispatcher {
-public:
+ public:
Signaler(PhysicalSocketServer* ss, bool* pf)
: EventDispatcher(ss), pf_(pf) {
}
@@ -775,18 +1141,29 @@
*pf_ = false;
}
-private:
+ private:
bool *pf_;
};
-PhysicalSocketServer::PhysicalSocketServer() : fWait_(false),
- last_tick_tracked_(0), last_tick_dispatch_count_(0) {
+PhysicalSocketServer::PhysicalSocketServer()
+ : fWait_(false),
+ last_tick_tracked_(0),
+ last_tick_dispatch_count_(0) {
signal_wakeup_ = new Signaler(this, &fWait_);
+#ifdef WIN32
+ socket_ev_ = WSACreateEvent();
+#endif
}
PhysicalSocketServer::~PhysicalSocketServer() {
+#ifdef WIN32
+ WSACloseEvent(socket_ev_);
+#endif
+#ifdef POSIX
+ PosixSignalDeliveryDispatcher::instance_.ClearOwner(this);
+#endif
delete signal_wakeup_;
- // ASSERT(dispatchers_.empty());
+ ASSERT(dispatchers_.empty());
}
void PhysicalSocketServer::WakeUp() {
@@ -825,12 +1202,29 @@
void PhysicalSocketServer::Add(Dispatcher *pdispatcher) {
CritScope cs(&crit_);
+ // Prevent duplicates. This can cause dead dispatchers to stick around.
+ DispatcherList::iterator pos = std::find(dispatchers_.begin(),
+ dispatchers_.end(),
+ pdispatcher);
+ if (pos != dispatchers_.end())
+ return;
dispatchers_.push_back(pdispatcher);
}
void PhysicalSocketServer::Remove(Dispatcher *pdispatcher) {
CritScope cs(&crit_);
- dispatchers_.erase(std::remove(dispatchers_.begin(), dispatchers_.end(), pdispatcher), dispatchers_.end());
+ DispatcherList::iterator pos = std::find(dispatchers_.begin(),
+ dispatchers_.end(),
+ pdispatcher);
+ ASSERT(pos != dispatchers_.end());
+ size_t index = pos - dispatchers_.begin();
+ dispatchers_.erase(pos);
+ for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end();
+ ++it) {
+ if (index < **it) {
+ --**it;
+ }
+ }
}
#ifdef POSIX
@@ -858,74 +1252,105 @@
// Zero all fd_sets. Don't need to do this inside the loop since
// select() zeros the descriptors not signaled
-
+
fd_set fdsRead;
FD_ZERO(&fdsRead);
fd_set fdsWrite;
FD_ZERO(&fdsWrite);
-
+
fWait_ = true;
while (fWait_) {
int fdmax = -1;
{
CritScope cr(&crit_);
- for (unsigned i = 0; i < dispatchers_.size(); i++) {
+ for (size_t i = 0; i < dispatchers_.size(); ++i) {
// Query dispatchers for read and write wait state
-
Dispatcher *pdispatcher = dispatchers_[i];
- assert(pdispatcher);
+ ASSERT(pdispatcher);
if (!process_io && (pdispatcher != signal_wakeup_))
continue;
int fd = pdispatcher->GetDescriptor();
if (fd > fdmax)
fdmax = fd;
+
uint32 ff = pdispatcher->GetRequestedEvents();
- if (ff & kfRead)
+ if (ff & (kfRead | kfAccept))
FD_SET(fd, &fdsRead);
if (ff & (kfWrite | kfConnect))
FD_SET(fd, &fdsWrite);
}
}
-
+
// Wait then call handlers as appropriate
// < 0 means error
// 0 means timeout
// > 0 means count of descriptors ready
int n = select(fdmax + 1, &fdsRead, &fdsWrite, NULL, ptvWait);
- // If error, return error
- // todo: do something intelligent
- if (n < 0)
- return false;
-
- // If timeout, return success
-
- if (n == 0)
+
+ // If error, return error.
+ if (n < 0) {
+ if (errno != EINTR) {
+ LOG_E(LS_ERROR, EN, errno) << "select";
+ return false;
+ }
+ // Else ignore the error and keep going. If this EINTR was for one of the
+ // signals managed by this PhysicalSocketServer, the
+ // PosixSignalDeliveryDispatcher will be in the signaled state in the next
+ // iteration.
+ } else if (n == 0) {
+ // If timeout, return success
return true;
-
- // We have signaled descriptors
-
- {
+ } else {
+ // We have signaled descriptors
CritScope cr(&crit_);
- for (unsigned i = 0; i < dispatchers_.size(); i++) {
+ for (size_t i = 0; i < dispatchers_.size(); ++i) {
Dispatcher *pdispatcher = dispatchers_[i];
int fd = pdispatcher->GetDescriptor();
uint32 ff = 0;
+ int errcode = 0;
+
+ // Reap any error code, which can be signaled through reads or writes.
+ // TODO: Should we set errcode if getsockopt fails?
+ if (FD_ISSET(fd, &fdsRead) || FD_ISSET(fd, &fdsWrite)) {
+ socklen_t len = sizeof(errcode);
+ ::getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &len);
+ }
+
+ // Check readable descriptors. If we're waiting on an accept, signal
+ // that. Otherwise we're waiting for data, check to see if we're
+ // readable or really closed.
+ // TODO: Only peek at TCP descriptors.
if (FD_ISSET(fd, &fdsRead)) {
FD_CLR(fd, &fdsRead);
- ff |= kfRead;
+ if (pdispatcher->GetRequestedEvents() & kfAccept) {
+ ff |= kfAccept;
+ } else if (errcode || pdispatcher->IsDescriptorClosed()) {
+ ff |= kfClose;
+ } else {
+ ff |= kfRead;
+ }
}
+
+ // Check writable descriptors. If we're waiting on a connect, detect
+ // success versus failure by the reaped error code.
if (FD_ISSET(fd, &fdsWrite)) {
FD_CLR(fd, &fdsWrite);
if (pdispatcher->GetRequestedEvents() & kfConnect) {
- ff |= kfConnect;
+ if (!errcode) {
+ ff |= kfConnect;
+ } else {
+ ff |= kfClose;
+ }
} else {
ff |= kfWrite;
}
}
+
+ // Tell the descriptor about the event.
if (ff != 0) {
pdispatcher->OnPreEvent(ff);
- pdispatcher->OnEvent(ff, 0);
+ pdispatcher->OnEvent(ff, errcode);
}
}
}
@@ -938,27 +1363,80 @@
ptvWait->tv_usec = 0;
struct timeval tvT;
gettimeofday(&tvT, NULL);
- if (tvStop.tv_sec >= tvT.tv_sec) {
+ if ((tvStop.tv_sec > tvT.tv_sec)
+ || ((tvStop.tv_sec == tvT.tv_sec)
+ && (tvStop.tv_usec > tvT.tv_usec))) {
ptvWait->tv_sec = tvStop.tv_sec - tvT.tv_sec;
ptvWait->tv_usec = tvStop.tv_usec - tvT.tv_usec;
if (ptvWait->tv_usec < 0) {
+ ASSERT(ptvWait->tv_sec > 0);
ptvWait->tv_usec += 1000000;
ptvWait->tv_sec -= 1;
}
}
}
}
-
+
return true;
}
-#endif // POSIX
+
+static void GlobalSignalHandler(int signum) {
+ PosixSignalDeliveryDispatcher::instance_.OnPosixSignalReceived(signum);
+}
+
+bool PhysicalSocketServer::SetPosixSignalHandler(int signum,
+ void (*handler)(int)) {
+ // If handler is SIG_IGN or SIG_DFL then clear our user-level handler,
+ // otherwise set one.
+ if (handler == SIG_IGN || handler == SIG_DFL) {
+ if (!InstallSignal(signum, handler)) {
+ return false;
+ }
+ if (PosixSignalDeliveryDispatcher::instance_.IsOwner(this)) {
+ PosixSignalDeliveryDispatcher::instance_.ClearHandler(signum);
+ if (!PosixSignalDeliveryDispatcher::instance_.HasHandlers()) {
+ PosixSignalDeliveryDispatcher::instance_.ClearOwner(this);
+ }
+ }
+ } else {
+ if (!PosixSignalDeliveryDispatcher::instance_.SetOwner(this)) {
+ LOG(LS_ERROR) <<
+ "Cannot do POSIX signal delivery on more than one PhysicalSocketServer";
+ return false;
+ }
+ PosixSignalDeliveryDispatcher::instance_.SetHandler(signum, handler);
+ if (!InstallSignal(signum, &GlobalSignalHandler)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool PhysicalSocketServer::InstallSignal(int signum, void (*handler)(int)) {
+ struct sigaction act;
+ // It doesn't really matter what we set this mask to.
+ if (sigemptyset(&act.sa_mask) != 0) {
+ LOG_ERR(LS_ERROR) << "Couldn't set mask";
+ return false;
+ }
+ act.sa_handler = handler;
+ // Use SA_RESTART so that our syscalls don't get EINTR, since we don't need it
+ // and it's a nuisance. Though some syscalls still return EINTR and there's no
+ // real standard for which ones. :(
+ act.sa_flags = SA_RESTART;
+ if (sigaction(signum, &act, NULL) != 0) {
+ LOG_ERR(LS_ERROR) << "Couldn't set sigaction";
+ return false;
+ }
+ return true;
+}
+#endif // POSIX
#ifdef WIN32
-bool PhysicalSocketServer::Wait(int cmsWait, bool process_io)
-{
+bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
int cmsTotal = cmsWait;
int cmsElapsed = 0;
- uint32 msStart = GetMillisecondCount();
+ uint32 msStart = Time();
#if LOGGING
if (last_tick_dispatch_count_ == 0) {
@@ -966,19 +1444,21 @@
}
#endif
- WSAEVENT socket_ev = WSACreateEvent();
-
fWait_ = true;
while (fWait_) {
std::vector<WSAEVENT> events;
std::vector<Dispatcher *> event_owners;
- events.push_back(socket_ev);
+ events.push_back(socket_ev_);
{
CritScope cr(&crit_);
- for (size_t i = 0; i < dispatchers_.size(); ++i) {
- Dispatcher * disp = dispatchers_[i];
+ size_t i = 0;
+ iterators_.push_back(&i);
+ // Don't track dispatchers_.size(), because we want to pick up any new
+ // dispatchers that were added while processing the loop.
+ while (i < dispatchers_.size()) {
+ Dispatcher* disp = dispatchers_[i++];
if (!process_io && (disp != signal_wakeup_))
continue;
SOCKET s = disp->GetSocket();
@@ -991,6 +1471,8 @@
event_owners.push_back(disp);
}
}
+ ASSERT(iterators_.back() == &i);
+ iterators_.pop_back();
}
// Which is shorter, the delay wait or the asked wait?
@@ -999,9 +1481,7 @@
if (cmsWait == kForever) {
cmsNext = cmsWait;
} else {
- cmsNext = cmsTotal - cmsElapsed;
- if (cmsNext < 0)
- cmsNext = 0;
+ cmsNext = _max(0, cmsTotal - cmsElapsed);
}
// Wait for one of the events to signal
@@ -1011,38 +1491,29 @@
// we track this information purely for logging purposes.
last_tick_dispatch_count_++;
if (last_tick_dispatch_count_ >= 1000) {
- uint32 now = GetMillisecondCount();
- LOG(INFO) << "PhysicalSocketServer took " << TimeDiff(now, last_tick_tracked_) << "ms for 1000 events";
+ int32 elapsed = TimeSince(last_tick_tracked_);
+ LOG(INFO) << "PhysicalSocketServer took " << elapsed << "ms for 1000 events";
// If we get more than 1000 events in a second, we are spinning badly
// (normally it should take about 8-20 seconds).
- assert(TimeDiff(now, last_tick_tracked_) > 1000);
-
- last_tick_tracked_ = now;
+ ASSERT(elapsed > 1000);
+
+ last_tick_tracked_ = Time();
last_tick_dispatch_count_ = 0;
}
#endif
- // Failed?
- // todo: need a better strategy than this!
-
if (dw == WSA_WAIT_FAILED) {
+ // Failed?
+ // TODO: need a better strategy than this!
int error = WSAGetLastError();
- assert(false);
- WSACloseEvent(socket_ev);
+ ASSERT(false);
return false;
- }
-
- // Timeout?
-
- if (dw == WSA_WAIT_TIMEOUT) {
- WSACloseEvent(socket_ev);
+ } else if (dw == WSA_WAIT_TIMEOUT) {
+ // Timeout?
return true;
- }
-
- // Figure out which one it is and call it
-
- {
+ } else {
+ // Figure out which one it is and call it
CritScope cr(&crit_);
int index = dw - WSA_WAIT_EVENT_0;
if (index > 0) {
@@ -1050,8 +1521,11 @@
event_owners[index]->OnPreEvent(0);
event_owners[index]->OnEvent(0, 0);
} else if (process_io) {
- for (size_t i = 0; i < dispatchers_.size(); ++i) {
- Dispatcher * disp = dispatchers_[i];
+ size_t i = 0, end = dispatchers_.size();
+ iterators_.push_back(&i);
+ iterators_.push_back(&end); // Don't iterate over new dispatchers.
+ while (i < end) {
+ Dispatcher* disp = dispatchers_[i++];
SOCKET s = disp->GetSocket();
if (s == INVALID_SOCKET)
continue;
@@ -1059,7 +1533,7 @@
WSANETWORKEVENTS wsaEvents;
int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents);
if (err == 0) {
-
+
#if LOGGING
{
if ((wsaEvents.lNetworkEvents & FD_READ) && wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
@@ -1089,13 +1563,12 @@
if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
ff |= kfConnect;
} else {
- // TODO: Decide whether we want to signal connect, but with an error code
- ff |= kfClose;
+ ff |= kfClose;
errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
}
}
if (wsaEvents.lNetworkEvents & FD_ACCEPT)
- ff |= kfRead;
+ ff |= kfAccept;
if (wsaEvents.lNetworkEvents & FD_CLOSE) {
ff |= kfClose;
errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
@@ -1106,27 +1579,28 @@
}
}
}
+ ASSERT(iterators_.back() == &end);
+ iterators_.pop_back();
+ ASSERT(iterators_.back() == &i);
+ iterators_.pop_back();
}
// Reset the network event until new activity occurs
- WSAResetEvent(socket_ev);
+ WSAResetEvent(socket_ev_);
}
// Break?
-
if (!fWait_)
break;
- cmsElapsed = GetMillisecondCount() - msStart;
+ cmsElapsed = TimeSince(msStart);
if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
break;
}
}
-
+
// Done
-
- WSACloseEvent(socket_ev);
return true;
}
-#endif // WIN32
+#endif // WIN32
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/physicalsocketserver.h b/talk/base/physicalsocketserver.h
old mode 100755
new mode 100644
index cc2e707..282e14c
--- a/talk/base/physicalsocketserver.h
+++ b/talk/base/physicalsocketserver.h
@@ -42,6 +42,9 @@
class Dispatcher;
class Signaler;
+#ifdef POSIX
+class PosixSignalDeliveryDispatcher;
+#endif
// A socket server that provides the real sockets of the underlying OS.
class PhysicalSocketServer : public SocketServer {
@@ -65,15 +68,39 @@
#ifdef POSIX
AsyncFile* CreateFile(int fd);
+
+ // Sets the function to be executed in response to the specified POSIX signal.
+ // The function is executed from inside Wait() using the "self-pipe trick"--
+ // regardless of which thread receives the signal--and hence can safely
+ // manipulate user-level data structures.
+ // "handler" may be SIG_IGN, SIG_DFL, or a user-specified function, just like
+ // with signal(2).
+ // Only one PhysicalSocketServer may have user-level signal handlers.
+ // Attempting to install a signal handler for a PhysicalSocketServer when
+ // another already owns some will fail.
+ // The signal mask is not modified. It is the caller's responsibily to
+ // maintain it as desired.
+ bool SetPosixSignalHandler(int signum, void (*handler)(int));
#endif
private:
- std::vector<Dispatcher*> dispatchers_;
+ typedef std::vector<Dispatcher*> DispatcherList;
+ typedef std::vector<size_t*> IteratorList;
+
+#ifdef POSIX
+ static bool InstallSignal(int signum, void (*handler)(int));
+#endif
+
+ DispatcherList dispatchers_;
+ IteratorList iterators_;
Signaler* signal_wakeup_;
CriticalSection crit_;
bool fWait_;
uint32 last_tick_tracked_;
int last_tick_dispatch_count_;
+#ifdef WIN32
+ WSAEVENT socket_ev_;
+#endif
};
} // namespace talk_base
diff --git a/talk/base/proxydetect.cc b/talk/base/proxydetect.cc
old mode 100755
new mode 100644
index 04a9c61..66213ee
--- a/talk/base/proxydetect.cc
+++ b/talk/base/proxydetect.cc
@@ -1,77 +1,155 @@
-// TODO: Abstract this better for cross-platformability
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
-#ifdef _WINDOWS
+#include "talk/base/proxydetect.h"
+
+#ifdef WIN32
#include "talk/base/win32.h"
#include <shlobj.h>
+#endif // WIN32
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
#endif
+#ifdef OSX
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+#include <Security/Security.h>
+#include "macconversion.h"
+#endif
+
+#include <map>
+
+#include "talk/base/fileutils.h"
#include "talk/base/httpcommon.h"
#include "talk/base/httpcommon-inl.h"
-#include "talk/base/proxydetect.h"
+#include "talk/base/pathutils.h"
#include "talk/base/stringutils.h"
-#include "talk/base/basicdefs.h"
-#if _WINDOWS
-#define _TRY_FIREFOX 1
+#ifdef WIN32
#define _TRY_WINHTTP 1
#define _TRY_JSPROXY 0
#define _TRY_WM_FINDPROXY 0
#define _TRY_IE_LAN_SETTINGS 1
-#endif // _WINDOWS
+#endif // WIN32
+
+// For all platforms try Firefox.
+#define _TRY_FIREFOX 1
+
+// Use profiles.ini to find the correct profile for this user.
+// If not set, we'll just look for the default one.
+#define USE_FIREFOX_PROFILES_INI 1
+
+static const size_t kMaxLineLength = 1024;
+static const char kFirefoxPattern[] = "Firefox";
+static const char kInternetExplorerPattern[] = "MSIE";
+
+struct StringMap {
+ public:
+ void Add(const char * name, const char * value) { map_[name] = value; }
+ const std::string& Get(const char * name, const char * def = "") const {
+ std::map<std::string, std::string>::const_iterator it =
+ map_.find(name);
+ if (it != map_.end())
+ return it->second;
+ def_ = def;
+ return def_;
+ }
+ bool IsSet(const char * name) const {
+ return (map_.find(name) != map_.end());
+ }
+ private:
+ std::map<std::string, std::string> map_;
+ mutable std::string def_;
+};
+
+enum UserAgent {
+ UA_FIREFOX,
+ UA_INTERNETEXPLORER,
+ UA_OTHER,
+ UA_UNKNOWN
+};
#if _TRY_WINHTTP
//#include <winhttp.h>
// Note: From winhttp.h
const char WINHTTP[] = "winhttp";
+
typedef LPVOID HINTERNET;
typedef struct {
- DWORD dwAccessType; // see WINHTTP_ACCESS_* types below
- LPWSTR lpszProxy; // proxy server list
- LPWSTR lpszProxyBypass; // proxy bypass list
+ DWORD dwAccessType; // see WINHTTP_ACCESS_* types below
+ LPWSTR lpszProxy; // proxy server list
+ LPWSTR lpszProxyBypass; // proxy bypass list
} WINHTTP_PROXY_INFO, * LPWINHTTP_PROXY_INFO;
typedef struct {
- DWORD dwFlags;
- DWORD dwAutoDetectFlags;
- LPCWSTR lpszAutoConfigUrl;
- LPVOID lpvReserved;
- DWORD dwReserved;
- BOOL fAutoLogonIfChallenged;
+ DWORD dwFlags;
+ DWORD dwAutoDetectFlags;
+ LPCWSTR lpszAutoConfigUrl;
+ LPVOID lpvReserved;
+ DWORD dwReserved;
+ BOOL fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;
typedef struct {
- BOOL fAutoDetect;
- LPWSTR lpszAutoConfigUrl;
- LPWSTR lpszProxy;
- LPWSTR lpszProxyBypass;
+ BOOL fAutoDetect;
+ LPWSTR lpszAutoConfigUrl;
+ LPWSTR lpszProxy;
+ LPWSTR lpszProxyBypass;
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
extern "C" {
-typedef HINTERNET (WINAPI * pfnWinHttpOpen)
-(
- IN LPCWSTR pwszUserAgent,
- IN DWORD dwAccessType,
- IN LPCWSTR pwszProxyName OPTIONAL,
- IN LPCWSTR pwszProxyBypass OPTIONAL,
- IN DWORD dwFlags
-);
-typedef BOOL (STDAPICALLTYPE * pfnWinHttpCloseHandle)
-(
- IN HINTERNET hInternet
-);
-typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetProxyForUrl)
-(
- IN HINTERNET hSession,
- IN LPCWSTR lpcwszUrl,
- IN WINHTTP_AUTOPROXY_OPTIONS * pAutoProxyOptions,
- OUT WINHTTP_PROXY_INFO * pProxyInfo
-);
-typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetIEProxyConfig)
-(
- IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig
-);
+ typedef HINTERNET (WINAPI * pfnWinHttpOpen)
+ (
+ IN LPCWSTR pwszUserAgent,
+ IN DWORD dwAccessType,
+ IN LPCWSTR pwszProxyName OPTIONAL,
+ IN LPCWSTR pwszProxyBypass OPTIONAL,
+ IN DWORD dwFlags
+ );
+ typedef BOOL (STDAPICALLTYPE * pfnWinHttpCloseHandle)
+ (
+ IN HINTERNET hInternet
+ );
+ typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetProxyForUrl)
+ (
+ IN HINTERNET hSession,
+ IN LPCWSTR lpcwszUrl,
+ IN WINHTTP_AUTOPROXY_OPTIONS * pAutoProxyOptions,
+ OUT WINHTTP_PROXY_INFO * pProxyInfo
+ );
+ typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetIEProxyConfig)
+ (
+ IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig
+ );
} // extern "C"
@@ -91,15 +169,15 @@
#if _TRY_JSPROXY
extern "C" {
-typedef BOOL (STDAPICALLTYPE * pfnInternetGetProxyInfo)
-(
- LPCSTR lpszUrl,
- DWORD dwUrlLength,
- LPSTR lpszUrlHostName,
- DWORD dwUrlHostNameLength,
- LPSTR * lplpszProxyHostName,
- LPDWORD lpdwProxyHostNameLength
- );
+ typedef BOOL (STDAPICALLTYPE * pfnInternetGetProxyInfo)
+ (
+ LPCSTR lpszUrl,
+ DWORD dwUrlLength,
+ LPSTR lpszUrlHostName,
+ DWORD dwUrlHostNameLength,
+ LPSTR * lplpszProxyHostName,
+ LPDWORD lpdwProxyHostNameLength
+ );
} // extern "C"
#endif // _TRY_JSPROXY
@@ -114,13 +192,13 @@
#include <string>
#endif // _TRY_IE_LAN_SETTINGS
-using namespace talk_base;
+namespace talk_base {
//////////////////////////////////////////////////////////////////////
// Utility Functions
//////////////////////////////////////////////////////////////////////
-#ifdef _WINDOWS
+#ifdef WIN32
#ifdef _UNICODE
typedef std::wstring tstring;
@@ -132,39 +210,11 @@
std::string Utf8String(const tstring& str) { return str; }
#endif // !_UNICODE
-#endif // _WINDOWS
-
-//////////////////////////////////////////////////////////////////////
-// GetProxySettingsForUrl
-//////////////////////////////////////////////////////////////////////
-
-bool WildMatch(const char * target, const char * pattern) {
- while (*pattern) {
- if (*pattern == '*') {
- if (!*++pattern) {
- return true;
- }
- while (*target) {
- if ((toupper(*pattern) == toupper(*target)) && WildMatch(target + 1, pattern + 1)) {
- return true;
- }
- ++target;
- }
- return false;
- } else {
- if (toupper(*pattern) != toupper(*target)) {
- return false;
- }
- ++target;
- ++pattern;
- }
- }
- return !*target;
-}
+#endif // WIN32
bool ProxyItemMatch(const Url<char>& url, char * item, size_t len) {
// hostname:443
- if (char * port = strchr(item, ':')) {
+ if (char * port = ::strchr(item, ':')) {
*port++ = '\0';
if (url.port() != atol(port)) {
return false;
@@ -175,34 +225,36 @@
int a, b, c, d, m;
int match = sscanf(item, "%d.%d.%d.%d/%d", &a, &b, &c, &d, &m);
if (match >= 4) {
- uint32 ip = ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | (d & 0xFF);
+ uint32 ip = ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) |
+ (d & 0xFF);
if ((match < 5) || (m > 32))
m = 32;
else if (m < 0)
m = 0;
uint32 mask = (m == 0) ? 0 : (~0UL) << (32 - m);
- SocketAddress addr(url.server());
+ SocketAddress addr(url.host(), 0);
return !addr.IsUnresolved() && ((addr.ip() & mask) == (ip & mask));
}
// .foo.com
if (*item == '.') {
- size_t hostlen = url.server().length();
+ size_t hostlen = url.host().length();
return (hostlen > len)
- && (stricmp(url.server().c_str() + (hostlen - len), item) == 0);
+ && (stricmp(url.host().c_str() + (hostlen - len), item) == 0);
}
// localhost or www.*.com
- if (!WildMatch(url.server().c_str(), item))
+ if (!string_match(url.host().c_str(), item))
return false;
return true;
}
-bool ProxyListMatch(const Url<char>& url, const std::string& slist, char sep) {
+bool ProxyListMatch(const Url<char>& url, const std::string& proxy_list,
+ char sep) {
const size_t BUFSIZE = 256;
char buffer[BUFSIZE];
- const char* list = slist.c_str();
+ const char* list = proxy_list.c_str();
while (*list) {
// Remove leading space
if (isspace(*list)) {
@@ -212,7 +264,7 @@
// Break on separator
size_t len;
const char * start = list;
- if (const char * end = strchr(list, sep)) {
+ if (const char * end = ::strchr(list, sep)) {
len = (end - list);
list += len + 1;
} else {
@@ -236,11 +288,11 @@
bool Better(ProxyType lhs, const ProxyType rhs) {
// PROXY_NONE, PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN
- const int PROXY_VALUE[4] = { 0, 2, 3, 1 };
+ const int PROXY_VALUE[5] = { 0, 2, 3, 1 };
return (PROXY_VALUE[lhs] > PROXY_VALUE[rhs]);
}
-bool ParseProxy(const std::string& saddress, ProxyInfo& proxy) {
+bool ParseProxy(const std::string& saddress, ProxyInfo* proxy) {
const size_t kMaxAddressLength = 1024;
// Allow semicolon, space, or tab as an address separator
const char* const kAddressSeparator = " ;\t";
@@ -256,7 +308,7 @@
if (const char * sep = strchr(address, kAddressSeparator)) {
len = (sep - address);
address += len + 1;
- while (strchr(kAddressSeparator, *address)) {
+ while (*address != '\0' && ::strchr(kAddressSeparator, *address)) {
address += 1;
}
} else {
@@ -273,7 +325,7 @@
memcpy(buffer, start, len);
buffer[len] = 0;
- char * colon = strchr(buffer, ':');
+ char * colon = ::strchr(buffer, ':');
if (!colon) {
LOG(LS_WARNING) << "Proxy address without port [" << buffer << "]";
continue;
@@ -287,7 +339,7 @@
continue;
}
- if (char * equals = strchr(buffer, '=')) {
+ if (char * equals = ::strchr(buffer, '=')) {
*equals = 0;
host = equals + 1;
if (_stricmp(buffer, "socks") == 0) {
@@ -304,17 +356,279 @@
ptype = PROXY_UNKNOWN;
}
- if (Better(ptype, proxy.type)) {
- proxy.type = ptype;
- proxy.address.SetIP(host);
- proxy.address.SetPort((int)port);
+ if (Better(ptype, proxy->type)) {
+ proxy->type = ptype;
+ proxy->address.SetIP(host);
+ proxy->address.SetPort(port);
}
}
- return (proxy.type != PROXY_NONE);
+ return proxy->type != PROXY_NONE;
}
-#if _WINDOWS
+UserAgent GetAgent(const char* agent) {
+ if (agent) {
+ std::string agent_str(agent);
+ if (agent_str.find(kFirefoxPattern) != std::string::npos) {
+ return UA_FIREFOX;
+ } else if (agent_str.find(kInternetExplorerPattern) != std::string::npos) {
+ return UA_INTERNETEXPLORER;
+ } else if (agent_str.empty()) {
+ return UA_UNKNOWN;
+ }
+ }
+ return UA_OTHER;
+}
+
+bool EndsWith(const std::string& a, const std::string& b) {
+ if (b.size() > a.size()) {
+ return false;
+ }
+ int result = a.compare(a.size() - b.size(), b.size(), b);
+ return result == 0;
+}
+
+bool GetFirefoxProfilePath(Pathname* path) {
+#ifdef WIN32
+ wchar_t w_path[MAX_PATH];
+ if (SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, w_path) !=
+ S_OK) {
+ LOG(LS_ERROR) << "SHGetFolderPath failed";
+ return false;
+ }
+ path->SetFolder(ToUtf8(w_path, wcslen(w_path)));
+ path->AppendFolder("Mozilla");
+ path->AppendFolder("Firefox");
+#elif OSX
+ FSRef fr;
+ if (0 != FSFindFolder(kUserDomain, kApplicationSupportFolderType,
+ kCreateFolder, &fr)) {
+ LOG(LS_ERROR) << "FSFindFolder failed";
+ return false;
+ }
+ char buffer[NAME_MAX + 1];
+ if (0 != FSRefMakePath(&fr, reinterpret_cast<uint8*>(buffer),
+ ARRAY_SIZE(buffer))) {
+ LOG(LS_ERROR) << "FSRefMakePath failed";
+ return false;
+ }
+ path->SetFolder(std::string(buffer));
+ path->AppendFolder("Firefox");
+#else
+ char* user_home = getenv("HOME");
+ if (user_home == NULL) {
+ return false;
+ }
+ path->SetFolder(std::string(user_home));
+ path->AppendFolder(".mozilla");
+ path->AppendFolder("firefox");
+#endif // WIN32
+ return true;
+}
+
+bool GetDefaultFirefoxProfile(Pathname* profile_path) {
+ ASSERT(NULL != profile_path);
+ Pathname path;
+ if (!GetFirefoxProfilePath(&path)) {
+ return false;
+ }
+
+#if USE_FIREFOX_PROFILES_INI
+ // [Profile0]
+ // Name=default
+ // IsRelative=1
+ // Path=Profiles/2de53ejb.default
+ // Default=1
+
+ // Note: we are looking for the first entry with "Default=1", or the last
+ // entry in the file
+ path.SetFilename("profiles.ini");
+ FileStream* fs = Filesystem::OpenFile(path, "r");
+ if (!fs) {
+ return false;
+ }
+ Pathname candidate;
+ bool relative = true;
+ std::string line;
+ while (fs->ReadLine(&line) == SR_SUCCESS) {
+ if (line.length() == 0) {
+ continue;
+ }
+ if (line.at(0) == '[') {
+ relative = true;
+ candidate.clear();
+ } else if (line.find("IsRelative=") == 0 &&
+ line.length() >= 12) {
+ // TODO: The initial Linux public launch revealed a fairly
+ // high number of machines where IsRelative= did not have anything after
+ // it. Perhaps that is legal profiles.ini syntax?
+ relative = (line.at(11) != '0');
+ } else if (line.find("Path=") == 0 &&
+ line.length() >= 6) {
+ if (relative) {
+ candidate = path;
+ } else {
+ candidate.clear();
+ }
+ candidate.AppendFolder(line.substr(5));
+ } else if (line.find("Default=") == 0 &&
+ line.length() >= 9) {
+ if ((line.at(8) != '0') && !candidate.empty()) {
+ break;
+ }
+ }
+ }
+ fs->Close();
+ if (candidate.empty()) {
+ return false;
+ }
+ profile_path->SetPathname(candidate.pathname());
+
+#else // !USE_FIREFOX_PROFILES_INI
+ path.AppendFolder("Profiles");
+ DirectoryIterator* it = Filesystem::IterateDirectory();
+ it->Iterate(path);
+ std::string extension(".default");
+ while (!EndsWith(it->Name(), extension)) {
+ if (!it->Next()) {
+ return false;
+ }
+ }
+
+ profile_path->SetPathname(path);
+ profile->AppendFolder("Profiles");
+ profile->AppendFolder(it->Name());
+ delete it;
+
+#endif // !USE_FIREFOX_PROFILES_INI
+
+ return true;
+}
+
+bool ReadFirefoxPrefs(const Pathname& filename,
+ const char * prefix,
+ StringMap* settings) {
+ FileStream* fs = Filesystem::OpenFile(filename, "r");
+ if (!fs) {
+ LOG(LS_ERROR) << "Failed to open file: " << filename.pathname();
+ return false;
+ }
+
+ std::string line;
+ while (fs->ReadLine(&line) == SR_SUCCESS) {
+ size_t prefix_len = strlen(prefix);
+
+ // Skip blank lines and too long lines.
+ if ((line.length() == 0) || (line.length() > kMaxLineLength)
+ || (line.at(0) == '#') || line.compare(0, 2, "/*") == 0
+ || line.compare(0, 2, " *") == 0) {
+ continue;
+ }
+
+ char buffer[kMaxLineLength];
+ strcpyn(buffer, sizeof(buffer), line.c_str());
+ int nstart = 0, nend = 0, vstart = 0, vend = 0;
+ sscanf(buffer, "user_pref(\"%n%*[^\"]%n\", %n%*[^)]%n);",
+ &nstart, &nend, &vstart, &vend);
+ if (vend > 0) {
+ char* name = buffer + nstart;
+ name[nend - nstart] = 0;
+ if ((vend - vstart >= 2) && (buffer[vstart] == '"')) {
+ vstart += 1;
+ vend -= 1;
+ }
+ char* value = buffer + vstart;
+ value[vend - vstart] = 0;
+ if ((strncmp(name, prefix, prefix_len) == 0) && *value) {
+ settings->Add(name + prefix_len, value);
+ }
+ } else {
+ LOG_F(LS_WARNING) << "Unparsed pref [" << buffer << "]";
+ }
+ }
+ fs->Close();
+ return true;
+}
+
+bool GetFirefoxProxySettings(const char* url, ProxyInfo* proxy) {
+ Url<char> purl(url);
+ Pathname path;
+ bool success = false;
+ if (GetDefaultFirefoxProfile(&path)) {
+ StringMap settings;
+ path.SetFilename("prefs.js");
+ if (ReadFirefoxPrefs(path, "network.proxy.", &settings)) {
+ success = true;
+ proxy->bypass_list =
+ settings.Get("no_proxies_on", "localhost, 127.0.0.1");
+ if (settings.Get("type") == "1") {
+ // User has manually specified a proxy, try to figure out what
+ // type it is.
+ if (ProxyListMatch(purl, proxy->bypass_list.c_str(), ',')) {
+ // Our url is in the list of url's to bypass proxy.
+ } else if (settings.Get("share_proxy_settings") == "true") {
+ proxy->type = PROXY_UNKNOWN;
+ proxy->address.SetIP(settings.Get("http"));
+ proxy->address.SetPort(atoi(settings.Get("http_port").c_str()));
+ } else if (settings.IsSet("socks")) {
+ proxy->type = PROXY_SOCKS5;
+ proxy->address.SetIP(settings.Get("socks"));
+ proxy->address.SetPort(atoi(settings.Get("socks_port").c_str()));
+ } else if (settings.IsSet("ssl")) {
+ proxy->type = PROXY_HTTPS;
+ proxy->address.SetIP(settings.Get("ssl"));
+ proxy->address.SetPort(atoi(settings.Get("ssl_port").c_str()));
+ } else if (settings.IsSet("http")) {
+ proxy->type = PROXY_HTTPS;
+ proxy->address.SetIP(settings.Get("http"));
+ proxy->address.SetPort(atoi(settings.Get("http_port").c_str()));
+ }
+ } else if (settings.Get("type") == "2") {
+ // Browser is configured to get proxy settings from a given url.
+ proxy->autoconfig_url = settings.Get("autoconfig_url").c_str();
+ } else if (settings.Get("type") == "4") {
+ // Browser is configured to auto detect proxy config.
+ proxy->autodetect = true;
+ } else {
+ // No proxy set.
+ }
+ }
+ }
+ return success;
+}
+
+#ifdef WIN32 // Windows specific implementation for reading Internet
+ // Explorer proxy settings.
+
+void LogGetProxyFault() {
+ LOG_GLEM(LERROR, WINHTTP) << "WinHttpGetProxyForUrl faulted!!";
+}
+
+BOOL MyWinHttpGetProxyForUrl(pfnWinHttpGetProxyForUrl pWHGPFU,
+ HINTERNET hWinHttp, LPCWSTR url,
+ WINHTTP_AUTOPROXY_OPTIONS *options,
+ WINHTTP_PROXY_INFO *info) {
+ // WinHttpGetProxyForUrl() can call plugins which can crash.
+ // In the case of McAfee scriptproxy.dll, it does crash in
+ // older versions. Try to catch crashes here and treat as an
+ // error.
+ BOOL success = FALSE;
+
+#if (_HAS_EXCEPTIONS == 0)
+ __try {
+ success = pWHGPFU(hWinHttp, url, options, info);
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ // This is a separate function to avoid
+ // Visual C++ error 2712 when compiling with C++ EH
+ LogGetProxyFault();
+ }
+#else
+ success = pWHGPFU(hWinHttp, url, options, info);
+#endif // (_HAS_EXCEPTIONS == 0)
+
+ return success;
+}
+
bool IsDefaultBrowserFirefox() {
HKEY key;
LONG result = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command",
@@ -337,7 +651,7 @@
bool success = false;
if (ERROR_SUCCESS == result) {
value[size] = L'\0';
- for (size_t i=0; i<size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
value[i] = tolowercase(value[i]);
}
success = (NULL != strstr(value, L"firefox.exe"));
@@ -345,483 +659,601 @@
delete [] value;
return success;
}
-#endif
-#if _TRY_FIREFOX
-
-#define USE_FIREFOX_PROFILES_INI 1
-
-bool GetDefaultFirefoxProfile(std::wstring* profile) {
- ASSERT(NULL != profile);
-
- wchar_t path[MAX_PATH];
- if (SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, path) != S_OK)
+bool GetWinHttpProxySettings(const char* url, ProxyInfo* proxy) {
+ HMODULE winhttp_handle = LoadLibrary(L"winhttp.dll");
+ if (winhttp_handle == NULL) {
+ LOG(LS_ERROR) << "Failed to load winhttp.dll.";
return false;
-
- std::wstring profile_root(path);
- profile_root.append(L"\\Mozilla\\Firefox\\");
-
-#if USE_FIREFOX_PROFILES_INI
- std::wstring tmp(profile_root);
- tmp.append(L"profiles.ini");
-
- FILE * fp = _wfopen(tmp.c_str(), L"rb");
- if (!fp)
- return false;
-
- // [Profile0]
- // Name=default
- // IsRelative=1
- // Path=Profiles/2de53ejb.default
- // Default=1
-
- // Note: we are looking for the first entry with "Default=1", or the last entry in the file
-
- std::wstring candidate;
- bool relative = true;
-
- char buffer[1024];
- while (fgets(buffer, sizeof(buffer), fp)) {
- size_t len = strlen(buffer);
- while ((len > 0) && isspace(buffer[len-1]))
- buffer[--len] = 0;
- if (buffer[0] == '[') {
- relative = true;
- candidate.clear();
- } else if (strnicmp(buffer, "IsRelative=", 11) == 0) {
- relative = (buffer[11] != '0');
- } else if (strnicmp(buffer, "Path=", 5) == 0) {
- if (relative) {
- candidate = profile_root;
- } else {
- candidate.clear();
+ }
+ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG iecfg;
+ memset(&iecfg, 0, sizeof(iecfg));
+ Url<char> purl(url);
+ pfnWinHttpGetIEProxyConfig pWHGIEPC =
+ reinterpret_cast<pfnWinHttpGetIEProxyConfig>(
+ GetProcAddress(winhttp_handle,
+ "WinHttpGetIEProxyConfigForCurrentUser"));
+ bool success = false;
+ if (pWHGIEPC && pWHGIEPC(&iecfg)) {
+ // We were read proxy config successfully.
+ success = true;
+ if (iecfg.fAutoDetect) {
+ proxy->autodetect = true;
+ }
+ if (iecfg.lpszAutoConfigUrl) {
+ proxy->autoconfig_url = ToUtf8(iecfg.lpszAutoConfigUrl);
+ GlobalFree(iecfg.lpszAutoConfigUrl);
+ }
+ if (iecfg.lpszProxyBypass) {
+ proxy->bypass_list = ToUtf8(iecfg.lpszProxyBypass);
+ GlobalFree(iecfg.lpszProxyBypass);
+ }
+ if (iecfg.lpszProxy) {
+ if (!ProxyListMatch(purl, proxy->bypass_list, ';')) {
+ ParseProxy(ToUtf8(iecfg.lpszProxy), proxy);
}
- candidate.append(ToUtf16(buffer + 5));
- candidate.append(L"\\");
- } else if (strnicmp(buffer, "Default=", 8) == 0) {
- if ((buffer[8] != '0') && !candidate.empty()) {
- break;
- }
+ GlobalFree(iecfg.lpszProxy);
}
}
- fclose(fp);
- if (candidate.empty())
- return false;
- *profile = candidate;
-
-#else // !USE_FIREFOX_PROFILES_INI
- std::wstring tmp(profile_root);
- tmp.append(L"Profiles\\*.default");
- WIN32_FIND_DATA fdata;
- HANDLE hFind = FindFirstFile(tmp.c_str(), &fdata);
- if (hFind == INVALID_HANDLE_VALUE)
- return false;
-
- profile->assign(profile_root);
- profile->append(L"Profiles\\");
- profile->append(fdata.cFileName);
- profile->append(L"\\");
- FindClose(hFind);
-#endif // !USE_FIREFOX_PROFILES_INI
-
- return true;
-}
-
-struct StringMap {
-public:
- void Add(const char * name, const char * value) { map_[name] = value; }
- const std::string& Get(const char * name, const char * def = "") const {
- std::map<std::string, std::string>::const_iterator it =
- map_.find(name);
- if (it != map_.end())
- return it->second;
- def_ = def;
- return def_;
- }
- bool IsSet(const char * name) const {
- return (map_.find(name) != map_.end());
- }
-private:
- std::map<std::string, std::string> map_;
- mutable std::string def_;
-};
-
-bool ReadFirefoxPrefs(const std::wstring& filename,
- const char * prefix,
- StringMap& settings) {
- FILE * fp = _wfopen(filename.c_str(), L"rb");
- if (!fp)
- return false;
-
- size_t prefix_len = strlen(prefix);
- bool overlong_line = false;
-
- char buffer[1024];
- while (fgets(buffer, sizeof(buffer), fp)) {
- size_t len = strlen(buffer);
- bool missing_newline = (len > 0) && (buffer[len-1] != '\n');
-
- if (missing_newline) {
- overlong_line = true;
- continue;
- } else if (overlong_line) {
- LOG_F(LS_INFO) << "Skipping long line";
- overlong_line = false;
- continue;
- }
-
- while ((len > 0) && isspace(buffer[len-1]))
- buffer[--len] = 0;
-
- // Skip blank lines
- if ((len == 0) || (buffer[0] == '#')
- || (strncmp(buffer, "/*", 2) == 0)
- || (strncmp(buffer, " *", 2) == 0))
- continue;
-
- int nstart = 0, nend = 0, vstart = 0, vend = 0;
- sscanf(buffer, "user_pref(\"%n%*[^\"]%n\", %n%*[^)]%n);",
- &nstart, &nend, &vstart, &vend);
- if (vend > 0) {
- char * name = buffer + nstart;
- name[nend - nstart] = 0;
- if ((vend - vstart >= 2) && (buffer[vstart] == '"')) {
- vstart += 1;
- vend -= 1;
- }
- char * value = buffer + vstart;
- value[vend - vstart] = 0;
- if ((strncmp(name, prefix, prefix_len) == 0) && *value) {
- settings.Add(name + prefix_len, value);
- }
- } else {
- LOG_F(LS_WARNING) << "Unparsed pref [" << buffer << "]";
- }
- }
- fclose(fp);
- return true;
-}
-#endif // _TRY_FIREFOX
-
-#ifdef WIN32
-BOOL MyWinHttpGetProxyForUrl(pfnWinHttpGetProxyForUrl pWHGPFU,
- HINTERNET hWinHttp, LPCWSTR url, WINHTTP_AUTOPROXY_OPTIONS *options,
- WINHTTP_PROXY_INFO *info) {
- // WinHttpGetProxyForUrl() can call plugins which can crash.
- // In the case of McAfee scriptproxy.dll, it does crash in
- // older versions. Try to catch crashes here and treat as an
- // error.
- BOOL success = FALSE;
-
-#if (_HAS_EXCEPTIONS == 0)
- __try {
- success = pWHGPFU(hWinHttp, url, options, info);
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- LOG_GLEM(LERROR,WINHTTP) << "WinHttpGetProxyForUrl faulted!!";
- }
-#else
- success = pWHGPFU(hWinHttp, url, options, info);
-#endif
-
+ FreeLibrary(winhttp_handle);
return success;
}
+
+// Uses the WinHTTP API to auto detect proxy for the given url. Firefox and IE
+// have slightly different option dialogs for proxy settings. In Firefox,
+// either a location of a proxy configuration file can be specified or auto
+// detection can be selected. In IE theese two options can be independently
+// selected. For the case where both options are selected (only IE) we try to
+// fetch the config file first, and if that fails we'll perform an auto
+// detection.
+//
+// Returns true if we successfully performed an auto detection not depending on
+// whether we found a proxy or not. Returns false on error.
+bool WinHttpAutoDetectProxyForUrl(const char* agent, const char* url,
+ ProxyInfo* proxy) {
+ Url<char> purl(url);
+ bool success = true;
+ HMODULE winhttp_handle = LoadLibrary(L"winhttp.dll");
+ if (winhttp_handle == NULL) {
+ LOG(LS_ERROR) << "Failed to load winhttp.dll.";
+ return false;
+ }
+ pfnWinHttpOpen pWHO =
+ reinterpret_cast<pfnWinHttpOpen>(GetProcAddress(winhttp_handle,
+ "WinHttpOpen"));
+ pfnWinHttpCloseHandle pWHCH =
+ reinterpret_cast<pfnWinHttpCloseHandle>(
+ GetProcAddress(winhttp_handle, "WinHttpCloseHandle"));
+ pfnWinHttpGetProxyForUrl pWHGPFU =
+ reinterpret_cast<pfnWinHttpGetProxyForUrl>(
+ GetProcAddress(winhttp_handle, "WinHttpGetProxyForUrl"));
+ if (pWHO && pWHCH && pWHGPFU) {
+ if (HINTERNET hWinHttp = pWHO(ToUtf16(agent).c_str(),
+ WINHTTP_ACCESS_TYPE_NO_PROXY,
+ WINHTTP_NO_PROXY_NAME,
+ WINHTTP_NO_PROXY_BYPASS,
+ 0)) {
+ BOOL result = FALSE;
+ WINHTTP_PROXY_INFO info;
+ memset(&info, 0, sizeof(info));
+ if (proxy->autodetect) {
+ // Use DHCP and DNS to try to find any proxy to use.
+ WINHTTP_AUTOPROXY_OPTIONS options;
+ memset(&options, 0, sizeof(options));
+ options.fAutoLogonIfChallenged = TRUE;
+
+ options.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT;
+ options.dwAutoDetectFlags |= WINHTTP_AUTO_DETECT_TYPE_DHCP
+ | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
+ result = MyWinHttpGetProxyForUrl(
+ pWHGPFU, hWinHttp, ToUtf16(url).c_str(), &options, &info);
+ }
+ if (!result && !proxy->autoconfig_url.empty()) {
+ // We have the location of a proxy config file. Download it and
+ // execute it to find proxy settings for our url.
+ WINHTTP_AUTOPROXY_OPTIONS options;
+ memset(&options, 0, sizeof(options));
+ memset(&info, 0, sizeof(info));
+ options.fAutoLogonIfChallenged = TRUE;
+
+ std::wstring autoconfig_url16((ToUtf16)(proxy->autoconfig_url));
+ options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
+ options.lpszAutoConfigUrl = autoconfig_url16.c_str();
+
+ result = MyWinHttpGetProxyForUrl(
+ pWHGPFU, hWinHttp, ToUtf16(url).c_str(), &options, &info);
+ }
+ if (result) {
+ // Either the given auto config url was valid or auto
+ // detection found a proxy on this network.
+ if (info.lpszProxy) {
+ // TODO: Does this bypass list differ from the list
+ // retreived from GetWinHttpProxySettings earlier?
+ if (info.lpszProxyBypass) {
+ proxy->bypass_list = ToUtf8(info.lpszProxyBypass);
+ GlobalFree(info.lpszProxyBypass);
+ } else {
+ proxy->bypass_list.clear();
+ }
+ if (!ProxyListMatch(purl, proxy->bypass_list, ';')) {
+ // Found proxy for this URL. If parsing the address turns
+ // out ok then we are successful.
+ success = ParseProxy(ToUtf8(info.lpszProxy), proxy);
+ }
+ GlobalFree(info.lpszProxy);
+ }
+ } else {
+ // We could not find any proxy for this url.
+ LOG(LS_INFO) << "No proxy detected for " << url;
+ }
+ pWHCH(hWinHttp);
+ }
+ } else {
+ LOG(LS_ERROR) << "Failed loading WinHTTP functions.";
+ success = false;
+ }
+ FreeLibrary(winhttp_handle);
+ return success;
+}
+
+#if 0 // Below functions currently not used.
+
+bool GetJsProxySettings(const char* url, ProxyInfo* proxy) {
+ Url<char> purl(url);
+ bool success = false;
+
+ if (HMODULE hModJS = LoadLibrary(_T("jsproxy.dll"))) {
+ pfnInternetGetProxyInfo pIGPI =
+ reinterpret_cast<pfnInternetGetProxyInfo>(
+ GetProcAddress(hModJS, "InternetGetProxyInfo"));
+ if (pIGPI) {
+ char proxy[256], host[256];
+ memset(proxy, 0, sizeof(proxy));
+ char * ptr = proxy;
+ DWORD proxylen = sizeof(proxy);
+ std::string surl = Utf8String(url);
+ DWORD hostlen = _snprintf(host, sizeof(host), "http%s://%S",
+ purl.secure() ? "s" : "", purl.server());
+ if (pIGPI(surl.data(), surl.size(), host, hostlen, &ptr, &proxylen)) {
+ LOG(INFO) << "Proxy: " << proxy;
+ } else {
+ LOG_GLE(INFO) << "InternetGetProxyInfo";
+ }
+ }
+ FreeLibrary(hModJS);
+ }
+ return success;
+}
+
+bool GetWmProxySettings(const char* url, ProxyInfo* proxy) {
+ Url<char> purl(url);
+ bool success = false;
+
+ INSNetSourceCreator * nsc = 0;
+ HRESULT hr = CoCreateInstance(CLSID_ClientNetManager, 0, CLSCTX_ALL,
+ IID_INSNetSourceCreator, (LPVOID *) &nsc);
+ if (SUCCEEDED(hr)) {
+ if (SUCCEEDED(hr = nsc->Initialize())) {
+ VARIANT dispatch;
+ VariantInit(&dispatch);
+ if (SUCCEEDED(hr = nsc->GetNetSourceAdminInterface(L"http", &dispatch))) {
+ IWMSInternalAdminNetSource * ians = 0;
+ if (SUCCEEDED(hr = dispatch.pdispVal->QueryInterface(
+ IID_IWMSInternalAdminNetSource, (LPVOID *) &ians))) {
+ _bstr_t host(purl.server());
+ BSTR proxy = 0;
+ BOOL bProxyEnabled = FALSE;
+ DWORD port, context = 0;
+ if (SUCCEEDED(hr = ians->FindProxyForURL(
+ L"http", host, &bProxyEnabled, &proxy, &port, &context))) {
+ success = true;
+ if (bProxyEnabled) {
+ _bstr_t sproxy = proxy;
+ proxy->ptype = PT_HTTPS;
+ proxy->host = sproxy;
+ proxy->port = port;
+ }
+ }
+ SysFreeString(proxy);
+ if (FAILED(hr = ians->ShutdownProxyContext(context))) {
+ LOG(LS_INFO) << "IWMSInternalAdminNetSource::ShutdownProxyContext"
+ << "failed: " << hr;
+ }
+ ians->Release();
+ }
+ }
+ VariantClear(&dispatch);
+ if (FAILED(hr = nsc->Shutdown())) {
+ LOG(LS_INFO) << "INSNetSourceCreator::Shutdown failed: " << hr;
+ }
+ }
+ nsc->Release();
+ }
+ return success;
+}
+
+bool GetIePerConnectionProxySettings(const char* url, ProxyInfo* proxy) {
+ Url<char> purl(url);
+ bool success = false;
+
+ INTERNET_PER_CONN_OPTION_LIST list;
+ INTERNET_PER_CONN_OPTION options[3];
+ memset(&list, 0, sizeof(list));
+ memset(&options, 0, sizeof(options));
+
+ list.dwSize = sizeof(list);
+ list.dwOptionCount = 3;
+ list.pOptions = options;
+ options[0].dwOption = INTERNET_PER_CONN_FLAGS;
+ options[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
+ options[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
+ DWORD dwSize = sizeof(list);
+
+ if (!InternetQueryOption(0, INTERNET_OPTION_PER_CONNECTION_OPTION, &list,
+ &dwSize)) {
+ LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
+ } else if ((options[0].Value.dwValue & PROXY_TYPE_PROXY) != 0) {
+ success = true;
+ if (!ProxyListMatch(purl, nonnull(options[2].Value.pszValue), _T(';'))) {
+ ParseProxy(nonnull(options[1].Value.pszValue), proxy);
+ }
+ } else if ((options[0].Value.dwValue & PROXY_TYPE_DIRECT) != 0) {
+ success = true;
+ } else {
+ LOG(LS_INFO) << "unknown internet access type: "
+ << options[0].Value.dwValue;
+ }
+ if (options[1].Value.pszValue) {
+ GlobalFree(options[1].Value.pszValue);
+ }
+ if (options[2].Value.pszValue) {
+ GlobalFree(options[2].Value.pszValue);
+ }
+ return success;
+}
+
+#endif // 0
+
+// Uses the InternetQueryOption function to retrieve proxy settings
+// from the registry. This will only give us the 'static' settings,
+// ie, not any information about auto config etc.
+bool GetIeLanProxySettings(const char* url, ProxyInfo* proxy) {
+ Url<char> purl(url);
+ bool success = false;
+
+ wchar_t buffer[1024];
+ memset(buffer, 0, sizeof(buffer));
+ INTERNET_PROXY_INFO * info = reinterpret_cast<INTERNET_PROXY_INFO *>(buffer);
+ DWORD dwSize = sizeof(buffer);
+
+ if (!InternetQueryOption(0, INTERNET_OPTION_PROXY, info, &dwSize)) {
+ LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
+ } else if (info->dwAccessType == INTERNET_OPEN_TYPE_DIRECT) {
+ success = true;
+ } else if (info->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
+ success = true;
+ if (!ProxyListMatch(purl, nonnull(reinterpret_cast<const char*>(
+ info->lpszProxyBypass)), ' ')) {
+ ParseProxy(nonnull(reinterpret_cast<const char*>(info->lpszProxy)),
+ proxy);
+ }
+ } else {
+ LOG(LS_INFO) << "unknown internet access type: " << info->dwAccessType;
+ }
+ return success;
+}
+
+bool GetIeProxySettings(const char* agent, const char* url, ProxyInfo* proxy) {
+ bool success = GetWinHttpProxySettings(url, proxy);
+ if (!success) {
+ // TODO: Should always call this if no proxy were detected by
+ // GetWinHttpProxySettings?
+ // WinHttp failed. Try using the InternetOptionQuery method instead.
+ return GetIeLanProxySettings(url, proxy);
+ }
+ return true;
+}
+
+#endif // WIN32
+
+#ifdef OSX // OSX specific implementation for reading system wide
+ // proxy settings.
+
+bool p_getProxyInfoForTypeFromDictWithKeys(ProxyInfo* proxy,
+ ProxyType type,
+ const CFDictionaryRef proxyDict,
+ const CFStringRef enabledKey,
+ const CFStringRef hostKey,
+ const CFStringRef portKey) {
+ // whether or not we set up the proxy info.
+ bool result = false;
+
+ // we use this as a scratch variable for determining if operations
+ // succeeded.
+ bool converted = false;
+
+ // the data we need to construct the SocketAddress for the proxy.
+ std::string hostname;
+ int port;
+
+ if ((proxyDict != NULL) &&
+ (CFGetTypeID(proxyDict) == CFDictionaryGetTypeID())) {
+ // CoreFoundation stuff that we'll have to get from
+ // the dictionaries and interpret or convert into more usable formats.
+ CFNumberRef enabledCFNum;
+ CFNumberRef portCFNum;
+ CFStringRef hostCFStr;
+
+ enabledCFNum = (CFNumberRef)CFDictionaryGetValue(proxyDict, enabledKey);
+
+ if (p_isCFNumberTrue(enabledCFNum)) {
+ // let's see if we can get the address and port.
+ hostCFStr = (CFStringRef)CFDictionaryGetValue(proxyDict, hostKey);
+ converted = p_convertHostCFStringRefToCPPString(hostCFStr, hostname);
+ if (converted) {
+ portCFNum = (CFNumberRef)CFDictionaryGetValue(proxyDict, portKey);
+ converted = p_convertCFNumberToInt(portCFNum, &port);
+ if (converted) {
+ // we have something enabled, with a hostname and a port.
+ // That's sufficient to set up the proxy info.
+ proxy->type = type;
+ proxy->address.SetIP(hostname);
+ proxy->address.SetPort(port);
+ result = true;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+// Looks for proxy information in the given dictionary,
+// return true if it found sufficient information to define one,
+// false otherwise. This is guaranteed to not change the values in proxy
+// unless a full-fledged proxy description was discovered in the dictionary.
+// However, at the present time this does not support username or password.
+// Checks first for a SOCKS proxy, then for HTTPS, then HTTP.
+bool GetMacProxySettingsFromDictionary(ProxyInfo* proxy,
+ const CFDictionaryRef proxyDict) {
+ // the function result.
+ bool gotProxy = false;
+
+
+ // first we see if there's a SOCKS proxy in place.
+ gotProxy = p_getProxyInfoForTypeFromDictWithKeys(proxy,
+ PROXY_SOCKS5,
+ proxyDict,
+ kSCPropNetProxiesSOCKSEnable,
+ kSCPropNetProxiesSOCKSProxy,
+ kSCPropNetProxiesSOCKSPort);
+
+ if (!gotProxy) {
+ // okay, no SOCKS proxy, let's look for https.
+ gotProxy = p_getProxyInfoForTypeFromDictWithKeys(proxy,
+ PROXY_HTTPS,
+ proxyDict,
+ kSCPropNetProxiesHTTPSEnable,
+ kSCPropNetProxiesHTTPSProxy,
+ kSCPropNetProxiesHTTPSPort);
+ if (!gotProxy) {
+ // Finally, try HTTP proxy. Note that flute doesn't
+ // differentiate between HTTPS and HTTP, hence we are using the
+ // same flute type here, ie. PROXY_HTTPS.
+ gotProxy = p_getProxyInfoForTypeFromDictWithKeys(
+ proxy, PROXY_HTTPS, proxyDict, kSCPropNetProxiesHTTPEnable,
+ kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort);
+ }
+ }
+ return gotProxy;
+}
+
+bool p_putPasswordInProxyInfo(ProxyInfo* proxy) {
+ bool result = true; // by default we assume we're good.
+ // for all we know there isn't any password. We'll set to false
+ // if we find a problem.
+
+ // Ask the keychain for an internet password search for the given protocol.
+ OSStatus oss = 0;
+ SecKeychainAttributeList attrList;
+ attrList.count = 3;
+ SecKeychainAttribute attributes[3];
+ attrList.attr = attributes;
+
+ attributes[0].tag = kSecProtocolItemAttr;
+ attributes[0].length = sizeof(SecProtocolType);
+ SecProtocolType protocol;
+ switch (proxy->type) {
+ case PROXY_HTTPS :
+ protocol = kSecProtocolTypeHTTPS;
+ break;
+ case PROXY_SOCKS5 :
+ protocol = kSecProtocolTypeSOCKS;
+ break;
+ default :
+ LOG(LS_ERROR) << "asked for proxy password for unknown proxy type.";
+ result = false;
+ break;
+ }
+ attributes[0].data = &protocol;
+
+ UInt32 port = proxy->address.port();
+ attributes[1].tag = kSecPortItemAttr;
+ attributes[1].length = sizeof(UInt32);
+ attributes[1].data = &port;
+
+ std::string ip = proxy->address.IPAsString();
+ attributes[2].tag = kSecServerItemAttr;
+ attributes[2].length = ip.length();
+ attributes[2].data = const_cast<char*>(ip.c_str());
+
+ if (result) {
+ LOG(LS_INFO) << "trying to get proxy username/password";
+ SecKeychainSearchRef sref;
+ oss = SecKeychainSearchCreateFromAttributes(NULL,
+ kSecInternetPasswordItemClass,
+ &attrList, &sref);
+ if (0 == oss) {
+ LOG(LS_INFO) << "SecKeychainSearchCreateFromAttributes was good";
+ // Get the first item, if there is one.
+ SecKeychainItemRef iref;
+ oss = SecKeychainSearchCopyNext(sref, &iref);
+ if (0 == oss) {
+ LOG(LS_INFO) << "...looks like we have the username/password data";
+ // If there is, get the username and the password.
+
+ SecKeychainAttributeInfo attribsToGet;
+ attribsToGet.count = 1;
+ UInt32 tag = kSecAccountItemAttr;
+ UInt32 format = CSSM_DB_ATTRIBUTE_FORMAT_STRING;
+ void *data;
+ UInt32 length;
+ SecKeychainAttributeList *localList;
+
+ attribsToGet.tag = &tag;
+ attribsToGet.format = &format;
+ OSStatus copyres = SecKeychainItemCopyAttributesAndData(iref,
+ &attribsToGet,
+ NULL,
+ &localList,
+ &length,
+ &data);
+ if (0 == copyres) {
+ LOG(LS_INFO) << "...and we can pull it out.";
+ // now, we know from experimentation (sadly not from docs)
+ // that the username is in the local attribute list,
+ // and the password in the data,
+ // both without null termination but with info on their length.
+ // grab the password from the data.
+ std::string password;
+ password.append(static_cast<const char*>(data), length);
+
+ // make the password into a CryptString
+ // huh, at the time of writing, you can't.
+ // so we'll skip that for now and come back to it later.
+
+ // now put the username in the proxy.
+ if (1 <= localList->attr->length) {
+ proxy->username.append(
+ static_cast<const char*>(localList->attr->data),
+ localList->attr->length);
+ LOG(LS_INFO) << "username is " << proxy->username;
+ } else {
+ LOG(LS_ERROR) << "got keychain entry with no username";
+ result = false;
+ }
+ } else {
+ LOG(LS_ERROR) << "couldn't copy info from keychain.";
+ result = false;
+ }
+ SecKeychainItemFreeAttributesAndData(localList, data);
+ } else if (errSecItemNotFound == oss) {
+ LOG(LS_INFO) << "...username/password info not found";
+ } else {
+ // oooh, neither 0 nor itemNotFound.
+ LOG(LS_ERROR) << "Couldn't get keychain information, error code" << oss;
+ result = false;
+ }
+ } else if (errSecItemNotFound == oss) { // noop
+ } else {
+ // oooh, neither 0 nor itemNotFound.
+ LOG(LS_ERROR) << "Couldn't get keychain information, error code" << oss;
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+bool GetMacProxySettings(ProxyInfo* proxy) {
+ // based on the Apple Technical Q&A QA1234
+ // http://developer.apple.com/qa/qa2001/qa1234.html
+ CFDictionaryRef proxyDict = SCDynamicStoreCopyProxies(NULL);
+ bool result = false;
+
+ if (proxyDict != NULL) {
+ // sending it off to another function makes it easier to unit test
+ // since we can make our own dictionary to hand to that function.
+ result = GetMacProxySettingsFromDictionary(proxy, proxyDict);
+
+ if (result) {
+ result = p_putPasswordInProxyInfo(proxy);
+ }
+
+ // We created the dictionary with something that had the
+ // word 'copy' in it, so we have to release it, according
+ // to the Carbon memory management standards.
+ CFRelease(proxyDict);
+ } else {
+ LOG(LS_ERROR) << "SCDynamicStoreCopyProxies failed";
+ }
+
+ return result;
+}
+#endif // OSX
+
+bool AutoDetectProxySettings(const char* agent, const char* url,
+ ProxyInfo* proxy) {
+#ifdef WIN32
+ return WinHttpAutoDetectProxyForUrl(agent, url, proxy);
+#else
+ LOG(LS_WARNING) << "Proxy auto-detection not implemented for this platform";
+ return false;
#endif
+}
+
+bool GetSystemDefaultProxySettings(const char* agent, const char* url,
+ ProxyInfo* proxy) {
+#ifdef WIN32
+ return GetIeProxySettings(agent, url, proxy);
+#elif OSX
+ return GetMacProxySettings(proxy);
+#else
+ // TODO: Get System settings if browser is not firefox.
+ return GetFirefoxProxySettings(url, proxy);
+#endif
+}
bool GetProxySettingsForUrl(const char* agent, const char* url,
- ProxyInfo& proxy,
- bool long_operation) {
- bool success = false;
- Url<char> purl(url);
-
-#if 0
- assert( WildMatch(_T("A.B.C.D"), _T("a.b.c.d")));
- assert( WildMatch(_T("127.0.0.1"), _T("12*.0.*1")));
- assert(!WildMatch(_T("127.0.0.0"), _T("12*.0.*1")));
- assert(!WildMatch(_T("127.0.0.0"), _T("12*.0.*1")));
- assert( WildMatch(_T("127.1.0.21"), _T("12*.0.*1")));
- assert(!WildMatch(_T("127.1.1.21"), _T("12*.0.*1")));
- purl = PUrl(_T("http://a.b.c:500/"));
- wchar_t item[256];
- _tcscpy(item, _T("a.b.c"));
- assert( ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("a.x.c"));
- assert(!ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("a.b.*"));
- assert( ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("a.x.*"));
- assert(!ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T(".b.c"));
- assert( ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T(".x.c"));
- assert(!ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("a.b.c:500"));
- assert( ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("a.b.c:501"));
- assert(!ProxyItemMatch(purl, item, _tcslen(item)));
- purl = PUrl(_T("http://1.2.3.4/"));
- _tcscpy(item, _T("1.2.3.4"));
- assert( ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("1.2.3.5"));
- assert(!ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("1.2.3.5/31"));
- assert( ProxyItemMatch(purl, item, _tcslen(item)));
- _tcscpy(item, _T("1.2.3.5/32"));
- assert(!ProxyItemMatch(purl, item, _tcslen(item)));
-#endif
-
- bool autoconfig = false;
- bool use_firefox = false;
- std::string autoconfig_url;
-
-#if _TRY_FIREFOX
- use_firefox = IsDefaultBrowserFirefox();
-
- if (use_firefox) {
- std::wstring tmp;
- if (GetDefaultFirefoxProfile(&tmp)) {
- bool complete = true;
-
- StringMap settings;
- tmp.append(L"prefs.js");
- if (ReadFirefoxPrefs(tmp, "network.proxy.", settings)) {
- success = true;
- if (settings.Get("type") == "1") {
- if (ProxyListMatch(purl, settings.Get("no_proxies_on", "localhost, 127.0.0.1").c_str(), ',')) {
- // Bypass proxy
- } else if (settings.Get("share_proxy_settings") == "true") {
- proxy.type = PROXY_UNKNOWN;
- proxy.address.SetIP(settings.Get("http"));
- proxy.address.SetPort(atoi(settings.Get("http_port").c_str()));
- } else if (settings.IsSet("socks")) {
- proxy.type = PROXY_SOCKS5;
- proxy.address.SetIP(settings.Get("socks"));
- proxy.address.SetPort(atoi(settings.Get("socks_port").c_str()));
- } else if (settings.IsSet("ssl")) {
- proxy.type = PROXY_HTTPS;
- proxy.address.SetIP(settings.Get("ssl"));
- proxy.address.SetPort(atoi(settings.Get("ssl_port").c_str()));
- } else if (settings.IsSet("http")) {
- proxy.type = PROXY_HTTPS;
- proxy.address.SetIP(settings.Get("http"));
- proxy.address.SetPort(atoi(settings.Get("http_port").c_str()));
- }
- } else if (settings.Get("type") == "2") {
- complete = success = false;
- autoconfig_url = settings.Get("autoconfig_url").c_str();
- } else if (settings.Get("type") == "4") {
- complete = success = false;
- autoconfig = true;
- }
+ ProxyInfo& proxy, bool long_operation) {
+ UserAgent a = GetAgent(agent);
+ bool result;
+ switch (a) {
+ case UA_FIREFOX: {
+ result = GetFirefoxProxySettings(url, &proxy);
+ break;
+ }
+#ifdef WIN32
+ case UA_INTERNETEXPLORER:
+ result = GetIeProxySettings(agent, url, &proxy);
+ break;
+ case UA_UNKNOWN:
+ // Agent not defined, check default browser.
+ if (IsDefaultBrowserFirefox()) {
+ result = GetFirefoxProxySettings(url, &proxy);
+ } else {
+ result = GetIeProxySettings(agent, url, &proxy);
}
- if (complete) { // Otherwise fall through to IE autoproxy code
- return success;
- }
+ break;
+#endif // WIN32
+ default:
+ result = GetSystemDefaultProxySettings(agent, url, &proxy);
+ break;
+ }
+
+ // TODO: Consider using the 'long_operation' parameter to
+ // decide whether to do the auto detection.
+ if (result && (proxy.autodetect ||
+ !proxy.autoconfig_url.empty())) {
+ // Use WinHTTP to auto detect proxy for us.
+ result = AutoDetectProxySettings(agent, url, &proxy);
+ if (!result) {
+ // Either auto detection is not supported or we simply didn't
+ // find any proxy, reset type.
+ proxy.type = talk_base::PROXY_NONE;
}
}
-#endif // _TRY_FIREFOX
-
-#if _TRY_WINHTTP
- if (!success) {
- if (HMODULE hModWH = LoadLibrary(L"winhttp.dll")) {
- pfnWinHttpOpen pWHO = reinterpret_cast<pfnWinHttpOpen>(GetProcAddress(hModWH, "WinHttpOpen"));
- pfnWinHttpCloseHandle pWHCH = reinterpret_cast<pfnWinHttpCloseHandle>(GetProcAddress(hModWH, "WinHttpCloseHandle"));
- pfnWinHttpGetProxyForUrl pWHGPFU = reinterpret_cast<pfnWinHttpGetProxyForUrl>(GetProcAddress(hModWH, "WinHttpGetProxyForUrl"));
- pfnWinHttpGetIEProxyConfig pWHGIEPC = reinterpret_cast<pfnWinHttpGetIEProxyConfig>(GetProcAddress(hModWH, "WinHttpGetIEProxyConfigForCurrentUser"));
- if (pWHO && pWHCH && pWHGPFU && pWHGIEPC) {
- WINHTTP_CURRENT_USER_IE_PROXY_CONFIG iecfg;
- memset(&iecfg, 0, sizeof(iecfg));
- if (!use_firefox && !pWHGIEPC(&iecfg)) {
- LOG_GLEM(LERROR,WINHTTP) << "WinHttpGetIEProxyConfigForCurrentUser";
- } else {
- success = true;
- if (!use_firefox) {
- if (iecfg.fAutoDetect) {
- autoconfig = true;
- }
- if (iecfg.lpszAutoConfigUrl) {
- autoconfig_url = ToUtf8(iecfg.lpszAutoConfigUrl);
- }
- }
- if (!long_operation) {
- // Unless we perform this operation in the background, don't allow
- // it to take a long time.
- autoconfig = false;
- }
- if (autoconfig || !autoconfig_url.empty()) {
- if (HINTERNET hWinHttp = pWHO(ToUtf16(agent).c_str(),
- WINHTTP_ACCESS_TYPE_NO_PROXY,
- WINHTTP_NO_PROXY_NAME,
- WINHTTP_NO_PROXY_BYPASS,
- 0)) {
- WINHTTP_AUTOPROXY_OPTIONS options;
- memset(&options, 0, sizeof(options));
- if (autoconfig) {
- options.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT;
- options.dwAutoDetectFlags |= WINHTTP_AUTO_DETECT_TYPE_DHCP
- | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
- }
- std::wstring autoconfig_url16((ToUtf16)(autoconfig_url));
- if (!autoconfig_url.empty()) {
- options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
- options.lpszAutoConfigUrl = autoconfig_url16.c_str();
- }
- options.fAutoLogonIfChallenged = TRUE;
- WINHTTP_PROXY_INFO info;
- memset(&info, 0, sizeof(info));
-
- BOOL success = MyWinHttpGetProxyForUrl(pWHGPFU,
- hWinHttp, ToUtf16(url).c_str(), &options, &info);
-
- if (!success) {
- LOG_GLEM(LERROR,WINHTTP) << "WinHttpGetProxyForUrl";
- } else {
- if (iecfg.lpszProxy)
- GlobalFree(iecfg.lpszProxy);
- if (iecfg.lpszProxyBypass)
- GlobalFree(iecfg.lpszProxyBypass);
- iecfg.lpszProxy = info.lpszProxy;
- iecfg.lpszProxyBypass = info.lpszProxyBypass;
- }
- pWHCH(hWinHttp);
- }
- }
- if (!ProxyListMatch(purl, ToUtf8(nonnull(iecfg.lpszProxyBypass)), ' ')) {
- ParseProxy(ToUtf8(nonnull(iecfg.lpszProxy)), proxy);
- }
- if (iecfg.lpszAutoConfigUrl)
- GlobalFree(iecfg.lpszAutoConfigUrl);
- if (iecfg.lpszProxy)
- GlobalFree(iecfg.lpszProxy);
- if (iecfg.lpszProxyBypass)
- GlobalFree(iecfg.lpszProxyBypass);
- }
- }
- FreeLibrary(hModWH);
- }
- }
-#endif // _TRY_WINHTTP
-
-#if _TRY_JSPROXY
- if (!success) {
- if (HMODULE hModJS = LoadLibrary(_T("jsproxy.dll"))) {
- pfnInternetGetProxyInfo pIGPI = reinterpret_cast<pfnInternetGetProxyInfo>(GetProcAddress(hModJS, "InternetGetProxyInfo"));
- if (pIGPI) {
- char proxy[256], host[256];
- memset(proxy, 0, sizeof(proxy));
- char * ptr = proxy;
- DWORD proxylen = sizeof(proxy);
- std::string surl = Utf8String(url);
- DWORD hostlen = _snprintf(host, sizeof(host), "http%s://%S", purl.secure() ? "s" : "", purl.server());
- if (pIGPI(surl.data(), surl.size(), host, hostlen, &ptr, &proxylen)) {
- LOG(INFO) << "Proxy: " << proxy;
- } else {
- LOG_GLE(INFO) << "InternetGetProxyInfo";
- }
- }
- FreeLibrary(hModJS);
- }
- }
-#endif // _TRY_JSPROXY
-
-#if _TRY_WM_FINDPROXY
- if (!success) {
- INSNetSourceCreator * nsc = 0;
- HRESULT hr = CoCreateInstance(CLSID_ClientNetManager, 0, CLSCTX_ALL, IID_INSNetSourceCreator, (LPVOID *) &nsc);
- if (SUCCEEDED(hr)) {
- if (SUCCEEDED(hr = nsc->Initialize())) {
- VARIANT dispatch;
- VariantInit(&dispatch);
- if (SUCCEEDED(hr = nsc->GetNetSourceAdminInterface(L"http", &dispatch))) {
- IWMSInternalAdminNetSource * ians = 0;
- if (SUCCEEDED(hr = dispatch.pdispVal->QueryInterface(IID_IWMSInternalAdminNetSource, (LPVOID *) &ians))) {
- _bstr_t host(purl.server());
- BSTR proxy = 0;
- BOOL bProxyEnabled = FALSE;
- DWORD port, context = 0;
- if (SUCCEEDED(hr = ians->FindProxyForURL(L"http", host, &bProxyEnabled, &proxy, &port, &context))) {
- success = true;
- if (bProxyEnabled) {
- _bstr_t sproxy = proxy;
- proxy.ptype = PT_HTTPS;
- proxy.host = sproxy;
- proxy.port = port;
- }
- }
- SysFreeString(proxy);
- if (FAILED(hr = ians->ShutdownProxyContext(context))) {
- LOG(LS_INFO) << "IWMSInternalAdminNetSource::ShutdownProxyContext failed: " << hr;
- }
- ians->Release();
- }
- }
- VariantClear(&dispatch);
- if (FAILED(hr = nsc->Shutdown())) {
- LOG(LS_INFO) << "INSNetSourceCreator::Shutdown failed: " << hr;
- }
- }
- nsc->Release();
- }
- }
-#endif // _TRY_WM_FINDPROXY
-
-#if _TRY_IE_LAN_SETTINGS
- if (!success) {
- wchar_t buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- INTERNET_PROXY_INFO * info = reinterpret_cast<INTERNET_PROXY_INFO *>(buffer);
- DWORD dwSize = sizeof(buffer);
-
- if (!InternetQueryOption(0, INTERNET_OPTION_PROXY, info, &dwSize)) {
- LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
- } else if (info->dwAccessType == INTERNET_OPEN_TYPE_DIRECT) {
- success = true;
- } else if (info->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
- success = true;
- if (!ProxyListMatch(purl, nonnull(reinterpret_cast<const char*>(info->lpszProxyBypass)), ' ')) {
- ParseProxy(nonnull(reinterpret_cast<const char*>(info->lpszProxy)), proxy);
- }
- } else {
- LOG(LS_INFO) << "unknown internet access type: " << info->dwAccessType;
- }
- }
-#endif // _TRY_IE_LAN_SETTINGS
-
-#if 0
- if (!success) {
- INTERNET_PER_CONN_OPTION_LIST list;
- INTERNET_PER_CONN_OPTION options[3];
- memset(&list, 0, sizeof(list));
- memset(&options, 0, sizeof(options));
-
- list.dwSize = sizeof(list);
- list.dwOptionCount = 3;
- list.pOptions = options;
- options[0].dwOption = INTERNET_PER_CONN_FLAGS;
- options[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
- options[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
- DWORD dwSize = sizeof(list);
-
- if (!InternetQueryOption(0, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &dwSize)) {
- LOG(LS_INFO) << "InternetQueryOption failed: " << GetLastError();
- } else if ((options[0].Value.dwValue & PROXY_TYPE_PROXY) != 0) {
- success = true;
- if (!ProxyListMatch(purl, nonnull(options[2].Value.pszValue), _T(';'))) {
- ParseProxy(nonnull(options[1].Value.pszValue), proxy);
- }
- } else if ((options[0].Value.dwValue & PROXY_TYPE_DIRECT) != 0) {
- success = true;
- } else {
- LOG(LS_INFO) << "unknown internet access type: "
- << options[0].Value.dwValue;
- }
- if (options[1].Value.pszValue) {
- GlobalFree(options[1].Value.pszValue);
- }
- if (options[2].Value.pszValue) {
- GlobalFree(options[2].Value.pszValue);
- }
- }
-#endif // 0
-
- return success;
+ return result;
}
+
+} // namespace talk_base
diff --git a/talk/base/proxydetect.h b/talk/base/proxydetect.h
old mode 100755
new mode 100644
index 3de2598..36ee672
--- a/talk/base/proxydetect.h
+++ b/talk/base/proxydetect.h
@@ -1,13 +1,48 @@
+/*
+ * libjingle
+ * Copyright 2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#ifndef _PROXYDETECT_H_
#define _PROXYDETECT_H_
#include "talk/base/proxyinfo.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+namespace talk_base {
// Auto-detect the proxy server. Returns true if a proxy is configured,
-// although hostname may be empty if the proxy is not required for the given URL.
+// although hostname may be empty if the proxy is not required for
+// the given URL.
bool GetProxySettingsForUrl(const char* agent, const char* url,
talk_base::ProxyInfo& proxy,
bool long_operation = false);
-#endif // _PROXYDETECT_H_
+} // namespace talk_base
+
+#endif // _PROXYDETECT_H_
diff --git a/talk/base/proxyinfo.cc b/talk/base/proxyinfo.cc
old mode 100755
new mode 100644
diff --git a/talk/base/proxyinfo.h b/talk/base/proxyinfo.h
old mode 100755
new mode 100644
index 834ec4f..9e28f1a
--- a/talk/base/proxyinfo.h
+++ b/talk/base/proxyinfo.h
@@ -34,16 +34,24 @@
namespace talk_base {
-enum ProxyType { PROXY_NONE, PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN };
+enum ProxyType {
+ PROXY_NONE,
+ PROXY_HTTPS,
+ PROXY_SOCKS5,
+ PROXY_UNKNOWN
+};
const char * ProxyToString(ProxyType proxy);
struct ProxyInfo {
ProxyType type;
SocketAddress address;
+ std::string autoconfig_url;
+ bool autodetect;
+ std::string bypass_list;
std::string username;
CryptString password;
- ProxyInfo() : type(PROXY_NONE) { }
+ ProxyInfo() : type(PROXY_NONE), autodetect(false) { }
};
} // namespace talk_base
diff --git a/talk/base/schanneladapter.cc b/talk/base/schanneladapter.cc
old mode 100755
new mode 100644
index d971c7e..01aa9ce
--- a/talk/base/schanneladapter.cc
+++ b/talk/base/schanneladapter.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -47,33 +47,6 @@
extern const ConstantLabel SECURITY_ERRORS[];
-const ConstantLabel SECURITY_ERRORS[] = {
- KLABEL(SEC_I_COMPLETE_AND_CONTINUE),
- KLABEL(SEC_I_COMPLETE_NEEDED),
- KLABEL(SEC_I_CONTEXT_EXPIRED),
- KLABEL(SEC_I_CONTINUE_NEEDED),
- KLABEL(SEC_I_INCOMPLETE_CREDENTIALS),
- KLABEL(SEC_I_RENEGOTIATE),
- KLABEL(SEC_E_CERT_EXPIRED),
- KLABEL(SEC_E_INCOMPLETE_MESSAGE),
- KLABEL(SEC_E_INSUFFICIENT_MEMORY),
- KLABEL(SEC_E_INTERNAL_ERROR),
- KLABEL(SEC_E_INVALID_HANDLE),
- KLABEL(SEC_E_INVALID_TOKEN),
- KLABEL(SEC_E_LOGON_DENIED),
- KLABEL(SEC_E_NO_AUTHENTICATING_AUTHORITY),
- KLABEL(SEC_E_NO_CREDENTIALS),
- KLABEL(SEC_E_NOT_OWNER),
- KLABEL(SEC_E_OK),
- KLABEL(SEC_E_SECPKG_NOT_FOUND),
- KLABEL(SEC_E_TARGET_UNKNOWN),
- KLABEL(SEC_E_UNKNOWN_CREDENTIALS),
- KLABEL(SEC_E_UNSUPPORTED_FUNCTION),
- KLABEL(SEC_E_UNTRUSTED_ROOT),
- KLABEL(SEC_E_WRONG_PRINCIPAL),
- LASTLABEL
-};
-
const ConstantLabel SCHANNEL_BUFFER_TYPES[] = {
KLABEL(SECBUFFER_EMPTY), // 0
KLABEL(SECBUFFER_DATA), // 1
@@ -92,7 +65,7 @@
void DescribeBuffer(LoggingSeverity severity, const char* prefix,
const SecBuffer& sb) {
- LOG_V(severity)
+ LOG_V(severity)
<< prefix
<< "(" << sb.cbBuffer
<< ", " << FindLabel(sb.BufferType & ~SECBUFFER_ATTRMASK,
@@ -207,9 +180,9 @@
PCCRYPT_OID_INFO oinfo = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
&alg_id, 0);
LPCWSTR alg_name = (NULL != oinfo) ? oinfo->pwszName : L"Unknown";
- LOG(LS_VERBOSE) << " " << talk_base::ToUtf8(alg_name)
- << " (" << alg_id << ")";
+ LOG(LS_VERBOSE) << " " << ToUtf8(alg_name) << " (" << alg_id << ")";
}
+ CSecBufferBase::FreeSSPI(supported_algs.palgSupportedAlgs);
}
}
@@ -263,7 +236,7 @@
|| (status != SEC_E_INCOMPLETE_MESSAGE)) {
level = LS_VERBOSE; // Expected messages
}
- LOG_V(level)
+ LOG_V(level)
<< "InitializeSecurityContext error: "
<< ErrorName(status, SECURITY_ERRORS);
//if (sbd_in)
@@ -275,7 +248,7 @@
// Wait for more input from server.
return Flush();
}
-
+
if (FAILED(status)) {
// We can't continue. Common errors:
// SEC_E_CERT_EXPIRED - Typically, this means the computer clock is wrong.
@@ -404,7 +377,7 @@
}
continue;
}
-
+
if (status == SEC_E_INCOMPLETE_MESSAGE) {
break;
} else {
@@ -604,7 +577,7 @@
SetError(EWOULDBLOCK);
return SOCKET_ERROR;
}
- size_t read = min(cb, readable.size());
+ size_t read = _min(cb, readable.size());
memcpy(pv, &readable[0], read);
if (size_t remaining = readable.size() - read) {
memmove(&readable[0], &readable[read], remaining);
diff --git a/talk/base/schanneladapter.h b/talk/base/schanneladapter.h
old mode 100755
new mode 100644
diff --git a/talk/base/scoped_ptr.h b/talk/base/scoped_ptr.h
old mode 100755
new mode 100644
index c5e3c5d..fd753ec
--- a/talk/base/scoped_ptr.h
+++ b/talk/base/scoped_ptr.h
@@ -25,9 +25,10 @@
#ifndef TALK_BASE_SCOPED_PTR_H__
#define TALK_BASE_SCOPED_PTR_H__
-#include <cstddef> // for std::ptrdiff_t
-#include <assert.h> // for assert
-#include <stdlib.h> // for free() decl
+#include <cstddef> // for std::ptrdiff_t
+#include <stdlib.h> // for free() decl
+
+#include "talk/base/common.h" // for ASSERT
#ifdef _WIN32
namespace std { using ::ptrdiff_t; };
@@ -48,29 +49,31 @@
typedef T element_type;
- explicit scoped_ptr(T* p = 0): ptr(p) {}
+ explicit scoped_ptr(T* p = NULL): ptr(p) {}
~scoped_ptr() {
typedef char type_must_be_complete[sizeof(T)];
delete ptr;
}
- void reset(T* p = 0) {
+ void reset(T* p = NULL) {
typedef char type_must_be_complete[sizeof(T)];
if (ptr != p) {
- delete ptr;
+ T* obj = ptr;
ptr = p;
+ // Delete last, in case obj destructor indirectly results in ~scoped_ptr
+ delete obj;
}
}
T& operator*() const {
- assert(ptr != 0);
+ ASSERT(ptr != NULL);
return *ptr;
}
T* operator->() const {
- assert(ptr != 0);
+ ASSERT(ptr != NULL);
return ptr;
}
@@ -86,14 +89,14 @@
T* release() {
T* tmp = ptr;
- ptr = 0;
+ ptr = NULL;
return tmp;
}
-
+
T** accept() {
if (ptr) {
delete ptr;
- ptr = 0;
+ ptr = NULL;
}
return &ptr;
}
@@ -128,25 +131,27 @@
typedef T element_type;
- explicit scoped_array(T* p = 0) : ptr(p) {}
+ explicit scoped_array(T* p = NULL) : ptr(p) {}
~scoped_array() {
typedef char type_must_be_complete[sizeof(T)];
delete[] ptr;
}
- void reset(T* p = 0) {
+ void reset(T* p = NULL) {
typedef char type_must_be_complete[sizeof(T)];
if (ptr != p) {
- delete [] ptr;
+ T* arr = ptr;
ptr = p;
+ // Delete last, in case arr destructor indirectly results in ~scoped_array
+ delete [] arr;
}
}
T& operator[](std::ptrdiff_t i) const {
- assert(ptr != 0);
- assert(i >= 0);
+ ASSERT(ptr != NULL);
+ ASSERT(i >= 0);
return ptr[i];
}
@@ -162,14 +167,14 @@
T* release() {
T* tmp = ptr;
- ptr = 0;
+ ptr = NULL;
return tmp;
}
T** accept() {
if (ptr) {
delete [] ptr;
- ptr = 0;
+ ptr = NULL;
}
return &ptr;
}
@@ -198,13 +203,10 @@
explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
~scoped_ptr_malloc() {
- typedef char type_must_be_complete[sizeof(T)];
FF(static_cast<void*>(ptr));
}
void reset(T* p = 0) {
- typedef char type_must_be_complete[sizeof(T)];
-
if (ptr != p) {
FF(static_cast<void*>(ptr));
ptr = p;
@@ -212,12 +214,12 @@
}
T& operator*() const {
- assert(ptr != 0);
+ ASSERT(ptr != 0);
return *ptr;
}
T* operator->() const {
- assert(ptr != 0);
+ ASSERT(ptr != 0);
return ptr;
}
@@ -253,7 +255,4 @@
} // namespace talk_base
-// TODO: get rid of this global using
-using talk_base::scoped_ptr;
-
#endif // #ifndef TALK_BASE_SCOPED_PTR_H__
diff --git a/talk/base/sec_buffer.h b/talk/base/sec_buffer.h
old mode 100755
new mode 100644
diff --git a/talk/base/signalthread.cc b/talk/base/signalthread.cc
old mode 100755
new mode 100644
index 919d1c3..d6a86c0
--- a/talk/base/signalthread.cc
+++ b/talk/base/signalthread.cc
@@ -1,30 +1,70 @@
-#include "talk/base/common.h"
+/*
+ * libjingle
+ * Copyright 2004--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include "talk/base/signalthread.h"
-using namespace talk_base;
+#include "talk/base/common.h"
+
+namespace talk_base {
///////////////////////////////////////////////////////////////////////////////
// SignalThread
///////////////////////////////////////////////////////////////////////////////
-SignalThread::SignalThread()
-: main_(Thread::Current()), state_(kInit)
-{
+SignalThread::SignalThread() : main_(Thread::Current()), state_(kInit) {
+ main_->SignalQueueDestroyed.connect(this,
+ &SignalThread::OnMainThreadDestroyed);
+ refcount_ = 1;
worker_.parent_ = this;
+ worker_.SetName("SignalThread", this);
}
SignalThread::~SignalThread() {
+ ASSERT(refcount_ == 0);
}
-void SignalThread::SetPriority(ThreadPriority priority) {
+bool SignalThread::SetName(const std::string& name, const void* obj) {
+ EnterExit ee(this);
ASSERT(main_->IsCurrent());
ASSERT(kInit == state_);
- worker_.SetPriority(priority);
+ return worker_.SetName(name, obj);
+}
+
+bool SignalThread::SetPriority(ThreadPriority priority) {
+ EnterExit ee(this);
+ ASSERT(main_->IsCurrent());
+ ASSERT(kInit == state_);
+ return worker_.SetPriority(priority);
}
void SignalThread::Start() {
+ EnterExit ee(this);
ASSERT(main_->IsCurrent());
- if (kInit == state_) {
+ if (kInit == state_ || kComplete == state_) {
state_ = kRunning;
OnWorkStart();
worker_.Start();
@@ -33,28 +73,34 @@
}
}
-void SignalThread::Destroy() {
+void SignalThread::Destroy(bool wait) {
+ EnterExit ee(this);
ASSERT(main_->IsCurrent());
if ((kInit == state_) || (kComplete == state_)) {
- delete this;
- } else if (kRunning == state_) {
+ refcount_--;
+ } else if (kRunning == state_ || kReleasing == state_) {
state_ = kStopping;
- // A couple tricky issues here:
- // 1) Thread::Stop() calls Join(), which we don't want... we just want
- // to stop the MessageQueue, which causes ContinueWork() to return false.
- // 2) OnWorkStop() must follow Stop(), so that when the thread wakes up
- // due to OWS(), ContinueWork() will return false.
- worker_.MessageQueue::Stop();
+ // OnWorkStop() must follow Quit(), so that when the thread wakes up due to
+ // OWS(), ContinueWork() will return false.
+ worker_.Quit();
OnWorkStop();
+ if (wait) {
+ // Release the thread's lock so that it can return from ::Run.
+ cs_.Leave();
+ worker_.Stop();
+ cs_.Enter();
+ refcount_--;
+ }
} else {
ASSERT(false);
}
}
void SignalThread::Release() {
+ EnterExit ee(this);
ASSERT(main_->IsCurrent());
if (kComplete == state_) {
- delete this;
+ refcount_--;
} else if (kRunning == state_) {
state_ = kReleasing;
} else {
@@ -64,11 +110,13 @@
}
bool SignalThread::ContinueWork() {
+ EnterExit ee(this);
ASSERT(worker_.IsCurrent());
return worker_.ProcessMessages(0);
}
void SignalThread::OnMessage(Message *msg) {
+ EnterExit ee(this);
if (ST_MSG_WORKER_DONE == msg->message_id) {
ASSERT(main_->IsCurrent());
OnWorkDone();
@@ -79,15 +127,38 @@
do_delete = true;
}
if (kStopping != state_) {
+ // Before signaling that the work is done, make sure that the worker
+ // thread actually is done. We got here because DoWork() finished and
+ // Run() posted the ST_MSG_WORKER_DONE message. This means the worker
+ // thread is about to go away anyway, but sometimes it doesn't actually
+ // finish before SignalWorkDone is processed, and for a reusable
+ // SignalThread this makes an assert in thread.cc fire.
+ //
+ // Calling Stop() on the worker ensures that the OS thread that underlies
+ // the worker will finish, and will be set to NULL, enabling us to call
+ // Start() again.
+ worker_.Stop();
SignalWorkDone(this);
}
if (do_delete) {
- delete this;
+ refcount_--;
}
}
}
void SignalThread::Run() {
DoWork();
- main_->Post(this, ST_MSG_WORKER_DONE);
+ {
+ EnterExit ee(this);
+ if (main_) {
+ main_->Post(this, ST_MSG_WORKER_DONE);
+ }
+ }
}
+
+void SignalThread::OnMainThreadDestroyed() {
+ EnterExit ee(this);
+ main_ = NULL;
+}
+
+} // namespace talk_base
diff --git a/talk/base/signalthread.h b/talk/base/signalthread.h
old mode 100755
new mode 100644
index 9e6bd05..99a6e69
--- a/talk/base/signalthread.h
+++ b/talk/base/signalthread.h
@@ -1,5 +1,34 @@
-#ifndef _SIGNALTHREAD_H_
-#define _SIGNALTHREAD_H_
+/*
+ * libjingle
+ * Copyright 2004--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_SIGNALTHREAD_H_
+#define TALK_BASE_SIGNALTHREAD_H_
+
+#include <string>
#include "talk/base/thread.h"
#include "talk/base/sigslot.h"
@@ -13,18 +42,25 @@
// Cancellation: Call Release(true), to abort the worker thread.
// Fire-and-forget: Call Release(false), which allows the thread to run to
// completion, and then self-destruct without further notification.
+// Periodic tasks: Wait for SignalWorkDone, then eventually call Start()
+// again to repeat the task. When the instance isn't needed anymore,
+// call Release. DoWork, OnWorkStart and OnWorkStop are called again,
+// on a new thread.
// The subclass should override DoWork() to perform the background task. By
// periodically calling ContinueWork(), it can check for cancellation.
// OnWorkStart and OnWorkDone can be overridden to do pre- or post-work
// tasks in the context of the main thread.
///////////////////////////////////////////////////////////////////////////////
-class SignalThread : protected MessageHandler {
-public:
+class SignalThread : public sigslot::has_slots<>, protected MessageHandler {
+ public:
SignalThread();
+ // Context: Main Thread. Call before Start to change the worker's name.
+ bool SetName(const std::string& name, const void* obj);
+
// Context: Main Thread. Call before Start to change the worker's priority.
- void SetPriority(ThreadPriority priority);
+ bool SetPriority(ThreadPriority priority);
// Context: Main Thread. Call to begin the worker thread.
void Start();
@@ -32,8 +68,9 @@
// Context: Main Thread. If the worker thread is not running, deletes the
// object immediately. Otherwise, asks the worker thread to abort processing,
// and schedules the object to be deleted once the worker exits.
- // SignalWorkDone will not be signalled.
- void Destroy();
+ // SignalWorkDone will not be signalled. If wait is true, does not return
+ // until the thread is deleted.
+ void Destroy(bool wait);
// Context: Main Thread. If the worker thread is complete, deletes the
// object immediately. Otherwise, schedules the object to be deleted once
@@ -45,12 +82,14 @@
enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE };
-protected:
+ protected:
virtual ~SignalThread();
+ Thread* worker() { return &worker_; }
+
// Context: Main Thread. Subclass should override to do pre-work setup.
virtual void OnWorkStart() { }
-
+
// Context: Worker Thread. Subclass should override to do work.
virtual void DoWork() = 0;
@@ -64,28 +103,56 @@
// Context: Main Thread. Subclass should override to do post-work cleanup.
virtual void OnWorkDone() { }
-
+
// Context: Any Thread. If subclass overrides, be sure to call the base
// implementation. Do not use (message_id < ST_MSG_FIRST_AVAILABLE)
virtual void OnMessage(Message *msg);
-private:
+ private:
+ enum State {
+ kInit, // Initialized, but not started
+ kRunning, // Started and doing work
+ kReleasing, // Same as running, but to be deleted when work is done
+ kComplete, // Work is done
+ kStopping, // Work is being interrupted
+ };
+
friend class Worker;
class Worker : public Thread {
- public:
+ public:
SignalThread* parent_;
virtual void Run() { parent_->Run(); }
};
+ friend class EnterExit;
+ class EnterExit {
+ public:
+ explicit EnterExit(SignalThread* t) : t_(t) {
+ t_->cs_.Enter();
+ t_->refcount_ += 1;
+ }
+ ~EnterExit() {
+ bool d = (0 == (--(t_->refcount_)));
+ t_->cs_.Leave();
+ if (d)
+ delete t_;
+ }
+ private:
+ SignalThread* t_;
+ };
+
void Run();
+ void OnMainThreadDestroyed();
Thread* main_;
Worker worker_;
- enum State { kInit, kRunning, kComplete, kStopping, kReleasing } state_;
+ CriticalSection cs_;
+ State state_;
+ int refcount_;
};
///////////////////////////////////////////////////////////////////////////////
} // namespace talk_base
-#endif // _SIGNALTHREAD_H_
+#endif // TALK_BASE_SIGNALTHREAD_H_
diff --git a/talk/base/sigslot.h b/talk/base/sigslot.h
old mode 100755
new mode 100644
index 539db8a..e9b85c7
--- a/talk/base/sigslot.h
+++ b/talk/base/sigslot.h
@@ -304,6 +304,7 @@
class _connection_base0
{
public:
+ virtual ~_connection_base0() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit() = 0;
virtual _connection_base0* clone() = 0;
@@ -314,6 +315,7 @@
class _connection_base1
{
public:
+ virtual ~_connection_base1() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type) = 0;
virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;
@@ -324,6 +326,7 @@
class _connection_base2
{
public:
+ virtual ~_connection_base2() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type, arg2_type) = 0;
virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;
@@ -334,6 +337,7 @@
class _connection_base3
{
public:
+ virtual ~_connection_base3() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type, arg2_type, arg3_type) = 0;
virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone() = 0;
@@ -344,6 +348,7 @@
class _connection_base4
{
public:
+ virtual ~_connection_base4() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0;
virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone() = 0;
@@ -355,6 +360,7 @@
class _connection_base5
{
public:
+ virtual ~_connection_base5() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type,
arg5_type) = 0;
@@ -369,6 +375,7 @@
class _connection_base6
{
public:
+ virtual ~_connection_base6() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
arg6_type) = 0;
@@ -383,6 +390,7 @@
class _connection_base7
{
public:
+ virtual ~_connection_base7() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
arg6_type, arg7_type) = 0;
@@ -397,6 +405,7 @@
class _connection_base8
{
public:
+ virtual ~_connection_base8() {}
virtual has_slots<mt_policy>* getdest() const = 0;
virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
arg6_type, arg7_type, arg8_type) = 0;
@@ -510,6 +519,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -578,8 +595,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -656,6 +673,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -724,8 +749,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -787,6 +812,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -855,8 +888,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -917,6 +950,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -985,8 +1026,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -1047,6 +1088,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -1115,8 +1164,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -1179,6 +1228,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -1247,8 +1304,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -1311,6 +1368,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -1379,8 +1444,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -1443,6 +1508,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -1511,8 +1584,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -1576,6 +1649,14 @@
disconnect_all();
}
+ bool is_empty()
+ {
+ lock_block<mt_policy> lock(this);
+ typename connections_list::const_iterator it = m_connected_slots.begin();
+ typename connections_list::const_iterator itEnd = m_connected_slots.end();
+ return it == itEnd;
+ }
+
void disconnect_all()
{
lock_block<mt_policy> lock(this);
@@ -1644,8 +1725,8 @@
if((*it)->getdest() == pslot)
{
+ delete *it;
m_connected_slots.erase(it);
- // delete *it;
}
it = itNext;
@@ -1673,6 +1754,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection0()
+ {
+ }
+
virtual _connection_base0<mt_policy>* clone()
{
return new _connection0<dest_type, mt_policy>(*this);
@@ -1714,6 +1799,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection1()
+ {
+ }
+
virtual _connection_base1<arg1_type, mt_policy>* clone()
{
return new _connection1<dest_type, arg1_type, mt_policy>(*this);
@@ -1756,6 +1845,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection2()
+ {
+ }
+
virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()
{
return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);
@@ -1798,6 +1891,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection3()
+ {
+ }
+
virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone()
{
return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>(*this);
@@ -1842,6 +1939,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection4()
+ {
+ }
+
virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone()
{
return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(*this);
@@ -1888,6 +1989,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection5()
+ {
+ }
+
virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
arg5_type, mt_policy>* clone()
{
@@ -1938,6 +2043,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection6()
+ {
+ }
+
virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
arg5_type, arg6_type, mt_policy>* clone()
{
@@ -1988,6 +2097,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection7()
+ {
+ }
+
virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
arg5_type, arg6_type, arg7_type, mt_policy>* clone()
{
@@ -2040,6 +2153,10 @@
m_pmemfun = pmemfun;
}
+ virtual ~_connection8()
+ {
+ }
+
virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone()
{
diff --git a/talk/base/sigslotrepeater.h b/talk/base/sigslotrepeater.h
new file mode 100644
index 0000000..3bcdc95
--- /dev/null
+++ b/talk/base/sigslotrepeater.h
@@ -0,0 +1,107 @@
+/*
+ * libjingle
+ * Copyright 2006, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_SIGSLOTREPEATER_H__
+#define TALK_BASE_SIGSLOTREPEATER_H__
+
+// repeaters are both signals and slots, which are designed as intermediate
+// pass-throughs for signals and slots which don't know about each other (for
+// modularity or encapsulation). This eliminates the need to declare a signal
+// handler whose sole purpose is to fire another signal. The repeater connects
+// to the originating signal using the 'repeat' method. When the repeated
+// signal fires, the repeater will also fire.
+
+#include "talk/base/sigslot.h"
+
+namespace sigslot {
+
+ template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class repeater0 : public signal0<mt_policy>,
+ public has_slots<mt_policy>
+ {
+ public:
+ typedef signal0<mt_policy> base_type;
+ typedef repeater0<mt_policy> this_type;
+
+ repeater0() { }
+ repeater0(const this_type& s) : base_type(s) { }
+
+ void reemit() { signal0<mt_policy>::emit(); }
+ void repeat(base_type &s) { s.connect(this, &this_type::reemit); }
+ };
+
+ template<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class repeater1 : public signal1<arg1_type, mt_policy>,
+ public has_slots<mt_policy>
+ {
+ public:
+ typedef signal1<arg1_type, mt_policy> base_type;
+ typedef repeater1<arg1_type, mt_policy> this_type;
+
+ repeater1() { }
+ repeater1(const this_type& s) : base_type(s) { }
+
+ void reemit(arg1_type a1) { signal1<arg1_type, mt_policy>::emit(a1); }
+ void repeat(base_type& s) { s.connect(this, &this_type::reemit); }
+ };
+
+ template<class arg1_type, class arg2_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class repeater2 : public signal2<arg1_type, arg2_type, mt_policy>,
+ public has_slots<mt_policy>
+ {
+ public:
+ typedef signal2<arg1_type, arg2_type, mt_policy> base_type;
+ typedef repeater2<arg1_type, arg2_type, mt_policy> this_type;
+
+ repeater2() { }
+ repeater2(const this_type& s) : base_type(s) { }
+
+ void reemit(arg1_type a1, arg2_type a2) { signal2<arg1_type, arg2_type, mt_policy>::emit(a1,a2); }
+ void repeat(base_type& s) { s.connect(this, &this_type::reemit); }
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type,
+ class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class repeater3 : public signal3<arg1_type, arg2_type, arg3_type, mt_policy>,
+ public has_slots<mt_policy>
+ {
+ public:
+ typedef signal3<arg1_type, arg2_type, arg3_type, mt_policy> base_type;
+ typedef repeater3<arg1_type, arg2_type, arg3_type, mt_policy> this_type;
+
+ repeater3() { }
+ repeater3(const this_type& s) : base_type(s) { }
+
+ void reemit(arg1_type a1, arg2_type a2, arg3_type a3) {
+ signal3<arg1_type, arg2_type, arg3_type, mt_policy>::emit(a1,a2,a3);
+ }
+ void repeat(base_type& s) { s.connect(this, &this_type::reemit); }
+ };
+
+} // namespace sigslot
+
+#endif // TALK_BASE_SIGSLOTREPEATER_H__
diff --git a/talk/base/socket.h b/talk/base/socket.h
old mode 100755
new mode 100644
index 0a30c4b..3094918
--- a/talk/base/socket.h
+++ b/talk/base/socket.h
@@ -75,6 +75,7 @@
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
+#undef ETIMEDOUT // remove pthreads.h's definition
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ELOOP WSAELOOP
@@ -144,8 +145,12 @@
virtual int EstimateMTU(uint16* mtu) = 0;
enum Option {
- OPT_DONTFRAGMENT
+ OPT_DONTFRAGMENT,
+ OPT_RCVBUF, // receive buffer size
+ OPT_SNDBUF, // send buffer size
+ OPT_NODELAY // whether Nagle algorithm is enabled
};
+ virtual int GetOption(Option opt, int* value) = 0;
virtual int SetOption(Option opt, int value) = 0;
protected:
diff --git a/talk/base/socketadapters.cc b/talk/base/socketadapters.cc
old mode 100755
new mode 100644
index fcbc20b..427ebdc
--- a/talk/base/socketadapters.cc
+++ b/talk/base/socketadapters.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -33,15 +33,14 @@
#include <errno.h>
#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
-#define _WINSOCKAPI_
-#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
#endif
-#include "talk/base/basicdefs.h"
#include "talk/base/bytebuffer.h"
#include "talk/base/common.h"
#include "talk/base/httpcommon.h"
@@ -52,12 +51,13 @@
#ifdef WIN32
#include "talk/base/sec_buffer.h"
-#endif // WIN32
+#endif // WIN32
namespace talk_base {
-BufferedReadAdapter::BufferedReadAdapter(AsyncSocket* socket, size_t buffer_size)
- : AsyncSocketAdapter(socket), buffer_size_(buffer_size), data_len_(0), buffering_(false) {
+BufferedReadAdapter::BufferedReadAdapter(AsyncSocket* socket, size_t size)
+ : AsyncSocketAdapter(socket), buffer_size_(size),
+ data_len_(0), buffering_(false) {
buffer_ = new char[buffer_size_];
}
@@ -123,65 +123,91 @@
int len = socket_->Recv(buffer_ + data_len_, buffer_size_ - data_len_);
if (len < 0) {
// TODO: Do something better like forwarding the error to the user.
- LOG(INFO) << "Recv: " << errno << " " << std::strerror(errno);
+ LOG_ERR(INFO) << "Recv";
return;
}
data_len_ += len;
- ProcessInput(buffer_, data_len_);
+ ProcessInput(buffer_, &data_len_);
}
///////////////////////////////////////////////////////////////////////////////
-const uint8 SSL_SERVER_HELLO[] = {
- 22,3,1,0,74,2,0,0,70,3,1,66,133,69,167,39,169,93,160,
- 179,197,231,83,218,72,43,63,198,90,202,137,193,88,82,
- 161,120,60,91,23,70,0,133,63,32,14,211,6,114,91,91,
- 27,95,21,172,19,249,136,83,157,155,232,61,123,12,48,
- 50,110,56,77,162,117,87,65,108,52,92,0,4,0
+// This is a SSL v2 CLIENT_HELLO message.
+// TODO: Should this have a session id? The response doesn't have a
+// certificate, so the hello should have a session id.
+static const uint8 kSslClientHello[] = {
+ 0x80, 0x46, // msg len
+ 0x01, // CLIENT_HELLO
+ 0x03, 0x01, // SSL 3.1
+ 0x00, 0x2d, // ciphersuite len
+ 0x00, 0x00, // session id len
+ 0x00, 0x10, // challenge len
+ 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x07, 0x00, 0xc0, // ciphersuites
+ 0x06, 0x00, 0x40, 0x02, 0x00, 0x80, 0x04, 0x00, 0x80, //
+ 0x00, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, //
+ 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, //
+ 0x00, 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, //
+ 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc, // challenge
+ 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea //
};
-const char SSL_CLIENT_HELLO[] = {
- -128,70,1,3,1,0,45,0,0,0,16,1,0,-128,3,0,-128,7,0,-64,6,0,64,2,0,
- -128,4,0,-128,0,0,4,0,-2,-1,0,0,10,0,-2,-2,0,0,9,0,0,100,0,0,98,0,
- 0,3,0,0,6,31,23,12,-90,47,0,120,-4,70,85,46,-79,-125,57,-15,-22
+// This is a TLSv1 SERVER_HELLO message.
+static const uint8 kSslServerHello[] = {
+ 0x16, // handshake message
+ 0x03, 0x01, // SSL 3.1
+ 0x00, 0x4a, // message len
+ 0x02, // SERVER_HELLO
+ 0x00, 0x00, 0x46, // handshake len
+ 0x03, 0x01, // SSL 3.1
+ 0x42, 0x85, 0x45, 0xa7, 0x27, 0xa9, 0x5d, 0xa0, // server random
+ 0xb3, 0xc5, 0xe7, 0x53, 0xda, 0x48, 0x2b, 0x3f, //
+ 0xc6, 0x5a, 0xca, 0x89, 0xc1, 0x58, 0x52, 0xa1, //
+ 0x78, 0x3c, 0x5b, 0x17, 0x46, 0x00, 0x85, 0x3f, //
+ 0x20, // session id len
+ 0x0e, 0xd3, 0x06, 0x72, 0x5b, 0x5b, 0x1b, 0x5f, // session id
+ 0x15, 0xac, 0x13, 0xf9, 0x88, 0x53, 0x9d, 0x9b, //
+ 0xe8, 0x3d, 0x7b, 0x0c, 0x30, 0x32, 0x6e, 0x38, //
+ 0x4d, 0xa2, 0x75, 0x57, 0x41, 0x6c, 0x34, 0x5c, //
+ 0x00, 0x04, // RSA/RC4-128/MD5
+ 0x00 // null compression
};
-AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket) : BufferedReadAdapter(socket, 1024) {
+AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket)
+ : BufferedReadAdapter(socket, 1024) {
}
int AsyncSSLSocket::Connect(const SocketAddress& addr) {
- // Begin buffering before we connect, so that there isn't a race condition between
- // potential senders and receiving the OnConnectEvent signal
+ // Begin buffering before we connect, so that there isn't a race condition
+ // between potential senders and receiving the OnConnectEvent signal
BufferInput(true);
return BufferedReadAdapter::Connect(addr);
}
void AsyncSSLSocket::OnConnectEvent(AsyncSocket * socket) {
ASSERT(socket == socket_);
-
// TODO: we could buffer output too...
- int res = DirectSend(SSL_CLIENT_HELLO, sizeof(SSL_CLIENT_HELLO));
- ASSERT(res == sizeof(SSL_CLIENT_HELLO));
+ VERIFY(sizeof(kSslClientHello) ==
+ DirectSend(kSslClientHello, sizeof(kSslClientHello)));
}
-void AsyncSSLSocket::ProcessInput(char * data, size_t& len) {
- if (len < sizeof(SSL_SERVER_HELLO))
+void AsyncSSLSocket::ProcessInput(char* data, size_t* len) {
+ if (*len < sizeof(kSslServerHello))
return;
- if (memcmp(SSL_SERVER_HELLO, data, sizeof(SSL_SERVER_HELLO)) != 0) {
+ if (memcmp(kSslServerHello, data, sizeof(kSslServerHello)) != 0) {
Close();
- SignalCloseEvent(this, 0); // TODO: error code?
+ SignalCloseEvent(this, 0); // TODO: error code?
return;
}
- len -= sizeof(SSL_SERVER_HELLO);
- if (len > 0) {
- memmove(data, data + sizeof(SSL_SERVER_HELLO), len);
+ *len -= sizeof(kSslServerHello);
+ if (*len > 0) {
+ memmove(data, data + sizeof(kSslServerHello), *len);
}
- bool remainder = (len > 0);
+ bool remainder = (*len > 0);
BufferInput(false);
SignalConnectEvent(this);
@@ -190,6 +216,35 @@
SignalReadEvent(this);
}
+AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket)
+ : BufferedReadAdapter(socket, 1024) {
+ BufferInput(true);
+}
+
+void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
+ // We only accept client hello messages.
+ if (*len < sizeof(kSslClientHello)) {
+ return;
+ }
+
+ if (memcmp(kSslClientHello, data, sizeof(kSslClientHello)) != 0) {
+ Close();
+ SignalCloseEvent(this, 0);
+ return;
+ }
+
+ *len -= sizeof(kSslClientHello);
+
+ // Clients should not send more data until the handshake is completed.
+ ASSERT(*len == 0);
+
+ // Send a server hello back to the client.
+ DirectSend(kSslServerHello, sizeof(kSslServerHello));
+
+ // Handshake completed for us, redirect input to our parent.
+ BufferInput(false);
+}
+
///////////////////////////////////////////////////////////////////////////////
AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket,
@@ -197,8 +252,9 @@
const SocketAddress& proxy,
const std::string& username,
const CryptString& password)
- : BufferedReadAdapter(socket, 1024), proxy_(proxy), agent_(user_agent),
- user_(username), pass_(password), state_(PS_ERROR), context_(0) {
+ : BufferedReadAdapter(socket, 1024), proxy_(proxy), agent_(user_agent),
+ user_(username), pass_(password), force_connect_(false), state_(PS_ERROR),
+ context_(0) {
}
AsyncHttpsProxySocket::~AsyncHttpsProxySocket() {
@@ -206,13 +262,17 @@
}
int AsyncHttpsProxySocket::Connect(const SocketAddress& addr) {
+ int ret;
LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::Connect("
<< proxy_.ToString() << ")";
dest_ = addr;
- if (dest_.port() != 80) {
+ state_ = PS_INIT;
+ if (ShouldIssueConnect()) {
BufferInput(true);
}
- return BufferedReadAdapter::Connect(proxy_);
+ ret = BufferedReadAdapter::Connect(proxy_);
+ // TODO: Set state_ appropriately if Connect fails.
+ return ret;
}
SocketAddress AsyncHttpsProxySocket::GetRemoteAddress() const {
@@ -222,16 +282,25 @@
int AsyncHttpsProxySocket::Close() {
headers_.clear();
state_ = PS_ERROR;
+ dest_.Clear();
delete context_;
- context_ = 0;
+ context_ = NULL;
return BufferedReadAdapter::Close();
}
+Socket::ConnState AsyncHttpsProxySocket::GetState() const {
+ if (state_ < PS_TUNNEL) {
+ return CS_CONNECTING;
+ } else if (state_ == PS_TUNNEL) {
+ return CS_CONNECTED;
+ } else {
+ return CS_CLOSED;
+ }
+}
+
void AsyncHttpsProxySocket::OnConnectEvent(AsyncSocket * socket) {
LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnConnectEvent";
- // TODO: Decide whether tunneling or not should be explicitly set,
- // or indicated by destination port (as below)
- if (dest_.port() == 80) {
+ if (!ShouldIssueConnect()) {
state_ = PS_TUNNEL;
BufferedReadAdapter::OnConnectEvent(socket);
return;
@@ -249,11 +318,11 @@
}
}
-void AsyncHttpsProxySocket::ProcessInput(char * data, size_t& len) {
+void AsyncHttpsProxySocket::ProcessInput(char* data, size_t* len) {
size_t start = 0;
- for (size_t pos = start; (state_ < PS_TUNNEL) && (pos < len); ) {
+ for (size_t pos = start; state_ < PS_TUNNEL && pos < *len;) {
if (state_ == PS_SKIP_BODY) {
- size_t consume = _min(len - pos, content_length_);
+ size_t consume = _min(*len - pos, content_length_);
pos += consume;
start = pos;
content_length_ -= consume;
@@ -275,21 +344,27 @@
start = pos;
}
- len -= start;
- if (len > 0) {
- memmove(data, data + start, len);
+ *len -= start;
+ if (*len > 0) {
+ memmove(data, data + start, *len);
}
if (state_ != PS_TUNNEL)
return;
- bool remainder = (len > 0);
+ bool remainder = (*len > 0);
BufferInput(false);
SignalConnectEvent(this);
// FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
if (remainder)
- SignalReadEvent(this); // TODO: signal this??
+ SignalReadEvent(this); // TODO: signal this??
+}
+
+bool AsyncHttpsProxySocket::ShouldIssueConnect() const {
+ // TODO: Think about whether a more sophisticated test
+ // than dest port == 80 is needed.
+ return force_connect_ || (dest_.port() != 80);
}
void AsyncHttpsProxySocket::SendRequest() {
@@ -346,7 +421,7 @@
MessageBoxA(0, msg.c_str(), "Oops!", MB_OK);
#endif
#ifdef POSIX
- //TODO: Raise a signal or something so the UI can be separated.
+ // TODO: Raise a signal so the UI can be separated.
LOG(LS_ERROR) << "Oops!\n\n" << msg;
#endif
}
@@ -355,8 +430,8 @@
return;
}
} else if (state_ == PS_LEADER) {
- uint32 code;
- if (sscanf(data, "HTTP/%*lu.%*lu %lu", &code) != 1) {
+ unsigned int code;
+ if (sscanf(data, "HTTP/%*u.%*u %u", &code) != 1) {
Error(0);
return;
}
@@ -368,7 +443,7 @@
#if defined(HTTP_STATUS_PROXY_AUTH_REQ) && (HTTP_STATUS_PROXY_AUTH_REQ != 407)
#error Wrong code for HTTP_STATUS_PROXY_AUTH_REQ
#endif
- case 407: // HTTP_STATUS_PROXY_AUTH_REQ
+ case 407: // HTTP_STATUS_PROXY_AUTH_REQ
state_ = PS_AUTHENTICATE;
return;
default:
@@ -439,35 +514,57 @@
///////////////////////////////////////////////////////////////////////////////
-AsyncSocksProxySocket::AsyncSocksProxySocket(AsyncSocket* socket, const SocketAddress& proxy,
- const std::string& username, const CryptString& password)
- : BufferedReadAdapter(socket, 1024), proxy_(proxy), user_(username), pass_(password),
- state_(SS_ERROR) {
+AsyncSocksProxySocket::AsyncSocksProxySocket(AsyncSocket* socket,
+ const SocketAddress& proxy,
+ const std::string& username,
+ const CryptString& password)
+ : BufferedReadAdapter(socket, 1024), state_(SS_ERROR), proxy_(proxy),
+ user_(username), pass_(password) {
}
int AsyncSocksProxySocket::Connect(const SocketAddress& addr) {
+ int ret;
dest_ = addr;
+ state_ = SS_INIT;
BufferInput(true);
- return BufferedReadAdapter::Connect(proxy_);
+ ret = BufferedReadAdapter::Connect(proxy_);
+ // TODO: Set state_ appropriately if Connect fails.
+ return ret;
}
SocketAddress AsyncSocksProxySocket::GetRemoteAddress() const {
return dest_;
}
-void AsyncSocksProxySocket::OnConnectEvent(AsyncSocket * socket) {
+int AsyncSocksProxySocket::Close() {
+ state_ = SS_ERROR;
+ dest_.Clear();
+ return BufferedReadAdapter::Close();
+}
+
+Socket::ConnState AsyncSocksProxySocket::GetState() const {
+ if (state_ < SS_TUNNEL) {
+ return CS_CONNECTING;
+ } else if (state_ == SS_TUNNEL) {
+ return CS_CONNECTED;
+ } else {
+ return CS_CLOSED;
+ }
+}
+
+void AsyncSocksProxySocket::OnConnectEvent(AsyncSocket* socket) {
SendHello();
}
-void AsyncSocksProxySocket::ProcessInput(char * data, size_t& len) {
+void AsyncSocksProxySocket::ProcessInput(char* data, size_t* len) {
ASSERT(state_ < SS_TUNNEL);
- ByteBuffer response(data, len);
+ ByteBuffer response(data, *len);
if (state_ == SS_HELLO) {
uint8 ver, method;
- if (!response.ReadUInt8(ver) ||
- !response.ReadUInt8(method))
+ if (!response.ReadUInt8(&ver) ||
+ !response.ReadUInt8(&method))
return;
if (ver != 5) {
@@ -485,8 +582,8 @@
}
} else if (state_ == SS_AUTH) {
uint8 ver, status;
- if (!response.ReadUInt8(ver) ||
- !response.ReadUInt8(status))
+ if (!response.ReadUInt8(&ver) ||
+ !response.ReadUInt8(&status))
return;
if ((ver != 1) || (status != 0)) {
@@ -497,10 +594,10 @@
SendConnect();
} else if (state_ == SS_CONNECT) {
uint8 ver, rep, rsv, atyp;
- if (!response.ReadUInt8(ver) ||
- !response.ReadUInt8(rep) ||
- !response.ReadUInt8(rsv) ||
- !response.ReadUInt8(atyp))
+ if (!response.ReadUInt8(&ver) ||
+ !response.ReadUInt8(&rep) ||
+ !response.ReadUInt8(&rsv) ||
+ !response.ReadUInt8(&atyp))
return;
if ((ver != 5) || (rep != 0)) {
@@ -511,22 +608,22 @@
uint16 port;
if (atyp == 1) {
uint32 addr;
- if (!response.ReadUInt32(addr) ||
- !response.ReadUInt16(port))
+ if (!response.ReadUInt32(&addr) ||
+ !response.ReadUInt16(&port))
return;
LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
} else if (atyp == 3) {
uint8 len;
std::string addr;
- if (!response.ReadUInt8(len) ||
- !response.ReadString(addr, len) ||
- !response.ReadUInt16(port))
+ if (!response.ReadUInt8(&len) ||
+ !response.ReadString(&addr, len) ||
+ !response.ReadUInt16(&port))
return;
LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
} else if (atyp == 4) {
std::string addr;
- if (!response.ReadString(addr, 16) ||
- !response.ReadUInt16(port))
+ if (!response.ReadString(&addr, 16) ||
+ !response.ReadUInt16(&port))
return;
LOG(LS_VERBOSE) << "Bound on <IPV6>:" << port;
} else {
@@ -538,31 +635,31 @@
}
// Consume parsed data
- len = response.Length();
- memcpy(data, response.Data(), len);
+ *len = response.Length();
+ memcpy(data, response.Data(), *len);
if (state_ != SS_TUNNEL)
return;
- bool remainder = (len > 0);
+ bool remainder = (*len > 0);
BufferInput(false);
SignalConnectEvent(this);
// FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
if (remainder)
- SignalReadEvent(this); // TODO: signal this??
+ SignalReadEvent(this); // TODO: signal this??
}
void AsyncSocksProxySocket::SendHello() {
ByteBuffer request;
- request.WriteUInt8(5); // Socks Version
+ request.WriteUInt8(5); // Socks Version
if (user_.empty()) {
- request.WriteUInt8(1); // Authentication Mechanisms
- request.WriteUInt8(0); // No authentication
+ request.WriteUInt8(1); // Authentication Mechanisms
+ request.WriteUInt8(0); // No authentication
} else {
- request.WriteUInt8(2); // Authentication Mechanisms
- request.WriteUInt8(0); // No authentication
- request.WriteUInt8(2); // Username/Password
+ request.WriteUInt8(2); // Authentication Mechanisms
+ request.WriteUInt8(0); // No authentication
+ request.WriteUInt8(2); // Username/Password
}
DirectSend(request.Data(), request.Length());
state_ = SS_HELLO;
@@ -570,14 +667,14 @@
void AsyncSocksProxySocket::SendAuth() {
ByteBuffer request;
- request.WriteUInt8(1); // Negotiation Version
+ request.WriteUInt8(1); // Negotiation Version
request.WriteUInt8(static_cast<uint8>(user_.size()));
- request.WriteString(user_); // Username
+ request.WriteString(user_); // Username
request.WriteUInt8(static_cast<uint8>(pass_.GetLength()));
size_t len = pass_.GetLength() + 1;
char * sensitive = new char[len];
pass_.CopyTo(sensitive, true);
- request.WriteString(sensitive); // Password
+ request.WriteString(sensitive); // Password
memset(sensitive, 0, len);
delete [] sensitive;
DirectSend(request.Data(), request.Length());
@@ -586,19 +683,19 @@
void AsyncSocksProxySocket::SendConnect() {
ByteBuffer request;
- request.WriteUInt8(5); // Socks Version
- request.WriteUInt8(1); // CONNECT
- request.WriteUInt8(0); // Reserved
+ request.WriteUInt8(5); // Socks Version
+ request.WriteUInt8(1); // CONNECT
+ request.WriteUInt8(0); // Reserved
if (dest_.IsUnresolved()) {
std::string hostname = dest_.IPAsString();
- request.WriteUInt8(3); // DOMAINNAME
+ request.WriteUInt8(3); // DOMAINNAME
request.WriteUInt8(static_cast<uint8>(hostname.size()));
- request.WriteString(hostname); // Destination Hostname
+ request.WriteString(hostname); // Destination Hostname
} else {
- request.WriteUInt8(1); // IPV4
- request.WriteUInt32(dest_.ip()); // Destination IP
+ request.WriteUInt8(1); // IPV4
+ request.WriteUInt32(dest_.ip()); // Destination IP
}
- request.WriteUInt16(dest_.port()); // Destination Port
+ request.WriteUInt16(dest_.port()); // Destination Port
DirectSend(request.Data(), request.Length());
state_ = SS_CONNECT;
}
@@ -611,67 +708,203 @@
SignalCloseEvent(this, error);
}
+AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket)
+ : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
+ BufferInput(true);
+}
+
+void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
+ // TODO: See if the whole message has arrived
+ ASSERT(state_ < SS_CONNECT_PENDING);
+
+ ByteBuffer response(data, *len);
+ if (state_ == SS_HELLO) {
+ HandleHello(&response);
+ } else if (state_ == SS_AUTH) {
+ HandleAuth(&response);
+ } else if (state_ == SS_CONNECT) {
+ HandleConnect(&response);
+ }
+
+ // Consume parsed data
+ *len = response.Length();
+ memcpy(data, response.Data(), *len);
+}
+
+void AsyncSocksProxyServerSocket::DirectSend(const ByteBuffer& buf) {
+ BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
+}
+
+void AsyncSocksProxyServerSocket::HandleHello(ByteBuffer* request) {
+ uint8 ver, num_methods;
+ if (!request->ReadUInt8(&ver) ||
+ !request->ReadUInt8(&num_methods)) {
+ Error(0);
+ return;
+ }
+
+ if (ver != 5) {
+ Error(0);
+ return;
+ }
+
+ // Handle either no-auth (0) or user/pass auth (2)
+ uint8 method = 0xFF;
+ if (num_methods > 0 && !request->ReadUInt8(&method)) {
+ Error(0);
+ return;
+ }
+
+ // TODO: Ask the server which method to use.
+ SendHelloReply(method);
+ if (method == 0) {
+ state_ = SS_CONNECT;
+ } else if (method == 2) {
+ state_ = SS_AUTH;
+ } else {
+ state_ = SS_ERROR;
+ }
+}
+
+void AsyncSocksProxyServerSocket::SendHelloReply(int method) {
+ ByteBuffer response;
+ response.WriteUInt8(5); // Socks Version
+ response.WriteUInt8(method); // Auth method
+ DirectSend(response);
+}
+
+void AsyncSocksProxyServerSocket::HandleAuth(ByteBuffer* request) {
+ uint8 ver, user_len, pass_len;
+ std::string user, pass;
+ if (!request->ReadUInt8(&ver) ||
+ !request->ReadUInt8(&user_len) ||
+ !request->ReadString(&user, user_len) ||
+ !request->ReadUInt8(&pass_len) ||
+ !request->ReadString(&pass, pass_len)) {
+ Error(0);
+ return;
+ }
+
+ // TODO: Allow for checking of credentials.
+ SendAuthReply(0);
+ state_ = SS_CONNECT;
+}
+
+void AsyncSocksProxyServerSocket::SendAuthReply(int result) {
+ ByteBuffer response;
+ response.WriteUInt8(1); // Negotiation Version
+ response.WriteUInt8(result);
+ DirectSend(response);
+}
+
+void AsyncSocksProxyServerSocket::HandleConnect(ByteBuffer* request) {
+ uint8 ver, command, reserved, addr_type;
+ uint32 ip;
+ uint16 port;
+ if (!request->ReadUInt8(&ver) ||
+ !request->ReadUInt8(&command) ||
+ !request->ReadUInt8(&reserved) ||
+ !request->ReadUInt8(&addr_type) ||
+ !request->ReadUInt32(&ip) ||
+ !request->ReadUInt16(&port)) {
+ Error(0);
+ return;
+ }
+
+ if (ver != 5 || command != 1 ||
+ reserved != 0 || addr_type != 1) {
+ Error(0);
+ return;
+ }
+
+ SignalConnectRequest(this, SocketAddress(ip, port));
+ state_ = SS_CONNECT_PENDING;
+}
+
+void AsyncSocksProxyServerSocket::SendConnectResult(int result,
+ const SocketAddress& addr) {
+ if (state_ != SS_CONNECT_PENDING)
+ return;
+
+ ByteBuffer response;
+ response.WriteUInt8(5); // Socks version
+ response.WriteUInt8((result != 0)); // 0x01 is generic error
+ response.WriteUInt8(0); // reserved
+ response.WriteUInt8(1); // IPv4 address
+ response.WriteUInt32(addr.ip());
+ response.WriteUInt16(addr.port());
+ DirectSend(response);
+ BufferInput(false);
+ state_ = SS_TUNNEL;
+}
+
+void AsyncSocksProxyServerSocket::Error(int error) {
+ state_ = SS_ERROR;
+ BufferInput(false);
+ Close();
+ SetError(SOCKET_EACCES);
+ SignalCloseEvent(this, error);
+}
+
///////////////////////////////////////////////////////////////////////////////
LoggingSocketAdapter::LoggingSocketAdapter(AsyncSocket* socket,
LoggingSeverity level,
const char * label, bool hex_mode)
-: AsyncSocketAdapter(socket), level_(level), hex_mode_(hex_mode)
-{
+ : AsyncSocketAdapter(socket), level_(level), hex_mode_(hex_mode) {
label_.append("[");
label_.append(label);
label_.append("]");
}
-int
-LoggingSocketAdapter::Send(const void *pv, size_t cb) {
+int LoggingSocketAdapter::Send(const void *pv, size_t cb) {
int res = AsyncSocketAdapter::Send(pv, cb);
if (res > 0)
- LogMultiline(level_, label_.c_str(), false,
- static_cast<const char *>(pv), res, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), false, pv, res, hex_mode_, &lms_);
return res;
}
-int
-LoggingSocketAdapter::SendTo(const void *pv, size_t cb,
+int LoggingSocketAdapter::SendTo(const void *pv, size_t cb,
const SocketAddress& addr) {
int res = AsyncSocketAdapter::SendTo(pv, cb, addr);
if (res > 0)
- LogMultiline(level_, label_.c_str(), false,
- static_cast<const char *>(pv), res, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), false, pv, res, hex_mode_, &lms_);
return res;
}
-int
-LoggingSocketAdapter::Recv(void *pv, size_t cb) {
+int LoggingSocketAdapter::Recv(void *pv, size_t cb) {
int res = AsyncSocketAdapter::Recv(pv, cb);
if (res > 0)
- LogMultiline(level_, label_.c_str(), true,
- static_cast<const char *>(pv), res, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_);
return res;
}
-int
-LoggingSocketAdapter::RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
+int LoggingSocketAdapter::RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
if (res > 0)
- LogMultiline(level_, label_.c_str(), true,
- static_cast<const char *>(pv), res, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_);
return res;
}
-void
-LoggingSocketAdapter::OnConnectEvent(AsyncSocket * socket) {
+int LoggingSocketAdapter::Close() {
+ LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_);
+ LOG_V(level_) << label_ << " Closed locally";
+ return socket_->Close();
+}
+
+void LoggingSocketAdapter::OnConnectEvent(AsyncSocket * socket) {
LOG_V(level_) << label_ << " Connected";
AsyncSocketAdapter::OnConnectEvent(socket);
}
-void
-LoggingSocketAdapter::OnCloseEvent(AsyncSocket * socket, int err) {
+void LoggingSocketAdapter::OnCloseEvent(AsyncSocket * socket, int err) {
+ LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_);
LOG_V(level_) << label_ << " Closed with error: " << err;
AsyncSocketAdapter::OnCloseEvent(socket, err);
}
///////////////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/socketadapters.h b/talk/base/socketadapters.h
old mode 100755
new mode 100644
index 6cd6a8f..320da6f
--- a/talk/base/socketadapters.h
+++ b/talk/base/socketadapters.h
@@ -2,31 +2,31 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_SOCKETADAPTERS_H__
-#define TALK_BASE_SOCKETADAPTERS_H__
+#ifndef TALK_BASE_SOCKETADAPTERS_H_
+#define TALK_BASE_SOCKETADAPTERS_H_
#include <map>
#include <string>
@@ -38,112 +38,201 @@
namespace talk_base {
struct HttpAuthContext;
+class ByteBuffer;
///////////////////////////////////////////////////////////////////////////////
+// Implements a socket adapter that can buffer and process data internally,
+// as in the case of connecting to a proxy, where you must speak the proxy
+// protocol before commencing normal socket behavior.
class BufferedReadAdapter : public AsyncSocketAdapter {
-public:
+ public:
BufferedReadAdapter(AsyncSocket* socket, size_t buffer_size);
virtual ~BufferedReadAdapter();
- virtual int Send(const void *pv, size_t cb);
- virtual int Recv(void *pv, size_t cb);
+ virtual int Send(const void* pv, size_t cb);
+ virtual int Recv(void* pv, size_t cb);
-protected:
- int DirectSend(const void *pv, size_t cb) { return AsyncSocketAdapter::Send(pv, cb); }
+ protected:
+ int DirectSend(const void* pv, size_t cb) {
+ return AsyncSocketAdapter::Send(pv, cb);
+ }
void BufferInput(bool on = true);
- virtual void ProcessInput(char * data, size_t& len) = 0;
+ virtual void ProcessInput(char* data, size_t* len) = 0;
virtual void OnReadEvent(AsyncSocket * socket);
-private:
+ private:
char * buffer_;
size_t buffer_size_, data_len_;
bool buffering_;
+ DISALLOW_EVIL_CONSTRUCTORS(BufferedReadAdapter);
};
///////////////////////////////////////////////////////////////////////////////
+// Interface for implementing proxy server sockets.
+class AsyncProxyServerSocket : public BufferedReadAdapter {
+ public:
+ AsyncProxyServerSocket(AsyncSocket* socket, size_t buffer_size)
+ : BufferedReadAdapter(socket, buffer_size) {}
+ sigslot::signal2<AsyncProxyServerSocket*,
+ const SocketAddress&> SignalConnectRequest;
+ virtual void SendConnectResult(int err, const SocketAddress& addr) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Implements a socket adapter that performs the client side of a
+// fake SSL handshake. Used for "ssltcp" P2P functionality.
class AsyncSSLSocket : public BufferedReadAdapter {
-public:
- AsyncSSLSocket(AsyncSocket* socket);
+ public:
+ explicit AsyncSSLSocket(AsyncSocket* socket);
virtual int Connect(const SocketAddress& addr);
-protected:
- virtual void OnConnectEvent(AsyncSocket * socket);
- virtual void ProcessInput(char * data, size_t& len);
+ protected:
+ virtual void OnConnectEvent(AsyncSocket* socket);
+ virtual void ProcessInput(char* data, size_t* len);
+ DISALLOW_EVIL_CONSTRUCTORS(AsyncSSLSocket);
+};
+
+// Implements a socket adapter that performs the server side of a
+// fake SSL handshake. Used when implementing a relay server that does "ssltcp".
+class AsyncSSLServerSocket : public BufferedReadAdapter {
+ public:
+ explicit AsyncSSLServerSocket(AsyncSocket* socket);
+
+ protected:
+ virtual void ProcessInput(char* data, size_t* len);
+ DISALLOW_EVIL_CONSTRUCTORS(AsyncSSLServerSocket);
};
///////////////////////////////////////////////////////////////////////////////
+// Implements a socket adapter that speaks the HTTP/S proxy protocol.
class AsyncHttpsProxySocket : public BufferedReadAdapter {
-public:
+ public:
AsyncHttpsProxySocket(AsyncSocket* socket, const std::string& user_agent,
const SocketAddress& proxy,
const std::string& username, const CryptString& password);
virtual ~AsyncHttpsProxySocket();
+ // If connect is forced, the adapter will always issue an HTTP CONNECT to the
+ // target address. Otherwise, it will connect only if the destination port
+ // is not port 80.
+ void SetForceConnect(bool force) { force_connect_ = force; }
+
virtual int Connect(const SocketAddress& addr);
virtual SocketAddress GetRemoteAddress() const;
virtual int Close();
+ virtual ConnState GetState() const;
-protected:
- virtual void OnConnectEvent(AsyncSocket * socket);
- virtual void OnCloseEvent(AsyncSocket * socket, int err);
- virtual void ProcessInput(char * data, size_t& len);
+ protected:
+ virtual void OnConnectEvent(AsyncSocket* socket);
+ virtual void OnCloseEvent(AsyncSocket* socket, int err);
+ virtual void ProcessInput(char* data, size_t* len);
+ bool ShouldIssueConnect() const;
void SendRequest();
- void ProcessLine(char * data, size_t len);
+ void ProcessLine(char* data, size_t len);
void EndResponse();
void Error(int error);
-private:
+ private:
SocketAddress proxy_, dest_;
std::string agent_, user_, headers_;
CryptString pass_;
+ bool force_connect_;
size_t content_length_;
int defer_error_;
bool expect_close_;
enum ProxyState {
- PS_LEADER, PS_AUTHENTICATE, PS_SKIP_HEADERS, PS_ERROR_HEADERS,
+ PS_INIT, PS_LEADER, PS_AUTHENTICATE, PS_SKIP_HEADERS, PS_ERROR_HEADERS,
PS_TUNNEL_HEADERS, PS_SKIP_BODY, PS_TUNNEL, PS_WAIT_CLOSE, PS_ERROR
} state_;
HttpAuthContext * context_;
std::string unknown_mechanisms_;
+ DISALLOW_EVIL_CONSTRUCTORS(AsyncHttpsProxySocket);
};
+/* TODO: Implement this.
+class AsyncHttpsProxyServerSocket : public AsyncProxyServerSocket {
+ public:
+ explicit AsyncHttpsProxyServerSocket(AsyncSocket* socket);
+
+ private:
+ virtual void ProcessInput(char * data, size_t& len);
+ void Error(int error);
+ DISALLOW_EVIL_CONSTRUCTORS(AsyncHttpsProxyServerSocket);
+};
+*/
+
///////////////////////////////////////////////////////////////////////////////
+// Implements a socket adapter that speaks the SOCKS proxy protocol.
class AsyncSocksProxySocket : public BufferedReadAdapter {
-public:
+ public:
AsyncSocksProxySocket(AsyncSocket* socket, const SocketAddress& proxy,
const std::string& username, const CryptString& password);
virtual int Connect(const SocketAddress& addr);
virtual SocketAddress GetRemoteAddress() const;
+ virtual int Close();
+ virtual ConnState GetState() const;
-protected:
- virtual void OnConnectEvent(AsyncSocket * socket);
- virtual void ProcessInput(char * data, size_t& len);
+ protected:
+ virtual void OnConnectEvent(AsyncSocket* socket);
+ virtual void ProcessInput(char* data, size_t* len);
void SendHello();
void SendConnect();
void SendAuth();
void Error(int error);
-private:
+ private:
+ enum State {
+ SS_INIT, SS_HELLO, SS_AUTH, SS_CONNECT, SS_TUNNEL, SS_ERROR
+ };
+ State state_;
SocketAddress proxy_, dest_;
std::string user_;
CryptString pass_;
- enum SocksState { SS_HELLO, SS_AUTH, SS_CONNECT, SS_TUNNEL, SS_ERROR } state_;
+ DISALLOW_EVIL_CONSTRUCTORS(AsyncSocksProxySocket);
+};
+
+// Implements a proxy server socket for the SOCKS protocol.
+class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
+ public:
+ explicit AsyncSocksProxyServerSocket(AsyncSocket* socket);
+
+ private:
+ virtual void ProcessInput(char* data, size_t* len);
+ void DirectSend(const ByteBuffer& buf);
+
+ void HandleHello(ByteBuffer* request);
+ void SendHelloReply(int method);
+ void HandleAuth(ByteBuffer* request);
+ void SendAuthReply(int result);
+ void HandleConnect(ByteBuffer* request);
+ virtual void SendConnectResult(int result, const SocketAddress& addr);
+
+ void Error(int error);
+
+ static const int kBufferSize = 1024;
+ enum State {
+ SS_HELLO, SS_AUTH, SS_CONNECT, SS_CONNECT_PENDING, SS_TUNNEL, SS_ERROR
+ };
+ State state_;
+ DISALLOW_EVIL_CONSTRUCTORS(AsyncSocksProxyServerSocket);
};
///////////////////////////////////////////////////////////////////////////////
+// Implements a socket adapter that logs everything that it sends and receives.
class LoggingSocketAdapter : public AsyncSocketAdapter {
-public:
+ public:
LoggingSocketAdapter(AsyncSocket* socket, LoggingSeverity level,
const char * label, bool hex_mode = false);
@@ -151,20 +240,22 @@
virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr);
virtual int Recv(void *pv, size_t cb);
virtual int RecvFrom(void *pv, size_t cb, SocketAddress *paddr);
+ virtual int Close();
-protected:
+ protected:
virtual void OnConnectEvent(AsyncSocket * socket);
virtual void OnCloseEvent(AsyncSocket * socket, int err);
-private:
+ private:
LoggingSeverity level_;
std::string label_;
bool hex_mode_;
LogMultilineState lms_;
+ DISALLOW_EVIL_CONSTRUCTORS(LoggingSocketAdapter);
};
///////////////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_SOCKETADAPTERS_H__
+#endif // TALK_BASE_SOCKETADAPTERS_H_
diff --git a/talk/base/socketaddress.cc b/talk/base/socketaddress.cc
old mode 100755
new mode 100644
index e3a04d1..cbb0805
--- a/talk/base/socketaddress.cc
+++ b/talk/base/socketaddress.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,31 +29,31 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <unistd.h>
#endif
-#include <cstring>
#include <sstream>
#include "talk/base/byteorder.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
+#include "talk/base/nethelpers.h"
#include "talk/base/socketaddress.h"
#ifdef WIN32
-#undef SetPort
-int inet_aton(const char * cp, struct in_addr * inp) {
+// Win32 doesn't provide inet_aton, so we add our own version here.
+// Since inet_addr returns 0xFFFFFFFF on error, if we get this value
+// we need to test the input to see if the address really was 255.255.255.255.
+// This is slightly fragile, but better than doing nothing.
+int inet_aton(const char* cp, struct in_addr* inp) {
inp->s_addr = inet_addr(cp);
- return (inp->s_addr == INADDR_NONE) ? 0 : 1;
+ return (inp->s_addr == INADDR_NONE &&
+ strcmp(cp, "255.255.255.255") != 0) ? 0 : 1;
}
-#endif // WIN32
-
-#ifdef _DEBUG
-#define DISABLE_DNS 0
-#else // !_DEBUG
-#define DISABLE_DNS 0
-#endif // !_DEBUG
+#endif // WIN32
namespace talk_base {
@@ -61,8 +61,8 @@
Clear();
}
-SocketAddress::SocketAddress(const std::string& hostname, int port, bool use_dns) {
- SetIP(hostname, use_dns);
+SocketAddress::SocketAddress(const std::string& hostname, int port) {
+ SetIP(hostname);
SetPort(port);
}
@@ -81,6 +81,14 @@
port_ = 0;
}
+bool SocketAddress::IsNil() const {
+ return hostname_.empty() && (0 == ip_) && (0 == port_);
+}
+
+bool SocketAddress::IsComplete() const {
+ return (0 != ip_) && (0 != port_);
+}
+
SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
hostname_ = addr.hostname_;
ip_ = addr.ip_;
@@ -93,10 +101,9 @@
ip_ = ip;
}
-bool SocketAddress::SetIP(const std::string& hostname, bool use_dns) {
+void SocketAddress::SetIP(const std::string& hostname) {
hostname_ = hostname;
- ip_ = 0;
- return Resolve(true, use_dns);
+ ip_ = StringToIP(hostname);
}
void SocketAddress::SetResolvedIP(uint32 ip) {
@@ -136,43 +143,92 @@
return ost.str();
}
-bool SocketAddress::IsAny() const {
+bool SocketAddress::FromString(const std::string& str) {
+ std::string::size_type pos = str.find(':');
+ if (std::string::npos == pos)
+ return false;
+ SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10));
+ SetIP(str.substr(0, pos));
+ return true;
+}
+
+std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
+ os << addr.IPAsString() << ":" << addr.port();
+ return os;
+}
+
+bool SocketAddress::IsAnyIP() const {
return (ip_ == 0);
}
+bool SocketAddress::IsLoopbackIP() const {
+ if (0 == ip_) {
+ return (0 == stricmp(hostname_.c_str(), "localhost"));
+ } else {
+ return ((ip_ >> 24) == 127);
+ }
+}
+
bool SocketAddress::IsLocalIP() const {
- return (ip_ >> 24) == 127;
+ if (IsLoopbackIP())
+ return true;
+
+ std::vector<uint32> ips;
+ if (0 == ip_) {
+ if (!hostname_.empty()
+ && (0 == stricmp(hostname_.c_str(), GetHostname().c_str()))) {
+ return true;
+ }
+ } else if (GetLocalIPs(ips)) {
+ for (size_t i = 0; i < ips.size(); ++i) {
+ if (ips[i] == ip_) {
+ return true;
+ }
+ }
+ }
+ return false;
}
bool SocketAddress::IsPrivateIP() const {
return ((ip_ >> 24) == 127) ||
((ip_ >> 24) == 10) ||
((ip_ >> 20) == ((172 << 4) | 1)) ||
- ((ip_ >> 16) == ((192 << 8) | 168));
+ ((ip_ >> 16) == ((192 << 8) | 168)) ||
+ ((ip_ >> 16) == ((169 << 8) | 254));
}
-bool SocketAddress::IsUnresolved() const {
+bool SocketAddress::IsUnresolvedIP() const {
return IsAny() && !hostname_.empty();
}
-bool SocketAddress::Resolve(bool force, bool use_dns) {
+bool SocketAddress::ResolveIP(bool force, int* error) {
if (hostname_.empty()) {
// nothing to resolve
} else if (!force && !IsAny()) {
// already resolved
- } else if (uint32 ip = StringToIP(hostname_, use_dns)) {
- ip_ = ip;
} else {
- return false;
+ LOG_F(LS_VERBOSE) << "(" << hostname_ << ")";
+ int errcode = 0;
+ if (hostent* pHost = SafeGetHostByName(hostname_.c_str(), &errcode)) {
+ ip_ = NetworkToHost32(*reinterpret_cast<uint32*>(pHost->h_addr_list[0]));
+ LOG_F(LS_VERBOSE) << "(" << hostname_ << ") resolved to: "
+ << IPToString(ip_);
+ FreeHostEnt(pHost);
+ } else {
+ LOG_F(LS_ERROR) << "(" << hostname_ << ") err: " << errcode;
+ }
+ if (error) {
+ *error = errcode;
+ }
}
- return true;
+ return (ip_ != 0);
}
-bool SocketAddress::operator ==(const SocketAddress& addr) const {
+bool SocketAddress::operator==(const SocketAddress& addr) const {
return EqualIPs(addr) && EqualPorts(addr);
}
-bool SocketAddress::operator <(const SocketAddress& addr) const {
+bool SocketAddress::operator<(const SocketAddress& addr) const {
if (ip_ < addr.ip_)
return true;
else if (addr.ip_ < ip_)
@@ -205,22 +261,25 @@
}
size_t SocketAddress::Size_() const {
- return sizeof(ip_) + sizeof(port_);
+ return sizeof(ip_) + sizeof(port_) + 2;
}
-void SocketAddress::Write_(char* buf, int len) const {
- // TODO: Depending on how this is used, we may want/need to write hostname
- ASSERT((size_t)len >= Size_());
- reinterpret_cast<uint32*>(buf)[0] = ip_;
- buf += sizeof(ip_);
- reinterpret_cast<uint16*>(buf)[0] = port_;
+bool SocketAddress::Write_(char* buf, int len) const {
+ if (len < static_cast<int>(Size_()))
+ return false;
+ buf[0] = 0;
+ buf[1] = AF_INET;
+ SetBE16(buf + 2, port_);
+ SetBE32(buf + 4, ip_);
+ return true;
}
-void SocketAddress::Read_(const char* buf, int len) {
- ASSERT((size_t)len >= Size_());
- ip_ = reinterpret_cast<const uint32*>(buf)[0];
- buf += sizeof(ip_);
- port_ = reinterpret_cast<const uint16*>(buf)[0];
+bool SocketAddress::Read_(const char* buf, int len) {
+ if (len < static_cast<int>(Size_()) || buf[1] != AF_INET)
+ return false;
+ port_ = GetBE16(buf + 2);
+ ip_ = GetBE32(buf + 4);
+ return true;
}
void SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
@@ -234,9 +293,12 @@
}
}
-void SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
+bool SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
+ if (saddr.sin_family != AF_INET)
+ return false;
SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
SetPort(NetworkToHost16(saddr.sin_port));
+ return true;
}
std::string SocketAddress::IPToString(uint32 ip) {
@@ -251,31 +313,17 @@
return ost.str();
}
-uint32 SocketAddress::StringToIP(const std::string& hostname, bool use_dns) {
- uint32 ip = 0;
+bool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) {
in_addr addr;
- if (inet_aton(hostname.c_str(), &addr) != 0) {
- ip = NetworkToHost32(addr.s_addr);
- } else if (use_dns) {
- // Note: this is here so we can spot spurious DNS resolutions for a while
- LOG(INFO) << "=== DNS RESOLUTION (" << hostname << ") ===";
-#if DISABLE_DNS
- LOG(WARNING) << "*** DNS DISABLED ***";
-#if WIN32
- WSASetLastError(WSAHOST_NOT_FOUND);
-#endif // WIN32
-#endif // DISABLE_DNS
- if (hostent * pHost = gethostbyname(hostname.c_str())) {
- ip = NetworkToHost32(*reinterpret_cast<uint32 *>(pHost->h_addr_list[0]));
- } else {
-#if WIN32
- LOG(LS_ERROR) << "gethostbyname error: " << WSAGetLastError();
-#else
- LOG(LS_ERROR) << "gethostbyname error: " << strerror(h_errno);
-#endif
- }
- LOG(INFO) << hostname << " resolved to " << IPToString(ip);
- }
+ if (inet_aton(hostname.c_str(), &addr) == 0)
+ return false;
+ *ip = NetworkToHost32(addr.s_addr);
+ return true;
+}
+
+uint32 SocketAddress::StringToIP(const std::string& hostname) {
+ uint32 ip = 0;
+ StringToIP(hostname, &ip);
return ip;
}
@@ -293,20 +341,18 @@
if (hostname.empty())
return false;
- if (hostent * pHost = gethostbyname(hostname.c_str())) {
- for (size_t i=0; pHost->h_addr_list[i]; ++i) {
+ int errcode;
+ if (hostent* pHost = SafeGetHostByName(hostname.c_str(), &errcode)) {
+ for (size_t i = 0; pHost->h_addr_list[i]; ++i) {
uint32 ip =
NetworkToHost32(*reinterpret_cast<uint32 *>(pHost->h_addr_list[i]));
ips.push_back(ip);
}
+ FreeHostEnt(pHost);
return !ips.empty();
}
-#if WIN32
- LOG(LS_ERROR) << "gethostbyname error: " << WSAGetLastError();
-#else
- LOG(LS_ERROR) << "gethostbyname error: " << strerror(h_errno);
-#endif
+ LOG(LS_ERROR) << "gethostbyname err: " << errcode;
return false;
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/socketaddress.h b/talk/base/socketaddress.h
old mode 100755
new mode 100644
index 7fdc22f..4af80c9
--- a/talk/base/socketaddress.h
+++ b/talk/base/socketaddress.h
@@ -2,46 +2,47 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_SOCKETADDRESS_H__
-#define TALK_BASE_SOCKETADDRESS_H__
+#ifndef TALK_BASE_SOCKETADDRESS_H_
+#define TALK_BASE_SOCKETADDRESS_H_
#include <string>
#include <vector>
+#include <iosfwd>
#include "talk/base/basictypes.h"
-struct sockaddr_in;
-
#undef SetPort
+struct sockaddr_in;
+
namespace talk_base {
// Records an IP address and port, which are 32 and 16 bit integers,
// respectively, both in <b>host byte-order</b>.
class SocketAddress {
-public:
- // Creates a missing / unknown address.
+ public:
+ // Creates a nil address.
SocketAddress();
// Creates the address with the given host and port. If use_dns is true,
@@ -49,7 +50,7 @@
// several seconds if DNS is not available). Alternately, set use_dns to
// false, and then call Resolve() to complete resolution later, or use
// SetResolvedIP to set the IP explictly.
- SocketAddress(const std::string& hostname, int port = 0, bool use_dns = true);
+ SocketAddress(const std::string& hostname, int port);
// Creates the address with the given IP and port.
SocketAddress(uint32 ip, int port);
@@ -57,18 +58,24 @@
// Creates a copy of the given address.
SocketAddress(const SocketAddress& addr);
- // Resets to missing / unknown address.
+ // Resets to the nil address.
void Clear();
+ // Determines if this is a nil address (empty hostname, any IP, null port)
+ bool IsNil() const;
+
+ // Returns true if ip and port are set.
+ bool IsComplete() const;
+
// Replaces our address with the given one.
- SocketAddress& operator =(const SocketAddress& addr);
+ SocketAddress& operator=(const SocketAddress& addr);
// Changes the IP of this address to the given one, and clears the hostname.
void SetIP(uint32 ip);
// Changes the hostname of this address to the given one.
- // Calls Resolve and returns the result.
- bool SetIP(const std::string& hostname, bool use_dns = true);
+ // Does not resolve the address; use Resolve to do so.
+ void SetIP(const std::string& hostname);
// Sets the IP address while retaining the hostname. Useful for bypassing
// DNS for a pre-resolved IP.
@@ -77,50 +84,57 @@
// Changes the port of this address to the given one.
void SetPort(int port);
+ // Returns the hostname
+ const std::string& hostname() const { return hostname_; }
+
// Returns the IP address.
uint32 ip() const;
// Returns the port part of this address.
uint16 port() const;
- // Returns the hostname
- const std::string& hostname() const { return hostname_; };
-
// Returns the IP address in dotted form.
std::string IPAsString() const;
// Returns the port as a string
std::string PortAsString() const;
- // Returns a display version of the IP/port.
+ // Returns hostname:port
std::string ToString() const;
- // Determines whether this represents a missing / any address.
- bool IsAny() const;
+ // Parses hostname:port
+ bool FromString(const std::string& str);
- // Synomym for missing / any.
- bool IsNil() const { return IsAny(); }
+ friend std::ostream& operator<<(std::ostream& os, const SocketAddress& addr);
- // Determines whether the IP address refers to the local host, i.e. within
+ // Determines whether this represents a missing / any IP address. Hostname
+ // and/or port may be set.
+ bool IsAnyIP() const;
+ inline bool IsAny() const { return IsAnyIP(); } // deprecated
+
+ // Determines whether the IP address refers to a loopback address, i.e. within
// the range 127.0.0.0/8.
+ bool IsLoopbackIP() const;
+
+ // Determines wither the IP address refers to any adapter on the local
+ // machine, including the loopback adapter.
bool IsLocalIP() const;
// Determines whether the IP address is in one of the private ranges:
// 127.0.0.0/8 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12.
bool IsPrivateIP() const;
- // Determines whether the hostname has been resolved to an IP
- bool IsUnresolved() const;
+ // Determines whether the hostname has been resolved to an IP.
+ bool IsUnresolvedIP() const;
+ inline bool IsUnresolved() const { return IsUnresolvedIP(); } // deprecated
// Attempt to resolve a hostname to IP address.
- // Returns false if resolution is required but failed.
+ // Returns false if resolution is required but failed, and sets error.
// 'force' will cause re-resolution of hostname.
- //
- bool Resolve(bool force = false, bool use_dns = true);
+ bool ResolveIP(bool force = false, int* error = NULL);
// Determines whether this address is identical to the given one.
bool operator ==(const SocketAddress& addr) const;
-
inline bool operator !=(const SocketAddress& addr) const {
return !this->operator ==(addr);
}
@@ -131,7 +145,7 @@
// Determines whether this address has the same IP as the one given.
bool EqualIPs(const SocketAddress& addr) const;
- // Deteremines whether this address has the same port as the one given.
+ // Determines whether this address has the same port as the one given.
bool EqualPorts(const SocketAddress& addr) const;
// Hashes this address into a small number.
@@ -140,22 +154,25 @@
// Returns the size of this address when written.
size_t Size_() const;
- // Writes this address into the given buffer.
- void Write_(char* buf, int len) const;
+ // Writes this address into the given buffer, according to RFC 3489.
+ bool Write_(char* buf, int len) const;
- // Reads this address from the given buffer.
- void Read_(const char* buf, int len);
+ // Reads this address from the given buffer, according to RFC 3489.
+ bool Read_(const char* buf, int len);
- // Convert to and from sockaddr_in
+ // Write this address to a sockaddr_in.
void ToSockAddr(sockaddr_in* saddr) const;
- void FromSockAddr(const sockaddr_in& saddr);
+
+ // Read this address from a sockaddr_in.
+ bool FromSockAddr(const sockaddr_in& saddr);
// Converts the IP address given in compact form into dotted form.
static std::string IPToString(uint32 ip);
// Converts the IP address given in dotted form into compact form.
- // Without 'use_dns', only dotted names (A.B.C.D) are resolved.
- static uint32 StringToIP(const std::string& str, bool use_dns = true);
+ // Only dotted names (A.B.C.D) are resolved.
+ static bool StringToIP(const std::string& str, uint32* ip);
+ static uint32 StringToIP(const std::string& str); // deprecated
// Get local machine's hostname
static std::string GetHostname();
@@ -163,12 +180,12 @@
// Get a list of the local machine's ip addresses
static bool GetLocalIPs(std::vector<uint32>& ips);
-private:
+ private:
std::string hostname_;
uint32 ip_;
uint16 port_;
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_SOCKETADDRESS_H__
+#endif // TALK_BASE_SOCKETADDRESS_H_
diff --git a/talk/base/socketaddresspair.cc b/talk/base/socketaddresspair.cc
old mode 100755
new mode 100644
diff --git a/talk/base/socketaddresspair.h b/talk/base/socketaddresspair.h
old mode 100755
new mode 100644
diff --git a/talk/base/socketfactory.h b/talk/base/socketfactory.h
old mode 100755
new mode 100644
diff --git a/talk/base/socketpool.cc b/talk/base/socketpool.cc
old mode 100755
new mode 100644
index 614ce89..6e89964
--- a/talk/base/socketpool.cc
+++ b/talk/base/socketpool.cc
@@ -25,13 +25,14 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
+#include <iomanip>
#include "talk/base/asyncsocket.h"
#include "talk/base/logging.h"
#include "talk/base/socketfactory.h"
#include "talk/base/socketpool.h"
#include "talk/base/socketstream.h"
+#include "talk/base/thread.h"
namespace talk_base {
@@ -56,7 +57,7 @@
StreamInterface* StreamCache::RequestConnectedStream(
const SocketAddress& remote, int* err) {
- LOG_F(LS_VERBOSE) << "(" << remote.ToString() << ")";
+ LOG_F(LS_VERBOSE) << "(" << remote << ")";
for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
++it) {
if (remote == it->first) {
@@ -83,7 +84,7 @@
for (ConnectedList::iterator it = active_.begin(); it != active_.end();
++it) {
if (stream == it->second) {
- LOG_F(LS_VERBOSE) << "(" << it->first.ToString() << ")";
+ LOG_F(LS_VERBOSE) << "(" << it->first << ")";
if (stream->GetState() == SS_CLOSED) {
// Return closed streams
LOG_F(LS_VERBOSE) << "Returning closed stream";
@@ -110,7 +111,7 @@
for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
++it) {
if (stream == it->second) {
- LOG_F(LS_VERBOSE) << "(" << it->first.ToString() << ")";
+ LOG_F(LS_VERBOSE) << "(" << it->first << ")";
// We don't cache closed streams, so return it.
it->second->SignalEvent.disconnect(this);
LOG_F(LS_VERBOSE) << "Returning closed stream";
@@ -130,9 +131,6 @@
}
NewSocketPool::~NewSocketPool() {
- for (size_t i = 0; i < used_.size(); ++i) {
- delete used_[i];
- }
}
StreamInterface*
@@ -157,33 +155,28 @@
void
NewSocketPool::ReturnConnectedStream(StreamInterface* stream) {
- used_.push_back(stream);
+ Thread::Current()->Dispose(stream);
}
//////////////////////////////////////////////////////////////////////
// ReuseSocketPool
//////////////////////////////////////////////////////////////////////
-ReuseSocketPool::ReuseSocketPool(SocketFactory* factory, AsyncSocket* socket)
- : factory_(factory), stream_(NULL) {
- stream_ = socket ? new SocketStream(socket) : NULL;
+ReuseSocketPool::ReuseSocketPool(SocketFactory* factory)
+: factory_(factory), stream_(NULL), checked_out_(false) {
}
ReuseSocketPool::~ReuseSocketPool() {
+ ASSERT(!checked_out_);
delete stream_;
}
-void
-ReuseSocketPool::setSocket(AsyncSocket* socket) {
- ASSERT(false); // TODO: need ref-counting to make this work
- delete stream_;
- stream_ = socket ? new SocketStream(socket) : NULL;
-}
-
StreamInterface*
ReuseSocketPool::RequestConnectedStream(const SocketAddress& remote, int* err) {
+ // Only one socket can be used from this "pool" at a time
+ ASSERT(!checked_out_);
if (!stream_) {
- LOG(LS_INFO) << "ReuseSocketPool - Creating new socket";
+ LOG_F(LS_VERBOSE) << "Creating new socket";
AsyncSocket* socket = factory_->CreateAsyncSocket(SOCK_STREAM);
if (!socket) {
ASSERT(false);
@@ -193,22 +186,22 @@
}
stream_ = new SocketStream(socket);
}
- if ((stream_->GetState() == SS_OPEN) &&
- (stream_->GetSocket()->GetRemoteAddress() == remote)) {
- LOG(LS_INFO) << "ReuseSocketPool - Reusing connection to: "
- << remote.ToString();
+ if ((stream_->GetState() == SS_OPEN) && (remote == remote_)) {
+ LOG_F(LS_VERBOSE) << "Reusing connection to: " << remote_;
} else {
+ remote_ = remote;
stream_->Close();
- if ((stream_->GetSocket()->Connect(remote) != 0)
+ if ((stream_->GetSocket()->Connect(remote_) != 0)
&& !stream_->GetSocket()->IsBlocking()) {
if (err)
*err = stream_->GetSocket()->GetError();
return NULL;
} else {
- LOG(LS_INFO) << "ReuseSocketPool - Opening connection to: "
- << remote.ToString();
+ LOG_F(LS_VERBOSE) << "Opening connection to: " << remote_;
}
}
+ stream_->SignalEvent.disconnect(this);
+ checked_out_ = true;
if (err)
*err = 0;
return stream_;
@@ -216,8 +209,21 @@
void
ReuseSocketPool::ReturnConnectedStream(StreamInterface* stream) {
- // Note: this might not be true with the advent of setSocket
ASSERT(stream == stream_);
+ ASSERT(checked_out_);
+ checked_out_ = false;
+ // Until the socket is reused, monitor it to determine if it closes.
+ stream_->SignalEvent.connect(this, &ReuseSocketPool::OnStreamEvent);
+}
+
+void
+ReuseSocketPool::OnStreamEvent(StreamInterface* stream, int events, int err) {
+ LOG_F(LS_VERBOSE) << "Connection closed with error: " << err;
+ ASSERT(stream == stream_);
+ ASSERT(!checked_out_);
+ ASSERT(0 != (events & SE_CLOSE));
+ // Socket has closed. We'll reconnect it the next time it is used.
+ stream_->Close();
}
///////////////////////////////////////////////////////////////////////////////
@@ -241,11 +247,20 @@
StreamInterface* LoggingPoolAdapter::RequestConnectedStream(
const SocketAddress& remote, int* err) {
if (StreamInterface* stream = pool_->RequestConnectedStream(remote, err)) {
+ ASSERT(SS_CLOSED != stream->GetState());
+ std::stringstream ss;
+ ss << label_ << "(0x" << std::setfill('0') << std::hex << std::setw(8)
+ << stream << ")";
+ LOG_V(level_) << ss.str()
+ << ((SS_OPEN == stream->GetState()) ? " Connected"
+ : " Connecting")
+ << " to " << remote;
if (recycle_bin_.empty()) {
- return new LoggingAdapter(stream, level_, label_, binary_mode_);
+ return new LoggingAdapter(stream, level_, ss.str(), binary_mode_);
}
LoggingAdapter* logging = recycle_bin_.front();
recycle_bin_.pop_front();
+ logging->set_label(ss.str());
logging->Attach(stream);
return logging;
}
diff --git a/talk/base/socketpool.h b/talk/base/socketpool.h
old mode 100755
new mode 100644
index edeebaa..3bfd108
--- a/talk/base/socketpool.h
+++ b/talk/base/socketpool.h
@@ -29,15 +29,15 @@
#define TALK_BASE_SOCKETPOOL_H__
#include <deque>
-#include <vector>
+#include <list>
#include "talk/base/logging.h"
#include "talk/base/sigslot.h"
+#include "talk/base/socketaddress.h"
namespace talk_base {
class AsyncSocket;
class LoggingAdapter;
-class SocketAddress;
class SocketFactory;
class SocketStream;
class StreamInterface;
@@ -84,11 +84,10 @@
ConnectedList cached_;
};
-//////////////////////////////////////////////////////////////////////
-// NewSocketPool //
-///////////////////
-// Creates a new PTcpSocket every time
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// NewSocketPool
+// Creates a new stream on every request
+///////////////////////////////////////////////////////////////////////////////
class NewSocketPool : public StreamPool {
public:
@@ -102,31 +101,31 @@
private:
SocketFactory* factory_;
- std::vector<StreamInterface*> used_;
};
-//////////////////////////////////////////////////////////////////////
-// ReuseSocketPool //
-/////////////////////
-// Pass a PTcpSocket chain to the constructor, and if the connection
-// is still open, it will be reused.
-//////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// ReuseSocketPool
+// Maintains a single socket at a time, and will reuse it without closing if
+// the destination address is the same.
+///////////////////////////////////////////////////////////////////////////////
-class ReuseSocketPool : public StreamPool {
+class ReuseSocketPool : public StreamPool, public sigslot::has_slots<> {
public:
- ReuseSocketPool(SocketFactory* factory, AsyncSocket* socket = 0);
+ ReuseSocketPool(SocketFactory* factory);
virtual ~ReuseSocketPool();
- void setSocket(AsyncSocket* socket);
-
// StreamPool Interface
virtual StreamInterface* RequestConnectedStream(const SocketAddress& remote,
int* err);
virtual void ReturnConnectedStream(StreamInterface* stream);
private:
+ void OnStreamEvent(StreamInterface* stream, int events, int err);
+
SocketFactory* factory_;
SocketStream* stream_;
+ SocketAddress remote_;
+ bool checked_out_; // Whether the stream is currently checked out
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/talk/base/socketserver.h b/talk/base/socketserver.h
old mode 100755
new mode 100644
index e06dd6b..151ce61
--- a/talk/base/socketserver.h
+++ b/talk/base/socketserver.h
@@ -2,37 +2,37 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_SOCKETSERVER_H__
-#define TALK_BASE_SOCKETSERVER_H__
+#ifndef TALK_BASE_SOCKETSERVER_H_
+#define TALK_BASE_SOCKETSERVER_H_
#include "talk/base/socketfactory.h"
namespace talk_base {
-const int kForever = -1;
+class MessageQueue;
// Provides the ability to wait for activity on a set of sockets. The Thread
// class provides a nice wrapper on a socket server.
@@ -40,7 +40,11 @@
// The server is also a socket factory. The sockets it creates will be
// notified of asynchronous I/O from this server's Wait method.
class SocketServer : public SocketFactory {
-public:
+ public:
+ // When the socket server is installed into a Thread, this function is
+ // called to allow the socket server to use the thread's message queue for
+ // any messaging that it might need to perform.
+ virtual void SetMessageQueue(MessageQueue* queue) {}
// Sleeps until:
// 1) cms milliseconds have elapsed (unless cms == kForever)
@@ -52,6 +56,6 @@
virtual void WakeUp() = 0;
};
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_SOCKETSERVER_H__
+#endif // TALK_BASE_SOCKETSERVER_H_
diff --git a/talk/base/socketstream.cc b/talk/base/socketstream.cc
new file mode 100644
index 0000000..3dc5a95
--- /dev/null
+++ b/talk/base/socketstream.cc
@@ -0,0 +1,138 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/socketstream.h"
+
+namespace talk_base {
+
+SocketStream::SocketStream(AsyncSocket* socket) : socket_(NULL) {
+ Attach(socket);
+}
+
+SocketStream::~SocketStream() {
+ delete socket_;
+}
+
+void SocketStream::Attach(AsyncSocket* socket) {
+ if (socket_)
+ delete socket_;
+ socket_ = socket;
+ if (socket_) {
+ socket_->SignalConnectEvent.connect(this, &SocketStream::OnConnectEvent);
+ socket_->SignalReadEvent.connect(this, &SocketStream::OnReadEvent);
+ socket_->SignalWriteEvent.connect(this, &SocketStream::OnWriteEvent);
+ socket_->SignalCloseEvent.connect(this, &SocketStream::OnCloseEvent);
+ }
+}
+
+AsyncSocket* SocketStream::Detach() {
+ AsyncSocket* socket = socket_;
+ if (socket_) {
+ socket_->SignalConnectEvent.disconnect(this);
+ socket_->SignalReadEvent.disconnect(this);
+ socket_->SignalWriteEvent.disconnect(this);
+ socket_->SignalCloseEvent.disconnect(this);
+ socket_ = NULL;
+ }
+ return socket;
+}
+
+StreamState SocketStream::GetState() const {
+ ASSERT(socket_ != NULL);
+ switch (socket_->GetState()) {
+ case Socket::CS_CONNECTED:
+ return SS_OPEN;
+ case Socket::CS_CONNECTING:
+ return SS_OPENING;
+ case Socket::CS_CLOSED:
+ default:
+ return SS_CLOSED;
+ }
+}
+
+StreamResult SocketStream::Read(void* buffer, size_t buffer_len,
+ size_t* read, int* error) {
+ ASSERT(socket_ != NULL);
+ int result = socket_->Recv(buffer, buffer_len);
+ if (result < 0) {
+ if (socket_->IsBlocking())
+ return SR_BLOCK;
+ if (error)
+ *error = socket_->GetError();
+ return SR_ERROR;
+ }
+ if ((result > 0) || (buffer_len == 0)) {
+ if (read)
+ *read = result;
+ return SR_SUCCESS;
+ }
+ return SR_EOS;
+}
+
+StreamResult SocketStream::Write(const void* data, size_t data_len,
+ size_t* written, int* error) {
+ ASSERT(socket_ != NULL);
+ int result = socket_->Send(data, data_len);
+ if (result < 0) {
+ if (socket_->IsBlocking())
+ return SR_BLOCK;
+ if (error)
+ *error = socket_->GetError();
+ return SR_ERROR;
+ }
+ if (written)
+ *written = result;
+ return SR_SUCCESS;
+}
+
+void SocketStream::Close() {
+ ASSERT(socket_ != NULL);
+ socket_->Close();
+}
+
+void SocketStream::OnConnectEvent(AsyncSocket* socket) {
+ ASSERT(socket == socket_);
+ SignalEvent(this, SE_OPEN | SE_READ | SE_WRITE, 0);
+}
+
+void SocketStream::OnReadEvent(AsyncSocket* socket) {
+ ASSERT(socket == socket_);
+ SignalEvent(this, SE_READ, 0);
+}
+
+void SocketStream::OnWriteEvent(AsyncSocket* socket) {
+ ASSERT(socket == socket_);
+ SignalEvent(this, SE_WRITE, 0);
+}
+
+void SocketStream::OnCloseEvent(AsyncSocket* socket, int err) {
+ ASSERT(socket == socket_);
+ SignalEvent(this, SE_CLOSE, err);
+}
+
+
+} // namespace talk_base
diff --git a/talk/base/socketstream.h b/talk/base/socketstream.h
old mode 100755
new mode 100644
index 4d56b75..591dc4c
--- a/talk/base/socketstream.h
+++ b/talk/base/socketstream.h
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2006, Google Inc.
+ * Copyright 2005--2010, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_SOCKET_STREAM_H__
-#define TALK_BASE_SOCKET_STREAM_H__
+#ifndef TALK_BASE_SOCKETSTREAM_H_
+#define TALK_BASE_SOCKETSTREAM_H_
#include "talk/base/asyncsocket.h"
#include "talk/base/common.h"
@@ -38,109 +38,30 @@
class SocketStream : public StreamInterface, public sigslot::has_slots<> {
public:
- SocketStream(AsyncSocket* socket) : socket_(NULL) {
- Attach(socket);
- }
- virtual ~SocketStream() { delete socket_; }
+ explicit SocketStream(AsyncSocket* socket);
+ virtual ~SocketStream();
- void Attach(AsyncSocket* socket) {
- if (socket_)
- delete socket_;
- socket_ = socket;
- if (socket_) {
- socket_->SignalConnectEvent.connect(this, &SocketStream::OnConnectEvent);
- socket_->SignalReadEvent.connect(this, &SocketStream::OnReadEvent);
- socket_->SignalWriteEvent.connect(this, &SocketStream::OnWriteEvent);
- socket_->SignalCloseEvent.connect(this, &SocketStream::OnCloseEvent);
- }
- }
-
- AsyncSocket* Detach() {
- AsyncSocket* socket = socket_;
- if (socket_) {
- socket_->SignalConnectEvent.disconnect(this);
- socket_->SignalReadEvent.disconnect(this);
- socket_->SignalWriteEvent.disconnect(this);
- socket_->SignalCloseEvent.disconnect(this);
- socket_ = NULL;
- }
- return socket;
- }
+ void Attach(AsyncSocket* socket);
+ AsyncSocket* Detach();
AsyncSocket* GetSocket() { return socket_; }
- virtual StreamState GetState() const {
- ASSERT(socket_ != NULL);
- switch (socket_->GetState()) {
- case Socket::CS_CONNECTED:
- return SS_OPEN;
- case Socket::CS_CONNECTING:
- return SS_OPENING;
- case Socket::CS_CLOSED:
- default:
- return SS_CLOSED;
- }
- }
+ virtual StreamState GetState() const;
virtual StreamResult Read(void* buffer, size_t buffer_len,
- size_t* read, int* error) {
- ASSERT(socket_ != NULL);
- int result = socket_->Recv(buffer, buffer_len);
- if (result < 0) {
- if (socket_->IsBlocking())
- return SR_BLOCK;
- if (error)
- *error = socket_->GetError();
- return SR_ERROR;
- }
- if ((result > 0) || (buffer_len == 0)) {
- if (read)
- *read = result;
- return SR_SUCCESS;
- }
- return SR_EOS;
- }
+ size_t* read, int* error);
virtual StreamResult Write(const void* data, size_t data_len,
- size_t* written, int* error) {
- ASSERT(socket_ != NULL);
- int result = socket_->Send(data, data_len);
- if (result < 0) {
- if (socket_->IsBlocking())
- return SR_BLOCK;
- if (error)
- *error = socket_->GetError();
- return SR_ERROR;
- }
- if (written)
- *written = result;
- return SR_SUCCESS;
- }
+ size_t* written, int* error);
- virtual void Close() { ASSERT(socket_ != NULL); socket_->Close(); }
-
- virtual bool GetSize(size_t* size) const { return false; }
- virtual bool ReserveSize(size_t size) { return true; }
- virtual bool Rewind() { return false; }
+ virtual void Close();
private:
- void OnConnectEvent(AsyncSocket* socket) {
- ASSERT(socket == socket_);
- SignalEvent(this, SE_OPEN | SE_READ | SE_WRITE, 0);
- }
- void OnReadEvent(AsyncSocket* socket) {
- ASSERT(socket == socket_);
- SignalEvent(this, SE_READ, 0);
- }
- void OnWriteEvent(AsyncSocket* socket) {
- ASSERT(socket == socket_);
- SignalEvent(this, SE_WRITE, 0);
- }
- void OnCloseEvent(AsyncSocket* socket, int err) {
- ASSERT(socket == socket_);
- SignalEvent(this, SE_CLOSE, err);
- }
-
+ void OnConnectEvent(AsyncSocket* socket);
+ void OnReadEvent(AsyncSocket* socket);
+ void OnWriteEvent(AsyncSocket* socket);
+ void OnCloseEvent(AsyncSocket* socket, int err);
+
AsyncSocket* socket_;
DISALLOW_EVIL_CONSTRUCTORS(SocketStream);
@@ -150,4 +71,4 @@
} // namespace talk_base
-#endif // TALK_BASE_SOCKET_STREAM_H__
+#endif // TALK_BASE_SOCKETSTREAM_H_
diff --git a/talk/base/ssladapter.cc b/talk/base/ssladapter.cc
old mode 100755
new mode 100644
index 68fe038..2368e7a
--- a/talk/base/ssladapter.cc
+++ b/talk/base/ssladapter.cc
@@ -2,79 +2,53 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/ssladapter.h"
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+// Decide which (if any) implementation of SSL we will use.
#if !defined(SSL_USE_SCHANNEL) && !defined(SSL_USE_OPENSSL)
#ifdef WIN32
#define SSL_USE_SCHANNEL 1
#else // !WIN32
-#define SSL_USE_OPENSSL 1
+#define SSL_USE_OPENSSL HAVE_OPENSSL_SSL_H
#endif // !WIN32
#endif
+#include "talk/base/ssladapter.h"
+
#if SSL_USE_SCHANNEL
+
#include "schanneladapter.h"
-namespace talk_base {
- typedef SChannelAdapter DefaultSSLAdapter;
-}
-#endif // SSL_USE_SCHANNEL
-#if SSL_USE_OPENSSL
-#include <openssl/crypto.h>
-#include <openssl/rand.h>
-#include <openssl/ssl.h>
+#elif SSL_USE_OPENSSL // && !SSL_USE_SCHANNEL
+
#include "openssladapter.h"
-namespace talk_base {
- typedef OpenSSLAdapter DefaultSSLAdapter;
-}
-#if defined(WIN32)
- #define MUTEX_TYPE HANDLE
- #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
- #define MUTEX_CLEANUP(x) CloseHandle(x)
- #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
- #define MUTEX_UNLOCK(x) ReleaseMutex(x)
- #define THREAD_ID GetCurrentThreadId()
-#elif defined(_POSIX_THREADS)
- // _POSIX_THREADS is normally defined in unistd.h if pthreads are available
- // on your platform.
- #define MUTEX_TYPE pthread_mutex_t
- #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
- #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
- #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
- #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
- #define THREAD_ID pthread_self()
-#else
- #error You must define mutex operations appropriate for your platform!
-#endif
-struct CRYPTO_dynlock_value {
- MUTEX_TYPE mutex;
-};
-
-#endif // SSL_USE_OPENSSL
+#endif // SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
///////////////////////////////////////////////////////////////////////////////
@@ -82,97 +56,34 @@
SSLAdapter*
SSLAdapter::Create(AsyncSocket* socket) {
- return new DefaultSSLAdapter(socket);
+#if SSL_USE_SCHANNEL
+ return new SChannelAdapter(socket);
+#elif SSL_USE_OPENSSL // && !SSL_USE_SCHANNEL
+ return new OpenSSLAdapter(socket);
+#else // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
+ return NULL;
+#endif // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
}
///////////////////////////////////////////////////////////////////////////////
#if SSL_USE_OPENSSL
-
-
-// This array will store all of the mutexes available to OpenSSL.
-static MUTEX_TYPE* mutex_buf = NULL;
-
-static void locking_function(int mode, int n, const char * file, int line) {
- if (mode & CRYPTO_LOCK) {
- MUTEX_LOCK(mutex_buf[n]);
- } else {
- MUTEX_UNLOCK(mutex_buf[n]);
- }
-}
-
-static pthread_t id_function() {
- return THREAD_ID;
-}
-
-static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
- CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
- if (!value)
- return NULL;
- MUTEX_SETUP(value->mutex);
- return value;
-}
-
-static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
- const char* file, int line) {
- if (mode & CRYPTO_LOCK) {
- MUTEX_LOCK(l->mutex);
- } else {
- MUTEX_UNLOCK(l->mutex);
- }
-}
-
-static void dyn_destroy_function(CRYPTO_dynlock_value* l,
- const char* file, int line) {
- MUTEX_CLEANUP(l->mutex);
- delete l;
-}
-
-bool InitializeSSL() {
- if (!InitializeSSLThread() || !SSL_library_init())
- return false;
- SSL_load_error_strings();
- ERR_load_BIO_strings();
- OpenSSL_add_all_algorithms();
- RAND_poll();
- return true;
+bool InitializeSSL(VerificationCallback callback) {
+ return OpenSSLAdapter::InitializeSSL(callback);
}
bool InitializeSSLThread() {
- mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
- if (!mutex_buf)
- return false;
- for (int i = 0; i < CRYPTO_num_locks(); ++i)
- MUTEX_SETUP(mutex_buf[i]);
-
- // we need to cast our id_function to return an unsigned long -- pthread_t is a pointer
- CRYPTO_set_id_callback((unsigned long (*)())id_function);
- CRYPTO_set_locking_callback(locking_function);
- CRYPTO_set_dynlock_create_callback(dyn_create_function);
- CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
- CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
- return true;
+ return OpenSSLAdapter::InitializeSSLThread();
}
bool CleanupSSL() {
- if (!mutex_buf)
- return false;
- CRYPTO_set_id_callback(NULL);
- CRYPTO_set_locking_callback(NULL);
- CRYPTO_set_dynlock_create_callback(NULL);
- CRYPTO_set_dynlock_lock_callback(NULL);
- CRYPTO_set_dynlock_destroy_callback(NULL);
- for (int i = 0; i < CRYPTO_num_locks(); ++i)
- MUTEX_CLEANUP(mutex_buf[i]);
- delete [] mutex_buf;
- mutex_buf = NULL;
- return true;
+ return OpenSSLAdapter::CleanupSSL();
}
#else // !SSL_USE_OPENSSL
-bool InitializeSSL() {
+bool InitializeSSL(VerificationCallback callback) {
return true;
}
diff --git a/talk/base/ssladapter.h b/talk/base/ssladapter.h
old mode 100755
new mode 100644
index 0f0155c..687cc24
--- a/talk/base/ssladapter.h
+++ b/talk/base/ssladapter.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -57,9 +57,11 @@
///////////////////////////////////////////////////////////////////////////////
+typedef bool (*VerificationCallback)(void* cert);
+
// Call this on the main thread, before using SSL.
// Call CleanupSSLThread when finished with SSL.
-bool InitializeSSL();
+bool InitializeSSL(VerificationCallback callback = NULL);
// Call to initialize additional threads.
bool InitializeSSLThread();
diff --git a/talk/base/sslidentity.cc b/talk/base/sslidentity.cc
new file mode 100644
index 0000000..665e700
--- /dev/null
+++ b/talk/base/sslidentity.cc
@@ -0,0 +1,72 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Handling of certificates and keypairs for SSLStreamAdapter's peer mode.
+
+#include <string>
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+// Decide which (if any) implementation of SSL we will use.
+#if !defined(SSL_USE_SCHANNEL) && !defined(SSL_USE_OPENSSL)
+#ifdef WIN32
+#define SSL_USE_SCHANNEL 1
+#else // !WIN32
+#define SSL_USE_OPENSSL HAVE_OPENSSL_SSL_H
+#endif // !WIN32
+#endif
+
+#include "talk/base/sslidentity.h"
+
+#if SSL_USE_SCHANNEL
+
+#error "Not implemented yet"
+
+#elif SSL_USE_OPENSSL // && !SSL_USE_SCHANNEL
+
+#include "talk/base/opensslidentity.h"
+
+namespace talk_base {
+
+SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string,
+ int* pem_length) {
+ return OpenSSLCertificate::FromPEMString(pem_string, pem_length);
+}
+
+SSLIdentity* SSLIdentity::Generate(const std::string& common_name) {
+ return OpenSSLIdentity::Generate(common_name);
+}
+
+} // namespace talk_base
+
+#else // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
+
+#error "No SSL implementation"
+
+#endif // SSL_USE_OPENSSL/!SSL_USE_SCHANNEL
diff --git a/talk/base/sslidentity.h b/talk/base/sslidentity.h
new file mode 100644
index 0000000..ed996b4
--- /dev/null
+++ b/talk/base/sslidentity.h
@@ -0,0 +1,91 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Handling of certificates and keypairs for SSLStreamAdapter's peer mode.
+
+#ifndef TALK_BASE_SSLIDENTITY_H__
+#define TALK_BASE_SSLIDENTITY_H__
+
+#include <string>
+
+namespace talk_base {
+
+// Abstract interface overridden by SSL library specific
+// implementations.
+
+// A somewhat opaque type used to encapsulate a certificate.
+// Wraps the SSL library's notion of a certificate, with reference counting.
+// The SSLCertificate object is pretty much immutable once created.
+// (The OpenSSL implementation only does reference counting and
+// possibly caching of intermediate results.)
+class SSLCertificate {
+ public:
+ // Parses and build a certificate from a PEM encoded string.
+ // Returns NULL on failure.
+ // The length of the string representation of the certificate is
+ // stored in *pem_length if it is non-NULL, and only if
+ // parsing was successful.
+ // Caller is responsible for freeing the returned object.
+ static SSLCertificate* FromPEMString(const std::string& pem_string,
+ int* pem_length);
+ virtual ~SSLCertificate() {}
+
+ // Returns a new SSLCertificate object instance wrapping the same
+ // underlying certificate.
+ // Caller is responsible for freeing the returned object.
+ virtual SSLCertificate* GetReference() = 0;
+
+ // Returns a PEM encoded string representation of the certificate.
+ virtual std::string ToPEMString() const = 0;
+};
+
+// Our identity in an SSL negotiation: a keypair and certificate (both
+// with the same public key).
+// This too is pretty much immutable once created.
+class SSLIdentity {
+ public:
+ // Generates an identity (keypair and self-signed certificate). If
+ // common_name is non-empty, it will be used for the certificate's
+ // subject and issuer name, otherwise a random string will be used.
+ // Returns NULL on failure.
+ // Caller is responsible for freeing the returned object.
+ static SSLIdentity* Generate(const std::string& common_name);
+
+ virtual ~SSLIdentity() {}
+
+ // Returns a new SSLIdentity object instance wrapping the same
+ // identity information.
+ // Caller is responsible for freeing the returned object.
+ virtual SSLIdentity* GetReference() = 0;
+
+ // Returns a temporary reference to the certificate.
+ virtual SSLCertificate& certificate() const = 0;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SSLIDENTITY_H__
diff --git a/talk/base/sslsocketfactory.cc b/talk/base/sslsocketfactory.cc
new file mode 100644
index 0000000..fcb2c0c
--- /dev/null
+++ b/talk/base/sslsocketfactory.cc
@@ -0,0 +1,181 @@
+/*
+ * libjingle
+ * Copyright 2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/autodetectproxy.h"
+#include "talk/base/httpcommon.h"
+#include "talk/base/httpcommon-inl.h"
+#include "talk/base/socketadapters.h"
+#include "talk/base/ssladapter.h"
+#include "talk/base/sslsocketfactory.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// ProxySocketAdapter
+// TODO: Consider combining AutoDetectProxy and ProxySocketAdapter. I think
+// the socket adapter is the more appropriate idiom for automatic proxy
+// detection. We may or may not want to combine proxydetect.* as well.
+///////////////////////////////////////////////////////////////////////////////
+
+class ProxySocketAdapter : public AsyncSocketAdapter {
+ public:
+ ProxySocketAdapter(SslSocketFactory* factory, int type)
+ : AsyncSocketAdapter(NULL), factory_(factory), type_(type),
+ detect_(NULL) {
+ }
+ virtual ~ProxySocketAdapter() {
+ Close();
+ }
+
+ virtual int Connect(const SocketAddress& addr) {
+ ASSERT(NULL == detect_);
+ ASSERT(NULL == socket_);
+ remote_ = addr;
+ if (remote_.IsAnyIP() && remote_.hostname().empty()) {
+ LOG_F(LS_ERROR) << "Empty address";
+ return SOCKET_ERROR;
+ }
+ Url<char> url("/", remote_.IPAsString(), remote_.port());
+ detect_ = new AutoDetectProxy(factory_->agent_);
+ detect_->set_server_url(url.url());
+ detect_->SignalWorkDone.connect(this,
+ &ProxySocketAdapter::OnProxyDetectionComplete);
+ detect_->Start();
+ return SOCKET_ERROR;
+ }
+ virtual int GetError() const {
+ if (socket_) {
+ return socket_->GetError();
+ }
+ return detect_ ? EWOULDBLOCK : EADDRNOTAVAIL;
+ }
+ virtual int Close() {
+ if (socket_) {
+ return socket_->Close();
+ }
+ if (detect_) {
+ detect_->Destroy(false);
+ detect_ = NULL;
+ }
+ return 0;
+ }
+ virtual ConnState GetState() const {
+ if (socket_) {
+ return socket_->GetState();
+ }
+ return detect_ ? CS_CONNECTING : CS_CLOSED;
+ }
+
+private:
+ // AutoDetectProxy Slots
+ void OnProxyDetectionComplete(SignalThread* thread) {
+ ASSERT(detect_ == thread);
+ Attach(factory_->CreateProxySocket(detect_->proxy(), type_));
+ detect_->Release();
+ detect_ = NULL;
+ if (0 == AsyncSocketAdapter::Connect(remote_)) {
+ SignalConnectEvent(this);
+ } else if (!IsBlockingError(socket_->GetError())) {
+ SignalCloseEvent(this, socket_->GetError());
+ }
+ }
+
+ SslSocketFactory* factory_;
+ int type_;
+ SocketAddress remote_;
+ AutoDetectProxy* detect_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// SslSocketFactory
+///////////////////////////////////////////////////////////////////////////////
+
+Socket* SslSocketFactory::CreateSocket(int type) {
+ return factory_->CreateSocket(type);
+}
+
+AsyncSocket* SslSocketFactory::CreateAsyncSocket(int type) {
+ if (autodetect_proxy_) {
+ return new ProxySocketAdapter(this, type);
+ } else {
+ return CreateProxySocket(proxy_, type);
+ }
+}
+
+AsyncSocket* SslSocketFactory::CreateProxySocket(const ProxyInfo& proxy,
+ int type) {
+ AsyncSocket* socket = factory_->CreateAsyncSocket(type);
+ if (!socket)
+ return NULL;
+
+ // Binary logging happens at the lowest level
+ if (!logging_label_.empty() && binary_mode_) {
+ socket = new LoggingSocketAdapter(socket, logging_level_,
+ logging_label_.c_str(), binary_mode_);
+ }
+
+ if (proxy.type) {
+ AsyncSocket* proxy_socket = 0;
+ if (proxy_.type == PROXY_SOCKS5) {
+ proxy_socket = new AsyncSocksProxySocket(socket, proxy.address,
+ proxy.username, proxy.password);
+ } else {
+ // Note: we are trying unknown proxies as HTTPS currently
+ AsyncHttpsProxySocket* http_proxy =
+ new AsyncHttpsProxySocket(socket, agent_, proxy.address,
+ proxy.username, proxy.password);
+ http_proxy->SetForceConnect(force_connect_ || !hostname_.empty());
+ proxy_socket = http_proxy;
+ }
+ if (!proxy_socket) {
+ delete socket;
+ return NULL;
+ }
+ socket = proxy_socket; // for our purposes the proxy is now the socket
+ }
+
+ if (!hostname_.empty()) {
+ if (SSLAdapter* ssl_adapter = SSLAdapter::Create(socket)) {
+ ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_);
+ ssl_adapter->StartSSL(hostname_.c_str(), true);
+ socket = ssl_adapter;
+ } else {
+ LOG_F(LS_ERROR) << "SSL unavailable";
+ }
+ }
+
+ // Regular logging occurs at the highest level
+ if (!logging_label_.empty() && !binary_mode_) {
+ socket = new LoggingSocketAdapter(socket, logging_level_,
+ logging_label_.c_str(), binary_mode_);
+ }
+ return socket;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/sslsocketfactory.h b/talk/base/sslsocketfactory.h
new file mode 100644
index 0000000..d42689a
--- /dev/null
+++ b/talk/base/sslsocketfactory.h
@@ -0,0 +1,94 @@
+/*
+ * libjingle
+ * Copyright 2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_SSLSOCKETFACTORY_H__
+#define TALK_BASE_SSLSOCKETFACTORY_H__
+
+#include "talk/base/proxyinfo.h"
+#include "talk/base/socketserver.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// SslSocketFactory
+///////////////////////////////////////////////////////////////////////////////
+
+class SslSocketFactory : public SocketFactory {
+ public:
+ SslSocketFactory(SocketFactory* factory, const std::string& user_agent)
+ : factory_(factory), agent_(user_agent), autodetect_proxy_(true),
+ force_connect_(false), logging_level_(LS_VERBOSE), binary_mode_(false) {
+ }
+
+ void SetAutoDetectProxy() {
+ autodetect_proxy_ = true;
+ }
+ void SetForceConnect(bool force) {
+ force_connect_ = force;
+ }
+ void SetProxy(const ProxyInfo& proxy) {
+ autodetect_proxy_ = false;
+ proxy_ = proxy;
+ }
+ bool autodetect_proxy() const { return autodetect_proxy_; }
+ const ProxyInfo& proxy() const { return proxy_; }
+
+ void UseSSL(const char* hostname) { hostname_ = hostname; }
+ void DisableSSL() { hostname_.clear(); }
+ void SetIgnoreBadCert(bool ignore) { ignore_bad_cert_ = ignore; }
+ bool ignore_bad_cert() const { return ignore_bad_cert_; }
+
+ void SetLogging(LoggingSeverity level, const std::string& label,
+ bool binary_mode = false) {
+ logging_level_ = level;
+ logging_label_ = label;
+ binary_mode_ = binary_mode;
+ }
+
+ // SocketFactory Interface
+ virtual Socket* CreateSocket(int type);
+ virtual AsyncSocket* CreateAsyncSocket(int type);
+
+ private:
+ friend class ProxySocketAdapter;
+ AsyncSocket* CreateProxySocket(const ProxyInfo& proxy, int type);
+
+ SocketFactory* factory_;
+ std::string agent_;
+ bool autodetect_proxy_, force_connect_;
+ ProxyInfo proxy_;
+ std::string hostname_, logging_label_;
+ LoggingSeverity logging_level_;
+ bool binary_mode_;
+ bool ignore_bad_cert_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SSLSOCKETFACTORY_H__
diff --git a/talk/base/sslstreamadapter.cc b/talk/base/sslstreamadapter.cc
new file mode 100644
index 0000000..17121fd
--- /dev/null
+++ b/talk/base/sslstreamadapter.cc
@@ -0,0 +1,70 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+// Decide which (if any) implementation of SSL we will use.
+#if !defined(SSL_USE_SCHANNEL) && !defined(SSL_USE_OPENSSL)
+#ifdef WIN32
+#define SSL_USE_SCHANNEL 1
+#else // !WIN32
+#define SSL_USE_OPENSSL HAVE_OPENSSL_SSL_H
+#endif // !WIN32
+#endif
+
+#include "talk/base/sslstreamadapter.h"
+
+#if SSL_USE_SCHANNEL
+
+#error "Not implemented yet"
+
+#elif SSL_USE_OPENSSL // && !SSL_USE_SCHANNEL
+
+#include "talk/base/opensslstreamadapter.h"
+
+#endif // SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace talk_base {
+
+SSLStreamAdapter* SSLStreamAdapter::Create(StreamInterface* stream) {
+#if SSL_USE_SCHANNEL
+ // not implemented yet
+ // return new SChannelStreamAdapter(stream);
+#elif SSL_USE_OPENSSL // && !SSL_USE_SCHANNEL
+ return new OpenSSLStreamAdapter(stream);
+#else // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
+ return NULL;
+#endif // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/sslstreamadapter.h b/talk/base/sslstreamadapter.h
new file mode 100644
index 0000000..62cef08
--- /dev/null
+++ b/talk/base/sslstreamadapter.h
@@ -0,0 +1,123 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_SSLSTREAMADAPTER_H__
+#define TALK_BASE_SSLSTREAMADAPTER_H__
+
+#include "talk/base/stream.h"
+#include "talk/base/sslidentity.h"
+
+namespace talk_base {
+
+// SSLStreamAdapter : A StreamInterfaceAdapter that does SSL/TLS.
+// After SSL has been started, the stream will only open on successful
+// SSL verification of certificates, and the communication is
+// encrypted of course.
+//
+// This class was written with SSLAdapter as a starting point. It
+// offers a similar interface, with two differences: there is no
+// support for a restartable SSL connection, and this class has a
+// peer-to-peer mode.
+//
+// The SSL library requires initialization and cleanup. Static method
+// for doing this are in SSLAdapter. They should possibly be moved out
+// to a neutral class.
+
+class SSLStreamAdapter : public StreamAdapterInterface {
+ public:
+ // Instantiate an SSLStreamAdapter wrapping the given stream,
+ // (using the selected implementation for the platform).
+ // Caller is responsible for freeing the returned object.
+ static SSLStreamAdapter* Create(StreamInterface* stream);
+
+ explicit SSLStreamAdapter(StreamInterface* stream)
+ : StreamAdapterInterface(stream), ignore_bad_cert_(false) { }
+
+ void set_ignore_bad_cert(bool ignore) { ignore_bad_cert_ = ignore; }
+ bool ignore_bad_cert() const { return ignore_bad_cert_; }
+
+ // Specify our SSL identity: key and certificate. Mostly this is
+ // only used in the peer-to-peer mode (unless we actually want to
+ // provide a client certificate to a server).
+ // SSLStream takes ownership of the SSLIdentity object and will
+ // free it when appropriate. Should be called no more than once on a
+ // given SSLStream instance.
+ virtual void SetIdentity(SSLIdentity* identity) = 0;
+
+ // Call this to indicate that we are to play the server's role in
+ // the peer-to-peer mode.
+ virtual void SetServerRole() = 0;
+
+ // The mode of operation is selected by calling either
+ // StartSSLWithServer or StartSSLWithPeer.
+ // Use of the stream prior to calling either of these functions will
+ // pass data in clear text.
+ // Calling one of these functions causes SSL negotiation to begin as
+ // soon as possible: right away if the underlying wrapped stream is
+ // already opened, or else as soon as it opens.
+ //
+ // These functions return a negative error code on failure.
+ // Returning 0 means success so far, but negotiation is probably not
+ // complete and will continue asynchronously. In that case, the
+ // exposed stream will open after successful negotiation and
+ // verification, or an SE_CLOSE event will be raised if negotiation
+ // fails.
+
+ // StartSSLWithServer starts SSL negotiation with a server in
+ // traditional mode. server_name specifies the expected server name
+ // which the server's certificate needs to specify.
+ virtual int StartSSLWithServer(const char* server_name) = 0;
+
+ // StartSSLWithPeer starts negotiation in the special peer-to-peer
+ // mode.
+ // Generally, SetIdentity() and possibly SetServerRole() should have
+ // been called before this.
+ // SetPeerCertificate() must also be called. It may be called after
+ // StartSSLWithPeer() but must be called before the underlying
+ // stream opens.
+ virtual int StartSSLWithPeer() = 0;
+
+ // Specify the certificate that our peer is expected to use in
+ // peer-to-peer mode. Only this certificate will be accepted during
+ // SSL verification. The certificate is assumed to have been
+ // obtained through some other secure channel (such as the XMPP
+ // channel). (This could also specify the certificate authority that
+ // will sign the peer's certificate.)
+ // SSLStream takes ownership of the SSLCertificate object and will
+ // free it when appropriate. Should be called no more than once on a
+ // given SSLStream instance.
+ virtual void SetPeerCertificate(SSLCertificate* cert) = 0;
+
+ // If true, the server certificate need not match the configured
+ // server_name, and in fact missing certificate authority and other
+ // verification errors are ignored.
+ bool ignore_bad_cert_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SSLSTREAMADAPTER_H__
diff --git a/talk/base/stl_decl.h b/talk/base/stl_decl.h
deleted file mode 100755
index 193e7af..0000000
--- a/talk/base/stl_decl.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_BASE_STL_DECL_H__
-#define TALK_BASE_STL_DECL_H__
-
-#if defined(_MSC_VER) && _MSC_VER <= 1200 // 1200 == VC++ 6.0
-#pragma warning(disable:4786)
-#endif
-
-#include <sys/types.h>
-
-namespace std {
- template <class Key> struct hash;
- template <class Key> struct equal_to;
- template <class Key> struct less;
- template <class T> class allocator;
- template <class Key, class Val,
- class Compare,
- class Alloc> class map;
- template <class T, class Alloc> class vector;
- template <class T, class Alloc> class list;
- template <class T, class Alloc> class slist;
- template <class T, class Sequence> class stack;
- template <class T, class Sequence> class queue;
- template <class T, class Sequence, class Compare> class priority_queue;
- template <class T1, class T2> struct pair;
- template <class Key, class Compare, class Alloc> class set;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Workaround declaration problem with defaults
-/////////////////////////////////////////////////////////////////////////////
-
-#if defined(_MSC_VER) && _MSC_VER <= 1200 // 1200 == VC++ 6.0
-
-#define STD_MAP(T1, T2) \
- std::map<T1 , T2, std::less<T1>, std::allocator<T2> >
-
-#define STD_VECTOR(T1) \
- std::vector<T1, std::allocator<T1> >
-
-#define STD_SET(T1) \
- std::set<T1, std::less<T1>, std::allocator<T1> >
-
-#else
-
-#define STD_MAP(T1, T2) \
- std::map<T1, T2, std::less<T1>, std::allocator<std::pair<const T1, T2 > > >
-
-#define STD_VECTOR(T1) \
- std::vector<T1, std::allocator<T1> >
-
-#define STD_SET(T1) \
- std::set<T1, std::less<T1>, std::allocator<T1> >
-
-#endif
-
-
-#endif // TALK_BASE_STL_DECL_H__
diff --git a/talk/base/stream.cc b/talk/base/stream.cc
old mode 100755
new mode 100644
index 50d49a6..45ba7ad
--- a/talk/base/stream.cc
+++ b/talk/base/stream.cc
@@ -1,38 +1,44 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#if defined(POSIX)
+#include <sys/file.h>
+#endif // POSIX
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string>
#include "talk/base/basictypes.h"
#include "talk/base/common.h"
+#include "talk/base/messagequeue.h"
#include "talk/base/stream.h"
#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/thread.h"
#ifdef WIN32
#include "talk/base/win32.h"
@@ -42,6 +48,20 @@
namespace talk_base {
///////////////////////////////////////////////////////////////////////////////
+// StreamInterface
+///////////////////////////////////////////////////////////////////////////////
+
+enum {
+ MSG_POST_EVENT = 0xF1F1
+};
+
+StreamInterface::~StreamInterface() {
+}
+
+struct PostEventData : public MessageData {
+ int events, error;
+ PostEventData(int ev, int er) : events(ev), error(er) { }
+};
StreamResult StreamInterface::WriteAll(const void* data, size_t data_len,
size_t* written, int* error) {
@@ -76,6 +96,7 @@
}
StreamResult StreamInterface::ReadLine(std::string* line) {
+ line->clear();
StreamResult result = SR_SUCCESS;
while (true) {
char ch;
@@ -94,6 +115,60 @@
return result;
}
+void StreamInterface::PostEvent(Thread* t, int events, int err) {
+ t->Post(this, MSG_POST_EVENT, new PostEventData(events, err));
+}
+
+void StreamInterface::PostEvent(int events, int err) {
+ PostEvent(Thread::Current(), events, err);
+}
+
+StreamInterface::StreamInterface() {
+}
+
+void StreamInterface::OnMessage(Message* msg) {
+ if (MSG_POST_EVENT == msg->message_id) {
+ PostEventData* pe = static_cast<PostEventData*>(msg->pdata);
+ SignalEvent(this, pe->events, pe->error);
+ delete msg->pdata;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamAdapterInterface
+///////////////////////////////////////////////////////////////////////////////
+
+StreamAdapterInterface::StreamAdapterInterface(StreamInterface* stream,
+ bool owned)
+ : stream_(stream), owned_(owned) {
+ if (NULL != stream_)
+ stream_->SignalEvent.connect(this, &StreamAdapterInterface::OnEvent);
+}
+
+void StreamAdapterInterface::Attach(StreamInterface* stream, bool owned) {
+ if (NULL != stream_)
+ stream_->SignalEvent.disconnect(this);
+ if (owned_)
+ delete stream_;
+ stream_ = stream;
+ owned_ = owned;
+ if (NULL != stream_)
+ stream_->SignalEvent.connect(this, &StreamAdapterInterface::OnEvent);
+}
+
+StreamInterface* StreamAdapterInterface::Detach() {
+ if (NULL != stream_)
+ stream_->SignalEvent.disconnect(this);
+ StreamInterface* stream = stream_;
+ stream_ = NULL;
+ return stream;
+}
+
+StreamAdapterInterface::~StreamAdapterInterface() {
+ if (owned_)
+ delete stream_;
+}
+
///////////////////////////////////////////////////////////////////////////////
// StreamTap
///////////////////////////////////////////////////////////////////////////////
@@ -109,7 +184,7 @@
tap_.reset(tap);
}
-StreamInterface* StreamTap::DetachTap() {
+StreamInterface* StreamTap::DetachTap() {
return tap_.release();
}
@@ -149,6 +224,92 @@
}
///////////////////////////////////////////////////////////////////////////////
+// StreamSegment
+///////////////////////////////////////////////////////////////////////////////
+
+StreamSegment::StreamSegment(StreamInterface* stream)
+: StreamAdapterInterface(stream), start_(SIZE_UNKNOWN), pos_(0),
+ length_(SIZE_UNKNOWN)
+{
+ // It's ok for this to fail, in which case start_ is left as SIZE_UNKNOWN.
+ stream->GetPosition(&start_);
+}
+
+StreamSegment::StreamSegment(StreamInterface* stream, size_t length)
+: StreamAdapterInterface(stream), start_(SIZE_UNKNOWN), pos_(0),
+ length_(length)
+{
+ // It's ok for this to fail, in which case start_ is left as SIZE_UNKNOWN.
+ stream->GetPosition(&start_);
+}
+
+StreamResult StreamSegment::Read(void* buffer, size_t buffer_len,
+ size_t* read, int* error)
+{
+ if (SIZE_UNKNOWN != length_) {
+ if (pos_ >= length_)
+ return SR_EOS;
+ buffer_len = _min(buffer_len, length_ - pos_);
+ }
+ size_t backup_read;
+ if (!read) {
+ read = &backup_read;
+ }
+ StreamResult result = StreamAdapterInterface::Read(buffer, buffer_len,
+ read, error);
+ if (SR_SUCCESS == result) {
+ pos_ += *read;
+ }
+ return result;
+}
+
+bool StreamSegment::SetPosition(size_t position) {
+ if (SIZE_UNKNOWN == start_)
+ return false; // Not seekable
+ if ((SIZE_UNKNOWN != length_) && (position > length_))
+ return false; // Seek past end of segment
+ if (!StreamAdapterInterface::SetPosition(start_ + position))
+ return false;
+ pos_ = position;
+ return true;
+}
+
+bool StreamSegment::GetPosition(size_t* position) const {
+ if (SIZE_UNKNOWN == start_)
+ return false; // Not seekable
+ if (!StreamAdapterInterface::GetPosition(position))
+ return false;
+ if (position) {
+ ASSERT(*position >= start_);
+ *position -= start_;
+ }
+ return true;
+}
+
+bool StreamSegment::GetSize(size_t* size) const {
+ if (!StreamAdapterInterface::GetSize(size))
+ return false;
+ if (size) {
+ if (SIZE_UNKNOWN != start_) {
+ ASSERT(*size >= start_);
+ *size -= start_;
+ }
+ if (SIZE_UNKNOWN != length_) {
+ *size = _min(*size, length_);
+ }
+ }
+ return true;
+}
+
+bool StreamSegment::GetAvailable(size_t* size) const {
+ if (!StreamAdapterInterface::GetAvailable(size))
+ return false;
+ if (size && (SIZE_UNKNOWN != length_))
+ *size = _min(*size, length_ - pos_);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
// NullStream
///////////////////////////////////////////////////////////////////////////////
@@ -168,7 +329,6 @@
return SR_ERROR;
}
-
StreamResult NullStream::Write(const void* data, size_t data_len,
size_t* written, int* error) {
if (written) *written = data_len;
@@ -178,20 +338,6 @@
void NullStream::Close() {
}
-bool NullStream::GetSize(size_t* size) const {
- if (size)
- *size = 0;
- return true;
-}
-
-bool NullStream::ReserveSize(size_t size) {
- return true;
-}
-
-bool NullStream::Rewind() {
- return false;
-}
-
///////////////////////////////////////////////////////////////////////////////
// FileStream
///////////////////////////////////////////////////////////////////////////////
@@ -206,28 +352,12 @@
bool FileStream::Open(const std::string& filename, const char* mode) {
Close();
#ifdef WIN32
- int filenamelen = MultiByteToWideChar(CP_UTF8, 0, filename.c_str(),
- filename.length() + 1, NULL, 0);
- int modelen = MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
- wchar_t *wfilename = new wchar_t[filenamelen+4]; // 4 for "\\?\"
- wchar_t *wfilename_dest = wfilename;
- wchar_t *wmode = new wchar_t[modelen];
-
- if (!filename.empty() && (filename[0] != '\\')) {
- wcscpy(wfilename, L"\\\\?\\");
- wfilename_dest = wfilename + 4;
- }
-
- if ((MultiByteToWideChar(CP_UTF8, 0, filename.c_str(), filename.length() + 1,
- wfilename_dest, filenamelen) > 0) &&
- (MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, modelen) > 0)) {
- file_ = _wfopen(wfilename, wmode);
+ std::wstring wfilename;
+ if (Utf8ToWindowsFilename(filename, &wfilename)) {
+ file_ = _wfopen(wfilename.c_str(), ToUtf16(mode).c_str());
} else {
file_ = NULL;
}
-
- delete[] wfilename;
- delete[] wmode;
#else
file_ = fopen(filename.c_str(), mode);
#endif
@@ -238,28 +368,12 @@
int shflag) {
Close();
#ifdef WIN32
- int filenamelen = MultiByteToWideChar(CP_UTF8, 0, filename.c_str(),
- filename.length() + 1, NULL, 0);
- int modelen = MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
- wchar_t *wfilename = new wchar_t[filenamelen+4]; // 4 for "\\?\"
- wchar_t *wfilename_dest = wfilename;
- wchar_t *wmode = new wchar_t[modelen];
-
- if (!filename.empty() && (filename[0] != '\\')) {
- wcscpy(wfilename, L"\\\\?\\");
- wfilename_dest = wfilename + 4;
- }
-
- if ((MultiByteToWideChar(CP_UTF8, 0, filename.c_str(), filename.length() + 1,
- wfilename_dest, filenamelen) > 0) &&
- (MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, modelen) > 0)) {
- file_ = _wfsopen(wfilename, wmode, shflag);
+ std::wstring wfilename;
+ if (Utf8ToWindowsFilename(filename, &wfilename)) {
+ file_ = _wfsopen(wfilename.c_str(), ToUtf16(mode).c_str(), shflag);
} else {
file_ = NULL;
}
-
- delete[] wfilename;
- delete[] wmode;
#else
return Open(filename, mode);
#endif
@@ -310,7 +424,7 @@
void FileStream::Close() {
if (file_) {
- fclose(file_);
+ DoClose();
file_ = NULL;
}
}
@@ -321,25 +435,39 @@
return (fseek(file_, position, SEEK_SET) == 0);
}
-bool FileStream::GetPosition(size_t * position) const {
- ASSERT(position != NULL);
- if (!file_ || !position)
+bool FileStream::GetPosition(size_t* position) const {
+ ASSERT(NULL != position);
+ if (!file_)
return false;
long result = ftell(file_);
if (result < 0)
return false;
- *position = result;
+ if (position)
+ *position = result;
return true;
}
-bool FileStream::GetSize(size_t * size) const {
- ASSERT(size != NULL);
- if (!file_ || !size)
+bool FileStream::GetSize(size_t* size) const {
+ ASSERT(NULL != size);
+ if (!file_)
return false;
struct stat file_stats;
if (fstat(fileno(file_), &file_stats) != 0)
return false;
- *size = file_stats.st_size;
+ if (size)
+ *size = file_stats.st_size;
+ return true;
+}
+
+bool FileStream::GetAvailable(size_t* size) const {
+ ASSERT(NULL != size);
+ if (!GetSize(size))
+ return false;
+ long result = ftell(file_);
+ if (result < 0)
+ return false;
+ if (size)
+ *size -= result;
return true;
}
@@ -356,60 +484,89 @@
return true;
}
-int FileStream::Flush() {
+bool FileStream::Flush() {
if (file_) {
- return fflush (file_);
+ return (0 == fflush(file_));
}
// try to flush empty file?
ASSERT(false);
- return 0;
+ return false;
}
+
+#if defined(POSIX)
+
+bool FileStream::TryLock() {
+ if (file_ == NULL) {
+ // Stream not open.
+ ASSERT(false);
+ return false;
+ }
+
+ return flock(fileno(file_), LOCK_EX|LOCK_NB) == 0;
+}
+
+bool FileStream::Unlock() {
+ if (file_ == NULL) {
+ // Stream not open.
+ ASSERT(false);
+ return false;
+ }
+
+ return flock(fileno(file_), LOCK_UN) == 0;
+}
+
+#endif
+
+void FileStream::DoClose() {
+ fclose(file_);
+}
+
+#ifdef POSIX
+
+// Have to identically rewrite the FileStream destructor or else it would call
+// the base class's Close() instead of the sub-class's.
+POpenStream::~POpenStream() {
+ POpenStream::Close();
+}
+
+bool POpenStream::Open(const std::string& subcommand, const char* mode) {
+ Close();
+ file_ = popen(subcommand.c_str(), mode);
+ return file_ != NULL;
+}
+
+bool POpenStream::OpenShare(const std::string& subcommand, const char* mode,
+ int shflag) {
+ return Open(subcommand, mode);
+}
+
+void POpenStream::DoClose() {
+ wait_status_ = pclose(file_);
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryStream
///////////////////////////////////////////////////////////////////////////////
-
-MemoryStream::MemoryStream()
- : allocated_length_(0), buffer_(NULL), data_length_(0), seek_position_(0) {
+MemoryStreamBase::MemoryStreamBase()
+ : buffer_(NULL), buffer_length_(0), data_length_(0), seek_position_(0) {
}
-MemoryStream::MemoryStream(const char* data)
- : allocated_length_(0), buffer_(NULL), data_length_(0), seek_position_(0) {
- SetContents(data, strlen(data));
-}
-
-MemoryStream::MemoryStream(const char* data, size_t length)
- : allocated_length_(0), buffer_(NULL), data_length_(0), seek_position_(0) {
- SetContents(data, length);
-}
-
-MemoryStream::~MemoryStream() {
- delete [] buffer_;
-}
-
-void MemoryStream::SetContents(const char* data, size_t length) {
- delete [] buffer_;
- data_length_ = allocated_length_ = length;
- buffer_ = new char[allocated_length_];
- memcpy(buffer_, data, data_length_);
-}
-
-StreamState MemoryStream::GetState() const {
+StreamState MemoryStreamBase::GetState() const {
return SS_OPEN;
}
-StreamResult MemoryStream::Read(void *buffer, size_t bytes,
- size_t *bytes_read, int *error) {
+StreamResult MemoryStreamBase::Read(void* buffer, size_t bytes,
+ size_t* bytes_read, int* error) {
if (seek_position_ >= data_length_) {
- // At end of stream
- if (error) {
- *error = EOF;
- }
return SR_EOS;
}
-
- size_t remaining_length = data_length_ - seek_position_;
- if (bytes > remaining_length) {
+ size_t available = data_length_ - seek_position_;
+ if (bytes > available) {
// Read partial buffer
- bytes = remaining_length;
+ bytes = available;
}
memcpy(buffer, &buffer_[seek_position_], bytes);
seek_position_ += bytes;
@@ -419,140 +576,301 @@
return SR_SUCCESS;
}
-StreamResult MemoryStream::Write(const void *buffer,
- size_t bytes, size_t *bytes_written, int *error) {
- StreamResult sr = SR_SUCCESS;
- int error_value = 0;
- size_t bytes_written_value = 0;
-
- size_t new_position = seek_position_ + bytes;
- if (new_position > allocated_length_) {
+StreamResult MemoryStreamBase::Write(const void* buffer, size_t bytes,
+ size_t* bytes_written, int* error) {
+ size_t available = buffer_length_ - seek_position_;
+ if (0 == available) {
// Increase buffer size to the larger of:
// a) new position rounded up to next 256 bytes
// b) double the previous length
- size_t new_allocated_length = _max((new_position | 0xFF) + 1,
- allocated_length_ * 2);
- if (char* new_buffer = new char[new_allocated_length]) {
- memcpy(new_buffer, buffer_, data_length_);
- delete [] buffer_;
- buffer_ = new_buffer;
- allocated_length_ = new_allocated_length;
- } else {
- error_value = ENOMEM;
- sr = SR_ERROR;
+ size_t new_buffer_length = _max(((seek_position_ + bytes) | 0xFF) + 1,
+ buffer_length_ * 2);
+ StreamResult result = DoReserve(new_buffer_length, error);
+ if (SR_SUCCESS != result) {
+ return result;
}
+ ASSERT(buffer_length_ >= new_buffer_length);
+ available = buffer_length_ - seek_position_;
}
- if (sr == SR_SUCCESS) {
- bytes_written_value = bytes;
- memcpy(&buffer_[seek_position_], buffer, bytes);
- seek_position_ = new_position;
- if (data_length_ < seek_position_) {
- data_length_ = seek_position_;
- }
+ if (bytes > available) {
+ bytes = available;
}
-
+ memcpy(&buffer_[seek_position_], buffer, bytes);
+ seek_position_ += bytes;
+ if (data_length_ < seek_position_) {
+ data_length_ = seek_position_;
+ }
if (bytes_written) {
- *bytes_written = bytes_written_value;
+ *bytes_written = bytes;
}
- if (error) {
- *error = error_value;
- }
-
- return sr;
+ return SR_SUCCESS;
}
-void MemoryStream::Close() {
+void MemoryStreamBase::Close() {
// nothing to do
}
-bool MemoryStream::SetPosition(size_t position) {
- if (position <= data_length_) {
- seek_position_ = position;
- return true;
- }
- return false;
-}
-
-bool MemoryStream::GetPosition(size_t *position) const {
- if (!position) {
+bool MemoryStreamBase::SetPosition(size_t position) {
+ if (position > data_length_)
return false;
- }
- *position = seek_position_;
+ seek_position_ = position;
return true;
}
-bool MemoryStream::GetSize(size_t *size) const {
- if (!size) {
- return false;
- }
- *size = data_length_;
+bool MemoryStreamBase::GetPosition(size_t *position) const {
+ if (position)
+ *position = seek_position_;
return true;
}
-bool MemoryStream::ReserveSize(size_t size) {
- if (allocated_length_ >= size)
- return true;
+bool MemoryStreamBase::GetSize(size_t *size) const {
+ if (size)
+ *size = data_length_;
+ return true;
+}
+
+bool MemoryStreamBase::GetAvailable(size_t *size) const {
+ if (size)
+ *size = data_length_ - seek_position_;
+ return true;
+}
+
+bool MemoryStreamBase::ReserveSize(size_t size) {
+ return (SR_SUCCESS == DoReserve(size, NULL));
+}
+
+StreamResult MemoryStreamBase::DoReserve(size_t size, int* error) {
+ return (buffer_length_ >= size) ? SR_SUCCESS : SR_EOS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+MemoryStream::MemoryStream() {
+}
+
+MemoryStream::MemoryStream(const char* data) {
+ SetData(data, strlen(data));
+}
+
+MemoryStream::MemoryStream(const void* data, size_t length) {
+ SetData(data, length);
+}
+
+MemoryStream::~MemoryStream() {
+ delete [] buffer_;
+}
+
+void MemoryStream::SetData(const void* data, size_t length) {
+ data_length_ = buffer_length_ = length;
+ delete [] buffer_;
+ buffer_ = new char[buffer_length_];
+ memcpy(buffer_, data, data_length_);
+ seek_position_ = 0;
+}
+
+StreamResult MemoryStream::DoReserve(size_t size, int* error) {
+ if (buffer_length_ >= size)
+ return SR_SUCCESS;
if (char* new_buffer = new char[size]) {
memcpy(new_buffer, buffer_, data_length_);
delete [] buffer_;
buffer_ = new_buffer;
- allocated_length_ = size;
- return true;
+ buffer_length_ = size;
+ return SR_SUCCESS;
}
- return false;
+ if (error) {
+ *error = ENOMEM;
+ }
+ return SR_ERROR;
}
///////////////////////////////////////////////////////////////////////////////
-StreamResult Flow(StreamInterface* source,
- char* buffer, size_t buffer_len,
- StreamInterface* sink) {
- ASSERT(buffer_len > 0);
+ExternalMemoryStream::ExternalMemoryStream() {
+}
- StreamResult result;
- size_t count, read_pos, write_pos;
+ExternalMemoryStream::ExternalMemoryStream(void* data, size_t length) {
+ SetData(data, length);
+}
- bool end_of_stream = false;
- do {
- // Read until buffer is full, end of stream, or error
- read_pos = 0;
- do {
- result = source->Read(buffer + read_pos, buffer_len - read_pos,
- &count, NULL);
- if (result == SR_EOS) {
- end_of_stream = true;
- } else if (result != SR_SUCCESS) {
- return result;
- } else {
- read_pos += count;
- }
- } while (!end_of_stream && (read_pos < buffer_len));
+ExternalMemoryStream::~ExternalMemoryStream() {
+}
- // Write until buffer is empty, or error (including end of stream)
- write_pos = 0;
- do {
- result = sink->Write(buffer + write_pos, read_pos - write_pos,
- &count, NULL);
- if (result != SR_SUCCESS)
- return result;
+void ExternalMemoryStream::SetData(void* data, size_t length) {
+ data_length_ = buffer_length_ = length;
+ buffer_ = static_cast<char*>(data);
+ seek_position_ = 0;
+}
- write_pos += count;
- } while (write_pos < read_pos);
- } while (!end_of_stream);
+///////////////////////////////////////////////////////////////////////////////
+// FifoBuffer
+///////////////////////////////////////////////////////////////////////////////
+
+FifoBuffer::FifoBuffer(size_t size)
+ : state_(SS_OPEN), buffer_(new char[size]), buffer_length_(size),
+ data_length_(0), read_position_(0), owner_(Thread::Current()) {
+ // all events are done on the owner_ thread
+}
+
+FifoBuffer::~FifoBuffer() {
+}
+
+bool FifoBuffer::GetBuffered(size_t* size) const {
+ CritScope cs(&crit_);
+ *size = data_length_;
+ return true;
+}
+
+bool FifoBuffer::SetCapacity(size_t size) {
+ CritScope cs(&crit_);
+ if (data_length_ > size) {
+ return false;
+ }
+
+ if (size != buffer_length_) {
+ char* buffer = new char[size];
+ const size_t copy = data_length_;
+ const size_t tail_copy = _min(copy, buffer_length_ - read_position_);
+ memcpy(buffer, &buffer_[read_position_], tail_copy);
+ memcpy(buffer + tail_copy, &buffer_[0], copy - tail_copy);
+ buffer_.reset(buffer);
+ read_position_ = 0;
+ buffer_length_ = size;
+ }
+ return true;
+}
+
+StreamState FifoBuffer::GetState() const {
+ return state_;
+}
+
+StreamResult FifoBuffer::Read(void* buffer, size_t bytes,
+ size_t* bytes_read, int* error) {
+ CritScope cs(&crit_);
+ const size_t available = data_length_;
+ if (0 == available) {
+ return (state_ != SS_CLOSED) ? SR_BLOCK : SR_EOS;
+ }
+
+ const bool was_writable = data_length_ < buffer_length_;
+ const size_t copy = _min(bytes, available);
+ const size_t tail_copy = _min(copy, buffer_length_ - read_position_);
+ char* const p = static_cast<char*>(buffer);
+ memcpy(p, &buffer_[read_position_], tail_copy);
+ memcpy(p + tail_copy, &buffer_[0], copy - tail_copy);
+ read_position_ = (read_position_ + copy) % buffer_length_;
+ data_length_ -= copy;
+ if (bytes_read) {
+ *bytes_read = copy;
+ }
+ // if we were full before, and now we're not, post an event
+ if (!was_writable && copy > 0) {
+ PostEvent(owner_, SE_WRITE, 0);
+ }
return SR_SUCCESS;
}
+StreamResult FifoBuffer::Write(const void* buffer, size_t bytes,
+ size_t* bytes_written, int* error) {
+ CritScope cs(&crit_);
+ if (state_ == SS_CLOSED) {
+ return SR_EOS;
+ }
+
+ const size_t available = buffer_length_ - data_length_;
+ if (0 == available) {
+ return SR_BLOCK;
+ }
+
+ const bool was_readable = (data_length_ > 0);
+ const size_t write_position = (read_position_ + data_length_)
+ % buffer_length_;
+ const size_t copy = _min(bytes, available);
+ const size_t tail_copy = _min(copy, buffer_length_ - write_position);
+ const char* const p = static_cast<const char*>(buffer);
+ memcpy(&buffer_[write_position], p, tail_copy);
+ memcpy(&buffer_[0], p + tail_copy, copy - tail_copy);
+ data_length_ += copy;
+ if (bytes_written) {
+ *bytes_written = copy;
+ }
+ // if we didn't have any data to read before, and now we do, post an event
+ if (!was_readable && copy > 0) {
+ PostEvent(owner_, SE_READ, 0);
+ }
+
+ return SR_SUCCESS;
+}
+
+void FifoBuffer::Close() {
+ CritScope cs(&crit_);
+ state_ = SS_CLOSED;
+}
+
+const void* FifoBuffer::GetReadData(size_t* size) {
+ CritScope cs(&crit_);
+ *size = (read_position_ + data_length_ <= buffer_length_) ?
+ data_length_ : buffer_length_ - read_position_;
+ return &buffer_[read_position_];
+}
+
+void FifoBuffer::ConsumeReadData(size_t size) {
+ CritScope cs(&crit_);
+ ASSERT(size <= data_length_);
+ const bool was_writable = data_length_ < buffer_length_;
+ read_position_ = (read_position_ + size) % buffer_length_;
+ data_length_ -= size;
+ if (!was_writable && size > 0) {
+ PostEvent(owner_, SE_WRITE, 0);
+ }
+}
+
+void* FifoBuffer::GetWriteBuffer(size_t* size) {
+ CritScope cs(&crit_);
+ if (state_ == SS_CLOSED) {
+ return NULL;
+ }
+
+ // if empty, reset the write position to the beginning, so we can get
+ // the biggest possible block
+ if (data_length_ == 0) {
+ read_position_ = 0;
+ }
+
+ const size_t write_position = (read_position_ + data_length_)
+ % buffer_length_;
+ *size = (write_position >= read_position_) ?
+ buffer_length_ - write_position : read_position_ - write_position;
+ return &buffer_[write_position];
+}
+
+void FifoBuffer::ConsumeWriteBuffer(size_t size) {
+ CritScope cs(&crit_);
+ ASSERT(size <= buffer_length_ - data_length_);
+ const bool was_readable = (data_length_ > 0);
+ data_length_ += size;
+ if (!was_readable && size > 0) {
+ PostEvent(owner_, SE_READ, 0);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// LoggingAdapter
///////////////////////////////////////////////////////////////////////////////
LoggingAdapter::LoggingAdapter(StreamInterface* stream, LoggingSeverity level,
const std::string& label, bool hex_mode)
: StreamAdapterInterface(stream), level_(level), hex_mode_(hex_mode)
{
- label_.append("[");
+ set_label(label);
+}
+
+void LoggingAdapter::set_label(const std::string& label) {
+ label_.assign("[");
label_.append(label);
label_.append("]");
}
@@ -560,10 +878,10 @@
StreamResult LoggingAdapter::Read(void* buffer, size_t buffer_len,
size_t* read, int* error) {
size_t local_read; if (!read) read = &local_read;
- StreamResult result = StreamAdapterInterface::Read(buffer, buffer_len, read, error);
+ StreamResult result = StreamAdapterInterface::Read(buffer, buffer_len, read,
+ error);
if (result == SR_SUCCESS) {
- LogMultiline(level_, label_.c_str(), true,
- static_cast<const char *>(buffer), *read, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), true, buffer, *read, hex_mode_, &lms_);
}
return result;
}
@@ -571,15 +889,18 @@
StreamResult LoggingAdapter::Write(const void* data, size_t data_len,
size_t* written, int* error) {
size_t local_written; if (!written) written = &local_written;
- StreamResult result = StreamAdapterInterface::Write(data, data_len, written, error);
+ StreamResult result = StreamAdapterInterface::Write(data, data_len, written,
+ error);
if (result == SR_SUCCESS) {
- LogMultiline(level_, label_.c_str(), false,
- static_cast<const char *>(data), *written, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), false, data, *written, hex_mode_,
+ &lms_);
}
return result;
}
void LoggingAdapter::Close() {
+ LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_);
LOG_V(level_) << label_ << " Closed locally";
StreamAdapterInterface::Close();
}
@@ -588,6 +909,8 @@
if (events & SE_OPEN) {
LOG_V(level_) << label_ << " Open";
} else if (events & SE_CLOSE) {
+ LogMultiline(level_, label_.c_str(), false, NULL, 0, hex_mode_, &lms_);
+ LogMultiline(level_, label_.c_str(), true, NULL, 0, hex_mode_, &lms_);
LOG_V(level_) << label_ << " Closed with error: " << err;
}
StreamAdapterInterface::OnEvent(stream, events, err);
@@ -613,7 +936,7 @@
StreamResult StringStream::Read(void* buffer, size_t buffer_len,
size_t* read, int* error) {
- size_t available = talk_base::_min(buffer_len, str_.size() - read_pos_);
+ size_t available = _min(buffer_len, str_.size() - read_pos_);
if (!available)
return SR_EOS;
memcpy(buffer, str_.data() + read_pos_, available);
@@ -641,9 +964,28 @@
void StringStream::Close() {
}
+bool StringStream::SetPosition(size_t position) {
+ if (position > str_.size())
+ return false;
+ read_pos_ = position;
+ return true;
+}
+
+bool StringStream::GetPosition(size_t* position) const {
+ if (position)
+ *position = read_pos_;
+ return true;
+}
+
bool StringStream::GetSize(size_t* size) const {
- ASSERT(size != NULL);
- *size = str_.size();
+ if (size)
+ *size = str_.size();
+ return true;
+}
+
+bool StringStream::GetAvailable(size_t* size) const {
+ if (size)
+ *size = str_.size() - read_pos_;
return true;
}
@@ -654,9 +996,89 @@
return true;
}
-bool StringStream::Rewind() {
- read_pos_ = 0;
- return true;
+///////////////////////////////////////////////////////////////////////////////
+// StreamReference
+///////////////////////////////////////////////////////////////////////////////
+
+StreamReference::StreamReference(StreamInterface* stream)
+ : StreamAdapterInterface(stream, false) {
+ // owner set to false so the destructor does not free the stream.
+ stream_ref_count_ = new StreamRefCount(stream);
+}
+
+StreamInterface* StreamReference::NewReference() {
+ stream_ref_count_->AddReference();
+ return new StreamReference(stream_ref_count_, stream());
+}
+
+StreamReference::~StreamReference() {
+ stream_ref_count_->Release();
+}
+
+StreamReference::StreamReference(StreamRefCount* stream_ref_count,
+ StreamInterface* stream)
+ : StreamAdapterInterface(stream, false),
+ stream_ref_count_(stream_ref_count) {
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+StreamResult Flow(StreamInterface* source,
+ char* buffer, size_t buffer_len,
+ StreamInterface* sink,
+ size_t* data_len /* = NULL */) {
+ ASSERT(buffer_len > 0);
+
+ StreamResult result;
+ size_t count, read_pos, write_pos;
+ if (data_len) {
+ read_pos = *data_len;
+ } else {
+ read_pos = 0;
+ }
+
+ bool end_of_stream = false;
+ do {
+ // Read until buffer is full, end of stream, or error
+ while (!end_of_stream && (read_pos < buffer_len)) {
+ result = source->Read(buffer + read_pos, buffer_len - read_pos,
+ &count, NULL);
+ if (result == SR_EOS) {
+ end_of_stream = true;
+ } else if (result != SR_SUCCESS) {
+ if (data_len) {
+ *data_len = read_pos;
+ }
+ return result;
+ } else {
+ read_pos += count;
+ }
+ }
+
+ // Write until buffer is empty, or error (including end of stream)
+ write_pos = 0;
+ while (write_pos < read_pos) {
+ result = sink->Write(buffer + write_pos, read_pos - write_pos,
+ &count, NULL);
+ if (result != SR_SUCCESS) {
+ if (data_len) {
+ *data_len = read_pos - write_pos;
+ if (write_pos > 0) {
+ memmove(buffer, buffer + write_pos, *data_len);
+ }
+ }
+ return result;
+ }
+ write_pos += count;
+ }
+
+ read_pos = 0;
+ } while (!end_of_stream);
+
+ if (data_len) {
+ *data_len = 0;
+ }
+ return SR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/talk/base/stream.h b/talk/base/stream.h
old mode 100755
new mode 100644
index cb91bb7..ea91eac
--- a/talk/base/stream.h
+++ b/talk/base/stream.h
@@ -1,27 +1,27 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2010, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,7 +29,9 @@
#define TALK_BASE_STREAM_H__
#include "talk/base/basictypes.h"
+#include "talk/base/criticalsection.h"
#include "talk/base/logging.h"
+#include "talk/base/messagehandler.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/sigslot.h"
@@ -39,7 +41,7 @@
// StreamInterface is a generic asynchronous stream interface, supporting read,
// write, and close operations, and asynchronous signalling of state changes.
// The interface is designed with file, memory, and socket implementations in
-// mind.
+// mind. Some implementations offer extended operations, such as seeking.
///////////////////////////////////////////////////////////////////////////////
// The following enumerations are declared outside of the StreamInterface
@@ -61,9 +63,11 @@
// SE_WRITE: Data can be written, so Write is likely to not return SR_BLOCK
enum StreamEvent { SE_OPEN = 1, SE_READ = 2, SE_WRITE = 4, SE_CLOSE = 8 };
-class StreamInterface {
+class Thread;
+
+class StreamInterface : public MessageHandler {
public:
- virtual ~StreamInterface() { }
+ virtual ~StreamInterface();
virtual StreamState GetState() const = 0;
@@ -84,23 +88,120 @@
size_t* read, int* error) = 0;
virtual StreamResult Write(const void* data, size_t data_len,
size_t* written, int* error) = 0;
-
// Attempt to transition to the SS_CLOSED state. SE_CLOSE will not be
// signalled as a result of this call.
virtual void Close() = 0;
- // Return the number of bytes that will be returned by Read, if known.
- virtual bool GetSize(size_t* size) const = 0;
+ // Streams may signal one or more StreamEvents to indicate state changes.
+ // The first argument identifies the stream on which the state change occured.
+ // The second argument is a bit-wise combination of StreamEvents.
+ // If SE_CLOSE is signalled, then the third argument is the associated error
+ // code. Otherwise, the value is undefined.
+ // Note: Not all streams will support asynchronous event signalling. However,
+ // SS_OPENING and SR_BLOCK returned from stream member functions imply that
+ // certain events will be raised in the future.
+ sigslot::signal3<StreamInterface*, int, int> SignalEvent;
+
+ // Like calling SignalEvent, but posts a message to the specified thread,
+ // which will call SignalEvent. This helps unroll the stack and prevent
+ // re-entrancy.
+ void PostEvent(Thread* t, int events, int err);
+ // Like the aforementioned method, but posts to the current thread.
+ void PostEvent(int events, int err);
+
+ //
+ // OPTIONAL OPERATIONS
+ //
+ // Not all implementations will support the following operations. In general,
+ // a stream will only support an operation if it reasonably efficient to do
+ // so. For example, while a socket could buffer incoming data to support
+ // seeking, it will not do so. Instead, a buffering stream adapter should
+ // be used.
+ //
+ // Even though several of these operations are related, you should
+ // always use whichever operation is most relevant. For example, you may
+ // be tempted to use GetSize() and GetPosition() to deduce the result of
+ // GetAvailable(). However, a stream which is read-once may support the
+ // latter operation but not the former.
+ //
+
+ // The following four methods are used to avoid coping data multiple times.
+
+ // GetReadData returns a pointer to a buffer which is owned by the stream.
+ // The buffer contains data_len bytes. NULL is returned if no data is
+ // available, or if the method fails. If the caller processes the data, it
+ // must call ConsumeReadData with the number of processed bytes. GetReadData
+ // does not require a matching call to ConsumeReadData if the data is not
+ // processed. Read and ConsumeReadData invalidate the buffer returned by
+ // GetReadData.
+ virtual const void* GetReadData(size_t* data_len) { return NULL; }
+ virtual void ConsumeReadData(size_t used) {}
+
+ // GetWriteBuffer returns a pointer to a buffer which is owned by the stream.
+ // The buffer has a capacity of buf_len bytes. NULL is returned if there is
+ // no buffer available, or if the method fails. The call may write data to
+ // the buffer, and then call ConsumeWriteBuffer with the number of bytes
+ // written. GetWriteBuffer does not require a matching call to
+ // ConsumeWriteData if no data is written. Write, ForceWrite, and
+ // ConsumeWriteData invalidate the buffer returned by GetWriteBuffer.
+ // TODO: Allow the caller to specify a minimum buffer size. If the specified
+ // amount of buffer is not yet available, return NULL and Signal SE_WRITE
+ // when it is available. If the requested amount is too large, return an
+ // error.
+ virtual void* GetWriteBuffer(size_t* buf_len) { return NULL; }
+ virtual void ConsumeWriteBuffer(size_t used) {}
+
+ // Write data_len bytes found in data, circumventing any throttling which
+ // would could cause SR_BLOCK to be returned. Returns true if all the data
+ // was written. Otherwise, the method is unsupported, or an unrecoverable
+ // error occurred, and the error value is set. This method should be used
+ // sparingly to write critical data which should not be throttled. A stream
+ // which cannot circumvent its blocking constraints should not implement this
+ // method.
+ // NOTE: This interface is being considered experimentally at the moment. It
+ // would be used by JUDP and BandwidthStream as a way to circumvent certain
+ // soft limits in writing.
+ //virtual bool ForceWrite(const void* data, size_t data_len, int* error) {
+ // if (error) *error = -1;
+ // return false;
+ //}
+
+ // Seek to a byte offset from the beginning of the stream. Returns false if
+ // the stream does not support seeking, or cannot seek to the specified
+ // position.
+ virtual bool SetPosition(size_t position) { return false; }
+
+ // Get the byte offset of the current position from the start of the stream.
+ // Returns false if the position is not known.
+ virtual bool GetPosition(size_t* position) const { return false; }
+
+ // Get the byte length of the entire stream. Returns false if the length
+ // is not known.
+ virtual bool GetSize(size_t* size) const { return false; }
+
+ // Return the number of Read()-able bytes remaining before end-of-stream.
+ // Returns false if not known.
+ virtual bool GetAvailable(size_t* size) const { return false; }
+
+ // Return the number of Write()-able bytes remaining before end-of-stream.
+ // Returns false if not known.
+ virtual bool GetWriteRemaining(size_t* size) const { return false; }
// Communicates the amount of data which will be written to the stream. The
// stream may choose to preallocate memory to accomodate this data. The
- // stream may return false to indicate that there is not enough room (ie,
+ // stream may return false to indicate that there is not enough room (ie,
// Write will return SR_EOS/SR_ERROR at some point). Note that calling this
// function should not affect the existing state of data in the stream.
- virtual bool ReserveSize(size_t size) = 0;
+ virtual bool ReserveSize(size_t size) { return true; }
- // Returns true if stream could be repositioned to the beginning.
- virtual bool Rewind() = 0;
+ //
+ // CONVENIENCE METHODS
+ //
+ // These methods are implemented in terms of other methods, for convenience.
+ //
+
+ // Seek to the start of the stream.
+ inline bool Rewind() { return SetPosition(0); }
// WriteAll is a helper function which repeatedly calls Write until all the
// data is written, or something other than SR_SUCCESS is returned. Note that
@@ -121,18 +222,11 @@
// readline object or adapter
StreamResult ReadLine(std::string *line);
- // Streams may signal one or more StreamEvents to indicate state changes.
- // The first argument identifies the stream on which the state change occured.
- // The second argument is a bit-wise combination of StreamEvents.
- // If SE_CLOSE is signalled, then the third argument is the associated error
- // code. Otherwise, the value is undefined.
- // Note: Not all streams will support asynchronous event signalling. However,
- // SS_OPENING and SR_BLOCK returned from stream member functions imply that
- // certain events will be raised in the future.
- sigslot::signal3<StreamInterface*, int, int> SignalEvent;
-
protected:
- StreamInterface() { }
+ StreamInterface();
+
+ // MessageHandler Interface
+ virtual void OnMessage(Message* msg);
private:
DISALLOW_EVIL_CONSTRUCTORS(StreamInterface);
@@ -141,16 +235,17 @@
///////////////////////////////////////////////////////////////////////////////
// StreamAdapterInterface is a convenient base-class for adapting a stream.
// By default, all operations are pass-through. Override the methods that you
-// require adaptation. Note that the adapter will delete the adapted stream.
+// require adaptation. Streams should really be upgraded to reference-counted.
+// In the meantime, use the owned flag to indicate whether the adapter should
+// own the adapted stream.
///////////////////////////////////////////////////////////////////////////////
class StreamAdapterInterface : public StreamInterface,
public sigslot::has_slots<> {
public:
- explicit StreamAdapterInterface(StreamInterface* stream) {
- Attach(stream);
- }
+ explicit StreamAdapterInterface(StreamInterface* stream, bool owned = true);
+ // Core Stream Interface
virtual StreamState GetState() const {
return stream_->GetState();
}
@@ -165,39 +260,69 @@
virtual void Close() {
stream_->Close();
}
+
+ // Optional Stream Interface
+ /* Note: Many stream adapters were implemented prior to this Read/Write
+ interface. Therefore, a simple pass through of data in those cases may
+ be broken. At a later time, we should do a once-over pass of all
+ adapters, and make them compliant with these interfaces, after which this
+ code can be uncommented.
+ virtual const void* GetReadData(size_t* data_len) {
+ return stream_->GetReadData(data_len);
+ }
+ virtual void ConsumeReadData(size_t used) {
+ stream_->ConsumeReadData(used);
+ }
+
+ virtual void* GetWriteBuffer(size_t* buf_len) {
+ return stream_->GetWriteBuffer(buf_len);
+ }
+ virtual void ConsumeWriteBuffer(size_t used) {
+ stream_->ConsumeWriteBuffer(used);
+ }
+ */
+
+ /* Note: This interface is currently undergoing evaluation.
+ virtual bool ForceWrite(const void* data, size_t data_len, int* error) {
+ return stream_->ForceWrite(data, data_len, error);
+ }
+ */
+
+ virtual bool SetPosition(size_t position) {
+ return stream_->SetPosition(position);
+ }
+ virtual bool GetPosition(size_t* position) const {
+ return stream_->GetPosition(position);
+ }
virtual bool GetSize(size_t* size) const {
return stream_->GetSize(size);
}
+ virtual bool GetAvailable(size_t* size) const {
+ return stream_->GetAvailable(size);
+ }
+ virtual bool GetWriteRemaining(size_t* size) const {
+ return stream_->GetWriteRemaining(size);
+ }
virtual bool ReserveSize(size_t size) {
return stream_->ReserveSize(size);
}
- virtual bool Rewind() {
- return stream_->Rewind();
- }
- void Attach(StreamInterface* stream) {
- if (NULL != stream_.get())
- stream_->SignalEvent.disconnect(this);
- stream_.reset(stream);
- if (NULL != stream_.get())
- stream_->SignalEvent.connect(this, &StreamAdapterInterface::OnEvent);
- }
- StreamInterface* Detach() {
- if (NULL == stream_.get())
- return NULL;
- stream_->SignalEvent.disconnect(this);
- return stream_.release();
- }
+ void Attach(StreamInterface* stream, bool owned = true);
+ StreamInterface* Detach();
protected:
+ virtual ~StreamAdapterInterface();
+
// Note that the adapter presents itself as the origin of the stream events,
// since users of the adapter may not recognize the adapted object.
virtual void OnEvent(StreamInterface* stream, int events, int err) {
SignalEvent(this, events, err);
}
+ StreamInterface* stream() { return stream_; }
private:
- scoped_ptr<StreamInterface> stream_;
+ StreamInterface* stream_;
+ bool owned_;
DISALLOW_EVIL_CONSTRUCTORS(StreamAdapterInterface);
};
@@ -229,6 +354,34 @@
};
///////////////////////////////////////////////////////////////////////////////
+// StreamSegment adapts a read stream, to expose a subset of the adapted
+// stream's data. This is useful for cases where a stream contains multiple
+// documents concatenated together. StreamSegment can expose a subset of
+// the data as an independent stream, including support for rewinding and
+// seeking.
+///////////////////////////////////////////////////////////////////////////////
+
+class StreamSegment : public StreamAdapterInterface {
+ public:
+ // The current position of the adapted stream becomes the beginning of the
+ // segment. If a length is specified, it bounds the length of the segment.
+ explicit StreamSegment(StreamInterface* stream);
+ explicit StreamSegment(StreamInterface* stream, size_t length);
+
+ // StreamAdapterInterface Interface
+ virtual StreamResult Read(void* buffer, size_t buffer_len,
+ size_t* read, int* error);
+ virtual bool SetPosition(size_t position);
+ virtual bool GetPosition(size_t* position) const;
+ virtual bool GetSize(size_t* size) const;
+ virtual bool GetAvailable(size_t* size) const;
+
+ private:
+ size_t start_, pos_, length_;
+ DISALLOW_EVIL_CONSTRUCTORS(StreamSegment);
+};
+
+///////////////////////////////////////////////////////////////////////////////
// NullStream gives errors on read, and silently discards all written data.
///////////////////////////////////////////////////////////////////////////////
@@ -244,9 +397,6 @@
virtual StreamResult Write(const void* data, size_t data_len,
size_t* written, int* error);
virtual void Close();
- virtual bool GetSize(size_t* size) const;
- virtual bool ReserveSize(size_t size);
- virtual bool Rewind();
};
///////////////////////////////////////////////////////////////////////////////
@@ -274,65 +424,172 @@
virtual StreamResult Write(const void* data, size_t data_len,
size_t* written, int* error);
virtual void Close();
+ virtual bool SetPosition(size_t position);
+ virtual bool GetPosition(size_t* position) const;
virtual bool GetSize(size_t* size) const;
+ virtual bool GetAvailable(size_t* size) const;
virtual bool ReserveSize(size_t size);
- virtual bool Rewind() { return SetPosition(0); }
- bool SetPosition(size_t position);
- bool GetPosition(size_t* position) const;
- int Flush();
+ bool Flush();
+
+#if defined(POSIX)
+ // Tries to aquire an exclusive lock on the file.
+ // Use OpenShare(...) on win32 to get similar functionality.
+ bool TryLock();
+ bool Unlock();
+#endif
+
+ // Note: Deprecated in favor of Filesystem::GetFileSize().
static bool GetSize(const std::string& filename, size_t* size);
- private:
+ protected:
+ virtual void DoClose();
+
FILE* file_;
+
+ private:
DISALLOW_EVIL_CONSTRUCTORS(FileStream);
};
+#ifdef POSIX
+// A FileStream that is actually not a file, but the output or input of a
+// sub-command. See "man 3 popen" for documentation of the underlying OS popen()
+// function.
+class POpenStream : public FileStream {
+ public:
+ POpenStream() : wait_status_(-1) {}
+ virtual ~POpenStream();
+
+ virtual bool Open(const std::string& subcommand, const char* mode);
+ // Same as Open(). shflag is ignored.
+ virtual bool OpenShare(const std::string& subcommand, const char* mode,
+ int shflag);
+
+ // Returns the wait status from the last Close() of an Open()'ed stream, or
+ // -1 if no Open()+Close() has been done on this object. Meaning of the number
+ // is documented in "man 2 wait".
+ int GetWaitStatus() const { return wait_status_; }
+
+ protected:
+ virtual void DoClose();
+
+ private:
+ int wait_status_;
+};
+#endif // POSIX
+
///////////////////////////////////////////////////////////////////////////////
// MemoryStream is a simple implementation of a StreamInterface over in-memory
-// data. It does not support asynchronous notification.
+// data. Data is read and written at the current seek position. Reads return
+// end-of-stream when they reach the end of data. Writes actually extend the
+// end of data mark.
///////////////////////////////////////////////////////////////////////////////
-class MemoryStream : public StreamInterface {
+class MemoryStreamBase : public StreamInterface {
public:
- MemoryStream();
- // Pre-populate stream with the provided data.
- MemoryStream(const char* data);
- MemoryStream(const char* data, size_t length);
- virtual ~MemoryStream();
-
virtual StreamState GetState() const;
- virtual StreamResult Read(void *buffer, size_t bytes, size_t *bytes_read, int *error);
- virtual StreamResult Write(const void *buffer, size_t bytes, size_t *bytes_written, int *error);
+ virtual StreamResult Read(void* buffer, size_t bytes, size_t* bytes_read,
+ int* error);
+ virtual StreamResult Write(const void* buffer, size_t bytes,
+ size_t* bytes_written, int* error);
virtual void Close();
+ virtual bool SetPosition(size_t position);
+ virtual bool GetPosition(size_t* position) const;
virtual bool GetSize(size_t* size) const;
+ virtual bool GetAvailable(size_t* size) const;
virtual bool ReserveSize(size_t size);
- virtual bool Rewind() { return SetPosition(0); }
char* GetBuffer() { return buffer_; }
const char* GetBuffer() const { return buffer_; }
- bool SetPosition(size_t position);
- bool GetPosition(size_t* position) const;
+
+ protected:
+ MemoryStreamBase();
+
+ virtual StreamResult DoReserve(size_t size, int* error);
+
+ // Invariant: 0 <= seek_position <= data_length_ <= buffer_length_
+ char* buffer_;
+ size_t buffer_length_;
+ size_t data_length_;
+ size_t seek_position_;
private:
- void SetContents(const char* data, size_t length);
+ DISALLOW_EVIL_CONSTRUCTORS(MemoryStreamBase);
+};
- size_t allocated_length_;
- char* buffer_;
- size_t data_length_;
- size_t seek_position_;
+// MemoryStream dynamically resizes to accomodate written data.
+
+class MemoryStream : public MemoryStreamBase {
+ public:
+ MemoryStream();
+ explicit MemoryStream(const char* data); // Calls SetData(data, strlen(data))
+ MemoryStream(const void* data, size_t length); // Calls SetData(data, length)
+ virtual ~MemoryStream();
+
+ void SetData(const void* data, size_t length);
+
+ protected:
+ virtual StreamResult DoReserve(size_t size, int* error);
+};
+
+// ExternalMemoryStream adapts an external memory buffer, so writes which would
+// extend past the end of the buffer will return end-of-stream.
+
+class ExternalMemoryStream : public MemoryStreamBase {
+ public:
+ ExternalMemoryStream();
+ ExternalMemoryStream(void* data, size_t length);
+ virtual ~ExternalMemoryStream();
+
+ void SetData(void* data, size_t length);
+};
+
+// FifoBuffer allows for efficient, thread-safe buffering of data between
+// writer and reader. As the data can wrap around the end of the buffer,
+// MemoryStreamBase can't help us here.
+
+class FifoBuffer : public StreamInterface {
+ public:
+ // Creates a FIFO buffer with the specified capacity.
+ explicit FifoBuffer(size_t length);
+ virtual ~FifoBuffer();
+ // Gets the amount of data currently readable from the buffer.
+ bool GetBuffered(size_t* data_len) const;
+ // Resizes the buffer to the specified capacity. Fails if data_length_ > size
+ bool SetCapacity(size_t length);
+
+ // StreamInterface methods
+ virtual StreamState GetState() const;
+ virtual StreamResult Read(void* buffer, size_t bytes,
+ size_t* bytes_read, int* error);
+ virtual StreamResult Write(const void* buffer, size_t bytes,
+ size_t* bytes_written, int* error);
+ virtual void Close();
+ virtual const void* GetReadData(size_t* data_len);
+ virtual void ConsumeReadData(size_t used);
+ virtual void* GetWriteBuffer(size_t *buf_len);
+ virtual void ConsumeWriteBuffer(size_t used);
private:
- DISALLOW_EVIL_CONSTRUCTORS(MemoryStream);
+ StreamState state_; // keeps the opened/closed state of the stream
+ scoped_array<char> buffer_; // the allocated buffer
+ size_t buffer_length_; // size of the allocated buffer
+ size_t data_length_; // amount of readable data in the buffer
+ size_t read_position_; // offset to the readable data
+ Thread* owner_; // stream callbacks are dispatched on this thread
+ mutable CriticalSection crit_; // object lock
+ DISALLOW_EVIL_CONSTRUCTORS(FifoBuffer);
};
///////////////////////////////////////////////////////////////////////////////
class LoggingAdapter : public StreamAdapterInterface {
-public:
+ public:
LoggingAdapter(StreamInterface* stream, LoggingSeverity level,
const std::string& label, bool hex_mode = false);
+ void set_label(const std::string& label);
+
virtual StreamResult Read(void* buffer, size_t buffer_len,
size_t* read, int* error);
virtual StreamResult Write(const void* data, size_t data_len,
@@ -356,9 +613,9 @@
///////////////////////////////////////////////////////////////////////////////
class StringStream : public StreamInterface {
-public:
- StringStream(std::string& str);
- StringStream(const std::string& str);
+ public:
+ explicit StringStream(std::string& str);
+ explicit StringStream(const std::string& str);
virtual StreamState GetState() const;
virtual StreamResult Read(void* buffer, size_t buffer_len,
@@ -366,17 +623,79 @@
virtual StreamResult Write(const void* data, size_t data_len,
size_t* written, int* error);
virtual void Close();
+ virtual bool SetPosition(size_t position);
+ virtual bool GetPosition(size_t* position) const;
virtual bool GetSize(size_t* size) const;
+ virtual bool GetAvailable(size_t* size) const;
virtual bool ReserveSize(size_t size);
- virtual bool Rewind();
-private:
+ private:
std::string& str_;
size_t read_pos_;
bool read_only_;
};
///////////////////////////////////////////////////////////////////////////////
+// StreamReference - A reference counting stream adapter
+///////////////////////////////////////////////////////////////////////////////
+
+// Keep in mind that the streams and adapters defined in this file are
+// not thread-safe, so this has limited uses.
+
+// A StreamRefCount holds the reference count and a pointer to the
+// wrapped stream. It deletes the wrapped stream when there are no
+// more references. We can then have multiple StreamReference
+// instances pointing to one StreamRefCount, all wrapping the same
+// stream.
+
+class StreamReference : public StreamAdapterInterface {
+ class StreamRefCount;
+ public:
+ // Constructor for the first reference to a stream
+ // Note: get more references through NewReference(). Use this
+ // constructor only once on a given stream.
+ explicit StreamReference(StreamInterface* stream);
+ StreamInterface* GetStream() { return stream(); }
+ StreamInterface* NewReference();
+ virtual ~StreamReference();
+
+ private:
+ class StreamRefCount {
+ public:
+ explicit StreamRefCount(StreamInterface* stream)
+ : stream_(stream), ref_count_(1) {
+ }
+ void AddReference() {
+ CritScope lock(&cs_);
+ ++ref_count_;
+ }
+ void Release() {
+ int ref_count;
+ { // Atomic ops would have been a better fit here.
+ CritScope lock(&cs_);
+ ref_count = --ref_count_;
+ }
+ if (ref_count == 0) {
+ delete stream_;
+ delete this;
+ }
+ }
+ private:
+ StreamInterface* stream_;
+ int ref_count_;
+ CriticalSection cs_;
+ DISALLOW_EVIL_CONSTRUCTORS(StreamRefCount);
+ };
+
+ // Constructor for adding references
+ explicit StreamReference(StreamRefCount* stream_ref_count,
+ StreamInterface* stream);
+
+ StreamRefCount* stream_ref_count_;
+ DISALLOW_EVIL_CONSTRUCTORS(StreamReference);
+};
+
+///////////////////////////////////////////////////////////////////////////////
// Flow attempts to move bytes from source to sink via buffer of size
// buffer_len. The function returns SR_SUCCESS when source reaches
@@ -384,13 +703,15 @@
// to sink. Alternately, if source returns SR_BLOCK or SR_ERROR, or if sink
// returns SR_BLOCK, SR_ERROR, or SR_EOS, then the function immediately returns
// with the unexpected StreamResult value.
-
+// data_len is the length of the valid data in buffer. in case of error
+// this is the data that read from source but can't move to destination.
+// as a pass in parameter, it indicates data in buffer that should move to sink
StreamResult Flow(StreamInterface* source,
char* buffer, size_t buffer_len,
- StreamInterface* sink);
+ StreamInterface* sink, size_t* data_len = NULL);
///////////////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
#endif // TALK_BASE_STREAM_H__
diff --git a/talk/base/streamutils.cc b/talk/base/streamutils.cc
deleted file mode 100755
index 52e6da7..0000000
--- a/talk/base/streamutils.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2006, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "talk/base/common.h"
-#include "talk/base/streamutils.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// TODO: Extend so that one side can close, and other side can send
-// buffered data.
-
-StreamRelay::StreamRelay(talk_base::StreamInterface* s1,
- talk_base::StreamInterface* s2,
- size_t buffer_size) : buffer_size_(buffer_size) {
- dir_[0].stream = s1;
- dir_[1].stream = s2;
-
- ASSERT(s1->GetState() != talk_base::SS_CLOSED);
- ASSERT(s2->GetState() != talk_base::SS_CLOSED);
-
- for (size_t i=0; i<2; ++i) {
- dir_[i].stream->SignalEvent.connect(this, &StreamRelay::OnEvent);
- dir_[i].buffer = new char[buffer_size_];
- dir_[i].data_len = 0;
- }
-}
-
-StreamRelay::~StreamRelay() {
- for (size_t i=0; i<2; ++i) {
- delete dir_[i].stream;
- delete [] dir_[i].buffer;
- }
-}
-
-void
-StreamRelay::Circulate() {
- int error = 0;
- if (!Flow(0, &error) || !Flow(1, &error)) {
- Close();
- SignalClosed(this, error);
- }
-}
-
-void
-StreamRelay::Close() {
- for (size_t i=0; i<2; ++i) {
- dir_[i].stream->SignalEvent.disconnect(this);
- dir_[i].stream->Close();
- }
-}
-
-bool
-StreamRelay::Flow(int read_index, int* error) {
- Direction& reader = dir_[read_index];
- Direction& writer = dir_[Complement(read_index)];
-
- bool progress;
- do {
- progress = false;
-
- while (reader.stream->GetState() == talk_base::SS_OPEN) {
- size_t available = buffer_size_ - reader.data_len;
- if (available == 0)
- break;
-
- *error = 0;
- size_t read = 0;
- talk_base::StreamResult result
- = reader.stream->Read(reader.buffer + reader.data_len, available,
- &read, error);
- if ((result == talk_base::SR_BLOCK) || (result == talk_base::SR_EOS))
- break;
-
- if (result == talk_base::SR_ERROR)
- return false;
-
- progress = true;
- ASSERT((read > 0) && (read <= available));
- reader.data_len += read;
- }
-
- size_t total_written = 0;
- while (writer.stream->GetState() == talk_base::SS_OPEN) {
- size_t available = reader.data_len - total_written;
- if (available == 0)
- break;
-
- *error = 0;
- size_t written = 0;
- talk_base::StreamResult result
- = writer.stream->Write(reader.buffer + total_written,
- available, &written, error);
- if ((result == talk_base::SR_BLOCK) || (result == talk_base::SR_EOS))
- break;
-
- if (result == talk_base::SR_ERROR)
- return false;
-
- progress = true;
- ASSERT((written > 0) && (written <= available));
- total_written += written;
- }
-
- reader.data_len -= total_written;
- if (reader.data_len > 0) {
- memmove(reader.buffer, reader.buffer + total_written, reader.data_len);
- }
- } while (progress);
-
- return true;
-}
-
-void StreamRelay::OnEvent(talk_base::StreamInterface* stream, int events,
- int error) {
- int index = Index(stream);
-
- // Note: In the following cases, we are treating the open event as both
- // readable and writeable, for robustness. It won't hurt if we are wrong.
-
- if ((events & talk_base::SE_OPEN | talk_base::SE_READ)
- && !Flow(index, &error)) {
- events = talk_base::SE_CLOSE;
- }
-
- if ((events & talk_base::SE_OPEN | talk_base::SE_WRITE)
- && !Flow(Complement(index), &error)) {
- events = talk_base::SE_CLOSE;
- }
-
- if (events & talk_base::SE_CLOSE) {
- Close();
- SignalClosed(this, error);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// StreamCounter - counts the number of bytes which are transferred in either
-// direction.
-///////////////////////////////////////////////////////////////////////////////
-
-StreamCounter::StreamCounter(talk_base::StreamInterface* stream)
- : StreamAdapterInterface(stream), count_(0) {
-}
-
-talk_base::StreamResult StreamCounter::Read(void* buffer, size_t buffer_len,
- size_t* read, int* error) {
- size_t tmp;
- if (!read)
- read = &tmp;
- talk_base::StreamResult result
- = StreamAdapterInterface::Read(buffer, buffer_len,
- read, error);
- if (result == talk_base::SR_SUCCESS)
- count_ += *read;
- SignalUpdateByteCount(count_);
- return result;
-}
-
-talk_base::StreamResult StreamCounter::Write(
- const void* data, size_t data_len, size_t* written, int* error) {
- size_t tmp;
- if (!written)
- written = &tmp;
- talk_base::StreamResult result
- = StreamAdapterInterface::Write(data, data_len, written, error);
- if (result == talk_base::SR_SUCCESS)
- count_ += *written;
- SignalUpdateByteCount(count_);
- return result;
-}
diff --git a/talk/base/streamutils.h b/talk/base/streamutils.h
deleted file mode 100755
index 7bb07a3..0000000
--- a/talk/base/streamutils.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2006, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_APP_STREAMUTILS_H__
-#define TALK_APP_STREAMUTILS_H__
-
-#include "talk/base/sigslot.h"
-#include "talk/base/stream.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// StreamRelay - acts as an intermediary between two asynchronous streams,
-// reading from one stream and writing to the other, using a pre-specified
-// amount of buffering in both directions.
-///////////////////////////////////////////////////////////////////////////////
-
-class StreamRelay : public sigslot::has_slots<> {
-public:
- StreamRelay(talk_base::StreamInterface* s1,
- talk_base::StreamInterface* s2, size_t buffer_size);
- virtual ~StreamRelay();
-
- void Circulate(); // Simulate events to get things flowing
- void Close();
-
- sigslot::signal2<StreamRelay*, int> SignalClosed;
-
-private:
- inline int Index(talk_base::StreamInterface* s) const
- { return (s == dir_[1].stream); }
- inline int Complement(int index) const { return (1-index); }
-
- bool Flow(int read_index, int* error);
- void OnEvent(talk_base::StreamInterface* stream, int events, int error);
-
- struct Direction {
- talk_base::StreamInterface* stream;
- char* buffer;
- size_t data_len;
- };
- Direction dir_[2];
- size_t buffer_size_;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// StreamCounter - counts the number of bytes which are transferred in either
-// direction.
-///////////////////////////////////////////////////////////////////////////////
-
-class StreamCounter : public talk_base::StreamAdapterInterface {
- public:
- explicit StreamCounter(talk_base::StreamInterface* stream);
-
- inline void ResetByteCount() { count_ = 0; }
- inline size_t GetByteCount() const { return count_; }
-
- sigslot::signal1<size_t> SignalUpdateByteCount;
-
- // StreamAdapterInterface
- virtual talk_base::StreamResult Read(void* buffer, size_t buffer_len,
- size_t* read, int* error);
- virtual talk_base::StreamResult Write(const void* data, size_t data_len,
- size_t* written, int* error);
-
- private:
- size_t count_;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-#endif // TALK_APP_STREAMUTILS_H__
diff --git a/talk/base/stringdigest.cc b/talk/base/stringdigest.cc
old mode 100755
new mode 100644
diff --git a/talk/base/stringdigest.h b/talk/base/stringdigest.h
old mode 100755
new mode 100644
diff --git a/talk/base/stringencode.cc b/talk/base/stringencode.cc
old mode 100755
new mode 100644
index ed6edfc..d588514
--- a/talk/base/stringencode.cc
+++ b/talk/base/stringencode.cc
@@ -25,17 +25,13 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
-#include <malloc.h>
-#endif // WIN32
-#ifdef POSIX
-#include <alloca.h>
-#define _alloca alloca
-#endif // POSIX
+#include "talk/base/stringencode.h"
+
+#include <cstdio>
+#include <cstdlib>
#include "talk/base/basictypes.h"
#include "talk/base/common.h"
-#include "talk/base/stringencode.h"
#include "talk/base/stringutils.h"
namespace talk_base {
@@ -51,10 +47,17 @@
return (val < 16) ? HEX[val] : '!';
}
-unsigned char hex_decode(char ch) {
- char lower = tolower(ch);
- ASSERT(((ch >= '0') && (ch <= '9')) || ((lower >= 'a') && (lower <= 'z')));
- return (ch <= '9') ? (ch - '0') : ((lower - 'a') + 10);
+bool hex_decode(char ch, unsigned char* val) {
+ if ((ch >= '0') && (ch <= '9')) {
+ *val = ch - '0';
+ } else if ((ch >= 'A') && (ch <= 'Z')) {
+ *val = (ch - 'A') + 10;
+ } else if ((ch >= 'a') && (ch <= 'z')) {
+ *val = (ch - 'a') + 10;
+ } else {
+ return false;
+ }
+ return true;
}
size_t escape(char * buffer, size_t buflen,
@@ -129,12 +132,15 @@
if (buflen <= 0)
return 0;
+ unsigned char h1, h2;
size_t srcpos = 0, bufpos = 0;
while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
char ch = source[srcpos++];
- if ((ch == escape) && (srcpos + 1 < srclen)) {
- buffer[bufpos++] = (hex_decode(source[srcpos]) << 4)
- | hex_decode(source[srcpos+1]);
+ if ((ch == escape)
+ && (srcpos + 1 < srclen)
+ && hex_decode(source[srcpos], &h1)
+ && hex_decode(source[srcpos+1], &h2)) {
+ buffer[bufpos++] = (h1 << 4) | h2;
srcpos += 2;
} else {
buffer[bufpos++] = ch;
@@ -151,6 +157,8 @@
return "\\/:*?\"<>|";
#else // !WIN32
// TODO
+ ASSERT(false);
+ return "";
#endif // !WIN23
}
@@ -202,14 +210,18 @@
if (buflen <= 0)
return 0;
+ unsigned char h1, h2;
size_t srcpos = 0, bufpos = 0;
while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
unsigned char ch = source[srcpos++];
if (ch == '+') {
buffer[bufpos++] = ' ';
- } else if ((ch == '%') && (srcpos + 1 < srclen)) {
- buffer[bufpos++] = (hex_decode(source[srcpos]) << 4)
- | hex_decode(source[srcpos+1]);
+ } else if ((ch == '%')
+ && (srcpos + 1 < srclen)
+ && hex_decode(source[srcpos], &h1)
+ && hex_decode(source[srcpos+1], &h2))
+ {
+ buffer[bufpos++] = (h1 << 4) | h2;
srcpos += 2;
} else {
buffer[bufpos++] = ch;
@@ -432,6 +444,13 @@
return bufpos;
}
+std::string hex_encode(const char * source, size_t srclen) {
+ const size_t kBufferSize = srclen * 2 + 1;
+ char* buffer = STACK_ARRAY(char, kBufferSize);
+ size_t length = hex_encode(buffer, kBufferSize, source, srclen);
+ return std::string(buffer, length);
+}
+
size_t hex_encode(char * buffer, size_t buflen,
const char * csource, size_t srclen) {
ASSERT(NULL != buffer); // TODO: estimate output size
@@ -461,32 +480,69 @@
unsigned char * bbuffer = reinterpret_cast<unsigned char *>(cbuffer);
+ unsigned char h1, h2;
size_t srcpos = 0, bufpos = 0;
- while ((srcpos + 1 < srclen) && (bufpos + 1 < buflen)) {
- unsigned char v1 = (hex_decode(source[srcpos]) << 4);
- unsigned char v2 = hex_decode(source[srcpos+1]);
- bbuffer[bufpos++] = v1 | v2;
+ while ((srcpos + 1 < srclen)
+ && (bufpos + 1 < buflen)
+ && hex_decode(source[srcpos], &h1)
+ && hex_decode(source[srcpos+1], &h2))
+ {
+ bbuffer[bufpos++] = (h1 << 4) | h2;
srcpos += 2;
}
bbuffer[bufpos] = '\0';
return bufpos;
}
-void transform(std::string& value, size_t maxlen, const std::string& source,
- Transform t) {
- char * buffer = static_cast<char *>(_alloca(maxlen + 1));
- value.assign(buffer, t(buffer, maxlen + 1, source.data(), source.length()));
+size_t transform(std::string& value, size_t maxlen, const std::string& source,
+ Transform t) {
+ char* buffer = STACK_ARRAY(char, maxlen + 1);
+ size_t length = t(buffer, maxlen + 1, source.data(), source.length());
+ value.assign(buffer, length);
+ return length;
}
std::string s_transform(const std::string& source, Transform t) {
// Ask transformation function to approximate the destination size (returns upper bound)
size_t maxlen = t(NULL, 0, source.data(), source.length());
- char * buffer = static_cast<char *>(_alloca(maxlen));
+ char * buffer = STACK_ARRAY(char, maxlen);
size_t len = t(buffer, maxlen, source.data(), source.length());
std::string result(buffer, len);
return result;
}
+size_t split(const std::string& source, char delimiter,
+ std::vector<std::string>* fields)
+{
+ ASSERT(NULL != fields);
+ fields->clear();
+ size_t last = 0;
+ for (size_t i=0; i<source.length(); ++i) {
+ if (source[i] == delimiter) {
+ fields->push_back(source.substr(last, i - last));
+ last = i+1;
+ }
+ }
+ fields->push_back(source.substr(last, source.length() - last));
+ return fields->size();
+}
+
+std::string split_one(const std::string& source, char delimiter, int* index) {
+ std::string substring;
+ size_t start = source.find_first_not_of(delimiter, *index);
+ size_t end = source.find_first_of(delimiter, start);
+ if (start != std::string::npos) {
+ if (end == std::string::npos) {
+ substring = source.substr(start);
+ *index = source.length();
+ } else {
+ substring = source.substr(start, end - start);
+ *index = source.find_first_not_of(delimiter, end);
+ }
+ }
+ return substring;
+}
+
char make_char_safe_for_filename(char c) {
if (c < 32)
return '_';
@@ -510,7 +566,7 @@
/*
void sprintf(std::string& value, size_t maxlen, const char * format, ...) {
- char * buffer = static_cast<char *>(alloca(maxlen + 1));
+ char * buffer = STACK_ARRAY(char, maxlen + 1);
va_list args;
va_start(args, format);
value.assign(buffer, vsprintfn(buffer, maxlen + 1, format, args));
@@ -519,61 +575,5 @@
*/
/////////////////////////////////////////////////////////////////////////////
-// Unit Tests
-/////////////////////////////////////////////////////////////////////////////
-
-#ifdef _DEBUG
-
-static int utf8_unittest() {
- const struct Utf8Test {
- const char* encoded;
- size_t encsize, enclen;
- unsigned long decoded;
- } kTests[] = {
- { "a ", 5, 1, 'a' },
- { "\x7F ", 5, 1, 0x7F },
- { "\xC2\x80 ", 5, 2, 0x80 },
- { "\xDF\xBF ", 5, 2, 0x7FF },
- { "\xE0\xA0\x80 ", 5, 3, 0x800 },
- { "\xEF\xBF\xBF ", 5, 3, 0xFFFF },
- { "\xF0\x90\x80\x80 ", 5, 4, 0x10000 },
- { "\xF0\x90\x80\x80 ", 3, 0, 0x10000 },
- { "\xF0\xF0\x80\x80 ", 5, 0, 0 },
- { "\xF0\x90\x80 ", 5, 0, 0 },
- { "\x90\x80\x80 ", 5, 0, 0 },
- { NULL, 0, 0 },
- };
- for (size_t i=0; kTests[i].encoded; ++i) {
- unsigned long val = 0;
- ASSERT(kTests[i].enclen == utf8_decode(kTests[i].encoded,
- kTests[i].encsize,
- &val));
- unsigned long result = (kTests[i].enclen == 0) ? 0 : kTests[i].decoded;
- ASSERT(val == result);
-
- if (kTests[i].decoded == 0) {
- // Not an interesting encoding test case
- continue;
- }
-
- char buffer[5];
- memset(buffer, 0x01, ARRAY_SIZE(buffer));
- ASSERT(kTests[i].enclen == utf8_encode(buffer,
- kTests[i].encsize,
- kTests[i].decoded));
- ASSERT(memcmp(buffer, kTests[i].encoded, kTests[i].enclen) == 0);
- // Make sure remainder of buffer is unchanged
- ASSERT(memory_check(buffer + kTests[i].enclen,
- 0x1,
- ARRAY_SIZE(buffer) - kTests[i].enclen));
- }
- return 1;
-}
-
-int test = utf8_unittest();
-
-#endif // _DEBUG
-
-/////////////////////////////////////////////////////////////////////////////
} // namespace talk_base
diff --git a/talk/base/stringencode.h b/talk/base/stringencode.h
old mode 100755
new mode 100644
index 08e5e4f..143b220
--- a/talk/base/stringencode.h
+++ b/talk/base/stringencode.h
@@ -30,6 +30,7 @@
#include <string>
#include <sstream>
+#include <vector>
namespace talk_base {
@@ -40,7 +41,7 @@
// Convert an unsigned value from 0 to 15 to the hex character equivalent...
char hex_encode(unsigned char val);
// ...and vice-versa.
-unsigned char hex_decode(char ch);
+bool hex_decode(char ch, unsigned char* val);
// Convert an unsigned value to it's utf8 representation. Returns the length
// of the encoded string, or 0 if the encoding is longer than buflen - 1.
@@ -102,14 +103,16 @@
const char * source, size_t srclen);
size_t hex_decode(char * buffer, size_t buflen,
const char * source, size_t srclen);
+// helper funtion for hex_encode
+std::string hex_encode(const char * source, size_t srclen);
// Apply any suitable string transform (including the ones above) to an STL
// string. Stack-allocated temporary space is used for the transformation,
// so value and source may refer to the same string.
typedef size_t (*Transform)(char * buffer, size_t buflen,
const char * source, size_t srclen);
-void transform(std::string& value, size_t maxlen, const std::string& source,
- Transform t);
+size_t transform(std::string& value, size_t maxlen, const std::string& source,
+ Transform t);
// Return the result of applying transform t to source.
std::string s_transform(const std::string& source, Transform t);
@@ -122,6 +125,15 @@
return s_transform(source, url_decode);
}
+// Splits the source string into multiple fields separated by delimiter.
+size_t split(const std::string& source, char delimiter,
+ std::vector<std::string>* fields);
+
+// Returns the first part of a string separated by delimiter.
+// Index indicates the location to start parsing in the string and
+// is increased to the start of the next substring.
+std::string split_one(const std::string& source, char delimiter, int* index);
+
// Safe sprintf to std::string
//void sprintf(std::string& value, size_t maxlen, const char * format, ...)
// PRINTF_FORMAT(3);
@@ -155,6 +167,11 @@
T val; FromString(str, &val); return val;
}
+template<typename T>
+static inline T FromString(const T& defaultValue, const std::string& str) {
+ T val(defaultValue); FromString(str, &val); return val;
+}
+
// simple function to strip out characters which shouldn't be
// used in filenames
char make_char_safe_for_filename(char c);
diff --git a/talk/base/stringutils.cc b/talk/base/stringutils.cc
old mode 100755
new mode 100644
index 1e43637..44dc7c8
--- a/talk/base/stringutils.cc
+++ b/talk/base/stringutils.cc
@@ -41,6 +41,31 @@
return true;
}
+bool string_match(const char* target, const char* pattern) {
+ while (*pattern) {
+ if (*pattern == '*') {
+ if (!*++pattern) {
+ return true;
+ }
+ while (*target) {
+ if ((toupper(*pattern) == toupper(*target))
+ && string_match(target + 1, pattern + 1)) {
+ return true;
+ }
+ ++target;
+ }
+ return false;
+ } else {
+ if (toupper(*pattern) != toupper(*target)) {
+ return false;
+ }
+ ++target;
+ ++pattern;
+ }
+ }
+ return !*target;
+}
+
#ifdef WIN32
int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
CharacterTransformation transformation) {
@@ -81,4 +106,27 @@
#endif // WIN32
+void replace_substrs(const char *search,
+ size_t search_len,
+ const char *replace,
+ size_t replace_len,
+ std::string *s) {
+ size_t pos = 0;
+ while ((pos = s->find(search, pos, search_len)) != std::string::npos) {
+ s->replace(pos, search_len, replace, replace_len);
+ pos += replace_len;
+ }
+}
+
+bool starts_with(const char *s1, const char *s2) {
+ while (*s2 != '\0') {
+ if (*s1 != *s2) {
+ return false;
+ }
+ s1++;
+ s2++;
+ }
+ return true;
+}
+
} // namespace talk_base
diff --git a/talk/base/stringutils.h b/talk/base/stringutils.h
old mode 100755
new mode 100644
index c3051fd..3e1771f
--- a/talk/base/stringutils.h
+++ b/talk/base/stringutils.h
@@ -31,21 +31,43 @@
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
+
#ifdef WIN32
+#include <malloc.h>
#include <wchar.h>
+#define alloca _alloca
#endif // WIN32
+#ifdef POSIX
+#ifdef BSD
+#include <stdlib.h>
+#else // BSD
+#include <alloca.h>
+#endif // !BSD
+#endif // POSIX
+
+#include <cstring>
#include <string>
+#include "talk/base/basictypes.h"
+
///////////////////////////////////////////////////////////////////////////////
// Generic string/memory utilities
///////////////////////////////////////////////////////////////////////////////
+#define STACK_ARRAY(TYPE, LEN) static_cast<TYPE*>(::alloca((LEN)*sizeof(TYPE)))
+
namespace talk_base {
// Complement to memset. Verifies memory consists of count bytes of value c.
bool memory_check(const void* memory, int c, size_t count);
+// Determines whether the simple wildcard pattern matches target.
+// Alpha characters in pattern match case-insensitively.
+// Asterisks in pattern match 0 or more characters.
+// Ex: string_match("www.TEST.GOOGLE.COM", "www.*.com") -> true
+bool string_match(const char* target, const char* pattern);
+
} // namespace talk_base
///////////////////////////////////////////////////////////////////////////////
@@ -55,7 +77,10 @@
// strlen, strcmp, stricmp, strncmp, strnicmp
// strchr, vsnprintf, strtoul, tolowercase
// tolowercase is like tolower, but not compatible with end-of-file value
-// Note that the wchar_t versions are not available on Linux
+//
+// It's not clear if we will ever use wchar_t strings on unix. In theory,
+// all strings should be Utf8 all the time, except when interfacing with Win32
+// APIs that require Utf16.
///////////////////////////////////////////////////////////////////////////////
inline char tolowercase(char c) {
@@ -85,12 +110,14 @@
inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) {
return wcsstr(haystack, needle);
}
+#ifndef vsnprintf
inline int vsnprintf(char* buf, size_t n, const char* fmt, va_list args) {
return _vsnprintf(buf, n, fmt, args);
}
inline int vsnprintf(wchar_t* buf, size_t n, const wchar_t* fmt, va_list args) {
return _vsnwprintf(buf, n, fmt, args);
}
+#endif // !vsnprintf
inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) {
return wcstoul(snum, end, base);
}
@@ -196,15 +223,8 @@
return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen);
}
-template<class CTYPE>
-size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) {
- va_list args;
- va_start(args, format);
- size_t len = vsprintfn(buffer, buflen, format, args);
- va_end(args);
- return len;
-}
-
+// Some compilers (clang specifically) require vsprintfn be defined before
+// sprintfn.
template<class CTYPE>
size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format,
va_list args) {
@@ -216,6 +236,22 @@
return len;
}
+template<class CTYPE>
+size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...);
+/* This works to get GCC to notice printf argument mismatches, but then complains of missing implementation of sprintfn<char>
+template<>
+size_t sprintfn(char* buffer, size_t buflen, const char* format, ...)
+GCC_ATTR(format(printf,3,4));
+*/
+template<class CTYPE>
+size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) {
+ va_list args;
+ va_start(args, format);
+ size_t len = vsprintfn(buffer, buflen, format, args);
+ va_end(args);
+ return len;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Allow safe comparing and copying ascii (not UTF-8) with both wide and
// non-wide character strings.
@@ -269,7 +305,7 @@
template<>
struct Traits<char> {
typedef std::string string;
- inline static const char* Traits<char>::empty_str() { return ""; }
+ inline static const char* empty_str() { return ""; }
};
///////////////////////////////////////////////////////////////////////////////
@@ -286,6 +322,16 @@
#endif // WIN32
+// Replaces all occurrences of "search" with "replace".
+void replace_substrs(const char *search,
+ size_t search_len,
+ const char *replace,
+ size_t replace_len,
+ std::string *s);
+
+// True iff s1 starts with s2.
+bool starts_with(const char *s1, const char *s2);
+
} // namespace talk_base
#endif // TALK_BASE_STRINGUTILS_H__
diff --git a/talk/base/tarstream.cc b/talk/base/tarstream.cc
deleted file mode 100755
index e1f17b1..0000000
--- a/talk/base/tarstream.cc
+++ /dev/null
@@ -1,601 +0,0 @@
-#include "talk/base/basicdefs.h"
-#include "talk/base/basictypes.h"
-#include "talk/base/tarstream.h"
-#include "talk/base/pathutils.h"
-#include "talk/base/stringutils.h"
-#include "talk/base/common.h"
-
-using namespace talk_base;
-
-///////////////////////////////////////////////////////////////////////////////
-// TarStream
-///////////////////////////////////////////////////////////////////////////////
-
-TarStream::TarStream() : mode_(M_NONE), next_block_(NB_NONE), block_pos_(0),
- current_(NULL), current_bytes_(0) {
-}
-
-TarStream::~TarStream() {
- Close();
-}
-
-bool TarStream::AddFilter(const std::string& pathname) {
- if (pathname.empty())
- return false;
- Pathname archive_path(pathname);
- archive_path.SetFolderDelimiter('/');
- archive_path.Normalize();
- filters_.push_back(archive_path.pathname());
- return true;
-}
-
-bool TarStream::Open(const std::string& folder, bool read) {
- Close();
-
- Pathname root_folder;
- root_folder.SetFolder(folder);
- root_folder.Normalize();
- root_folder_.assign(root_folder.folder());
-
- if (read) {
- std::string pattern(root_folder_);
- DirectoryIterator *iter = new DirectoryIterator();
-
- if (iter->Iterate(pattern) == false) {
- delete iter;
- return false;
- }
- mode_ = M_READ;
- find_.push_front(iter);
- next_block_ = NB_FILE_HEADER;
- block_pos_ = BLOCK_SIZE;
- int error;
- if (SR_SUCCESS != ProcessNextEntry(find_.front(), &error)) {
- return false;
- }
- } else {
- if (!Filesystem::CreateFolder(root_folder_)) {
- return false;
- }
-
- mode_ = M_WRITE;
- next_block_ = NB_FILE_HEADER;
- block_pos_ = 0;
- }
- return true;
-}
-
-StreamState TarStream::GetState() const {
- return (M_NONE == mode_) ? SS_CLOSED : SS_OPEN;
-}
-
-StreamResult TarStream::Read(void* buffer, size_t buffer_len,
- size_t* read, int* error) {
- if (M_READ != mode_) {
- return SR_EOS;
- }
- return ProcessBuffer(buffer, buffer_len, read, error);
-}
-
-StreamResult TarStream::Write(const void* data, size_t data_len,
- size_t* written, int* error) {
- if (M_WRITE != mode_) {
- return SR_EOS;
- }
- // Note: data is not modified unless M_READ == mode_
- return ProcessBuffer(const_cast<void*>(data), data_len, written, error);
-}
-
-void TarStream::Close() {
- root_folder_.clear();
- next_block_ = NB_NONE;
- block_pos_ = 0;
- delete current_;
- current_ = NULL;
- current_bytes_ = 0;
- for (DirectoryList::iterator it = find_.begin(); it != find_.end(); ++it) {
- delete(*it);
- }
- find_.clear();
- subfolder_.clear();
-}
-
-StreamResult TarStream::ProcessBuffer(void* buffer, size_t buffer_len,
- size_t* consumed, int* error) {
- size_t local_consumed;
- if (!consumed) consumed = &local_consumed;
- int local_error;
- if (!error) error = &local_error;
-
- StreamResult result = SR_SUCCESS;
- *consumed = 0;
-
- while (*consumed < buffer_len) {
- size_t available = BLOCK_SIZE - block_pos_;
- if (available == 0) {
- result = ProcessNextBlock(error);
- if (SR_SUCCESS != result) {
- break;
- }
- } else {
- size_t bytes_to_copy = talk_base::_min(available, buffer_len - *consumed);
- char* buffer_ptr = static_cast<char*>(buffer) + *consumed;
- char* block_ptr = block_ + block_pos_;
- if (M_READ == mode_) {
- memcpy(buffer_ptr, block_ptr, bytes_to_copy);
- } else {
- memcpy(block_ptr, buffer_ptr, bytes_to_copy);
- }
- *consumed += bytes_to_copy;
- block_pos_ += bytes_to_copy;
- }
- }
-
- // SR_EOS means no data was consumed on this operation. So we may need to
- // return SR_SUCCESS instead, and then we will return SR_EOS next time.
- if ((SR_EOS == result) && (*consumed > 0)) {
- result = SR_SUCCESS;
- }
-
- return result;
-}
-
-StreamResult TarStream::ProcessNextBlock(int* error) {
- ASSERT(NULL != error);
- ASSERT(M_NONE != mode_);
- ASSERT(BLOCK_SIZE == block_pos_);
-
- StreamResult result;
- if (NB_NONE == next_block_) {
-
- return SR_EOS;
-
- } else if (NB_TRAILER == next_block_) {
-
- // Trailer block is zeroed
- result = ProcessEmptyBlock(0, error);
- if (SR_SUCCESS != result)
- return result;
- next_block_ = NB_NONE;
-
- } else if (NB_FILE_HEADER == next_block_) {
-
- if (M_READ == mode_) {
- result = ReadNextFile(error);
- } else {
- result = WriteNextFile(error);
- }
-
- // If there are no more files, we are at the first trailer block
- if (SR_EOS == result) {
- block_pos_ = 0;
- next_block_ = NB_TRAILER;
- result = ProcessEmptyBlock(0, error);
- }
- if (SR_SUCCESS != result)
- return result;
-
- } else if (NB_DATA == next_block_) {
-
- size_t block_consumed = 0;
- size_t block_available = talk_base::_min<size_t>(BLOCK_SIZE, current_bytes_);
- while (block_consumed < block_available) {
- void* block_ptr = static_cast<char*>(block_) + block_consumed;
- size_t available = block_available - block_consumed, consumed;
- if (M_READ == mode_) {
- ASSERT(NULL != current_);
- result = current_->Read(block_ptr, available, &consumed, error);
- } else if (current_) {
- result = current_->Write(block_ptr, available, &consumed, error);
- } else {
- consumed = available;
- result = SR_SUCCESS;
- }
- switch (result) {
- case SR_ERROR:
- return result;
- case SR_BLOCK:
- case SR_EOS:
- ASSERT(false);
- *error = 0; // TODO: make errors
- return SR_ERROR;
- case SR_SUCCESS:
- block_consumed += consumed;
- break;
- }
- }
-
- current_bytes_ -= block_consumed;
- if (current_bytes_ == 0) {
- // The remainder of the block is zeroed
- result = ProcessEmptyBlock(block_consumed, error);
- if (SR_SUCCESS != result)
- return result;
- delete current_;
- current_ = NULL;
- next_block_ = NB_FILE_HEADER;
- }
-
- } else {
- ASSERT(false);
- }
-
- block_pos_ = 0;
- return SR_SUCCESS;
-}
-
-StreamResult TarStream::ProcessEmptyBlock(size_t start, int* error) {
- ASSERT(NULL != error);
- ASSERT(M_NONE != mode_);
- if (M_READ == mode_) {
- memset(block_ + start, 0, BLOCK_SIZE - start);
- } else {
- if (!talk_base::memory_check(block_ + start, 0, BLOCK_SIZE - start)) {
- *error = 0; // TODO: make errors
- return SR_ERROR;
- }
- }
- return SR_SUCCESS;
-}
-
-StreamResult TarStream::ReadNextFile(int* error) {
- ASSERT(NULL != error);
- ASSERT(M_READ == mode_);
- ASSERT(NB_FILE_HEADER == next_block_);
- ASSERT(BLOCK_SIZE == block_pos_);
- ASSERT(NULL == current_);
-
- // ReadNextFile conducts a depth-first recursive search through the directory
- // tree. find_ maintains a stack of open directory handles, which
- // corresponds to our current position in the tree. At any point, the
- // directory at the top (front) of the stack is being enumerated. If a
- // directory is found, it is opened and pushed onto the top of the stack.
- // When a directory enumeration completes, that directory is popped off the
- // top of the stack.
-
- // Note: Since ReadNextFile can only return one block of data at a time, we
- // cannot simultaneously return the entry for a directory, and the entry for
- // the first element in that directory at the same time. In this case, we
- // push a NULL entry onto the find_ stack, which indicates that the next
- // iteration should begin enumeration of the "new" directory.
- StreamResult result = SR_SUCCESS;
- while (BLOCK_SIZE == block_pos_) {
- ASSERT(!find_.empty());
-
- if (NULL != find_.front()) {
- if (find_.front()->Next()) {
- result = ProcessNextEntry(find_.front(), error);
- if (SR_SUCCESS != result) {
- return result;
- }
- continue;
- }
- delete(find_.front());
- } else {
- Pathname pattern(root_folder_);
- pattern.AppendFolder(subfolder_);
- find_.front() = new DirectoryIterator();
- if (find_.front()->Iterate(pattern.pathname())) {
- result = ProcessNextEntry(find_.front(), error);
- if (SR_SUCCESS != result) {
- return result;
- }
- continue;
- }
- // TODO: should this be an error?
- LOG_F(LS_WARNING) << "Couldn't open folder: " << pattern.pathname();
- }
-
- find_.pop_front();
- subfolder_ = Pathname(subfolder_).parent_folder();
-
- if (find_.empty()) {
- return SR_EOS;
- }
- }
-
- ASSERT(0 == block_pos_);
- return SR_SUCCESS;
-}
-
-StreamResult TarStream::WriteNextFile(int* error) {
- ASSERT(NULL != error);
- ASSERT(M_WRITE == mode_);
- ASSERT(NB_FILE_HEADER == next_block_);
- ASSERT(BLOCK_SIZE == block_pos_);
- ASSERT(NULL == current_);
- ASSERT(0 == current_bytes_);
-
- std::string pathname, link, linked_name, magic, mversion;
- size_t file_size, modify_time, unused, checksum;
-
- size_t block_data = 0;
- ReadFieldS(block_data, 100, &pathname);
- ReadFieldN(block_data, 8, &unused); // mode
- ReadFieldN(block_data, 8, &unused); // owner uid
- ReadFieldN(block_data, 8, &unused); // owner gid
- ReadFieldN(block_data, 12, &file_size);
- ReadFieldN(block_data, 12, &modify_time);
- ReadFieldN(block_data, 8, &checksum);
- if (checksum == 0)
- block_data -= 8; // back-compatiblity
- ReadFieldS(block_data, 1, &link);
- ReadFieldS(block_data, 100, &linked_name); // name of linked file
- ReadFieldS(block_data, 6, &magic);
- ReadFieldS(block_data, 2, &mversion);
-
- if (pathname.empty())
- return SR_EOS;
-
- std::string user, group, dev_major, dev_minor, prefix;
- if (magic == "ustar" || magic == "ustar ") {
- ReadFieldS(block_data, 32, &user);
- ReadFieldS(block_data, 32, &group);
- ReadFieldS(block_data, 8, &dev_major);
- ReadFieldS(block_data, 8, &dev_minor);
- ReadFieldS(block_data, 155, &prefix);
-
- pathname = prefix + pathname;
- }
-
- // Rest of the block must be empty
- StreamResult result = ProcessEmptyBlock(block_data, error);
- if (SR_SUCCESS != result) {
- return result;
- }
-
- Pathname archive_path(pathname);
- archive_path.SetFolderDelimiter('/');
- archive_path.Normalize();
-
- bool is_folder = archive_path.filename().empty();
- if (is_folder) {
- ASSERT(NB_FILE_HEADER == next_block_);
- ASSERT(0 == file_size);
- } else if (file_size > 0) {
- // We assign current_bytes_ because we must skip over the upcoming data
- // segments, regardless of whether we want to write them.
- next_block_ = NB_DATA;
- current_bytes_ = file_size;
- }
-
- if (!CheckFilter(archive_path.pathname())) {
- // If it's a directory, we will ignore it and all children by nature of
- // filter prefix matching. If it is a file, we will ignore it because
- // current_ is NULL.
- return SR_SUCCESS;
- }
-
- // Sanity checks:
- // 1) No .. path segments
- if (archive_path.pathname().find("../") != std::string::npos) {
- LOG_F(LS_WARNING) << "Skipping path with .. entry: "
- << archive_path.pathname();
- return SR_SUCCESS;
- }
- // 2) No drive letters
- if (archive_path.pathname().find(':') != std::string::npos) {
- LOG_F(LS_WARNING) << "Skipping path with drive letter: "
- << archive_path.pathname();
- return SR_SUCCESS;
- }
- // 3) No absolute paths
- if (archive_path.pathname().find("//") != std::string::npos) {
- LOG_F(LS_WARNING) << "Skipping absolute path: "
- << archive_path.pathname();
- return SR_SUCCESS;
- }
-
- Pathname local_path(root_folder_);
- local_path.AppendPathname(archive_path.pathname());
- local_path.Normalize();
-
- if (is_folder) {
- if (!Filesystem::CreateFolder(local_path)) {
- LOG_F(LS_WARNING) << "Couldn't create folder: " << local_path.pathname();
- *error = 0; // TODO
- return SR_ERROR;
- }
- } else {
- FileStream* stream = new FileStream;
-
- if (!stream->Open(local_path.pathname().c_str(), "wb")) {
- LOG_F(LS_WARNING) << "Couldn't create file: " << local_path.pathname();
- *error = 0; // TODO
- delete stream;
- return SR_ERROR;
- }
- if (file_size > 0) {
- current_ = stream;
- } else {
- stream->Close();
- delete stream;
- }
- }
-
- SignalNextEntry(archive_path.filename(), current_bytes_);
-
-
- return SR_SUCCESS;
-}
-
-StreamResult TarStream::ProcessNextEntry(const DirectoryIterator *data, int *error) {
- ASSERT(M_READ == mode_);
- ASSERT(NB_FILE_HEADER == next_block_);
- ASSERT(BLOCK_SIZE == block_pos_);
- ASSERT(NULL == current_);
- ASSERT(0 == current_bytes_);
-
- if (data->IsDirectory() &&
- (data->Name() == "." || data->Name() == ".."))
- return SR_SUCCESS;
-
- Pathname archive_path;
- archive_path.SetFolder(subfolder_);
- if (data->IsDirectory()) {
- archive_path.AppendFolder(data->Name());
- } else {
- archive_path.SetFilename(data->Name());
- }
- archive_path.SetFolderDelimiter('/');
- archive_path.Normalize();
-
- if (!CheckFilter(archive_path.pathname()))
- return SR_SUCCESS;
-
- if (archive_path.pathname().length() > 255) {
- // Cannot send a file name longer than 255 (yet)
- return SR_ERROR;
- }
-
- Pathname local_path(root_folder_);
- local_path.AppendPathname(archive_path.pathname());
- local_path.Normalize();
-
- if (data->IsDirectory()) {
- // Note: the NULL handle indicates that we need to open the folder next
- // time.
- find_.push_front(NULL);
- subfolder_ = archive_path.pathname();
- } else {
- FileStream* stream = new FileStream;
- if (!stream->Open(local_path.pathname().c_str(), "rb")) {
- // TODO: Should this be an error?
- LOG_F(LS_WARNING) << "Couldn't open file: " << local_path.pathname();
- delete stream;
- return SR_SUCCESS;
- }
- current_ = stream;
- current_bytes_ = data->FileSize();
- }
-
- time_t modify_time = data->FileModifyTime();
-
- std::string pathname = archive_path.pathname();
- std::string magic, user, group, dev_major, dev_minor, prefix;
- std::string name = pathname;
- bool ustar = false;
- if (name.length() > 100) {
- ustar = true;
- // Put last 100 characters into the name, and rest in prefix
- size_t path_length = pathname.length();
- prefix = pathname.substr(0, path_length - 100);
- name = pathname.substr(path_length - 100);
- }
-
- size_t block_data = 0;
- memset(block_, 0, BLOCK_SIZE);
- WriteFieldS(block_data, 100, name.c_str());
- WriteFieldS(block_data, 8, data->IsDirectory() ? "777" : "666"); // mode
- WriteFieldS(block_data, 8, "5"); // owner uid
- WriteFieldS(block_data, 8, "5"); // owner gid
- WriteFieldN(block_data, 12, current_bytes_);
- WriteFieldN(block_data, 12, modify_time);
- WriteFieldS(block_data, 8, " "); // Checksum. To be filled in later.
- WriteFieldS(block_data, 1, data->IsDirectory() ? "5" : "0"); // link indicator (0 == normal file, 5 == directory)
- WriteFieldS(block_data, 100, ""); // name of linked file
-
- if (ustar) {
- WriteFieldS(block_data, 6, "ustar");
- WriteFieldS(block_data, 2, "");
- WriteFieldS(block_data, 32, user.c_str());
- WriteFieldS(block_data, 32, group.c_str());
- WriteFieldS(block_data, 8, dev_major.c_str());
- WriteFieldS(block_data, 8, dev_minor.c_str());
- WriteFieldS(block_data, 155, prefix.c_str());
- }
-
- // Rest of the block must be empty
- StreamResult result = ProcessEmptyBlock(block_data, error);
- WriteChecksum();
-
- block_pos_ = 0;
- if (current_bytes_ > 0) {
- next_block_ = data->IsDirectory() ? NB_FILE_HEADER : NB_DATA;
- }
-
- SignalNextEntry(archive_path.filename(), current_bytes_);
-
- return result;
-}
-
-void TarStream::WriteChecksum() {
- unsigned int sum = 0;
-
- for (int i = 0; i < BLOCK_SIZE; i++)
- sum += static_cast<unsigned char>(block_[i]);
-
- sprintf(block_ + 148, "%06o", sum);
-}
-
-bool TarStream::CheckFilter(const std::string& pathname) {
- if (filters_.empty())
- return true;
-
- // pathname is allowed when there is a filter which:
- // A) Equals name
- // B) Matches a folder prefix of name
- for (size_t i=0; i<filters_.size(); ++i) {
- const std::string& filter = filters_[i];
- // Make sure the filter is a prefix of name
- if (_strnicmp(pathname.c_str(), filter.data(), filter.length()) != 0)
- continue;
-
- // If the filter is not a directory, must match exactly
- if (!Pathname::IsFolderDelimiter(filter[filter.length()-1])
- && (filter.length() != pathname.length()))
- continue;
-
- return true;
- }
-
- return false;
-}
-
-void TarStream::WriteFieldN(size_t& pos, size_t max_len, size_t numeric_field) {
- WriteFieldF(pos, max_len, "%.*o", max_len - 1, numeric_field);
-}
-
-void TarStream::WriteFieldS(size_t& pos, size_t max_len,
- const char* string_field) {
- ASSERT(pos + max_len <= BLOCK_SIZE);
- size_t len = strlen(string_field);
- size_t use_len = _min(len, max_len);
- memcpy(block_ + pos, string_field, use_len);
- pos += max_len;
-}
-
-void TarStream::WriteFieldF(size_t& pos, size_t max_len,
- const char* format, ...) {
- va_list args;
- va_start(args, format);
- char buffer[BLOCK_SIZE];
- vsprintfn(buffer, ARRAY_SIZE(buffer), format, args);
- WriteFieldS(pos, max_len, buffer);
- va_end(args);
-}
-
-void TarStream::ReadFieldN(size_t& pos, size_t max_len, size_t* numeric_field) {
- ASSERT(NULL != numeric_field);
- std::string buffer;
- ReadFieldS(pos, max_len, &buffer);
-
- int value;
- if (!buffer.empty() && (1 == sscanf(buffer.c_str(), "%o", &value))) {
- *numeric_field = value;
- } else {
- *numeric_field = 0;
- }
-}
-
-void TarStream::ReadFieldS(size_t& pos, size_t max_len,
- std::string* string_field) {
- ASSERT(NULL != string_field);
- ASSERT(pos + max_len <= BLOCK_SIZE);
- size_t value_len = talk_base::strlenn(block_ + pos, max_len);
- string_field->assign(block_ + pos, value_len);
- ASSERT(talk_base::memory_check(block_ + pos + value_len,
- 0,
- max_len - value_len));
- pos += max_len;
-}
diff --git a/talk/base/tarstream.h b/talk/base/tarstream.h
deleted file mode 100755
index 772fb14..0000000
--- a/talk/base/tarstream.h
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef TALK_APP_WIN32_TARSTREAM_H__
-#define TALK_APP_WIN32_TARSTREAM_H__
-
-#include <string>
-#include <vector>
-#include "talk/base/fileutils.h"
-#include "talk/base/sigslot.h"
-#include "talk/base/stream.h"
-
-namespace talk_base {
-
-///////////////////////////////////////////////////////////////////////////////
-// TarStream - acts as a source or sink for a tar-encoded collection of files
-// and directories. Operates synchronously.
-///////////////////////////////////////////////////////////////////////////////
-
-class TarStream : public StreamInterface {
- public:
- TarStream();
- virtual ~TarStream();
-
- // AddFilter is used to limit the elements which will be read or written.
- // In general, all members of the parent folder are read, and all members
- // of a tarfile are written. However, if any filters are added, only those
- // items (and their contents, in the case of folders) are processed. Filters
- // must be added before opening the stream.
- bool AddFilter(const std::string& pathname);
-
- // 'folder' is parent of the tar contents. All paths will be evaluated
- // relative to it. When 'read' is true, the specified folder will be
- // traversed, and a tar stream will be generated (via Read). Otherwise, a
- // tar stream is consumed (via Write), and files and folders will be created.
- bool Open(const std::string& folder, bool read);
-
- virtual talk_base::StreamState GetState() const;
- virtual talk_base::StreamResult Read(void* buffer, size_t buffer_len,
- size_t* read, int* error);
- virtual talk_base::StreamResult Write(const void* data, size_t data_len,
- size_t* written, int* error);
- virtual void Close();
-
- virtual bool GetSize(size_t* size) const { return false; }
- virtual bool ReserveSize(size_t size) { return true; }
- virtual bool Rewind() { return false; }
-
- // Every time a new entry header is read/written, this signal is fired with
- // the entry's name and size.
- sigslot::signal2<const std::string&, size_t> SignalNextEntry;
-
- private:
- typedef std::list<DirectoryIterator*> DirectoryList;
- enum ModeType { M_NONE, M_READ, M_WRITE };
- enum NextBlockType { NB_NONE, NB_FILE_HEADER, NB_DATA, NB_TRAILER };
- enum { BLOCK_SIZE = 512 };
-
- talk_base::StreamResult ProcessBuffer(void* buffer, size_t buffer_len,
- size_t* consumed, int* error);
- talk_base::StreamResult ProcessNextBlock(int* error);
- talk_base::StreamResult ProcessEmptyBlock(size_t start, int* error);
- talk_base::StreamResult ReadNextFile(int* error);
- talk_base::StreamResult WriteNextFile(int* error);
-
- talk_base::StreamResult ProcessNextEntry(const DirectoryIterator *data,
- int *error);
-
- // Determine whether the given entry is allowed by our filters
- bool CheckFilter(const std::string& pathname);
-
- void WriteFieldN(size_t& pos, size_t max_len, size_t numeric_field);
- void WriteFieldS(size_t& pos, size_t max_len, const char* string_field);
- void WriteFieldF(size_t& pos, size_t max_len, const char* format, ...);
-
- void ReadFieldN(size_t& pos, size_t max_len, size_t* numeric_field);
- void ReadFieldS(size_t& pos, size_t max_len, std::string* string_field);
-
- void WriteChecksum(void);
-
- // Files and/or folders that should be processed
- std::vector<std::string> filters_;
- // Folder passed to Open
- std::string root_folder_;
- // Open for read or write?
- ModeType mode_;
- // The expected type of the next block
- NextBlockType next_block_;
- // The partial contents of the current block
- char block_[BLOCK_SIZE];
- size_t block_pos_;
- // The file which is currently being read or written
- talk_base::FileStream* current_;
- // Bytes remaining to be processed for current_
- size_t current_bytes_;
- // Note: the following variables are used in M_READ mode only.
- // Stack of open directory handles, representing depth-first search
- DirectoryList find_;
- // Subfolder path corresponding to current position in the directory tree
- std::string subfolder_;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-} // namespace talk_base
-
-#endif // TALK_APP_WIN32_TARSTREAM_H__
diff --git a/talk/base/task.cc b/talk/base/task.cc
old mode 100755
new mode 100644
index d7e0e82..ad17438
--- a/talk/base/task.cc
+++ b/talk/base/task.cc
@@ -25,8 +25,6 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <algorithm>
-
#include "talk/base/task.h"
#include "talk/base/common.h"
#include "talk/base/taskrunner.h"
@@ -35,35 +33,40 @@
int32 Task::unique_id_seed_ = 0;
-Task::Task(Task *parent)
- : state_(STATE_INIT),
- parent_(parent),
+Task::Task(TaskParent *parent)
+ : TaskParent(this, parent),
+ state_(STATE_INIT),
blocked_(false),
done_(false),
aborted_(false),
busy_(false),
error_(false),
- child_error_(false),
start_time_(0),
- timeout_seconds_(0),
timeout_time_(0),
+ timeout_seconds_(0),
timeout_suspended_(false) {
- children_.reset(new ChildSet());
- runner_ = ((parent == NULL) ?
- reinterpret_cast<TaskRunner *>(this) :
- parent->GetRunner());
- if (parent_ != NULL) {
- parent_->AddChild(this);
- }
-
unique_id_ = unique_id_seed_++;
// sanity check that we didn't roll-over our id seed
ASSERT(unique_id_ < unique_id_seed_);
}
+Task::~Task() {
+ // Is this task being deleted in the correct manner?
+ ASSERT(!done_ || GetRunner()->is_ok_to_delete(this));
+ ASSERT(state_ == STATE_INIT || done_);
+ ASSERT(state_ == STATE_INIT || blocked_);
+
+ // If the task is being deleted without being done, it
+ // means that it hasn't been removed from its parent.
+ // This happens if a task is deleted outside of TaskRunner.
+ if (!done_) {
+ Stop();
+ }
+}
+
int64 Task::CurrentTime() {
- return runner_->CurrentTime();
+ return GetRunner()->CurrentTime();
}
int64 Task::ElapsedTime() {
@@ -82,11 +85,11 @@
void Task::Step() {
if (done_) {
-#ifdef DEBUG
+#ifdef _DEBUG
// we do not know how !blocked_ happens when done_ - should be impossible.
// But it causes problems, so in retail build, we force blocked_, and
// under debug we assert.
- assert(blocked_);
+ ASSERT(blocked_);
#else
blocked_ = true;
#endif
@@ -100,7 +103,12 @@
blocked_ = true;
// obsolete - an errored task is not considered done now
// SignalDone();
+
Stop();
+#ifdef _DEBUG
+ // verify that stop removed this from its parent
+ ASSERT(!parent()->IsChildTask(this));
+#endif
return;
}
@@ -132,22 +140,43 @@
if (done_) {
// obsolete - call this yourself
// SignalDone();
+
Stop();
+#if _DEBUG
+ // verify that stop removed this from its parent
+ ASSERT(!parent()->IsChildTask(this));
+#endif
blocked_ = true;
}
}
void Task::Abort(bool nowake) {
- if (aborted_ || done_)
+ // Why only check for done_ (instead of "aborted_ || done_")?
+ //
+ // If aborted_ && !done_, it means the logic for aborting still
+ // needs to be executed (because busy_ must have been true when
+ // Abort() was previously called).
+ if (done_)
return;
aborted_ = true;
if (!busy_) {
done_ = true;
blocked_ = true;
error_ = true;
+
+ // "done_" is set before calling "Stop()" to ensure that this code
+ // doesn't execute more than once (recursively) for the same task.
Stop();
- if (!nowake)
- Wake(); // to self-delete
+#ifdef _DEBUG
+ // verify that stop removed this from its parent
+ ASSERT(!parent()->IsChildTask(this));
+#endif
+ if (!nowake) {
+ // WakeTasks to self-delete.
+ // Don't call Wake() because it is a no-op after "done_" is set.
+ // Even if Wake() did run, it clears "blocked_" which isn't desireable.
+ GetRunner()->WakeTasks();
+ }
}
}
@@ -214,43 +243,9 @@
return newstate;
}
-void Task::AddChild(Task *child) {
- children_->insert(child);
-}
-
-bool Task::AllChildrenDone() {
- for (ChildSet::iterator it = children_->begin();
- it != children_->end();
- ++it) {
- if (!(*it)->IsDone())
- return false;
- }
- return true;
-}
-
-bool Task::AnyChildError() {
- return child_error_;
-}
-
-void Task::AbortAllChildren() {
- if (children_->size() > 0) {
- ChildSet copy = *children_;
- for (ChildSet::iterator it = copy.begin(); it != copy.end(); ++it) {
- (*it)->Abort(true); // Note we do not wake
- }
- }
-}
-
void Task::Stop() {
// No need to wake because we're either awake or in abort
- AbortAllChildren();
- parent_->OnChildStopped(this);
-}
-
-void Task::OnChildStopped(Task *child) {
- if (child->HasError())
- child_error_ = true;
- children_->erase(child);
+ TaskParent::OnStopped(this);
}
void Task::set_timeout_seconds(const int timeout_seconds) {
@@ -261,10 +256,11 @@
bool Task::TimedOut() {
return timeout_seconds_ &&
timeout_time_ &&
- CurrentTime() > timeout_time_;
+ CurrentTime() >= timeout_time_;
}
void Task::ResetTimeout() {
+ int64 previous_timeout_time = timeout_time_;
bool timeout_allowed = (state_ != STATE_INIT)
&& (state_ != STATE_DONE)
&& (state_ != STATE_ERROR);
@@ -274,12 +270,13 @@
else
timeout_time_ = 0;
- GetRunner()->UpdateTaskTimeout(this);
+ GetRunner()->UpdateTaskTimeout(this, previous_timeout_time);
}
void Task::ClearTimeout() {
+ int64 previous_timeout_time = timeout_time_;
timeout_time_ = 0;
- GetRunner()->UpdateTaskTimeout(this);
+ GetRunner()->UpdateTaskTimeout(this, previous_timeout_time);
}
void Task::SuspendTimeout() {
diff --git a/talk/base/task.h b/talk/base/task.h
old mode 100755
new mode 100644
index b524ab7..10e6f5c
--- a/talk/base/task.h
+++ b/talk/base/task.h
@@ -29,9 +29,10 @@
#define TALK_BASE_TASK_H__
#include <string>
-#include "talk/base/scoped_ptr.h"
#include "talk/base/basictypes.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/base/sigslot.h"
+#include "talk/base/taskparent.h"
/////////////////////////////////////////////////////////////////////
//
@@ -52,13 +53,13 @@
// STATE_BLOCKED. If you _could_ do anything, do not return
// STATE_BLOCKED - even if you end up in the same state, return
// STATE_mysamestate. When you are done, return STATE_DONE and then the
-// task will self-delete sometimea afterwards.
+// task will self-delete sometime afterwards.
//
// (2) It helps you avoid all those reentrancy problems when you chain
// too many triggers on one thread. Basically if you want to tell a task
// to process something for you, you feed your task some information and
// then you Wake() it. Don't tell it to process it right away. If it
-// might be working on something as you send it infomration, you may want
+// might be working on something as you send it information, you may want
// to have a queue in the task.
//
// (3) Finally it helps manage parent tasks and children. If a parent
@@ -105,19 +106,13 @@
namespace talk_base {
-class TaskRunner;
-
-// A task executes a sequence of steps
-
-class Task;
-class RootTask;
-
-class Task {
+// Executes a sequence of steps
+class Task : public TaskParent {
public:
- Task(Task *parent);
- virtual ~Task() {}
+ Task(TaskParent *parent);
+ virtual ~Task();
- int32 get_unique_id() { return unique_id_; }
+ int32 unique_id() { return unique_id_; }
void Start();
void Step();
@@ -127,20 +122,13 @@
bool IsDone() const { return done_; }
int64 ElapsedTime();
- Task *GetParent() { return parent_; }
- TaskRunner *GetRunner() { return runner_; }
- virtual Task *GetParent(int code) { return parent_->GetParent(code); }
-
// Called from outside to stop task without any more callbacks
void Abort(bool nowake = false);
- // For managing children
- bool AllChildrenDone();
- bool AnyChildError();
-
bool TimedOut();
- int64 get_timeout_time() { return timeout_time_; }
+ int64 timeout_time() const { return timeout_time_; }
+ int timeout_seconds() const { return timeout_seconds_; }
void set_timeout_seconds(int timeout_seconds);
sigslot::signal0<> SignalTimeout;
@@ -171,10 +159,6 @@
virtual int ProcessStart() = 0;
virtual int ProcessResponse() { return STATE_DONE; }
- // for managing children (if any)
- void AddChild(Task *child);
- void AbortAllChildren();
-
void ResetTimeout();
void ClearTimeout();
@@ -189,30 +173,22 @@
private:
void Done();
- void OnChildStopped(Task *child);
int state_;
- Task *parent_;
- TaskRunner *runner_;
bool blocked_;
bool done_;
bool aborted_;
bool busy_;
bool error_;
- bool child_error_;
int64 start_time_;
int64 timeout_time_;
int timeout_seconds_;
bool timeout_suspended_;
int32 unique_id_;
-
+
static int32 unique_id_seed_;
-
- // for managing children
- typedef std::set<Task *> ChildSet;
- scoped_ptr<ChildSet> children_;
};
-} // namespace talk_base
+} // namespace talk_base
#endif // TALK_BASE_TASK_H__
diff --git a/talk/base/taskparent.cc b/talk/base/taskparent.cc
new file mode 100644
index 0000000..f05ee82
--- /dev/null
+++ b/talk/base/taskparent.cc
@@ -0,0 +1,112 @@
+/*
+ * libjingle
+ * Copyright 2004--2006, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <algorithm>
+
+#include "talk/base/taskparent.h"
+
+#include "talk/base/task.h"
+#include "talk/base/taskrunner.h"
+
+namespace talk_base {
+
+TaskParent::TaskParent(Task* derived_instance, TaskParent *parent)
+ : parent_(parent) {
+ ASSERT(derived_instance != NULL);
+ ASSERT(parent != NULL);
+ runner_ = parent->GetRunner();
+ parent_->AddChild(derived_instance);
+ Initialize();
+}
+
+TaskParent::TaskParent(TaskRunner *derived_instance)
+ : parent_(NULL),
+ runner_(derived_instance) {
+ ASSERT(derived_instance != NULL);
+ Initialize();
+}
+
+// Does common initialization of member variables
+void TaskParent::Initialize() {
+ children_.reset(new ChildSet());
+ child_error_ = false;
+}
+
+void TaskParent::AddChild(Task *child) {
+ children_->insert(child);
+}
+
+#ifdef _DEBUG
+bool TaskParent::IsChildTask(Task *task) {
+ ASSERT(task != NULL);
+ return task->parent_ == this && children_->find(task) != children_->end();
+}
+#endif
+
+bool TaskParent::AllChildrenDone() {
+ for (ChildSet::iterator it = children_->begin();
+ it != children_->end();
+ ++it) {
+ if (!(*it)->IsDone())
+ return false;
+ }
+ return true;
+}
+
+bool TaskParent::AnyChildError() {
+ return child_error_;
+}
+
+void TaskParent::AbortAllChildren() {
+ if (children_->size() > 0) {
+#ifdef _DEBUG
+ runner_->IncrementAbortCount();
+#endif
+
+ ChildSet copy = *children_;
+ for (ChildSet::iterator it = copy.begin(); it != copy.end(); ++it) {
+ (*it)->Abort(true); // Note we do not wake
+ }
+
+#ifdef _DEBUG
+ runner_->DecrementAbortCount();
+#endif
+ }
+}
+
+void TaskParent::OnStopped(Task *task) {
+ AbortAllChildren();
+ parent_->OnChildStopped(task);
+}
+
+void TaskParent::OnChildStopped(Task *child) {
+ if (child->HasError())
+ child_error_ = true;
+ children_->erase(child);
+}
+
+} // namespace talk_base
diff --git a/talk/base/taskparent.h b/talk/base/taskparent.h
new file mode 100644
index 0000000..a6c5795
--- /dev/null
+++ b/talk/base/taskparent.h
@@ -0,0 +1,89 @@
+/*
+ * libjingle
+ * Copyright 2004--2006, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_TASKPARENT_H__
+#define TALK_BASE_TASKPARENT_H__
+
+#include <set>
+
+#include "talk/base/basictypes.h"
+#include "talk/base/scoped_ptr.h"
+
+namespace talk_base {
+
+class Task;
+class TaskRunner;
+
+class TaskParent {
+ public:
+ TaskParent(Task *derived_instance, TaskParent *parent);
+ explicit TaskParent(TaskRunner *derived_instance);
+ virtual ~TaskParent() { }
+
+ TaskParent *GetParent() { return parent_; }
+ TaskRunner *GetRunner() { return runner_; }
+
+ // Retrieves a parent that corresponds to the given "code". The code
+ // should be defined in a unique manner for the given subtree. This
+ // method will crash (when the parent_ is NULL) if there is no corresponding
+ // parent.
+ //
+ // Example use:
+ // XmppClient* client =
+ // static_cast<XmppClient*>(parent->GetParent(XMPP_CLIENT_TASK_CODE));
+ virtual TaskParent *GetParent(int code) { return parent_->GetParent(code); }
+
+ bool AllChildrenDone();
+ bool AnyChildError();
+#ifdef _DEBUG
+ bool IsChildTask(Task *task);
+#endif
+
+ protected:
+ void OnStopped(Task *task);
+ void AbortAllChildren();
+ TaskParent *parent() {
+ return parent_;
+ }
+
+ private:
+ void Initialize();
+ void OnChildStopped(Task *child);
+ void AddChild(Task *child);
+
+ TaskParent *parent_;
+ TaskRunner *runner_;
+ bool child_error_;
+ typedef std::set<Task *> ChildSet;
+ scoped_ptr<ChildSet> children_;
+ DISALLOW_EVIL_CONSTRUCTORS(TaskParent);
+};
+
+
+} // namespace talk_base
+
+#endif // TALK_BASE_TASKPARENT_H__
diff --git a/talk/base/taskrunner.cc b/talk/base/taskrunner.cc
old mode 100755
new mode 100644
index 050171f..0c0816c
--- a/talk/base/taskrunner.cc
+++ b/talk/base/taskrunner.cc
@@ -37,15 +37,20 @@
namespace talk_base {
TaskRunner::TaskRunner()
- : Task(NULL),
- tasks_running_(false),
- next_timeout_task_(NULL) {
+ : TaskParent(this),
+ next_timeout_task_(NULL),
+ tasks_running_(false)
+#ifdef _DEBUG
+ , abort_count_(0),
+ deleting_task_(NULL)
+#endif
+{
}
TaskRunner::~TaskRunner() {
// this kills and deletes children silently!
AbortAllChildren();
- RunTasks();
+ InternalRunTasks(true);
}
void TaskRunner::StartTask(Task * task) {
@@ -53,12 +58,22 @@
// the task we just started could be about to timeout --
// make sure our "next timeout task" is correct
- UpdateTaskTimeout(task);
+ UpdateTaskTimeout(task, 0);
WakeTasks();
}
void TaskRunner::RunTasks() {
+ InternalRunTasks(false);
+}
+
+void TaskRunner::InternalRunTasks(bool in_destructor) {
+ // This shouldn't run while an abort is happening.
+ // If that occurs, then tasks may be deleted in this method,
+ // but pointers to them will still be in the
+ // "ChildSet copy" in TaskParent::AbortAllChildren.
+ // Subsequent use of those task may cause data corruption or crashes.
+ ASSERT(!abort_count_);
// Running continues until all tasks are Blocked (ok for a small # of tasks)
if (tasks_running_) {
return; // don't reenter
@@ -66,6 +81,8 @@
tasks_running_ = true;
+ int64 previous_timeout_time = next_task_timeout();
+
int did_run = true;
while (did_run) {
did_run = false;
@@ -83,12 +100,18 @@
if (tasks_[i]->IsDone()) {
Task* task = tasks_[i];
if (next_timeout_task_ &&
- task->get_unique_id() == next_timeout_task_->get_unique_id()) {
+ task->unique_id() == next_timeout_task_->unique_id()) {
next_timeout_task_ = NULL;
need_timeout_recalc = true;
}
+#ifdef _DEBUG
+ deleting_task_ = task;
+#endif
delete task;
+#ifdef _DEBUG
+ deleting_task_ = NULL;
+#endif
tasks_[i] = NULL;
}
}
@@ -103,19 +126,39 @@
if (need_timeout_recalc)
RecalcNextTimeout(NULL);
+ // Make sure that adjustments are done to account
+ // for any timeout changes (but don't call this
+ // while being destroyed since it calls a pure virtual function).
+ if (!in_destructor)
+ CheckForTimeoutChange(previous_timeout_time);
+
tasks_running_ = false;
}
void TaskRunner::PollTasks() {
// see if our "next potentially timed-out task" has indeed timed out.
// If it has, wake it up, then queue up the next task in line
- if (next_timeout_task_ &&
+ // Repeat while we have new timed-out tasks.
+ // TODO: We need to guard against WakeTasks not updating
+ // next_timeout_task_. Maybe also add documentation in the header file once
+ // we understand this code better.
+ Task* old_timeout_task = NULL;
+ while (next_timeout_task_ &&
+ old_timeout_task != next_timeout_task_ &&
next_timeout_task_->TimedOut()) {
+ old_timeout_task = next_timeout_task_;
next_timeout_task_->Wake();
WakeTasks();
}
}
+int64 TaskRunner::next_task_timeout() const {
+ if (next_timeout_task_) {
+ return next_timeout_task_->timeout_time();
+ }
+ return 0;
+}
+
// this function gets called frequently -- when each task changes
// state to something other than DONE, ERROR or BLOCKED, it calls
// ResetTimeout(), which will call this function to make sure that
@@ -123,26 +166,38 @@
// prevents RecalcNextTimeout() from getting called in most cases,
// effectively making the task scheduler O-1 instead of O-N
-void TaskRunner::UpdateTaskTimeout(Task *task) {
+void TaskRunner::UpdateTaskTimeout(Task* task,
+ int64 previous_task_timeout_time) {
ASSERT(task != NULL);
+ int64 previous_timeout_time = next_task_timeout();
+ bool task_is_timeout_task = next_timeout_task_ != NULL &&
+ task->unique_id() == next_timeout_task_->unique_id();
+ if (task_is_timeout_task) {
+ previous_timeout_time = previous_task_timeout_time;
+ }
// if the relevant task has a timeout, then
// check to see if it's closer than the current
// "about to timeout" task
- if (task->get_timeout_time()) {
+ if (task->timeout_time()) {
if (next_timeout_task_ == NULL ||
- (task->get_timeout_time() <=
- next_timeout_task_->get_timeout_time())) {
+ (task->timeout_time() <= next_timeout_task_->timeout_time())) {
next_timeout_task_ = task;
}
- } else if (next_timeout_task_ != NULL &&
- task->get_unique_id() == next_timeout_task_->get_unique_id()) {
+ } else if (task_is_timeout_task) {
// otherwise, if the task doesn't have a timeout,
// and it used to be our "about to timeout" task,
// walk through all the tasks looking for the real
// "about to timeout" task
RecalcNextTimeout(task);
}
+
+ // Note when task_running_, then the running routine
+ // (TaskRunner::InternalRunTasks) is responsible for calling
+ // CheckForTimeoutChange.
+ if (!tasks_running_) {
+ CheckForTimeoutChange(previous_timeout_time);
+ }
}
void TaskRunner::RecalcNextTimeout(Task *exclude_task) {
@@ -158,19 +213,29 @@
for (size_t i = 0; i < tasks_.size(); ++i) {
Task *task = tasks_[i];
// if the task isn't complete, and it actually has a timeout time
- if (!task->IsDone() &&
- (task->get_timeout_time() > 0))
+ if (!task->IsDone() && (task->timeout_time() > 0))
// if it doesn't match our "exclude" task
if (exclude_task == NULL ||
- exclude_task->get_unique_id() != task->get_unique_id())
+ exclude_task->unique_id() != task->unique_id())
// if its timeout time is sooner than our current timeout time
if (next_timeout_time == 0 ||
- task->get_timeout_time() <= next_timeout_time) {
+ task->timeout_time() <= next_timeout_time) {
// set this task as our next-to-timeout
- next_timeout_time = task->get_timeout_time();
+ next_timeout_time = task->timeout_time();
next_timeout_task_ = task;
}
}
}
+void TaskRunner::CheckForTimeoutChange(int64 previous_timeout_time) {
+ int64 next_timeout = next_task_timeout();
+ bool timeout_change = (previous_timeout_time == 0 && next_timeout != 0) ||
+ next_timeout < previous_timeout_time ||
+ (previous_timeout_time <= CurrentTime() &&
+ previous_timeout_time != next_timeout);
+ if (timeout_change) {
+ OnTimeoutChange();
+ }
+}
+
} // namespace talk_base
diff --git a/talk/base/taskrunner.h b/talk/base/taskrunner.h
old mode 100755
new mode 100644
index e1c5ed6..f34a609
--- a/talk/base/taskrunner.h
+++ b/talk/base/taskrunner.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2006, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -30,41 +30,84 @@
#include <vector>
+#include "talk/base/basictypes.h"
#include "talk/base/sigslot.h"
-#include "talk/base/task.h"
+#include "talk/base/taskparent.h"
namespace talk_base {
-
class Task;
const int64 kSecToMsec = 1000;
const int64 kMsecTo100ns = 10000;
const int64 kSecTo100ns = kSecToMsec * kMsecTo100ns;
-class TaskRunner : public Task, public sigslot::has_slots<> {
+class TaskRunner : public TaskParent, public sigslot::has_slots<> {
public:
TaskRunner();
virtual ~TaskRunner();
virtual void WakeTasks() = 0;
- // This method returns the current time in 100ns units since 1/1/1601. This
- // Is the GetSystemTimeAsFileTime method on windows.
+ // Returns the current time in 100ns units. It is used for
+ // determining timeouts. The origin is not important, only
+ // the units and that rollover while the computer is running.
+ //
+ // On Windows, GetSystemTimeAsFileTime is the typical implementation.
virtual int64 CurrentTime() = 0 ;
void StartTask(Task *task);
void RunTasks();
void PollTasks();
- void UpdateTaskTimeout(Task *task);
+ void UpdateTaskTimeout(Task *task, int64 previous_task_timeout_time);
- // dummy state machine - never run.
- virtual int ProcessStart() { return STATE_DONE; }
+#ifdef _DEBUG
+ bool is_ok_to_delete(Task* task) {
+ return task == deleting_task_;
+ }
+
+ void IncrementAbortCount() {
+ ++abort_count_;
+ }
+
+ void DecrementAbortCount() {
+ --abort_count_;
+ }
+#endif
+
+ // Returns the next absolute time when a task times out
+ // OR "0" if there is no next timeout.
+ int64 next_task_timeout() const;
+
+ protected:
+ // The primary usage of this method is to know if
+ // a callback timer needs to be set-up or adjusted.
+ // This method will be called
+ // * when the next_task_timeout() becomes a smaller value OR
+ // * when next_task_timeout() has changed values and the previous
+ // value is in the past.
+ //
+ // If the next_task_timeout moves to the future, this method will *not*
+ // get called (because it subclass should check next_task_timeout()
+ // when its timer goes off up to see if it needs to set-up a new timer).
+ //
+ // Note that this maybe called conservatively. In that it may be
+ // called when no time change has happened.
+ virtual void OnTimeoutChange() {
+ // by default, do nothing.
+ }
private:
+ void InternalRunTasks(bool in_destructor);
+ void CheckForTimeoutChange(int64 previous_timeout_time);
+
std::vector<Task *> tasks_;
Task *next_timeout_task_;
bool tasks_running_;
+#ifdef _DEBUG
+ int abort_count_;
+ Task* deleting_task_;
+#endif
void RecalcNextTimeout(Task *exclude_task);
};
diff --git a/talk/base/testclient.cc b/talk/base/testclient.cc
deleted file mode 100755
index ecb45fc..0000000
--- a/talk/base/testclient.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-#include <cassert>
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-#include "talk/base/testclient.h"
-#include "talk/base/time.h"
-
-
-namespace talk_base {
-
-// DESIGN: Each packet received is posted to ourselves as a message on the
-// thread given to the constructor. When we receive the message, we
-// put it into a list of packets. We take the latter step so that we
-// can wait for a new packet to arrive by calling Get/Dispatch on the
-// thread.
-
-TestClient::TestClient(AsyncPacketSocket* socket, Thread* thread)
- : thread_(thread), socket_(socket) {
- if (!thread_)
- thread_ = Thread::Current();
- packets_ = new std::vector<Packet*>();
- socket_->SignalReadPacket.connect(this, &TestClient::OnPacket);
-}
-
-TestClient::~TestClient() {
- delete socket_;
- for (unsigned i = 0; i < packets_->size(); i++)
- delete (*packets_)[i];
-}
-
-void TestClient::Send(const char* buf, size_t size) {
- int result = socket_->Send(buf, size);
- if (result < 0) {
- std::cerr << "send: " << std::strerror(errno) << std::endl;
- exit(1);
- }
-}
-
-void TestClient::SendTo(
- const char* buf, size_t size, const SocketAddress& dest) {
- int result = socket_->SendTo(buf, size, dest);
- if (result < 0) {
- std::cerr << "sendto: " << std::strerror(errno) << std::endl;
- exit(1);
- }
-}
-
-void TestClient::OnPacket(
- const char* buf, size_t size, const SocketAddress& remote_addr,
- AsyncPacketSocket* socket) {
- thread_->Post(this, 0, new Packet(remote_addr, buf, size));
-}
-
-void TestClient::OnMessage(Message *pmsg) {
- assert(pmsg->pdata);
- packets_->push_back(new Packet(*static_cast<Packet*>(pmsg->pdata)));
-}
-
-TestClient::Packet* TestClient::NextPacket() {
-
- // If no packets are currently available, we go into a get/dispatch loop for
- // at most 1 second. If, during the loop, a packet arrives, then we can stop
- // early and return it.
- //
- // Note that the case where no packet arrives is important. We often want to
- // test that a packet does not arrive.
-
- if (packets_->size() == 0) {
- uint32 msNext = 1000;
- uint32 msEnd = GetMillisecondCount() + msNext;
-
- while (true) {
- Message msg;
- if (!thread_->Get(&msg, msNext))
- break;
- thread_->Dispatch(&msg);
-
- uint32 msCur = GetMillisecondCount();
- if (msCur >= msEnd)
- break;
- msNext = msEnd - msCur;
-
- if (packets_->size() > 0)
- break;
- }
- }
-
- if (packets_->size() == 0) {
- return 0;
- } else {
- // Return the first packet placed in the queue.
- Packet* packet = packets_->front();
- packets_->erase(packets_->begin());
- return packet;
- }
-}
-
-void TestClient::CheckNextPacket(
- const char* buf, size_t size, SocketAddress* addr) {
- Packet* packet = NextPacket();
- assert(packet);
- assert(packet->size == size);
- assert(std::memcmp(packet->buf, buf, size) == 0);
- if (addr)
- *addr = packet->addr;
-}
-
-void TestClient::CheckNoPacket() {
- Packet* packet = NextPacket();
- assert(!packet);
-}
-
-TestClient::Packet::Packet(const SocketAddress& a, const char* b, size_t s)
- : addr(a), buf(0), size(s) {
- buf = new char[size];
- memcpy(buf, b, size);
-}
-
-TestClient::Packet::Packet(const Packet& p)
- : addr(p.addr), buf(0), size(p.size) {
- buf = new char[size];
- memcpy(buf, p.buf, size);
-}
-
-TestClient::Packet::~Packet() {
- delete buf;
-}
-
-} // namespace talk_base
diff --git a/talk/base/testclient.h b/talk/base/testclient.h
deleted file mode 100755
index 012e858..0000000
--- a/talk/base/testclient.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_BASE_TESTCLIENT_H__
-#define TALK_BASE_TESTCLIENT_H__
-
-#include "talk/base/asyncudpsocket.h"
-#include "talk/base/thread.h"
-#include <vector>
-
-namespace talk_base {
-
-class TestClient : public MessageHandler, public sigslot::has_slots<> {
-public:
- // Creates a client that will send and receive with the given socket and
- // will post itself messages with the given thread.
- TestClient(AsyncPacketSocket* socket, Thread* thread = 0);
- ~TestClient();
-
- // Sends using the clients socket.
- void Send(const char* buf, size_t size);
-
- // Sends using the clients socket to the given destination.
- void SendTo(const char* buf, size_t size, const SocketAddress& dest);
-
- // Records the contents of a packet that was received.
- struct Packet : public MessageData {
- Packet(const SocketAddress& a, const char* b, size_t s);
- Packet(const Packet& p);
- virtual ~Packet();
-
- SocketAddress addr;
- char* buf;
- size_t size;
- };
-
- // Returns the next packet received by the client or 0 if none is received
- // within a reasonable amount of time. The caller must delete the packet
- // when done with it.
- Packet* NextPacket();
-
- // Checks that the next packet has the given contents. Returns the remote
- // address that the packet was sent from.
- void CheckNextPacket(const char* buf, size_t len, SocketAddress* addr);
-
- // Checks that no packets have arrived or will arrive in the next second.
- void CheckNoPacket();
-
- // Messagehandler:
- void OnMessage(Message *pmsg);
-
-private:
- Thread* thread_;
- AsyncPacketSocket* socket_;
- std::vector<Packet*>* packets_;
-
- // Slot for packets read on the socket.
- void OnPacket(
- const char* buf, size_t len, const SocketAddress& remote_addr,
- AsyncPacketSocket* socket);
-};
-
-} // namespace talk_base
-
-#endif // TALK_BASE_TESTCLIENT_H__
diff --git a/talk/base/thread.cc b/talk/base/thread.cc
old mode 100755
new mode 100644
index 8fc45e1..28f3e48
--- a/talk/base/thread.cc
+++ b/talk/base/thread.cc
@@ -2,41 +2,49 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef POSIX
-extern "C" {
-#include <sys/time.h>
-}
+#include "talk/base/thread.h"
+
+#if defined(WIN32)
+#include <comdef.h>
+#elif defined(POSIX)
+#include <time.h>
#endif
#include "talk/base/common.h"
#include "talk/base/logging.h"
-#include "talk/base/thread.h"
+#include "talk/base/stringutils.h"
#include "talk/base/time.h"
-#define MSDEV_SET_THREAD_NAME 0x406D1388
+#ifdef OSX_USE_COCOA
+#ifndef OSX
+#error OSX_USE_COCOA is defined but not OSX
+#endif
+#include "talk/base/maccocoathreadhelper.h"
+#include "talk/base/scoped_autorelease_pool.h"
+#endif
namespace talk_base {
@@ -47,17 +55,26 @@
ThreadManager::ThreadManager() {
pthread_key_create(&key_, NULL);
- main_thread_ = new Thread();
- SetCurrent(main_thread_);
+ main_thread_ = WrapCurrentThread();
+#if defined(OSX_USE_COCOA)
+ InitCocoaMultiThreading();
+#endif
}
ThreadManager::~ThreadManager() {
+#ifdef OSX_USE_COCOA
+ // This is called during exit, at which point apparently no NSAutoreleasePools
+ // are available; but we might still need them to do cleanup (or we get the
+ // "no autoreleasepool in place, just leaking" warning when exiting).
+ ScopedAutoreleasePool pool;
+#endif
+ UnwrapCurrentThread();
+ // Unwrap deletes main_thread_ automatically.
pthread_key_delete(key_);
- delete main_thread_;
}
Thread *ThreadManager::CurrentThread() {
- return (Thread *)pthread_getspecific(key_);
+ return static_cast<Thread *>(pthread_getspecific(key_));
}
void ThreadManager::SetCurrent(Thread *thread) {
@@ -70,17 +87,16 @@
ThreadManager::ThreadManager() {
key_ = TlsAlloc();
- main_thread_ = new Thread();
- SetCurrent(main_thread_);
+ main_thread_ = WrapCurrentThread();
}
ThreadManager::~ThreadManager() {
+ UnwrapCurrentThread();
TlsFree(key_);
- delete main_thread_;
}
Thread *ThreadManager::CurrentThread() {
- return (Thread *)TlsGetValue(key_);
+ return static_cast<Thread *>(TlsGetValue(key_));
}
void ThreadManager::SetCurrent(Thread *thread) {
@@ -88,6 +104,44 @@
}
#endif
+// static
+Thread *ThreadManager::WrapCurrentThread() {
+ Thread* result = CurrentThread();
+ if (NULL == result) {
+ result = new Thread();
+#if defined(WIN32)
+ // We explicitly ask for no rights other than synchronization.
+ // This gives us the best chance of succeeding.
+ result->thread_ = OpenThread(SYNCHRONIZE, FALSE, GetCurrentThreadId());
+ if (!result->thread_)
+ LOG_GLE(LS_ERROR) << "Unable to get handle to thread.";
+#elif defined(POSIX)
+ result->thread_ = pthread_self();
+#endif
+ result->owned_ = false;
+ result->started_ = true;
+ SetCurrent(result);
+ }
+
+ return result;
+}
+
+// static
+void ThreadManager::UnwrapCurrentThread() {
+ Thread* t = CurrentThread();
+ if (t && !(t->IsOwned())) {
+ // Clears the platform-specific thread-specific storage.
+ SetCurrent(NULL);
+#ifdef WIN32
+ if (!CloseHandle(t->thread_)) {
+ LOG_GLE(LS_ERROR) << "When unwrapping thread, failed to close handle.";
+ }
+#endif
+ t->started_ = false;
+ delete t;
+ }
+}
+
void ThreadManager::Add(Thread *thread) {
CritScope cs(&crit_);
threads_.push_back(thread);
@@ -95,13 +149,34 @@
void ThreadManager::Remove(Thread *thread) {
CritScope cs(&crit_);
- threads_.erase(std::remove(threads_.begin(), threads_.end(), thread), threads_.end());
+ threads_.erase(std::remove(threads_.begin(), threads_.end(), thread),
+ threads_.end());
}
-Thread::Thread(SocketServer* ss) : MessageQueue(ss), priority_(PRIORITY_NORMAL) {
+void ThreadManager::StopAllThreads_() {
+ // TODO: In order to properly implement, Threads need to be ref-counted.
+ CritScope cs(&g_thmgr.crit_);
+ for (size_t i = 0; i < g_thmgr.threads_.size(); ++i) {
+ g_thmgr.threads_[i]->Stop();
+ }
+}
+
+struct ThreadInit {
+ Thread* thread;
+ Runnable* runnable;
+};
+
+Thread::Thread(SocketServer* ss)
+ : MessageQueue(ss),
+ priority_(PRIORITY_NORMAL),
+ started_(false),
+ has_sends_(false),
+#if defined(WIN32)
+ thread_(NULL),
+#endif
+ owned_(true) {
g_thmgr.Add(this);
- started_ = false;
- has_sends_ = false;
+ SetName("Thread", this); // default name
}
Thread::~Thread() {
@@ -111,91 +186,172 @@
g_thmgr.Remove(this);
}
-#ifdef POSIX
-void Thread::Start() {
+bool Thread::SleepMs(int milliseconds) {
+#ifdef WIN32
+ ::Sleep(milliseconds);
+ return true;
+#else
+ // POSIX has both a usleep() and a nanosleep(), but the former is deprecated,
+ // so we use nanosleep() even though it has greater precision than necessary.
+ struct timespec ts;
+ ts.tv_sec = milliseconds / 1000;
+ ts.tv_nsec = (milliseconds % 1000) * 1000000;
+ int ret = nanosleep(&ts, NULL);
+ if (ret != 0) {
+ LOG_ERR(LS_WARNING) << "nanosleep() returning early";
+ return false;
+ }
+ return true;
+#endif
+}
+
+bool Thread::SetName(const std::string& name, const void* obj) {
+ if (started_) return false;
+ name_ = name;
+ if (obj) {
+ char buf[16];
+ sprintfn(buf, sizeof(buf), " 0x%p", obj);
+ name_ += buf;
+ }
+ return true;
+}
+
+bool Thread::SetPriority(ThreadPriority priority) {
+ if (started_) return false;
+ priority_ = priority;
+ return true;
+}
+
+bool Thread::Start(Runnable* runnable) {
+ ASSERT(owned_);
+ if (!owned_) return false;
+ ASSERT(!started_);
+ if (started_) return false;
+
+ ThreadInit* init = new ThreadInit;
+ init->thread = this;
+ init->runnable = runnable;
+#if defined(WIN32)
+ DWORD flags = 0;
+ if (priority_ != PRIORITY_NORMAL) {
+ flags = CREATE_SUSPENDED;
+ }
+ thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreRun, init, flags,
+ NULL);
+ if (thread_) {
+ if (priority_ != PRIORITY_NORMAL) {
+ if (priority_ == PRIORITY_HIGH) {
+ ::SetThreadPriority(thread_, THREAD_PRIORITY_HIGHEST);
+ } else if (priority_ == PRIORITY_ABOVE_NORMAL) {
+ ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL);
+ } else if (priority_ == PRIORITY_IDLE) {
+ ::SetThreadPriority(thread_, THREAD_PRIORITY_IDLE);
+ }
+ ::ResumeThread(thread_);
+ }
+ } else {
+ return false;
+ }
+#elif defined(POSIX)
pthread_attr_t attr;
pthread_attr_init(&attr);
- if (priority_ == PRIORITY_IDLE) {
- struct sched_param param;
- pthread_attr_getschedparam(&attr, ¶m);
- param.sched_priority = 15; // +15 =
- pthread_attr_setschedparam(&attr, ¶m);
+ if (priority_ != PRIORITY_NORMAL) {
+ if (priority_ == PRIORITY_IDLE) {
+ // There is no POSIX-standard way to set a below-normal priority for an
+ // individual thread (only whole process), so let's not support it.
+ LOG(LS_WARNING) << "PRIORITY_IDLE not supported";
+ } else {
+ // Set real-time round-robin policy.
+ if (pthread_attr_setschedpolicy(&attr, SCHED_RR) != 0) {
+ LOG(LS_ERROR) << "pthread_attr_setschedpolicy";
+ }
+ struct sched_param param;
+ if (pthread_attr_getschedparam(&attr, ¶m) != 0) {
+ LOG(LS_ERROR) << "pthread_attr_getschedparam";
+ } else {
+ // The numbers here are arbitrary.
+ if (priority_ == PRIORITY_HIGH) {
+ param.sched_priority = 6; // 6 = HIGH
+ } else {
+ ASSERT(priority_ == PRIORITY_ABOVE_NORMAL);
+ param.sched_priority = 4; // 4 = ABOVE_NORMAL
+ }
+ if (pthread_attr_setschedparam(&attr, ¶m) != 0) {
+ LOG(LS_ERROR) << "pthread_attr_setschedparam";
+ }
+ }
+ }
}
- pthread_create(&thread_, &attr, PreRun, this);
+ int error_code = pthread_create(&thread_, &attr, PreRun, init);
+ if (0 != error_code) {
+ LOG(LS_ERROR) << "Unable to create pthread, error " << error_code;
+ return false;
+ }
+#endif
started_ = true;
+ return true;
}
void Thread::Join() {
if (started_) {
+ ASSERT(!IsCurrent());
+#if defined(WIN32)
+ WaitForSingleObject(thread_, INFINITE);
+ CloseHandle(thread_);
+ thread_ = NULL;
+#elif defined(POSIX)
void *pv;
pthread_join(thread_, &pv);
+#endif
+ started_ = false;
}
}
-#endif
#ifdef WIN32
-
-typedef struct tagTHREADNAME_INFO
-{
+// As seen on MSDN.
+// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
+#define MSDEV_SET_THREAD_NAME 0x406D1388
+typedef struct tagTHREADNAME_INFO {
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} THREADNAME_INFO;
-void SetThreadName( DWORD dwThreadID, LPCSTR szThreadName)
-{
+void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName) {
THREADNAME_INFO info;
- {
- info.dwType = 0x1000;
- info.szName = szThreadName;
- info.dwThreadID = dwThreadID;
- info.dwFlags = 0;
- }
- __try
- {
- RaiseException(MSDEV_SET_THREAD_NAME, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
- }
- __except(EXCEPTION_CONTINUE_EXECUTION)
- {
- }
-}
+ info.dwType = 0x1000;
+ info.szName = szThreadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
-void Thread::Start() {
- DWORD flags = 0;
- if (priority_ != PRIORITY_NORMAL) {
- flags = CREATE_SUSPENDED;
+ __try {
+ RaiseException(MSDEV_SET_THREAD_NAME, 0, sizeof(info) / sizeof(DWORD),
+ reinterpret_cast<DWORD*>(&info));
}
- thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreRun, this, flags, NULL);
- if (thread_) {
- if (priority_ != PRIORITY_NORMAL) {
- if (priority_ == PRIORITY_IDLE) {
- ::SetThreadPriority(thread_, THREAD_PRIORITY_IDLE);
- }
- ::ResumeThread(thread_);
- }
+ __except(EXCEPTION_CONTINUE_EXECUTION) {
}
- started_ = true;
}
+#endif // WIN32
-void Thread::Join() {
- if (started_) {
- WaitForSingleObject(thread_, INFINITE);
- CloseHandle(thread_);
- started_ = false;
- }
-}
+void* Thread::PreRun(void* pv) {
+ ThreadInit* init = static_cast<ThreadInit*>(pv);
+ ThreadManager::SetCurrent(init->thread);
+#if defined(WIN32)
+ SetThreadName(GetCurrentThreadId(), init->thread->name_.c_str());
+#elif defined(POSIX)
+ // TODO: See if naming exists for pthreads.
#endif
-
-void *Thread::PreRun(void *pv) {
- Thread *thread = (Thread *)pv;
- ThreadManager::SetCurrent(thread);
-#if defined(WIN32) && defined(_DEBUG)
- char buf[256];
- _snprintf(buf, sizeof(buf), "Thread 0x%.8x", thread);
- SetThreadName(GetCurrentThreadId(), buf);
+#ifdef OSX_USE_COCOA
+ // Make sure the new thread has an autoreleasepool
+ ScopedAutoreleasePool pool;
#endif
- thread->Run();
+ if (init->runnable) {
+ init->runnable->Run(init->thread);
+ } else {
+ init->thread->Run();
+ }
+ delete init;
return NULL;
}
@@ -203,8 +359,12 @@
ProcessMessages(kForever);
}
+bool Thread::IsOwned() {
+ return owned_;
+}
+
void Thread::Stop() {
- MessageQueue::Stop();
+ MessageQueue::Quit();
Join();
}
@@ -225,7 +385,7 @@
return;
}
- AutoThread thread;
+ AutoThread thread;
Thread *current_thread = Thread::Current();
ASSERT(current_thread != NULL); // AutoThread ensures this
@@ -293,7 +453,8 @@
crit_.Leave();
}
-void Thread::Clear(MessageHandler *phandler, uint32 id) {
+void Thread::Clear(MessageHandler *phandler, uint32 id,
+ MessageList* removed) {
CritScope cs(&crit_);
// Remove messages on sendlist_ with phandler
@@ -303,37 +464,37 @@
std::list<_SendMessage>::iterator iter = sendlist_.begin();
while (iter != sendlist_.end()) {
_SendMessage smsg = *iter;
- if (phandler == NULL || smsg.msg.phandler == phandler) {
- if (id == (uint32)-1 || smsg.msg.message_id == id) {
- iter = sendlist_.erase(iter);
- *smsg.ready = true;
- smsg.thread->socketserver()->WakeUp();
- continue;
+ if (smsg.msg.Match(phandler, id)) {
+ if (removed) {
+ removed->push_back(smsg.msg);
+ } else {
+ delete smsg.msg.pdata;
}
+ iter = sendlist_.erase(iter);
+ *smsg.ready = true;
+ smsg.thread->socketserver()->WakeUp();
+ continue;
}
++iter;
}
- MessageQueue::Clear(phandler, id);
+ MessageQueue::Clear(phandler, id, removed);
}
bool Thread::ProcessMessages(int cmsLoop) {
- uint32 msEnd;
- if (cmsLoop != kForever)
- msEnd = GetMillisecondCount() + cmsLoop;
+ uint32 msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop);
int cmsNext = cmsLoop;
while (true) {
Message msg;
if (!Get(&msg, cmsNext))
- return false;
+ return !IsQuitting();
Dispatch(&msg);
-
+
if (cmsLoop != kForever) {
- uint32 msCur = GetMillisecondCount();
- if (msCur >= msEnd)
+ cmsNext = TimeUntil(msEnd);
+ if (cmsNext < 0)
return true;
- cmsNext = msEnd - msCur;
}
}
}
@@ -350,4 +511,17 @@
}
}
-} // namespace talk_base
+#ifdef WIN32
+void ComThread::Run() {
+ HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ ASSERT(SUCCEEDED(hr));
+ if (SUCCEEDED(hr)) {
+ Thread::Run();
+ CoUninitialize();
+ } else {
+ LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr;
+ }
+}
+#endif
+
+} // namespace talk_base
diff --git a/talk/base/thread.h b/talk/base/thread.h
old mode 100755
new mode 100644
index 5da0aed..36b9e76
--- a/talk/base/thread.h
+++ b/talk/base/thread.h
@@ -2,34 +2,35 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_THREAD_H__
-#define TALK_BASE_THREAD_H__
+#ifndef TALK_BASE_THREAD_H_
+#define TALK_BASE_THREAD_H_
#include <algorithm>
#include <list>
+#include <string>
#include <vector>
#ifdef POSIX
@@ -56,13 +57,31 @@
void Add(Thread *thread);
void Remove(Thread *thread);
+ // Returns a thread object with its thread_ ivar set
+ // to whatever the OS uses to represent the thread.
+ // If there already *is* a Thread object corresponding to this thread,
+ // this method will return that. Otherwise it creates a new Thread
+ // object whose wrapped() method will return true, and whose
+ // handle will, on Win32, be opened with only synchronization privileges -
+ // if you need more privilegs, rather than changing this method, please
+ // write additional code to adjust the privileges, or call a different
+ // factory method of your own devising, because this one gets used in
+ // unexpected contexts (like inside browser plugins) and it would be a
+ // shame to break it. It is also conceivable on Win32 that we won't even
+ // be able to get synchronization privileges, in which case the result
+ // will have a NULL handle.
+ static Thread *WrapCurrentThread();
+ static void UnwrapCurrentThread();
+
+ static void StopAllThreads_(); // Experimental
+
private:
Thread *main_thread_;
std::vector<Thread *> threads_;
CriticalSection crit_;
#ifdef POSIX
- static pthread_key_t key_;
+ static pthread_key_t key_;
#endif
#ifdef WIN32
@@ -80,27 +99,53 @@
};
enum ThreadPriority {
+ PRIORITY_HIGH,
+ PRIORITY_ABOVE_NORMAL,
PRIORITY_NORMAL,
PRIORITY_IDLE,
};
+class Runnable {
+ public:
+ virtual ~Runnable() {}
+ virtual void Run(Thread* thread) = 0;
+};
+
class Thread : public MessageQueue {
public:
- Thread(SocketServer* ss = 0);
+ Thread(SocketServer* ss = NULL);
virtual ~Thread();
static inline Thread* Current() {
return ThreadManager::CurrentThread();
}
- inline bool IsCurrent() const {
+
+ bool IsCurrent() const {
return (ThreadManager::CurrentThread() == this);
}
- void SetPriority(ThreadPriority priority) {
- priority_ = priority;
- }
-
- virtual void Start();
+ // Sleeps the calling thread for the specified number of milliseconds, during
+ // which time no processing is performed. Returns false if sleeping was
+ // interrupted by a signal (POSIX only).
+ static bool SleepMs(int millis);
+
+ // Sets the thread's name, for debugging. Must be called before Start().
+ // If |obj| is non-NULL, its value is appended to |name|.
+ const std::string& name() const { return name_; }
+ bool SetName(const std::string& name, const void* obj);
+
+ // Sets the thread's priority. Must be called before Start().
+ ThreadPriority priority() const { return priority_; }
+ bool SetPriority(ThreadPriority priority);
+
+ // Starts the execution of the thread.
+ bool started() const { return started_; }
+ bool Start(Runnable* runnable = NULL);
+
+ // Tells the thread to stop and waits until it is joined.
+ // Never call Stop on the current thread. Instead use the inherited Quit
+ // function which will exit the base MessageQueue without terminating the
+ // underlying OS thread.
virtual void Stop();
// By default, Thread::Run() calls ProcessMessages(kForever). To do other
@@ -112,7 +157,8 @@
MessageData *pdata = NULL);
// From MessageQueue
- virtual void Clear(MessageHandler *phandler, uint32 id = (uint32)-1);
+ virtual void Clear(MessageHandler *phandler, uint32 id = MQID_ANY,
+ MessageList* removed = NULL);
virtual void ReceiveSends();
// ProcessMessages will process I/O and dispatch messages until:
@@ -120,17 +166,31 @@
// 2) Stop() is called (returns false)
bool ProcessMessages(int cms);
+ // Returns true if this is a thread that we created using the standard
+ // constructor, false if it was created by a call to
+ // ThreadManager::WrapCurrentThread(). The main thread of an application
+ // is generally not owned, since the OS representation of the thread
+ // obviously exists before we can get to it.
+ // You cannot call Start on non-owned threads.
+ bool IsOwned();
+
#ifdef WIN32
HANDLE GetHandle() {
return thread_;
}
+#elif POSIX
+ pthread_t GetPThread() {
+ return thread_;
+ }
#endif
private:
static void *PreRun(void *pv);
+ // Blocks the calling thread until this thread has terminated.
void Join();
std::list<_SendMessage> sendlist_;
+ std::string name_;
ThreadPriority priority_;
bool started_;
bool has_sends_;
@@ -143,6 +203,8 @@
HANDLE thread_;
#endif
+ bool owned_;
+
friend class ThreadManager;
};
@@ -156,6 +218,28 @@
virtual ~AutoThread();
};
-} // namespace talk_base
+// Win32 extension for threads that need to use COM
+#ifdef WIN32
+class ComThread : public Thread {
+ protected:
+ virtual void Run();
+};
+#endif
-#endif // TALK_BASE_THREAD_H__
+// Provides an easy way to install/uninstall a socketserver on a thread.
+class SocketServerScope {
+ public:
+ explicit SocketServerScope(SocketServer* ss) {
+ old_ss_ = Thread::Current()->socketserver();
+ Thread::Current()->set_socketserver(ss);
+ }
+ ~SocketServerScope() {
+ Thread::Current()->set_socketserver(old_ss_);
+ }
+ private:
+ SocketServer* old_ss_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_THREAD_H_
diff --git a/talk/base/time.cc b/talk/base/time.cc
old mode 100755
new mode 100644
index d4a61ac..f5fa6db
--- a/talk/base/time.cc
+++ b/talk/base/time.cc
@@ -25,16 +25,26 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <iostream>
-#include <cstdlib>
-#include <cstring>
+#ifdef POSIX
+#include <sys/time.h>
+#endif
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "talk/base/common.h"
#include "talk/base/time.h"
+#define EFFICIENT_IMPLEMENTATION 1
+
namespace talk_base {
+const uint32 LAST = 0xFFFFFFFF;
+const uint32 HALF = 0x80000000;
+
#ifdef POSIX
-#include <sys/time.h>
uint32 Time() {
struct timeval tv;
gettimeofday(&tv, 0);
@@ -43,7 +53,6 @@
#endif
#ifdef WIN32
-#include <windows.h>
uint32 Time() {
return GetTickCount();
}
@@ -58,11 +67,13 @@
// Make sure someone calls it so that it gets initialized
static uint32 ignore = StartTime();
-uint32 ElapsedTime() {
- return TimeDiff(Time(), StartTime());
+uint32 TimeAfter(int32 elapsed) {
+ ASSERT(elapsed >= 0);
+ ASSERT(static_cast<uint32>(elapsed) < HALF);
+ return Time() + elapsed;
}
-bool TimeIsBetween(uint32 later, uint32 middle, uint32 earlier) {
+bool TimeIsBetween(uint32 earlier, uint32 middle, uint32 later) {
if (earlier <= later) {
return ((earlier <= middle) && (middle <= later));
} else {
@@ -70,10 +81,32 @@
}
}
+bool TimeIsLaterOrEqual(uint32 earlier, uint32 later) {
+#if EFFICIENT_IMPLEMENTATION
+ int32 diff = later - earlier;
+ return (diff >= 0 && static_cast<uint32>(diff) < HALF);
+#else
+ const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF);
+ return later_or_equal;
+#endif
+}
+
+bool TimeIsLater(uint32 earlier, uint32 later) {
+#if EFFICIENT_IMPLEMENTATION
+ int32 diff = later - earlier;
+ return (diff > 0 && static_cast<uint32>(diff) < HALF);
+#else
+ const bool earlier_or_equal = TimeIsBetween(later, earlier, later + HALF);
+ return !earlier_or_equal;
+#endif
+}
+
int32 TimeDiff(uint32 later, uint32 earlier) {
- uint32 LAST = 0xFFFFFFFF;
- uint32 HALF = 0x80000000;
- if (TimeIsBetween(earlier + HALF, later, earlier)) {
+#if EFFICIENT_IMPLEMENTATION
+ return later - earlier;
+#else
+ const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF);
+ if (later_or_equal) {
if (earlier <= later) {
return static_cast<long>(later - earlier);
} else {
@@ -86,6 +119,7 @@
return -static_cast<long>(earlier + (LAST - later) + 1);
}
}
+#endif
}
} // namespace talk_base
diff --git a/talk/base/time.h b/talk/base/time.h
old mode 100755
new mode 100644
index 9088aae..eca0e4e
--- a/talk/base/time.h
+++ b/talk/base/time.h
@@ -28,26 +28,54 @@
#ifndef TALK_BASE_TIME_H__
#define TALK_BASE_TIME_H__
+#ifndef WIN32
+#include_next <time.h>
+#endif
+
#include "talk/base/basictypes.h"
namespace talk_base {
+typedef uint32 TimeStamp;
+
// Returns the current time in milliseconds.
uint32 Time();
// Approximate time when the program started.
uint32 StartTime();
-// Elapsed milliseconds since StartTime()
-uint32 ElapsedTime();
-
-// TODO: Delete this old version.
-#define GetMillisecondCount Time
+// Returns a future timestamp, 'elapsed' milliseconds from now.
+uint32 TimeAfter(int32 elapsed);
// Comparisons between time values, which can wrap around.
-bool TimeIsBetween(uint32 later, uint32 middle, uint32 earlier);
+bool TimeIsBetween(uint32 earlier, uint32 middle, uint32 later); // Inclusive
+bool TimeIsLaterOrEqual(uint32 earlier, uint32 later); // Inclusive
+bool TimeIsLater(uint32 earlier, uint32 later); // Exclusive
+
+// Returns the later of two timestamps.
+inline uint32 TimeMax(uint32 ts1, uint32 ts2) {
+ return TimeIsLaterOrEqual(ts1, ts2) ? ts2 : ts1;
+}
+
+// Returns the earlier of two timestamps.
+inline uint32 TimeMin(uint32 ts1, uint32 ts2) {
+ return TimeIsLaterOrEqual(ts1, ts2) ? ts1 : ts2;
+}
+
+// Number of milliseconds that would elapse between 'earlier' and 'later'
+// timestamps. The value is negative if 'later' occurs before 'earlier'.
int32 TimeDiff(uint32 later, uint32 earlier);
+// The number of milliseconds that have elapsed since 'earlier'.
+inline int32 TimeSince(uint32 earlier) {
+ return TimeDiff(Time(), earlier);
+}
+
+// The number of milliseconds that will elapse between now and 'later'.
+inline int32 TimeUntil(uint32 later) {
+ return TimeDiff(later, Time());
+}
+
} // namespace talk_base
#endif // TALK_BASE_TIME_H__
diff --git a/talk/base/unixfilesystem.cc b/talk/base/unixfilesystem.cc
old mode 100755
new mode 100644
index 2c2732f..436dc2f
--- a/talk/base/unixfilesystem.cc
+++ b/talk/base/unixfilesystem.cc
@@ -24,27 +24,82 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
-#include <cassert>
-
-#include "talk/base/basicdefs.h"
-#include "talk/base/pathutils.h"
-#include "talk/base/fileutils.h"
-#include "talk/base/stringutils.h"
-#include "talk/base/stream.h"
#include "talk/base/unixfilesystem.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef OSX
+#include <Carbon/Carbon.h>
+#include <IOKit/IOCFBundle.h>
+#include <sys/statvfs.h>
+#include "talk/base/macutils.h"
+#endif // OSX
+
+#if defined(POSIX) && !defined(OSX)
+#include <sys/types.h>
+#ifdef ANDROID
+#include <sys/statfs.h>
+#else
+#include <sys/statvfs.h>
+#endif // ANDROID
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+#endif // POSIX && !OSX
+
+#ifdef LINUX
+#include <ctype.h>
+#include <algorithm>
+#endif
+
+#include "talk/base/fileutils.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/stream.h"
+#include "talk/base/stringutils.h"
+
+#ifdef ANDROID
+namespace {
+// Android does not have a concept of a single temp dir shared by all
+// because resource are scarse on a phone. Instead each app gets some
+// space on the sdcard under a path that is given at runtime by the
+// system.
+// The disk allocation feature is still work in progress so currently
+// we return a hardcoded a path on the sdcard. In the future, we
+// should do a JNI call to get that info from the context.
+// TODO: Replace hardcoded path with a query to the Context
+// object to get the equivalents of '/tmp' and '~/.'
+
+// @return the folder for libjingle. Some extra path (typically
+// Google/<app name>) will be added.
+const char* GetAndroidAppDataFolder() {
+ return "/sdcard";
+}
+
+// @return the tmp folder to be used. Some extra path will be added to
+// that base folder.
+const char* GetAndroidTempFolder() {
+ return "/sdcard";
+}
+
+} // anonymous namespace
+#endif
+
namespace talk_base {
-bool UnixFilesystem::CreateFolderI(const Pathname &path) {
- LOG(LS_INFO) << "Creating folder: " << path.pathname();
- int len = path.pathname().length();
- const char *pathname = path.pathname().c_str();
- if ((len <= 0) || (pathname[len-1] != '/'))
+std::string UnixFilesystem::app_temp_path_;
+
+bool UnixFilesystem::CreateFolder(const Pathname &path) {
+ std::string pathname(path.pathname());
+ int len = pathname.length();
+ if ((len == 0) || (pathname[len - 1] != '/'))
return false;
+
struct stat st;
- int res = ::stat(pathname, &st);
+ int res = ::stat(pathname.c_str(), &st);
if (res == 0) {
// Something exists at this location, check if it is a directory
return S_ISDIR(st.st_mode) != 0;
@@ -52,84 +107,124 @@
// Unexpected error
return false;
}
+
// Directory doesn't exist, look up one directory level
do {
--len;
- } while ((len > 0) && (pathname[len-1] !='/'));
+ } while ((len > 0) && (pathname[len - 1] != '/'));
- char *newstring = new char[len+1];
- strncpy(newstring, pathname, len);
- newstring[len] = '\0';
-
- if (!CreateFolder(Pathname(newstring))) {
- delete[] newstring;
+ if (!CreateFolder(Pathname(pathname.substr(0, len)))) {
return false;
}
- delete[] newstring;
- std::string no_slash(path.pathname(), 0, path.pathname().length()-1);
-
- return (::mkdir(no_slash.c_str(), 0755) == 0);
- }
-FileStream *UnixFilesystem::OpenFileI(const Pathname &filename,
- const std::string &mode) {
- talk_base::FileStream *fs = new talk_base::FileStream();
- if (fs)
- fs->Open(filename.pathname().c_str(), mode.c_str());
+ LOG(LS_INFO) << "Creating folder: " << pathname;
+ return (0 == ::mkdir(pathname.c_str(), 0755));
+}
+
+FileStream *UnixFilesystem::OpenFile(const Pathname &filename,
+ const std::string &mode) {
+ FileStream *fs = new FileStream();
+ if (fs && !fs->Open(filename.pathname().c_str(), mode.c_str())) {
+ delete fs;
+ fs = NULL;
+ }
return fs;
}
-bool UnixFilesystem::DeleteFileI(const Pathname &filename) {
- LOG(LS_INFO) << "Deleting " << filename.pathname();
-
- if (IsFolder(filename)) {
- Pathname dir;
- dir.SetFolder(filename.pathname());
- DirectoryIterator di;
- di.Iterate(dir.pathname());
- while(di.Next()) {
- if (di.Name() == "." || di.Name() == "..")
- continue;
- Pathname subdir;
- subdir.SetFolder(filename.pathname());
- subdir.SetFilename(di.Name());
-
- if (!DeleteFile(subdir.pathname()))
- return false;
- }
- std::string no_slash(filename.pathname(), 0, filename.pathname().length()-1);
- return ::rmdir(no_slash.c_str()) == 0;
- }
- return ::unlink(filename.pathname().c_str()) == 0;
-}
-
-bool UnixFilesystem::GetTemporaryFolderI(Pathname &pathname, bool create,
- const std::string *append) {
- pathname.SetPathname("/tmp");
- if (append) {
- pathname.AppendFolder(*append);
- if (create)
- CreateFolder(pathname);
+bool UnixFilesystem::CreatePrivateFile(const Pathname &filename) {
+ int fd = open(filename.pathname().c_str(),
+ O_RDWR | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ LOG_ERR(LS_ERROR) << "open() failed.";
+ return false;
}
+ // Don't need to keep the file descriptor.
+ if (close(fd) < 0) {
+ LOG_ERR(LS_ERROR) << "close() failed.";
+ // Continue.
+ }
+ return true;
}
-std::string UnixFilesystem::TempFilenameI(const Pathname &dir, const std::string &prefix) {
+bool UnixFilesystem::DeleteFile(const Pathname &filename) {
+ LOG(LS_INFO) << "Deleting file:" << filename.pathname();
+
+ if (!IsFile(filename)) {
+ ASSERT(IsFile(filename));
+ return false;
+ }
+ return ::unlink(filename.pathname().c_str()) == 0;
+}
+
+bool UnixFilesystem::DeleteEmptyFolder(const Pathname &folder) {
+ LOG(LS_INFO) << "Deleting folder" << folder.pathname();
+
+ if (!IsFolder(folder)) {
+ ASSERT(IsFolder(folder));
+ return false;
+ }
+ std::string no_slash(folder.pathname(), 0, folder.pathname().length()-1);
+ return ::rmdir(no_slash.c_str()) == 0;
+}
+
+bool UnixFilesystem::GetTemporaryFolder(Pathname &pathname, bool create,
+ const std::string *append) {
+#ifdef OSX
+ FSRef fr;
+ if (0 != FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType,
+ kCreateFolder, &fr))
+ return false;
+ unsigned char buffer[NAME_MAX+1];
+ if (0 != FSRefMakePath(&fr, buffer, ARRAY_SIZE(buffer)))
+ return false;
+ pathname.SetPathname(reinterpret_cast<char*>(buffer), "");
+#elif defined(ANDROID)
+ pathname.SetPathname(GetAndroidTempFolder(), "");
+#else // !OSX && !ANDROID
+ if (const char* tmpdir = getenv("TMPDIR")) {
+ pathname.SetPathname(tmpdir, "");
+ } else if (const char* tmp = getenv("TMP")) {
+ pathname.SetPathname(tmp, "");
+ } else {
+#ifdef P_tmpdir
+ pathname.SetPathname(P_tmpdir, "");
+#else // !P_tmpdir
+ pathname.SetPathname("/tmp/", "");
+#endif // !P_tmpdir
+ }
+#endif // !OSX && !ANDROID
+ if (append) {
+ ASSERT(!append->empty());
+ pathname.AppendFolder(*append);
+ }
+ return !create || CreateFolder(pathname);
+}
+
+std::string UnixFilesystem::TempFilename(const Pathname &dir,
+ const std::string &prefix) {
int len = dir.pathname().size() + prefix.size() + 2 + 6;
char *tempname = new char[len];
-
- snprintf(tempname, len, "%s/%sXXXXXX", dir.pathname().c_str(), prefix.c_str());
+
+ snprintf(tempname, len, "%s/%sXXXXXX", dir.pathname().c_str(),
+ prefix.c_str());
int fd = ::mkstemp(tempname);
if (fd != -1)
::close(fd);
std::string ret(tempname);
delete[] tempname;
-
+
return ret;
}
-bool UnixFilesystem::MoveFileI(const Pathname &old_path, const Pathname &new_path)
-{
- LOG(LS_INFO) << "Moving " << old_path.pathname() << " to " << new_path.pathname();
+bool UnixFilesystem::MoveFile(const Pathname &old_path,
+ const Pathname &new_path) {
+ if (!IsFile(old_path)) {
+ ASSERT(IsFile(old_path));
+ return false;
+ }
+ LOG(LS_VERBOSE) << "Moving " << old_path.pathname()
+ << " to " << new_path.pathname();
if (rename(old_path.pathname().c_str(), new_path.pathname().c_str()) != 0) {
if (errno != EXDEV)
return false;
@@ -141,45 +236,38 @@
return true;
}
-bool UnixFilesystem::IsFolderI(const Pathname &path)
-{
+bool UnixFilesystem::MoveFolder(const Pathname &old_path,
+ const Pathname &new_path) {
+ if (!IsFolder(old_path)) {
+ ASSERT(IsFolder(old_path));
+ return false;
+ }
+ LOG(LS_VERBOSE) << "Moving " << old_path.pathname()
+ << " to " << new_path.pathname();
+ if (rename(old_path.pathname().c_str(), new_path.pathname().c_str()) != 0) {
+ if (errno != EXDEV)
+ return false;
+ if (!CopyFolder(old_path, new_path))
+ return false;
+ if (!DeleteFolderAndContents(old_path))
+ return false;
+ }
+ return true;
+}
+
+bool UnixFilesystem::IsFolder(const Pathname &path) {
struct stat st;
if (stat(path.pathname().c_str(), &st) < 0)
return false;
-
return S_ISDIR(st.st_mode);
}
-bool UnixFilesystem::CopyFileI(const Pathname &old_path, const Pathname &new_path)
-{
- LOG(LS_INFO) << "Copying " << old_path.pathname() << " to " << new_path.pathname();
+bool UnixFilesystem::CopyFile(const Pathname &old_path,
+ const Pathname &new_path) {
+ LOG(LS_VERBOSE) << "Copying " << old_path.pathname()
+ << " to " << new_path.pathname();
char buf[256];
size_t len;
- if (IsFolder(old_path)) {
- Pathname new_dir;
- new_dir.SetFolder(new_path.pathname());
- Pathname old_dir;
- old_dir.SetFolder(old_path.pathname());
-
- if (!CreateFolder(new_dir))
- return false;
- DirectoryIterator di;
- di.Iterate(old_dir.pathname());
- while(di.Next()) {
- if (di.Name() == "." || di.Name() == "..")
- continue;
- Pathname source;
- Pathname dest;
- source.SetFolder(old_dir.pathname());
- dest.SetFolder(new_path.pathname());
- source.SetFilename(di.Name());
- dest.SetFilename(di.Name());
-
- if (!CopyFile(source, dest))
- return false;
- }
- return true;
- }
StreamInterface *source = OpenFile(old_path, "rb");
if (!source)
@@ -190,8 +278,8 @@
delete source;
return false;
}
-
- while (source->Read(buf, sizeof(buf), &len, NULL) == talk_base::SR_SUCCESS)
+
+ while (source->Read(buf, sizeof(buf), &len, NULL) == SR_SUCCESS)
dest->Write(buf, len, NULL, NULL);
delete source;
@@ -199,20 +287,41 @@
return true;
}
-bool UnixFilesystem::IsTemporaryPathI(const Pathname& pathname)
-{
- return (!strncmp(pathname.pathname().c_str(), "/tmp/", strlen("/tmp/")));
+bool UnixFilesystem::IsTemporaryPath(const Pathname& pathname) {
+ const char* const kTempPrefixes[] = {
+#ifdef ANDROID
+ GetAndroidTempFolder()
+#else
+ "/tmp/", "/var/tmp/",
+#ifdef OSX
+ "/private/tmp/", "/private/var/tmp/", "/private/var/folders/",
+#endif // OSX
+#endif // ANDROID
+ };
+ for (size_t i = 0; i < ARRAY_SIZE(kTempPrefixes); ++i) {
+ if (0 == strncmp(pathname.pathname().c_str(), kTempPrefixes[i],
+ strlen(kTempPrefixes[i])))
+ return true;
+ }
+ return false;
}
-bool UnixFilesystem::FileExistsI(const Pathname& pathname)
-{
- struct stat st;
- int res = ::stat(pathname.pathname().c_str(), &st);
- return res == 0;
+bool UnixFilesystem::IsFile(const Pathname& pathname) {
+ struct stat st;
+ int res = ::stat(pathname.pathname().c_str(), &st);
+ // Treat symlinks, named pipes, etc. all as files.
+ return res == 0 && !S_ISDIR(st.st_mode);
}
-bool UnixFilesystem::GetFileSizeI(const Pathname& pathname, size_t *size)
-{
+bool UnixFilesystem::IsAbsent(const Pathname& pathname) {
+ struct stat st;
+ int res = ::stat(pathname.pathname().c_str(), &st);
+ // Note: we specifically maintain ENOTDIR as an error, because that implies
+ // that you could not call CreateFolder(pathname).
+ return res != 0 && ENOENT == errno;
+}
+
+bool UnixFilesystem::GetFileSize(const Pathname& pathname, size_t *size) {
struct stat st;
if (::stat(pathname.pathname().c_str(), &st) != 0)
return false;
@@ -220,4 +329,194 @@
return true;
}
+bool UnixFilesystem::GetFileTime(const Pathname& path, FileTimeType which,
+ time_t* time) {
+ struct stat st;
+ if (::stat(path.pathname().c_str(), &st) != 0)
+ return false;
+ switch (which) {
+ case FTT_CREATED:
+ *time = st.st_ctime;
+ break;
+ case FTT_MODIFIED:
+ *time = st.st_mtime;
+ break;
+ case FTT_ACCESSED:
+ *time = st.st_atime;
+ break;
+ default:
+ return false;
+ }
+ return true;
}
+
+bool UnixFilesystem::GetAppPathname(Pathname* path) {
+#ifdef OSX
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ CFDictionaryRef procinfo = ProcessInformationCopyDictionary(&psn,
+ kProcessDictionaryIncludeAllInformationMask);
+ if (NULL == procinfo)
+ return false;
+ CFStringRef cfpath = (CFStringRef) CFDictionaryGetValue(procinfo,
+ kIOBundleExecutableKey);
+ std::string path8;
+ bool success = ToUtf8(cfpath, &path8);
+ CFRelease(procinfo);
+ if (success)
+ path->SetPathname(path8);
+ return success;
+#else // OSX
+ char buffer[NAME_MAX+1];
+ size_t len = readlink("/proc/self/exe", buffer, ARRAY_SIZE(buffer) - 1);
+ if (len <= 0)
+ return false;
+ buffer[len] = '\0';
+ path->SetPathname(buffer);
+ return true;
+#endif // OSX
+}
+
+bool UnixFilesystem::GetAppDataFolder(Pathname* path, bool per_user) {
+ ASSERT(!organization_name_.empty());
+ ASSERT(!application_name_.empty());
+
+ // First get the base directory for app data.
+#ifdef OSX
+ if (per_user) {
+ // Use ~/Library/Application Support/<orgname>/<appname>/
+ FSRef fr;
+ if (0 != FSFindFolder(kUserDomain, kApplicationSupportFolderType,
+ kCreateFolder, &fr))
+ return false;
+ unsigned char buffer[NAME_MAX+1];
+ if (0 != FSRefMakePath(&fr, buffer, ARRAY_SIZE(buffer)))
+ return false;
+ path->SetPathname(reinterpret_cast<char*>(buffer), "");
+ } else {
+ // TODO
+ return false;
+ }
+#elif defined(ANDROID) // && !OSX
+ // TODO: Check if the new disk allocation mechanism works
+ // per-user and we don't have the per_user distinction.
+ path->SetPathname(GetAndroidAppDataFolder(), "");
+#elif defined(LINUX) // && !OSX && !defined(ANDROID)
+ if (per_user) {
+ // We follow the recommendations in
+ // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ // It specifies separate directories for data and config files, but
+ // GetAppDataFolder() does not distinguish. We just return the config dir
+ // path.
+ const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
+ if (xdg_config_home) {
+ path->SetPathname(xdg_config_home, "");
+ } else {
+ // XDG says to default to $HOME/.config. We also support falling back to
+ // other synonyms for HOME if for some reason it is not defined.
+ const char* homedir;
+ if (const char* home = getenv("HOME")) {
+ homedir = home;
+ } else if (const char* dotdir = getenv("DOTDIR")) {
+ homedir = dotdir;
+ } else if (passwd* pw = getpwuid(geteuid())) {
+ homedir = pw->pw_dir;
+ } else {
+ return false;
+ }
+ path->SetPathname(homedir, "");
+ path->AppendFolder(".config");
+ }
+ } else {
+ // XDG does not define a standard directory for writable global data. Let's
+ // just use this.
+ path->SetPathname("/var/cache/", "");
+ }
+#endif // !OSX && !defined(ANDROID) && !defined(LINUX)
+
+ // Now add on a sub-path for our app.
+#if defined(OSX) || defined(ANDROID)
+ path->AppendFolder(organization_name_);
+ path->AppendFolder(application_name_);
+#elif defined(LINUX)
+ // XDG says to use a single directory level, so we concatenate the org and app
+ // name with a hyphen. We also do the Linuxy thing and convert to all
+ // lowercase with no spaces.
+ std::string subdir(organization_name_);
+ subdir.append("-");
+ subdir.append(application_name_);
+ replace_substrs(" ", 1, "", 0, &subdir);
+ std::transform(subdir.begin(), subdir.end(), subdir.begin(), ::tolower);
+ path->AppendFolder(subdir);
+#endif
+ return CreateFolder(*path);
+}
+
+bool UnixFilesystem::GetAppTempFolder(Pathname* path) {
+ ASSERT(!application_name_.empty());
+ // TODO: Consider whether we are worried about thread safety.
+ if (!app_temp_path_.empty()) {
+ path->SetPathname(app_temp_path_);
+ return true;
+ }
+
+ // Create a random directory as /tmp/<appname>-<pid>-<timestamp>
+ char buffer[128];
+ sprintfn(buffer, ARRAY_SIZE(buffer), "-%d-%d",
+ static_cast<int>(getpid()),
+ static_cast<int>(time(0)));
+ std::string folder(application_name_);
+ folder.append(buffer);
+ if (!GetTemporaryFolder(*path, true, &folder))
+ return false;
+
+ app_temp_path_ = path->pathname();
+ // TODO: atexit(DeleteFolderAndContents(app_temp_path_));
+ return true;
+}
+
+bool UnixFilesystem::GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
+ ASSERT(NULL != freebytes);
+ // TODO: Consider making relative paths absolute using cwd.
+ // TODO: When popping off a symlink, push back on the components of the
+ // symlink, so we don't jump out of the target disk inadvertently.
+ Pathname existing_path(path.folder(), "");
+ while (!existing_path.folder().empty() && IsAbsent(existing_path)) {
+ existing_path.SetFolder(existing_path.parent_folder());
+ }
+#ifdef ANDROID
+ struct statfs fs;
+ memset(&fs, 0, sizeof(fs));
+ if (0 != statfs(existing_path.pathname().c_str(), &fs))
+ return false;
+#else
+ struct statvfs vfs;
+ memset(&vfs, 0, sizeof(vfs));
+ if (0 != statvfs(existing_path.pathname().c_str(), &vfs))
+ return false;
+#endif // ANDROID
+#ifdef LINUX
+ *freebytes = static_cast<int64>(vfs.f_bsize) * vfs.f_bavail;
+#elif defined(OSX)
+ *freebytes = static_cast<int64>(vfs.f_frsize) * vfs.f_bavail;
+#elif defined(ANDROID)
+ *freebytes = static_cast<int64>(fs.f_bsize) * fs.f_bavail;
+#endif
+
+ return true;
+}
+
+Pathname UnixFilesystem::GetCurrentDirectory() {
+ Pathname cwd;
+ char buffer[PATH_MAX];
+ char *path = getcwd(buffer, PATH_MAX);
+
+ if (!path) {
+ LOG_ERR(LS_ERROR) << "getcwd() failed";
+ return cwd; // returns empty pathname
+ }
+ cwd.SetFolder(std::string(path));
+
+ return cwd;
+}
+
+} // namespace talk_base
diff --git a/talk/base/unixfilesystem.h b/talk/base/unixfilesystem.h
old mode 100755
new mode 100644
index bd145bb..71960ac
--- a/talk/base/unixfilesystem.h
+++ b/talk/base/unixfilesystem.h
@@ -32,55 +32,83 @@
namespace talk_base {
-class UnixFilesystem : public Filesystem{
+class UnixFilesystem : public FilesystemInterface {
public:
- virtual bool CreateFolderI(const Pathname &pathname);
-
// Opens a file. Returns an open StreamInterface if function succeeds. Otherwise,
// returns NULL.
- virtual FileStream *OpenFileI(const Pathname &filename,
- const std::string &mode);
+ virtual FileStream *OpenFile(const Pathname &filename,
+ const std::string &mode);
- // This will attempt to delete the path located at filename. If filename is a file,
- // it will be unlinked. If the path is a directory, it will recursively unlink and remove
- // all the files and directory within it
- virtual bool DeleteFileI(const Pathname &filename);
+ // Atomically creates an empty file accessible only to the current user if one
+ // does not already exist at the given path, otherwise fails.
+ virtual bool CreatePrivateFile(const Pathname &filename);
+ // This will attempt to delete the file located at filename.
+ // It will fail with VERIY if you pass it a non-existant file, or a directory.
+ virtual bool DeleteFile(const Pathname &filename);
+
+ // This will attempt to delete the folder located at 'folder'
+ // It ASSERTs and returns false if you pass it a non-existant folder or a plain file.
+ virtual bool DeleteEmptyFolder(const Pathname &folder);
+
// Creates a directory. This will call itself recursively to create /foo/bar even if
// /foo does not exist.
// Returns TRUE if function succeeds
+ virtual bool CreateFolder(const Pathname &pathname);
// This moves a file from old_path to new_path, where "file" can be a plain file
// or directory, which will be moved recursively.
// Returns true if function succeeds.
- virtual bool MoveFileI(const Pathname &old_path, const Pathname &new_path);
+ virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path);
+ virtual bool MoveFolder(const Pathname &old_path, const Pathname &new_path);
// This copies a file from old_path to _new_path where "file" can be a plain file
// or directory, which will be copied recursively.
// Returns true if function succeeds
- virtual bool CopyFileI(const Pathname &old_path, const Pathname &new_path);
+ virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path);
// Returns true if a pathname is a directory
- virtual bool IsFolderI(const Pathname& pathname);
+ virtual bool IsFolder(const Pathname& pathname);
// Returns true if pathname represents a temporary location on the system.
- virtual bool IsTemporaryPathI(const Pathname& pathname);
+ virtual bool IsTemporaryPath(const Pathname& pathname);
// Returns true of pathname represents an existing file
- virtual bool FileExistsI(const Pathname& pathname);
+ virtual bool IsFile(const Pathname& pathname);
- virtual std::string TempFilenameI(const Pathname &dir, const std::string &prefix);
+ // Returns true if pathname refers to no filesystem object, every parent
+ // directory either exists, or is also absent.
+ virtual bool IsAbsent(const Pathname& pathname);
+
+ virtual std::string TempFilename(const Pathname &dir, const std::string &prefix);
// A folder appropriate for storing temporary files (Contents are
// automatically deleted when the program exists)
- virtual bool GetTemporaryFolderI(Pathname &path, bool create,
+ virtual bool GetTemporaryFolder(Pathname &path, bool create,
const std::string *append);
- virtual bool GetFileSizeI(const Pathname &path, size_t *size);
+ virtual bool GetFileSize(const Pathname& path, size_t* size);
+ virtual bool GetFileTime(const Pathname& path, FileTimeType which,
+ time_t* time);
- };
+ // Returns the path to the running application.
+ virtual bool GetAppPathname(Pathname* path);
-}
+ virtual bool GetAppDataFolder(Pathname* path, bool per_user);
+
+ // Get a temporary folder that is unique to the current user and application.
+ virtual bool GetAppTempFolder(Pathname* path);
+
+ virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes);
+
+ // Returns the absolute path of the current directory.
+ virtual Pathname GetCurrentDirectory();
+
+ private:
+ static std::string app_temp_path_;
+};
+
+} // namespace talk_base
#endif // _UNIXFILESYSTEM_H__
diff --git a/talk/base/urlencode.cc b/talk/base/urlencode.cc
old mode 100755
new mode 100644
index b654c35..6dd51e1
--- a/talk/base/urlencode.cc
+++ b/talk/base/urlencode.cc
@@ -1,5 +1,35 @@
+/*
+ * libjingle
+ * Copyright 2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include "talk/base/urlencode.h"
+#include "talk/base/common.h"
+#include "talk/base/stringutils.h"
+
static int HexPairValue(const char * code) {
int value = 0;
const char * pch = code;
@@ -23,14 +53,18 @@
}
}
-int UrlDecode(const char *source, char *dest)
-{
+int InternalUrlDecode(const char *source, char *dest,
+ bool encode_space_as_plus) {
char * start = dest;
while (*source) {
switch (*source) {
case '+':
- *(dest++) = ' ';
+ if (encode_space_as_plus) {
+ *(dest++) = ' ';
+ } else {
+ *dest++ = *source;
+ }
break;
case '%':
if (source[1] && source[2]) {
@@ -52,69 +86,111 @@
}
source++;
}
-
+
*dest = 0;
return dest - start;
-}
+}
-int UrlEncode(const char *source, char *dest, unsigned max)
-{
+int UrlDecode(const char *source, char *dest) {
+ return InternalUrlDecode(source, dest, true);
+}
+
+int UrlDecodeWithoutEncodingSpaceAsPlus(const char *source, char *dest) {
+ return InternalUrlDecode(source, dest, false);
+}
+
+bool IsValidUrlChar(char ch, bool unsafe_only) {
+ if (unsafe_only) {
+ return !(ch <= ' ' || strchr("\\\"^&`<>[]{}", ch));
+ } else {
+ return isalnum(ch) || strchr("-_.!~*'()", ch);
+ }
+}
+
+int InternalUrlEncode(const char *source, char *dest, unsigned int max,
+ bool encode_space_as_plus, bool unsafe_only) {
static const char *digits = "0123456789ABCDEF";
- unsigned char ch;
- unsigned len = 0;
- char *start = dest;
+ if (max == 0) {
+ return 0;
+ }
- while (len < max - 4 && *source)
- {
- ch = (unsigned char)*source;
- if (*source == ' ') {
+ char *start = dest;
+ while (static_cast<unsigned>(dest - start) < max && *source) {
+ unsigned char ch = static_cast<unsigned char>(*source);
+ if (*source == ' ' && encode_space_as_plus && !unsafe_only) {
*dest++ = '+';
- }
- else if (isalnum(ch) || strchr("-_.!~*'()", ch)) {
+ } else if (IsValidUrlChar(ch, unsafe_only)) {
*dest++ = *source;
- }
- else {
+ } else {
+ if (static_cast<unsigned>(dest - start) + 4 > max) {
+ break;
+ }
*dest++ = '%';
*dest++ = digits[(ch >> 4) & 0x0F];
*dest++ = digits[ ch & 0x0F];
- }
+ }
source++;
}
+ ASSERT(static_cast<unsigned int>(dest - start) < max);
*dest = 0;
- return start - dest;
+
+ return dest - start;
+}
+
+int UrlEncode(const char *source, char *dest, unsigned max) {
+ return InternalUrlEncode(source, dest, max, true, false);
+}
+
+int UrlEncodeWithoutEncodingSpaceAsPlus(const char *source, char *dest,
+ unsigned max) {
+ return InternalUrlEncode(source, dest, max, false, false);
+}
+
+int UrlEncodeOnlyUnsafeChars(const char *source, char *dest, unsigned max) {
+ return InternalUrlEncode(source, dest, max, false, true);
+}
+
+std::string
+InternalUrlDecodeString(const std::string & encoded,
+ bool encode_space_as_plus) {
+ size_t needed_length = encoded.length() + 1;
+ char* buf = STACK_ARRAY(char, needed_length);
+ InternalUrlDecode(encoded.c_str(), buf, encode_space_as_plus);
+ return buf;
}
std::string
UrlDecodeString(const std::string & encoded) {
- const char * sz_encoded = encoded.c_str();
- size_t needed_length = encoded.length();
- for (const char * pch = sz_encoded; *pch; pch++) {
- if (*pch == '%')
- needed_length += 2;
- }
- needed_length += 10;
- char stackalloc[64];
- char * buf = needed_length > sizeof(stackalloc)/sizeof(*stackalloc) ?
- (char *)malloc(needed_length) : stackalloc;
- UrlDecode(encoded.c_str(), buf);
- std::string result(buf);
- if (buf != stackalloc) {
- free(buf);
- }
- return result;
+ return InternalUrlDecodeString(encoded, true);
+}
+
+std::string
+UrlDecodeStringWithoutEncodingSpaceAsPlus(const std::string & encoded) {
+ return InternalUrlDecodeString(encoded, false);
+}
+
+std::string
+InternalUrlEncodeString(const std::string & decoded,
+ bool encode_space_as_plus,
+ bool unsafe_only) {
+ size_t needed_length = decoded.length() * 3 + 1;
+ char* buf = STACK_ARRAY(char, needed_length);
+ InternalUrlEncode(decoded.c_str(), buf, needed_length,
+ encode_space_as_plus, unsafe_only);
+ return buf;
}
std::string
UrlEncodeString(const std::string & decoded) {
- const char * sz_decoded = decoded.c_str();
- size_t needed_length = decoded.length() * 3 + 3;
- char stackalloc[64];
- char * buf = needed_length > sizeof(stackalloc)/sizeof(*stackalloc) ?
- (char *)malloc(needed_length) : stackalloc;
- UrlEncode(decoded.c_str(), buf, needed_length);
- std::string result(buf);
- if (buf != stackalloc) {
- free(buf);
- }
- return result;
+ return InternalUrlEncodeString(decoded, true, false);
+}
+
+std::string
+UrlEncodeStringWithoutEncodingSpaceAsPlus(const std::string & decoded) {
+ return InternalUrlEncodeString(decoded, false, false);
+}
+
+std::string
+UrlEncodeStringForOnlyUnsafeChars(const std::string & decoded) {
+ return InternalUrlEncodeString(decoded, false, true);
}
diff --git a/talk/base/urlencode.h b/talk/base/urlencode.h
old mode 100755
new mode 100644
index 9d2b3f6..05165e8
--- a/talk/base/urlencode.h
+++ b/talk/base/urlencode.h
@@ -1,12 +1,60 @@
+/*
+ * libjingle
+ * Copyright 2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#ifndef _URLENCODE_H_
#define _URLENCODE_H_
#include <string>
+// Decode all encoded characters. Also decode + as space.
int UrlDecode(const char *source, char *dest);
+
+// Decode all encoded characters.
+int UrlDecodeWithoutEncodingSpaceAsPlus(const char *source, char *dest);
+
+// Encode all characters except alphas, numbers, and -_.!~*'()
+// Also encode space as +.
int UrlEncode(const char *source, char *dest, unsigned max);
+
+// Encode all characters except alphas, numbers, and -_.!~*'()
+int UrlEncodeWithoutEncodingSpaceAsPlus(const char *source, char *dest,
+ unsigned max);
+
+// Encode only unsafe chars, including \ "^&`<>[]{}
+// Also encode space as %20, instead of +
+int UrlEncodeOnlyUnsafeChars(const char *source, char *dest, unsigned max);
+
std::string UrlDecodeString(const std::string & encoded);
+std::string UrlDecodeStringWithoutEncodingSpaceAsPlus(
+ const std::string & encoded);
std::string UrlEncodeString(const std::string & decoded);
+std::string UrlEncodeStringWithoutEncodingSpaceAsPlus(
+ const std::string & decoded);
+std::string UrlEncodeStringForOnlyUnsafeChars(const std::string & decoded);
#endif
diff --git a/talk/base/virtualsocket_unittest.cc b/talk/base/virtualsocket_unittest.cc
deleted file mode 100755
index 16456a2..0000000
--- a/talk/base/virtualsocket_unittest.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2006, Google Inc.
-
-#include <complex>
-#include <iostream>
-#include <cassert>
-
-#include "talk/base/thread.h"
-#include "talk/base/virtualsocketserver.h"
-#include "talk/base/testclient.h"
-#include "talk/base/time.h"
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-using namespace talk_base;
-
-void test_basic(Thread* thread, VirtualSocketServer* ss) {
- std::cout << "basic: ";
- std::cout.flush();
-
- SocketAddress addr1(ss->GetNextIP(), 5000);
- AsyncUDPSocket* socket = CreateAsyncUDPSocket(ss);
- socket->Bind(addr1);
-
- TestClient* client1 = new TestClient(socket);
- TestClient* client2 = new TestClient(CreateAsyncUDPSocket(ss));
-
- SocketAddress addr2;
- client2->SendTo("foo", 3, addr1);
- client1->CheckNextPacket("foo", 3, &addr2);
-
- SocketAddress addr3;
- client1->SendTo("bizbaz", 6, addr2);
- client2->CheckNextPacket("bizbaz", 6, &addr3);
- assert(addr3 == addr1);
-
- for (int i = 0; i < 10; i++) {
- client2 = new TestClient(CreateAsyncUDPSocket(ss));
-
- SocketAddress addr4;
- client2->SendTo("foo", 3, addr1);
- client1->CheckNextPacket("foo", 3, &addr4);
- assert((addr4.ip() == addr2.ip()) && (addr4.port() == addr2.port() + 1));
-
- SocketAddress addr5;
- client1->SendTo("bizbaz", 6, addr4);
- client2->CheckNextPacket("bizbaz", 6, &addr5);
- assert(addr5 == addr1);
-
- addr2 = addr4;
- }
-
- std::cout << "PASS" << std::endl;
-}
-
-// Sends at a constant rate but with random packet sizes.
-struct Sender : public MessageHandler {
- Sender(Thread* th, AsyncUDPSocket* s, uint32 rt)
- : thread(th), socket(s), done(false), rate(rt), count(0) {
- last_send = GetMillisecondCount();
- thread->PostDelayed(NextDelay(), this, 1);
- }
-
- uint32 NextDelay() {
- uint32 size = (rand() % 4096) + 1;
- return 1000 * size / rate;
- }
-
- void OnMessage(Message* pmsg) {
- assert(pmsg->message_id == 1);
-
- if (done)
- return;
-
- uint32 cur_time = GetMillisecondCount();
- uint32 delay = cur_time - last_send;
- uint32 size = rate * delay / 1000;
- size = std::min(size, uint32(4096));
- size = std::max(size, uint32(4));
-
- count += size;
- *reinterpret_cast<uint32*>(dummy) = cur_time;
- socket->Send(dummy, size);
-
- last_send = cur_time;
- thread->PostDelayed(NextDelay(), this, 1);
- }
-
- Thread* thread;
- AsyncUDPSocket* socket;
- bool done;
- uint32 rate; // bytes per second
- uint32 count;
- uint32 last_send;
- char dummy[4096];
-};
-
-struct Receiver : public MessageHandler, public sigslot::has_slots<> {
- Receiver(Thread* th, AsyncUDPSocket* s, uint32 bw)
- : thread(th), socket(s), bandwidth(bw), done(false), count(0),
- sec_count(0), sum(0), sum_sq(0), samples(0) {
- socket->SignalReadPacket.connect(this, &Receiver::OnReadPacket);
- thread->PostDelayed(1000, this, 1);
- }
-
- ~Receiver() {
- thread->Clear(this);
- }
-
- void OnReadPacket(
- const char* data, size_t size, const SocketAddress& remote_addr,
- AsyncPacketSocket* s) {
- assert(s == socket);
- assert(size >= 4);
-
- count += size;
- sec_count += size;
-
- uint32 send_time = *reinterpret_cast<const uint32*>(data);
- uint32 recv_time = GetMillisecondCount();
- uint32 delay = recv_time - send_time;
- sum += delay;
- sum_sq += delay * delay;
- samples += 1;
- }
-
- void OnMessage(Message* pmsg) {
- assert(pmsg->message_id == 1);
- // It is always possible for us to receive more than expected because
- // packets can be further delayed in delivery.
- if (bandwidth > 0)
- assert(sec_count <= 5 * bandwidth / 4);
- sec_count = 0;
- thread->PostDelayed(1000, this, 1);
- }
-
- Thread* thread;
- AsyncUDPSocket* socket;
- uint32 bandwidth;
- bool done;
- uint32 count;
- uint32 sec_count;
- double sum;
- double sum_sq;
- uint32 samples;
-};
-
-void test_bandwidth(Thread* thread, VirtualSocketServer* ss) {
- std::cout << "bandwidth: ";
- std::cout.flush();
-
- AsyncUDPSocket* send_socket = CreateAsyncUDPSocket(ss);
- AsyncUDPSocket* recv_socket = CreateAsyncUDPSocket(ss);
- assert(send_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
- assert(recv_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
- assert(send_socket->Connect(recv_socket->GetLocalAddress()) >= 0);
-
- uint32 bandwidth = 64 * 1024;
- ss->set_bandwidth(bandwidth);
-
- Sender sender(thread, send_socket, 80 * 1024);
- Receiver receiver(thread, recv_socket, bandwidth);
-
- Thread* pthMain = Thread::Current();
- pthMain->ProcessMessages(5000);
- sender.done = true;
- pthMain->ProcessMessages(5000);
-
- assert(receiver.count >= 5 * 3 * bandwidth / 4);
- assert(receiver.count <= 6 * bandwidth); // queue could drain for 1 sec
-
- delete send_socket;
- delete recv_socket;
-
- ss->set_bandwidth(0);
-
- std::cout << "PASS" << std::endl;
-}
-
-void test_delay(Thread* thread, VirtualSocketServer* ss) {
- std::cout << "delay: ";
- std::cout.flush();
-
- uint32 mean = 2000;
- uint32 stddev = 500;
-
- ss->set_delay_mean(mean);
- ss->set_delay_stddev(stddev);
- ss->UpdateDelayDistribution();
-
- AsyncUDPSocket* send_socket = CreateAsyncUDPSocket(ss);
- AsyncUDPSocket* recv_socket = CreateAsyncUDPSocket(ss);
- assert(send_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
- assert(recv_socket->Bind(SocketAddress(ss->GetNextIP(), 1000)) >= 0);
- assert(send_socket->Connect(recv_socket->GetLocalAddress()) >= 0);
-
- Sender sender(thread, send_socket, 64 * 1024);
- Receiver receiver(thread, recv_socket, 0);
-
- Thread* pthMain = Thread::Current();
- pthMain->ProcessMessages(5000);
- sender.done = true;
- pthMain->ProcessMessages(5000);
-
- double sample_mean = receiver.sum / receiver.samples;
- double num = receiver.sum_sq - 2 * sample_mean * receiver.sum +
- receiver.samples * sample_mean * sample_mean;
- double sample_stddev = std::sqrt(num / (receiver.samples - 1));
-std::cout << "mean=" << sample_mean << " dev=" << sample_stddev << std::endl;
-
- assert(0.9 * mean <= sample_mean);
- assert(sample_mean <= 1.1 * mean);
- assert(0.9 * stddev <= sample_stddev);
- assert(sample_stddev <= 1.1 * stddev);
-
- delete send_socket;
- delete recv_socket;
-
- ss->set_delay_mean(0);
- ss->set_delay_stddev(0);
- ss->UpdateDelayDistribution();
-
- std::cout << "PASS" << std::endl;
-}
-
-int main(int argc, char* argv) {
- Thread *pthMain = Thread::Current();
- VirtualSocketServer* ss = new VirtualSocketServer();
- pthMain->set_socketserver(ss);
-
- test_basic(pthMain, ss);
- test_bandwidth(pthMain, ss);
- test_delay(pthMain, ss);
-
- return 0;
-}
diff --git a/talk/base/virtualsocketserver.cc b/talk/base/virtualsocketserver.cc
deleted file mode 100755
index 884b324..0000000
--- a/talk/base/virtualsocketserver.cc
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <algorithm>
-#include <cassert>
-#include <cmath>
-#include <cstring>
-#include <iostream>
-#include <vector>
-#include <errno.h>
-
-#include "talk/base/virtualsocketserver.h"
-#include "talk/base/common.h"
-#include "talk/base/time.h"
-
-namespace talk_base {
-
-const uint32 HEADER_SIZE = 28; // IP + UDP headers
-
-const uint32 MSG_ID_PACKET = 1;
-// TODO: Add a message type for new connections.
-
-// Packets are passed between sockets as messages. We copy the data just like
-// the kernel does.
-class Packet : public MessageData {
-public:
- Packet(const char* data, size_t size, const SocketAddress& from)
- : size_(size), from_(from) {
- assert(data);
- assert(size_ >= 0);
- data_ = new char[size_];
- std::memcpy(data_, data, size_);
- }
-
- virtual ~Packet() {
- delete data_;
- }
-
- const char* data() const { return data_; }
- size_t size() const { return size_; }
- const SocketAddress& from() const { return from_; }
-
- // Remove the first size bytes from the data.
- void Consume(size_t size) {
- assert(size < size_);
- size_ -= size;
- char* new_data = new char[size_];
- std::memcpy(new_data, data_, size);
- delete[] data_;
- data_ = new_data;
- }
-
-private:
- char* data_;
- size_t size_;
- SocketAddress from_;
-};
-
-// Implements the socket interface using the virtual network. Packets are
-// passed as messages using the message queue of the socket server.
-class VirtualSocket : public AsyncSocket, public MessageHandler {
-public:
- VirtualSocket(
- VirtualSocketServer* server, int type, bool async, uint32 ip)
- : server_(server), type_(type), async_(async), connected_(false),
- local_ip_(ip), readable_(true), queue_size_(0) {
- assert((type_ == SOCK_DGRAM) || (type_ == SOCK_STREAM));
- packets_ = new std::vector<Packet*>();
- }
-
- ~VirtualSocket() {
- Close();
-
- for (unsigned i = 0; i < packets_->size(); i++)
- delete (*packets_)[i];
- delete packets_;
- }
-
- SocketAddress GetLocalAddress() const {
- return local_addr_;
- }
-
- SocketAddress GetRemoteAddress() const {
- return remote_addr_;
- }
-
- int Bind(const SocketAddress& addr) {
- assert(addr.port() != 0);
- int result = server_->Bind(addr, this);
- if (result >= 0)
- local_addr_ = addr;
- else
- error_ = EADDRINUSE;
- return result;
- }
-
- int Connect(const SocketAddress& addr) {
- assert(!connected_);
- connected_ = true;
- remote_addr_ = addr;
- assert(type_ == SOCK_DGRAM); // stream not yet implemented
- return 0;
- }
-
- int Close() {
- if (!local_addr_.IsAny())
- server_->Unbind(local_addr_, this);
-
- connected_ = false;
- local_addr_ = SocketAddress();
- remote_addr_ = SocketAddress();
- return 0;
- }
-
- int Send(const void *pv, size_t cb) {
- assert(connected_);
- return SendInternal(pv, cb, remote_addr_);
- }
-
- int SendTo(const void *pv, size_t cb, const SocketAddress& addr) {
- assert(!connected_);
- return SendInternal(pv, cb, addr);
- }
-
- int SendInternal(const void *pv, size_t cb, const SocketAddress& addr) {
- // If we have not been assigned a local port, then get one.
- if (local_addr_.IsAny()) {
- local_addr_.SetIP(local_ip_);
- int result = server_->Bind(this, &local_addr_);
- if (result < 0) {
- local_addr_.SetIP(0);
- error_ = EADDRINUSE;
- return result;
- }
- }
-
- // Send the data in a message to the appropriate socket.
- return server_->Send(this, pv, cb, local_addr_, addr);
- }
-
- int Recv(void *pv, size_t cb) {
- SocketAddress addr;
- return RecvFrom(pv, cb, &addr);
- }
-
- int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
- // If we don't have a packet, then either error or wait for one to arrive.
- if (packets_->size() == 0) {
- if (async_) {
- error_ = EAGAIN;
- return -1;
- }
- while (packets_->size() == 0) {
- Message msg;
- server_->msg_queue_->Get(&msg);
- server_->msg_queue_->Dispatch(&msg);
- }
- }
-
- // Return the packet at the front of the queue.
- Packet* packet = packets_->front();
- *paddr = packet->from();
- int size = (int)packet->size();
- if (size <= (int)cb) {
- std::memcpy(pv, packet->data(), size);
- packets_->erase(packets_->begin());
- delete packet;
- return size;
- } else {
- std::memcpy(pv, packet->data(), cb);
- packet->Consume(cb);
- return (int)cb;
- }
- }
-
- int Listen(int backlog) {
- assert(false); // not yet implemented
- return 0;
- }
-
- Socket* Accept(SocketAddress *paddr) {
- assert(false); // not yet implemented
- return 0;
- }
-
- bool readable() { return readable_; }
- void set_readable(bool value) { readable_ = value; }
-
- bool writable() { return false; }
- void set_writable(bool value) {
- // TODO: Send ourselves messages (delayed after the first) to give them a
- // chance to write.
- assert(false);
- }
-
- int GetError() const {
- return error_;
- }
-
- void SetError(int error) {
- error_ = error;
- }
-
- ConnState GetState() const {
- return connected_ ? CS_CONNECTED : CS_CLOSED;
- }
-
- int SetOption(Option opt, int value) {
- return 0;
- }
-
- int EstimateMTU(uint16* mtu) {
- if (!connected_)
- return ENOTCONN;
- else
- return 65536;
- }
-
- void OnMessage(Message *pmsg) {
- if (pmsg->message_id == MSG_ID_PACKET) {
- assert(pmsg->pdata);
- Packet* packet = static_cast<Packet*>(pmsg->pdata);
-
- if (!readable_)
- return;
-
- packets_->push_back(packet);
-
- if (async_) {
- SignalReadEvent(this);
-
- // TODO: If the listeners don't want to read this packet now, we will
- // need to send ourselves delayed messages to try again.
- assert(packets_->size() == 0);
- }
- } else {
- assert(false);
- }
- }
-
-private:
- struct QueueEntry {
- uint32 size;
- uint32 done_time;
- };
-
- typedef std::deque<QueueEntry> SendQueue;
-
- VirtualSocketServer* server_;
- int type_;
- bool async_;
- bool connected_;
- uint32 local_ip_;
- bool readable_;
- SocketAddress local_addr_;
- SocketAddress remote_addr_;
- std::vector<Packet*>* packets_;
- int error_;
- SendQueue queue_;
- uint32 queue_size_;
- CriticalSection queue_crit_;
-
- friend class VirtualSocketServer;
-};
-
-VirtualSocketServer::VirtualSocketServer()
- : fWait_(false), wait_version_(0), next_ip_(1), next_port_(45000),
- bandwidth_(0), queue_capacity_(64 * 1024), delay_mean_(0),
- delay_stddev_(0), delay_dist_(0), drop_prob_(0.0) {
- msg_queue_ = new MessageQueue(); // uses physical socket server for Wait
- bindings_ = new AddressMap();
-
- UpdateDelayDistribution();
-}
-
-VirtualSocketServer::~VirtualSocketServer() {
- delete bindings_;
- delete msg_queue_;
- delete delay_dist_;
-}
-
-uint32 VirtualSocketServer::GetNextIP() {
- return next_ip_++;
-}
-
-Socket* VirtualSocketServer::CreateSocket(int type) {
- return CreateSocketInternal(type);
-}
-
-AsyncSocket* VirtualSocketServer::CreateAsyncSocket(int type) {
- return CreateSocketInternal(type);
-}
-
-VirtualSocket* VirtualSocketServer::CreateSocketInternal(int type) {
- uint32 ip = (next_ip_ > 1) ? next_ip_ - 1 : 1;
- return new VirtualSocket(this, type, true, ip);
-}
-
-bool VirtualSocketServer::Wait(int cmsWait, bool process_io) {
- ASSERT(process_io); // This can't be easily supported.
-
- uint32 msEnd;
- if (cmsWait != kForever)
- msEnd = GetMillisecondCount() + cmsWait;
- uint32 cmsNext = cmsWait;
-
- fWait_ = true;
- wait_version_ += 1;
-
- while (fWait_) {
- Message msg;
- if (!msg_queue_->Get(&msg, cmsNext))
- return true;
- msg_queue_->Dispatch(&msg);
-
- if (cmsWait != kForever) {
- uint32 msCur = GetMillisecondCount();
- if (msCur >= msEnd)
- return true;
- cmsNext = msEnd - msCur;
- }
- }
- return true;
-}
-
-const uint32 MSG_WAKE_UP = 1;
-
-struct WakeUpMessage : public MessageData {
- WakeUpMessage(uint32 ver) : wait_version(ver) {}
- virtual ~WakeUpMessage() {}
-
- uint32 wait_version;
-};
-
-void VirtualSocketServer::WakeUp() {
- msg_queue_->Post(this, MSG_WAKE_UP, new WakeUpMessage(wait_version_));
-}
-
-void VirtualSocketServer::OnMessage(Message* pmsg) {
- assert(pmsg->message_id == MSG_WAKE_UP);
- assert(pmsg->pdata);
- WakeUpMessage* wmsg = static_cast<WakeUpMessage*>(pmsg->pdata);
- if (wmsg->wait_version == wait_version_)
- fWait_ = false;
- delete pmsg->pdata;
-}
-
-int VirtualSocketServer::Bind(
- const SocketAddress& addr, VirtualSocket* socket) {
- assert(addr.ip() > 0); // don't support any-address right now
- assert(addr.port() > 0);
- assert(socket);
-
- if (bindings_->find(addr) == bindings_->end()) {
- (*bindings_)[addr] = socket;
- return 0;
- } else {
- return -1;
- }
-}
-
-int VirtualSocketServer::Bind(VirtualSocket* socket, SocketAddress* addr) {
- assert(addr->ip() > 0); // don't support any-address right now
- assert(socket);
-
- for (int i = 0; i < 65536; i++) {
- addr->SetPort(next_port_++);
- if (addr->port() > 0) {
- AddressMap::iterator iter = bindings_->find(*addr);
- if (iter == bindings_->end()) {
- (*bindings_)[*addr] = socket;
- return 0;
- }
- }
- }
-
- errno = EADDRINUSE; // TODO: is there a better error number?
- return -1;
-}
-
-int VirtualSocketServer::Unbind(
- const SocketAddress& addr, VirtualSocket* socket) {
- assert((*bindings_)[addr] == socket);
- bindings_->erase(bindings_->find(addr));
- return 0;
-}
-
-static double Random() {
- return double(rand()) / RAND_MAX;
-}
-
-int VirtualSocketServer::Send(
- VirtualSocket* socket, const void *pv, size_t cb,
- const SocketAddress& local_addr, const SocketAddress& remote_addr) {
-
- // See if we want to drop this packet.
- if (Random() < drop_prob_) {
- std::cerr << "Dropping packet: bad luck" << std::endl;
- return 0;
- }
-
- uint32 cur_time = GetMillisecondCount();
- uint32 send_delay;
-
- // Determine whether we have enough bandwidth to accept this packet. To do
- // this, we need to update the send queue. Once we know it's current size,
- // we know whether we can fit this packet.
- //
- // NOTE: There are better algorithms for maintaining such a queue (such as
- // "Derivative Random Drop"); however, this algorithm is a more accurate
- // simulation of what a normal network would do.
- {
- CritScope cs(&socket->queue_crit_);
-
- while ((socket->queue_.size() > 0) &&
- (socket->queue_.front().done_time <= cur_time)) {
- assert(socket->queue_size_ >= socket->queue_.front().size);
- socket->queue_size_ -= socket->queue_.front().size;
- socket->queue_.pop_front();
- }
-
- VirtualSocket::QueueEntry entry;
- entry.size = uint32(cb) + HEADER_SIZE;
-
- if (socket->queue_size_ + entry.size > queue_capacity_) {
- std::cerr << "Dropping packet: queue capacity exceeded" << std::endl;
- return 0; // not an error
- }
-
- socket->queue_size_ += entry.size;
- send_delay = SendDelay(socket->queue_size_);
- entry.done_time = cur_time + send_delay;
- socket->queue_.push_back(entry);
- }
-
- // Find the delay for crossing the many virtual hops of the network.
- uint32 transit_delay = GetRandomTransitDelay();
-
- // Post the packet as a message to be delivered (on our own thread)
-
- AddressMap::iterator iter = bindings_->find(remote_addr);
- if (iter != bindings_->end()) {
- Packet* p = new Packet(static_cast<const char*>(pv), cb, local_addr);
- uint32 delay = send_delay + transit_delay;
- msg_queue_->PostDelayed(delay, iter->second, MSG_ID_PACKET, p);
- } else {
- std::cerr << "No one listening at " << remote_addr.ToString() << std::endl;
- }
- return (int)cb;
-}
-
-uint32 VirtualSocketServer::SendDelay(uint32 size) {
- if (bandwidth_ == 0)
- return 0;
- else
- return 1000 * size / bandwidth_;
-}
-
-void PrintFunction(std::vector<std::pair<double,double> >* f) {
- for (uint32 i = 0; i < f->size(); i++)
- std::cout << (*f)[i].first << '\t' << (*f)[i].second << std::endl;
-}
-
-void VirtualSocketServer::UpdateDelayDistribution() {
- Function* dist = GetDelayDistribution();
- dist = Resample(Invert(Accumulate(dist)), 0, 1);
-
- // We take a lock just to make sure we don't leak memory.
- {
- CritScope cs(&delay_crit_);
- delete delay_dist_;
- delay_dist_ = dist;
- }
-}
-
-const int NUM_SAMPLES = 100; // 1000;
-
-static double PI = 4 * std::atan(1.0);
-
-static double Normal(double x, double mean, double stddev) {
- double a = (x - mean) * (x - mean) / (2 * stddev * stddev);
- return std::exp(-a) / (stddev * sqrt(2 * PI));
-}
-
-#if 0 // static unused gives a warning
-static double Pareto(double x, double min, double k) {
- if (x < min)
- return 0;
- else
- return k * std::pow(min, k) / std::pow(x, k+1);
-}
-#endif
-
-VirtualSocketServer::Function* VirtualSocketServer::GetDelayDistribution() {
- Function* f = new Function();
-
- if (delay_stddev_ == 0) {
-
- f->push_back(Point(delay_mean_, 1.0));
-
- } else {
-
- double start = 0;
- if (delay_mean_ >= 4 * double(delay_stddev_))
- start = delay_mean_ - 4 * double(delay_stddev_);
- double end = delay_mean_ + 4 * double(delay_stddev_);
-
- double delay_min = 0;
- if (delay_mean_ >= 1.0 * delay_stddev_)
- delay_min = delay_mean_ - 1.0 * delay_stddev_;
-
- for (int i = 0; i < NUM_SAMPLES; i++) {
- double x = start + (end - start) * i / (NUM_SAMPLES - 1);
- double y = Normal(x, delay_mean_, delay_stddev_);
- f->push_back(Point(x, y));
- }
-
- }
-
- return f;
-}
-
-uint32 VirtualSocketServer::GetRandomTransitDelay() {
- double delay = (*delay_dist_)[rand() % delay_dist_->size()].second;
- return uint32(delay);
-}
-
-struct FunctionDomainCmp {
- bool operator ()(const VirtualSocketServer::Point& p1, const VirtualSocketServer::Point& p2) {
- return p1.first < p2.first;
- }
- bool operator ()(double v1, const VirtualSocketServer::Point& p2) {
- return v1 < p2.first;
- }
- bool operator ()(const VirtualSocketServer::Point& p1, double v2) {
- return p1.first < v2;
- }
-};
-
-VirtualSocketServer::Function* VirtualSocketServer::Accumulate(Function* f) {
- assert(f->size() >= 1);
- double v = 0;
- for (Function::size_type i = 0; i < f->size() - 1; ++i) {
- double dx = (*f)[i].second * ((*f)[i+1].first - (*f)[i].first);
- v = (*f)[i].second = v + dx;
- }
- (*f)[f->size()-1].second = v;
- return f;
-}
-
-VirtualSocketServer::Function* VirtualSocketServer::Invert(Function* f) {
- for (Function::size_type i = 0; i < f->size(); ++i)
- std::swap((*f)[i].first, (*f)[i].second);
-
- std::sort(f->begin(), f->end(), FunctionDomainCmp());
- return f;
-}
-
-VirtualSocketServer::Function* VirtualSocketServer::Resample(
- Function* f, double x1, double x2) {
- Function* g = new Function();
-
- for (int i = 0; i < NUM_SAMPLES; i++) {
- double x = x1 + (x2 - x1) * i / (NUM_SAMPLES - 1);
- double y = Evaluate(f, x);
- g->push_back(Point(x, y));
- }
-
- delete f;
- return g;
-}
-
-double VirtualSocketServer::Evaluate(Function* f, double x) {
- Function::iterator iter =
- std::lower_bound(f->begin(), f->end(), x, FunctionDomainCmp());
- if (iter == f->begin()) {
- return (*f)[0].second;
- } else if (iter == f->end()) {
- assert(f->size() >= 1);
- return (*f)[f->size() - 1].second;
- } else if (iter->first == x) {
- return iter->second;
- } else {
- double x1 = (iter - 1)->first;
- double y1 = (iter - 1)->second;
- double x2 = iter->first;
- double y2 = iter->second;
- return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
- }
-}
-
-} // namespace talk_base
diff --git a/talk/base/virtualsocketserver.h b/talk/base/virtualsocketserver.h
deleted file mode 100755
index d2e894a..0000000
--- a/talk/base/virtualsocketserver.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_BASE_VIRTUALSOCKETSERVER_H__
-#define TALK_BASE_VIRTUALSOCKETSERVER_H__
-
-#include <cassert>
-#include <deque>
-#include <map>
-
-#include "talk/base/messagequeue.h"
-#include "talk/base/socketserver.h"
-
-namespace talk_base {
-
-class VirtualSocket;
-
-// Simulates a network in the same manner as a loopback interface. The
-// interface can create as many addresses as you want. All of the sockets
-// created by this network will be able to communicate with one another.
-class VirtualSocketServer : public SocketServer, public MessageHandler {
-public:
- VirtualSocketServer();
- virtual ~VirtualSocketServer();
-
- // Returns a new IP not used before in this network.
- uint32 GetNextIP();
-
- // Limits the network bandwidth (maximum bytes per second). Zero means that
- // all sends occur instantly.
- uint32 bandwidth() { return bandwidth_; }
- void set_bandwidth(uint32 bandwidth) { bandwidth_ = bandwidth; }
-
- // Limits the total size of packets that will be kept in the send queue,
- // waiting for their turn to be written to the network Defaults to 64 KB.
- uint32 queue_capacity() { return queue_capacity_; }
- void set_queue_capacity(uint32 queue_capacity) {
- queue_capacity_ = queue_capacity;
- }
-
- // Controls the (transit) delay for packets sent in the network. This does
- // not inclue the time required to sit in the send queue. Both of these
- // values are measured in milliseconds.
- uint32 delay_mean() { return delay_mean_; }
- uint32 delay_stddev() { return delay_stddev_; }
- void set_delay_mean(uint32 delay_mean) { delay_mean_ = delay_mean; }
- void set_delay_stddev(uint32 delay_stddev) {
- delay_stddev_ = delay_stddev;
- }
-
- // If the (transit) delay parameters are modified, this method should be
- // called to recompute the new distribution.
- void UpdateDelayDistribution();
-
- // Controls the (uniform) probability that any sent packet is dropped. This
- // is separate from calculations to drop based on queue size.
- double drop_probability() { return drop_prob_; }
- void set_drop_probability(double drop_prob) {
- assert((0 <= drop_prob) && (drop_prob <= 1));
- drop_prob_ = drop_prob;
- }
-
- // SocketFactory:
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
-
- // SocketServer:
- virtual bool Wait(int cms, bool process_io);
- virtual void WakeUp();
-
- // Used to send internal wake-up messages.
- virtual void OnMessage(Message* msg);
-
- typedef std::pair<double,double> Point;
- typedef std::vector<Point> Function;
-
-private:
- friend class VirtualSocket;
-
- typedef std::map<SocketAddress, VirtualSocket*> AddressMap;
-
- MessageQueue* msg_queue_;
- bool fWait_;
- uint32 wait_version_;
- uint32 next_ip_;
- uint16 next_port_;
- AddressMap* bindings_;
-
- uint32 bandwidth_;
- uint32 queue_capacity_;
- uint32 delay_mean_;
- uint32 delay_stddev_;
- Function* delay_dist_;
- CriticalSection delay_crit_;
-
- double drop_prob_;
-
- VirtualSocket* CreateSocketInternal(int type);
-
- // Attempts to bind the given socket to the given (non-zero) address.
- int Bind(const SocketAddress& addr, VirtualSocket* socket);
-
- // Binds the given socket to the given (non-zero) IP on an unused port.
- int Bind(VirtualSocket* socket, SocketAddress* addr);
-
- // Removes the binding for the given socket.
- int Unbind(const SocketAddress& addr, VirtualSocket* socket);
-
- // Sends the given packet to the socket at the given address (if one exists).
- int Send(VirtualSocket* socket, const void *pv, size_t cb,
- const SocketAddress& local_addr, const SocketAddress& remote_addr);
-
- // Computes the number of milliseconds required to send a packet of this size.
- uint32 SendDelay(uint32 size);
-
- // Returns the probability density function for the transit delay.
- Function* GetDelayDistribution();
-
- // Returns a random transit delay chosen from the appropriate distribution.
- uint32 GetRandomTransitDelay();
-
- // Basic operations on functions. Those that return a function also take
- // ownership of the function given (and hence, may modify or delete it).
- Function* Accumulate(Function* f);
- Function* Invert(Function* f);
- Function* Resample(Function* f, double x1, double x2);
- double Evaluate(Function* f, double x);
-};
-
-} // namespace talk_base
-
-#endif // TALK_BASE_VIRTUALSOCKETSERVER_H__
diff --git a/talk/base/win32.cc b/talk/base/win32.cc
new file mode 100644
index 0000000..9a816c4
--- /dev/null
+++ b/talk/base/win32.cc
@@ -0,0 +1,183 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/win32.h"
+#include <algorithm>
+
+#include "talk/base/basictypes.h"
+#include "talk/base/common.h"
+
+namespace talk_base {
+
+//
+// Unix time is in seconds relative to 1/1/1970. So we compute the windows
+// FILETIME of that time/date, then we add/subtract in appropriate units to
+// convert to/from unix time.
+// The units of FILETIME are 100ns intervals, so by multiplying by or dividing
+// by 10000000, we can convert to/from seconds.
+//
+// FileTime = UnixTime*10000000 + FileTime(1970)
+// UnixTime = (FileTime-FileTime(1970))/10000000
+//
+
+void FileTimeToUnixTime(const FILETIME& ft, time_t* ut) {
+ ASSERT(NULL != ut);
+
+ // FILETIME has an earlier date base than time_t (1/1/1970), so subtract off
+ // the difference.
+ SYSTEMTIME base_st;
+ memset(&base_st, 0, sizeof(base_st));
+ base_st.wDay = 1;
+ base_st.wMonth = 1;
+ base_st.wYear = 1970;
+
+ FILETIME base_ft;
+ SystemTimeToFileTime(&base_st, &base_ft);
+
+ ULARGE_INTEGER base_ul, current_ul;
+ memcpy(&base_ul, &base_ft, sizeof(FILETIME));
+ memcpy(¤t_ul, &ft, sizeof(FILETIME));
+
+ // Divide by big number to convert to seconds, then subtract out the 1970
+ // base date value.
+ const ULONGLONG RATIO = 10000000;
+ *ut = static_cast<time_t>((current_ul.QuadPart - base_ul.QuadPart) / RATIO);
+}
+
+void UnixTimeToFileTime(const time_t& ut, FILETIME* ft) {
+ ASSERT(NULL != ft);
+
+ // FILETIME has an earlier date base than time_t (1/1/1970), so add in
+ // the difference.
+ SYSTEMTIME base_st;
+ memset(&base_st, 0, sizeof(base_st));
+ base_st.wDay = 1;
+ base_st.wMonth = 1;
+ base_st.wYear = 1970;
+
+ FILETIME base_ft;
+ SystemTimeToFileTime(&base_st, &base_ft);
+
+ ULARGE_INTEGER base_ul;
+ memcpy(&base_ul, &base_ft, sizeof(FILETIME));
+
+ // Multiply by big number to convert to 100ns units, then add in the 1970
+ // base date value.
+ const ULONGLONG RATIO = 10000000;
+ ULARGE_INTEGER current_ul;
+ current_ul.QuadPart = base_ul.QuadPart + static_cast<int64>(ut) * RATIO;
+ memcpy(ft, ¤t_ul, sizeof(FILETIME));
+}
+
+bool Utf8ToWindowsFilename(const std::string& utf8, std::wstring* filename) {
+ // TODO: Integrate into fileutils.h
+ // TODO: Handle wide and non-wide cases via TCHAR?
+ // TODO: Skip \\?\ processing if the length is not > MAX_PATH?
+ // TODO: Write unittests
+
+ // Convert to Utf16
+ int wlen = ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.length() + 1,
+ NULL, 0);
+ if (0 == wlen) {
+ return false;
+ }
+ wchar_t* wfilename = STACK_ARRAY(wchar_t, wlen);
+ if (0 == ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), utf8.length() + 1,
+ wfilename, wlen)) {
+ return false;
+ }
+ // Replace forward slashes with backslashes
+ std::replace(wfilename, wfilename + wlen, L'/', L'\\');
+ // Convert to complete filename
+ DWORD full_len = ::GetFullPathName(wfilename, 0, NULL, NULL);
+ if (0 == full_len) {
+ return false;
+ }
+ wchar_t* filepart = NULL;
+ wchar_t* full_filename = STACK_ARRAY(wchar_t, full_len + 6);
+ wchar_t* start = full_filename + 6;
+ if (0 == ::GetFullPathName(wfilename, full_len, start, &filepart)) {
+ return false;
+ }
+ // Add long-path prefix
+ const wchar_t kLongPathPrefix[] = L"\\\\?\\UNC";
+ if ((start[0] != L'\\') || (start[1] != L'\\')) {
+ // Non-unc path: <pathname>
+ // Becomes: \\?\<pathname>
+ start -= 4;
+ ASSERT(start >= full_filename);
+ memcpy(start, kLongPathPrefix, 4 * sizeof(wchar_t));
+ } else if (start[2] != L'?') {
+ // Unc path: \\<server>\<pathname>
+ // Becomes: \\?\UNC\<server>\<pathname>
+ start -= 6;
+ ASSERT(start >= full_filename);
+ memcpy(start, kLongPathPrefix, 7 * sizeof(wchar_t));
+ } else {
+ // Already in long-path form.
+ }
+ filename->assign(start);
+ return true;
+}
+
+bool GetOsVersion(int* major, int* minor, int* build) {
+ OSVERSIONINFO info = {0};
+ info.dwOSVersionInfoSize = sizeof(info);
+ if (GetVersionEx(&info)) {
+ if (major) *major = info.dwMajorVersion;
+ if (minor) *minor = info.dwMinorVersion;
+ if (build) *build = info.dwBuildNumber;
+ return true;
+ }
+ return false;
+}
+
+bool GetCurrentProcessIntegrityLevel(int* level) {
+ bool ret = false;
+ HANDLE process = GetCurrentProcess(), token;
+ if (OpenProcessToken(process, TOKEN_QUERY | TOKEN_QUERY_SOURCE, &token)) {
+ DWORD size;
+ if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &size) &&
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+
+ char* buf = STACK_ARRAY(char, size);
+ TOKEN_MANDATORY_LABEL* til =
+ reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buf);
+ if (GetTokenInformation(token, TokenIntegrityLevel, til, size, &size)) {
+
+ DWORD count = *GetSidSubAuthorityCount(til->Label.Sid);
+ *level = *GetSidSubAuthority(til->Label.Sid, count - 1);
+ ret = true;
+ }
+ }
+ CloseHandle(token);
+ }
+ return ret;
+}
+
+} // namespace talk_base
+
diff --git a/talk/base/win32.h b/talk/base/win32.h
old mode 100755
new mode 100644
index 082e84f..6274b0e
--- a/talk/base/win32.h
+++ b/talk/base/win32.h
@@ -2,59 +2,80 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_WIN32_H__
-#define TALK_BASE_WIN32_H__
+#ifndef TALK_BASE_WIN32_H_
+#define TALK_BASE_WIN32_H_
+#ifdef WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
#include <winsock2.h>
#include <windows.h>
-#include <malloc.h>
+
+#ifndef SECURITY_MANDATORY_LABEL_AUTHORITY
+// Add defines that we use if we are compiling against older sdks
+#define SECURITY_MANDATORY_MEDIUM_RID (0x00002000L)
+#define TokenIntegrityLevel static_cast<TOKEN_INFORMATION_CLASS>(0x19)
+typedef struct _TOKEN_MANDATORY_LABEL {
+ SID_AND_ATTRIBUTES Label;
+} TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
+#endif // SECURITY_MANDATORY_LABEL_AUTHORITY
+
+#undef SetPort
#include <string>
+#include "talk/base/stringutils.h"
+#include "talk/base/basictypes.h"
+
namespace talk_base {
///////////////////////////////////////////////////////////////////////////////
+inline std::wstring ToUtf16(const char* utf8, size_t len) {
+ int len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
+ wchar_t* ws = STACK_ARRAY(wchar_t, len16);
+ ::MultiByteToWideChar(CP_UTF8, 0, utf8, len, ws, len16);
+ return std::wstring(ws, len16);
+}
+
inline std::wstring ToUtf16(const std::string& str) {
- int len16 = ::MultiByteToWideChar(CP_UTF8, 0, str.data(), str.length(),
- NULL, 0);
- wchar_t *ws = static_cast<wchar_t*>(_alloca(len16 * sizeof(wchar_t)));
- ::MultiByteToWideChar(CP_UTF8, 0, str.data(), str.length(), ws, len16);
- std::wstring result(ws, len16);
- return result;
+ return ToUtf16(str.data(), str.length());
+}
+
+inline std::string ToUtf8(const wchar_t* wide, size_t len) {
+ int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, len, NULL, 0, NULL, NULL);
+ char* ns = STACK_ARRAY(char, len8);
+ ::WideCharToMultiByte(CP_UTF8, 0, wide, len, ns, len8, NULL, NULL);
+ return std::string(ns, len8);
}
inline std::string ToUtf8(const std::wstring& wstr) {
- int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr.length(),
- NULL, 0, NULL, NULL);
- char* ns = static_cast<char*>(_alloca(len8));
- ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr.length(),
- ns, len8, NULL, NULL);
- std::string result(ns, len8);
- return result;
+ return ToUtf8(wstr.data(), wstr.length());
}
// Convert FILETIME to time_t
@@ -63,8 +84,47 @@
// Convert time_t to FILETIME
void UnixTimeToFileTime(const time_t& ut, FILETIME * ft);
+// Convert a Utf8 path representation to a non-length-limited Unicode pathname.
+bool Utf8ToWindowsFilename(const std::string& utf8, std::wstring* filename);
+
+// Convert a FILETIME to a UInt64
+inline uint64 ToUInt64(const FILETIME& ft) {
+ ULARGE_INTEGER r = {ft.dwLowDateTime, ft.dwHighDateTime};
+ return r.QuadPart;
+}
+
+enum WindowsMajorVersions {
+ kWindows2000 = 5,
+ kWindowsVista = 6,
+};
+bool GetOsVersion(int* major, int* minor, int* build);
+
+inline bool IsWindowsVistaOrLater() {
+ int major;
+ return (GetOsVersion(&major, NULL, NULL) && major >= kWindowsVista);
+}
+
+inline bool IsWindowsXpOrLater() {
+ int major, minor;
+ return (GetOsVersion(&major, &minor, NULL) &&
+ (major >= kWindowsVista ||
+ (major == kWindows2000 && minor >= 1)));
+}
+
+// Determine the current integrity level of the process.
+bool GetCurrentProcessIntegrityLevel(int* level);
+
+inline bool IsCurrentProcessLowIntegrity() {
+ int level;
+ return (GetCurrentProcessIntegrityLevel(&level) &&
+ level < SECURITY_MANDATORY_MEDIUM_RID);
+}
+
+bool AdjustCurrentProcessPrivilege(const TCHAR* privilege, bool to_enable);
+
///////////////////////////////////////////////////////////////////////////////
} // namespace talk_base
-#endif // TALK_BASE_WIN32_H__
+#endif // WIN32
+#endif // TALK_BASE_WIN32_H_
diff --git a/talk/base/win32filesystem.cc b/talk/base/win32filesystem.cc
old mode 100755
new mode 100644
index 5b8b023..f2a2256
--- a/talk/base/win32filesystem.cc
+++ b/talk/base/win32filesystem.cc
@@ -24,28 +24,38 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
-#include <cassert>
-
-#include "talk/base/basicdefs.h"
-#include "talk/base/convert.h"
-#include "talk/base/pathutils.h"
-#include "talk/base/fileutils.h"
-#include "talk/base/stringutils.h"
-#include "talk/base/stream.h"
#include "talk/base/win32filesystem.h"
+#include "talk/base/win32.h"
+#include <shellapi.h>
+#include <shlobj.h>
+#include <tchar.h>
+
+#include "talk/base/fileutils.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/stream.h"
+#include "talk/base/stringutils.h"
+
+// In several places in this file, we test the integrity level of the process
+// before calling GetLongPathName. We do this because calling GetLongPathName
+// when running under protected mode IE (a low integrity process) can result in
+// a virtualized path being returned, which is wrong if you only plan to read.
+// TODO: Waiting to hear back from IE team on whether this is the
+// best approach; IEIsProtectedModeProcess is another possible solution.
+
namespace talk_base {
-bool Win32Filesystem::CreateFolderI(const Pathname &pathname) {
- int len = pathname.pathname().length();
-
- if ((len <= 0) || (pathname.pathname().c_str()[len-1] != '\\')) {
+bool Win32Filesystem::CreateFolder(const Pathname &pathname) {
+ if (pathname.pathname().empty() || !pathname.filename().empty())
return false;
- }
- DWORD res = ::GetFileAttributes(Utf16(pathname.pathname()).AsWz());
+ std::wstring path16;
+ if (!Utf8ToWindowsFilename(pathname.pathname(), &path16))
+ return false;
+
+ DWORD res = ::GetFileAttributes(path16.c_str());
if (res != INVALID_FILE_ATTRIBUTES) {
// Something exists at this location, check if it is a directory
return ((res & FILE_ATTRIBUTE_DIRECTORY) != 0);
@@ -54,141 +64,414 @@
// Unexpected error
return false;
}
+
// Directory doesn't exist, look up one directory level
- do {
- --len;
- } while ((len > 0) && (pathname.pathname().c_str()[len-1] != '\\'));
-
- if (!CreateFolder(std::string(pathname.pathname().c_str(),len)))
- return false;
-
- if (pathname.pathname().c_str()[0] != '\\') {
- std::string long_path = std::string("\\\\?\\") + pathname.pathname();
- return (::CreateDirectory(Utf16(long_path).AsWz(), NULL) != 0);
- } else {
- return (::CreateDirectory(Utf16(pathname.pathname()).AsWz(), NULL) != 0);
+ if (!pathname.parent_folder().empty()) {
+ Pathname parent(pathname);
+ parent.SetFolder(pathname.parent_folder());
+ if (!CreateFolder(parent)) {
+ return false;
+ }
}
+
+ return (::CreateDirectory(path16.c_str(), NULL) != 0);
}
-FileStream *Win32Filesystem::OpenFileI(const Pathname &filename,
- const std::string &mode) {
- talk_base::FileStream *fs = new talk_base::FileStream();
- if (fs)
- fs->Open(filename.pathname().c_str(), mode.c_str());
+FileStream *Win32Filesystem::OpenFile(const Pathname &filename,
+ const std::string &mode) {
+ FileStream *fs = new FileStream();
+ if (fs && !fs->Open(filename.pathname().c_str(), mode.c_str())) {
+ delete fs;
+ fs = NULL;
+ }
return fs;
}
-bool Win32Filesystem::DeleteFileI(const Pathname &filename) {
- LOG(LS_INFO) << "Deleting " << filename.pathname();
+bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
+ // To make the file private to the current user, we first must construct a
+ // SECURITY_DESCRIPTOR specifying an ACL. This code is mostly based upon
+ // http://msdn.microsoft.com/en-us/library/ms707085%28VS.85%29.aspx
- if (IsFolder(filename)) {
- Pathname dir;
- dir.SetFolder(filename.pathname());
- DirectoryIterator di;
- di.Iterate(dir.pathname());
- while(di.Next()) {
- if (di.Name() == "." || di.Name() == "..")
- continue;
- Pathname subdir;
- subdir.SetFolder(filename.pathname());
- subdir.SetFilename(di.Name());
-
- if (!DeleteFile(subdir.pathname()))
- return false;
- }
- std::string no_slash(filename.pathname(), 0, filename.pathname().length()-1);
- return ::RemoveDirectory(Utf16(no_slash).AsWz()) == 0;
- }
- return ::DeleteFile(Utf16(filename.pathname()).AsWz()) == 0;
+ // Get the current process token.
+ HANDLE process_token = INVALID_HANDLE_VALUE;
+ if (!::OpenProcessToken(GetCurrentProcess(),
+ TOKEN_QUERY,
+ &process_token)) {
+ LOG_ERR(LS_ERROR) << "OpenProcessToken() failed";
+ return false;
+ }
+
+ // Get the size of its TOKEN_USER structure. Return value is not checked
+ // because we expect it to fail.
+ DWORD token_user_size = 0;
+ (void)::GetTokenInformation(process_token,
+ TokenUser,
+ NULL,
+ 0,
+ &token_user_size);
+
+ // Get the TOKEN_USER structure.
+ scoped_array<char> token_user_bytes(new char[token_user_size]);
+ PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>(
+ token_user_bytes.get());
+ memset(token_user, 0, token_user_size);
+ BOOL success = ::GetTokenInformation(process_token,
+ TokenUser,
+ token_user,
+ token_user_size,
+ &token_user_size);
+ // We're now done with this.
+ ::CloseHandle(process_token);
+ if (!success) {
+ LOG_ERR(LS_ERROR) << "GetTokenInformation() failed";
+ return false;
+ }
+
+ if (!IsValidSid(token_user->User.Sid)) {
+ LOG_ERR(LS_ERROR) << "Current process has invalid user SID";
+ return false;
+ }
+
+ // Compute size needed for an ACL that allows access to just this user.
+ int acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
+ GetLengthSid(token_user->User.Sid);
+
+ // Allocate it.
+ scoped_array<char> acl_bytes(new char[acl_size]);
+ PACL acl = reinterpret_cast<PACL>(acl_bytes.get());
+ memset(acl, 0, acl_size);
+ if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) {
+ LOG_ERR(LS_ERROR) << "InitializeAcl() failed";
+ return false;
+ }
+
+ // Allow access to only the current user.
+ if (!::AddAccessAllowedAce(acl,
+ ACL_REVISION,
+ GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_ALL,
+ token_user->User.Sid)) {
+ LOG_ERR(LS_ERROR) << "AddAccessAllowedAce() failed";
+ return false;
+ }
+
+ // Now make the security descriptor.
+ SECURITY_DESCRIPTOR security_descriptor;
+ if (!::InitializeSecurityDescriptor(&security_descriptor,
+ SECURITY_DESCRIPTOR_REVISION)) {
+ LOG_ERR(LS_ERROR) << "InitializeSecurityDescriptor() failed";
+ return false;
+ }
+
+ // Put the ACL in it.
+ if (!::SetSecurityDescriptorDacl(&security_descriptor,
+ TRUE,
+ acl,
+ FALSE)) {
+ LOG_ERR(LS_ERROR) << "SetSecurityDescriptorDacl() failed";
+ return false;
+ }
+
+ // Finally create the file.
+ SECURITY_ATTRIBUTES security_attributes;
+ security_attributes.nLength = sizeof(security_attributes);
+ security_attributes.lpSecurityDescriptor = &security_descriptor;
+ security_attributes.bInheritHandle = FALSE;
+ HANDLE handle = ::CreateFile(
+ ToUtf16(filename.pathname()).c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &security_attributes,
+ CREATE_NEW,
+ 0,
+ NULL);
+ if (INVALID_HANDLE_VALUE == handle) {
+ LOG_ERR(LS_ERROR) << "CreateFile() failed";
+ return false;
+ }
+ if (!::CloseHandle(handle)) {
+ LOG_ERR(LS_ERROR) << "CloseFile() failed";
+ // Continue.
+ }
+ return true;
}
-bool Win32Filesystem::GetTemporaryFolderI(Pathname &pathname, bool create,
- const std::string *append) {
- ASSERT(!g_application_name_.empty());
+bool Win32Filesystem::DeleteFile(const Pathname &filename) {
+ LOG(LS_INFO) << "Deleting file " << filename.pathname();
+ if (!IsFile(filename)) {
+ ASSERT(IsFile(filename));
+ return false;
+ }
+ return ::DeleteFile(ToUtf16(filename.pathname()).c_str()) != 0;
+}
+
+bool Win32Filesystem::DeleteEmptyFolder(const Pathname &folder) {
+ LOG(LS_INFO) << "Deleting folder " << folder.pathname();
+
+ std::string no_slash(folder.pathname(), 0, folder.pathname().length()-1);
+ return ::RemoveDirectory(ToUtf16(no_slash).c_str()) != 0;
+}
+
+bool Win32Filesystem::GetTemporaryFolder(Pathname &pathname, bool create,
+ const std::string *append) {
wchar_t buffer[MAX_PATH + 1];
if (!::GetTempPath(ARRAY_SIZE(buffer), buffer))
return false;
- if (!::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
+ if (!IsCurrentProcessLowIntegrity() &&
+ !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
return false;
size_t len = strlen(buffer);
if ((len > 0) && (buffer[len-1] != '\\')) {
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- L"\\");
- }
- if ((len > 0) && (buffer[len-1] != '\\')) {
- len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
- L"\\");
+ len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, L"\\");
}
if (len >= ARRAY_SIZE(buffer) - 1)
return false;
pathname.clear();
- pathname.SetFolder(Utf8(buffer).AsSz());
- if (append != NULL)
+ pathname.SetFolder(ToUtf8(buffer));
+ if (append != NULL) {
+ ASSERT(!append->empty());
pathname.AppendFolder(*append);
- if (create)
- CreateFolderI(pathname);
- return true;
+ }
+ return !create || CreateFolder(pathname);
}
-std::string Win32Filesystem::TempFilenameI(const Pathname &dir, const std::string &prefix) {
- wchar_t filename[MAX_PATH];
- if (::GetTempFileName(Utf16(dir.pathname()).AsWz(), Utf16(prefix).AsWz(), 0, filename) == 0)
- return Utf8(filename).AsString();
- return "";
+std::string Win32Filesystem::TempFilename(const Pathname &dir,
+ const std::string &prefix) {
+ wchar_t filename[MAX_PATH];
+ if (::GetTempFileName(ToUtf16(dir.pathname()).c_str(),
+ ToUtf16(prefix).c_str(), 0, filename) != 0)
+ return ToUtf8(filename);
+ ASSERT(false);
+ return "";
}
-bool Win32Filesystem::MoveFileI(const Pathname &old_path, const Pathname &new_path)
-{
- LOG(LS_INFO) << "Moving " << old_path.pathname() << " to " << new_path.pathname();
- if (_wrename(Utf16(old_path.pathname()).AsWz(), Utf16(new_path.pathname()).AsWz()) != 0) {
- if (errno != EXDEV) {
- printf("errno: %d\n", errno);
+bool Win32Filesystem::MoveFile(const Pathname &old_path,
+ const Pathname &new_path) {
+ if (!IsFile(old_path)) {
+ ASSERT(IsFile(old_path));
+ return false;
+ }
+ LOG(LS_INFO) << "Moving " << old_path.pathname()
+ << " to " << new_path.pathname();
+ return ::MoveFile(ToUtf16(old_path.pathname()).c_str(),
+ ToUtf16(new_path.pathname()).c_str()) != 0;
+}
+
+bool Win32Filesystem::MoveFolder(const Pathname &old_path,
+ const Pathname &new_path) {
+ if (!IsFolder(old_path)) {
+ ASSERT(IsFolder(old_path));
+ return false;
+ }
+ LOG(LS_INFO) << "Moving " << old_path.pathname()
+ << " to " << new_path.pathname();
+ if (::MoveFile(ToUtf16(old_path.pathname()).c_str(),
+ ToUtf16(new_path.pathname()).c_str()) == 0) {
+ if (::GetLastError() != ERROR_NOT_SAME_DEVICE) {
+ LOG_GLE(LS_ERROR) << "Failed to move file";
return false;
}
- if (!CopyFile(old_path, new_path))
+ if (!CopyFolder(old_path, new_path))
return false;
- if (!DeleteFile(old_path))
+ if (!DeleteFolderAndContents(old_path))
return false;
}
return true;
}
-bool Win32Filesystem::IsFolderI(const Pathname &path)
-{
+bool Win32Filesystem::IsFolder(const Pathname &path) {
WIN32_FILE_ATTRIBUTE_DATA data = {0};
- if (0 == ::GetFileAttributesEx(Utf16(path.pathname()).AsWz(), GetFileExInfoStandard, &data))
+ if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
+ GetFileExInfoStandard, &data))
return false;
- return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
+ return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
+ FILE_ATTRIBUTE_DIRECTORY;
}
-bool Win32Filesystem::FileExistsI(const Pathname &path)
-{
- DWORD res = ::GetFileAttributes(Utf16(path.pathname()).AsWz());
- return res != INVALID_FILE_ATTRIBUTES;
+bool Win32Filesystem::IsFile(const Pathname &path) {
+ WIN32_FILE_ATTRIBUTE_DATA data = {0};
+ if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
+ GetFileExInfoStandard, &data))
+ return false;
+ return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
-bool Win32Filesystem::CopyFileI(const Pathname &old_path, const Pathname &new_path)
-{
- return ::CopyFile(Utf16(old_path.pathname()).AsWz(), Utf16(new_path.pathname()).AsWz(), TRUE) == 0;
+bool Win32Filesystem::IsAbsent(const Pathname& path) {
+ WIN32_FILE_ATTRIBUTE_DATA data = {0};
+ if (0 != ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
+ GetFileExInfoStandard, &data))
+ return false;
+ DWORD err = ::GetLastError();
+ return (ERROR_FILE_NOT_FOUND == err || ERROR_PATH_NOT_FOUND == err);
}
-bool Win32Filesystem::IsTemporaryPathI(const Pathname& pathname)
-{
+bool Win32Filesystem::CopyFile(const Pathname &old_path,
+ const Pathname &new_path) {
+ return ::CopyFile(ToUtf16(old_path.pathname()).c_str(),
+ ToUtf16(new_path.pathname()).c_str(), TRUE) != 0;
+}
+
+bool Win32Filesystem::IsTemporaryPath(const Pathname& pathname) {
TCHAR buffer[MAX_PATH + 1];
if (!::GetTempPath(ARRAY_SIZE(buffer), buffer))
return false;
- if (!::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
+ if (!IsCurrentProcessLowIntegrity() &&
+ !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
return false;
- return (::strnicmp(Utf16(pathname.pathname()).AsWz(), buffer, strlen(buffer)) == 0);
+ return (::strnicmp(ToUtf16(pathname.pathname()).c_str(),
+ buffer, strlen(buffer)) == 0);
}
-bool Win32Filesystem::GetFileSizeI(const Pathname &pathname, size_t *size)
-{
+bool Win32Filesystem::GetFileSize(const Pathname &pathname, size_t *size) {
WIN32_FILE_ATTRIBUTE_DATA data = {0};
- if (::GetFileAttributesEx(Utf16(pathname.pathname()).AsWz(), GetFileExInfoStandard, &data) == 0)
- return false;
+ if (::GetFileAttributesEx(ToUtf16(pathname.pathname()).c_str(),
+ GetFileExInfoStandard, &data) == 0)
+ return false;
*size = data.nFileSizeLow;
return true;
}
+bool Win32Filesystem::GetFileTime(const Pathname& path, FileTimeType which,
+ time_t* time) {
+ WIN32_FILE_ATTRIBUTE_DATA data = {0};
+ if (::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
+ GetFileExInfoStandard, &data) == 0)
+ return false;
+ switch (which) {
+ case FTT_CREATED:
+ FileTimeToUnixTime(data.ftCreationTime, time);
+ break;
+ case FTT_MODIFIED:
+ FileTimeToUnixTime(data.ftLastWriteTime, time);
+ break;
+ case FTT_ACCESSED:
+ FileTimeToUnixTime(data.ftLastAccessTime, time);
+ break;
+ default:
+ return false;
+ }
+ return true;
}
+
+bool Win32Filesystem::GetAppPathname(Pathname* path) {
+ TCHAR buffer[MAX_PATH + 1];
+ if (0 == ::GetModuleFileName(NULL, buffer, ARRAY_SIZE(buffer)))
+ return false;
+ path->SetPathname(ToUtf8(buffer));
+ return true;
+}
+
+bool Win32Filesystem::GetAppDataFolder(Pathname* path, bool per_user) {
+ ASSERT(!organization_name_.empty());
+ ASSERT(!application_name_.empty());
+ TCHAR buffer[MAX_PATH + 1];
+ int csidl = per_user ? CSIDL_LOCAL_APPDATA : CSIDL_COMMON_APPDATA;
+ if (!::SHGetSpecialFolderPath(NULL, buffer, csidl, TRUE))
+ return false;
+ if (!IsCurrentProcessLowIntegrity() &&
+ !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
+ return false;
+ size_t len = strcatn(buffer, ARRAY_SIZE(buffer), __T("\\"));
+ len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
+ ToUtf16(organization_name_).c_str());
+ if ((len > 0) && (buffer[len-1] != __T('\\'))) {
+ len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, __T("\\"));
+ }
+ len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
+ ToUtf16(application_name_).c_str());
+ if ((len > 0) && (buffer[len-1] != __T('\\'))) {
+ len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, __T("\\"));
+ }
+ if (len >= ARRAY_SIZE(buffer) - 1)
+ return false;
+ path->clear();
+ path->SetFolder(ToUtf8(buffer));
+ return CreateFolder(*path);
+}
+
+bool Win32Filesystem::GetAppTempFolder(Pathname* path) {
+ if (!GetAppPathname(path))
+ return false;
+ std::string filename(path->filename());
+ return GetTemporaryFolder(*path, true, &filename);
+}
+
+bool Win32Filesystem::GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
+ if (!freebytes) {
+ return false;
+ }
+ char drive[4];
+ std::wstring drive16;
+ const wchar_t* target_drive = NULL;
+ if (path.GetDrive(drive, sizeof(drive))) {
+ drive16 = ToUtf16(drive);
+ target_drive = drive16.c_str();
+ } else if (path.folder().substr(0, 2) == "\\\\") {
+ // UNC path, fail.
+ // TODO: Handle UNC paths.
+ return false;
+ } else {
+ // The path is probably relative. GetDriveType and GetDiskFreeSpaceEx
+ // use the current drive if NULL is passed as the drive name.
+ // TODO: Add method to Pathname to determine if the path is relative.
+ // TODO: Add method to Pathname to convert a path to absolute.
+ }
+ UINT driveType = ::GetDriveType(target_drive);
+ if ( (driveType & DRIVE_REMOTE) || (driveType & DRIVE_UNKNOWN) ) {
+ LOG(LS_VERBOSE) << " remove or unknown drive " << drive;
+ return false;
+ }
+
+ int64 totalNumberOfBytes; // receives the number of bytes on disk
+ int64 totalNumberOfFreeBytes; // receives the free bytes on disk
+ // make sure things won't change in 64 bit machine
+ // TODO replace with compile time assert
+ ASSERT(sizeof(ULARGE_INTEGER) == sizeof(uint64)); //NOLINT
+ if (::GetDiskFreeSpaceEx(target_drive,
+ (PULARGE_INTEGER)freebytes,
+ (PULARGE_INTEGER)&totalNumberOfBytes,
+ (PULARGE_INTEGER)&totalNumberOfFreeBytes)) {
+ return true;
+ } else {
+ LOG(LS_VERBOSE) << " GetDiskFreeSpaceEx returns error ";
+ return false;
+ }
+}
+
+Pathname Win32Filesystem::GetCurrentDirectory() {
+ Pathname cwd;
+ int path_len = 0;
+ scoped_array<wchar_t> path;
+ do {
+ int needed = ::GetCurrentDirectory(path_len, path.get());
+ if (needed == 0) {
+ // Error.
+ LOG_GLE(LS_ERROR) << "::GetCurrentDirectory() failed";
+ return cwd; // returns empty pathname
+ }
+ if (needed <= path_len) {
+ // It wrote successfully.
+ break;
+ }
+ // Else need to re-alloc for "needed".
+ path.reset(new wchar_t[needed]);
+ path_len = needed;
+ } while (true);
+ cwd.SetFolder(ToUtf8(path.get()));
+ return cwd;
+}
+
+// TODO: Consider overriding DeleteFolderAndContents for speed and potentially
+// better OS integration (recycle bin?)
+/*
+ std::wstring temp_path16 = ToUtf16(temp_path.pathname());
+ temp_path16.append(1, '*');
+ temp_path16.append(1, '\0');
+
+ SHFILEOPSTRUCT file_op = { 0 };
+ file_op.wFunc = FO_DELETE;
+ file_op.pFrom = temp_path16.c_str();
+ file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
+ return (0 == SHFileOperation(&file_op));
+*/
+
+} // namespace talk_base
diff --git a/talk/base/win32filesystem.h b/talk/base/win32filesystem.h
old mode 100755
new mode 100644
index 1c13157..c17bdd9
--- a/talk/base/win32filesystem.h
+++ b/talk/base/win32filesystem.h
@@ -32,60 +32,87 @@
namespace talk_base {
-class Win32Filesystem : public Filesystem{
+class Win32Filesystem : public FilesystemInterface {
public:
-
- virtual bool CreateFolderI(const Pathname &pathname);
-
// Opens a file. Returns an open StreamInterface if function succeeds. Otherwise,
// returns NULL.
- virtual FileStream *OpenFileI(const Pathname &filename,
- const std::string &mode);
+ virtual FileStream *OpenFile(const Pathname &filename,
+ const std::string &mode);
- // This will attempt to delete the path located at filename. If filename is a file,
- // it will be unlinked. If the path is a directory, it will recursively unlink and remove
- // all the files and directory within it
- virtual bool DeleteFileI(const Pathname &filename);
+ // Atomically creates an empty file accessible only to the current user if one
+ // does not already exist at the given path, otherwise fails.
+ virtual bool CreatePrivateFile(const Pathname &filename);
+
+ // This will attempt to delete the path located at filename.
+ // If the path points to a folder, it will fail with VERIFY
+ virtual bool DeleteFile(const Pathname &filename);
+
+ // This will attempt to delete an empty folder. If the path does not point to
+ // a folder, it fails with VERIFY. If the folder is not empty, it fails normally
+ virtual bool DeleteEmptyFolder(const Pathname &folder);
// Creates a directory. This will call itself recursively to create /foo/bar even if
// /foo does not exist.
// Returns TRUE if function succeeds
+ virtual bool CreateFolder(const Pathname &pathname);
- // This moves a file from old_path to new_path, where "file" can be a plain file
- // or directory, which will be moved recursively.
- // Returns true if function succeeds.
- virtual bool MoveFileI(const Pathname &old_path, const Pathname &new_path);
+ // This moves a file from old_path to new_path. If the new path is on a
+ // different volume than the old, it will attempt to copy and then delete
+ // the folder
+ // Returns true if the file is successfully moved
+ virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path);
- // This copies a file from old_path to _new_path where "file" can be a plain file
- // or directory, which will be copied recursively.
+ // Moves a folder from old_path to new_path. If the new path is on a different
+ // volume from the old, it will attempt to Copy and then Delete the folder
+ // Returns true if the folder is successfully moved
+ virtual bool MoveFolder(const Pathname &old_path, const Pathname &new_path);
+
+ // This copies a file from old_path to _new_path
// Returns true if function succeeds
- virtual bool CopyFileI(const Pathname &old_path, const Pathname &new_path);
+ virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path);
// Returns true if a pathname is a directory
- virtual bool IsFolderI(const Pathname& pathname);
+ virtual bool IsFolder(const Pathname& pathname);
// Returns true if a file exists at path
- virtual bool FileExistsI(const Pathname &path);
+ virtual bool IsFile(const Pathname &path);
+
+ // Returns true if pathname refers to no filesystem object, every parent
+ // directory either exists, or is also absent.
+ virtual bool IsAbsent(const Pathname& pathname);
// Returns true if pathname represents a temporary location on the system.
- virtual bool IsTemporaryPathI(const Pathname& pathname);
-
+ virtual bool IsTemporaryPath(const Pathname& pathname);
// All of the following functions set pathname and return true if successful.
// Returned paths always include a trailing backslash.
// If create is true, the path will be recursively created.
// If append is non-NULL, it will be appended (and possibly created).
- virtual std::string TempFilenameI(const Pathname &dir, const std::string &prefix);
+ virtual std::string TempFilename(const Pathname &dir, const std::string &prefix);
- virtual bool GetFileSizeI(const Pathname &pathname, size_t *size);
-
+ virtual bool GetFileSize(const Pathname& path, size_t* size);
+ virtual bool GetFileTime(const Pathname& path, FileTimeType which,
+ time_t* time);
+
// A folder appropriate for storing temporary files (Contents are
// automatically deleted when the program exists)
- virtual bool GetTemporaryFolderI(Pathname &path, bool create,
+ virtual bool GetTemporaryFolder(Pathname &path, bool create,
const std::string *append);
- };
-}
+ // Returns the path to the running application.
+ virtual bool GetAppPathname(Pathname* path);
+
+ virtual bool GetAppDataFolder(Pathname* path, bool per_user);
+
+ // Get a temporary folder that is unique to the current user and application.
+ virtual bool GetAppTempFolder(Pathname* path);
+
+ virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes);
+
+ virtual Pathname GetCurrentDirectory();
+};
+
+} // namespace talk_base
#endif // _WIN32FILESYSTEM_H__
diff --git a/talk/base/win32securityerrors.cc b/talk/base/win32securityerrors.cc
new file mode 100644
index 0000000..50f4f66
--- /dev/null
+++ b/talk/base/win32securityerrors.cc
@@ -0,0 +1,66 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/win32.h"
+#include "talk/base/logging.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern const ConstantLabel SECURITY_ERRORS[];
+
+const ConstantLabel SECURITY_ERRORS[] = {
+ KLABEL(SEC_I_COMPLETE_AND_CONTINUE),
+ KLABEL(SEC_I_COMPLETE_NEEDED),
+ KLABEL(SEC_I_CONTEXT_EXPIRED),
+ KLABEL(SEC_I_CONTINUE_NEEDED),
+ KLABEL(SEC_I_INCOMPLETE_CREDENTIALS),
+ KLABEL(SEC_I_RENEGOTIATE),
+ KLABEL(SEC_E_CERT_EXPIRED),
+ KLABEL(SEC_E_INCOMPLETE_MESSAGE),
+ KLABEL(SEC_E_INSUFFICIENT_MEMORY),
+ KLABEL(SEC_E_INTERNAL_ERROR),
+ KLABEL(SEC_E_INVALID_HANDLE),
+ KLABEL(SEC_E_INVALID_TOKEN),
+ KLABEL(SEC_E_LOGON_DENIED),
+ KLABEL(SEC_E_NO_AUTHENTICATING_AUTHORITY),
+ KLABEL(SEC_E_NO_CREDENTIALS),
+ KLABEL(SEC_E_NOT_OWNER),
+ KLABEL(SEC_E_OK),
+ KLABEL(SEC_E_SECPKG_NOT_FOUND),
+ KLABEL(SEC_E_TARGET_UNKNOWN),
+ KLABEL(SEC_E_UNKNOWN_CREDENTIALS),
+ KLABEL(SEC_E_UNSUPPORTED_FUNCTION),
+ KLABEL(SEC_E_UNTRUSTED_ROOT),
+ KLABEL(SEC_E_WRONG_PRINCIPAL),
+ LASTLABEL
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/natsocketfactory.h b/talk/base/win32socketinit.cc
old mode 100755
new mode 100644
similarity index 60%
copy from talk/base/natsocketfactory.h
copy to talk/base/win32socketinit.cc
index a689158..f6ac666
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/win32socketinit.cc
@@ -1,51 +1,63 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2009, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+#include "talk/base/win32socketinit.h"
-#include "talk/base/socketfactory.h"
+#include "talk/base/win32.h"
namespace talk_base {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+// Please don't remove this function.
+void EnsureWinsockInit() {
+ // The default implementation uses a global initializer, so WSAStartup
+ // happens at module load time. Thus we don't need to do anything here.
+ // The hook is provided so that a client that statically links with
+ // libjingle can override it, to provide its own initialization.
+}
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
-
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
+#ifdef WIN32
+class WinsockInitializer {
+ public:
+ WinsockInitializer() {
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(1, 0);
+ err_ = WSAStartup(wVersionRequested, &wsaData);
+ }
+ ~WinsockInitializer() {
+ if (!err_)
+ WSACleanup();
+ }
+ int error() {
+ return err_;
+ }
+ private:
+ int err_;
};
+WinsockInitializer g_winsockinit;
+#endif
-} // namespace talk_base
-
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+} // namespace talk_base
diff --git a/talk/base/natsocketfactory.h b/talk/base/win32socketinit.h
old mode 100755
new mode 100644
similarity index 64%
copy from talk/base/natsocketfactory.h
copy to talk/base/win32socketinit.h
index a689158..f56b7ff
--- a/talk/base/natsocketfactory.h
+++ b/talk/base/win32socketinit.h
@@ -1,51 +1,37 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2009, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
-
-#include "talk/base/socketfactory.h"
+#ifndef TALK_BASE_WIN32SOCKETINIT_H_
+#define TALK_BASE_WIN32SOCKETINIT_H_
namespace talk_base {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+void EnsureWinsockInit();
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+} // namespace talk_base
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
-};
-
-} // namespace talk_base
-
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif // TALK_BASE_WIN32SOCKETINIT_H_
diff --git a/talk/base/win32socketserver.cc b/talk/base/win32socketserver.cc
old mode 100755
new mode 100644
index 49c8fee..490799c
--- a/talk/base/win32socketserver.cc
+++ b/talk/base/win32socketserver.cc
@@ -2,36 +2,36 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "talk/base/win32socketserver.h"
#include "talk/base/byteorder.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
#include "talk/base/winping.h"
-#include "talk/base/win32socketserver.h"
#include "talk/base/win32window.h"
-#include <ws2tcpip.h>
+#include <ws2tcpip.h> // NOLINT
namespace talk_base {
@@ -39,26 +39,25 @@
// Win32Socket
///////////////////////////////////////////////////////////////////////////////
-static const int kfRead = 0x0001;
-static const int kfWrite = 0x0002;
-
+// TODO: Move this to a common place where PhysicalSocketServer can
+// share it.
// Standard MTUs
static const uint16 PACKET_MAXIMUMS[] = {
65535, // Theoretical maximum, Hyperchannel
32000, // Nothing
17914, // 16Mb IBM Token Ring
8166, // IEEE 802.4
- //4464, // IEEE 802.5 (4Mb max)
+ // 4464 // IEEE 802.5 (4Mb max)
4352, // FDDI
- //2048, // Wideband Network
+ // 2048, // Wideband Network
2002, // IEEE 802.5 (4Mb recommended)
- //1536, // Expermental Ethernet Networks
- //1500, // Ethernet, Point-to-Point (default)
+ // 1536, // Expermental Ethernet Networks
+ // 1500, // Ethernet, Point-to-Point (default)
1492, // IEEE 802.3
1006, // SLIP, ARPANET
- //576, // X.25 Networks
- //544, // DEC IP Portal
- //512, // NETBIOS
+ // 576, // X.25 Networks
+ // 544, // DEC IP Portal
+ // 512, // NETBIOS
508, // IEEE 802/Source-Rt Bridge, ARCNET
296, // Point-to-Point (low delay)
68, // Official minimum
@@ -68,7 +67,8 @@
static const uint32 IP_HEADER_SIZE = 20;
static const uint32 ICMP_HEADER_SIZE = 8;
-#ifdef DEBUG
+// TODO: Enable for production builds also? Use FormatMessage?
+#ifdef _DEBUG
LPCSTR WSAErrorToString(int error, LPCSTR *description_result) {
LPCSTR string = "Unspecified";
LPCSTR description = "Unspecified description";
@@ -136,9 +136,7 @@
return string;
}
-void ReportWSAError(LPCSTR context, int error, const sockaddr_in& addr) {
- talk_base::SocketAddress address;
- address.FromSockAddr(addr);
+void ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {
LPCSTR description_string;
LPCSTR error_string = WSAErrorToString(error, &description_string);
LOG(LS_INFO) << context << " = " << error
@@ -146,7 +144,7 @@
<< address.ToString() << "]";
}
#else
-void ReportWSAError(LPCSTR context, int error, const sockaddr_in& addr) { }
+void ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {}
#endif
/////////////////////////////////////////////////////////////////////////////
@@ -163,8 +161,8 @@
};
class Win32Socket::EventSink : public Win32Window {
-public:
- EventSink(Win32Socket * parent) : parent_(parent) { }
+ public:
+ explicit EventSink(Win32Socket * parent) : parent_(parent) { }
void Dispose();
@@ -172,15 +170,14 @@
LRESULT& result);
virtual void OnFinalMessage(HWND hWnd);
-private:
+ private:
bool OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result);
bool OnDnsNotify(WPARAM wParam, LPARAM lParam, LRESULT& result);
Win32Socket * parent_;
};
-void
-Win32Socket::EventSink::Dispose() {
+void Win32Socket::EventSink::Dispose() {
parent_ = NULL;
if (::IsWindow(handle())) {
::DestroyWindow(handle());
@@ -189,8 +186,8 @@
}
}
-bool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
- LRESULT& result) {
+bool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam,
+ LPARAM lParam, LRESULT& result) {
switch (uMsg) {
case WM_SOCKETNOTIFY:
case WM_TIMER:
@@ -201,62 +198,35 @@
return false;
}
-bool
-Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam,
- LRESULT& result) {
+bool Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam,
+ LPARAM lParam, LRESULT& result) {
result = 0;
- // Make sure the socket isn't already closed
- if (!parent_ || (parent_->socket_ == INVALID_SOCKET))
- return true;
-
- int event = WSAGETSELECTEVENT(lParam);
+ int wsa_event = WSAGETSELECTEVENT(lParam);
int wsa_error = WSAGETSELECTERROR(lParam);
+ // Treat connect timeouts as close notifications
if (uMsg == WM_TIMER) {
- event = FD_CLOSE;
+ wsa_event = FD_CLOSE;
wsa_error = WSAETIMEDOUT;
- } else if (event == FD_CLOSE) {
- char ch;
- if (::recv(parent_->socket_, &ch, 1, MSG_PEEK) > 0) {
- parent_->signal_close_ = true;
- return true;
- }
}
- parent_->OnSocketNotify(event, wsa_error);
+ if (parent_)
+ parent_->OnSocketNotify(static_cast<SOCKET>(wParam), wsa_event, wsa_error);
return true;
}
-bool
-Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam,
- LRESULT& result) {
+bool Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam,
+ LRESULT& result) {
result = 0;
- if (!parent_)
- return true;
-
- if (!parent_->dns_ ||
- (parent_->dns_->handle != reinterpret_cast<HANDLE>(wParam))) {
- ASSERT(false);
- return true;
- }
-
- uint32 ip = 0;
int error = WSAGETASYNCERROR(lParam);
-
- if (error == 0) {
- hostent * pHost = reinterpret_cast<hostent *>(parent_->dns_->buffer);
- uint32 net_ip = *reinterpret_cast<uint32 *>(pHost->h_addr_list[0]);
- ip = talk_base::NetworkToHost32(net_ip);
- }
-
- parent_->OnDnsNotify(ip, error);
+ if (parent_)
+ parent_->OnDnsNotify(reinterpret_cast<HANDLE>(wParam), error);
return true;
}
-void
-Win32Socket::EventSink::OnFinalMessage(HWND hWnd) {
+void Win32Socket::EventSink::OnFinalMessage(HWND hWnd) {
delete this;
}
@@ -265,18 +235,29 @@
/////////////////////////////////////////////////////////////////////////////
Win32Socket::Win32Socket()
- : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED),
- signal_close_(false), sink_(NULL), dns_(NULL) {
- // TODO: replace addr_ with SocketAddress
- memset(&addr_, 0, sizeof(addr_));
+ : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED), connect_time_(0),
+ closing_(false), close_error_(0), sink_(NULL), dns_(NULL) {
}
Win32Socket::~Win32Socket() {
Close();
}
-int
-Win32Socket::Attach(SOCKET s) {
+bool Win32Socket::CreateT(int type) {
+ Close();
+ int proto = (SOCK_DGRAM == type) ? IPPROTO_UDP : IPPROTO_TCP;
+ socket_ = ::WSASocket(AF_INET, type, proto, NULL, NULL, 0);
+ if (socket_ == INVALID_SOCKET) {
+ UpdateLastError();
+ return false;
+ }
+ if ((SOCK_DGRAM == type) && !SetAsync(FD_READ | FD_WRITE)) {
+ return false;
+ }
+ return true;
+}
+
+int Win32Socket::Attach(SOCKET s) {
ASSERT(socket_ == INVALID_SOCKET);
if (socket_ != INVALID_SOCKET)
return SOCKET_ERROR;
@@ -288,79 +269,72 @@
socket_ = s;
state_ = CS_CONNECTED;
- if (!Create(FD_READ | FD_WRITE | FD_CLOSE))
+ if (!SetAsync(FD_READ | FD_WRITE | FD_CLOSE))
return SOCKET_ERROR;
return 0;
}
-void
-Win32Socket::SetTimeout(int ms) {
- if (sink_)
+void Win32Socket::SetTimeout(int ms) {
+ if (sink_)
::SetTimer(sink_->handle(), 1, ms, 0);
}
-talk_base::SocketAddress
-Win32Socket::GetLocalAddress() const {
+SocketAddress Win32Socket::GetLocalAddress() const {
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
- int result = ::getsockname(socket_, (sockaddr*)&addr, &addrlen);
- ASSERT(addrlen == sizeof(addr));
- talk_base::SocketAddress address;
+ int result = ::getsockname(socket_, reinterpret_cast<sockaddr*>(&addr),
+ &addrlen);
+ SocketAddress address;
if (result >= 0) {
+ ASSERT(addrlen == sizeof(addr));
address.FromSockAddr(addr);
} else {
- ASSERT(result >= 0);
+ LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
+ << socket_;
}
return address;
}
-talk_base::SocketAddress
-Win32Socket::GetRemoteAddress() const {
+SocketAddress Win32Socket::GetRemoteAddress() const {
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
- int result = ::getpeername(socket_, (sockaddr*)&addr, &addrlen);
+ int result = ::getpeername(socket_, reinterpret_cast<sockaddr*>(&addr),
+ &addrlen);
ASSERT(addrlen == sizeof(addr));
- talk_base::SocketAddress address;
+ SocketAddress address;
if (result >= 0) {
+ ASSERT(addrlen == sizeof(addr));
address.FromSockAddr(addr);
} else {
- ASSERT(errno == ENOTCONN);
+ LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
+ << socket_;
}
return address;
}
-int
-Win32Socket::Bind(const talk_base::SocketAddress& addr) {
- ASSERT(socket_ == INVALID_SOCKET);
- if (socket_ != INVALID_SOCKET)
- return SOCKET_ERROR;
-
- if (!Create(FD_ACCEPT | FD_CLOSE))
+int Win32Socket::Bind(const SocketAddress& addr) {
+ ASSERT(socket_ != INVALID_SOCKET);
+ if (socket_ == INVALID_SOCKET)
return SOCKET_ERROR;
sockaddr_in saddr;
addr.ToSockAddr(&saddr);
- int err = ::bind(socket_, (sockaddr*)&saddr, sizeof(saddr));
+ int err = ::bind(socket_, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr));
UpdateLastError();
return err;
}
-int
-Win32Socket::Connect(const talk_base::SocketAddress& addr) {
- ASSERT(socket_ == INVALID_SOCKET);
- if (socket_ != INVALID_SOCKET)
+int Win32Socket::Connect(const SocketAddress& addr) {
+ if ((socket_ == INVALID_SOCKET) && !CreateT(SOCK_STREAM))
return SOCKET_ERROR;
- if (!Create(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE))
+ if (!sink_ && !SetAsync(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE))
return SOCKET_ERROR;
+ // If we have an IP address, connect now.
if (!addr.IsUnresolved()) {
- sockaddr_in saddr;
- addr.ToSockAddr(&saddr);
-
- // now connect
- return DoConnect(saddr);
+ return DoConnect(addr);
}
LOG_F(LS_INFO) << "async dns lookup (" << addr.IPAsString() << ")";
@@ -382,13 +356,19 @@
return 0;
}
-int
-Win32Socket::DoConnect(const sockaddr_in& addr) {
- connect_time_ = talk_base::GetMillisecondCount();
- int result = connect(socket_, (SOCKADDR*)&addr, sizeof(addr));
- if (result == SOCKET_ERROR) {
+int Win32Socket::DoConnect(const SocketAddress& addr) {
+ sockaddr_in saddr;
+ addr.ToSockAddr(&saddr);
+ connect_time_ = Time();
+ int result = connect(socket_, reinterpret_cast<SOCKADDR*>(&saddr),
+ sizeof(saddr));
+ if (result != SOCKET_ERROR) {
+ state_ = CS_CONNECTED;
+ } else {
int code = WSAGetLastError();
- if (code != WSAEWOULDBLOCK) {
+ if (code == WSAEWOULDBLOCK) {
+ state_ = CS_CONNECTING;
+ } else {
ReportWSAError("WSAAsync:connect", code, addr);
error_ = code;
Close();
@@ -396,180 +376,96 @@
}
}
addr_ = addr;
- state_ = CS_CONNECTING;
+
return 0;
}
-void
-Win32Socket::OnSocketNotify(int event, int error) {
- error_ = error;
- switch (event) {
- case FD_CONNECT:
- if (error != ERROR_SUCCESS) {
- ReportWSAError("WSAAsync:connect notify", error, addr_);
-#ifdef DEBUG
- int32 duration = talk_base::TimeDiff(talk_base::GetMillisecondCount(),
- connect_time_);
- LOG(LS_INFO) << "WSAAsync:connect error (" << duration
- << " ms), faking close";
-#endif
- Close();
- // If you get an error connecting, close doesn't really do anything
- // and it certainly doesn't send back any close notification, but
- // we really only maintain a few states, so it is easiest to get
- // back into a known state by pretending that a close happened, even
- // though the connect event never did occur.
- SignalCloseEvent(this, error);
- } else {
-#ifdef DEBUG
- int32 duration = talk_base::TimeDiff(talk_base::GetMillisecondCount(),
- connect_time_);
- LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)";
-#endif
- state_ = CS_CONNECTED;
- SignalConnectEvent(this);
- }
- break;
-
- case FD_ACCEPT:
- case FD_READ:
- if (error != ERROR_SUCCESS) {
- ReportWSAError("WSAAsync:read notify", error, addr_);
- Close();
- } else {
- SignalReadEvent(this);
- }
- break;
-
- case FD_WRITE:
- if (error != ERROR_SUCCESS) {
- ReportWSAError("WSAAsync:write notify", error, addr_);
- Close();
- } else {
- SignalWriteEvent(this);
- }
- break;
-
- case FD_CLOSE:
- ReportWSAError("WSAAsync:close notify", error, addr_);
- Close();
- SignalCloseEvent(this, error);
- break;
- }
-}
-
-void
-Win32Socket::OnDnsNotify(int ip, int error) {
- LOG_F(LS_INFO) << "(" << talk_base::SocketAddress::IPToString(ip)
- << ", " << error << ")";
- if (error == 0) {
- talk_base::SocketAddress address(ip, dns_->port);
- sockaddr_in addr;
- address.ToSockAddr(&addr);
- error = DoConnect(addr);
- } else {
- Close();
- }
-
- if (error) {
- error_ = error;
- SignalCloseEvent(this, error_);
- } else {
- delete dns_;
- dns_ = NULL;
- }
-}
-
-int
-Win32Socket::GetError() const {
+int Win32Socket::GetError() const {
return error_;
}
-void
-Win32Socket::SetError(int error) {
+void Win32Socket::SetError(int error) {
error_ = error;
}
-Socket::ConnState
-Win32Socket::GetState() const {
+Socket::ConnState Win32Socket::GetState() const {
return state_;
}
-int
-Win32Socket::SetOption(Option opt, int value) {
- ASSERT(opt == OPT_DONTFRAGMENT);
- value = (value == 0) ? 0 : 1;
- return ::setsockopt(socket_, IPPROTO_IP, IP_DONTFRAGMENT,
- reinterpret_cast<char*>(&value), sizeof(value));
+int Win32Socket::GetOption(Option opt, int* value) {
+ int slevel;
+ int sopt;
+ if (TranslateOption(opt, &slevel, &sopt) == -1)
+ return -1;
+
+ char* p = reinterpret_cast<char*>(value);
+ int optlen = sizeof(value);
+ return ::getsockopt(socket_, slevel, sopt, p, &optlen);
}
-int
-Win32Socket::Send(const void *pv, size_t cb) {
- int sent = ::send(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0);
+int Win32Socket::SetOption(Option opt, int value) {
+ int slevel;
+ int sopt;
+ if (TranslateOption(opt, &slevel, &sopt) == -1)
+ return -1;
+
+ const char* p = reinterpret_cast<const char*>(&value);
+ return ::setsockopt(socket_, slevel, sopt, p, sizeof(value));
+}
+
+int Win32Socket::Send(const void *pv, size_t cb) {
+ int sent = ::send(socket_, reinterpret_cast<const char*>(pv), cb, 0);
UpdateLastError();
return sent;
}
-int
-Win32Socket::SendTo(const void *pv, size_t cb,
- const talk_base::SocketAddress& addr) {
+int Win32Socket::SendTo(const void *pv, size_t cb,
+ const SocketAddress& addr) {
sockaddr_in saddr;
addr.ToSockAddr(&saddr);
- int sent = ::sendto(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0,
- (sockaddr*)&saddr, sizeof(saddr));
+ int sent = ::sendto(socket_, reinterpret_cast<const char*>(pv), cb, 0,
+ reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr));
UpdateLastError();
return sent;
}
-int
-Win32Socket::Recv(void *pv, size_t cb) {
- int received = ::recv(socket_, (char *)pv, (int)cb, 0);
+int Win32Socket::Recv(void *pv, size_t cb) {
+ int received = ::recv(socket_, static_cast<char*>(pv), cb, 0);
UpdateLastError();
- if (signal_close_ && (received > 0)) {
- char ch;
- if (::recv(socket_, &ch, 1, MSG_PEEK) <= 0) {
- signal_close_ = false;
- ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,
- WSAMAKESELECTREPLY(FD_CLOSE, 0), 0);
- }
- }
+ if (closing_ && received <= static_cast<int>(cb))
+ PostClosed();
return received;
}
-int
-Win32Socket::RecvFrom(void *pv, size_t cb, talk_base::SocketAddress *paddr) {
+int Win32Socket::RecvFrom(void *pv, size_t cb,
+ SocketAddress *paddr) {
sockaddr_in saddr;
socklen_t cbAddr = sizeof(saddr);
- int received = ::recvfrom(socket_, (char *)pv, (int)cb, 0, (sockaddr*)&saddr,
- &cbAddr);
+ int received = ::recvfrom(socket_, static_cast<char*>(pv), cb, 0,
+ reinterpret_cast<sockaddr*>(&saddr), &cbAddr);
UpdateLastError();
if (received != SOCKET_ERROR)
paddr->FromSockAddr(saddr);
- if (signal_close_ && (received > 0)) {
- char ch;
- if (::recv(socket_, &ch, 1, MSG_PEEK) <= 0) {
- signal_close_ = false;
- ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,
- WSAMAKESELECTREPLY(FD_CLOSE, 0), 0);
- }
- }
+ if (closing_ && received <= static_cast<int>(cb))
+ PostClosed();
return received;
}
-int
-Win32Socket::Listen(int backlog) {
+int Win32Socket::Listen(int backlog) {
int err = ::listen(socket_, backlog);
+ if (!SetAsync(FD_ACCEPT))
+ return SOCKET_ERROR;
+
UpdateLastError();
if (err == 0)
state_ = CS_CONNECTING;
return err;
}
-talk_base::Socket*
-Win32Socket::Accept(talk_base::SocketAddress *paddr) {
+Win32Socket* Win32Socket::Accept(SocketAddress *paddr) {
sockaddr_in saddr;
socklen_t cbAddr = sizeof(saddr);
- SOCKET s = ::accept(socket_, (sockaddr*)&saddr, &cbAddr);
+ SOCKET s = ::accept(socket_, reinterpret_cast<sockaddr*>(&saddr), &cbAddr);
UpdateLastError();
if (s == INVALID_SOCKET)
return NULL;
@@ -582,13 +478,13 @@
return NULL;
}
-int
-Win32Socket::Close() {
+int Win32Socket::Close() {
int err = 0;
if (socket_ != INVALID_SOCKET) {
err = ::closesocket(socket_);
socket_ = INVALID_SOCKET;
- signal_close_ = false;
+ closing_ = false;
+ close_error_ = 0;
UpdateLastError();
}
if (dns_) {
@@ -600,34 +496,32 @@
sink_->Dispose();
sink_ = NULL;
}
- memset(&addr_, 0, sizeof(addr_)); // no longer connected, zero ip/port
+ addr_.Clear();
state_ = CS_CLOSED;
return err;
}
-int
-Win32Socket::EstimateMTU(uint16* mtu) {
- talk_base::SocketAddress addr = GetRemoteAddress();
+int Win32Socket::EstimateMTU(uint16* mtu) {
+ SocketAddress addr = GetRemoteAddress();
if (addr.IsAny()) {
error_ = ENOTCONN;
return -1;
}
- talk_base::WinPing ping;
+ WinPing ping;
if (!ping.IsValid()) {
- error_ = EINVAL; // can't think of a better error ID
+ error_ = EINVAL; // can't think of a better error ID
return -1;
}
for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
- talk_base::WinPing::PingResult result =
- ping.Ping(addr.ip(), size, 0, 1, false);
- if (result == talk_base::WinPing::PING_FAIL) {
- error_ = EINVAL; // can't think of a better error ID
+ WinPing::PingResult result = ping.Ping(addr.ip(), size, 0, 1, false);
+ if (result == WinPing::PING_FAIL) {
+ error_ = EINVAL; // can't think of a better error ID
return -1;
}
- if (result != talk_base::WinPing::PING_TOO_LARGE) {
+ if (result != WinPing::PING_TOO_LARGE) {
*mtu = PACKET_MAXIMUMS[level];
return 0;
}
@@ -637,18 +531,9 @@
return 0;
}
-bool
-Win32Socket::Create(long events) {
+bool Win32Socket::SetAsync(int events) {
ASSERT(NULL == sink_);
- if (INVALID_SOCKET == socket_) {
- socket_ = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, 0);
- if (socket_ == INVALID_SOCKET) {
- UpdateLastError();
- return false;
- }
- }
-
// Create window
sink_ = new EventSink(this);
sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10);
@@ -664,104 +549,263 @@
return true;
}
-void
-Win32Socket::UpdateLastError() {
+bool Win32Socket::HandleClosed(int close_error) {
+ // WM_CLOSE will be received before all data has been read, so we need to
+ // hold on to it until the read buffer has been drained.
+ char ch;
+ closing_ = true;
+ close_error_ = close_error;
+ return (::recv(socket_, &ch, 1, MSG_PEEK) <= 0);
+}
+
+void Win32Socket::PostClosed() {
+ // If we see that the buffer is indeed drained, then send the close.
+ closing_ = false;
+ ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,
+ socket_, WSAMAKESELECTREPLY(FD_CLOSE, close_error_));
+}
+
+void Win32Socket::UpdateLastError() {
error_ = WSAGetLastError();
}
+int Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) {
+ switch (opt) {
+ case OPT_DONTFRAGMENT:
+ *slevel = IPPROTO_IP;
+ *sopt = IP_DONTFRAGMENT;
+ break;
+ case OPT_RCVBUF:
+ *slevel = SOL_SOCKET;
+ *sopt = SO_RCVBUF;
+ break;
+ case OPT_SNDBUF:
+ *slevel = SOL_SOCKET;
+ *sopt = SO_SNDBUF;
+ break;
+ case OPT_NODELAY:
+ *slevel = IPPROTO_TCP;
+ *sopt = TCP_NODELAY;
+ break;
+ default:
+ ASSERT(false);
+ return -1;
+ }
+ return 0;
+}
+
+void Win32Socket::OnSocketNotify(SOCKET socket, int event, int error) {
+ // Ignore events if we're already closed.
+ if (socket != socket_)
+ return;
+
+ error_ = error;
+ switch (event) {
+ case FD_CONNECT:
+ if (error != ERROR_SUCCESS) {
+ ReportWSAError("WSAAsync:connect notify", error, addr_);
+#ifdef _DEBUG
+ int32 duration = TimeSince(connect_time_);
+ LOG(LS_INFO) << "WSAAsync:connect error (" << duration
+ << " ms), faking close";
+#endif
+ state_ = CS_CLOSED;
+ // If you get an error connecting, close doesn't really do anything
+ // and it certainly doesn't send back any close notification, but
+ // we really only maintain a few states, so it is easiest to get
+ // back into a known state by pretending that a close happened, even
+ // though the connect event never did occur.
+ SignalCloseEvent(this, error);
+ } else {
+#ifdef _DEBUG
+ int32 duration = TimeSince(connect_time_);
+ LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)";
+#endif
+ state_ = CS_CONNECTED;
+ SignalConnectEvent(this);
+ }
+ break;
+
+ case FD_ACCEPT:
+ case FD_READ:
+ if (error != ERROR_SUCCESS) {
+ ReportWSAError("WSAAsync:read notify", error, addr_);
+ } else {
+ SignalReadEvent(this);
+ }
+ break;
+
+ case FD_WRITE:
+ if (error != ERROR_SUCCESS) {
+ ReportWSAError("WSAAsync:write notify", error, addr_);
+ } else {
+ SignalWriteEvent(this);
+ }
+ break;
+
+ case FD_CLOSE:
+ if (HandleClosed(error)) {
+ ReportWSAError("WSAAsync:close notify", error, addr_);
+ state_ = CS_CLOSED;
+ SignalCloseEvent(this, error);
+ }
+ break;
+ }
+}
+
+void Win32Socket::OnDnsNotify(HANDLE task, int error) {
+ if (!dns_ || dns_->handle != task)
+ return;
+
+ uint32 ip = 0;
+ if (error == 0) {
+ hostent* pHost = reinterpret_cast<hostent*>(dns_->buffer);
+ uint32 net_ip = *reinterpret_cast<uint32*>(pHost->h_addr_list[0]);
+ ip = NetworkToHost32(net_ip);
+ }
+
+ LOG_F(LS_INFO) << "(" << SocketAddress::IPToString(ip)
+ << ", " << error << ")";
+
+ if (error == 0) {
+ SocketAddress address(ip, dns_->port);
+ error = DoConnect(address);
+ } else {
+ Close();
+ }
+
+ if (error) {
+ error_ = error;
+ SignalCloseEvent(this, error_);
+ } else {
+ delete dns_;
+ dns_ = NULL;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Win32SocketServer
+// Provides cricket base services on top of a win32 gui thread
///////////////////////////////////////////////////////////////////////////////
-static UINT s_wm_wakeup_id;
+static UINT s_wm_wakeup_id = 0;
+const TCHAR Win32SocketServer::kWindowName[] = L"libjingle Message Window";
-LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp);
-
-// A socket server that provides cricket base services on top of a win32 gui thread
-
-Win32SocketServer::Win32SocketServer(MessageQueue *message_queue) {
+Win32SocketServer::Win32SocketServer(MessageQueue *message_queue)
+ : message_queue_(message_queue), wnd_(this), posted_(false) {
if (s_wm_wakeup_id == 0)
s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP");
- message_queue_ = message_queue;
- hwnd_ = NULL;
- CreateDummyWindow();
+ if (!wnd_.Create(NULL, kWindowName, 0, 0, 0, 0, 0, 0)) {
+ LOG_GLE(LS_ERROR) << "Failed to create message window.";
+ }
}
Win32SocketServer::~Win32SocketServer() {
- if (hwnd_ != NULL) {
- KillTimer(hwnd_, 1);
- ::DestroyWindow(hwnd_);
+ if (wnd_.handle() != NULL) {
+ KillTimer(wnd_.handle(), 1);
+ wnd_.Destroy();
}
}
Socket* Win32SocketServer::CreateSocket(int type) {
- ASSERT(SOCK_STREAM == type);
- return new Win32Socket;
+ return CreateAsyncSocket(type);
}
AsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) {
- ASSERT(SOCK_STREAM == type);
- return new Win32Socket;
+ Win32Socket* socket = new Win32Socket;
+ if (socket->CreateT(type)) {
+ return socket;
+ }
+ delete socket;
+ return NULL;
+}
+
+void Win32SocketServer::SetMessageQueue(MessageQueue* queue) {
+ message_queue_ = queue;
}
bool Win32SocketServer::Wait(int cms, bool process_io) {
- ASSERT(!process_io || (cms == 0)); // Should only be used for Thread::Send, or in Pump, below
- if (cms == -1) {
+ BOOL b;
+ if (process_io) {
+ // Spin the Win32 message pump at least once, and as long as requested.
+ // This is the Thread::ProcessMessages case.
+ uint32 start = Time();
MSG msg;
- GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);
+ do {
+ SetTimer(wnd_.handle(), 0, cms, NULL);
+ b = GetMessage(&msg, NULL, 0, 0);
+ if (b) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ KillTimer(wnd_.handle(), 0);
+ } while (b && TimeSince(start) < cms);
} else if (cms != 0) {
- Sleep(cms);
+ // Sit and wait forever for a WakeUp. This is the Thread::Send case.
+ ASSERT(cms == -1);
+ MSG msg;
+ b = GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);
+ {
+ CritScope scope(&cs_);
+ posted_ = false;
+ }
+ } else {
+ // No-op (cms == 0 && !process_io). This is the Pump case.
+ b = TRUE;
}
- return true;
+ return (b != FALSE);
}
void Win32SocketServer::WakeUp() {
- // Always post for every wakeup, so there are no
- // critical sections
- if (hwnd_ != NULL)
- PostMessage(hwnd_, s_wm_wakeup_id, 0, 0);
+ if (wnd_.handle()) {
+ // Set the "message pending" flag, if not already set.
+ {
+ CritScope scope(&cs_);
+ if (posted_)
+ return;
+ posted_ = true;
+ }
+
+ PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0);
+ }
}
void Win32SocketServer::Pump() {
- // Process messages
+ // Clear the "message pending" flag.
+ {
+ CritScope scope(&cs_);
+ posted_ = false;
+ }
+
+ // Dispatch all the messages that are currently in our queue. If new messages
+ // are posted during the dispatch, they will be handled in the next Pump.
+ // We use max(1, ...) to make sure we try to dispatch at least once, since
+ // this allow us to process "sent" messages, not included in the size() count.
Message msg;
- while (message_queue_->Get(&msg, 0))
+ for (size_t max_messages_to_process = _max<size_t>(1, message_queue_->size());
+ max_messages_to_process > 0 && message_queue_->Get(&msg, 0, false);
+ --max_messages_to_process) {
message_queue_->Dispatch(&msg);
+ }
// Anything remaining?
int delay = message_queue_->GetDelay();
if (delay == -1) {
- KillTimer(hwnd_, 1);
+ KillTimer(wnd_.handle(), 1);
} else {
- SetTimer(hwnd_, 1, delay, NULL);
+ SetTimer(wnd_.handle(), 1, delay, NULL);
}
}
-void Win32SocketServer::CreateDummyWindow()
-{
- static bool s_registered;
- if (!s_registered) {
- ::WNDCLASSW wc;
- memset(&wc, 0, sizeof(wc));
- wc.cbWndExtra = sizeof(this);
- wc.lpszClassName = L"Dummy";
- wc.lpfnWndProc = DummyWndProc;
- ::RegisterClassW(&wc);
- s_registered = true;
- }
-
- hwnd_ = ::CreateWindowW(L"Dummy", L"", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
- SetWindowLong(hwnd_, GWL_USERDATA, (LONG)(LONG_PTR)this);
-}
-
-LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
-{
+bool Win32SocketServer::MessageWindow::OnMessage(UINT wm, WPARAM wp,
+ LPARAM lp, LRESULT& lr) {
+ bool handled = false;
if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) {
- Win32SocketServer *ss = (Win32SocketServer *)(LONG_PTR)GetWindowLong(hwnd, GWL_USERDATA);
- ss->Pump();
- return 0;
+ ss_->Pump();
+ lr = 0;
+ handled = true;
}
- return ::DefWindowProc(hwnd, wm, wp, lp);
+ return handled;
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/win32socketserver.h b/talk/base/win32socketserver.h
old mode 100755
new mode 100644
index 770141a..f14a197
--- a/talk/base/win32socketserver.h
+++ b/talk/base/win32socketserver.h
@@ -2,39 +2,41 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_WIN32SOCKETSERVER_H__
-#define TALK_BASE_WIN32SOCKETSERVER_H__
+#ifndef TALK_BASE_WIN32SOCKETSERVER_H_
+#define TALK_BASE_WIN32SOCKETSERVER_H_
#ifdef WIN32
-
+#include "talk/base/asyncsocket.h"
+#include "talk/base/criticalsection.h"
#include "talk/base/messagequeue.h"
#include "talk/base/socketserver.h"
#include "talk/base/socketfactory.h"
#include "talk/base/socket.h"
-#include "talk/base/asyncsocket.h"
+#include "talk/base/thread.h"
+#include "talk/base/win32window.h"
namespace talk_base {
@@ -42,11 +44,13 @@
// Win32Socket
///////////////////////////////////////////////////////////////////////////////
-class Win32Socket : public talk_base::AsyncSocket {
-public:
+class Win32Socket : public AsyncSocket {
+ public:
Win32Socket();
virtual ~Win32Socket();
+ bool CreateT(int type);
+
int Attach(SOCKET s);
void SetTimeout(int ms);
@@ -60,28 +64,33 @@
virtual int Recv(void *pv, size_t cb);
virtual int RecvFrom(void *pv, size_t cb, SocketAddress *paddr);
virtual int Listen(int backlog);
- virtual Socket *Accept(SocketAddress *paddr);
+ virtual Win32Socket *Accept(SocketAddress *paddr);
virtual int Close();
virtual int GetError() const;
virtual void SetError(int error);
virtual ConnState GetState() const;
virtual int EstimateMTU(uint16* mtu);
+ virtual int GetOption(Option opt, int* value);
virtual int SetOption(Option opt, int value);
-private:
- bool Create(long events);
+ private:
+ bool SetAsync(int events);
+ int DoConnect(const SocketAddress& addr);
+ bool HandleClosed(int close_error);
+ void PostClosed();
void UpdateLastError();
-
- int DoConnect(const sockaddr_in& addr);
- void OnSocketNotify(int event, int error);
- void OnDnsNotify(int ip, int error);
+ static int TranslateOption(Option opt, int* slevel, int* sopt);
- sockaddr_in addr_; // address that we connected to (see DoConnect)
+ void OnSocketNotify(SOCKET socket, int event, int error);
+ void OnDnsNotify(HANDLE task, int error);
+
SOCKET socket_;
int error_;
- uint32 connect_time_;
ConnState state_;
- bool signal_close_;
+ SocketAddress addr_; // address that we connected to (see DoConnect)
+ uint32 connect_time_;
+ bool closing_;
+ int close_error_;
class EventSink;
friend class EventSink;
@@ -96,29 +105,70 @@
///////////////////////////////////////////////////////////////////////////////
class Win32SocketServer : public SocketServer {
-public:
- Win32SocketServer(MessageQueue *message_queue);
+ public:
+ explicit Win32SocketServer(MessageQueue *message_queue);
virtual ~Win32SocketServer();
// SocketServer Interface
virtual Socket* CreateSocket(int type);
virtual AsyncSocket* CreateAsyncSocket(int type);
+ virtual void SetMessageQueue(MessageQueue* queue);
virtual bool Wait(int cms, bool process_io);
virtual void WakeUp();
void Pump();
-private:
- void CreateDummyWindow();
+ HWND handle() { return wnd_.handle(); }
+ private:
+ class MessageWindow : public Win32Window {
+ public:
+ explicit MessageWindow(Win32SocketServer* ss) : ss_(ss) {}
+ private:
+ virtual bool OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT& result);
+ Win32SocketServer* ss_;
+ };
+
+ static const TCHAR kWindowName[];
MessageQueue *message_queue_;
- HWND hwnd_;
+ MessageWindow wnd_;
+ CriticalSection cs_;
+ bool posted_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Win32Thread. Automatically pumps Windows messages.
+///////////////////////////////////////////////////////////////////////////////
+
+class Win32Thread : public Thread {
+ public:
+ Win32Thread() : ss_(this), id_(0) {
+ set_socketserver(&ss_);
+ }
+ virtual ~Win32Thread() {
+ set_socketserver(NULL);
+ }
+ virtual void Run() {
+ MSG msg;
+ id_ = GetCurrentThreadId();
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ id_ = 0;
+ }
+ virtual void Quit() {
+ PostThreadMessage(id_, WM_QUIT, 0, 0);
+ }
+ private:
+ Win32SocketServer ss_;
+ DWORD id_;
};
///////////////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
#endif // WIN32
-#endif // TALK_BASE_WIN32SOCKETSERVER_H__
+#endif // TALK_BASE_WIN32SOCKETSERVER_H_
diff --git a/talk/base/win32window.cc b/talk/base/win32window.cc
new file mode 100644
index 0000000..0e7761f
--- /dev/null
+++ b/talk/base/win32window.cc
@@ -0,0 +1,134 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/win32window.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// Win32Window
+///////////////////////////////////////////////////////////////////////////////
+
+static const wchar_t kWindowBaseClassName[] = L"WindowBaseClass";
+HINSTANCE Win32Window::instance_ = GetModuleHandle(NULL);
+ATOM Win32Window::window_class_ = 0;
+
+Win32Window::Win32Window() : wnd_(NULL) {
+}
+
+Win32Window::~Win32Window() {
+ ASSERT(NULL == wnd_);
+}
+
+bool Win32Window::Create(HWND parent, const wchar_t* title, DWORD style,
+ DWORD exstyle, int x, int y, int cx, int cy) {
+ if (wnd_) {
+ // Window already exists.
+ return false;
+ }
+
+ if (!window_class_) {
+ // Class not registered, register it.
+ WNDCLASSEX wcex;
+ memset(&wcex, 0, sizeof(wcex));
+ wcex.cbSize = sizeof(wcex);
+ wcex.hInstance = instance_;
+ wcex.lpfnWndProc = &Win32Window::WndProc;
+ wcex.lpszClassName = kWindowBaseClassName;
+ window_class_ = ::RegisterClassEx(&wcex);
+ if (!window_class_) {
+ LOG_GLE(LS_ERROR) << "RegisterClassEx failed";
+ return false;
+ }
+ }
+ wnd_ = ::CreateWindowEx(exstyle, kWindowBaseClassName, title, style,
+ x, y, cx, cy, parent, NULL, instance_, this);
+ return (NULL != wnd_);
+}
+
+void Win32Window::Destroy() {
+ VERIFY(::DestroyWindow(wnd_) != FALSE);
+}
+
+void Win32Window::SetInstance(HINSTANCE instance) {
+ instance_ = instance;
+}
+
+void Win32Window::Shutdown() {
+ if (window_class_) {
+ ::UnregisterClass(MAKEINTATOM(window_class_), instance_);
+ window_class_ = 0;
+ }
+}
+
+bool Win32Window::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
+ LRESULT& result) {
+ switch (uMsg) {
+ case WM_CLOSE:
+ if (!OnClose()) {
+ result = 0;
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+LRESULT Win32Window::WndProc(HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam) {
+ Win32Window* that = reinterpret_cast<Win32Window*>(
+ ::GetWindowLongPtr(hwnd, GWL_USERDATA));
+ if (!that && (WM_CREATE == uMsg)) {
+ CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
+ that = static_cast<Win32Window*>(cs->lpCreateParams);
+ that->wnd_ = hwnd;
+ ::SetWindowLongPtr(hwnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(that));
+ }
+ if (that) {
+ LRESULT result;
+ bool handled = that->OnMessage(uMsg, wParam, lParam, result);
+ if (WM_DESTROY == uMsg) {
+ for (HWND child = ::GetWindow(hwnd, GW_CHILD); child;
+ child = ::GetWindow(child, GW_HWNDNEXT)) {
+ LOG(LS_INFO) << "Child window: " << static_cast<void*>(child);
+ }
+ }
+ if (WM_NCDESTROY == uMsg) {
+ ::SetWindowLongPtr(hwnd, GWL_USERDATA, NULL);
+ that->wnd_ = NULL;
+ that->OnDestroyed();
+ }
+ if (handled) {
+ return result;
+ }
+ }
+ return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+} // namespace talk_base
diff --git a/talk/base/win32window.h b/talk/base/win32window.h
old mode 100755
new mode 100644
index a4cdb47..66a56ce
--- a/talk/base/win32window.h
+++ b/talk/base/win32window.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_WIN32WINDOW_H__
-#define TALK_BASE_WIN32WINDOW_H__
+#ifndef TALK_BASE_WIN32WINDOW_H_
+#define TALK_BASE_WIN32WINDOW_H_
#ifdef WIN32
@@ -39,34 +39,41 @@
///////////////////////////////////////////////////////////////////////////////
class Win32Window {
-public:
+ public:
Win32Window();
virtual ~Win32Window();
- HWND handle() { return wnd_; }
+ HWND handle() const { return wnd_; }
bool Create(HWND parent, const wchar_t* title, DWORD style, DWORD exstyle,
int x, int y, int cx, int cy);
void Destroy();
-protected:
+ // Call this first if you are running inside a DLL.
+ static void SetInstance(HINSTANCE instance);
+ // Call this when your DLL unloads.
+ static void Shutdown();
+
+ protected:
virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
LRESULT& result);
virtual bool OnClose() { return true; }
virtual void OnDestroyed() { }
-private:
+ private:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam);
HWND wnd_;
+ static HINSTANCE instance_;
+ static ATOM window_class_;
};
///////////////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
#endif // WIN32
-#endif // TALK_BASE_WIN32WINDOW_H__
+#endif // TALK_BASE_WIN32WINDOW_H_
diff --git a/talk/base/winfirewall.cc b/talk/base/winfirewall.cc
old mode 100755
new mode 100644
index 9323d01..e87ee5a
--- a/talk/base/winfirewall.cc
+++ b/talk/base/winfirewall.cc
@@ -2,35 +2,42 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <comdef.h>
-#include "netfw.h"
-#include "winfirewall.h"
+#include "talk/base/winfirewall.h"
-#define RELEASE(lpUnk) do \
- { if ((lpUnk) != NULL) { (lpUnk)->Release(); (lpUnk) = NULL; } } while (0)
+#include "talk/base/win32.h"
+
+#include <comdef.h>
+#include <netfw.h>
+
+#define RELEASE(lpUnk) do { \
+ if ((lpUnk) != NULL) { \
+ (lpUnk)->Release(); \
+ (lpUnk) = NULL; \
+ } \
+} while (0)
namespace talk_base {
@@ -45,10 +52,13 @@
Shutdown();
}
-bool
-WinFirewall::Initialize() {
- if (mgr_)
+bool WinFirewall::Initialize(HRESULT* result) {
+ if (mgr_) {
+ if (result) {
+ *result = S_OK;
+ }
return true;
+ }
HRESULT hr = CoCreateInstance(__uuidof(NetFwMgr),
0, CLSCTX_INPROC_SERVER,
@@ -58,18 +68,19 @@
hr = mgr_->get_LocalPolicy(&policy_);
if (SUCCEEDED(hr) && (policy_ != NULL))
hr = policy_->get_CurrentProfile(&profile_);
+
+ if (result)
+ *result = hr;
return SUCCEEDED(hr) && (profile_ != NULL);
}
-void
-WinFirewall::Shutdown() {
+void WinFirewall::Shutdown() {
RELEASE(profile_);
RELEASE(policy_);
RELEASE(mgr_);
}
-bool
-WinFirewall::Enabled() {
+bool WinFirewall::Enabled() const {
if (!profile_)
return false;
@@ -78,45 +89,63 @@
return (fwEnabled != VARIANT_FALSE);
}
-bool
-WinFirewall::Authorized(const char * filename, bool * known) {
- if (known) {
- *known = false;
- }
+bool WinFirewall::QueryAuthorized(const char* filename, bool* authorized)
+ const {
+ return QueryAuthorizedW(ToUtf16(filename).c_str(), authorized);
+}
+
+bool WinFirewall::QueryAuthorizedW(const wchar_t* filename, bool* authorized)
+ const {
+ *authorized = false;
+ bool success = false;
if (!profile_)
return false;
- VARIANT_BOOL fwEnabled = VARIANT_FALSE;
_bstr_t bfilename = filename;
- INetFwAuthorizedApplications * apps = NULL;
+ INetFwAuthorizedApplications* apps = NULL;
HRESULT hr = profile_->get_AuthorizedApplications(&apps);
if (SUCCEEDED(hr) && (apps != NULL)) {
- INetFwAuthorizedApplication * app = NULL;
+ INetFwAuthorizedApplication* app = NULL;
hr = apps->Item(bfilename, &app);
if (SUCCEEDED(hr) && (app != NULL)) {
+ VARIANT_BOOL fwEnabled = VARIANT_FALSE;
hr = app->get_Enabled(&fwEnabled);
app->Release();
- if (known) {
- *known = true;
+
+ if (SUCCEEDED(hr)) {
+ success = true;
+ *authorized = (fwEnabled != VARIANT_FALSE);
}
- } else if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
+ } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
+ // No entry in list of authorized apps
+ success = true;
+ } else {
// Unexpected error
}
apps->Release();
}
- return (fwEnabled != VARIANT_FALSE);
+ return success;
}
-bool
-WinFirewall::AddApplication(const char * filename, const char * friendly_name,
- bool authorized) {
- INetFwAuthorizedApplications * apps = NULL;
+bool WinFirewall::AddApplication(const char* filename,
+ const char* friendly_name,
+ bool authorized,
+ HRESULT* result) {
+ return AddApplicationW(ToUtf16(filename).c_str(),
+ ToUtf16(friendly_name).c_str(), authorized, result);
+}
+
+bool WinFirewall::AddApplicationW(const wchar_t* filename,
+ const wchar_t* friendly_name,
+ bool authorized,
+ HRESULT* result) {
+ INetFwAuthorizedApplications* apps = NULL;
HRESULT hr = profile_->get_AuthorizedApplications(&apps);
if (SUCCEEDED(hr) && (apps != NULL)) {
- INetFwAuthorizedApplication * app = NULL;
+ INetFwAuthorizedApplication* app = NULL;
hr = CoCreateInstance(__uuidof(NetFwAuthorizedApplication),
0, CLSCTX_INPROC_SERVER,
__uuidof(INetFwAuthorizedApplication),
@@ -135,7 +164,9 @@
}
apps->Release();
}
+ if (result)
+ *result = hr;
return SUCCEEDED(hr);
}
-} // namespace talk_base
+} // namespace talk_base
diff --git a/talk/base/winfirewall.h b/talk/base/winfirewall.h
old mode 100755
new mode 100644
index 09d5a2f..11d687e
--- a/talk/base/winfirewall.h
+++ b/talk/base/winfirewall.h
@@ -2,31 +2,36 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_WINFIREWALL_H__
-#define TALK_BASE_WINFIREWALL_H__
+#ifndef TALK_BASE_WINFIREWALL_H_
+#define TALK_BASE_WINFIREWALL_H_
+
+#ifndef _HRESULT_DEFINED
+#define _HRESULT_DEFINED
+typedef long HRESULT; // Can't forward declare typedef, but don't need all win
+#endif // !_HRESULT_DEFINED
struct INetFwMgr;
struct INetFwPolicy;
@@ -39,26 +44,30 @@
//////////////////////////////////////////////////////////////////////
class WinFirewall {
-public:
+ public:
WinFirewall();
~WinFirewall();
- bool Initialize();
+ bool Initialize(HRESULT* result);
void Shutdown();
- bool Enabled();
- bool Authorized(const char * filename, bool * known = 0);
+ bool Enabled() const;
+ bool QueryAuthorized(const char* filename, bool* authorized) const;
+ bool QueryAuthorizedW(const wchar_t* filename, bool* authorized) const;
- bool AddApplication(const char * filename, const char * friendly_name, bool authorized = true);
+ bool AddApplication(const char* filename, const char* friendly_name,
+ bool authorized, HRESULT* result);
+ bool AddApplicationW(const wchar_t* filename, const wchar_t* friendly_name,
+ bool authorized, HRESULT* result);
-private:
- INetFwMgr * mgr_;
- INetFwPolicy * policy_;
- INetFwProfile * profile_;
+ private:
+ INetFwMgr* mgr_;
+ INetFwPolicy* policy_;
+ INetFwProfile* profile_;
};
//////////////////////////////////////////////////////////////////////
-} // namespace talk_base
+} // namespace talk_base
-#endif // TALK_BASE_WINFIREWALL_H__
+#endif // TALK_BASE_WINFIREWALL_H_
diff --git a/talk/base/winping.cc b/talk/base/winping.cc
old mode 100755
new mode 100644
index 401a1b2..1802e03
--- a/talk/base/winping.cc
+++ b/talk/base/winping.cc
@@ -26,6 +26,7 @@
*/
#include "talk/base/byteorder.h"
+#include "talk/base/common.h"
#include "talk/base/socketaddress.h"
#include "talk/base/winping.h"
#include "talk/base/logging.h"
@@ -130,7 +131,7 @@
inline uint32 ReplySize(uint32 data_size) {
// A ping error message is 8 bytes long, so make sure we allow for at least
// 8 bytes of reply data.
- return sizeof(ICMP_ECHO_REPLY) + max(8UL, data_size);
+ return sizeof(ICMP_ECHO_REPLY) + talk_base::_max<uint32>(8, data_size);
}
//////////////////////////////////////////////////////////////////////
@@ -314,4 +315,4 @@
//
//////////////////////////////////////////////////////////////////////
-} // namespace talk_base
\ No newline at end of file
+} // namespace talk_base
diff --git a/talk/base/winping.h b/talk/base/winping.h
old mode 100755
new mode 100644
index 0d0b051..35d36e3
--- a/talk/base/winping.h
+++ b/talk/base/winping.h
@@ -30,15 +30,7 @@
#ifdef WIN32
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include <winsock2.h>
-#define _WINSOCKAPI_
-#include <windows.h>
-#undef SetPort
-
+#include "talk/base/win32.h"
#include "talk/base/basictypes.h"
namespace talk_base {
diff --git a/talk/build/.sconsign_linux2.dblite b/talk/build/.sconsign_linux2.dblite
new file mode 100644
index 0000000..2c42751
--- /dev/null
+++ b/talk/build/.sconsign_linux2.dblite
Binary files differ
diff --git a/talk/build/dbg/lib/libexpat.a b/talk/build/dbg/lib/libexpat.a
new file mode 100644
index 0000000..5385d82
--- /dev/null
+++ b/talk/build/dbg/lib/libexpat.a
Binary files differ
diff --git a/talk/build/dbg/lib/libjingle.a b/talk/build/dbg/lib/libjingle.a
new file mode 100644
index 0000000..2d23922
--- /dev/null
+++ b/talk/build/dbg/lib/libjingle.a
Binary files differ
diff --git a/talk/build/dbg/lib/libxmpphelp.a b/talk/build/dbg/lib/libxmpphelp.a
new file mode 100644
index 0000000..d1a18f9
--- /dev/null
+++ b/talk/build/dbg/lib/libxmpphelp.a
Binary files differ
diff --git a/talk/build/dbg/obj/base/asynchttprequest.o b/talk/build/dbg/obj/base/asynchttprequest.o
new file mode 100644
index 0000000..cdbe867
--- /dev/null
+++ b/talk/build/dbg/obj/base/asynchttprequest.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/asyncpacketsocket.o b/talk/build/dbg/obj/base/asyncpacketsocket.o
new file mode 100644
index 0000000..aaa6140
--- /dev/null
+++ b/talk/build/dbg/obj/base/asyncpacketsocket.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/asynctcpsocket.o b/talk/build/dbg/obj/base/asynctcpsocket.o
new file mode 100644
index 0000000..388c18e
--- /dev/null
+++ b/talk/build/dbg/obj/base/asynctcpsocket.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/asyncudpsocket.o b/talk/build/dbg/obj/base/asyncudpsocket.o
new file mode 100644
index 0000000..ed5a373
--- /dev/null
+++ b/talk/build/dbg/obj/base/asyncudpsocket.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/autodetectproxy.o b/talk/build/dbg/obj/base/autodetectproxy.o
new file mode 100644
index 0000000..6b53a7d
--- /dev/null
+++ b/talk/build/dbg/obj/base/autodetectproxy.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/base64.o b/talk/build/dbg/obj/base/base64.o
new file mode 100644
index 0000000..8e3d01f
--- /dev/null
+++ b/talk/build/dbg/obj/base/base64.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/bytebuffer.o b/talk/build/dbg/obj/base/bytebuffer.o
new file mode 100644
index 0000000..4c1af5c
--- /dev/null
+++ b/talk/build/dbg/obj/base/bytebuffer.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/checks.o b/talk/build/dbg/obj/base/checks.o
new file mode 100644
index 0000000..428f072
--- /dev/null
+++ b/talk/build/dbg/obj/base/checks.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/common.o b/talk/build/dbg/obj/base/common.o
new file mode 100644
index 0000000..1abec0b
--- /dev/null
+++ b/talk/build/dbg/obj/base/common.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/diskcache.o b/talk/build/dbg/obj/base/diskcache.o
new file mode 100644
index 0000000..90170b3
--- /dev/null
+++ b/talk/build/dbg/obj/base/diskcache.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/event.o b/talk/build/dbg/obj/base/event.o
new file mode 100644
index 0000000..962efab
--- /dev/null
+++ b/talk/build/dbg/obj/base/event.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/fileutils.o b/talk/build/dbg/obj/base/fileutils.o
new file mode 100644
index 0000000..33e751e
--- /dev/null
+++ b/talk/build/dbg/obj/base/fileutils.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/firewallsocketserver.o b/talk/build/dbg/obj/base/firewallsocketserver.o
new file mode 100644
index 0000000..5a99133
--- /dev/null
+++ b/talk/build/dbg/obj/base/firewallsocketserver.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/flags.o b/talk/build/dbg/obj/base/flags.o
new file mode 100644
index 0000000..2f04850
--- /dev/null
+++ b/talk/build/dbg/obj/base/flags.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/helpers.o b/talk/build/dbg/obj/base/helpers.o
new file mode 100644
index 0000000..0fdbe59
--- /dev/null
+++ b/talk/build/dbg/obj/base/helpers.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/host.o b/talk/build/dbg/obj/base/host.o
new file mode 100644
index 0000000..c5e5a66
--- /dev/null
+++ b/talk/build/dbg/obj/base/host.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/httpbase.o b/talk/build/dbg/obj/base/httpbase.o
new file mode 100644
index 0000000..929bdfc
--- /dev/null
+++ b/talk/build/dbg/obj/base/httpbase.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/httpclient.o b/talk/build/dbg/obj/base/httpclient.o
new file mode 100644
index 0000000..878221e
--- /dev/null
+++ b/talk/build/dbg/obj/base/httpclient.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/httpcommon.o b/talk/build/dbg/obj/base/httpcommon.o
new file mode 100644
index 0000000..f481344
--- /dev/null
+++ b/talk/build/dbg/obj/base/httpcommon.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/httprequest.o b/talk/build/dbg/obj/base/httprequest.o
new file mode 100644
index 0000000..7d39aae
--- /dev/null
+++ b/talk/build/dbg/obj/base/httprequest.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/linux.o b/talk/build/dbg/obj/base/linux.o
new file mode 100644
index 0000000..586ed02
--- /dev/null
+++ b/talk/build/dbg/obj/base/linux.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/logging.o b/talk/build/dbg/obj/base/logging.o
new file mode 100644
index 0000000..38696a0
--- /dev/null
+++ b/talk/build/dbg/obj/base/logging.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/md5c.o b/talk/build/dbg/obj/base/md5c.o
new file mode 100644
index 0000000..5b9ff71
--- /dev/null
+++ b/talk/build/dbg/obj/base/md5c.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/messagehandler.o b/talk/build/dbg/obj/base/messagehandler.o
new file mode 100644
index 0000000..ef9b57f
--- /dev/null
+++ b/talk/build/dbg/obj/base/messagehandler.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/messagequeue.o b/talk/build/dbg/obj/base/messagequeue.o
new file mode 100644
index 0000000..d0a1207
--- /dev/null
+++ b/talk/build/dbg/obj/base/messagequeue.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/nethelpers.o b/talk/build/dbg/obj/base/nethelpers.o
new file mode 100644
index 0000000..dd69ffd
--- /dev/null
+++ b/talk/build/dbg/obj/base/nethelpers.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/network.o b/talk/build/dbg/obj/base/network.o
new file mode 100644
index 0000000..3fff2c6
--- /dev/null
+++ b/talk/build/dbg/obj/base/network.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/openssladapter.o b/talk/build/dbg/obj/base/openssladapter.o
new file mode 100644
index 0000000..5569452
--- /dev/null
+++ b/talk/build/dbg/obj/base/openssladapter.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/opensslidentity.o b/talk/build/dbg/obj/base/opensslidentity.o
new file mode 100644
index 0000000..8cbc953
--- /dev/null
+++ b/talk/build/dbg/obj/base/opensslidentity.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/opensslstreamadapter.o b/talk/build/dbg/obj/base/opensslstreamadapter.o
new file mode 100644
index 0000000..8f26923
--- /dev/null
+++ b/talk/build/dbg/obj/base/opensslstreamadapter.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/pathutils.o b/talk/build/dbg/obj/base/pathutils.o
new file mode 100644
index 0000000..86a65e0
--- /dev/null
+++ b/talk/build/dbg/obj/base/pathutils.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/physicalsocketserver.o b/talk/build/dbg/obj/base/physicalsocketserver.o
new file mode 100644
index 0000000..59854c9
--- /dev/null
+++ b/talk/build/dbg/obj/base/physicalsocketserver.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/proxydetect.o b/talk/build/dbg/obj/base/proxydetect.o
new file mode 100644
index 0000000..ad47923
--- /dev/null
+++ b/talk/build/dbg/obj/base/proxydetect.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/proxyinfo.o b/talk/build/dbg/obj/base/proxyinfo.o
new file mode 100644
index 0000000..a4283dd
--- /dev/null
+++ b/talk/build/dbg/obj/base/proxyinfo.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/signalthread.o b/talk/build/dbg/obj/base/signalthread.o
new file mode 100644
index 0000000..b228bd4
--- /dev/null
+++ b/talk/build/dbg/obj/base/signalthread.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/socketadapters.o b/talk/build/dbg/obj/base/socketadapters.o
new file mode 100644
index 0000000..558b07e
--- /dev/null
+++ b/talk/build/dbg/obj/base/socketadapters.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/socketaddress.o b/talk/build/dbg/obj/base/socketaddress.o
new file mode 100644
index 0000000..950b792
--- /dev/null
+++ b/talk/build/dbg/obj/base/socketaddress.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/socketpool.o b/talk/build/dbg/obj/base/socketpool.o
new file mode 100644
index 0000000..fbf2a1f
--- /dev/null
+++ b/talk/build/dbg/obj/base/socketpool.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/ssladapter.o b/talk/build/dbg/obj/base/ssladapter.o
new file mode 100644
index 0000000..6d5532d
--- /dev/null
+++ b/talk/build/dbg/obj/base/ssladapter.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/sslidentity.o b/talk/build/dbg/obj/base/sslidentity.o
new file mode 100644
index 0000000..9653172
--- /dev/null
+++ b/talk/build/dbg/obj/base/sslidentity.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/sslsocketfactory.o b/talk/build/dbg/obj/base/sslsocketfactory.o
new file mode 100644
index 0000000..d7bd7d0
--- /dev/null
+++ b/talk/build/dbg/obj/base/sslsocketfactory.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/sslstreamadapter.o b/talk/build/dbg/obj/base/sslstreamadapter.o
new file mode 100644
index 0000000..915b8cd
--- /dev/null
+++ b/talk/build/dbg/obj/base/sslstreamadapter.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/stream.o b/talk/build/dbg/obj/base/stream.o
new file mode 100644
index 0000000..39aceb4
--- /dev/null
+++ b/talk/build/dbg/obj/base/stream.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/stringdigest.o b/talk/build/dbg/obj/base/stringdigest.o
new file mode 100644
index 0000000..bb1b7dc
--- /dev/null
+++ b/talk/build/dbg/obj/base/stringdigest.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/stringencode.o b/talk/build/dbg/obj/base/stringencode.o
new file mode 100644
index 0000000..544a047
--- /dev/null
+++ b/talk/build/dbg/obj/base/stringencode.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/stringutils.o b/talk/build/dbg/obj/base/stringutils.o
new file mode 100644
index 0000000..cb02437
--- /dev/null
+++ b/talk/build/dbg/obj/base/stringutils.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/task.o b/talk/build/dbg/obj/base/task.o
new file mode 100644
index 0000000..a895c55
--- /dev/null
+++ b/talk/build/dbg/obj/base/task.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/taskparent.o b/talk/build/dbg/obj/base/taskparent.o
new file mode 100644
index 0000000..12a5e09
--- /dev/null
+++ b/talk/build/dbg/obj/base/taskparent.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/taskrunner.o b/talk/build/dbg/obj/base/taskrunner.o
new file mode 100644
index 0000000..712f9d7
--- /dev/null
+++ b/talk/build/dbg/obj/base/taskrunner.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/thread.o b/talk/build/dbg/obj/base/thread.o
new file mode 100644
index 0000000..24641f6
--- /dev/null
+++ b/talk/build/dbg/obj/base/thread.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/time.o b/talk/build/dbg/obj/base/time.o
new file mode 100644
index 0000000..648968a
--- /dev/null
+++ b/talk/build/dbg/obj/base/time.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/unixfilesystem.o b/talk/build/dbg/obj/base/unixfilesystem.o
new file mode 100644
index 0000000..d649ea8
--- /dev/null
+++ b/talk/build/dbg/obj/base/unixfilesystem.o
Binary files differ
diff --git a/talk/build/dbg/obj/base/urlencode.o b/talk/build/dbg/obj/base/urlencode.o
new file mode 100644
index 0000000..35be9f7
--- /dev/null
+++ b/talk/build/dbg/obj/base/urlencode.o
Binary files differ
diff --git a/talk/build/dbg/obj/call b/talk/build/dbg/obj/call
new file mode 100755
index 0000000..24d6b85
--- /dev/null
+++ b/talk/build/dbg/obj/call
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/call_main.o b/talk/build/dbg/obj/examples/call/call_main.o
new file mode 100644
index 0000000..3f0dc5d
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/call_main.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/callclient.o b/talk/build/dbg/obj/examples/call/callclient.o
new file mode 100644
index 0000000..fa50902
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/callclient.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/console.o b/talk/build/dbg/obj/examples/call/console.o
new file mode 100644
index 0000000..c15e34c
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/console.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/discoitemsquerytask.o b/talk/build/dbg/obj/examples/call/discoitemsquerytask.o
new file mode 100644
index 0000000..aa91eb5
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/discoitemsquerytask.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/friendinvitesendtask.o b/talk/build/dbg/obj/examples/call/friendinvitesendtask.o
new file mode 100644
index 0000000..8f1bfd0
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/friendinvitesendtask.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/mucinviterecvtask.o b/talk/build/dbg/obj/examples/call/mucinviterecvtask.o
new file mode 100644
index 0000000..aa37350
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/mucinviterecvtask.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/mucinvitesendtask.o b/talk/build/dbg/obj/examples/call/mucinvitesendtask.o
new file mode 100644
index 0000000..6073286
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/mucinvitesendtask.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/presenceouttask.o b/talk/build/dbg/obj/examples/call/presenceouttask.o
new file mode 100644
index 0000000..44c0ce4
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/presenceouttask.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/presencepushtask.o b/talk/build/dbg/obj/examples/call/presencepushtask.o
new file mode 100644
index 0000000..80a7a63
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/presencepushtask.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/call/voicemailjidrequester.o b/talk/build/dbg/obj/examples/call/voicemailjidrequester.o
new file mode 100644
index 0000000..03ab110
--- /dev/null
+++ b/talk/build/dbg/obj/examples/call/voicemailjidrequester.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/login/login_main.o b/talk/build/dbg/obj/examples/login/login_main.o
new file mode 100644
index 0000000..f192e3c
--- /dev/null
+++ b/talk/build/dbg/obj/examples/login/login_main.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/login/xmppauth.o b/talk/build/dbg/obj/examples/login/xmppauth.o
new file mode 100644
index 0000000..1b1b078
--- /dev/null
+++ b/talk/build/dbg/obj/examples/login/xmppauth.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/login/xmpppump.o b/talk/build/dbg/obj/examples/login/xmpppump.o
new file mode 100644
index 0000000..b76d3f7
--- /dev/null
+++ b/talk/build/dbg/obj/examples/login/xmpppump.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/login/xmppsocket.o b/talk/build/dbg/obj/examples/login/xmppsocket.o
new file mode 100644
index 0000000..8e8e9f9
--- /dev/null
+++ b/talk/build/dbg/obj/examples/login/xmppsocket.o
Binary files differ
diff --git a/talk/build/dbg/obj/examples/login/xmppthread.o b/talk/build/dbg/obj/examples/login/xmppthread.o
new file mode 100644
index 0000000..06380ff
--- /dev/null
+++ b/talk/build/dbg/obj/examples/login/xmppthread.o
Binary files differ
diff --git a/talk/build/dbg/obj/libexpat.a b/talk/build/dbg/obj/libexpat.a
new file mode 100644
index 0000000..5385d82
--- /dev/null
+++ b/talk/build/dbg/obj/libexpat.a
Binary files differ
diff --git a/talk/build/dbg/obj/libjingle.a b/talk/build/dbg/obj/libjingle.a
new file mode 100644
index 0000000..2d23922
--- /dev/null
+++ b/talk/build/dbg/obj/libjingle.a
Binary files differ
diff --git a/talk/build/dbg/obj/libxmpphelp.a b/talk/build/dbg/obj/libxmpphelp.a
new file mode 100644
index 0000000..d1a18f9
--- /dev/null
+++ b/talk/build/dbg/obj/libxmpphelp.a
Binary files differ
diff --git a/talk/build/dbg/obj/login b/talk/build/dbg/obj/login
new file mode 100755
index 0000000..7b53255
--- /dev/null
+++ b/talk/build/dbg/obj/login
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/constants.o b/talk/build/dbg/obj/p2p/base/constants.o
new file mode 100644
index 0000000..e3131e1
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/constants.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/p2ptransport.o b/talk/build/dbg/obj/p2p/base/p2ptransport.o
new file mode 100644
index 0000000..372d0a5
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/p2ptransport.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/p2ptransportchannel.o b/talk/build/dbg/obj/p2p/base/p2ptransportchannel.o
new file mode 100644
index 0000000..4a0888d
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/p2ptransportchannel.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/parsing.o b/talk/build/dbg/obj/p2p/base/parsing.o
new file mode 100644
index 0000000..ec9150d
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/parsing.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/port.o b/talk/build/dbg/obj/p2p/base/port.o
new file mode 100644
index 0000000..7759343
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/port.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/pseudotcp.o b/talk/build/dbg/obj/p2p/base/pseudotcp.o
new file mode 100644
index 0000000..80be5a0
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/pseudotcp.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/rawtransport.o b/talk/build/dbg/obj/p2p/base/rawtransport.o
new file mode 100644
index 0000000..8b6b29f
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/rawtransport.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/rawtransportchannel.o b/talk/build/dbg/obj/p2p/base/rawtransportchannel.o
new file mode 100644
index 0000000..b88e37c
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/rawtransportchannel.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/relayport.o b/talk/build/dbg/obj/p2p/base/relayport.o
new file mode 100644
index 0000000..202e720
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/relayport.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/session.o b/talk/build/dbg/obj/p2p/base/session.o
new file mode 100644
index 0000000..6140780
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/session.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/sessionmanager.o b/talk/build/dbg/obj/p2p/base/sessionmanager.o
new file mode 100644
index 0000000..d6bd8f1
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/sessionmanager.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/sessionmessages.o b/talk/build/dbg/obj/p2p/base/sessionmessages.o
new file mode 100644
index 0000000..fce7af6
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/sessionmessages.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/stun.o b/talk/build/dbg/obj/p2p/base/stun.o
new file mode 100644
index 0000000..484a581
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/stun.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/stunport.o b/talk/build/dbg/obj/p2p/base/stunport.o
new file mode 100644
index 0000000..23acf0b
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/stunport.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/stunrequest.o b/talk/build/dbg/obj/p2p/base/stunrequest.o
new file mode 100644
index 0000000..7f8a830
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/stunrequest.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/tcpport.o b/talk/build/dbg/obj/p2p/base/tcpport.o
new file mode 100644
index 0000000..ced675c
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/tcpport.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/transport.o b/talk/build/dbg/obj/p2p/base/transport.o
new file mode 100644
index 0000000..d3d3ba9
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/transport.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/transportchannel.o b/talk/build/dbg/obj/p2p/base/transportchannel.o
new file mode 100644
index 0000000..fe7b13b
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/transportchannel.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/transportchannelproxy.o b/talk/build/dbg/obj/p2p/base/transportchannelproxy.o
new file mode 100644
index 0000000..4bf32b8
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/transportchannelproxy.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/base/udpport.o b/talk/build/dbg/obj/p2p/base/udpport.o
new file mode 100644
index 0000000..05aa530
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/base/udpport.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/client/basicportallocator.o b/talk/build/dbg/obj/p2p/client/basicportallocator.o
new file mode 100644
index 0000000..badd28a
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/client/basicportallocator.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/client/httpportallocator.o b/talk/build/dbg/obj/p2p/client/httpportallocator.o
new file mode 100644
index 0000000..4657b3a
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/client/httpportallocator.o
Binary files differ
diff --git a/talk/build/dbg/obj/p2p/client/socketmonitor.o b/talk/build/dbg/obj/p2p/client/socketmonitor.o
new file mode 100644
index 0000000..a0d6ae3
--- /dev/null
+++ b/talk/build/dbg/obj/p2p/client/socketmonitor.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/audiomonitor.o b/talk/build/dbg/obj/session/phone/audiomonitor.o
new file mode 100644
index 0000000..c99d8e8
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/audiomonitor.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/call.o b/talk/build/dbg/obj/session/phone/call.o
new file mode 100644
index 0000000..007bd11
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/call.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/channel.o b/talk/build/dbg/obj/session/phone/channel.o
new file mode 100644
index 0000000..c79df1a
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/channel.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/channelmanager.o b/talk/build/dbg/obj/session/phone/channelmanager.o
new file mode 100644
index 0000000..3bf11cc
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/channelmanager.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/codec.o b/talk/build/dbg/obj/session/phone/codec.o
new file mode 100644
index 0000000..02c464f
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/codec.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/devicemanager.o b/talk/build/dbg/obj/session/phone/devicemanager.o
new file mode 100644
index 0000000..7d64b92
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/devicemanager.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/mediaengine.o b/talk/build/dbg/obj/session/phone/mediaengine.o
new file mode 100644
index 0000000..716c4f2
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/mediaengine.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/mediamonitor.o b/talk/build/dbg/obj/session/phone/mediamonitor.o
new file mode 100644
index 0000000..2a3b312
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/mediamonitor.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/mediasessionclient.o b/talk/build/dbg/obj/session/phone/mediasessionclient.o
new file mode 100644
index 0000000..a5cb82d
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/mediasessionclient.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/soundclip.o b/talk/build/dbg/obj/session/phone/soundclip.o
new file mode 100644
index 0000000..56e0824
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/soundclip.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/srtpfilter.o b/talk/build/dbg/obj/session/phone/srtpfilter.o
new file mode 100644
index 0000000..bfb29fa
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/srtpfilter.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/phone/v4llookup.o b/talk/build/dbg/obj/session/phone/v4llookup.o
new file mode 100644
index 0000000..acc3090
--- /dev/null
+++ b/talk/build/dbg/obj/session/phone/v4llookup.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/tunnel/pseudotcpchannel.o b/talk/build/dbg/obj/session/tunnel/pseudotcpchannel.o
new file mode 100644
index 0000000..d1186ea
--- /dev/null
+++ b/talk/build/dbg/obj/session/tunnel/pseudotcpchannel.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/tunnel/securetunnelsessionclient.o b/talk/build/dbg/obj/session/tunnel/securetunnelsessionclient.o
new file mode 100644
index 0000000..f61e80a
--- /dev/null
+++ b/talk/build/dbg/obj/session/tunnel/securetunnelsessionclient.o
Binary files differ
diff --git a/talk/build/dbg/obj/session/tunnel/tunnelsessionclient.o b/talk/build/dbg/obj/session/tunnel/tunnelsessionclient.o
new file mode 100644
index 0000000..18e81a1
--- /dev/null
+++ b/talk/build/dbg/obj/session/tunnel/tunnelsessionclient.o
Binary files differ
diff --git a/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmlparse.o b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmlparse.o
new file mode 100644
index 0000000..2bf598e
--- /dev/null
+++ b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmlparse.o
Binary files differ
diff --git a/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmlrole.o b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmlrole.o
new file mode 100644
index 0000000..a6a2c4c
--- /dev/null
+++ b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmlrole.o
Binary files differ
diff --git a/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok.o b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok.o
new file mode 100644
index 0000000..9f7c54a
--- /dev/null
+++ b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok.o
Binary files differ
diff --git a/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok_impl.o b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok_impl.o
new file mode 100644
index 0000000..c1b2b7f
--- /dev/null
+++ b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok_impl.o
Binary files differ
diff --git a/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok_ns.o b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok_ns.o
new file mode 100644
index 0000000..b6c7f23
--- /dev/null
+++ b/talk/build/dbg/obj/third_party/expat/v2_0_1/Source/lib/xmltok_ns.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmllite/qname.o b/talk/build/dbg/obj/xmllite/qname.o
new file mode 100644
index 0000000..b888a02
--- /dev/null
+++ b/talk/build/dbg/obj/xmllite/qname.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmllite/xmlbuilder.o b/talk/build/dbg/obj/xmllite/xmlbuilder.o
new file mode 100644
index 0000000..54ac7d7
--- /dev/null
+++ b/talk/build/dbg/obj/xmllite/xmlbuilder.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmllite/xmlconstants.o b/talk/build/dbg/obj/xmllite/xmlconstants.o
new file mode 100644
index 0000000..393f095
--- /dev/null
+++ b/talk/build/dbg/obj/xmllite/xmlconstants.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmllite/xmlelement.o b/talk/build/dbg/obj/xmllite/xmlelement.o
new file mode 100644
index 0000000..5ea5f85
--- /dev/null
+++ b/talk/build/dbg/obj/xmllite/xmlelement.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmllite/xmlnsstack.o b/talk/build/dbg/obj/xmllite/xmlnsstack.o
new file mode 100644
index 0000000..4e3f767
--- /dev/null
+++ b/talk/build/dbg/obj/xmllite/xmlnsstack.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmllite/xmlparser.o b/talk/build/dbg/obj/xmllite/xmlparser.o
new file mode 100644
index 0000000..561e1bf
--- /dev/null
+++ b/talk/build/dbg/obj/xmllite/xmlparser.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmllite/xmlprinter.o b/talk/build/dbg/obj/xmllite/xmlprinter.o
new file mode 100644
index 0000000..8721bb1
--- /dev/null
+++ b/talk/build/dbg/obj/xmllite/xmlprinter.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/constants.o b/talk/build/dbg/obj/xmpp/constants.o
new file mode 100644
index 0000000..b569a0a
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/constants.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/jid.o b/talk/build/dbg/obj/xmpp/jid.o
new file mode 100644
index 0000000..ffa5a31
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/jid.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/ratelimitmanager.o b/talk/build/dbg/obj/xmpp/ratelimitmanager.o
new file mode 100644
index 0000000..e943d2a
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/ratelimitmanager.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/saslmechanism.o b/talk/build/dbg/obj/xmpp/saslmechanism.o
new file mode 100644
index 0000000..c941188
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/saslmechanism.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/xmppclient.o b/talk/build/dbg/obj/xmpp/xmppclient.o
new file mode 100644
index 0000000..845eff8
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/xmppclient.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/xmppengineimpl.o b/talk/build/dbg/obj/xmpp/xmppengineimpl.o
new file mode 100644
index 0000000..4b45fe7
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/xmppengineimpl.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/xmppengineimpl_iq.o b/talk/build/dbg/obj/xmpp/xmppengineimpl_iq.o
new file mode 100644
index 0000000..84d78a7
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/xmppengineimpl_iq.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/xmpplogintask.o b/talk/build/dbg/obj/xmpp/xmpplogintask.o
new file mode 100644
index 0000000..9ee8257
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/xmpplogintask.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/xmppstanzaparser.o b/talk/build/dbg/obj/xmpp/xmppstanzaparser.o
new file mode 100644
index 0000000..0206ce7
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/xmppstanzaparser.o
Binary files differ
diff --git a/talk/build/dbg/obj/xmpp/xmpptask.o b/talk/build/dbg/obj/xmpp/xmpptask.o
new file mode 100644
index 0000000..896aa05
--- /dev/null
+++ b/talk/build/dbg/obj/xmpp/xmpptask.o
Binary files differ
diff --git a/talk/build/dbg/staging/.nfs000000000085007f00000181 b/talk/build/dbg/staging/.nfs000000000085007f00000181
new file mode 100755
index 0000000..49bae59
--- /dev/null
+++ b/talk/build/dbg/staging/.nfs000000000085007f00000181
Binary files differ
diff --git a/talk/build/dbg/staging/call b/talk/build/dbg/staging/call
new file mode 100755
index 0000000..24d6b85
--- /dev/null
+++ b/talk/build/dbg/staging/call
Binary files differ
diff --git a/talk/build/dbg/staging/login b/talk/build/dbg/staging/login
new file mode 100755
index 0000000..7b53255
--- /dev/null
+++ b/talk/build/dbg/staging/login
Binary files differ
diff --git a/talk/examples/Makefile.am b/talk/examples/Makefile.am
deleted file mode 100755
index fd05e37..0000000
--- a/talk/examples/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-if PHONE
-SUBDIRS=login call pcp
-else
-SUBDIRS=login pcp
-endif
diff --git a/talk/examples/call/Makefile.am b/talk/examples/call/Makefile.am
deleted file mode 100755
index 30a3dc6..0000000
--- a/talk/examples/call/Makefile.am
+++ /dev/null
@@ -1,15 +0,0 @@
-EXTRA_DIST=call.vcproj
-bin_PROGRAMS = call
-call_CXXFLAGS = $(AM_CXXFLAGS)
-call_SOURCES = call_main.cc callclient.cc console.cc
-noinst_HEADERS = callclient.h console.h
-call_LDADD = \
- $(top_srcdir)/talk/examples/login/libcricketexampleslogin.la \
- $(top_srcdir)/talk/session/phone/libcricketsessionphone.la \
- $(top_srcdir)/talk/p2p/client/libcricketp2pclient.la \
- $(top_srcdir)/talk/p2p/base/libcricketp2pbase.la \
- $(top_srcdir)/talk/xmpp/libcricketxmpp.la \
- $(top_srcdir)/talk/xmllite/libcricketxmllite.la \
- $(top_srcdir)/talk/base/libcricketbase.la \
- $(EXPAT_LIBS) $(ORTP_LIBS) -lpthread -lssl -lcrypto $(ILBC_LIBS) $(SPEEX_LIBS) $(GLIB_LIBS) $(MEDIA_LIBS)
-AM_CPPFLAGS = -DPOSIX
diff --git a/talk/examples/call/call.vcproj b/talk/examples/call/call.vcproj
deleted file mode 100755
index 14d126f..0000000
--- a/talk/examples/call/call.vcproj
+++ /dev/null
@@ -1,261 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="call"
- ProjectGUID="{A4132D45-BAE2-40E5-AC7C-C3C44FB24325}"
- RootNamespace="call"
- Keyword="Win32Proj"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="../../.."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_WINDOWS;UNICODE;_UNICODE;WINVER=0x0500;_WIN32_WINNT=0x500;PRODUCTION_BUILD;PRODUCTION;XML_STATIC;FEATURE_ENABLE_SSL;FEATURE_ENABLE_CHAT_ARCHIVING;FEATURE_ENABLE_VOICEMAIL"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- TreatWChar_tAsBuiltInType="false"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="comsupp.lib secur32.lib ws2_32.lib libexpatMT.lib Iphlpapi.lib "$(SolutionDir)\third_party\gips\Library\gipsvoiceenginelite.lib" crypt32.lib"
- LinkIncremental="2"
- IgnoreAllDefaultLibraries="false"
- IgnoreDefaultLibraryNames=""
- GenerateDebugInformation="true"
- SubSystem="1"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="1"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="../../.."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_WINDOWS;UNICODE;_UNICODE;WINVER=0x0500;_WIN32_WINNT=0x500;PRODUCTION_BUILD;PRODUCTION;XML_STATIC;FEATURE_ENABLE_SSL;FEATURE_ENABLE_CHAT_ARCHIVING"
- RuntimeLibrary="0"
- TreatWChar_tAsBuiltInType="false"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="comsupp.lib secur32.lib ws2_32.lib libexpatMT.lib Iphlpapi.lib "$(SolutionDir)\third_party\gips\Library\gipsvoiceenginelite.lib""
- LinkIncremental="1"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath=".\call_main.cc"
- >
- </File>
- <File
- RelativePath=".\callclient.cc"
- >
- </File>
- <File
- RelativePath=".\console.cc"
- >
- </File>
- <File
- RelativePath="..\login\jingleinfotask.cc"
- >
- </File>
- <File
- RelativePath="..\login\presenceouttask.cc"
- >
- </File>
- <File
- RelativePath="..\login\presencepushtask.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmppauth.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmpppump.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmppsocket.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmppthread.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath=".\callclient.h"
- >
- </File>
- <File
- RelativePath=".\console.h"
- >
- </File>
- <File
- RelativePath=".\presenceouttask.h"
- >
- </File>
- <File
- RelativePath=".\presencepushtask.h"
- >
- </File>
- <File
- RelativePath=".\status.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/talk/examples/call/call_main.cc b/talk/examples/call/call_main.cc
old mode 100755
new mode 100644
index 989e3a2..dde0784
--- a/talk/examples/call/call_main.cc
+++ b/talk/examples/call/call_main.cc
@@ -1,66 +1,51 @@
/*
- * Jingle call example
+ * libjingle
* Copyright 2004--2005, Google Inc.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <time.h>
#include <iomanip>
+#include <cstdio>
+#include <cstring>
+#include <vector>
#include "talk/base/logging.h"
-#include "talk/base/physicalsocketserver.h"
+#include "talk/base/flags.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/stream.h"
#include "talk/base/ssladapter.h"
+#include "talk/base/win32socketserver.h"
#include "talk/xmpp/xmppclientsettings.h"
#include "talk/examples/login/xmppthread.h"
#include "talk/examples/login/xmppauth.h"
+#include "talk/examples/login/xmpppump.h"
#include "talk/examples/call/callclient.h"
#include "talk/examples/call/console.h"
+#include "talk/session/phone/filemediaengine.h"
-#if defined(_MSC_VER) && (_MSC_VER < 1400)
-// The following are necessary to properly link when compiling STL without
-// /EHsc, otherwise known as C++ exceptions.
-void __cdecl std::_Throw(const std::exception &) {}
-std::_Prhand std::_Raise_handler = 0;
-#endif
-
-void SetConsoleEcho(bool on) {
-#ifdef WIN32
- HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
- if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
- return;
-
- DWORD mode;
- if (!GetConsoleMode(hIn, &mode))
- return;
-
- if (on) {
- mode = mode | ENABLE_ECHO_INPUT;
- } else {
- mode = mode & ~ENABLE_ECHO_INPUT;
- }
-
- SetConsoleMode(hIn, mode);
-#else
- if (on)
- system("stty echo");
- else
- system("stty -echo");
-#endif
-}
class DebugLog : public sigslot::has_slots<> {
-public:
+ public:
DebugLog() :
debug_input_buf_(NULL), debug_input_len_(0), debug_input_alloc_(0),
debug_output_buf_(NULL), debug_output_len_(0), debug_output_alloc_(0),
@@ -106,8 +91,7 @@
DebugPrint(debug_output_buf_, &debug_output_len_, true);
}
- static bool
- IsAuthTag(const char * str, size_t len) {
+ static bool IsAuthTag(const char * str, size_t len) {
if (str[0] == '<' && str[1] == 'a' &&
str[2] == 'u' &&
str[3] == 't' &&
@@ -117,13 +101,11 @@
if (tag.find("mechanism") != std::string::npos)
return true;
-
}
return false;
}
- void
- DebugPrint(char * buf, int * plen, bool output) {
+ void DebugPrint(char * buf, int * plen, bool output) {
int len = *plen;
if (len > 0) {
time_t tim = time(NULL);
@@ -135,8 +117,8 @@
time_string[time_len-1] = 0; // trim off terminating \n
}
}
- LOG(INFO) << (output ? "SEND >>>>>>>>>>>>>>>>>>>>>>>>>" : "RECV <<<<<<<<<<<<<<<<<<<<<<<<<")
- << " : " << time_string;
+ LOG(INFO) << (output ? "SEND >>>>>>>>>>>>>>>>" : "RECV <<<<<<<<<<<<<<<<")
+ << " : " << time_string;
bool indent;
int start = 0, nest = 3;
@@ -152,28 +134,29 @@
}
// Output a tag
- LOG(INFO) << std::setw(nest) << " " << std::string(buf + start, i + 1 - start);
+ LOG(INFO) << std::setw(nest) << " "
+ << std::string(buf + start, i + 1 - start);
if (indent)
nest += 2;
// Note if it's a PLAIN auth tag
- if (IsAuthTag(buf + start, i + 1 - start)) {
- censor_password_ = true;
- }
+ if (IsAuthTag(buf + start, i + 1 - start)) {
+ censor_password_ = true;
+ }
// incr
start = i + 1;
}
if (buf[i] == '<' && start < i) {
- if (censor_password_) {
- LOG(INFO) << std::setw(nest) << " " << "## TEXT REMOVED ##";
- censor_password_ = false;
- }
- else {
- LOG(INFO) << std::setw(nest) << " " << std::string(buf + start, i - start);
- }
+ if (censor_password_) {
+ LOG(INFO) << std::setw(nest) << " " << "## TEXT REMOVED ##";
+ censor_password_ = false;
+ } else {
+ LOG(INFO) << std::setw(nest) << " "
+ << std::string(buf + start, i - start);
+ }
start = i;
}
}
@@ -182,67 +165,171 @@
*plen = len;
}
}
-
};
static DebugLog debug_log_;
+static const int DEFAULT_PORT = 5222;
+cricket::MediaEngine* CreateFileMediaEngine(const char* voice_in,
+ const char* voice_out,
+ const char* video_in,
+ const char* video_out) {
+ cricket::FileMediaEngine* file_media_engine = new cricket::FileMediaEngine;
+ // Set the RTP dump file names.
+ if (voice_in) {
+ file_media_engine->set_voice_input_filename(voice_in);
+ }
+ if (voice_out) {
+ file_media_engine->set_voice_output_filename(voice_out);
+ }
+ if (video_in) {
+ file_media_engine->set_video_input_filename(video_in);
+ }
+ if (video_out) {
+ file_media_engine->set_video_output_filename(video_out);
+ }
+
+ // Set voice and video codecs. TODO: The codecs actually depend on
+ // the the input voice and video streams.
+ std::vector<cricket::AudioCodec> voice_codecs;
+ voice_codecs.push_back(
+ cricket::AudioCodec(9, "G722", 16000, 64000, 1, 0));
+ file_media_engine->set_voice_codecs(voice_codecs);
+ std::vector<cricket::VideoCodec> video_codecs;
+ video_codecs.push_back(
+ cricket::VideoCodec(97, "H264", 320, 240, 30, 0));
+ file_media_engine->set_video_codecs(video_codecs);
+
+ return file_media_engine;
+}
+
int main(int argc, char **argv) {
- // This app has three threads. The main thread will run the XMPP client,
- // which will print to the screen in its own thread. A second thread
+ // This app has three threads. The main thread will run the XMPP client,
+ // which will print to the screen in its own thread. A second thread
// will get input from the console, parse it, and pass the appropriate
// message back to the XMPP client's thread. A third thread is used
- // by PhoneSessionClient as its worker thread.
+ // by MediaSessionClient as its worker thread.
- bool debug = false;
- if (argc > 1 && !strcmp(argv[1], "-d"))
- debug = true;
-
+ // define options
+ DEFINE_bool(a, false, "Turn on auto accept.");
+ DEFINE_bool(d, false, "Turn on debugging.");
+ DEFINE_bool(testserver, false, "Use test server");
+ DEFINE_int(portallocator, 0, "Filter out unwanted connection types.");
+ DEFINE_string(filterhost, NULL, "Filter out the host from all candidates.");
+ DEFINE_string(pmuc, "groupchat.google.com", "The persistant muc domain.");
+ DEFINE_string(s, "talk.google.com", "The connection server to use.");
+ DEFINE_string(voiceinput, NULL, "RTP dump file for voice input.");
+ DEFINE_string(voiceoutput, NULL, "RTP dump file for voice output.");
+ DEFINE_string(videoinput, NULL, "RTP dump file for video input.");
+ DEFINE_string(videooutput, NULL, "RTP dump file for video output.");
+ DEFINE_bool(help, false, "Prints this message");
+
+ // parse options
+ FlagList::SetFlagsFromCommandLine(&argc, argv, true);
+ if (FLAG_help) {
+ FlagList::Print(NULL, false);
+ return 0;
+ }
+
+ bool auto_accept = FLAG_a;
+ bool debug = FLAG_d;
+ bool test_server = FLAG_testserver;
+ int32 portallocator_flags = FLAG_portallocator;
+ std::string pmuc_domain = FLAG_pmuc;
+ std::string server = FLAG_s;
+
+ // parse username and password, if present
+ buzz::Jid jid;
+ std::string username;
+ talk_base::InsecureCryptStringImpl pass;
+ if (argc > 1) {
+ username = argv[1];
+ if (argc > 2) {
+ pass.password() = argv[2];
+ }
+ }
+
if (debug)
talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
-
- talk_base::InitializeSSL();
- XmppPump pump;
- buzz::Jid jid;
- buzz::XmppClientSettings xcs;
- talk_base::InsecureCryptStringImpl pass;
- std::string username;
-
- std::cout << "JID: ";
- std::cin >> username;
+ if (username.empty()) {
+ std::cout << "JID: ";
+ std::cin >> username;
+ }
+ if (username.find('@') == std::string::npos) {
+ username.append("@localhost");
+ }
jid = buzz::Jid(username);
if (!jid.IsValid() || jid.node() == "") {
printf("Invalid JID. JIDs should be in the form user@domain\n");
return 1;
}
- SetConsoleEcho(false);
- std::cout << "Password: ";
- std::cin >> pass.password();
- SetConsoleEcho(true);
- std::cout << std::endl;
+ if (pass.password().empty() && !test_server) {
+ Console::SetEcho(false);
+ std::cout << "Password: ";
+ std::cin >> pass.password();
+ Console::SetEcho(true);
+ std::cout << std::endl;
+ }
+ buzz::XmppClientSettings xcs;
xcs.set_user(jid.node());
xcs.set_resource("call");
xcs.set_host(jid.domain());
- xcs.set_use_tls(true);
-
+ xcs.set_use_tls(!test_server);
+
+ if (test_server) {
+ pass.password() = jid.node();
+ xcs.set_allow_plain(true);
+ }
xcs.set_pass(talk_base::CryptString(pass));
- xcs.set_server(talk_base::SocketAddress("talk.google.com", 5222));
- printf("Logging in as %s\n", jid.Str().c_str());
- talk_base::PhysicalSocketServer ss;
+ std::string host;
+ int port;
+ int colon = server.find(':');
+ if (colon == -1) {
+ host = server;
+ port = DEFAULT_PORT;
+ } else {
+ host = server.substr(0, colon);
+ port = atoi(server.substr(colon + 1).c_str());
+ }
+
+ xcs.set_server(talk_base::SocketAddress(host, port));
+ printf("Logging in to %s as %s\n", server.c_str(), jid.Str().c_str());
+
+ talk_base::InitializeSSL();
+
+
+#if WIN32
+ // Need to pump messages on our main thread on Windows.
+ talk_base::Win32Thread w32_thread;
+ talk_base::ThreadManager::SetCurrent(&w32_thread);
+#endif
+ talk_base::Thread* main_thread = talk_base::Thread::Current();
+
+ XmppPump pump;
CallClient *client = new CallClient(pump.client());
-
- talk_base::Thread main_thread(&ss);
- talk_base::ThreadManager::SetCurrent(&main_thread);
- Console *console = new Console(&main_thread, client);
+
+ if (FLAG_voiceinput || FLAG_voiceoutput ||
+ FLAG_videoinput || FLAG_videooutput) {
+ // If any dump file is specified, we use FileMediaEngine.
+ cricket::MediaEngine* engine = CreateFileMediaEngine(FLAG_voiceinput,
+ FLAG_voiceoutput,
+ FLAG_videoinput,
+ FLAG_videooutput);
+ // The engine will be released by the client later.
+ client->SetMediaEngine(engine);
+ }
+
+ Console *console = new Console(main_thread, client);
client->SetConsole(console);
- talk_base::Thread *console_thread = new talk_base::Thread(&ss);
- console_thread->Start();
- console_thread->Post(console, MSG_START);
+ client->SetAutoAccept(auto_accept);
+ client->SetPmucDomain(pmuc_domain);
+ client->SetPortAllocatorFlags(portallocator_flags);
+ console->Start();
if (debug) {
pump.client()->SignalLogInput.connect(&debug_log_, &DebugLog::Input);
@@ -250,7 +337,12 @@
}
pump.DoLogin(xcs, new XmppSocket(true), NULL);
- main_thread.Run();
+ main_thread->Run();
+ pump.DoDisconnect();
+
+ console->Stop();
+ delete console;
+ delete client;
return 0;
}
diff --git a/talk/examples/call/call_main.cc~ b/talk/examples/call/call_main.cc~
new file mode 100644
index 0000000..fd7aafd
--- /dev/null
+++ b/talk/examples/call/call_main.cc~
@@ -0,0 +1,348 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time.h>
+#include <iomanip>
+#include <cstdio>
+#include <cstring>
+#include <vector>
+#include "talk/base/logging.h"
+#include "talk/base/flags.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/stream.h"
+#include "talk/base/ssladapter.h"
+#include "talk/base/win32socketserver.h"
+#include "talk/xmpp/xmppclientsettings.h"
+#include "talk/examples/login/xmppthread.h"
+#include "talk/examples/login/xmppauth.h"
+#include "talk/examples/login/xmpppump.h"
+#include "talk/examples/call/callclient.h"
+#include "talk/examples/call/console.h"
+#include "talk/session/phone/filemediaengine.h"
+
+class DebugLog : public sigslot::has_slots<> {
+ public:
+ DebugLog() :
+ debug_input_buf_(NULL), debug_input_len_(0), debug_input_alloc_(0),
+ debug_output_buf_(NULL), debug_output_len_(0), debug_output_alloc_(0),
+ censor_password_(false)
+ {}
+ char * debug_input_buf_;
+ int debug_input_len_;
+ int debug_input_alloc_;
+ char * debug_output_buf_;
+ int debug_output_len_;
+ int debug_output_alloc_;
+ bool censor_password_;
+
+ void Input(const char * data, int len) {
+ if (debug_input_len_ + len > debug_input_alloc_) {
+ char * old_buf = debug_input_buf_;
+ debug_input_alloc_ = 4096;
+ while (debug_input_alloc_ < debug_input_len_ + len) {
+ debug_input_alloc_ *= 2;
+ }
+ debug_input_buf_ = new char[debug_input_alloc_];
+ memcpy(debug_input_buf_, old_buf, debug_input_len_);
+ delete[] old_buf;
+ }
+ memcpy(debug_input_buf_ + debug_input_len_, data, len);
+ debug_input_len_ += len;
+ DebugPrint(debug_input_buf_, &debug_input_len_, false);
+ }
+
+ void Output(const char * data, int len) {
+ if (debug_output_len_ + len > debug_output_alloc_) {
+ char * old_buf = debug_output_buf_;
+ debug_output_alloc_ = 4096;
+ while (debug_output_alloc_ < debug_output_len_ + len) {
+ debug_output_alloc_ *= 2;
+ }
+ debug_output_buf_ = new char[debug_output_alloc_];
+ memcpy(debug_output_buf_, old_buf, debug_output_len_);
+ delete[] old_buf;
+ }
+ memcpy(debug_output_buf_ + debug_output_len_, data, len);
+ debug_output_len_ += len;
+ DebugPrint(debug_output_buf_, &debug_output_len_, true);
+ }
+
+ static bool IsAuthTag(const char * str, size_t len) {
+ if (str[0] == '<' && str[1] == 'a' &&
+ str[2] == 'u' &&
+ str[3] == 't' &&
+ str[4] == 'h' &&
+ str[5] <= ' ') {
+ std::string tag(str, len);
+
+ if (tag.find("mechanism") != std::string::npos)
+ return true;
+ }
+ return false;
+ }
+
+ void DebugPrint(char * buf, int * plen, bool output) {
+ int len = *plen;
+ if (len > 0) {
+ time_t tim = time(NULL);
+ struct tm * now = localtime(&tim);
+ char *time_string = asctime(now);
+ if (time_string) {
+ size_t time_len = strlen(time_string);
+ if (time_len > 0) {
+ time_string[time_len-1] = 0; // trim off terminating \n
+ }
+ }
+ LOG(INFO) << (output ? "SEND >>>>>>>>>>>>>>>>" : "RECV <<<<<<<<<<<<<<<<")
+ << " : " << time_string;
+
+ bool indent;
+ int start = 0, nest = 3;
+ for (int i = 0; i < len; i += 1) {
+ if (buf[i] == '>') {
+ if ((i > 0) && (buf[i-1] == '/')) {
+ indent = false;
+ } else if ((start + 1 < len) && (buf[start + 1] == '/')) {
+ indent = false;
+ nest -= 2;
+ } else {
+ indent = true;
+ }
+
+ // Output a tag
+ LOG(INFO) << std::setw(nest) << " "
+ << std::string(buf + start, i + 1 - start);
+
+ if (indent)
+ nest += 2;
+
+ // Note if it's a PLAIN auth tag
+ if (IsAuthTag(buf + start, i + 1 - start)) {
+ censor_password_ = true;
+ }
+
+ // incr
+ start = i + 1;
+ }
+
+ if (buf[i] == '<' && start < i) {
+ if (censor_password_) {
+ LOG(INFO) << std::setw(nest) << " " << "## TEXT REMOVED ##";
+ censor_password_ = false;
+ } else {
+ LOG(INFO) << std::setw(nest) << " "
+ << std::string(buf + start, i - start);
+ }
+ start = i;
+ }
+ }
+ len = len - start;
+ memcpy(buf, buf + start, len);
+ *plen = len;
+ }
+ }
+};
+
+static DebugLog debug_log_;
+static const int DEFAULT_PORT = 5222;
+
+
+cricket::MediaEngine* CreateFileMediaEngine(const char* voice_in,
+ const char* voice_out,
+ const char* video_in,
+ const char* video_out) {
+ cricket::FileMediaEngine* file_media_engine = new cricket::FileMediaEngine;
+ // Set the RTP dump file names.
+ if (voice_in) {
+ file_media_engine->set_voice_input_filename(voice_in);
+ }
+ if (voice_out) {
+ file_media_engine->set_voice_output_filename(voice_out);
+ }
+ if (video_in) {
+ file_media_engine->set_video_input_filename(video_in);
+ }
+ if (video_out) {
+ file_media_engine->set_video_output_filename(video_out);
+ }
+
+ // Set voice and video codecs. TODO: The codecs actually depend on
+ // the the input voice and video streams.
+ std::vector<cricket::AudioCodec> voice_codecs;
+ voice_codecs.push_back(
+ cricket::AudioCodec(9, "G722", 16000, 0, 1, 0));
+ file_media_engine->set_voice_codecs(voice_codecs);
+ std::vector<cricket::VideoCodec> video_codecs;
+ video_codecs.push_back(
+ cricket::VideoCodec(97, "H264", 320, 240, 30, 0));
+ file_media_engine->set_video_codecs(video_codecs);
+
+ return file_media_engine;
+}
+
+int main(int argc, char **argv) {
+ // This app has three threads. The main thread will run the XMPP client,
+ // which will print to the screen in its own thread. A second thread
+ // will get input from the console, parse it, and pass the appropriate
+ // message back to the XMPP client's thread. A third thread is used
+ // by MediaSessionClient as its worker thread.
+
+ // define options
+ DEFINE_bool(a, false, "Turn on auto accept.");
+ DEFINE_bool(d, false, "Turn on debugging.");
+ DEFINE_bool(testserver, false, "Use test server");
+ DEFINE_int(portallocator, 0, "Filter out unwanted connection types.");
+ DEFINE_string(filterhost, NULL, "Filter out the host from all candidates.");
+ DEFINE_string(pmuc, "groupchat.google.com", "The persistant muc domain.");
+ DEFINE_string(s, "talk.google.com", "The connection server to use.");
+ DEFINE_string(voiceinput, NULL, "RTP dump file for voice input.");
+ DEFINE_string(voiceoutput, NULL, "RTP dump file for voice output.");
+ DEFINE_string(videoinput, NULL, "RTP dump file for video input.");
+ DEFINE_string(videooutput, NULL, "RTP dump file for video output.");
+ DEFINE_bool(help, false, "Prints this message");
+
+ // parse options
+ FlagList::SetFlagsFromCommandLine(&argc, argv, true);
+ if (FLAG_help) {
+ FlagList::Print(NULL, false);
+ return 0;
+ }
+
+ bool auto_accept = FLAG_a;
+ bool debug = FLAG_d;
+ bool test_server = FLAG_testserver;
+ int32 portallocator_flags = FLAG_portallocator;
+ std::string pmuc_domain = FLAG_pmuc;
+ std::string server = FLAG_s;
+
+ // parse username and password, if present
+ buzz::Jid jid;
+ std::string username;
+ talk_base::InsecureCryptStringImpl pass;
+ if (argc > 1) {
+ username = argv[1];
+ if (argc > 2) {
+ pass.password() = argv[2];
+ }
+ }
+
+ if (debug)
+ talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
+
+ if (username.empty()) {
+ std::cout << "JID: ";
+ std::cin >> username;
+ }
+ if (username.find('@') == std::string::npos) {
+ username.append("@localhost");
+ }
+ jid = buzz::Jid(username);
+ if (!jid.IsValid() || jid.node() == "") {
+ printf("Invalid JID. JIDs should be in the form user@domain\n");
+ return 1;
+ }
+ if (pass.password().empty() && !test_server) {
+ Console::SetEcho(false);
+ std::cout << "Password: ";
+ std::cin >> pass.password();
+ Console::SetEcho(true);
+ std::cout << std::endl;
+ }
+
+ buzz::XmppClientSettings xcs;
+ xcs.set_user(jid.node());
+ xcs.set_resource("call");
+ xcs.set_host(jid.domain());
+ xcs.set_use_tls(!test_server);
+
+ if (test_server) {
+ pass.password() = jid.node();
+ xcs.set_allow_plain(true);
+ }
+ xcs.set_pass(talk_base::CryptString(pass));
+
+ std::string host;
+ int port;
+
+ int colon = server.find(':');
+ if (colon == -1) {
+ host = server;
+ port = DEFAULT_PORT;
+ } else {
+ host = server.substr(0, colon);
+ port = atoi(server.substr(colon + 1).c_str());
+ }
+
+ xcs.set_server(talk_base::SocketAddress(host, port));
+ printf("Logging in to %s as %s\n", server.c_str(), jid.Str().c_str());
+
+ talk_base::InitializeSSL();
+
+
+#if WIN32
+ // Need to pump messages on our main thread on Windows.
+ talk_base::Win32Thread w32_thread;
+ talk_base::ThreadManager::SetCurrent(&w32_thread);
+#endif
+ talk_base::Thread* main_thread = talk_base::Thread::Current();
+
+ XmppPump pump;
+ CallClient *client = new CallClient(pump.client());
+
+ if (FLAG_voiceinput || FLAG_voiceoutput ||
+ FLAG_videoinput || FLAG_videooutput) {
+ // If any dump file is specified, we use FileMediaEngine.
+ cricket::MediaEngine* engine = CreateFileMediaEngine(FLAG_voiceinput,
+ FLAG_voiceoutput,
+ FLAG_videoinput,
+ FLAG_videooutput);
+ // The engine will be released by the client later.
+ client->SetMediaEngine(engine);
+ }
+
+ Console *console = new Console(main_thread, client);
+ client->SetConsole(console);
+ client->SetAutoAccept(auto_accept);
+ client->SetPmucDomain(pmuc_domain);
+ client->SetPortAllocatorFlags(portallocator_flags);
+ console->Start();
+
+ if (debug) {
+ pump.client()->SignalLogInput.connect(&debug_log_, &DebugLog::Input);
+ pump.client()->SignalLogOutput.connect(&debug_log_, &DebugLog::Output);
+ }
+
+ pump.DoLogin(xcs, new XmppSocket(true), NULL);
+ main_thread->Run();
+ pump.DoDisconnect();
+
+ console->Stop();
+ delete console;
+ delete client;
+
+ return 0;
+}
diff --git a/talk/examples/call/callclient.cc b/talk/examples/call/callclient.cc
old mode 100755
new mode 100644
index 38b535b..03edf95
--- a/talk/examples/call/callclient.cc
+++ b/talk/examples/call/callclient.cc
@@ -1,39 +1,73 @@
/*
- * Jingle call example
+ * libjingle
* Copyright 2004--2005, Google Inc.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "talk/examples/call/callclient.h"
+
#include <string>
-#include <vector>
#include "talk/xmpp/constants.h"
#include "talk/base/helpers.h"
#include "talk/base/thread.h"
#include "talk/base/network.h"
#include "talk/base/socketaddress.h"
+#include "talk/base/stringutils.h"
#include "talk/p2p/base/sessionmanager.h"
-#include "talk/p2p/client/httpportallocator.h"
+#include "talk/p2p/client/basicportallocator.h"
#include "talk/p2p/client/sessionmanagertask.h"
-#include "talk/session/phone/phonesessionclient.h"
-#include "talk/examples/call/callclient.h"
+#include "talk/session/phone/devicemanager.h"
+#include "talk/session/phone/mediaengine.h"
+#include "talk/session/phone/mediasessionclient.h"
#include "talk/examples/call/console.h"
-#include "talk/examples/login/presencepushtask.h"
-#include "talk/examples/login/presenceouttask.h"
-#include "talk/examples/login/jingleinfotask.h"
+#include "talk/examples/call/presencepushtask.h"
+#include "talk/examples/call/presenceouttask.h"
+#include "talk/examples/call/mucinviterecvtask.h"
+#include "talk/examples/call/mucinvitesendtask.h"
+#include "talk/examples/call/friendinvitesendtask.h"
+#include "talk/examples/call/muc.h"
+#include "talk/examples/call/voicemailjidrequester.h"
+#ifdef USE_TALK_SOUND
+#include "talk/sound/platformsoundsystemfactory.h"
+#endif
+
+#include "talk/base/logging.h"
+
+class NullRenderer : public cricket::VideoRenderer {
+ public:
+ explicit NullRenderer(const char* s) : s_(s) {}
+ private:
+ bool SetSize(int width, int height, int reserved) {
+ LOG(LS_INFO) << "Video size for " << s_ << ": " << width << "x" << height;
+ return true;
+ }
+ bool RenderFrame(const cricket::VideoFrame *frame) {
+ return true;
+ }
+ const char* s_;
+};
namespace {
@@ -48,7 +82,7 @@
}
}
-} // namespace
+} // namespace
const char* CALL_COMMANDS =
"Available commands:\n"
@@ -56,6 +90,7 @@
" hangup Ends the call.\n"
" mute Stops sending voice.\n"
" unmute Re-starts sending voice.\n"
+" dtmf Sends a DTMF tone.\n"
" quit Quits the application.\n"
"";
@@ -70,9 +105,18 @@
const char* CONSOLE_COMMANDS =
"Available commands:\n"
"\n"
-" roster Prints the online friends from your roster.\n"
-" call <name> Initiates a call to the friend with the given name.\n"
-" quit Quits the application.\n"
+" roster Prints the online friends from your roster.\n"
+" friend user Request to add a user to your roster.\n"
+" call [jid] Initiates a call to the user[/room] with the\n"
+" given JID.\n"
+" vcall [jid] Initiates a video call to the user[/room] with\n"
+" the given JID.\n"
+" voicemail [jid] Leave a voicemail for the user with the given JID.\n"
+" join [room] Joins a multi-user-chat.\n"
+" invite user [room] Invites a friend to a multi-user-chat.\n"
+" leave [room] Leaves a multi-user-chat.\n"
+" getdevs Prints the available media devices.\n"
+" quit Quits the application.\n"
"";
void CallClient::ParseLine(const std::string& line) {
@@ -86,11 +130,11 @@
state = 1;
}
} else {
- assert(state == 1);
- assert(start >= 0);
+ ASSERT(state == 1);
+ ASSERT(start >= 0);
if (isspace(line[index])) {
std::string word(line, start, index - start);
- words.push_back(word);
+ words.push_back(word);
start = -1;
state = 0;
}
@@ -99,39 +143,53 @@
// Global commands
if ((words.size() == 1) && (words[0] == "quit")) {
- exit(0);
- }
-
- if (call_ && incoming_call_) {
+ Quit();
+ } else if (call_ && incoming_call_) {
if ((words.size() == 1) && (words[0] == "accept")) {
- assert(call_->sessions().size() == 1);
- call_->AcceptSession(call_->sessions()[0]);
- phone_client()->SetFocus(call_);
- incoming_call_ = false;
+ Accept();
} else if ((words.size() == 1) && (words[0] == "reject")) {
- call_->RejectSession(call_->sessions()[0]);
- incoming_call_ = false;
+ Reject();
} else {
console_->Print(RECEIVE_COMMANDS);
- }
+ }
} else if (call_) {
if ((words.size() == 1) && (words[0] == "hangup")) {
+ // TODO: do more shutdown here, move to Terminate()
call_->Terminate();
- call_ = NULL;
- session_ = NULL;
- console_->SetPrompt(NULL);
+ call_ = NULL;
+ session_ = NULL;
+ console_->SetPrompt(NULL);
} else if ((words.size() == 1) && (words[0] == "mute")) {
call_->Mute(true);
} else if ((words.size() == 1) && (words[0] == "unmute")) {
call_->Mute(false);
+ } else if ((words.size() == 2) && (words[0] == "dtmf")) {
+ int ev = std::string("0123456789*#").find(words[1][0]);
+ call_->PressDTMF(ev);
} else {
console_->Print(CALL_COMMANDS);
}
} else {
if ((words.size() == 1) && (words[0] == "roster")) {
PrintRoster();
- } else if ((words.size() == 2) && (words[0] == "call")) {
- MakeCallTo(words[1]);
+ } else if ((words.size() == 2) && (words[0] == "friend")) {
+ InviteFriend(words[1]);
+ } else if ((words.size() >= 1) && (words[0] == "call")) {
+ MakeCallTo((words.size() >= 2) ? words[1] : "", false);
+ } else if ((words.size() >= 1) && (words[0] == "vcall")) {
+ MakeCallTo((words.size() >= 2) ? words[1] : "", true);
+ } else if ((words.size() >= 1) && (words[0] == "join")) {
+ JoinMuc((words.size() >= 2) ? words[1] : "");
+ } else if ((words.size() >= 2) && (words[0] == "invite")) {
+ InviteToMuc(words[1], (words.size() >= 3) ? words[2] : "");
+ } else if ((words.size() >= 1) && (words[0] == "leave")) {
+ LeaveMuc((words.size() >= 2) ? words[1] : "");
+ } else if ((words.size() == 1) && (words[0] == "getdevs")) {
+ GetDevices();
+ } else if ((words.size() == 2) && (words[0] == "setvol")) {
+ SetVolume(words[1]);
+ } else if ((words.size() >= 1) && (words[0] == "voicemail")) {
+ CallVoicemail((words.size() >= 2) ? words[1] : "");
} else {
console_->Print(CONSOLE_COMMANDS);
}
@@ -139,61 +197,69 @@
}
CallClient::CallClient(buzz::XmppClient* xmpp_client)
- : xmpp_client_(xmpp_client), roster_(new RosterMap), call_(NULL),
- incoming_call_(false) {
+ : xmpp_client_(xmpp_client), media_engine_(NULL), media_client_(NULL),
+ call_(NULL), incoming_call_(false),
+ auto_accept_(false), pmuc_domain_("groupchat.google.com"),
+ local_renderer_(NULL), remote_renderer_(NULL),
+ roster_(new RosterMap), portallocator_flags_(0)
+#ifdef USE_TALK_SOUND
+ , sound_system_factory_(NULL)
+#endif
+ {
xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange);
}
CallClient::~CallClient() {
+ delete media_client_;
delete roster_;
}
const std::string CallClient::strerror(buzz::XmppEngine::Error err) {
switch (err) {
- case buzz::XmppEngine::ERROR_NONE:
- return "";
- case buzz::XmppEngine::ERROR_XML:
- return "Malformed XML or encoding error";
- case buzz::XmppEngine::ERROR_STREAM:
- return "XMPP stream error";
- case buzz::XmppEngine::ERROR_VERSION:
- return "XMPP version error";
- case buzz::XmppEngine::ERROR_UNAUTHORIZED:
- return "User is not authorized (Check your username and password)";
- case buzz::XmppEngine::ERROR_TLS:
- return "TLS could not be negotiated";
- case buzz::XmppEngine::ERROR_AUTH:
- return "Authentication could not be negotiated";
- case buzz::XmppEngine::ERROR_BIND:
- return "Resource or session binding could not be negotiated";
- case buzz::XmppEngine::ERROR_CONNECTION_CLOSED:
- return "Connection closed by output handler.";
- case buzz::XmppEngine::ERROR_DOCUMENT_CLOSED:
- return "Closed by </stream:stream>";
- case buzz::XmppEngine::ERROR_SOCKET:
- return "Socket error";
- default:
- return "Unknown error";
+ case buzz::XmppEngine::ERROR_NONE:
+ return "";
+ case buzz::XmppEngine::ERROR_XML:
+ return "Malformed XML or encoding error";
+ case buzz::XmppEngine::ERROR_STREAM:
+ return "XMPP stream error";
+ case buzz::XmppEngine::ERROR_VERSION:
+ return "XMPP version error";
+ case buzz::XmppEngine::ERROR_UNAUTHORIZED:
+ return "User is not authorized (Check your username and password)";
+ case buzz::XmppEngine::ERROR_TLS:
+ return "TLS could not be negotiated";
+ case buzz::XmppEngine::ERROR_AUTH:
+ return "Authentication could not be negotiated";
+ case buzz::XmppEngine::ERROR_BIND:
+ return "Resource or session binding could not be negotiated";
+ case buzz::XmppEngine::ERROR_CONNECTION_CLOSED:
+ return "Connection closed by output handler.";
+ case buzz::XmppEngine::ERROR_DOCUMENT_CLOSED:
+ return "Closed by </stream:stream>";
+ case buzz::XmppEngine::ERROR_SOCKET:
+ return "Socket error";
+ default:
+ return "Unknown error";
}
}
void CallClient::OnCallDestroy(cricket::Call* call) {
if (call == call_) {
- console_->SetPrompt(NULL);
+ if (remote_renderer_) {
+ delete remote_renderer_;
+ remote_renderer_ = NULL;
+ }
+ if (local_renderer_) {
+ delete local_renderer_;
+ local_renderer_ = NULL;
+ }
+ console_->SetPrompt(NULL);
console_->Print("call destroyed");
call_ = NULL;
- session_ = NULL;
+ session_ = NULL;
}
}
-void CallClient::OnJingleInfo(const std::string &relay_token,
- const std::vector<std::string> &relay_addresses,
- const std::vector<talk_base::SocketAddress> &stun_addresses) {
- port_allocator_->SetStunHosts(stun_addresses);
- port_allocator_->SetRelayHosts(relay_addresses);
- port_allocator_->SetRelayToken(relay_token);
-}
-
void CallClient::OnStateChange(buzz::XmppEngine::State state) {
switch (state) {
case buzz::XmppEngine::STATE_START:
@@ -213,18 +279,32 @@
case buzz::XmppEngine::STATE_CLOSED:
buzz::XmppEngine::Error error = xmpp_client_->GetError(NULL);
console_->Print("logged out..." + strerror(error));
- exit(0);
+ Quit();
}
}
void CallClient::InitPhone() {
std::string client_unique = xmpp_client_->jid().Str();
- cricket::InitRandom(client_unique.c_str(), client_unique.size());
+ talk_base::InitRandom(client_unique.c_str(), client_unique.size());
worker_thread_ = new talk_base::Thread();
+ // The worker thread must be started here since initialization of
+ // the ChannelManager will generate messages that need to be
+ // dispatched by it.
+ worker_thread_->Start();
- port_allocator_ = new cricket::HttpPortAllocator(&network_manager_, "call");
+ network_manager_ = new talk_base::NetworkManager();
+ // TODO: Decide if the relay address should be specified here.
+ talk_base::SocketAddress stun_addr("stun.l.google.com", 19302);
+ port_allocator_ =
+ new cricket::BasicPortAllocator(network_manager_, stun_addr,
+ talk_base::SocketAddress(), talk_base::SocketAddress(),
+ talk_base::SocketAddress());
+
+ if (portallocator_flags_ != 0) {
+ port_allocator_->set_flags(portallocator_flags_);
+ }
session_manager_ = new cricket::SessionManager(
port_allocator_, worker_thread_);
session_manager_->SignalRequestSignaling.connect(
@@ -236,16 +316,32 @@
session_manager_task_->EnableOutgoingMessages();
session_manager_task_->Start();
- buzz::JingleInfoTask *jit = new buzz::JingleInfoTask(xmpp_client_);
- jit->RefreshJingleInfoNow();
- jit->SignalJingleInfo.connect(this, &CallClient::OnJingleInfo);
- jit->Start();
-
- phone_client_ = new cricket::PhoneSessionClient(
- xmpp_client_->jid(),session_manager_);
- phone_client_->SignalCallCreate.connect(this, &CallClient::OnCallCreate);
+#ifdef USE_TALK_SOUND
+ if (!sound_system_factory_) {
+ sound_system_factory_ = new cricket::PlatformSoundSystemFactory();
+ }
+#endif
- worker_thread_->Start();
+ if (!media_engine_) {
+ media_engine_ = cricket::MediaEngine::Create(
+#ifdef USE_TALK_SOUND
+ sound_system_factory_
+#endif
+ );
+ }
+
+ media_client_ = new cricket::MediaSessionClient(
+ xmpp_client_->jid(),
+ session_manager_,
+ media_engine_,
+ new cricket::DeviceManager(
+#ifdef USE_TALK_SOUND
+ sound_system_factory_
+#endif
+ ));
+ media_client_->SignalCallCreate.connect(this, &CallClient::OnCallCreate);
+ media_client_->SignalDevicesChange.connect(this,
+ &CallClient::OnDevicesChange);
}
void CallClient::OnRequestSignaling() {
@@ -254,17 +350,24 @@
void CallClient::OnCallCreate(cricket::Call* call) {
call->SignalSessionState.connect(this, &CallClient::OnSessionState);
+ if (call->video()) {
+ local_renderer_ = new NullRenderer("local");
+ remote_renderer_ = new NullRenderer("remote");
+ }
}
void CallClient::OnSessionState(cricket::Call* call,
- cricket::Session* session,
- cricket::Session::State state) {
+ cricket::BaseSession* session,
+ cricket::BaseSession::State state) {
if (state == cricket::Session::STATE_RECEIVEDINITIATE) {
buzz::Jid jid(session->remote_name());
console_->Printf("Incoming call from '%s'", jid.Str().c_str());
call_ = call;
- session_ = session;
- incoming_call_ = true;
+ session_ = session;
+ incoming_call_ = true;
+ if (auto_accept_) {
+ Accept();
+ }
} else if (state == cricket::Session::STATE_SENTINITIATE) {
console_->Print("calling...");
} else if (state == cricket::Session::STATE_RECEIVEDACCEPT) {
@@ -276,28 +379,51 @@
} else if (state == cricket::Session::STATE_RECEIVEDTERMINATE) {
console_->Print("other side hung up");
}
- }
+}
void CallClient::InitPresence() {
- presence_push_ = new buzz::PresencePushTask(xmpp_client_);
+ presence_push_ = new buzz::PresencePushTask(xmpp_client_, this);
presence_push_->SignalStatusUpdate.connect(
this, &CallClient::OnStatusUpdate);
+ presence_push_->SignalMucJoined.connect(this, &CallClient::OnMucJoined);
+ presence_push_->SignalMucLeft.connect(this, &CallClient::OnMucLeft);
+ presence_push_->SignalMucStatusUpdate.connect(
+ this, &CallClient::OnMucStatusUpdate);
presence_push_->Start();
- buzz::Status my_status;
- my_status.set_jid(xmpp_client_->jid());
- my_status.set_available(true);
- my_status.set_show(buzz::Status::SHOW_ONLINE);
- my_status.set_priority(0);
- my_status.set_know_capabilities(true);
- my_status.set_phone_capability(true);
- my_status.set_is_google_client(true);
- my_status.set_version("1.0.0.66");
-
- buzz::PresenceOutTask* presence_out_ =
- new buzz::PresenceOutTask(xmpp_client_);
- presence_out_->Send(my_status);
+ presence_out_ = new buzz::PresenceOutTask(xmpp_client_);
+ RefreshStatus();
presence_out_->Start();
+
+ muc_invite_recv_ = new buzz::MucInviteRecvTask(xmpp_client_);
+ muc_invite_recv_->SignalInviteReceived.connect(this,
+ &CallClient::OnMucInviteReceived);
+ muc_invite_recv_->Start();
+
+ muc_invite_send_ = new buzz::MucInviteSendTask(xmpp_client_);
+ muc_invite_send_->Start();
+
+ friend_invite_send_ = new buzz::FriendInviteSendTask(xmpp_client_);
+ friend_invite_send_->Start();
+}
+
+void CallClient::RefreshStatus() {
+ int media_caps = media_client_->GetCapabilities();
+ my_status_.set_jid(xmpp_client_->jid());
+ my_status_.set_available(true);
+ my_status_.set_show(buzz::Status::SHOW_ONLINE);
+ my_status_.set_priority(0);
+ my_status_.set_know_capabilities(true);
+ my_status_.set_pmuc_capability(true);
+ my_status_.set_phone_capability(
+ (media_caps & cricket::MediaEngine::AUDIO_RECV) != 0);
+ my_status_.set_video_capability(
+ (media_caps & cricket::MediaEngine::VIDEO_RECV) != 0);
+ my_status_.set_camera_capability(
+ (media_caps & cricket::MediaEngine::VIDEO_SEND) != 0);
+ my_status_.set_is_google_client(true);
+ my_status_.set_version("1.0.0.67");
+ presence_out_->Send(my_status_);
}
void CallClient::OnStatusUpdate(const buzz::Status& status) {
@@ -319,46 +445,417 @@
}
}
-void CallClient::PrintRoster() {
- console_->SetPrompting(false);
- console_->Printf("Roster contains %d callable", roster_->size());
- RosterMap::iterator iter = roster_->begin();
- while (iter != roster_->end()) {
- console_->Printf("%s - %s",
- iter->second.jid.BareJid().Str().c_str(),
- DescribeStatus(iter->second.show, iter->second.status));
- iter++;
- }
- console_->SetPrompting(true);
-}
-
-void CallClient::MakeCallTo(const std::string& name) {
- bool found = false;
- buzz::Jid found_jid;
- buzz::Jid callto_jid = buzz::Jid(name);
+void CallClient::PrintRoster() {
+ console_->SetPrompting(false);
+ console_->Printf("Roster contains %d callable", roster_->size());
RosterMap::iterator iter = roster_->begin();
while (iter != roster_->end()) {
- if (iter->second.jid.BareEquals(callto_jid)) {
- found = true;
- found_jid = iter->second.jid;
- break;
+ console_->Printf("%s - %s",
+ iter->second.jid.BareJid().Str().c_str(),
+ DescribeStatus(iter->second.show, iter->second.status));
+ iter++;
+ }
+ console_->SetPrompting(true);
+}
+
+void CallClient::InviteFriend(const std::string& name) {
+ buzz::Jid jid(name);
+ if (!jid.IsValid() || jid.node() == "") {
+ console_->Printf("Invalid JID. JIDs should be in the form user@domain\n");
+ return;
+ }
+ // Note: for some reason the Buzz backend does not forward our presence
+ // subscription requests to the end user when that user is another call
+ // client as opposed to a Smurf user. Thus, in that scenario, you must
+ // run the friend command as the other user too to create the linkage
+ // (and you won't be notified to do so).
+ friend_invite_send_->Send(jid);
+ console_->Printf("Requesting to befriend %s.\n", name.c_str());
+}
+
+void CallClient::MakeCallTo(const std::string& name, bool video) {
+ bool found = false;
+ bool is_muc = false;
+ buzz::Jid callto_jid(name);
+ buzz::Jid found_jid;
+ if (name.length() == 0 && mucs_.size() > 0) {
+ // if no name, and in a MUC, establish audio with the MUC
+ found_jid = mucs_.begin()->first;
+ found = true;
+ is_muc = true;
+ } else if (name[0] == '+') {
+ // if the first character is a +, assume it's a phone number
+ found_jid = callto_jid;
+ found = true;
+ } else if (callto_jid.resource() == "voicemail") {
+ // if the resource is /voicemail, allow that
+ found_jid = callto_jid;
+ found = true;
+ } else {
+ // otherwise, it's a friend
+ for (RosterMap::iterator iter = roster_->begin();
+ iter != roster_->end(); ++iter) {
+ if (iter->second.jid.BareEquals(callto_jid)) {
+ found = true;
+ found_jid = iter->second.jid;
+ break;
+ }
}
- ++iter;
+
+ if (!found) {
+ if (mucs_.count(callto_jid) == 1 &&
+ mucs_[callto_jid]->state() == buzz::Muc::MUC_JOINED) {
+ found = true;
+ found_jid = callto_jid;
+ is_muc = true;
+ }
+ }
}
-
if (found) {
- console_->Printf("Found online friend '%s'", found_jid.Str().c_str());
- phone_client()->SignalCallDestroy.connect(
- this, &CallClient::OnCallDestroy);
- if (!call_) {
- call_ = phone_client()->CreateCall();
- console_->SetPrompt(found_jid.Str().c_str());
- call_->SignalSessionState.connect(this, &CallClient::OnSessionState);
- session_ = call_->InitiateSession(found_jid, NULL);
- }
- phone_client()->SetFocus(call_);
+ console_->Printf("Found %s '%s'", is_muc ? "room" : "online friend",
+ found_jid.Str().c_str());
+ PlaceCall(found_jid, is_muc, video);
} else {
console_->Printf("Could not find online friend '%s'", name.c_str());
- }
+ }
+}
+
+void CallClient::PlaceCall(const buzz::Jid& jid, bool is_muc, bool video) {
+ media_client_->SignalCallDestroy.connect(
+ this, &CallClient::OnCallDestroy);
+ if (!call_) {
+ call_ = media_client_->CreateCall(video, is_muc);
+ console_->SetPrompt(jid.Str().c_str());
+ session_ = call_->InitiateSession(jid);
+ if (is_muc) {
+ // If people in this room are already in a call, must add all their
+ // streams.
+ buzz::Muc::MemberMap& members = mucs_[jid]->members();
+ for (buzz::Muc::MemberMap::iterator elem = members.begin();
+ elem != members.end();
+ ++elem) {
+ AddStream(elem->second.audio_src_id(), elem->second.video_src_id());
+ }
+ }
+ }
+ media_client_->SetFocus(call_);
+ if (call_->video()) {
+ call_->SetLocalRenderer(local_renderer_);
+ // TODO: Call this once for every different remote SSRC
+ // once we get to testing multiway video.
+ call_->SetVideoRenderer(session_, 0, remote_renderer_);
+ }
+}
+
+void CallClient::CallVoicemail(const std::string& name) {
+ buzz::Jid jid(name);
+ if (!jid.IsValid() || jid.node() == "") {
+ console_->Printf("Invalid JID. JIDs should be in the form user@domain\n");
+ return;
+ }
+ buzz::VoicemailJidRequester *request =
+ new buzz::VoicemailJidRequester(xmpp_client_, jid, my_status_.jid());
+ request->SignalGotVoicemailJid.connect(this,
+ &CallClient::OnFoundVoicemailJid);
+ request->SignalVoicemailJidError.connect(this,
+ &CallClient::OnVoicemailJidError);
+ request->Start();
+}
+
+void CallClient::OnFoundVoicemailJid(const buzz::Jid& to,
+ const buzz::Jid& voicemail) {
+ console_->Printf("Calling %s's voicemail.\n", to.Str().c_str());
+ PlaceCall(voicemail, false, false);
+}
+
+void CallClient::OnVoicemailJidError(const buzz::Jid& to) {
+ console_->Printf("Unable to voicemail %s.\n", to.Str().c_str());
+}
+
+void CallClient::AddStream(uint32 audio_src_id, uint32 video_src_id) {
+ if (audio_src_id || video_src_id) {
+ console_->Printf("Adding stream (%u, %u)\n", audio_src_id, video_src_id);
+ call_->AddStream(session_, audio_src_id, video_src_id);
+ }
+}
+
+void CallClient::RemoveStream(uint32 audio_src_id, uint32 video_src_id) {
+ if (audio_src_id || video_src_id) {
+ console_->Printf("Removing stream (%u, %u)\n", audio_src_id, video_src_id);
+ call_->RemoveStream(session_, audio_src_id, video_src_id);
+ }
+}
+
+void CallClient::Accept() {
+ ASSERT(call_ && incoming_call_);
+ ASSERT(call_->sessions().size() == 1);
+ call_->AcceptSession(call_->sessions()[0]);
+ media_client_->SetFocus(call_);
+ if (call_->video()) {
+ call_->SetLocalRenderer(local_renderer_);
+ // The client never does an accept for multiway, so this must be 1:1,
+ // so there's no SSRC.
+ call_->SetVideoRenderer(session_, 0, remote_renderer_);
+ }
+ incoming_call_ = false;
+}
+
+void CallClient::Reject() {
+ ASSERT(call_ && incoming_call_);
+ call_->RejectSession(call_->sessions()[0]);
+ incoming_call_ = false;
+}
+
+void CallClient::Quit() {
+ talk_base::Thread::Current()->Quit();
+}
+
+void CallClient::JoinMuc(const std::string& room) {
+ buzz::Jid room_jid;
+ if (room.length() > 0) {
+ room_jid = buzz::Jid(room);
+ } else {
+ // generate a GUID of the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,
+ // for an eventual JID of private-chat-<GUID>@groupchat.google.com
+ char guid[37], guid_room[256];
+ for (size_t i = 0; i < ARRAY_SIZE(guid) - 1;) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ guid[i++] = '-';
+ } else {
+ sprintf(guid + i, "%04x", rand());
+ i += 4;
+ }
+ }
+
+ talk_base::sprintfn(guid_room, ARRAY_SIZE(guid_room),
+ "private-chat-%s@%s", guid, pmuc_domain_.c_str());
+ room_jid = buzz::Jid(guid_room);
+ }
+
+ if (!room_jid.IsValid()) {
+ console_->Printf("Unable to make valid muc endpoint for %s", room.c_str());
+ return;
+ }
+
+ MucMap::iterator elem = mucs_.find(room_jid);
+ if (elem != mucs_.end()) {
+ console_->Printf("This MUC already exists.");
+ return;
+ }
+
+ buzz::Muc* muc = new buzz::Muc(room_jid, xmpp_client_->jid().node());
+ mucs_[room_jid] = muc;
+ presence_out_->SendDirected(muc->local_jid(), my_status_);
+}
+
+void CallClient::OnMucInviteReceived(const buzz::Jid& inviter,
+ const buzz::Jid& room,
+ const std::vector<buzz::AvailableMediaEntry>& avail) {
+
+ console_->Printf("Invited to join %s by %s.\n", room.Str().c_str(),
+ inviter.Str().c_str());
+ console_->Printf("Available media:\n");
+ if (avail.size() > 0) {
+ for (std::vector<buzz::AvailableMediaEntry>::const_iterator i =
+ avail.begin();
+ i != avail.end();
+ ++i) {
+ console_->Printf(" %s, %s\n",
+ buzz::AvailableMediaEntry::TypeAsString(i->type),
+ buzz::AvailableMediaEntry::StatusAsString(i->status));
+ }
+ } else {
+ console_->Printf(" None\n");
+ }
+ // We automatically join the room.
+ JoinMuc(room.Str());
+}
+
+void CallClient::OnMucJoined(const buzz::Jid& endpoint) {
+ MucMap::iterator elem = mucs_.find(endpoint);
+ ASSERT(elem != mucs_.end() &&
+ elem->second->state() == buzz::Muc::MUC_JOINING);
+
+ buzz::Muc* muc = elem->second;
+ muc->set_state(buzz::Muc::MUC_JOINED);
+ console_->Printf("Joined \"%s\"", muc->jid().Str().c_str());
+}
+
+void CallClient::OnMucStatusUpdate(const buzz::Jid& jid,
+ const buzz::MucStatus& status) {
+
+ // Look up this muc.
+ MucMap::iterator elem = mucs_.find(jid);
+ ASSERT(elem != mucs_.end() &&
+ elem->second->state() == buzz::Muc::MUC_JOINED);
+
+ buzz::Muc* muc = elem->second;
+
+ if (status.jid().IsBare() || status.jid() == muc->local_jid()) {
+ // We are only interested in status about other users.
+ return;
+ }
+
+ if (!status.available()) {
+ // User is leaving the room.
+ buzz::Muc::MemberMap::iterator elem =
+ muc->members().find(status.jid().resource());
+
+ ASSERT(elem != muc->members().end());
+
+ // If user had src-ids, they have the left the room without explicitly
+ // hanging-up; must tear down the stream if in a call to this room.
+ if (call_ && session_->remote_name() == muc->jid().Str()) {
+ RemoveStream(elem->second.audio_src_id(), elem->second.video_src_id());
+ }
+
+ // Remove them from the room.
+ muc->members().erase(elem);
+ } else {
+ // Either user has joined or something changed about them.
+ // Note: The [] operator here will create a new entry if it does not
+ // exist, which is what we want.
+ buzz::MucStatus& member_status(
+ muc->members()[status.jid().resource()]);
+ if (call_ && session_->remote_name() == muc->jid().Str()) {
+ // We are in a call to this muc. Must potentially update our streams.
+ // The following code will correctly update our streams regardless of
+ // whether the SSRCs have been removed, added, or changed and regardless
+ // of whether that has been done to both or just one. This relies on the
+ // fact that AddStream/RemoveStream do nothing for SSRC arguments that are
+ // zero.
+ uint32 remove_audio_src_id = 0;
+ uint32 remove_video_src_id = 0;
+ uint32 add_audio_src_id = 0;
+ uint32 add_video_src_id = 0;
+ if (member_status.audio_src_id() != status.audio_src_id()) {
+ remove_audio_src_id = member_status.audio_src_id();
+ add_audio_src_id = status.audio_src_id();
+ }
+ if (member_status.video_src_id() != status.video_src_id()) {
+ remove_video_src_id = member_status.video_src_id();
+ add_video_src_id = status.video_src_id();
+ }
+ // Remove the old SSRCs, if any.
+ RemoveStream(remove_audio_src_id, remove_video_src_id);
+ // Add the new SSRCs, if any.
+ AddStream(add_audio_src_id, add_video_src_id);
+ }
+ // Update the status. This will use the compiler-generated copy
+ // constructor, which is perfectly adequate for this class.
+ member_status = status;
+ }
+}
+
+void CallClient::LeaveMuc(const std::string& room) {
+ buzz::Jid room_jid;
+ if (room.length() > 0) {
+ room_jid = buzz::Jid(room);
+ } else if (mucs_.size() > 0) {
+ // leave the first MUC if no JID specified
+ room_jid = mucs_.begin()->first;
+ }
+
+ if (!room_jid.IsValid()) {
+ console_->Printf("Invalid MUC JID.");
+ return;
+ }
+
+ MucMap::iterator elem = mucs_.find(room_jid);
+ if (elem == mucs_.end()) {
+ console_->Printf("No such MUC.");
+ return;
+ }
+
+ buzz::Muc* muc = elem->second;
+ muc->set_state(buzz::Muc::MUC_LEAVING);
+
+ buzz::Status status;
+ status.set_jid(my_status_.jid());
+ status.set_available(false);
+ status.set_priority(0);
+ presence_out_->SendDirected(muc->local_jid(), status);
+}
+
+void CallClient::OnMucLeft(const buzz::Jid& endpoint, int error) {
+ // We could be kicked from a room from any state. We would hope this
+ // happens While in the MUC_LEAVING state
+ MucMap::iterator elem = mucs_.find(endpoint);
+ if (elem == mucs_.end())
+ return;
+
+ buzz::Muc* muc = elem->second;
+ if (muc->state() == buzz::Muc::MUC_JOINING) {
+ console_->Printf("Failed to join \"%s\", code=%d",
+ muc->jid().Str().c_str(), error);
+ } else if (muc->state() == buzz::Muc::MUC_JOINED) {
+ console_->Printf("Kicked from \"%s\"",
+ muc->jid().Str().c_str());
+ }
+
+ delete muc;
+ mucs_.erase(elem);
+}
+
+void CallClient::InviteToMuc(const std::string& user, const std::string& room) {
+ // First find the room.
+ const buzz::Muc* found_muc;
+ if (room.length() == 0) {
+ if (mucs_.size() == 0) {
+ console_->Printf("Not in a room yet; can't invite.\n");
+ return;
+ }
+ // Invite to the first muc
+ found_muc = mucs_.begin()->second;
+ } else {
+ MucMap::iterator elem = mucs_.find(buzz::Jid(room));
+ if (elem == mucs_.end()) {
+ console_->Printf("Not in room %s.\n", room.c_str());
+ return;
+ }
+ found_muc = elem->second;
+ }
+ // Now find the user. We invite all of their resources.
+ bool found_user = false;
+ buzz::Jid user_jid(user);
+ for (RosterMap::iterator iter = roster_->begin();
+ iter != roster_->end(); ++iter) {
+ if (iter->second.jid.BareEquals(user_jid)) {
+ muc_invite_send_->Send(iter->second.jid, *found_muc);
+ found_user = true;
+ }
+ }
+ if (!found_user) {
+ console_->Printf("No such friend as %s.\n", user.c_str());
+ return;
+ }
+}
+
+void CallClient::GetDevices() {
+ std::vector<std::string> names;
+ media_client_->GetAudioInputDevices(&names);
+ printf("Audio input devices:\n");
+ PrintDevices(names);
+ media_client_->GetAudioOutputDevices(&names);
+ printf("Audio output devices:\n");
+ PrintDevices(names);
+ media_client_->GetVideoCaptureDevices(&names);
+ printf("Video capture devices:\n");
+ PrintDevices(names);
+}
+
+void CallClient::PrintDevices(const std::vector<std::string>& names) {
+ for (size_t i = 0; i < names.size(); ++i) {
+ printf("%d: %s\n", static_cast<int>(i), names[i].c_str());
+ }
+}
+
+void CallClient::OnDevicesChange() {
+ printf("Devices changed.\n");
+ RefreshStatus();
+}
+
+void CallClient::SetVolume(const std::string& level) {
+ media_client_->SetOutputVolume(strtol(level.c_str(), NULL, 10));
}
diff --git a/talk/examples/call/callclient.h b/talk/examples/call/callclient.h
old mode 100755
new mode 100644
index 1138f52..af27f34
--- a/talk/examples/call/callclient.h
+++ b/talk/examples/call/callclient.h
@@ -1,37 +1,58 @@
/*
- * Jingle call example
+ * libjingle
* Copyright 2004--2005, Google Inc.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CRICKET_EXAMPLES_CALL_CALLCLIENT_H__
-#define CRICKET_EXAMPLES_CALL_CALLCLIENT_H__
+#ifndef TALK_EXAMPLES_CALL_CALLCLIENT_H_
+#define TALK_EXAMPLES_CALL_CALLCLIENT_H_
#include <map>
#include <string>
-#include "talk/base/autodetectproxy.h"
+#include <vector>
+
#include "talk/p2p/base/session.h"
-#include "talk/p2p/client/httpportallocator.h"
+#include "talk/session/phone/mediachannel.h"
#include "talk/xmpp/xmppclient.h"
-#include "talk/examples/login/status.h"
+#include "talk/examples/call/status.h"
#include "talk/examples/call/console.h"
+#ifdef USE_TALK_SOUND
+#include "talk/sound/soundsystemfactory.h"
+#endif
namespace buzz {
class PresencePushTask;
+class PresenceOutTask;
+class MucInviteRecvTask;
+class MucInviteSendTask;
+class FriendInviteSendTask;
+class VoicemailJidRequester;
+class DiscoInfoQueryTask;
+class Muc;
class Status;
+class MucStatus;
+struct AvailableMediaEntry;
}
namespace talk_base {
@@ -41,7 +62,8 @@
namespace cricket {
class PortAllocator;
-class PhoneSessionClient;
+class MediaEngine;
+class MediaSessionClient;
class Receiver;
class Call;
class SessionManagerTask;
@@ -53,53 +75,112 @@
std::string status;
};
+class NullRenderer;
+
class CallClient: public sigslot::has_slots<> {
-public:
- CallClient(buzz::XmppClient* xmpp_client);
+ public:
+ explicit CallClient(buzz::XmppClient* xmpp_client);
~CallClient();
- cricket::PhoneSessionClient* phone_client() const { return phone_client_; }
+ cricket::MediaSessionClient* media_client() const { return media_client_; }
+ void SetMediaEngine(cricket::MediaEngine* media_engine) {
+ media_engine_ = media_engine;
+ }
+ void SetAutoAccept(bool auto_accept) {
+ auto_accept_ = auto_accept;
+ }
+ void SetPmucDomain(const std::string &pmuc_domain) {
+ pmuc_domain_ = pmuc_domain;
+ }
+ void SetConsole(Console *console) {
+ console_ = console;
+ }
- void PrintRoster();
- void MakeCallTo(const std::string& name);
- void SetConsole(Console *console) {console_ = console;}
void ParseLine(const std::string &str);
-private:
- typedef std::map<std::string,RosterItem> RosterMap;
+ void InviteFriend(const std::string& user);
+ void JoinMuc(const std::string& room);
+ void InviteToMuc(const std::string& user, const std::string& room);
+ void LeaveMuc(const std::string& room);
+ void SetPortAllocatorFlags(uint32 flags) { portallocator_flags_ = flags; }
+
+ typedef std::map<buzz::Jid, buzz::Muc*> MucMap;
+
+ const MucMap& mucs() const {
+ return mucs_;
+ }
+
+ private:
+ void AddStream(uint32 audio_src_id, uint32 video_src_id);
+ void RemoveStream(uint32 audio_src_id, uint32 video_src_id);
+ void OnStateChange(buzz::XmppEngine::State state);
+
+ void InitPhone();
+ void InitPresence();
+ void RefreshStatus();
+ void OnRequestSignaling();
+ void OnCallCreate(cricket::Call* call);
+ void OnCallDestroy(cricket::Call* call);
+ void OnSessionState(cricket::Call* call,
+ cricket::BaseSession* session,
+ cricket::BaseSession::State state);
+ void OnStatusUpdate(const buzz::Status& status);
+ void OnMucInviteReceived(const buzz::Jid& inviter, const buzz::Jid& room,
+ const std::vector<buzz::AvailableMediaEntry>& avail);
+ void OnMucJoined(const buzz::Jid& endpoint);
+ void OnMucStatusUpdate(const buzz::Jid& jid, const buzz::MucStatus& status);
+ void OnMucLeft(const buzz::Jid& endpoint, int error);
+ void OnDevicesChange();
+ void OnFoundVoicemailJid(const buzz::Jid& to, const buzz::Jid& voicemail);
+ void OnVoicemailJidError(const buzz::Jid& to);
+
+ static const std::string strerror(buzz::XmppEngine::Error err);
+
+ void PrintRoster();
+ void MakeCallTo(const std::string& name, bool video);
+ void PlaceCall(const buzz::Jid& jid, bool is_muc, bool video);
+ void CallVoicemail(const std::string& name);
+ void Accept();
+ void Reject();
+ void Quit();
+
+ void GetDevices();
+ void PrintDevices(const std::vector<std::string>& names);
+
+ void SetVolume(const std::string& level);
+
+ typedef std::map<std::string, RosterItem> RosterMap;
Console *console_;
buzz::XmppClient* xmpp_client_;
talk_base::Thread* worker_thread_;
- talk_base::NetworkManager network_manager_;
- talk_base::AutoDetectProxy *proxy_detect_;
- cricket::HttpPortAllocator* port_allocator_;
+ talk_base::NetworkManager* network_manager_;
+ cricket::PortAllocator* port_allocator_;
cricket::SessionManager* session_manager_;
cricket::SessionManagerTask* session_manager_task_;
- cricket::PhoneSessionClient* phone_client_;
-
- cricket::Call* call_;
- cricket::Session *session_;
+ cricket::MediaEngine* media_engine_;
+ cricket::MediaSessionClient* media_client_;
+ MucMap mucs_;
+
+ cricket::Call* call_;
+ cricket::BaseSession *session_;
bool incoming_call_;
+ bool auto_accept_;
+ std::string pmuc_domain_;
+ NullRenderer* local_renderer_;
+ NullRenderer* remote_renderer_;
+ buzz::Status my_status_;
buzz::PresencePushTask* presence_push_;
+ buzz::PresenceOutTask* presence_out_;
+ buzz::MucInviteRecvTask* muc_invite_recv_;
+ buzz::MucInviteSendTask* muc_invite_send_;
+ buzz::FriendInviteSendTask* friend_invite_send_;
RosterMap* roster_;
-
- void OnStateChange(buzz::XmppEngine::State state);
- void OnJingleInfo(const std::string &relay_token, const std::vector<std::string> &relay_hosts,
- const std::vector<talk_base::SocketAddress> &stun_hosts);
- void OnProxyDetect(talk_base::SignalThread *thread);
- void InitPhone();
- void OnRequestSignaling();
- void OnCallCreate(cricket::Call* call);
- void OnCallDestroy(cricket::Call* call);
- const std::string strerror(buzz::XmppEngine::Error err);
- void OnSessionState(cricket::Call* call,
- cricket::Session* session,
- cricket::Session::State state);
-
- void InitPresence();
- void OnStatusUpdate(const buzz::Status& status);
+ uint32 portallocator_flags_;
+#ifdef USE_TALK_SOUND
+ cricket::SoundSystemFactory* sound_system_factory_;
+#endif
};
-#endif // CRICKET_EXAMPLES_CALL_CALLCLIENT_H__
+#endif // TALK_EXAMPLES_CALL_CALLCLIENT_H_
diff --git a/talk/examples/call/console.cc b/talk/examples/call/console.cc
old mode 100755
new mode 100644
index d489fd8..0aa7a4f
--- a/talk/examples/call/console.cc
+++ b/talk/examples/call/console.cc
@@ -1,55 +1,113 @@
/*
- * Jingle call example
+ * libjingle
* Copyright 2004--2005, Google Inc.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _CRT_SECURE_NO_DEPRECATE 1
+#ifdef POSIX
+#include <unistd.h>
+#endif // POSIX
#include <cassert>
+#include "talk/base/logging.h"
#include "talk/base/messagequeue.h"
#include "talk/base/stringutils.h"
#include "talk/examples/call/console.h"
#include "talk/examples/call/callclient.h"
-Console::Console(talk_base::Thread *thread, CallClient *client) :
- client_thread_(thread), client_(client), prompt_(std::string("call")),
+#ifdef POSIX
+#include <signal.h>
+
+static void DoNothing(int unused) {}
+#endif
+
+Console::Console(talk_base::Thread *thread, CallClient *client) :
+ client_(client), client_thread_(thread),
+ console_thread_(new talk_base::Thread()), prompt_(std::string("call")),
prompting_(true) {
}
-void Console::StartConsole() {
- char input_buffer[64];
- for (;;) {
- fgets(input_buffer, sizeof(input_buffer), stdin);
- client_thread_->Post(this, MSG_INPUT,
- new talk_base::TypedMessageData<std::string>(input_buffer));
+Console::~Console() {
+ Stop();
+}
+
+void Console::Start() {
+ if (!console_thread_.get()) {
+ // stdin was closed in Stop(), so we can't restart.
+ LOG(LS_ERROR) << "Cannot re-start";
+ return;
+ }
+ if (console_thread_->started()) {
+ LOG(LS_WARNING) << "Already started";
+ return;
+ }
+ console_thread_->Start();
+ console_thread_->Post(this, MSG_START);
+}
+
+void Console::Stop() {
+ if (console_thread_.get() && console_thread_->started()) {
+#ifdef WIN32
+ CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
+#else
+ close(fileno(stdin));
+ // This forces the read() in fgets() to return with errno = EINTR. fgets()
+ // will retry the read() and fail, thus returning.
+ pthread_kill(console_thread_->GetPThread(), SIGUSR1);
+#endif
+ console_thread_->Stop();
+ console_thread_.reset();
}
}
-void Console::OnMessage(talk_base::Message *msg) {
- switch (msg->message_id) {
- case MSG_START:
- StartConsole();
- break;
- case MSG_INPUT:
- talk_base::TypedMessageData<std::string> *data =
- static_cast<talk_base::TypedMessageData<std::string>*>(msg->pdata);
- client_->ParseLine(data->data());
- break;
+void Console::SetEcho(bool on) {
+#ifdef WIN32
+ HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
+ if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
+ return;
+
+ DWORD mode;
+ if (!GetConsoleMode(hIn, &mode))
+ return;
+
+ if (on) {
+ mode = mode | ENABLE_ECHO_INPUT;
+ } else {
+ mode = mode & ~ENABLE_ECHO_INPUT;
}
+
+ SetConsoleMode(hIn, mode);
+#else
+ int re;
+ if (on)
+ re = system("stty echo");
+ else
+ re = system("stty -echo");
+ if (-1 == re)
+ return;
+#endif
}
void Console::Print(const char* str) {
@@ -74,4 +132,36 @@
Print(buf);
va_end(ap);
-}
\ No newline at end of file
+}
+
+void Console::RunConsole() {
+ char input_buffer[128];
+ while (fgets(input_buffer, sizeof(input_buffer), stdin) != NULL) {
+ client_thread_->Post(this, MSG_INPUT,
+ new talk_base::TypedMessageData<std::string>(input_buffer));
+ }
+}
+
+void Console::OnMessage(talk_base::Message *msg) {
+ switch (msg->message_id) {
+ case MSG_START:
+#ifdef POSIX
+ // Install a no-op signal so that we can abort RunConsole() by raising
+ // SIGUSR1.
+ struct sigaction act;
+ act.sa_handler = &DoNothing;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ if (sigaction(SIGUSR1, &act, NULL) < 0) {
+ LOG(LS_WARNING) << "Can't install signal";
+ }
+#endif
+ RunConsole();
+ break;
+ case MSG_INPUT:
+ talk_base::TypedMessageData<std::string> *data =
+ static_cast<talk_base::TypedMessageData<std::string>*>(msg->pdata);
+ client_->ParseLine(data->data());
+ break;
+ }
+}
diff --git a/talk/examples/call/console.h b/talk/examples/call/console.h
old mode 100755
new mode 100644
index 264251a..e2ba4f7
--- a/talk/examples/call/console.h
+++ b/talk/examples/call/console.h
@@ -1,60 +1,85 @@
/*
- * Jingle call example
+ * libjingle
* Copyright 2004--2005, Google Inc.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CRICKET_EXAMPLES_CALL_CONSOLE_H__
-#define CRICKET_EXAMPLES_CALL_CONSOLE_H__
+#ifndef TALK_EXAMPLES_CALL_CONSOLE_H_
+#define TALK_EXAMPLES_CALL_CONSOLE_H_
+
+#include <cstdio>
#include "talk/base/thread.h"
#include "talk/base/messagequeue.h"
+#include "talk/base/scoped_ptr.h"
class CallClient;
-enum {
- MSG_START,
- MSG_INPUT,
-};
-
class Console : public talk_base::MessageHandler {
public:
Console(talk_base::Thread *thread, CallClient *client);
+ ~Console();
+
+ // Starts reading lines from the console and giving them to the CallClient.
+ void Start();
+ // Stops reading lines. Cannot be restarted.
+ void Stop();
+
virtual void OnMessage(talk_base::Message *msg);
+
void SetPrompt(const char *prompt) {
- prompt_ = prompt ? std::string(prompt) : std::string("call");
+ prompt_ = prompt ? std::string(prompt) : std::string("call");
}
+
void SetPrompting(bool prompting) {
prompting_ = prompting;
if (prompting)
- printf("\n(%s) ", prompt_.c_str());
- }
- bool prompting() {return prompting_;}
+ printf("\n(%s) ", prompt_.c_str());
+ }
+
+ bool prompting() { return prompting_; }
void Print(const char* str);
void Print(const std::string& str);
void Printf(const char* format, ...);
+
+ static void SetEcho(bool on);
+
private:
+ enum {
+ MSG_START,
+ MSG_INPUT,
+ };
+
+ void RunConsole();
+ void ParseLine(std::string &str);
+
CallClient *client_;
talk_base::Thread *client_thread_;
- void StartConsole();
- void ParseLine(std::string &str);
+ talk_base::scoped_ptr<talk_base::Thread> console_thread_;
std::string prompt_;
bool prompting_;
};
-#endif // CRICKET_EXAMPLES_CALL_CONSOLE_H__
-
+#endif // TALK_EXAMPLES_CALL_CONSOLE_H_
diff --git a/talk/examples/call/discoitemsquerytask.cc b/talk/examples/call/discoitemsquerytask.cc
new file mode 100644
index 0000000..df6d96d
--- /dev/null
+++ b/talk/examples/call/discoitemsquerytask.cc
@@ -0,0 +1,97 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/examples/call/discoitemsquerytask.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/xmpp/constants.h"
+
+
+namespace buzz {
+
+namespace {
+const int kDiscoItemsTimeout = 60;
+} // namespace
+
+DiscoItemsQueryTask::DiscoItemsQueryTask(Task* parent,
+ const std::string node,
+ const Jid& to)
+ : XmppTask(parent, XmppEngine::HL_SINGLE), node_(node) {
+ set_timeout_seconds(kDiscoItemsTimeout);
+ to_ = to;
+}
+
+int DiscoItemsQueryTask::ProcessStart() {
+ talk_base::scoped_ptr<XmlElement> get(MakeIq(STR_GET, to_, task_id()));
+
+ XmlElement* element = new XmlElement(QN_DISCO_ITEMS_QUERY, true);
+ element->AddAttr(QN_NODE, node_);
+
+ get->AddElement(element);
+
+ if (SendStanza(get.get()) != XMPP_RETURN_OK) {
+ SignalDiscoItemsError(to_, NULL);
+ return STATE_ERROR;
+ }
+
+ return STATE_RESPONSE;
+}
+
+int DiscoItemsQueryTask::ProcessResponse() {
+ const XmlElement* stanza = NextStanza();
+ if (stanza == NULL)
+ return STATE_BLOCKED;
+
+ bool success = false;
+ if (stanza->Attr(QN_TYPE) != STR_ERROR) {
+ const XmlElement* query = stanza->FirstNamed(QN_DISCO_ITEMS_QUERY);
+ if (query) {
+ SignalGotDiscoItems(to_, query);
+ success = true;
+ }
+ }
+
+ if (!success) {
+ SignalDiscoItemsError(to_, stanza->FirstNamed(QN_ERROR));
+ }
+
+ return STATE_DONE;
+}
+
+int DiscoItemsQueryTask::OnTimeout() {
+ SignalDiscoItemsError(to_, NULL);
+ return XmppTask::OnTimeout();
+}
+
+bool DiscoItemsQueryTask::HandleStanza(const XmlElement* stanza) {
+ if (!MatchResponseIq(stanza, to_, task_id()))
+ return false;
+ QueueStanza(stanza);
+ return true;
+
+}
+
+}
diff --git a/talk/examples/call/discoitemsquerytask.h b/talk/examples/call/discoitemsquerytask.h
new file mode 100644
index 0000000..6be8c35
--- /dev/null
+++ b/talk/examples/call/discoitemsquerytask.h
@@ -0,0 +1,88 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Fires a disco items query, such as the following example:
+//
+// <iq type='get'
+// from='foo@gmail.com/asdf'
+// to='bar@google.com'
+// id='1234'>
+// <query xmlns=' http://jabber.org/protocol/disco#items'
+// node='blah '/>
+// </iq>
+//
+// Sample response:
+//
+// <iq type='result'
+// from=' hendriks@google.com'
+// to='rsturgell@google.com/asdf'
+// id='1234'>
+// <query xmlns=' http://jabber.org/protocol/disco#items '
+// node='blah'>
+// <item something='somethingelse'/>
+// </query>
+// </iq>
+
+
+#ifndef _DISCOITEMSQUERYTASK_H_
+#define _DISCOITEMSQUERYTASK_H_
+
+#include "talk/xmpp/xmpptask.h"
+
+namespace buzz {
+
+class DiscoItemsQueryTask : public XmppTask {
+ public:
+ // TODO: Currently, this only supports one query stanza - we may eventually
+ // need it to support multiple
+ DiscoItemsQueryTask(Task* parent, const std::string node, const Jid& to);
+
+ virtual int ProcessStart();
+ virtual int ProcessResponse();
+
+ // On success, fires a signal with the jid we sent the query to and the inner
+ // XmlElement
+ sigslot::signal2<Jid, const XmlElement*> SignalGotDiscoItems;
+
+ // The XmlElement here is the error element under the error response. If the
+ // request just timed out then this will be NULL
+ sigslot::signal2<Jid, const XmlElement*> SignalDiscoItemsError;
+
+ protected:
+ virtual bool HandleStanza(const XmlElement* stanza);
+ virtual int OnTimeout();
+
+ private:
+ // The jid we're querying
+ Jid to_;
+ // The name of the node
+ const std::string node_;
+};
+
+}
+
+#endif
diff --git a/talk/examples/call/friendinvitesendtask.cc b/talk/examples/call/friendinvitesendtask.cc
new file mode 100644
index 0000000..cdb0b2c
--- /dev/null
+++ b/talk/examples/call/friendinvitesendtask.cc
@@ -0,0 +1,76 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/xmpp/constants.h"
+#include "talk/examples/call/friendinvitesendtask.h"
+
+namespace buzz {
+
+XmppReturnStatus
+FriendInviteSendTask::Send(const Jid& user) {
+ if (GetState() != STATE_INIT && GetState() != STATE_START)
+ return XMPP_RETURN_BADSTATE;
+
+ // Need to first add to roster, then subscribe to presence.
+ XmlElement* iq = new XmlElement(QN_IQ);
+ iq->AddAttr(QN_TYPE, STR_SET);
+ XmlElement* query = new XmlElement(QN_ROSTER_QUERY);
+ XmlElement* item = new XmlElement(QN_ROSTER_ITEM);
+ item->AddAttr(QN_JID, user.Str());
+ item->AddAttr(QN_NAME, user.node());
+ query->AddElement(item);
+ iq->AddElement(query);
+ QueueStanza(iq);
+
+ // Subscribe to presence
+ XmlElement* presence = new XmlElement(QN_PRESENCE);
+ presence->AddAttr(QN_TO, user.Str());
+ presence->AddAttr(QN_TYPE, STR_SUBSCRIBE);
+ XmlElement* invitation = new XmlElement(QN_INVITATION);
+ invitation->AddAttr(QN_INVITE_MESSAGE,
+ "I've been using Google Talk and thought you might like to try it out. "
+ "We can use it to call each other for free over the internet. Here's an "
+ "invitation to download Google Talk. Give it a try!");
+ presence->AddElement(invitation);
+ QueueStanza(presence);
+
+ return XMPP_RETURN_OK;
+}
+
+int
+FriendInviteSendTask::ProcessStart() {
+ const XmlElement* stanza = NextStanza();
+ if (stanza == NULL)
+ return STATE_BLOCKED;
+
+ if (SendStanza(stanza) != XMPP_RETURN_OK)
+ return STATE_ERROR;
+
+ return STATE_START;
+}
+
+}
diff --git a/talk/base/natsocketfactory.h b/talk/examples/call/friendinvitesendtask.h
old mode 100755
new mode 100644
similarity index 65%
copy from talk/base/natsocketfactory.h
copy to talk/examples/call/friendinvitesendtask.h
index a689158..3f776bb
--- a/talk/base/natsocketfactory.h
+++ b/talk/examples/call/friendinvitesendtask.h
@@ -2,50 +2,47 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+#ifndef _FRIENDINVITESENDTASK_H_
+#define _FRIENDINVITESENDTASK_H_
-#include "talk/base/socketfactory.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
-namespace talk_base {
+namespace buzz {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
+class FriendInviteSendTask : public XmppTask {
public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+ FriendInviteSendTask(Task* parent) : XmppTask(parent) {}
+ virtual ~FriendInviteSendTask() {}
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+ XmppReturnStatus Send(const Jid& user);
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
+ virtual int ProcessStart();
};
-} // namespace talk_base
+}
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif
diff --git a/talk/base/natsocketfactory.h b/talk/examples/call/muc.h
old mode 100755
new mode 100644
similarity index 60%
copy from talk/base/natsocketfactory.h
copy to talk/examples/call/muc.h
index a689158..2f6df2e
--- a/talk/base/natsocketfactory.h
+++ b/talk/examples/call/muc.h
@@ -2,50 +2,65 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+#ifndef _MUC_H_
+#define _MUC_H_
-#include "talk/base/socketfactory.h"
+#include <map>
+#include "talk/xmpp/jid.h"
+#include "talk/examples/call/status.h"
-namespace talk_base {
+namespace buzz {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+class Muc {
+ public:
+ Muc(const Jid& jid, const std::string& nick) : state_(MUC_JOINING),
+ jid_(jid), local_jid_(Jid(jid.Str() + "/" + nick)) {}
+ ~Muc() {};
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+ enum State { MUC_JOINING, MUC_JOINED, MUC_LEAVING };
+ State state() const { return state_; }
+ void set_state(State state) { state_ = state; }
+ const Jid & jid() const { return jid_; }
+ const Jid & local_jid() const { return local_jid_; }
+
+ typedef std::map<std::string, MucStatus> MemberMap;
+
+ // All the intelligence about how to manage the members is in
+ // CallClient, so we completely expose the map.
+ MemberMap& members() {
+ return members_;
+ }
private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
+ State state_;
+ Jid jid_;
+ Jid local_jid_;
+ MemberMap members_;
};
-} // namespace talk_base
+}
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif
diff --git a/talk/examples/call/mucinviterecvtask.cc b/talk/examples/call/mucinviterecvtask.cc
new file mode 100644
index 0000000..061db74
--- /dev/null
+++ b/talk/examples/call/mucinviterecvtask.cc
@@ -0,0 +1,124 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/xmpp/constants.h"
+#include "talk/examples/call/mucinviterecvtask.h"
+
+namespace buzz {
+
+const char* types[] = {
+ "unknown",
+ "audio",
+ "video",
+};
+
+const char* statuses[] = {
+ "unknown",
+ "sendrecv",
+ "sendonly",
+ "recvonly",
+ "inactive",
+};
+
+const char*
+AvailableMediaEntry::TypeAsString(type_t type) {
+ // The values of the constants have been chosen such that this is correct.
+ return types[type];
+}
+
+const char*
+AvailableMediaEntry::StatusAsString(status_t status) {
+ // The values of the constants have been chosen such that this is correct.
+ return statuses[status];
+}
+
+int bodytext_to_array_pos(const XmlElement* elem, const char* array[],
+ int len, int defval = -1) {
+ if (elem) {
+ const std::string& body(elem->BodyText());
+ for (int i = 0; i < len; ++i) {
+ if (body == array[i]) {
+ // Found it.
+ return i;
+ }
+ }
+ }
+ // If we get here, it's not any value in the array.
+ return defval;
+}
+
+bool
+MucInviteRecvTask::HandleStanza(const XmlElement* stanza) {
+ // Figuring out that we want to handle this is a lot of the work of
+ // actually handling it, so we handle it right here instead of queueing it.
+ const XmlElement* xstanza;
+ const XmlElement* invite;
+ if (stanza->Name() != QN_MESSAGE) return false;
+ xstanza = stanza->FirstNamed(QN_MUC_USER_X);
+ if (!xstanza) return false;
+ invite = xstanza->FirstNamed(QN_MUC_USER_INVITE);
+ if (!invite) return false;
+ // Else it's an invite and we definitely want to handle it. Parse the
+ // available-media, if any.
+ std::vector<AvailableMediaEntry> v;
+ const XmlElement* avail =
+ invite->FirstNamed(QN_GOOGLE_MUC_USER_AVAILABLE_MEDIA);
+ if (avail) {
+ for (const XmlElement* entry = avail->FirstNamed(QN_GOOGLE_MUC_USER_ENTRY);
+ entry;
+ entry = entry->NextNamed(QN_GOOGLE_MUC_USER_ENTRY)) {
+ AvailableMediaEntry tmp;
+ // In the interest of debugging, we accept as much valid-looking data
+ // as we can.
+ tmp.label = atoi(entry->Attr(QN_LABEL).c_str());
+ tmp.type = static_cast<AvailableMediaEntry::type_t>(
+ bodytext_to_array_pos(
+ entry->FirstNamed(QN_GOOGLE_MUC_USER_TYPE),
+ types,
+ sizeof(types)/sizeof(const char*),
+ AvailableMediaEntry::TYPE_UNKNOWN));
+ tmp.status = static_cast<AvailableMediaEntry::status_t>(
+ bodytext_to_array_pos(
+ entry->FirstNamed(QN_GOOGLE_MUC_USER_STATUS),
+ statuses,
+ sizeof(statuses)/sizeof(const char*),
+ AvailableMediaEntry::STATUS_UNKNOWN));
+ v.push_back(tmp);
+ }
+ }
+ SignalInviteReceived(Jid(invite->Attr(QN_FROM)), Jid(stanza->Attr(QN_FROM)),
+ v);
+ return true;
+}
+
+int
+MucInviteRecvTask::ProcessStart() {
+ // We never queue anything so we are always blocked.
+ return STATE_BLOCKED;
+}
+
+}
diff --git a/talk/examples/call/mucinviterecvtask.h b/talk/examples/call/mucinviterecvtask.h
new file mode 100644
index 0000000..892b484
--- /dev/null
+++ b/talk/examples/call/mucinviterecvtask.h
@@ -0,0 +1,81 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MUCINVITERECVTASK_H_
+#define _MUCINVITERECVTASK_H_
+
+#include <vector>
+
+#include "talk/base/sigslot.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
+
+namespace buzz {
+
+struct AvailableMediaEntry {
+ enum type_t {
+ // SIP defines other media types, but these are the only ones we use in
+ // multiway jingle.
+ // These numbers are important; see .cc file
+ TYPE_UNKNOWN = 0, // indicates invalid string
+ TYPE_AUDIO = 1,
+ TYPE_VIDEO = 2,
+ };
+
+ enum status_t {
+ // These numbers are important; see .cc file
+ STATUS_UNKNOWN = 0, // indicates invalid string
+ STATUS_SENDRECV = 1,
+ STATUS_SENDONLY = 2,
+ STATUS_RECVONLY = 3,
+ STATUS_INACTIVE = 4,
+ };
+
+ uint32 label;
+ type_t type;
+ status_t status;
+
+ static const char* TypeAsString(type_t type);
+ static const char* StatusAsString(status_t status);
+};
+
+class MucInviteRecvTask : public XmppTask {
+ public:
+ MucInviteRecvTask(Task* parent) : XmppTask(parent, XmppEngine::HL_TYPE) {}
+ virtual int ProcessStart();
+
+ // First arg is inviter's JID; second is MUC's JID.
+ sigslot::signal3<const Jid&, const Jid&, const std::vector<AvailableMediaEntry>& > SignalInviteReceived;
+
+ protected:
+ virtual bool HandleStanza(const XmlElement* stanza);
+
+};
+
+}
+
+#endif
diff --git a/talk/examples/call/mucinvitesendtask.cc b/talk/examples/call/mucinvitesendtask.cc
new file mode 100644
index 0000000..efd9a81
--- /dev/null
+++ b/talk/examples/call/mucinvitesendtask.cc
@@ -0,0 +1,63 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/examples/call/mucinvitesendtask.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/xmppclient.h"
+
+namespace buzz {
+
+XmppReturnStatus
+MucInviteSendTask::Send(const Jid& user, const Muc& muc) {
+ if (GetState() != STATE_INIT && GetState() != STATE_START)
+ return XMPP_RETURN_BADSTATE;
+
+ XmlElement* message = new XmlElement(QN_MESSAGE);
+ message->AddAttr(QN_TO, muc.jid().Str());
+ XmlElement* xstanza = new XmlElement(QN_MUC_USER_X);
+ XmlElement* invite = new XmlElement(QN_MUC_USER_INVITE);
+ invite->AddAttr(QN_TO, user.Str());
+ xstanza->AddElement(invite);
+ message->AddElement(xstanza);
+
+ QueueStanza(message);
+ return XMPP_RETURN_OK;
+}
+
+int
+MucInviteSendTask::ProcessStart() {
+ const XmlElement* stanza = NextStanza();
+ if (stanza == NULL)
+ return STATE_BLOCKED;
+
+ if (SendStanza(stanza) != XMPP_RETURN_OK)
+ return STATE_ERROR;
+
+ return STATE_START;
+}
+
+}
diff --git a/talk/base/natsocketfactory.h b/talk/examples/call/mucinvitesendtask.h
old mode 100755
new mode 100644
similarity index 65%
copy from talk/base/natsocketfactory.h
copy to talk/examples/call/mucinvitesendtask.h
index a689158..18e0f99
--- a/talk/base/natsocketfactory.h
+++ b/talk/examples/call/mucinvitesendtask.h
@@ -2,50 +2,48 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+#ifndef _MUCINVITESENDTASK_H_
+#define _MUCINVITESENDTASK_H_
-#include "talk/base/socketfactory.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
+#include "talk/examples/call/muc.h"
-namespace talk_base {
+namespace buzz {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
+class MucInviteSendTask : public XmppTask {
public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+ MucInviteSendTask(Task* parent) : XmppTask(parent) {}
+ virtual ~MucInviteSendTask() {}
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+ XmppReturnStatus Send(const Jid& user, const Muc& muc);
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
+ virtual int ProcessStart();
};
-} // namespace talk_base
+}
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif
diff --git a/talk/examples/call/presenceouttask.cc b/talk/examples/call/presenceouttask.cc
new file mode 100644
index 0000000..ff3d91b
--- /dev/null
+++ b/talk/examples/call/presenceouttask.cc
@@ -0,0 +1,147 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time.h>
+#include <sstream>
+#include "talk/base/stringencode.h"
+#include "talk/examples/call/presenceouttask.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/xmppclient.h"
+
+namespace buzz {
+
+XmppReturnStatus
+PresenceOutTask::Send(const Status & s) {
+ if (GetState() != STATE_INIT && GetState() != STATE_START)
+ return XMPP_RETURN_BADSTATE;
+
+ QueueStanza(TranslateStatus(s));
+ return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+PresenceOutTask::SendDirected(const Jid & j, const Status & s) {
+ if (GetState() != STATE_INIT && GetState() != STATE_START)
+ return XMPP_RETURN_BADSTATE;
+
+ XmlElement * presence = TranslateStatus(s);
+ presence->AddAttr(QN_TO, j.Str());
+ QueueStanza(presence);
+ return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus PresenceOutTask::SendProbe(const Jid & jid) {
+ if (GetState() != STATE_INIT && GetState() != STATE_START)
+ return XMPP_RETURN_BADSTATE;
+
+ XmlElement * presence = new XmlElement(QN_PRESENCE);
+ presence->AddAttr(QN_TO, jid.Str());
+ presence->AddAttr(QN_TYPE, "probe");
+
+ QueueStanza(presence);
+ return XMPP_RETURN_OK;
+}
+
+int
+PresenceOutTask::ProcessStart() {
+ const XmlElement * stanza = NextStanza();
+ if (stanza == NULL)
+ return STATE_BLOCKED;
+
+ if (SendStanza(stanza) != XMPP_RETURN_OK)
+ return STATE_ERROR;
+
+ return STATE_START;
+}
+
+XmlElement *
+PresenceOutTask::TranslateStatus(const Status & s) {
+ XmlElement * result = new XmlElement(QN_PRESENCE);
+ if (!s.available()) {
+ result->AddAttr(QN_TYPE, STR_UNAVAILABLE);
+ }
+ else {
+ if (s.show() != Status::SHOW_ONLINE && s.show() != Status::SHOW_OFFLINE) {
+ result->AddElement(new XmlElement(QN_SHOW));
+ switch (s.show()) {
+ default:
+ result->AddText(STR_SHOW_AWAY, 1);
+ break;
+ case Status::SHOW_XA:
+ result->AddText(STR_SHOW_XA, 1);
+ break;
+ case Status::SHOW_DND:
+ result->AddText(STR_SHOW_DND, 1);
+ break;
+ case Status::SHOW_CHAT:
+ result->AddText(STR_SHOW_CHAT, 1);
+ break;
+ }
+ }
+
+ result->AddElement(new XmlElement(QN_STATUS));
+ result->AddText(s.status(), 1);
+
+ std::string pri;
+ talk_base::ToString(s.priority(), &pri);
+
+ result->AddElement(new XmlElement(QN_PRIORITY));
+ result->AddText(pri, 1);
+
+ if (s.know_capabilities() && s.is_google_client()) {
+ result->AddElement(new XmlElement(QN_CAPS_C, true));
+ result->AddAttr(QN_NODE, GOOGLE_CLIENT_NODE, 1);
+ result->AddAttr(QN_VER, s.version(), 1);
+
+ std::string caps;
+ caps.append(s.phone_capability() ? "voice-v1" : "");
+ caps.append(s.pmuc_capability() ? " pmuc-v1" : "");
+ caps.append(s.video_capability() ? " video-v1" : "");
+ caps.append(s.camera_capability() ? " camera-v1" : "");
+
+ result->AddAttr(QN_EXT, caps, 1);
+ }
+
+ // Put the delay mark on the presence according to JEP-0091
+ {
+ result->AddElement(new XmlElement(kQnDelayX, true));
+
+ // This here is why we *love* the C runtime
+ time_t current_time_seconds;
+ time(¤t_time_seconds);
+ struct tm* current_time = gmtime(¤t_time_seconds);
+ char output[256];
+ strftime(output, ARRAY_SIZE(output), "%Y%m%dT%H:%M:%S", current_time);
+ result->AddAttr(kQnStamp, output, 1);
+ }
+ }
+
+ return result;
+}
+
+
+}
diff --git a/talk/base/natsocketfactory.h b/talk/examples/call/presenceouttask.h
old mode 100755
new mode 100644
similarity index 66%
copy from talk/base/natsocketfactory.h
copy to talk/examples/call/presenceouttask.h
index a689158..36e7f15
--- a/talk/base/natsocketfactory.h
+++ b/talk/examples/call/presenceouttask.h
@@ -2,50 +2,52 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+#ifndef _PRESENCEOUTTASK_H_
+#define _PRESENCEOUTTASK_H_
-#include "talk/base/socketfactory.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
+#include "talk/examples/call/status.h"
-namespace talk_base {
+namespace buzz {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
+class PresenceOutTask : public XmppTask {
public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+ PresenceOutTask(Task * parent) : XmppTask(parent) {}
+ virtual ~PresenceOutTask() {}
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+ XmppReturnStatus Send(const Status & s);
+ XmppReturnStatus SendDirected(const Jid & j, const Status & s);
+ XmppReturnStatus SendProbe(const Jid& jid);
+ virtual int ProcessStart();
private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
+ XmlElement * TranslateStatus(const Status & s);
};
-} // namespace talk_base
+}
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif
diff --git a/talk/examples/call/presencepushtask.cc b/talk/examples/call/presencepushtask.cc
new file mode 100644
index 0000000..f820030
--- /dev/null
+++ b/talk/examples/call/presencepushtask.cc
@@ -0,0 +1,254 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/examples/call/presencepushtask.h"
+
+#include "talk/base/stringencode.h"
+#include "talk/examples/call/muc.h"
+#include "talk/xmpp/constants.h"
+
+
+
+namespace buzz {
+
+// string helper functions -----------------------------------------------------
+
+static bool
+IsXmlSpace(int ch) {
+ return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
+}
+
+static bool ListContainsToken(const std::string & list,
+ const std::string & token) {
+ size_t i = list.find(token);
+ if (i == std::string::npos || token.empty())
+ return false;
+ bool boundary_before = (i == 0 || IsXmlSpace(list[i - 1]));
+ bool boundary_after = (i == list.length() - token.length() ||
+ IsXmlSpace(list[i + token.length()]));
+ return boundary_before && boundary_after;
+}
+
+
+bool PresencePushTask::HandleStanza(const XmlElement * stanza) {
+ if (stanza->Name() != QN_PRESENCE)
+ return false;
+ QueueStanza(stanza);
+ return true;
+}
+
+static bool IsUtf8FirstByte(int c) {
+ return (((c)&0x80)==0) || // is single byte
+ ((unsigned char)((c)-0xc0)<0x3e); // or is lead byte
+}
+
+int PresencePushTask::ProcessStart() {
+ const XmlElement * stanza = NextStanza();
+ if (stanza == NULL)
+ return STATE_BLOCKED;
+
+ Jid from(stanza->Attr(QN_FROM));
+ std::map<Jid, buzz::Muc*>::const_iterator elem =
+ client_->mucs().find(from.BareJid());
+ if (elem == client_->mucs().end()) {
+ HandlePresence(from, stanza);
+ } else {
+ HandleMucPresence(elem->second, from, stanza);
+ }
+
+ return STATE_START;
+}
+
+void PresencePushTask::HandlePresence(const Jid& from,
+ const XmlElement* stanza) {
+ if (stanza->Attr(QN_TYPE) == STR_ERROR)
+ return;
+
+ Status s;
+ FillStatus(from, stanza, &s);
+ SignalStatusUpdate(s);
+}
+
+void PresencePushTask::HandleMucPresence(buzz::Muc* muc,
+ const Jid& from,
+ const XmlElement* stanza) {
+ if (from == muc->local_jid()) {
+ if (!stanza->HasAttr(QN_TYPE)) {
+ // We joined the MUC.
+ const XmlElement* elem = stanza->FirstNamed(QN_MUC_USER_X);
+ if (elem) {
+ elem = elem->FirstNamed(QN_MUC_USER_STATUS);
+ }
+ if (elem && (elem->Attr(QN_CODE) == "110" ||
+ elem->Attr(QN_CODE) == "100")) {
+ SignalMucJoined(muc->jid());
+ }
+ } else {
+ // We've been kicked. Bye.
+ int error = 0;
+ if (stanza->Attr(QN_TYPE) == STR_ERROR) {
+ const XmlElement* elem = stanza->FirstNamed(QN_ERROR);
+ if (elem && elem->HasAttr(QN_CODE)) {
+ error = atoi(elem->Attr(QN_CODE).c_str());
+ }
+ }
+ SignalMucLeft(muc->jid(), error);
+ }
+ } else {
+ MucStatus s;
+ FillMucStatus(from, stanza, &s);
+ SignalMucStatusUpdate(muc->jid(), s);
+ }
+}
+
+void PresencePushTask::FillStatus(const Jid& from, const XmlElement* stanza,
+ Status* s) {
+ s->set_jid(from);
+ if (stanza->Attr(QN_TYPE) == STR_UNAVAILABLE) {
+ s->set_available(false);
+ } else {
+ s->set_available(true);
+ const XmlElement * status = stanza->FirstNamed(QN_STATUS);
+ if (status != NULL) {
+ s->set_status(status->BodyText());
+
+ // Truncate status messages longer than 300 bytes
+ if (s->status().length() > 300) {
+ size_t len = 300;
+
+ // Be careful not to split legal utf-8 chars in half
+ while (!IsUtf8FirstByte(s->status()[len]) && len > 0) {
+ len -= 1;
+ }
+ std::string truncated(s->status(), 0, len);
+ s->set_status(truncated);
+ }
+ }
+
+ const XmlElement * priority = stanza->FirstNamed(QN_PRIORITY);
+ if (priority != NULL) {
+ int pri;
+ if (talk_base::FromString(priority->BodyText(), &pri)) {
+ s->set_priority(pri);
+ }
+ }
+
+ const XmlElement * show = stanza->FirstNamed(QN_SHOW);
+ if (show == NULL || show->FirstChild() == NULL) {
+ s->set_show(Status::SHOW_ONLINE);
+ }
+ else {
+ if (show->BodyText() == "away") {
+ s->set_show(Status::SHOW_AWAY);
+ }
+ else if (show->BodyText() == "xa") {
+ s->set_show(Status::SHOW_XA);
+ }
+ else if (show->BodyText() == "dnd") {
+ s->set_show(Status::SHOW_DND);
+ }
+ else if (show->BodyText() == "chat") {
+ s->set_show(Status::SHOW_CHAT);
+ }
+ else {
+ s->set_show(Status::SHOW_ONLINE);
+ }
+ }
+
+ const XmlElement * caps = stanza->FirstNamed(QN_CAPS_C);
+ if (caps != NULL) {
+ std::string node = caps->Attr(QN_NODE);
+ std::string ver = caps->Attr(QN_VER);
+ std::string exts = caps->Attr(QN_EXT);
+
+ s->set_know_capabilities(true);
+
+ if (node == GOOGLE_CLIENT_NODE) {
+ s->set_is_google_client(true);
+ s->set_version(ver);
+ }
+
+ if (ListContainsToken(exts, "voice-v1")) {
+ s->set_phone_capability(true);
+ }
+ if (ListContainsToken(exts, "video-v1")) {
+ s->set_video_capability(true);
+ }
+ }
+
+ const XmlElement* delay = stanza->FirstNamed(kQnDelayX);
+ if (delay != NULL) {
+ // Ideally we would parse this according to the Psuedo ISO-8601 rules
+ // that are laid out in JEP-0082:
+ // http://www.jabber.org/jeps/jep-0082.html
+ std::string stamp = delay->Attr(kQnStamp);
+ s->set_sent_time(stamp);
+ }
+ }
+}
+
+void PresencePushTask::FillMucStatus(const Jid& from, const XmlElement* stanza,
+ MucStatus* s) {
+ // First get the normal user status info. Happily, this is in the same
+ // format as it is for user presence.
+ FillStatus(from, stanza, s);
+
+ // Now look for src IDs, which will be present if this user is in a
+ // multiway call to this MUC.
+ const XmlElement* xstanza = stanza->FirstNamed(QN_MUC_USER_X);
+ if (xstanza) {
+ const XmlElement* media;
+ for (media = xstanza->FirstNamed(QN_GOOGLE_MUC_USER_MEDIA);
+ media; media = media->NextNamed(QN_GOOGLE_MUC_USER_MEDIA)) {
+
+ const XmlElement* type = media->FirstNamed(QN_GOOGLE_MUC_USER_TYPE);
+ if (!type) continue; // Shouldn't happen
+
+ const XmlElement* src_id = media->FirstNamed(QN_GOOGLE_MUC_USER_SRC_ID);
+ if (!src_id) continue; // Shouldn't happen
+
+ char *endptr;
+ uint32 src_id_num = strtoul(src_id->BodyText().c_str(), &endptr, 10);
+ if (src_id->BodyText().c_str()[0] == '\0' || endptr[0] != '\0') {
+ // String is not composed exclusively of leading whitespace plus a
+ // number (shouldn't happen). Ignore it.
+ continue;
+ }
+ // Else it's valid. Set it.
+
+ if (type->BodyText() == "audio") {
+ // This is the audio media element. Get the src-id.
+ s->set_audio_src_id(src_id_num);
+ } else if (type->BodyText() == "video") {
+ // This is the video media element. Get the src-id.
+ s->set_video_src_id(src_id_num);
+ }
+ }
+ }
+}
+
+}
diff --git a/talk/examples/call/presencepushtask.h b/talk/examples/call/presencepushtask.h
new file mode 100644
index 0000000..998a98e
--- /dev/null
+++ b/talk/examples/call/presencepushtask.h
@@ -0,0 +1,70 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PRESENCEPUSHTASK_H_
+#define _PRESENCEPUSHTASK_H_
+
+#include <vector>
+
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
+#include "talk/base/sigslot.h"
+#include "talk/examples/call/status.h"
+#include "talk/examples/call/callclient.h"
+
+namespace buzz {
+
+class PresencePushTask : public XmppTask {
+ public:
+ PresencePushTask(Task * parent, CallClient* client)
+ : XmppTask(parent, XmppEngine::HL_TYPE),
+ client_(client) {}
+ virtual int ProcessStart();
+
+ sigslot::signal1<const Status&> SignalStatusUpdate;
+ sigslot::signal1<const Jid&> SignalMucJoined;
+ sigslot::signal2<const Jid&, int> SignalMucLeft;
+ sigslot::signal2<const Jid&, const MucStatus&> SignalMucStatusUpdate;
+
+ protected:
+ virtual bool HandleStanza(const XmlElement * stanza);
+ void HandlePresence(const Jid& from, const XmlElement * stanza);
+ void HandleMucPresence(buzz::Muc* muc,
+ const Jid& from, const XmlElement * stanza);
+ static void FillStatus(const Jid& from, const XmlElement * stanza,
+ Status* status);
+ static void FillMucStatus(const Jid& from, const XmlElement * stanza,
+ MucStatus* status);
+
+ private:
+ CallClient* client_;
+};
+
+
+}
+
+#endif
diff --git a/talk/examples/login/status.h b/talk/examples/call/status.h
old mode 100755
new mode 100644
similarity index 66%
rename from talk/examples/login/status.h
rename to talk/examples/call/status.h
index 69f82b1..be4c2bd
--- a/talk/examples/login/status.h
+++ b/talk/examples/call/status.h
@@ -1,21 +1,30 @@
/*
- * Jingle call example
+ * libjingle
* Copyright 2004--2005, Google Inc.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#ifndef _STATUS_H_
#define _STATUS_H_
@@ -33,11 +42,13 @@
show_(SHOW_NONE),
available_(false),
e_code_(0),
- phone_capability_(false),
- fileshare_capability_(false),
+ feedback_probation_(false),
know_capabilities_(false),
- is_google_client_(false),
- feedback_probation_(false) {};
+ phone_capability_(false),
+ pmuc_capability_(false),
+ video_capability_(false),
+ camera_capability_(false),
+ is_google_client_(false) {}
~Status() {}
@@ -64,7 +75,9 @@
const std::string & error_string() const { return e_str_; }
bool know_capabilities() const { return know_capabilities_; }
bool phone_capability() const { return phone_capability_; }
- bool fileshare_capability() const { return fileshare_capability_; }
+ bool pmuc_capability() const { return pmuc_capability_; }
+ bool video_capability() const { return video_capability_; }
+ bool camera_capability() const { return camera_capability_; }
bool is_google_client() const { return is_google_client_; }
const std::string & version() const { return version_; }
bool feedback_probation() const { return feedback_probation_; }
@@ -79,7 +92,9 @@
{ e_code_ = e_code; e_str_ = e_str; }
void set_know_capabilities(bool f) { know_capabilities_ = f; }
void set_phone_capability(bool f) { phone_capability_ = f; }
- void set_fileshare_capability(bool f) { fileshare_capability_ = f; }
+ void set_pmuc_capability(bool f) { pmuc_capability_ = f; }
+ void set_video_capability(bool f) { video_capability_ = f; }
+ void set_camera_capability(bool f) { camera_capability_ = f; }
void set_is_google_client(bool f) { is_google_client_ = f; }
void set_version(const std::string & v) { version_ = v; }
void set_feedback_probation(bool f) { feedback_probation_ = f; }
@@ -199,13 +214,31 @@
// capabilities (valid only if know_capabilities_
bool know_capabilities_;
bool phone_capability_;
- bool fileshare_capability_;
+ bool pmuc_capability_;
+ bool video_capability_;
+ bool camera_capability_;
bool is_google_client_;
std::string version_;
std::string sent_time_; // from the jabber:x:delay element
};
+class MucStatus : public Status {
+public:
+ MucStatus() : audio_src_id_(0), video_src_id_(0) {}
+ uint32 audio_src_id() const { return audio_src_id_; }
+ uint32 video_src_id() const { return video_src_id_; }
+ void set_audio_src_id(uint32 audio_src_id) {
+ audio_src_id_ = audio_src_id;
+ }
+ void set_video_src_id(uint32 video_src_id) {
+ video_src_id_ = video_src_id;
+ }
+private:
+ uint32 audio_src_id_;
+ uint32 video_src_id_;
+};
+
}
diff --git a/talk/examples/call/voicemailjidrequester.cc b/talk/examples/call/voicemailjidrequester.cc
new file mode 100644
index 0000000..81f3dbc
--- /dev/null
+++ b/talk/examples/call/voicemailjidrequester.cc
@@ -0,0 +1,135 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/examples/call/discoitemsquerytask.h"
+#include "talk/examples/call/voicemailjidrequester.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/xmpp/constants.h"
+
+namespace buzz {
+
+VoicemailJidRequester::VoicemailJidRequester(talk_base::Task* parent,
+ const Jid& their_jid,
+ const Jid& my_jid) : Task(parent),
+ their_jid_(their_jid),
+ my_jid_(my_jid),
+ done_with_query_(false) {
+ parent_ = parent;
+}
+
+int VoicemailJidRequester::ProcessStart() {
+ // Start first query to node='voicemail'
+ DiscoItemsQueryTask* disco_items_task = new DiscoItemsQueryTask(this,
+ STR_VOICEMAIL, their_jid_.BareJid());
+ disco_items_task->SignalGotDiscoItems.connect(this,
+ &VoicemailJidRequester::OnFirstVoicemailJidSuccess);
+ disco_items_task->SignalDiscoItemsError.connect(this,
+ &VoicemailJidRequester::OnFirstVoicemailJidError);
+ disco_items_task->Start();
+ return STATE_BLOCKED;
+}
+
+void VoicemailJidRequester::OnFirstVoicemailJidError(buzz::Jid jid,
+ const XmlElement* xml_element) {
+ // First query gave us an error - try second query to node='outgoingvoicemail'
+ // and send it to your own jid
+ StartSecondQuery();
+}
+
+void VoicemailJidRequester::OnFirstVoicemailJidSuccess(buzz::Jid jid,
+ const XmlElement* xml_element) {
+ // Process the XML and fire the appropriate signals. If the xml was valid,
+ // then we're done with queries. If it wasn't valid, then start the second
+ // query.
+ bool valid_xml = ProcessVoicemailXml(xml_element);
+ if (valid_xml) {
+ done_with_query_ = true;
+ Wake();
+ } else {
+ StartSecondQuery();
+ }
+}
+
+void VoicemailJidRequester::OnSecondVoicemailJidError(buzz::Jid jid,
+ const XmlElement* xml_element) {
+ SignalVoicemailJidError(their_jid_);
+ done_with_query_ = true;
+ Wake();
+}
+
+void VoicemailJidRequester::OnSecondVoicemailJidSuccess(buzz::Jid jid,
+ const XmlElement* xml_element) {
+ // Whether this is good xml or bad, we're still done with the query
+ bool valid_xml = ProcessVoicemailXml(xml_element);
+ if (!valid_xml) {
+ SignalVoicemailJidError(their_jid_);
+ }
+ done_with_query_ = true;
+ Wake();
+}
+
+
+void VoicemailJidRequester::StartSecondQuery() {
+ // Send a query to your own jid to get the voicemail jid
+ DiscoItemsQueryTask* disco_items_task = new DiscoItemsQueryTask(this,
+ STR_OUTGOINGVOICEMAIL, my_jid_.BareJid());
+ disco_items_task->SignalGotDiscoItems.connect(this,
+ &VoicemailJidRequester::OnSecondVoicemailJidSuccess);
+ disco_items_task->SignalDiscoItemsError.connect(this,
+ &VoicemailJidRequester::OnSecondVoicemailJidError);
+ disco_items_task->Start();
+}
+
+int VoicemailJidRequester::Process(int state) {
+ if (done_with_query_) {
+ return STATE_DONE;
+ } else {
+ return talk_base::Task::Process(state);
+ }
+}
+
+bool VoicemailJidRequester::ProcessVoicemailXml(const XmlElement* xml_element) {
+ if (!xml_element) {
+ return false;
+ }
+ const std::string& node_name = xml_element->Attr(QN_NODE);
+ // Verify that it's one of the two nodes - we don't really care which one
+ if (node_name != "voicemail" &&
+ node_name != "outgoingvoicemail") {
+ return false;
+ }
+
+ const XmlElement* item = xml_element->FirstNamed(QN_DISCO_ITEM);
+ if (item) {
+ const std::string& jid_str = item->Attr(QN_JID);
+ buzz::Jid voicemail_jid(jid_str);
+ SignalGotVoicemailJid(their_jid_, voicemail_jid);
+ return true;
+ }
+ return false;
+}
+}
diff --git a/talk/examples/call/voicemailjidrequester.h b/talk/examples/call/voicemailjidrequester.h
new file mode 100644
index 0000000..34b3c4b
--- /dev/null
+++ b/talk/examples/call/voicemailjidrequester.h
@@ -0,0 +1,126 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// VoicemailJidRequester wraps the requesting of voicemail jids for a user.
+//
+// To request a voicemail jid, we first set off a query to the user's bare jid
+// that looks like this:
+//
+// <iq type='get'
+// from='foo@gmail.com/asdf'
+// to='bar@google.com'
+// id='1234'>
+// <query xmlns=' http://jabber.org/protocol/disco#items'
+// node='voicemail '/>
+// </iq>
+//
+// If foo@gmail.com's server supports voicemail, it'll return this, and forward
+// the jid up to phoneapp. We do not do the second query.
+//
+// <iq type='result'
+// from='foo@google.com'
+// to='bar@google.com/asdf'
+// id='1234'>
+// <query xmlns=' http://jabber.org/protocol/disco#items '
+// node=' voicemail '>
+// <item jid='bar@google.com/voicemail '/>
+// </query>
+// </iq>
+//
+// If we get an error, we spin off a new request:
+//
+// <iq type='get'
+// from='foo@google.com/asdf'
+// to='foo@google.com'
+// id='1234'>
+// <query xmlns=' http://jabber.org/protocol/disco#items'
+// node='outgoingvoicemail '/>
+// </iq>
+//
+// If both of these return errors, we then forward the request to phoneapp.
+
+#ifndef TALK_EXAMPLES_CALL_VOICEMAILJIDREQUESTER_H_
+#define TALK_EXAMPLES_CALL_VOICEMAILJIDREQUESTER_H_
+
+#include "talk/xmpp/xmpptask.h"
+
+namespace buzz {
+
+class Task;
+
+class VoicemailJidRequester : public sigslot::has_slots<>,
+ public talk_base::Task {
+ public:
+ VoicemailJidRequester(talk_base::Task* parent, const Jid& their_jid, const Jid& my_jid);
+
+ // Provides the target jid and the voicemail to reach it
+ sigslot::signal2<const Jid&, const Jid&> SignalGotVoicemailJid;
+ sigslot::signal1<const Jid&> SignalVoicemailJidError;
+
+ virtual int ProcessStart();
+ protected:
+
+ virtual int Process(int state);
+
+ private:
+ // The first query (to node='voicemail' has returned an error) - we now spin
+ // off a request to node='outgoingvoicemail')
+ void OnFirstVoicemailJidError(buzz::Jid jid, const XmlElement* xml_element);
+
+ // The first query (to node='voicemail' has returned a successfully)
+ void OnFirstVoicemailJidSuccess(buzz::Jid jid, const XmlElement* xml_element);
+
+ // The second query (to node='outgoingvoicemail') has returned an error -
+ // nothing we can do now, just fire our error signal
+ void OnSecondVoicemailJidError(buzz::Jid jid, const XmlElement* xml_element);
+
+ // The second query (to node='outgoingvoicemail') has returned a successfully
+ void OnSecondVoicemailJidSuccess(buzz::Jid jid,
+ const XmlElement* xml_element);
+
+ // Parse the xml, fire SignalGotVoicemail jid if it was valid (and had a jid)
+ // and return true if it was a valid xml.
+ bool ProcessVoicemailXml(const XmlElement* xml_element);
+
+ // Send a query to your own jid to get the voicemail jid. This is used after
+ // the first query fails.
+ void StartSecondQuery();
+
+ talk_base::Task* parent_;
+
+ Jid their_jid_;
+
+ // Your own jid (not the other user's)
+ Jid my_jid_;
+
+ // A flag indicating whether or not we're done with the query so that we can
+ // set the state correctly in Process(int state)
+ bool done_with_query_;
+};
+}
+
+#endif // TALK_EXAMPLES_CALL_VOICEMAILJIDREQUESTER_H_
diff --git a/talk/examples/login/Makefile.am b/talk/examples/login/Makefile.am
deleted file mode 100755
index 7bb7804..0000000
--- a/talk/examples/login/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-noinst_LTLIBRARIES= libcricketexampleslogin.la
-libcricketexampleslogin_la_SOURCES = xmppsocket.cc \
- xmppauth.cc \
- xmppthread.cc \
- xmpppump.cc \
- jingleinfotask.cc \
- presenceouttask.cc \
- presencepushtask.cc
-
-noinst_HEADERS = xmppauth.h \
- xmpppump.h \
- xmppsocket.h \
- xmppthread.h \
- jingleinfotask.h \
- presenceouttask.h \
- presencepushtask.h \
- status.h
-
-bin_PROGRAMS = login
-login_CXXFLAGS = $(AM_CXXFLAGS)
-login_SOURCES = login_main.cc xmppsocket.cc xmppthread.cc xmpppump.cc xmppauth.cc
-login_LDADD = $(top_srcdir)/talk/xmpp/libcricketxmpp.la \
- $(top_srcdir)/talk/xmllite/libcricketxmllite.la \
- $(top_srcdir)/talk/base/libcricketbase.la \
- $(EXPAT_LIBS) -lpthread -lssl -lcrypto
-AM_CPPFLAGS = -DPOSIX
diff --git a/talk/examples/login/jingleinfotask.cc b/talk/examples/login/jingleinfotask.cc
deleted file mode 100755
index 4f75853..0000000
--- a/talk/examples/login/jingleinfotask.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-#include "talk/examples/login/jingleinfotask.h"
-#include "talk/base/socketaddress.h"
-#include "talk/xmpp/constants.h"
-#include "talk/xmpp/xmppclient.h"
-
-
-namespace buzz {
-
-class JingleInfoTask::JingleInfoGetTask : public XmppTask {
-public:
- JingleInfoGetTask(Task * parent) : XmppTask(parent, XmppEngine::HL_SINGLE),
- done_(false) {}
-
- virtual int ProcessStart() {
- scoped_ptr<XmlElement> get(MakeIq(STR_GET, JID_EMPTY, task_id()));
- get->AddElement(new XmlElement(QN_JINGLE_INFO_QUERY, true));
- if (SendStanza(get.get()) != XMPP_RETURN_OK) {
- return STATE_ERROR;
- }
- return STATE_RESPONSE;
- }
- virtual int ProcessResponse() {
- if (done_)
- return STATE_DONE;
- return STATE_BLOCKED;
- }
-
-protected:
- virtual bool HandleStanza(const XmlElement * stanza) {
- if (!MatchResponseIq(stanza, JID_EMPTY, task_id()))
- return false;
-
- if (stanza->Attr(QN_TYPE) != STR_RESULT)
- return false;
-
- // Queue the stanza with the parent so these don't get handled out of order
- JingleInfoTask* parent = static_cast<JingleInfoTask*>(GetParent());
- parent->QueueStanza(stanza);
-
- // Wake ourselves so we can go into the done state
- done_ = true;
- Wake();
- return true;
- }
-
- bool done_;
-};
-
-
-void JingleInfoTask::RefreshJingleInfoNow() {
- JingleInfoGetTask* get_task = new JingleInfoGetTask(this);
- get_task->Start();
-}
-
-bool
-JingleInfoTask::HandleStanza(const XmlElement * stanza) {
- if (!MatchRequestIq(stanza, "set", QN_JINGLE_INFO_QUERY))
- return false;
-
- // only respect relay push from the server
- Jid from(stanza->Attr(QN_FROM));
- if (from != JID_EMPTY &&
- !from.BareEquals(GetClient()->jid()) &&
- from != Jid(GetClient()->jid().domain()))
- return false;
-
- QueueStanza(stanza);
- return true;
-}
-
-int
-JingleInfoTask::ProcessStart() {
- std::vector<std::string> relay_hosts;
- std::vector<talk_base::SocketAddress> stun_hosts;
- std::string relay_token;
- const XmlElement * stanza = NextStanza();
- if (stanza == NULL)
- return STATE_BLOCKED;
- const XmlElement * query = stanza->FirstNamed(QN_JINGLE_INFO_QUERY);
- if (query == NULL)
- return STATE_START;
- const XmlElement *stun = query->FirstNamed(QN_JINGLE_INFO_STUN);
- if (stun) {
- for (const XmlElement *server = stun->FirstNamed(QN_JINGLE_INFO_SERVER);
- server != NULL; server = server->NextNamed(QN_JINGLE_INFO_SERVER)) {
- std::string host = server->Attr(QN_JINGLE_INFO_HOST);
- std::string port = server->Attr(QN_JINGLE_INFO_UDP);
- if (host != STR_EMPTY && host != STR_EMPTY)
- stun_hosts.push_back(talk_base::SocketAddress(host, atoi(port.c_str())));
- }
- }
-
- const XmlElement *relay = query->FirstNamed(QN_JINGLE_INFO_RELAY);
- if (relay) {
- relay_token = relay->TextNamed(QN_JINGLE_INFO_TOKEN);
- for (const XmlElement *server = relay->FirstNamed(QN_JINGLE_INFO_SERVER);
- server != NULL; server = server->NextNamed(QN_JINGLE_INFO_SERVER)) {
- std::string host = server->Attr(QN_JINGLE_INFO_HOST);
- if (host != STR_EMPTY) {
- relay_hosts.push_back(host);
- }
- }
- }
- SignalJingleInfo(relay_token, relay_hosts, stun_hosts);
- return STATE_START;
-}
-
-
-}
-
-
-
diff --git a/talk/examples/login/jingleinfotask.h b/talk/examples/login/jingleinfotask.h
deleted file mode 100755
index be7073b..0000000
--- a/talk/examples/login/jingleinfotask.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _JINGLEINFOTASK_H_
-#define _JINGLEINFOTASK_H_
-
-#include "talk/p2p/client/httpportallocator.h"
-#include "talk/xmpp/xmppengine.h"
-#include "talk/xmpp/xmpptask.h"
-#include "talk/base/sigslot.h"
-#include "status.h"
-
-namespace buzz {
-
-class JingleInfoTask : public XmppTask {
-
- public:
- JingleInfoTask(Task * parent) :
- XmppTask(parent, XmppEngine::HL_TYPE) {}
-
- virtual int ProcessStart();
- void RefreshJingleInfoNow();
-
- sigslot::signal3<const std::string &,
- const std::vector<std::string> &,
- const std::vector<talk_base::SocketAddress> &> SignalJingleInfo;
-
- protected:
- class JingleInfoGetTask;
- friend class JingleInfoGetTask;
-
- virtual bool HandleStanza(const XmlElement * stanza);
-};
-
-
-}
-
-#endif
-
diff --git a/talk/examples/login/login_main.cc b/talk/examples/login/login_main.cc
old mode 100755
new mode 100644
index 186d6f7..186020a
--- a/talk/examples/login/login_main.cc
+++ b/talk/examples/login/login_main.cc
@@ -25,30 +25,31 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <cstdio>
+#include <iostream>
+
#include "talk/base/thread.h"
#include "talk/xmpp/xmppclientsettings.h"
#include "talk/examples/login/xmppthread.h"
-#include <iostream>
int main(int argc, char **argv) {
- printf("Auth Cookie: ");
- fflush(stdout);
+ std::cout << "Auth Cookie: ";
+ std::string auth_cookie;
+ std::getline(std::cin, auth_cookie);
- char auth_cookie[256];
- scanf("%s", auth_cookie);
-
- char username[256];
- scanf("%s", username);
+ std::cout << "User Name: ";
+ std::string username;
+ std::getline(std::cin, username);
// Start xmpp on a different thread
XmppThread thread;
thread.Start();
buzz::XmppClientSettings xcs;
- xcs.set_user(username);
+ xcs.set_user(username.c_str());
xcs.set_host("gmail.com");
xcs.set_use_tls(false);
- xcs.set_auth_cookie(auth_cookie);
+ xcs.set_auth_cookie(auth_cookie.c_str());
xcs.set_server(talk_base::SocketAddress("talk.google.com", 5222));
thread.Login(xcs);
diff --git a/talk/examples/login/presenceouttask.cc b/talk/examples/login/presenceouttask.cc
deleted file mode 100755
index 1eaf516..0000000
--- a/talk/examples/login/presenceouttask.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Jingle call example
- * Copyright 2004--2005, Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <time.h>
-#include <sstream>
-#include "talk/base/stringencode.h"
-#include "talk/examples/login/presenceouttask.h"
-#include "talk/xmpp/constants.h"
-#include "talk/xmpp/xmppclient.h"
-
-namespace buzz {
-
-XmppReturnStatus
-PresenceOutTask::Send(const Status & s) {
- if (GetState() != STATE_INIT)
- return XMPP_RETURN_BADSTATE;
-
- stanza_.reset(TranslateStatus(s));
- return XMPP_RETURN_OK;
-}
-
-XmppReturnStatus
-PresenceOutTask::SendDirected(const Jid & j, const Status & s) {
- if (GetState() != STATE_INIT)
- return XMPP_RETURN_BADSTATE;
-
- XmlElement * presence = TranslateStatus(s);
- presence->AddAttr(QN_TO, j.Str());
- stanza_.reset(presence);
- return XMPP_RETURN_OK;
-}
-
-XmppReturnStatus PresenceOutTask::SendProbe(const Jid & jid) {
- if (GetState() != STATE_INIT)
- return XMPP_RETURN_BADSTATE;
-
- XmlElement * presence = new XmlElement(QN_PRESENCE);
- presence->AddAttr(QN_TO, jid.Str());
- presence->AddAttr(QN_TYPE, "probe");
-
- stanza_.reset(presence);
- return XMPP_RETURN_OK;
-}
-
-int
-PresenceOutTask::ProcessStart() {
- if (SendStanza(stanza_.get()) != XMPP_RETURN_OK)
- return STATE_ERROR;
- return STATE_DONE;
-}
-
-XmlElement *
-PresenceOutTask::TranslateStatus(const Status & s) {
- XmlElement * result = new XmlElement(QN_PRESENCE);
- if (!s.available()) {
- result->AddAttr(QN_TYPE, STR_UNAVAILABLE);
- }
- else {
- if (s.show() != Status::SHOW_ONLINE && s.show() != Status::SHOW_OFFLINE) {
- result->AddElement(new XmlElement(QN_SHOW));
- switch (s.show()) {
- default:
- result->AddText(STR_SHOW_AWAY, 1);
- break;
- case Status::SHOW_XA:
- result->AddText(STR_SHOW_XA, 1);
- break;
- case Status::SHOW_DND:
- result->AddText(STR_SHOW_DND, 1);
- break;
- case Status::SHOW_CHAT:
- result->AddText(STR_SHOW_CHAT, 1);
- break;
- }
- }
-
- result->AddElement(new XmlElement(QN_STATUS));
- result->AddText(s.status(), 1);
-
- std::string pri;
- talk_base::ToString(s.priority(), &pri);
-
- result->AddElement(new XmlElement(QN_PRIORITY));
- result->AddText(pri, 1);
-
- if (s.know_capabilities() && s.is_google_client()) {
- std::string caps;
- if (s.fileshare_capability())
- caps += "share-v1";
- if (s.phone_capability())
- caps += " voice-v1";
- result->AddElement(new XmlElement(QN_CAPS_C, true));
- result->AddAttr(QN_NODE, GOOGLE_CLIENT_NODE, 1);
- result->AddAttr(QN_VER, s.version(), 1);
- result->AddAttr(QN_EXT, caps, 1);
- }
-
- // Put the delay mark on the presence according to JEP-0091
- {
- result->AddElement(new XmlElement(kQnDelayX, true));
-
- // This here is why we *love* the C runtime
- time_t current_time_seconds;
- time(¤t_time_seconds);
- struct tm* current_time = gmtime(¤t_time_seconds);
- char output[256];
- strftime(output, ARRAY_SIZE(output), "%Y%m%dT%H:%M:%S", current_time);
- result->AddAttr(kQnStamp, output, 1);
- }
-
- }
-
- return result;
-}
-
-
-}
diff --git a/talk/examples/login/presenceouttask.h b/talk/examples/login/presenceouttask.h
deleted file mode 100755
index bd691f4..0000000
--- a/talk/examples/login/presenceouttask.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Jingle call example
- * Copyright 2004--2005, Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _PRESENCEOUTTASK_H_
-#define _PRESENCEOUTTASK_H_
-
-#include "talk/xmpp/xmppengine.h"
-#include "talk/xmpp/xmpptask.h"
-#include "talk/examples/login/status.h"
-
-namespace buzz {
-
-class PresenceOutTask : public XmppTask {
-public:
- PresenceOutTask(Task * parent) : XmppTask(parent) {}
- virtual ~PresenceOutTask() {}
-
- XmppReturnStatus Send(const Status & s);
- XmppReturnStatus SendDirected(const Jid & j, const Status & s);
- XmppReturnStatus SendProbe(const Jid& jid);
-
- virtual int ProcessStart();
-private:
- XmlElement * TranslateStatus(const Status & s);
- scoped_ptr<XmlElement> stanza_;
-};
-
-}
-
-#endif
diff --git a/talk/examples/login/presencepushtask.cc b/talk/examples/login/presencepushtask.cc
deleted file mode 100755
index 4895190..0000000
--- a/talk/examples/login/presencepushtask.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Jingle call example
- * Copyright 2004--2005, Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "talk/base/stringencode.h"
-#include "talk/examples/login/presencepushtask.h"
-#include "talk/xmpp/constants.h"
-#include <sstream>
-
-
-namespace buzz {
-
-// string helper functions -----------------------------------------------------
-
-static bool
-IsXmlSpace(int ch) {
- return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
-}
-
-static bool
-ListContainsToken(const std::string & list, const std::string & token) {
- size_t i = list.find(token);
- if (i == std::string::npos || token.empty())
- return false;
- bool boundary_before = (i == 0 || IsXmlSpace(list[i - 1]));
- bool boundary_after = (i == list.length() - token.length() || IsXmlSpace(list[i + token.length()]));
- return boundary_before && boundary_after;
-}
-
-
-bool
-PresencePushTask::HandleStanza(const XmlElement * stanza) {
- if (stanza->Name() != QN_PRESENCE)
- return false;
- if (stanza->HasAttr(QN_TYPE) && stanza->Attr(QN_TYPE) != STR_UNAVAILABLE)
- return false;
- QueueStanza(stanza);
- return true;
-}
-
-static bool IsUtf8FirstByte(int c) {
- return (((c)&0x80)==0) || // is single byte
- ((unsigned char)((c)-0xc0)<0x3e); // or is lead byte
-}
-
-int
-PresencePushTask::ProcessStart() {
- const XmlElement * stanza = NextStanza();
- if (stanza == NULL)
- return STATE_BLOCKED;
- Status s;
-
- s.set_jid(Jid(stanza->Attr(QN_FROM)));
-
- if (stanza->Attr(QN_TYPE) == STR_UNAVAILABLE) {
- s.set_available(false);
- SignalStatusUpdate(s);
- }
- else {
- s.set_available(true);
- const XmlElement * status = stanza->FirstNamed(QN_STATUS);
- if (status != NULL) {
- s.set_status(status->BodyText());
-
- // Truncate status messages longer than 300 bytes
- if (s.status().length() > 300) {
- size_t len = 300;
-
- // Be careful not to split legal utf-8 chars in half
- while (!IsUtf8FirstByte(s.status()[len]) && len > 0) {
- len -= 1;
- }
- std::string truncated(s.status(), 0, len);
- s.set_status(truncated);
- }
- }
-
- const XmlElement * priority = stanza->FirstNamed(QN_PRIORITY);
- if (priority != NULL) {
- int pri;
- if (talk_base::FromString(priority->BodyText(), &pri)) {
- s.set_priority(pri);
- }
- }
-
- const XmlElement * show = stanza->FirstNamed(QN_SHOW);
- if (show == NULL || show->FirstChild() == NULL) {
- s.set_show(Status::SHOW_ONLINE);
- }
- else {
- if (show->BodyText() == "away") {
- s.set_show(Status::SHOW_AWAY);
- }
- else if (show->BodyText() == "xa") {
- s.set_show(Status::SHOW_XA);
- }
- else if (show->BodyText() == "dnd") {
- s.set_show(Status::SHOW_DND);
- }
- else if (show->BodyText() == "chat") {
- s.set_show(Status::SHOW_CHAT);
- }
- else {
- s.set_show(Status::SHOW_ONLINE);
- }
- }
-
- const XmlElement * caps = stanza->FirstNamed(QN_CAPS_C);
- if (caps != NULL) {
- std::string node = caps->Attr(QN_NODE);
- std::string ver = caps->Attr(QN_VER);
- std::string exts = caps->Attr(QN_EXT);
-
- s.set_know_capabilities(true);
-
- if (node == GOOGLE_CLIENT_NODE) {
- s.set_is_google_client(true);
- s.set_version(ver);
- if (ListContainsToken(exts, "voice-v1")) {
- s.set_phone_capability(true);
- }
- if (ListContainsToken(exts, "share-v1")) {
- s.set_fileshare_capability(true);
- }
- }
- }
-
- const XmlElement* delay = stanza->FirstNamed(kQnDelayX);
- if (delay != NULL) {
- // Ideally we would parse this according to the Psuedo ISO-8601 rules
- // that are laid out in JEP-0082:
- // http://www.jabber.org/jeps/jep-0082.html
- std::string stamp = delay->Attr(kQnStamp);
- s.set_sent_time(stamp);
- }
-
- SignalStatusUpdate(s);
- }
-
- return STATE_START;
-}
-
-
-}
-
-
diff --git a/talk/examples/login/presencepushtask.h b/talk/examples/login/presencepushtask.h
deleted file mode 100755
index 23cd1b8..0000000
--- a/talk/examples/login/presencepushtask.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Jingle call example
- * Copyright 2004--2005, Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _PRESENCEPUSHTASK_H_
-#define _PRESENCEPUSHTASK_H_
-
-#include "talk/xmpp/xmppengine.h"
-#include "talk/xmpp/xmpptask.h"
-#include "talk/base/sigslot.h"
-#include "talk/examples/login/status.h"
-
-namespace buzz {
-
-class PresencePushTask : public XmppTask {
-
-public:
- PresencePushTask(Task * parent) : XmppTask(parent, XmppEngine::HL_TYPE) {}
- virtual int ProcessStart();
- sigslot::signal1<const Status &>SignalStatusUpdate;
-
-protected:
- virtual bool HandleStanza(const XmlElement * stanza);
-};
-
-
-}
-
-#endif
diff --git a/talk/examples/login/xmppauth.cc b/talk/examples/login/xmppauth.cc
old mode 100755
new mode 100644
index 8bbadb0..3551b97
--- a/talk/examples/login/xmppauth.cc
+++ b/talk/examples/login/xmppauth.cc
@@ -25,12 +25,14 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <algorithm>
#include "talk/examples/login/xmppauth.h"
+
+#include <algorithm>
+
#include "talk/xmpp/saslcookiemechanism.h"
#include "talk/xmpp/saslplainmechanism.h"
-XmppAuth::XmppAuth() : done_(false), error_(false) {
+XmppAuth::XmppAuth() : done_(false) {
}
XmppAuth::~XmppAuth() {
@@ -43,7 +45,6 @@
jid_ = jid;
passwd_ = pass;
auth_cookie_ = auth_cookie;
- error_ = auth_cookie.empty();
done_ = true;
SignalAuthDone();
@@ -56,12 +57,12 @@
// a token is the weakest auth - 15s, service-limited, so prefer it.
it = std::find(mechanisms.begin(), mechanisms.end(), "X-GOOGLE-TOKEN");
- if (it != mechanisms.end())
+ if (it != mechanisms.end() && !auth_cookie_.empty())
return "X-GOOGLE-TOKEN";
// a cookie is the next weakest - 14 days
it = std::find(mechanisms.begin(), mechanisms.end(), "X-GOOGLE-COOKIE");
- if (it != mechanisms.end())
+ if (it != mechanisms.end() && !auth_cookie_.empty())
return "X-GOOGLE-COOKIE";
it = std::find(mechanisms.begin(), mechanisms.end(), "PLAIN");
diff --git a/talk/examples/login/xmppauth.h b/talk/examples/login/xmppauth.h
old mode 100755
new mode 100644
index fe379fe..18672b8
--- a/talk/examples/login/xmppauth.h
+++ b/talk/examples/login/xmppauth.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -40,20 +40,20 @@
public:
XmppAuth();
virtual ~XmppAuth();
-
+
virtual void StartPreXmppAuth(const buzz::Jid & jid,
const talk_base::SocketAddress & server,
const talk_base::CryptString & pass,
const std::string & auth_cookie);
-
- virtual bool IsAuthDone() { return done_; }
- virtual bool IsAuthorized() { return !error_; }
- virtual bool HadError() { return error_; }
- virtual int GetError() { return 0; }
- virtual buzz::CaptchaChallenge GetCaptchaChallenge() {
+
+ virtual bool IsAuthDone() const { return done_; }
+ virtual bool IsAuthorized() const { return true; }
+ virtual bool HadError() const { return false; }
+ virtual int GetError() const { return 0; }
+ virtual buzz::CaptchaChallenge GetCaptchaChallenge() const {
return buzz::CaptchaChallenge();
}
- virtual std::string GetAuthCookie() { return auth_cookie_; }
+ virtual std::string GetAuthCookie() const { return auth_cookie_; }
virtual std::string ChooseBestSaslMechanism(
const std::vector<std::string> & mechanisms,
@@ -66,7 +66,7 @@
buzz::Jid jid_;
talk_base::CryptString passwd_;
std::string auth_cookie_;
- bool done_, error_;
+ bool done_;
};
#endif
diff --git a/talk/examples/login/xmpppump.cc b/talk/examples/login/xmpppump.cc
old mode 100755
new mode 100644
diff --git a/talk/examples/login/xmpppump.h b/talk/examples/login/xmpppump.h
old mode 100755
new mode 100644
index e982184..4e79748
--- a/talk/examples/login/xmpppump.h
+++ b/talk/examples/login/xmpppump.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -40,6 +40,7 @@
class XmppPumpNotify {
public:
+ virtual ~XmppPumpNotify() {}
virtual void OnStateChange(buzz::XmppEngine::State state) = 0;
};
diff --git a/talk/examples/login/xmppsocket.cc b/talk/examples/login/xmppsocket.cc
old mode 100755
new mode 100644
index 3c96413..89e8662
--- a/talk/examples/login/xmppsocket.cc
+++ b/talk/examples/login/xmppsocket.cc
@@ -38,30 +38,54 @@
#endif
#include "xmppsocket.h"
+#ifdef USE_SSLSTREAM
+#include "talk/base/socketstream.h"
+#ifdef FEATURE_ENABLE_SSL
+#include "talk/base/sslstreamadapter.h"
+#endif // FEATURE_ENABLE_SSL
+#endif // USE_SSLSTREAM
+
XmppSocket::XmppSocket(bool tls) : tls_(tls) {
talk_base::Thread* pth = talk_base::Thread::Current();
talk_base::AsyncSocket* socket =
pth->socketserver()->CreateAsyncSocket(SOCK_STREAM);
+#ifndef USE_SSLSTREAM
#ifdef FEATURE_ENABLE_SSL
if (tls_) {
socket = talk_base::SSLAdapter::Create(socket);
}
-#endif
+#endif // FEATURE_ENABLE_SSL
cricket_socket_ = socket;
cricket_socket_->SignalReadEvent.connect(this, &XmppSocket::OnReadEvent);
cricket_socket_->SignalWriteEvent.connect(this, &XmppSocket::OnWriteEvent);
cricket_socket_->SignalConnectEvent.connect(this,
&XmppSocket::OnConnectEvent);
+ cricket_socket_->SignalCloseEvent.connect(this, &XmppSocket::OnCloseEvent);
+#else // USE_SSLSTREAM
+ cricket_socket_ = socket;
+ stream_ = new talk_base::SocketStream(cricket_socket_);
+#ifdef FEATURE_ENABLE_SSL
+ if (tls_)
+ stream_ = talk_base::SSLStreamAdapter::Create(stream_);
+#endif // FEATURE_ENABLE_SSL
+ stream_->SignalEvent.connect(this, &XmppSocket::OnEvent);
+#endif // USE_SSLSTREAM
+
state_ = buzz::AsyncSocket::STATE_CLOSED;
}
XmppSocket::~XmppSocket() {
Close();
+#ifndef USE_SSLSTREAM
delete cricket_socket_;
+#else // USE_SSLSTREAM
+ delete stream_;
+#endif // USE_SSLSTREAM
}
+#ifndef USE_SSLSTREAM
void XmppSocket::OnReadEvent(talk_base::AsyncSocket * socket) {
- SignalRead();
+ SignalRead();
}
void XmppSocket::OnWriteEvent(talk_base::AsyncSocket * socket) {
@@ -91,6 +115,53 @@
SignalConnected();
}
+void XmppSocket::OnCloseEvent(talk_base::AsyncSocket * socket, int error) {
+ SignalCloseEvent(error);
+}
+
+#else // USE_SSLSTREAM
+
+void XmppSocket::OnEvent(talk_base::StreamInterface* stream,
+ int events, int err) {
+ if ((events & talk_base::SE_OPEN)) {
+#if defined(FEATURE_ENABLE_SSL)
+ if (state_ == buzz::AsyncSocket::STATE_TLS_CONNECTING) {
+ state_ = buzz::AsyncSocket::STATE_TLS_OPEN;
+ SignalSSLConnected();
+ events |= talk_base::SE_WRITE;
+ } else
+#endif
+ {
+ state_ = buzz::AsyncSocket::STATE_OPEN;
+ SignalConnected();
+ }
+ }
+ if ((events & talk_base::SE_READ))
+ SignalRead();
+ if ((events & talk_base::SE_WRITE)) {
+ // Write bytes if there are any
+ while (buffer_.Length() != 0) {
+ talk_base::StreamResult result;
+ size_t written;
+ int error;
+ result = stream_->Write(buffer_.Data(), buffer_.Length(),
+ &written, &error);
+ if (result == talk_base::SR_ERROR) {
+ LOG(LS_ERROR) << "Send error: " << error;
+ return;
+ }
+ if (result == talk_base::SR_BLOCK)
+ return;
+ ASSERT(result == talk_base::SR_SUCCESS);
+ ASSERT(written > 0);
+ buffer_.Shift(written);
+ }
+ }
+ if ((events & talk_base::SE_CLOSE))
+ SignalCloseEvent(err);
+}
+#endif // USE_SSLSTREAM
+
buzz::AsyncSocket::State XmppSocket::state() {
return state_;
}
@@ -111,40 +182,65 @@
}
bool XmppSocket::Read(char * data, size_t len, size_t* len_read) {
+#ifndef USE_SSLSTREAM
int read = cricket_socket_->Recv(data, len);
if (read > 0) {
*len_read = (size_t)read;
return true;
}
+#else // USE_SSLSTREAM
+ talk_base::StreamResult result = stream_->Read(data, len, len_read, NULL);
+ if (result == talk_base::SR_SUCCESS)
+ return true;
+#endif // USE_SSLSTREAM
return false;
}
bool XmppSocket::Write(const char * data, size_t len) {
buffer_.WriteBytes(data, len);
+#ifndef USE_SSLSTREAM
OnWriteEvent(cricket_socket_);
+#else // USE_SSLSTREAM
+ OnEvent(stream_, talk_base::SE_WRITE, 0);
+#endif // USE_SSLSTREAM
return true;
}
bool XmppSocket::Close() {
if (state_ != buzz::AsyncSocket::STATE_OPEN)
return false;
+#ifndef USE_SSLSTREAM
if (cricket_socket_->Close() == 0) {
state_ = buzz::AsyncSocket::STATE_CLOSED;
SignalClosed();
return true;
}
return false;
+#else // USE_SSLSTREAM
+ state_ = buzz::AsyncSocket::STATE_CLOSED;
+ stream_->Close();
+ SignalClosed();
+ return true;
+#endif // USE_SSLSTREAM
}
bool XmppSocket::StartTls(const std::string & domainname) {
#if defined(FEATURE_ENABLE_SSL)
if (!tls_)
return false;
+#ifndef USE_SSLSTREAM
talk_base::SSLAdapter* ssl_adapter =
static_cast<talk_base::SSLAdapter *>(cricket_socket_);
ssl_adapter->set_ignore_bad_cert(true);
if (ssl_adapter->StartSSL(domainname.c_str(), false) != 0)
return false;
+#else // USE_SSLSTREAM
+ talk_base::SSLStreamAdapter* ssl_stream =
+ static_cast<talk_base::SSLStreamAdapter *>(stream_);
+ ssl_stream->set_ignore_bad_cert(true);
+ if (ssl_stream->StartSSLWithServer(domainname.c_str()) != 0)
+ return false;
+#endif // USE_SSLSTREAM
state_ = buzz::AsyncSocket::STATE_TLS_CONNECTING;
return true;
#else // !defined(FEATURE_ENABLE_SSL)
diff --git a/talk/examples/login/xmppsocket.h b/talk/examples/login/xmppsocket.h
old mode 100755
new mode 100644
index 8ed7e3c..bce8ee3
--- a/talk/examples/login/xmppsocket.h
+++ b/talk/examples/login/xmppsocket.h
@@ -33,6 +33,13 @@
#include "talk/base/sigslot.h"
#include "talk/xmpp/asyncsocket.h"
+// The below define selects the SSLStreamAdapter implementation for
+// SSL, as opposed to the SSLAdapter socket adapter.
+// #define USE_SSLSTREAM
+
+namespace talk_base {
+ class StreamInterface;
+};
extern talk_base::AsyncSocket* cricket_socket_;
class XmppSocket : public buzz::AsyncSocket, public sigslot::has_slots<> {
@@ -50,12 +57,22 @@
virtual bool Close();
virtual bool StartTls(const std::string & domainname);
+ sigslot::signal1<int> SignalCloseEvent;
+
private:
+#ifndef USE_SSLSTREAM
void OnReadEvent(talk_base::AsyncSocket * socket);
void OnWriteEvent(talk_base::AsyncSocket * socket);
void OnConnectEvent(talk_base::AsyncSocket * socket);
+ void OnCloseEvent(talk_base::AsyncSocket * socket, int error);
+#else // USE_SSLSTREAM
+ void OnEvent(talk_base::StreamInterface* stream, int events, int err);
+#endif // USE_SSLSTREAM
talk_base::AsyncSocket * cricket_socket_;
+#ifdef USE_SSLSTREAM
+ talk_base::StreamInterface *stream_;
+#endif // USE_SSLSTREAM
buzz::AsyncSocket::State state_;
talk_base::ByteBuffer buffer_;
bool tls_;
diff --git a/talk/examples/login/xmppthread.cc b/talk/examples/login/xmppthread.cc
old mode 100755
new mode 100644
index bb5d8cd..c030391
--- a/talk/examples/login/xmppthread.cc
+++ b/talk/examples/login/xmppthread.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -68,13 +68,13 @@
void XmppThread::OnMessage(talk_base::Message* pmsg) {
if (pmsg->message_id == MSG_LOGIN) {
- assert(pmsg->pdata);
+ ASSERT(pmsg->pdata != NULL);
LoginData* data = reinterpret_cast<LoginData*>(pmsg->pdata);
pump_->DoLogin(data->xcs, new XmppSocket(false), new XmppAuth());
delete data;
} else if (pmsg->message_id == MSG_DISCONNECT) {
pump_->DoDisconnect();
} else {
- assert(false);
+ ASSERT(false);
}
}
diff --git a/talk/examples/login/xmppthread.h b/talk/examples/login/xmppthread.h
old mode 100755
new mode 100644
diff --git a/talk/examples/pcp/Makefile.am b/talk/examples/pcp/Makefile.am
deleted file mode 100755
index de779cd..0000000
--- a/talk/examples/pcp/Makefile.am
+++ /dev/null
@@ -1,15 +0,0 @@
-bin_PROGRAMS = pcp
-pcp_CXXFLAGS = $(AM_CXXFLAGS)
-pcp_SOURCES = pcp_main.cc
-pcp_LDADD = $(top_srcdir)/talk/examples/login/libcricketexampleslogin.la \
- $(top_srcdir)/talk/session/fileshare/libcricketsessionfileshare.la \
- $(top_srcdir)/talk/session/tunnel/libcricketsessiontunnel.la \
- $(top_srcdir)/talk/p2p/client/libcricketp2pclient.la \
- $(top_srcdir)/talk/p2p/base/libcricketp2pbase.la \
- $(top_srcdir)/talk/xmpp/libcricketxmpp.la \
- $(top_srcdir)/talk/xmllite/libcricketxmllite.la \
- $(top_srcdir)/talk/base/libcricketbase.la \
- $(EXPAT_LIBS) -lpthread -lssl -lcrypto
-
-AM_CPPFLAGS = -DPOSIX
-EXTRA_DIST = pcp.vcproj
diff --git a/talk/examples/pcp/pcp.vcproj b/talk/examples/pcp/pcp.vcproj
deleted file mode 100755
index 23ba860..0000000
--- a/talk/examples/pcp/pcp.vcproj
+++ /dev/null
@@ -1,233 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="pcp"
- ProjectGUID="{EF5C9C17-874A-44C3-93CB-1165F03DBCD3}"
- RootNamespace="pcp"
- Keyword="Win32Proj"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="../../.."
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_WINDOWS;UNICODE;_UNICODE;WINVER=0x0500;_WIN32_WINNT=0x500;PRODUCTION_BUILD;PRODUCTION;XML_STATIC;FEATURE_ENABLE_SSL;FEATURE_ENABLE_CHAT_ARCHIVING;FEATURE_ENABLE_VOICEMAIL"
- MinimalRebuild="true"
- ExceptionHandling="1"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- TreatWChar_tAsBuiltInType="false"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="comsupp.lib secur32.lib ws2_32.lib libexpatMT.lib Iphlpapi.lib crypt32.lib"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="1"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="../../.."
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_WINDOWS;UNICODE;_UNICODE;WINVER=0x0500;_WIN32_WINNT=0x500;PRODUCTION_BUILD;PRODUCTION;XML_STATIC;FEATURE_ENABLE_SSL;FEATURE_ENABLE_CHAT_ARCHIVING"
- ExceptionHandling="1"
- RuntimeLibrary="0"
- TreatWChar_tAsBuiltInType="false"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="comsupp.lib secur32.lib ws2_32.lib libexpatMT.lib Iphlpapi.lib"
- LinkIncremental="1"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\login\jingleinfotask.cc"
- >
- </File>
- <File
- RelativePath="pcp_main.cc"
- >
- </File>
- <File
- RelativePath="..\login\presenceouttask.cc"
- >
- </File>
- <File
- RelativePath="..\login\presencepushtask.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmppauth.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmpppump.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmppsocket.cc"
- >
- </File>
- <File
- RelativePath="..\login\xmppthread.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/talk/examples/pcp/pcp_main.cc b/talk/examples/pcp/pcp_main.cc
deleted file mode 100755
index 4d5646d..0000000
--- a/talk/examples/pcp/pcp_main.cc
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Jingle call example
- * Copyright 2004--2005, Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Tempe Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <iomanip>
-#include <time.h>
-
-#ifndef WIN32
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <iomanip>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#else
-#include <direct.h>
-//typedef _getcwd getcwd;
-#include "talk/base/win32.h"
-#endif
-
-#include "talk/base/fileutils.h"
-#include "talk/base/pathutils.h"
-#include "talk/base/helpers.h"
-#include "talk/base/httpclient.h"
-#include "talk/base/logging.h"
-#include "talk/base/physicalsocketserver.h"
-#include "talk/base/ssladapter.h"
-#include "talk/xmpp/xmppclientsettings.h"
-#include "talk/examples/login/xmppthread.h"
-#include "talk/examples/login/xmppauth.h"
-#include "talk/p2p/client/httpportallocator.h"
-#include "talk/p2p/client/sessionmanagertask.h"
-#include "talk/session/fileshare/fileshare.h"
-#include "talk/examples/login/presencepushtask.h"
-#include "talk/examples/login/presenceouttask.h"
-#include "talk/examples/login/jingleinfotask.h"
-
-#if defined(_MSC_VER) && (_MSC_VER < 1400)
-// The following are necessary to properly link when compiling STL without
-// /EHsc, otherwise known as C++ exceptions.
-void __cdecl std::_Throw(const std::exception &) {}
-std::_Prhand std::_Raise_handler = 0;
-#endif
-
-void SetConsoleEcho(bool on) {
-#ifdef WIN32
- HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
- if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
- return;
-
- DWORD mode;
- if (!GetConsoleMode(hIn, &mode))
- return;
-
- if (on) {
- mode = mode | ENABLE_ECHO_INPUT;
- } else {
- mode = mode & ~ENABLE_ECHO_INPUT;
- }
-
- SetConsoleMode(hIn, mode);
-#else
- if (on)
- system("stty echo");
- else
- system("stty -echo");
-#endif
-}
-class DebugLog : public sigslot::has_slots<> {
-public:
- DebugLog() :
- debug_input_buf_(NULL), debug_input_len_(0), debug_input_alloc_(0),
- debug_output_buf_(NULL), debug_output_len_(0), debug_output_alloc_(0),
- censor_password_(false)
- {}
- char * debug_input_buf_;
- int debug_input_len_;
- int debug_input_alloc_;
- char * debug_output_buf_;
- int debug_output_len_;
- int debug_output_alloc_;
- bool censor_password_;
-
- void Input(const char * data, int len) {
- if (debug_input_len_ + len > debug_input_alloc_) {
- char * old_buf = debug_input_buf_;
- debug_input_alloc_ = 4096;
- while (debug_input_alloc_ < debug_input_len_ + len) {
- debug_input_alloc_ *= 2;
- }
- debug_input_buf_ = new char[debug_input_alloc_];
- memcpy(debug_input_buf_, old_buf, debug_input_len_);
- delete[] old_buf;
- }
- memcpy(debug_input_buf_ + debug_input_len_, data, len);
- debug_input_len_ += len;
- DebugPrint(debug_input_buf_, &debug_input_len_, false);
- }
-
- void Output(const char * data, int len) {
- if (debug_output_len_ + len > debug_output_alloc_) {
- char * old_buf = debug_output_buf_;
- debug_output_alloc_ = 4096;
- while (debug_output_alloc_ < debug_output_len_ + len) {
- debug_output_alloc_ *= 2;
- }
- debug_output_buf_ = new char[debug_output_alloc_];
- memcpy(debug_output_buf_, old_buf, debug_output_len_);
- delete[] old_buf;
- }
- memcpy(debug_output_buf_ + debug_output_len_, data, len);
- debug_output_len_ += len;
- DebugPrint(debug_output_buf_, &debug_output_len_, true);
- }
-
- static bool
- IsAuthTag(const char * str, size_t len) {
- if (str[0] == '<' && str[1] == 'a' &&
- str[2] == 'u' &&
- str[3] == 't' &&
- str[4] == 'h' &&
- str[5] <= ' ') {
- std::string tag(str, len);
-
- if (tag.find("mechanism") != std::string::npos)
- return true;
-
- }
- return false;
- }
-
- void
- DebugPrint(char * buf, int * plen, bool output) {
- int len = *plen;
- if (len > 0) {
- time_t tim = time(NULL);
- struct tm * now = localtime(&tim);
- char *time_string = asctime(now);
- if (time_string) {
- size_t time_len = strlen(time_string);
- if (time_len > 0) {
- time_string[time_len-1] = 0; // trim off terminating \n
- }
- }
- LOG(INFO) << (output ? "SEND >>>>>>>>>>>>>>>>>>>>>>>>>" : "RECV <<<<<<<<<<<<<<<<<<<<<<<<<")
- << " : " << time_string;
-
- bool indent;
- int start = 0, nest = 3;
- for (int i = 0; i < len; i += 1) {
- if (buf[i] == '>') {
- if ((i > 0) && (buf[i-1] == '/')) {
- indent = false;
- } else if ((start + 1 < len) && (buf[start + 1] == '/')) {
- indent = false;
- nest -= 2;
- } else {
- indent = true;
- }
-
- // Output a tag
- LOG(INFO) << std::setw(nest) << " " << std::string(buf + start, i + 1 - start);
-
- if (indent)
- nest += 2;
-
- // Note if it's a PLAIN auth tag
- if (IsAuthTag(buf + start, i + 1 - start)) {
- censor_password_ = true;
- }
-
- // incr
- start = i + 1;
- }
-
- if (buf[i] == '<' && start < i) {
- if (censor_password_) {
- LOG(INFO) << std::setw(nest) << " " << "## TEXT REMOVED ##";
- censor_password_ = false;
- }
- else {
- LOG(INFO) << std::setw(nest) << " " << std::string(buf + start, i - start);
- }
- start = i;
- }
- }
- len = len - start;
- memcpy(buf, buf + start, len);
- *plen = len;
- }
- }
-
-};
-
-static DebugLog debug_log_;
-
-
-class FileShareClient : public sigslot::has_slots<>, public talk_base::MessageHandler {
- public:
- FileShareClient(buzz::XmppClient *xmppclient, const buzz::Jid &send_to, const cricket::FileShareManifest *manifest, std::string root_dir) :
- xmpp_client_(xmppclient),
- root_dir_(root_dir),
- send_to_jid_(send_to),
- waiting_for_file_(send_to == buzz::JID_EMPTY),
- manifest_(manifest) {}
-
- void OnStateChange(buzz::XmppEngine::State state) {
- switch (state) {
- case buzz::XmppEngine::STATE_START:
- std::cout << "Connecting..." << std::endl;
- break;
- case buzz::XmppEngine::STATE_OPENING:
- std::cout << "Logging in. " << std::endl;
- break;
- case buzz::XmppEngine::STATE_OPEN:
- std::cout << "Logged in as " << xmpp_client_->jid().Str() << std::endl;
- if (!waiting_for_file_)
- std::cout << "Waiting for " << send_to_jid_.Str() << std::endl;
- OnSignon();
- break;
- case buzz::XmppEngine::STATE_CLOSED:
- std::cout << "Logged out." << std::endl;
- break;
- }
- }
-
- private:
-
- enum {
- MSG_STOP,
- };
-
- void OnJingleInfo(const std::string & relay_token,
- const std::vector<std::string> &relay_addresses,
- const std::vector<talk_base::SocketAddress> &stun_addresses) {
- port_allocator_->SetStunHosts(stun_addresses);
- port_allocator_->SetRelayHosts(relay_addresses);
- port_allocator_->SetRelayToken(relay_token);
- }
-
-
- void OnStatusUpdate(const buzz::Status &status) {
- if (status.available() && status.fileshare_capability()) {
-
- // A contact's status has changed. If the person we're looking for is online and able to receive
- // files, send it.
- if (send_to_jid_.BareEquals(status.jid())) {
- std::cout << send_to_jid_.Str() << " has signed on." << std::endl;
- cricket::FileShareSession* share = file_share_session_client_->CreateFileShareSession();
- share->Share(status.jid(), const_cast<cricket::FileShareManifest*>(manifest_));
- send_to_jid_ = buzz::Jid("");
- }
-
- }
- }
-
- void OnMessage(talk_base::Message *m) {
- ASSERT(m->message_id == MSG_STOP);
- talk_base::Thread *thread = talk_base::ThreadManager::CurrentThread();
- delete session_;
- thread->Stop();
- }
-
- std::string filesize_to_string(unsigned int size) {
- double size_display;
- std::string format;
- std::stringstream ret;
-
- // the comparisons to 1000 * (2^(n10)) are intentional
- // it's so you don't see something like "1023 bytes",
- // instead you'll see ".9 KB"
-
- if (size < 1000) {
- format = "Bytes";
- size_display = size;
- } else if (size < 1000 * 1024) {
- format = "KiB";
- size_display = (double)size / 1024.0;
- } else if (size < 1000 * 1024 * 1024) {
- format = "MiB";
- size_display = (double)size / (1024.0 * 1024.0);
- } else {
- format = "GiB";
- size_display = (double)size / (1024.0 * 1024.0 * 1024.0);
- }
-
- ret << std::setprecision(1) << std::setiosflags(std::ios::fixed) << size_display << " " << format;
- return ret.str();
- }
-
- void OnSessionState(cricket::FileShareState state) {
- talk_base::Thread *thread = talk_base::ThreadManager::CurrentThread();
- std::stringstream manifest_description;
-
- switch(state) {
- case cricket::FS_OFFER:
-
- // The offer has been made; print a summary of it and, if it's an incoming transfer, accept it
-
- if (manifest_->size() == 1)
- manifest_description << session_->manifest()->item(0).name;
- else if (session_->manifest()->GetFileCount() && session_->manifest()->GetFolderCount())
- manifest_description << session_->manifest()->GetFileCount() << " files and " <<
- session_->manifest()->GetFolderCount() << " directories";
- else if (session_->manifest()->GetFileCount() > 0)
- manifest_description << session_->manifest()->GetFileCount() << " files";
- else
- manifest_description << session_->manifest()->GetFolderCount() << " directories";
-
- size_t filesize;
- if (!session_->GetTotalSize(filesize)) {
- manifest_description << " (Unknown size)";
- } else {
- manifest_description << " (" << filesize_to_string(filesize) << ")";
- }
- if (session_->is_sender()) {
- std::cout << "Offering " << manifest_description.str() << " to " << send_to_jid_.Str() << std::endl;
- } else if (waiting_for_file_) {
- std::cout << "Receiving " << manifest_description.str() << " from " << session_->jid().BareJid().Str() << std::endl;
- session_->Accept();
- waiting_for_file_ = false;
-
- // If this were a graphical client, we might want to go through the manifest, look for images,
- // and request previews. There are two ways to go about this:
- //
- // If we want to display the preview in a web browser (like the embedded IE control in Google Talk), we could call
- // GetImagePreviewUrl on the session, with the image's index in the manifest, the size, and a pointer to the URL.
- // This will cause the session to listen for HTTP requests on localhost, and set url to a localhost URL that any
- // web browser can use to get the image preview:
- //
- // std::string url;
- // session_->GetImagePreviewUrl(0, 100, 100, &url);
- // url = std::string("firefox \"") + url + "\"";
- // system(url.c_str());
- //
- // Alternately, you could use libjingle's own HTTP code with the FileShareSession's SocketPool interface to
- // write the image preview directly into a StreamInterface:
- //
- // talk_base::HttpClient *client = new talk_base::HttpClient("pcp", session_);
- // std::string path;
- // session_->GetItemNetworkPath(0,1,&path);
- //
- // client->request().verb = talk_base::HV_GET;
- // client->request().path = path + "?width=100&height=100";
- // talk_base::FileStream *file = new talk_base::FileStream;
- // file->Open("/home/username/foo.jpg", "wb");
- // client->response().document.reset(file);
- // client->start();
- }
- break;
- case cricket::FS_TRANSFER:
- std::cout << "File transfer started." << std::endl;
- break;
- case cricket::FS_COMPLETE:
- thread->Post(this, MSG_STOP);
- std::cout << std::endl << "File transfer completed." << std::endl;
- break;
- case cricket::FS_LOCAL_CANCEL:
- case cricket::FS_REMOTE_CANCEL:
- std::cout << std::endl << "File transfer cancelled." << std::endl;
- thread->Post(this, MSG_STOP);
- break;
- case cricket::FS_FAILURE:
- std::cout << std::endl << "File transfer failed." << std::endl;
- thread->Post(this, MSG_STOP);
- break;
- }
- }
-
- void OnUpdateProgress(cricket::FileShareSession *sess) {
- // Progress has occured on the transfer; update the UI
-
- size_t totalsize, progress;
- std::string itemname;
- unsigned int width = 79;
-
-#ifndef WIN32
- struct winsize ws;
- if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0))
- width = ws.ws_col;
-#endif
-
- if(sess->GetTotalSize(totalsize) && sess->GetProgress(progress) && sess->GetCurrentItemName(&itemname)) {
- float percent = (float)progress / totalsize;
- unsigned int progressbar_width = (width * 4) / 5;
-
- const char *filename = itemname.c_str();
- std::cout.put('\r');
- for (unsigned int l = 0; l < width; l++) {
- if (l < percent * progressbar_width)
- std::cout.put('#');
- else if (l > progressbar_width && l < progressbar_width + 1 + strlen(filename))
- std::cout.put(filename[l-(progressbar_width + 1)]);
- else
- std::cout.put(' ');
- }
- std::cout.flush();
- }
- }
-
- void OnResampleImage(std::string path, int width, int height, talk_base::HttpTransaction *trans) {
-
- // The other side has requested an image preview. This is an asynchronous request. We should resize
- // the image to the requested size,and send that to ResampleComplete(). For simplicity, here, we
- // send back the original sized image. Note that because we don't recognize images in our manifest
- // this will never be called in pcp
-
- // Even if you don't resize images, you should implement this method and connect to the
- // SignalResampleImage signal, just to return an error.
-
- talk_base::FileStream *s = new talk_base::FileStream();
- if (s->Open(path.c_str(), "rb"))
- session_->ResampleComplete(s, trans, true);
- else {
- delete s;
- session_->ResampleComplete(NULL, trans, false);
- }
- }
-
- void OnFileShareSessionCreate(cricket::FileShareSession *sess) {
- session_ = sess;
- sess->SignalState.connect(this, &FileShareClient::OnSessionState);
- sess->SignalNextFile.connect(this, &FileShareClient::OnUpdateProgress);
- sess->SignalUpdateProgress.connect(this, &FileShareClient::OnUpdateProgress);
- sess->SignalResampleImage.connect(this, &FileShareClient::OnResampleImage);
- sess->SetLocalFolder(root_dir_);
- }
-
- void OnSignon() {
- std::string client_unique = xmpp_client_->jid().Str();
- cricket::InitRandom(client_unique.c_str(), client_unique.size());
-
- buzz::PresencePushTask *presence_push_ = new buzz::PresencePushTask(xmpp_client_);
- presence_push_->SignalStatusUpdate.connect(this, &FileShareClient::OnStatusUpdate);
- presence_push_->Start();
-
- buzz::Status my_status;
- my_status.set_jid(xmpp_client_->jid());
- my_status.set_available(true);
- my_status.set_show(buzz::Status::SHOW_ONLINE);
- my_status.set_priority(0);
- my_status.set_know_capabilities(true);
- my_status.set_fileshare_capability(true);
- my_status.set_is_google_client(true);
- my_status.set_version("1.0.0.66");
-
- buzz::PresenceOutTask* presence_out_ =
- new buzz::PresenceOutTask(xmpp_client_);
- presence_out_->Send(my_status);
- presence_out_->Start();
-
- port_allocator_.reset(new cricket::HttpPortAllocator(&network_manager_, "pcp"));
-
- session_manager_.reset(new cricket::SessionManager(port_allocator_.get(), NULL));
-
- cricket::SessionManagerTask * session_manager_task = new cricket::SessionManagerTask(xmpp_client_, session_manager_.get());
- session_manager_task->EnableOutgoingMessages();
- session_manager_task->Start();
-
- buzz::JingleInfoTask *jingle_info_task = new buzz::JingleInfoTask(xmpp_client_);
- jingle_info_task->RefreshJingleInfoNow();
- jingle_info_task->SignalJingleInfo.connect(this, &FileShareClient::OnJingleInfo);
- jingle_info_task->Start();
-
- file_share_session_client_.reset(new cricket::FileShareSessionClient(session_manager_.get(), xmpp_client_->jid(), "pcp"));
- file_share_session_client_->SignalFileShareSessionCreate.connect(this, &FileShareClient::OnFileShareSessionCreate);
- session_manager_->AddClient(NS_GOOGLE_SHARE, file_share_session_client_.get());
- }
-
- talk_base::NetworkManager network_manager_;
- talk_base::scoped_ptr<cricket::HttpPortAllocator> port_allocator_;
- talk_base::scoped_ptr<cricket::SessionManager> session_manager_;
- talk_base::scoped_ptr<cricket::FileShareSessionClient> file_share_session_client_;
- buzz::XmppClient *xmpp_client_;
- buzz::Jid send_to_jid_;
- const cricket::FileShareManifest *manifest_;
- cricket::FileShareSession *session_;
- bool waiting_for_file_;
- std::string root_dir_;
-};
-
-static unsigned int get_dir_size(const char *directory) {
- unsigned int total = 0;
- talk_base::DirectoryIterator iter;
- talk_base::Pathname path;
- path.AppendFolder(directory);
- iter.Iterate(path.pathname());
- while (iter.Next()) {
- if (iter.Name() == "." || iter.Name() == "..")
- continue;
- if (iter.IsDirectory()) {
- path.AppendPathname(iter.Name());
- total += get_dir_size(path.pathname().c_str());
- }
- else
- total += iter.FileSize();
- }
- return total;
-}
-
-int main(int argc, char **argv) {
- talk_base::PhysicalSocketServer ss;
- int i;
- bool debug = false;
- bool send_mode = false;
- char cwd[256];
- getcwd(cwd, sizeof(cwd));
- for (i = 1; i < argc && *argv[i] == '-'; i++) {
- if (!strcmp(argv[i], "-d")) {
- debug = true;
- } else {
- std::cout << "USAGE: " << argv[0] << " [-d][-h] [FILE1 FILE2 ... FILE#] [JID]" << std::endl;
- std::cout << " To send files, specify a list of files to send, followed by the JID of the recipient" << std::endl;
- std::cout << " To receive files, specify no files or JID" << std::endl;
- std::cout << "COMMAND LINE ARGUMENTS" << std::endl;
- std::cout << " -h -- Prints this help message" << std::endl;
- std::cout << " -d -- Prints debug messages to stderr" << std::endl;
- exit(0);
- }
- }
-
- if (debug)
- talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
- else
- talk_base::LogMessage::LogToDebug(talk_base::LS_ERROR + 1);
-
-
- talk_base::InitializeSSL();
- XmppPump pump;
- buzz::Jid jid;
- buzz::XmppClientSettings xcs;
- talk_base::InsecureCryptStringImpl pass;
- std::string username;
-
- std::cout << "JID: ";
- std::cin >> username;
- jid = buzz::Jid(username);
- if (!jid.IsValid() || jid.node() == "") {
- printf("Invalid JID. JIDs should be in the form user@domain\n");
- return 1;
- }
- SetConsoleEcho(false);
- std::cout << "Password: ";
- std::cin >> pass.password();
- SetConsoleEcho(true);
- std::cout << std::endl;
-
- xcs.set_user(jid.node());
- xcs.set_resource("pcp");
- xcs.set_host(jid.domain());
- xcs.set_use_tls(true);
-
- xcs.set_pass(talk_base::CryptString(pass));
- xcs.set_server(talk_base::SocketAddress("talk.google.com", 5222));
-
- talk_base::Thread main_thread(&ss);
- talk_base::ThreadManager::SetCurrent(&main_thread);
-
- if (debug) {
- pump.client()->SignalLogInput.connect(&debug_log_, &DebugLog::Input);
- pump.client()->SignalLogOutput.connect(&debug_log_, &DebugLog::Output);
- }
-
- cricket::FileShareManifest *manifest = new cricket::FileShareManifest();
-
- for (;i < argc - 1;i++) {
- if (0) {
- printf("%s is not a valid file\n", argv[i]);
- continue;
- }
- send_mode = true;
-
- // Additionally, we should check for image files here, and call
- // AddImage on the manifest with their file size and image size.
- // The receiving client can then request previews of those images
- if (talk_base::Filesystem::IsFolder(std::string(argv[i]))) {
- manifest->AddFolder(argv[i], get_dir_size(argv[i]));
- } else {
- size_t size = 0;
- talk_base::Filesystem::GetFileSize(std::string(argv[i]), &size);
- manifest->AddFile(argv[i], size);
- }
- }
- buzz::Jid j;
- if (send_mode)
- j = buzz::Jid(argv[argc-1]);
- else
- j = buzz::JID_EMPTY;
-
- FileShareClient fs_client(pump.client(), j, manifest, cwd);
-
- pump.client()->SignalStateChange.connect(&fs_client, &FileShareClient::OnStateChange);
-
- pump.DoLogin(xcs, new XmppSocket(true), NULL);
- main_thread.Run();
- pump.DoDisconnect();
-
- return 0;
-}
diff --git a/talk/libjingle.scons b/talk/libjingle.scons
new file mode 100644
index 0000000..09a3bc1
--- /dev/null
+++ b/talk/libjingle.scons
@@ -0,0 +1,308 @@
+import talk
+Import("env")
+
+talk.Library(env, name = "expat",
+ cppdefines = [
+ "XML_STATIC",
+ ],
+ srcs = [
+ "third_party/expat-2.0.1/lib/xmlparse.c",
+ "third_party/expat-2.0.1/lib/xmlrole.c",
+ "third_party/expat-2.0.1/lib/xmltok.c",
+ ],
+ includedirs = [
+ "third_party/expat-2.0.1/",
+ ],
+ win_cppdefines = [
+ "COMPILED_FROM_DSP",
+ ],
+ posix_cppdefines = [
+ "HAVE_EXPAT_CONFIG_H",
+ ],
+)
+talk.Library(env, name = "libsrtp",
+ srcs = [
+ "third_party/srtp/crypto/cipher/aes.c",
+ "third_party/srtp/crypto/cipher/aes_cbc.c",
+ "third_party/srtp/crypto/cipher/aes_icm.c",
+ "third_party/srtp/crypto/cipher/cipher.c",
+ "third_party/srtp/crypto/cipher/null_cipher.c",
+ "third_party/srtp/crypto/hash/auth.c",
+ "third_party/srtp/crypto/hash/hmac.c",
+ "third_party/srtp/crypto/hash/null_auth.c",
+ "third_party/srtp/crypto/hash/sha1.c",
+ "third_party/srtp/crypto/replay/rdb.c",
+ "third_party/srtp/crypto/replay/rdbx.c",
+ "third_party/srtp/crypto/replay/ut_sim.c",
+ "third_party/srtp/crypto/math/datatypes.c",
+ "third_party/srtp/crypto/math/stat.c",
+ "third_party/srtp/crypto/kernel/alloc.c",
+ "third_party/srtp/crypto/kernel/crypto_kernel.c",
+ "third_party/srtp/crypto/kernel/err.c",
+ "third_party/srtp/crypto/kernel/key.c",
+ "third_party/srtp/crypto/rng/ctr_prng.c",
+ "third_party/srtp/crypto/rng/rand_source.c",
+ "third_party/srtp/srtp/ekt.c",
+ "third_party/srtp/srtp/srtp.c",
+ ],
+ includedirs = [
+ "third_party/srtp/include",
+ "third_party/srtp/crypto/include",
+ ],
+ win_ccflags = [
+ "/wd4701",
+ "/wd4702",
+ ],
+)
+talk.Library(env, name = "libjingle",
+ lin_srcs = [
+ "base/linux.cc",
+ "session/phone/v4llookup.cc",
+ ],
+ mac_srcs = [
+ "base/macconversion.cc",
+ "base/macutils.cc",
+ "session/phone/devicemanager_mac.mm",
+ ],
+ posix_srcs = [
+ "base/unixfilesystem.cc",
+ "base/opensslidentity.cc",
+ "base/opensslstreamadapter.cc",
+ "base/sslidentity.cc",
+ "base/sslstreamadapter.cc",
+ ],
+ cppdefines = [
+ "FEATURE_ENABLE_VOICEMAIL",
+ "EXPAT_RELATIVE_PATH",
+ "SRTP_RELATIVE_PATH",
+ "XML_STATIC",
+ ],
+ srcs = [
+ "base/asyncfile.cc",
+ "base/asynchttprequest.cc",
+ "base/asyncpacketsocket.cc",
+ "base/asyncsocket.cc",
+ "base/asynctcpsocket.cc",
+ "base/asyncudpsocket.cc",
+ "base/autodetectproxy.cc",
+ "base/base64.cc",
+ "base/bytebuffer.cc",
+ "base/checks.cc",
+ "base/common.cc",
+ "base/diskcache.cc",
+ "base/event.cc",
+ "base/fileutils.cc",
+ "base/firewallsocketserver.cc",
+ "base/flags.cc",
+ "base/helpers.cc",
+ "base/host.cc",
+ "base/httpbase.cc",
+ "base/httpclient.cc",
+ "base/httpcommon.cc",
+ "base/httprequest.cc",
+ "base/logging.cc",
+ "base/md5c.c",
+ "base/messagehandler.cc",
+ "base/messagequeue.cc",
+ "base/nethelpers.cc",
+ "base/network.cc",
+ "base/openssladapter.cc",
+ "base/pathutils.cc",
+ "base/physicalsocketserver.cc",
+ "base/proxydetect.cc",
+ "base/proxyinfo.cc",
+ "base/signalthread.cc",
+ "base/socketadapters.cc",
+ "base/socketaddress.cc",
+ "base/socketaddresspair.cc",
+ "base/socketpool.cc",
+ "base/socketstream.cc",
+ "base/ssladapter.cc",
+ "base/sslsocketfactory.cc",
+ "base/stream.cc",
+ "base/stringdigest.cc",
+ "base/stringencode.cc",
+ "base/stringutils.cc",
+ "base/task.cc",
+ "base/taskparent.cc",
+ "base/taskrunner.cc",
+ "base/thread.cc",
+ "base/time.cc",
+ "base/urlencode.cc",
+ "p2p/base/constants.cc",
+ "p2p/base/p2ptransport.cc",
+ "p2p/base/p2ptransportchannel.cc",
+ "p2p/base/parsing.cc",
+ "p2p/base/port.cc",
+ "p2p/base/pseudotcp.cc",
+ "p2p/base/relayport.cc",
+ "p2p/base/relayserver.cc",
+ "p2p/base/rawtransport.cc",
+ "p2p/base/rawtransportchannel.cc",
+ "p2p/base/session.cc",
+ "p2p/base/sessiondescription.cc",
+ "p2p/base/sessionmanager.cc",
+ "p2p/base/sessionmessages.cc",
+ "p2p/base/stun.cc",
+ "p2p/base/stunport.cc",
+ "p2p/base/stunrequest.cc",
+ "p2p/base/stunserver.cc",
+ "p2p/base/tcpport.cc",
+ "p2p/base/transport.cc",
+ "p2p/base/transportchannel.cc",
+ "p2p/base/transportchannelproxy.cc",
+ "p2p/base/udpport.cc",
+ "p2p/client/basicportallocator.cc",
+ "p2p/client/httpportallocator.cc",
+ "p2p/client/socketmonitor.cc",
+ "session/tunnel/pseudotcpchannel.cc",
+ "session/tunnel/tunnelsessionclient.cc",
+ "session/tunnel/securetunnelsessionclient.cc",
+ "session/phone/audiomonitor.cc",
+ "session/phone/call.cc",
+ "session/phone/channel.cc",
+ "session/phone/channelmanager.cc",
+ "session/phone/codec.cc",
+ "session/phone/devicemanager.cc",
+ "session/phone/filemediaengine.cc",
+ "session/phone/mediaengine.cc",
+ "session/phone/mediamonitor.cc",
+ "session/phone/mediasessionclient.cc",
+ "session/phone/rtpdump.cc",
+ "session/phone/soundclip.cc",
+ "session/phone/srtpfilter.cc",
+ "xmllite/qname.cc",
+ "xmllite/xmlbuilder.cc",
+ "xmllite/xmlconstants.cc",
+ "xmllite/xmlelement.cc",
+ "xmllite/xmlnsstack.cc",
+ "xmllite/xmlparser.cc",
+ "xmllite/xmlprinter.cc",
+ "xmpp/constants.cc",
+ "xmpp/jid.cc",
+ "xmpp/ratelimitmanager.cc",
+ "xmpp/saslmechanism.cc",
+ "xmpp/xmppclient.cc",
+ "xmpp/xmppengineimpl.cc",
+ "xmpp/xmppengineimpl_iq.cc",
+ "xmpp/xmpplogintask.cc",
+ "xmpp/xmppstanzaparser.cc",
+ "xmpp/xmpptask.cc",
+ ],
+ includedirs = [
+ "third_party/expat-2.0.1/",
+ "third_party/srtp/include",
+ "third_party/srtp/crypto/include",
+ ],
+ win_srcs = [
+ "base/schanneladapter.cc",
+ "base/win32.cc",
+ "base/win32filesystem.cc",
+ "base/win32securityerrors.cc",
+ "base/win32socketserver.cc",
+ "base/win32socketinit.cc",
+ "base/win32window.cc",
+ "base/winfirewall.cc",
+ "base/winping.cc",
+ ],
+)
+talk.App(env, name = "login",
+ libs = [
+ "libjingle",
+ "expat",
+ "libxmpphelp",
+ ],
+ srcs = [
+ "examples/login/xmppthread.cc",
+ "examples/login/login_main.cc",
+ ],
+ mac_libs = [
+ "crypto",
+ "ssl",
+ ],
+ lin_libs = [
+ "libpthread",
+ ":libssl.so.0.9.8",
+ ],
+)
+talk.Library(env, name = "libxmpphelp",
+ libs = [
+ "libjingle",
+ ],
+ srcs = [
+ "examples/login/xmppauth.cc",
+ "examples/login/xmpppump.cc",
+ "examples/login/xmppsocket.cc",
+ ],
+)
+talk.App(env, name = "call",
+ mac_frameworks = [
+ "AudioToolbox",
+ "AudioUnit",
+ "Cocoa",
+ "CoreAudio",
+ "CoreFoundation",
+ "IOKit",
+ "QTKit",
+ "QuickTime",
+ ],
+ win_libs = [
+ "d3d9.lib",
+ "gdi32.lib",
+ "powrprof.lib",
+ "strmiids.lib",
+ "winmm.lib",
+ ],
+ mac_libs = [
+ "crypto",
+ "ssl",
+ ],
+ cppdefines = [
+ "FEATURE_ENABLE_VOICEMAIL",
+ ],
+ lin_libs = [
+ "libasound",
+ "libpthread",
+ ":libssl.so.0.9.8",
+ ],
+ srcs = [
+ "examples/call/call_main.cc",
+ "examples/call/callclient.cc",
+ "examples/call/console.cc",
+ "examples/call/discoitemsquerytask.cc",
+ "examples/call/friendinvitesendtask.cc",
+ "examples/call/mucinviterecvtask.cc",
+ "examples/call/mucinvitesendtask.cc",
+ "examples/call/presenceouttask.cc",
+ "examples/call/presencepushtask.cc",
+ "examples/call/voicemailjidrequester.cc",
+ ],
+ libs = [
+ "libjingle",
+ "expat",
+ "libsrtp",
+ "libxmpphelp",
+ ],
+)
+talk.App(env, name = "relayserver",
+ libs = [
+ "libjingle",
+ ],
+ srcs = [
+ "p2p/base/relayserver_main.cc",
+ ],
+ lin_libs = [
+ "libpthread",
+ ],
+)
+talk.App(env, name = "stunserver",
+ libs = [
+ "libjingle",
+ ],
+ srcs = [
+ "p2p/base/stunserver_main.cc",
+ ],
+ lin_libs = [
+ "libpthread",
+ ],
+)
diff --git a/talk/libjingle.sln b/talk/libjingle.sln
deleted file mode 100755
index fe0cf35..0000000
--- a/talk/libjingle.sln
+++ /dev/null
@@ -1,37 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual C++ Express 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjingle", "libjingle.vcproj", "{DC948D76-8503-490C-A07D-11044004FCE3}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcp", "examples\pcp\pcp.vcproj", "{EF5C9C17-874A-44C3-93CB-1165F03DBCD3}"
- ProjectSection(ProjectDependencies) = postProject
- {DC948D76-8503-490C-A07D-11044004FCE3} = {DC948D76-8503-490C-A07D-11044004FCE3}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "call", "examples\call\call.vcproj", "{A4132D45-BAE2-40E5-AC7C-C3C44FB24325}"
- ProjectSection(ProjectDependencies) = postProject
- {DC948D76-8503-490C-A07D-11044004FCE3} = {DC948D76-8503-490C-A07D-11044004FCE3}
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {DC948D76-8503-490C-A07D-11044004FCE3}.Debug|Win32.ActiveCfg = Debug|Win32
- {DC948D76-8503-490C-A07D-11044004FCE3}.Debug|Win32.Build.0 = Debug|Win32
- {DC948D76-8503-490C-A07D-11044004FCE3}.Release|Win32.ActiveCfg = Release|Win32
- {DC948D76-8503-490C-A07D-11044004FCE3}.Release|Win32.Build.0 = Release|Win32
- {EF5C9C17-874A-44C3-93CB-1165F03DBCD3}.Debug|Win32.ActiveCfg = Debug|Win32
- {EF5C9C17-874A-44C3-93CB-1165F03DBCD3}.Debug|Win32.Build.0 = Debug|Win32
- {EF5C9C17-874A-44C3-93CB-1165F03DBCD3}.Release|Win32.ActiveCfg = Release|Win32
- {EF5C9C17-874A-44C3-93CB-1165F03DBCD3}.Release|Win32.Build.0 = Release|Win32
- {A4132D45-BAE2-40E5-AC7C-C3C44FB24325}.Debug|Win32.ActiveCfg = Debug|Win32
- {A4132D45-BAE2-40E5-AC7C-C3C44FB24325}.Debug|Win32.Build.0 = Debug|Win32
- {A4132D45-BAE2-40E5-AC7C-C3C44FB24325}.Release|Win32.ActiveCfg = Release|Win32
- {A4132D45-BAE2-40E5-AC7C-C3C44FB24325}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/talk/libjingle.vcproj b/talk/libjingle.vcproj
deleted file mode 100755
index 2e3f7b2..0000000
--- a/talk/libjingle.vcproj
+++ /dev/null
@@ -1,1131 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="libjingle"
- ProjectGUID="{DC948D76-8503-490C-A07D-11044004FCE3}"
- RootNamespace="libjingle"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..;third_party/expat"
- PreprocessorDefinitions="_DEBUG;_WINDOWS;WIN32;UNICODE;_UNICODE;WINVER=0x0500;_WIN32_WINNT=0x500;_SCL_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;PRODUCTION_BUILD;PRODUCTION;XML_STATIC;FEATURE_ENABLE_SSL;FEATURE_ENABLE_CHAT_ARCHIVING;FEATURE_ENABLE_VOICEMAIL;NO_ATL;HAVE_GIPSLITE"
- ExceptionHandling="1"
- RuntimeLibrary="1"
- TreatWChar_tAsBuiltInType="false"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- IgnoreAllDefaultLibraries="true"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..;third_party/expat"
- PreprocessorDefinitions="_WINDOWS;WIN32;UNICODE;_UNICODE;WINVER=0x0500;_WIN32_WINNT=0x500;_SCL_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;PRODUCTION_BUILD;PRODUCTION;_SCL_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;XML_STATIC;FEATURE_ENABLE_SSL;FEATURE_ENABLE_CHAT_ARCHIVING"
- ExceptionHandling="1"
- RuntimeLibrary="0"
- TreatWChar_tAsBuiltInType="false"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <Filter
- Name="XMLLite"
- >
- <File
- RelativePath=".\xmllite\qname.cc"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlbuilder.cc"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlconstants.cc"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlelement.cc"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlnsstack.cc"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlparser.cc"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlprinter.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="XMPP"
- >
- <File
- RelativePath=".\xmpp\constants.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\jid.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\ratelimitmanager.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\saslmechanism.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppclient.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppengineimpl.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppengineimpl_iq.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmpplogintask.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppstanzaparser.cc"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmpptask.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="base"
- >
- <File
- RelativePath=".\base\asynchttprequest.cc"
- >
- </File>
- <File
- RelativePath=".\base\asyncpacketsocket.cc"
- >
- </File>
- <File
- RelativePath=".\base\asynctcpsocket.cc"
- >
- </File>
- <File
- RelativePath=".\base\asyncudpsocket.cc"
- >
- </File>
- <File
- RelativePath=".\base\autodetectproxy.cc"
- >
- </File>
- <File
- RelativePath=".\base\base64.cc"
- >
- </File>
- <File
- RelativePath=".\base\bytebuffer.cc"
- >
- </File>
- <File
- RelativePath=".\base\common.cc"
- >
- </File>
- <File
- RelativePath=".\base\diskcache.cc"
- >
- </File>
- <File
- RelativePath=".\base\diskcache_win32.cc"
- >
- </File>
- <File
- RelativePath=".\base\fileutils.cc"
- >
- </File>
- <File
- RelativePath=".\base\firewallsocketserver.cc"
- >
- </File>
- <File
- RelativePath=".\base\helpers.cc"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- ObjectFile="$(IntDir)\$(InputName)1.obj"
- XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- ObjectFile="$(IntDir)\$(InputName)1.obj"
- XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\base\host.cc"
- >
- </File>
- <File
- RelativePath=".\base\httpbase.cc"
- >
- </File>
- <File
- RelativePath=".\base\httpclient.cc"
- >
- </File>
- <File
- RelativePath=".\base\httpcommon.cc"
- >
- </File>
- <File
- RelativePath=".\base\httpserver.cc"
- >
- </File>
- <File
- RelativePath=".\base\logging.cc"
- >
- </File>
- <File
- RelativePath=".\base\md5c.c"
- >
- </File>
- <File
- RelativePath=".\base\messagequeue.cc"
- >
- </File>
- <File
- RelativePath=".\base\network.cc"
- >
- </File>
- <File
- RelativePath=".\base\pathutils.cc"
- >
- </File>
- <File
- RelativePath=".\base\physicalsocketserver.cc"
- >
- </File>
- <File
- RelativePath=".\base\proxydetect.cc"
- >
- </File>
- <File
- RelativePath=".\base\proxyinfo.cc"
- >
- </File>
- <File
- RelativePath=".\base\schanneladapter.cc"
- >
- </File>
- <File
- RelativePath=".\base\signalthread.cc"
- >
- </File>
- <File
- RelativePath=".\base\socketadapters.cc"
- >
- </File>
- <File
- RelativePath=".\base\socketaddress.cc"
- >
- </File>
- <File
- RelativePath=".\base\socketpool.cc"
- >
- </File>
- <File
- RelativePath=".\base\ssladapter.cc"
- >
- </File>
- <File
- RelativePath=".\base\stream.cc"
- >
- </File>
- <File
- RelativePath=".\base\streamutils.cc"
- >
- </File>
- <File
- RelativePath=".\base\stringdigest.cc"
- >
- </File>
- <File
- RelativePath=".\base\stringencode.cc"
- >
- </File>
- <File
- RelativePath=".\base\stringutils.cc"
- >
- </File>
- <File
- RelativePath=".\base\tarstream.cc"
- >
- </File>
- <File
- RelativePath=".\base\task.cc"
- >
- </File>
- <File
- RelativePath=".\base\taskrunner.cc"
- >
- </File>
- <File
- RelativePath=".\base\thread.cc"
- >
- </File>
- <File
- RelativePath=".\base\time.cc"
- >
- </File>
- <File
- RelativePath=".\base\win32filesystem.cc"
- >
- </File>
- <File
- RelativePath=".\base\win32socketserver.cc"
- >
- </File>
- <File
- RelativePath=".\base\winfirewall.cc"
- >
- </File>
- <File
- RelativePath=".\base\winping.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="p2p"
- >
- <Filter
- Name="base"
- >
- <File
- RelativePath=".\p2p\base\constants.cc"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- ObjectFile="$(IntDir)\$(InputName)1.obj"
- XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- ObjectFile="$(IntDir)\$(InputName)1.obj"
- XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath=".\p2p\base\p2ptransport.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\p2ptransportchannel.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\port.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\pseudotcp.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\rawtransport.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\rawtransportchannel.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\relayport.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\session.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\sessionmanager.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\stun.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\stunport.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\stunrequest.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\tcpport.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\transport.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\transportchannel.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\transportchannelproxy.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\base\udpport.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="client"
- >
- <File
- RelativePath=".\p2p\client\basicportallocator.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\client\httpportallocator.cc"
- >
- </File>
- <File
- RelativePath=".\p2p\client\socketmonitor.cc"
- >
- </File>
- </Filter>
- </Filter>
- <Filter
- Name="session"
- >
- <Filter
- Name="tunnel"
- >
- <File
- RelativePath=".\session\tunnel\tunnelsessionclient.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="phone"
- >
- <File
- RelativePath=".\session\phone\audiomonitor.cc"
- >
- </File>
- <File
- RelativePath=".\session\phone\call.cc"
- >
- </File>
- <File
- RelativePath=".\session\phone\channelmanager.cc"
- >
- </File>
- <File
- RelativePath=".\session\phone\gipslitemediaengine.cc"
- >
- </File>
- <File
- RelativePath=".\session\phone\phonesessionclient.cc"
- >
- </File>
- <File
- RelativePath=".\session\phone\voicechannel.cc"
- >
- </File>
- </Filter>
- <Filter
- Name="fileshare"
- >
- <File
- RelativePath=".\session\fileshare\fileshare.cc"
- >
- </File>
- <File
- RelativePath=".\session\fileshare\fileshare.h"
- >
- </File>
- </Filter>
- </Filter>
- <Filter
- Name="examples"
- >
- <Filter
- Name="login"
- >
- <File
- RelativePath=".\examples\login\xmppauth.cc"
- >
- </File>
- <File
- RelativePath=".\examples\login\xmpppump.cc"
- >
- </File>
- <File
- RelativePath=".\examples\login\xmppsocket.cc"
- >
- </File>
- <File
- RelativePath=".\examples\login\xmppthread.cc"
- >
- </File>
- </Filter>
- </Filter>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <Filter
- Name="XMLLite"
- >
- <File
- RelativePath=".\xmllite\qname.h"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlbuilder.h"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlconstants.h"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlelement.h"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlnsstack.h"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlparser.h"
- >
- </File>
- <File
- RelativePath=".\xmllite\xmlprinter.h"
- >
- </File>
- </Filter>
- <Filter
- Name="XMPP"
- >
- <File
- RelativePath=".\xmpp\asyncsocket.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\constants.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\jid.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\plainsaslhandler.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\prexmppauth.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\saslcookiemechanism.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\saslhandler.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\saslmechanism.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\saslplainmechanism.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppclient.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppclientsettings.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppengine.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppengineimpl.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmpplogintask.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmpppassword.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmppstanzaparser.h"
- >
- </File>
- <File
- RelativePath=".\xmpp\xmpptask.h"
- >
- </File>
- </Filter>
- <Filter
- Name="base"
- >
- <File
- RelativePath=".\base\asyncfile.h"
- >
- </File>
- <File
- RelativePath=".\base\asyncpacketsocket.h"
- >
- </File>
- <File
- RelativePath=".\base\asyncsocket.h"
- >
- </File>
- <File
- RelativePath=".\base\asynctcpsocket.h"
- >
- </File>
- <File
- RelativePath=".\base\asyncudpsocket.h"
- >
- </File>
- <File
- RelativePath=".\base\base64.h"
- >
- </File>
- <File
- RelativePath=".\base\basicdefs.h"
- >
- </File>
- <File
- RelativePath=".\base\basictypes.h"
- >
- </File>
- <File
- RelativePath=".\base\bytebuffer.h"
- >
- </File>
- <File
- RelativePath=".\base\byteorder.h"
- >
- </File>
- <File
- RelativePath=".\base\common.h"
- >
- </File>
- <File
- RelativePath=".\base\criticalsection.h"
- >
- </File>
- <File
- RelativePath=".\base\helpers.h"
- >
- </File>
- <File
- RelativePath=".\base\host.h"
- >
- </File>
- <File
- RelativePath=".\base\linked_ptr.h"
- >
- </File>
- <File
- RelativePath=".\base\logging.h"
- >
- </File>
- <File
- RelativePath=".\base\md5.h"
- >
- </File>
- <File
- RelativePath=".\base\messagequeue.h"
- >
- </File>
- <File
- RelativePath=".\base\network.h"
- >
- </File>
- <File
- RelativePath=".\base\physicalsocketserver.h"
- >
- </File>
- <File
- RelativePath=".\base\proxyinfo.h"
- >
- </File>
- <File
- RelativePath=".\base\schanneladapter.h"
- >
- </File>
- <File
- RelativePath=".\base\scoped_ptr.h"
- >
- </File>
- <File
- RelativePath=".\base\sec_buffer.h"
- >
- </File>
- <File
- RelativePath=".\base\sigslot.h"
- >
- </File>
- <File
- RelativePath=".\base\socket.h"
- >
- </File>
- <File
- RelativePath=".\base\socketadapters.h"
- >
- </File>
- <File
- RelativePath=".\base\socketaddress.h"
- >
- </File>
- <File
- RelativePath=".\base\socketaddresspair.h"
- >
- </File>
- <File
- RelativePath=".\base\socketfactory.h"
- >
- </File>
- <File
- RelativePath=".\base\socketserver.h"
- >
- </File>
- <File
- RelativePath=".\base\ssladapter.h"
- >
- </File>
- <File
- RelativePath=".\base\stl_decl.h"
- >
- </File>
- <File
- RelativePath=".\base\stream.h"
- >
- </File>
- <File
- RelativePath=".\base\stringdigest.h"
- >
- </File>
- <File
- RelativePath=".\base\stringencode.h"
- >
- </File>
- <File
- RelativePath=".\base\stringutils.h"
- >
- </File>
- <File
- RelativePath=".\base\task.h"
- >
- </File>
- <File
- RelativePath=".\base\taskrunner.h"
- >
- </File>
- <File
- RelativePath=".\base\thread.h"
- >
- </File>
- <File
- RelativePath=".\base\time.h"
- >
- </File>
- <File
- RelativePath=".\base\urlencode.cc"
- >
- </File>
- <File
- RelativePath=".\base\win32.h"
- >
- </File>
- <File
- RelativePath=".\base\win32socketserver.h"
- >
- </File>
- <File
- RelativePath=".\base\winfirewall.h"
- >
- </File>
- <File
- RelativePath=".\base\winping.h"
- >
- </File>
- </Filter>
- <Filter
- Name="p2p"
- >
- <Filter
- Name="base"
- >
- <File
- RelativePath=".\p2p\base\candidate.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\helpers.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\p2psocket.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\port.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\portallocator.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\pseudotcp.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\relayport.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\relayserver.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\session.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\sessiondescription.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\sessionid.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\sessionmanager.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\sessionmessage.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\sessionmessagefactory.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\sessionresponsemessage.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\socketmanager.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\stun.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\stunport.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\stunrequest.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\stunserver.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\tcpport.h"
- >
- </File>
- <File
- RelativePath=".\p2p\base\udpport.h"
- >
- </File>
- </Filter>
- <Filter
- Name="client"
- >
- <File
- RelativePath=".\p2p\client\basicportallocator.h"
- >
- </File>
- <File
- RelativePath=".\p2p\client\sessionclient.h"
- >
- </File>
- <File
- RelativePath=".\p2p\client\socketmonitor.h"
- >
- </File>
- <File
- RelativePath=".\p2p\client\xmppsessionmessage.h"
- >
- </File>
- <File
- RelativePath=".\p2p\client\xmppsessionmessagefactory.h"
- >
- </File>
- <File
- RelativePath=".\p2p\client\xmppsessionresponsemessage.h"
- >
- </File>
- </Filter>
- </Filter>
- <Filter
- Name="session"
- >
- <File
- RelativePath=".\session\receiver.h"
- >
- </File>
- <File
- RelativePath=".\session\sessionsendtask.h"
- >
- </File>
- <Filter
- Name="tunnel"
- >
- <File
- RelativePath=".\session\tunnel\pseudotcpchannel.cc"
- >
- </File>
- <File
- RelativePath=".\session\tunnel\tunnelsessionclient.h"
- >
- </File>
- </Filter>
- <Filter
- Name="phone"
- >
- <File
- RelativePath=".\session\phone\audiomonitor.h"
- >
- </File>
- <File
- RelativePath=".\session\phone\call.h"
- >
- </File>
- <File
- RelativePath=".\session\phone\channelmanager.h"
- >
- </File>
- <File
- RelativePath=".\session\phone\gipslitemediaengine.h"
- >
- </File>
- <File
- RelativePath=".\session\phone\mediachannel.h"
- >
- </File>
- <File
- RelativePath=".\session\phone\mediaengine.h"
- >
- </File>
- <File
- RelativePath=".\session\phone\phonesessionclient.h"
- >
- </File>
- <File
- RelativePath=".\session\phone\voicechannel.h"
- >
- </File>
- </Filter>
- </Filter>
- <Filter
- Name="examples"
- >
- <Filter
- Name="login"
- >
- <File
- RelativePath=".\examples\login\xmppauth.h"
- >
- </File>
- <File
- RelativePath=".\examples\login\xmpppump.h"
- >
- </File>
- <File
- RelativePath=".\examples\login\xmppsocket.h"
- >
- </File>
- <File
- RelativePath=".\examples\login\xmppthread.h"
- >
- </File>
- </Filter>
- </Filter>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/talk/main.scons b/talk/main.scons
new file mode 100644
index 0000000..d4163df
--- /dev/null
+++ b/talk/main.scons
@@ -0,0 +1,406 @@
+# -*- Python -*-
+#
+# All the helper functions are defined in:
+# - site_scons/talk.py
+# Use 'import talk' in any .scons file to get access to it.
+# Add any new helper functions to it; unittest are available
+# in talk_unittest.py.
+#
+# Each 'component' that is built is defined in a .scons file.
+# See talk.Components(...) for further info on file naming convention.
+#
+# To add a new platform clone and modify the root_env object. Remember to add
+# the new environment object to the envs list otherwise it will not be included
+# in the build.
+#
+#
+#
+import talk
+import os
+
+#-------------------------------------------------------------------------------
+# The build files/directories to 'build'.
+# If the name is the name of a directory then that directory shall contain a
+# .scons file with the same name as the directory itself:
+# Ex: The directory session/phone contains a file called phone.scons
+#
+components = talk.Components("libjingle.scons")
+
+#-------------------------------------------------------------------------------
+# Build environments
+#
+
+# The list of build environments.
+envs = []
+
+# The root of all builds.
+root_env = Environment(
+ tools = [
+ 'component_bits',
+ 'component_setup',
+ 'replace_strings',
+ 'talk_noops',
+ ],
+ BUILD_SCONSCRIPTS = components,
+ DESTINATION_ROOT = '$MAIN_DIR/build',
+ CPPPATH = [
+ '$OBJ_ROOT', # generated headers are relative to here
+ '$MAIN_DIR/..', # TODO: how can we use GOOGLECLIENT instead?
+ ],
+ CPPDEFINES = [
+ # Temp flag while porting to hammer.
+ 'HAMMER_TIME=1',
+ 'LOGGING=1',
+
+ # Feature selection
+ 'FEATURE_ENABLE_SSL',
+ 'FEATURE_ENABLE_VOICEMAIL',
+ 'FEATURE_ENABLE_PSTN',
+ 'HAVE_SRTP',
+ ]
+)
+
+#-------------------------------------------------------------------------------
+# W I N D O W S
+#
+win_env = root_env.Clone(
+ tools = [
+ 'atlmfc_vc80',
+ #'code_signing',
+ 'component_targets_msvs',
+ 'directx_9_0_c',
+ #'grid_builder',
+ 'midl',
+ 'target_platform_windows',
+ ],
+ # Don't use default vc80 midl.exe. It doesn't understand vista_sdk idl files.
+ MIDL = '$PLATFORM_SDK_VISTA_6_0_DIR/Bin/midl.exe ',
+ WIX_DIR = '$GOOGLECLIENT/third_party/wix/v3_0_2925/files',
+ # Flags for debug and optimization are added to CCFLAGS instead
+ CCPDBFLAGS = '',
+ CCFLAGS_DEBUG = '',
+ CCFLAGS_OPTIMIZED = '',
+)
+
+win_env.Append(
+ COMPONENT_LIBRARY_PUBLISH = True, # Put dlls in output dir too
+ CCFLAGS = [
+ '/Fd${TARGET}.pdb', # pdb per object allows --jobs=
+ '/WX', # warnings are errors
+ '/Zc:forScope', # handle 'for (int i = 0 ...)' right
+ '/EHs-c-', # disable C++ EH
+ '/GR-', # disable RTTI
+ '/wd4996', # ignore POSIX deprecated warnings
+
+ # promote certain level 4 warnings
+ '/w14701', # potentially uninitialized var
+ '/w14702', # unreachable code
+ '/w14706', # assignment within a conditional
+ '/w14709', # comma operator within array index
+ '/w14063', # case 'identifier' is not a valid value for switch of enum
+ '/w14064', # switch of incomplete enum 'enumeration'
+ '/w14057', # 'identifier1' indirection to slightly different base
+ # types from 'identifier2'
+ '/w14263', # member function does not override any base class virtual
+ # member function
+ '/w14266', # no override available for virtual memberfunction from base
+ # 'type'; function is hidden
+ '/w14296', # expression is always false
+ '/w14355', # 'this' : used in base member initializer list
+ ],
+ CPPDEFINES = [
+ '_ATL_CSTRING_EXPLICIT_CONSTRUCTORS',
+ # TODO: encapsulate all string operations that are not based
+ # on std::string/std::wstring and make sure we use the safest versions
+ # available on all platforms.
+ '_CRT_SECURE_NO_WARNINGS',
+ '_SCL_SECURE_NO_WARNINGS',
+ '_USE_32BIT_TIME_T',
+ '_UNICODE',
+ 'UNICODE',
+ '_HAS_EXCEPTIONS=0',
+ 'WIN32',
+ # TODO: remove this from logging.cc and enable here instead.
+ #'WIN32_LEAN_AND_MEAN',
+
+ 'WINVER=0x0500',
+ '_WIN32_WINNT=0x0501',
+ '_WIN32_IE=0x0501',
+ # The Vista platform SDK 6.0 needs at least
+ # this NTDDI version or else the headers
+ # that LMI includes from it won't compile.
+ 'NTDDI_VERSION=NTDDI_WINXP',
+ ],
+ CPPPATH = [
+ '$THIRD_PARTY/wtl_71/include',
+ '$PLATFORM_SDK_VISTA_6_0_DIR/Include',
+ ],
+ LIBPATH = [
+ '$PLATFORM_SDK_VISTA_6_0_DIR/Lib'
+ ],
+ LINKFLAGS = [
+ '-manifest' # TODO: Why do we need this?
+ ],
+ MIDLFLAGS = [
+ '/win32',
+ '/I$PLATFORM_SDK_VISTA_6_0_DIR/include'
+ ]
+)
+
+# TODO: Figure out what this does; found it in
+# omaha/main.scons. This fixes the problem with redefinition
+# of OS_WINDOWS symbol.
+win_env.FilterOut(CPPDEFINES = ['OS_WINDOWS=OS_WINDOWS'])
+
+# Set up digital signing
+DeclareBit('test_signing', 'Sign binaries with the test certificate')
+win_env.SetBitFromOption('test_signing', False)
+if win_env.Bit('test_signing'):
+ win_env.Replace(
+ CERTIFICATE_PATH = win_env.File(
+ '$GOOGLECLIENT/tools/test_key/testkey.pfx').abspath,
+ CERTIFICATE_PASSWORD = 'test',
+ )
+AddTargetGroup('signed_binaries', 'digitally signed binaries can be built')
+
+win_dbg_env = win_env.Clone(
+ BUILD_TYPE = 'dbg',
+ BUILD_TYPE_DESCRIPTION = 'Windows debug build',
+ BUILD_GROUPS = ['default', 'all'],
+ tools = ['target_debug'],
+)
+
+win_dbg_env.Prepend(
+ CCFLAGS=[
+ '/ZI', # enable debugging
+ '/Od', # disable optimizations
+ '/MTd', # link with LIBCMTD.LIB debug lib
+ '/RTC1', # enable runtime checks
+ ],
+)
+
+envs.append(win_dbg_env)
+
+win_opt_env = win_env.Clone(
+ BUILD_TYPE = 'opt',
+ BUILD_TYPE_DESCRIPTION = 'Windows opt build',
+ BUILD_GROUPS = ['all'],
+ tools = ['target_optimized'],
+)
+
+win_opt_env.Prepend(
+ CCFLAGS=[
+ '/Zi', # enable debugging
+ '/O1', # optimize for size
+ '/MT', # link with LIBCMT.LIB (multi-threaded, static linked crt)
+ '/GS', # enable security checks
+ ],
+)
+
+envs.append(win_opt_env)
+
+
+#-------------------------------------------------------------------------------
+# P O S I X
+#
+posix_env = root_env.Clone()
+posix_env.Append(
+ CPPDEFINES = [
+ 'HASHNAMESPACE=__gnu_cxx',
+ 'HASH_NAMESPACE=__gnu_cxx',
+ 'POSIX',
+ 'DISABLE_DYNAMIC_CAST',
+ 'HAVE_OPENSSL_SSL_H=1',
+ ],
+ CCFLAGS = [
+ '-m32',
+ '-Wall',
+ '-Werror',
+ '-Wno-switch',
+ '-fno-exceptions',
+ ],
+ CXXFLAGS = [
+ '-Wno-non-virtual-dtor',
+ '-Wno-ctor-dtor-privacy',
+ '-fno-rtti',
+ ],
+ LINKFLAGS = [
+ '-m32',
+ ],
+)
+
+#-------------------------------------------------------------------------------
+# M A C OSX
+#
+mac_env = posix_env.Clone(
+ tools = [
+ 'target_platform_mac',
+ #'talk_mac',
+ #'fill_plist',
+ ],
+)
+mac_env.Append(
+ CPPDEFINES = [
+ 'OSX',
+ 'MAC_OS_X_VERSION_MIN_REQUIRED=1040',
+ ],
+ CCFLAGS = [
+ '-arch', 'i386',
+ '-isysroot', '/Developer/SDKs/MacOSX10.5.sdk',
+ '-fasm-blocks',
+ ],
+ LINKFLAGS = [
+ '-Wl,-search_paths_first',
+ # This flag makes all members of a static library be included in the
+ # final exe - that increases the size of the exe, but without it
+ # Obj-C categories aren't properly included in the exe.
+ # TODO: consider only defining for libs that actually have objc.
+ '-ObjC',
+ '-arch', 'i386',
+ ],
+ FRAMEWORKS = [
+ 'CoreServices',
+ 'Carbon',
+ 'Security',
+ 'SystemConfiguration',
+ 'OpenGL',
+ ]
+)
+
+mac_dbg_env = mac_env.Clone(
+ BUILD_TYPE = 'dbg',
+ BUILD_TYPE_DESCRIPTION = 'Mac debug build',
+ BUILD_GROUPS = ['default', 'all'],
+ tools = ['target_debug']
+)
+mac_dbg_env.Append(
+ CPPDEFINES = [
+ 'FLAVOR_DBG',
+ 'ENABLE_DEBUG',
+ ],
+ CCFLAGS = [
+ '-O0',
+ ]
+)
+envs.append(mac_dbg_env)
+
+mac_opt_env = mac_env.Clone(
+ BUILD_TYPE = 'opt',
+ BUILD_TYPE_DESCRIPTION = 'Mac opt build',
+ BUILD_GROUPS = ['all'],
+ tools = ['target_optimized']
+)
+mac_opt_env.Append(
+ CCFLAGS = [
+ # TODO: Figure out how mk can compile without
+ # this flag, then remove. Confirmed asserts are preprocessed
+ # out. Maybe it's a different version of gcc?
+ '-Wno-unused-variable',
+ ],
+)
+envs.append(mac_opt_env)
+
+#-------------------------------------------------------------------------------
+# L I N U X
+#
+linux_env = posix_env.Clone(
+ tools = ['target_platform_linux'],
+)
+
+linux_env.Append(
+ CPPDEFINES = [
+ 'LINUX',
+ 'HAVE_GLIB',
+ # TODO() Enable once we figure out multiple defines with gips lib
+ # Also consider other linux flags: 64bit, no-strict-aliasing, wrap, etc
+ ],
+ LINKFLAGS = [
+ # TODO consider enabling gc-sections. Perhaps only in opt.
+ #'-Wl,--gc-sections',
+ '-Wl,--start-group',
+ ],
+ _LIBFLAGS = ['-Wl,--end-group'],
+)
+
+linux_dbg_env = linux_env.Clone(
+ BUILD_TYPE = 'dbg',
+ BUILD_TYPE_DESCRIPTION = 'Linux debug build',
+ BUILD_GROUPS = ['default', 'all'],
+ tools = ['target_debug']
+)
+envs.append(linux_dbg_env)
+
+linux_opt_env = linux_env.Clone(
+ BUILD_TYPE = 'opt',
+ BUILD_TYPE_DESCRIPTION = 'Linux optimized build',
+ BUILD_GROUPS = ['all'],
+ tools = ['target_optimized']
+)
+envs.append(linux_opt_env)
+
+
+
+# TODO(): Clone linux envs for 64bit. See 'variant' documentation.
+
+# Parse child .scons files
+BuildEnvironments(envs)
+
+# Explicitly set which targets to build when not stated on commandline
+Default(None)
+# Build the following, which excludes unit test output (ie running them)
+# To run unittests, specify the test to run, or run_all_tests. See -h option.
+Default(['all_libraries', 'all_programs', 'all_test_programs'])
+
+# .sln creation code lifted from googleclient/bar/main.scons. Must be after
+# the call to BuildEnvironments for all_foo aliases to be defined.
+# Run 'hammer --mode=all --vsproj' to generate
+DeclareBit('vsproj', 'Generate Visual Studio projects and solution files.')
+win_env.SetBitFromOption('vsproj', False)
+
+if win_env.Bit('vsproj'):
+ vs_env = win_env.Clone()
+ vs_env.Append(
+ COMPONENT_VS_SOURCE_SUFFIXES = [
+ '.def',
+ '.grd',
+ '.html',
+ '.idl',
+ '.mk',
+ '.txt',
+ '.py',
+ '.scons',
+ '.wxs.template',
+ ]
+ )
+
+ # Source project
+ p = vs_env.ComponentVSDirProject(
+ 'flute_source',
+ ['$MAIN_DIR',
+ '$THIRD_PARTY'],
+ COMPONENT_VS_SOURCE_FOLDERS = [
+ # Files are assigned to first matching folder. Folder names of None
+ # are filters.
+ (None, '$DESTINATION_ROOT'),
+ ('flute', '$MAIN_DIR'),
+ ('google3', '$GOOGLE3'),
+ ('third_party', '$THIRD_PARTY'),
+ ],
+ # Force source project to main dir, so that Visual Studio can find the
+ # source files corresponding to build errors.
+ COMPONENT_VS_PROJECT_DIR = '$MAIN_DIR',
+ )
+ vs_env.AlwaysBuild(p)
+
+ # Solution and target projects
+ s = vs_env.ComponentVSSolution(
+ ['all_libraries', 'all_programs', 'all_test_programs'],
+ projects = [p],
+ )
+
+ print '***Unfortunately the vsproj creator isn\'t smart enough to '
+ print '***automatically get the correct output locations. It is very easy'
+ print '***though to change it in the properties pane to the following'
+ print '***($SolutionDir)/build/<foo>/staging/<bar>.exe'
+ Default(None)
+ Default([s])
diff --git a/talk/p2p/Makefile.am b/talk/p2p/Makefile.am
deleted file mode 100755
index c935a6b..0000000
--- a/talk/p2p/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS=base client
diff --git a/talk/p2p/base/Makefile.am b/talk/p2p/base/Makefile.am
deleted file mode 100755
index 537b6c2..0000000
--- a/talk/p2p/base/Makefile.am
+++ /dev/null
@@ -1,68 +0,0 @@
-libcricketp2pbase_la_SOURCES = stun.cc \
- port.cc \
- udpport.cc \
- tcpport.cc \
- stunport.cc \
- relayport.cc \
- stunrequest.cc \
- sessionmanager.cc \
- session.cc \
- transport.cc \
- transportchannel.cc \
- transportchannelproxy.cc \
- p2ptransport.cc \
- p2ptransportchannel.cc \
- rawtransport.cc \
- rawtransportchannel.cc \
- constants.cc \
- pseudotcp.cc
-
-noinst_HEADERS = candidate.h \
- portallocator.h \
- relayport.h \
- session.h \
- stunport.h \
- tcpport.h \
- port.h \
- sessionid.h \
- stunrequest.h \
- udpport.h \
- pseudotcp.h \
- sessiondescription.h \
- sessionmanager.h \
- stun.h \
- relayserver.h \
- stunserver.h \
- sessionclient.h \
- transport.h \
- transportchannel.h \
- transportchannelproxy.h \
- transportchannelimpl.h \
- p2ptransport.h \
- p2ptransportchannel.h \
- rawtransport.h \
- rawtransportchannel.h \
- constants.h \
- common.h
-
-AM_CPPFLAGS = -DPOSIX -DENABLE_DEBUG -D_DEBUG -g
-
-P2PLIBS = libcricketp2pbase.la ../../base/libcricketbase.la -lpthread
-XMLLIBS = ../../xmllite/libcricketxmllite.la ../../xmpp/libcricketxmpp.la $(EXPAT_LIBS)
-TESTLIBS = ../../base/libcrickettest.la
-
-bin_PROGRAMS = relayserver stunserver
-noinst_PROGRAMS = stunserver_unittest session_unittest port_unittest
-
-relayserver_SOURCES = relayserver.cc relayserver_main.cc
-relayserver_LDADD = $(P2PLIBS)
-stunserver_SOURCES = stunserver.cc stunserver_main.cc
-stunserver_LDADD = $(P2PLIBS)
-stunserver_unittest_SOURCES = stunserver_unittest.cc stunserver.cc
-stunserver_unittest_LDADD = $(P2PLIBS) $(TESTLIBS)
-session_unittest_SOURCES = session_unittest.cc stunserver.cc relayserver.cc
-session_unittest_LDADD = $(TESTLIBS) $(P2PLIBS) $(XMLLIBS)
-port_unittest_SOURCES = port_unittest.cc stunserver.cc relayserver.cc
-port_unittest_LDADD = $(P2PLIBS) $(TESTLIBS)
-
-noinst_LTLIBRARIES = libcricketp2pbase.la
diff --git a/talk/p2p/base/candidate.h b/talk/p2p/base/candidate.h
old mode 100755
new mode 100644
index ac41311..e347ec5
--- a/talk/p2p/base/candidate.h
+++ b/talk/p2p/base/candidate.h
@@ -2,31 +2,31 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CANDIDATE_H_
-#define _CANDIDATE_H_
+#ifndef TALK_P2P_BASE_CANDIDATE_H_
+#define TALK_P2P_BASE_CANDIDATE_H_
#include <string>
#include <sstream>
@@ -37,7 +37,16 @@
// Candidate for ICE based connection discovery.
class Candidate {
-public:
+ public:
+ Candidate() : preference_(0), generation_(0) {}
+ Candidate(const std::string& name, const std::string& protocol,
+ const talk_base::SocketAddress& address, float preference,
+ const std::string& username, const std::string& password,
+ const std::string& type, const std::string& network_name,
+ uint32 generation)
+ : name_(name), protocol_(protocol), address_(address),
+ preference_(preference), username_(username), password_(password),
+ type_(type), network_name_(network_name), generation_(generation) {}
const std::string & name() const { return name_; }
void set_name(const std::string & name) { name_ = name; }
@@ -46,10 +55,11 @@
void set_protocol(const std::string & protocol) { protocol_ = protocol; }
const talk_base::SocketAddress & address() const { return address_; }
- void set_address(const talk_base::SocketAddress & address)
- { address_ = address; }
+ void set_address(const talk_base::SocketAddress & address) {
+ address_ = address;
+ }
- const float preference() const { return preference_; }
+ float preference() const { return preference_; }
void set_preference(const float preference) { preference_ = preference; }
const std::string preference_str() const {
std::ostringstream ost;
@@ -102,7 +112,15 @@
(generation_ == c.generation_);
}
-private:
+ std::string ToString() const {
+ std::ostringstream ost;
+ ost << "Cand[" << name_ << ":" << type_ << ":" << protocol_ << ":"
+ << network_name_ << ":" << address_.ToString() << ":"
+ << username_ << ":" << password_ << "]";
+ return ost.str();
+ }
+
+ private:
std::string name_;
std::string protocol_;
talk_base::SocketAddress address_;
@@ -114,6 +132,6 @@
uint32 generation_;
};
-} // namespace cricket
+} // namespace cricket
-#endif // _CANDIDATE_H_
+#endif // TALK_P2P_BASE_CANDIDATE_H_
diff --git a/talk/p2p/base/common.h b/talk/p2p/base/common.h
old mode 100755
new mode 100644
diff --git a/talk/p2p/base/constants.cc b/talk/p2p/base/constants.cc
old mode 100755
new mode 100644
index 13b9f2d..9e45457
--- a/talk/p2p/base/constants.cc
+++ b/talk/p2p/base/constants.cc
@@ -30,33 +30,146 @@
namespace cricket {
const std::string NS_EMPTY("");
-const std::string NS_GOOGLESESSION("http://www.google.com/session");
-#ifdef FEATURE_ENABLE_VOICEMAIL
-const std::string NS_GOOGLEVOICEMAIL("http://www.google.com/session/voicemail");
-#endif
+const std::string NS_JINGLE("urn:xmpp:jingle:1");
+const std::string NS_GINGLE("http://www.google.com/session");
-const buzz::QName QN_SESSION(true, NS_GOOGLESESSION, "session");
+// actions (aka <session> or <jingle>)
+const buzz::QName QN_ACTION(true, NS_EMPTY, "action");
+const std::string LN_INITIATOR("initiator");
+const buzz::QName QN_INITIATOR(true, NS_EMPTY, LN_INITIATOR);
+const buzz::QName QN_CREATOR(true, NS_EMPTY, "creator");
-const buzz::QName QN_REDIRECT_TARGET(true, NS_GOOGLESESSION, "target");
-const buzz::QName QN_REDIRECT_COOKIE(true, NS_GOOGLESESSION, "cookie");
-const buzz::QName QN_REDIRECT_REGARDING(true, NS_GOOGLESESSION, "regarding");
+const buzz::QName QN_JINGLE(true, NS_JINGLE, "jingle");
+const buzz::QName QN_JINGLE_CONTENT(true, NS_JINGLE, "content");
+const buzz::QName QN_JINGLE_CONTENT_NAME(true, NS_EMPTY, "name");
+const buzz::QName QN_JINGLE_CONTENT_MEDIA(true, NS_EMPTY, "media");
+const buzz::QName QN_JINGLE_REASON(true, NS_JINGLE, "reason");
+const std::string JINGLE_CONTENT_MEDIA_AUDIO("audio");
+const std::string JINGLE_CONTENT_MEDIA_VIDEO("video");
+const std::string JINGLE_ACTION_SESSION_INITIATE("session-initiate");
+const std::string JINGLE_ACTION_SESSION_INFO("session-info");
+const std::string JINGLE_ACTION_SESSION_ACCEPT("session-accept");
+const std::string JINGLE_ACTION_SESSION_TERMINATE("session-terminate");
+const std::string JINGLE_ACTION_TRANSPORT_INFO("transport-info");
+const std::string JINGLE_ACTION_TRANSPORT_ACCEPT("transport-accept");
-#ifdef FEATURE_ENABLE_VOICEMAIL
-const buzz::QName QN_VOICEMAIL_REGARDING(true, NS_GOOGLEVOICEMAIL, "regarding");
-#endif
+const buzz::QName QN_GINGLE_SESSION(true, NS_GINGLE, "session");
+const std::string GINGLE_ACTION_INITIATE("initiate");
+const std::string GINGLE_ACTION_INFO("info");
+const std::string GINGLE_ACTION_ACCEPT("accept");
+const std::string GINGLE_ACTION_REJECT("reject");
+const std::string GINGLE_ACTION_TERMINATE("terminate");
+const std::string GINGLE_ACTION_CANDIDATES("candidates");
-const buzz::QName QN_INITIATOR(true, NS_EMPTY, "initiator");
+// Session Contents (aka Gingle <session><description>
+// or Jingle <content><description>)
+const std::string LN_DESCRIPTION("description");
+const std::string LN_PAYLOADTYPE("payload-type");
+const buzz::QName QN_ID(true, NS_EMPTY, "id");
+const buzz::QName QN_NAME(true, NS_EMPTY, "name");
+const buzz::QName QN_CLOCKRATE(true, NS_EMPTY, "clockrate");
+const buzz::QName QN_BITRATE(true, NS_EMPTY, "bitrate");
+const buzz::QName QN_CHANNELS(true, NS_EMPTY, "channels");
+const buzz::QName QN_WIDTH(true, NS_EMPTY, "width");
+const buzz::QName QN_HEIGHT(true, NS_EMPTY, "height");
+const buzz::QName QN_FRAMERATE(true, NS_EMPTY, "framerate");
+const std::string LN_NAME("name");
+const std::string LN_VALUE("value");
+const buzz::QName QN_PAYLOADTYPE_PARAMETER_NAME(true, NS_EMPTY, LN_NAME);
+const buzz::QName QN_PAYLOADTYPE_PARAMETER_VALUE(true, NS_EMPTY, LN_VALUE);
+const std::string PAYLOADTYPE_PARAMETER_BITRATE("bitrate");
+const std::string PAYLOADTYPE_PARAMETER_HEIGHT("height");
+const std::string PAYLOADTYPE_PARAMETER_WIDTH("width");
+const std::string PAYLOADTYPE_PARAMETER_FRAMERATE("framerate");
-const buzz::QName QN_ADDRESS(true, cricket::NS_EMPTY, "address");
+const std::string CN_AUDIO("audio");
+const std::string CN_VIDEO("video");
+const std::string CN_OTHER("main");
+
+const std::string NS_JINGLE_RTP("urn:xmpp:jingle:apps:rtp:1");
+const buzz::QName QN_JINGLE_RTP_CONTENT(
+ true, NS_JINGLE_RTP, LN_DESCRIPTION);
+const buzz::QName QN_JINGLE_RTP_PAYLOADTYPE(
+ true, NS_JINGLE_RTP, LN_PAYLOADTYPE);
+const buzz::QName QN_PARAMETER(true, NS_JINGLE_RTP, "parameter");
+
+const std::string NS_GINGLE_AUDIO("http://www.google.com/session/phone");
+const buzz::QName QN_GINGLE_AUDIO_CONTENT(
+ true, NS_GINGLE_AUDIO, LN_DESCRIPTION);
+const buzz::QName QN_GINGLE_AUDIO_PAYLOADTYPE(
+ true, NS_GINGLE_AUDIO, LN_PAYLOADTYPE);
+const buzz::QName QN_GINGLE_AUDIO_SRCID(true, NS_GINGLE_AUDIO, "src-id");
+const std::string NS_GINGLE_VIDEO("http://www.google.com/session/video");
+const buzz::QName QN_GINGLE_VIDEO_CONTENT(
+ true, NS_GINGLE_VIDEO, LN_DESCRIPTION);
+const buzz::QName QN_GINGLE_VIDEO_PAYLOADTYPE(
+ true, NS_GINGLE_VIDEO, LN_PAYLOADTYPE);
+const buzz::QName QN_GINGLE_VIDEO_SRCID(true, NS_GINGLE_VIDEO, "src-id");
+const buzz::QName QN_GINGLE_VIDEO_BANDWIDTH(true, NS_GINGLE_VIDEO, "bandwidth");
+
+// transports and candidates
+const std::string LN_TRANSPORT("transport");
+const std::string LN_CANDIDATE("candidate");
+const buzz::QName QN_UFRAG(true, cricket::NS_EMPTY, "ufrag");
+const buzz::QName QN_PWD(true, cricket::NS_EMPTY, "pwd");
+const buzz::QName QN_COMPONENT(true, cricket::NS_EMPTY, "component");
+const buzz::QName QN_IP(true, cricket::NS_EMPTY, "ip");
const buzz::QName QN_PORT(true, cricket::NS_EMPTY, "port");
const buzz::QName QN_NETWORK(true, cricket::NS_EMPTY, "network");
const buzz::QName QN_GENERATION(true, cricket::NS_EMPTY, "generation");
+const buzz::QName QN_PRIORITY(true, cricket::NS_EMPTY, "priority");
+const buzz::QName QN_PROTOCOL(true, cricket::NS_EMPTY, "protocol");
+const std::string JINGLE_CANDIDATE_TYPE_PEER_STUN("prflx");
+const std::string JINGLE_CANDIDATE_TYPE_SERVER_STUN("srflx");
+const std::string JINGLE_CANDIDATE_NAME_RTP("1");
+const std::string JINGLE_CANDIDATE_NAME_RTCP("2");
+
+// TODO Once we are full ICE-UDP compliant, use this namespace.
+// For now, just use the same as NS_GINGLE_P2P.
+// const std::string NS_JINGLE_ICE_UDP("urn:xmpp:jingle:transports:ice-udp:1");
+const std::string NS_GINGLE_P2P("http://www.google.com/transport/p2p");
+const buzz::QName QN_GINGLE_P2P_TRANSPORT(true, NS_GINGLE_P2P, LN_TRANSPORT);
+const buzz::QName QN_GINGLE_P2P_CANDIDATE(true, NS_GINGLE_P2P, LN_CANDIDATE);
+const buzz::QName QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME(
+ true, NS_GINGLE_P2P, "unknown-channel-name");
+const buzz::QName QN_GINGLE_CANDIDATE(true, NS_GINGLE, LN_CANDIDATE);
+const buzz::QName QN_ADDRESS(true, cricket::NS_EMPTY, "address");
const buzz::QName QN_USERNAME(true, cricket::NS_EMPTY, "username");
const buzz::QName QN_PASSWORD(true, cricket::NS_EMPTY, "password");
const buzz::QName QN_PREFERENCE(true, cricket::NS_EMPTY, "preference");
-const buzz::QName QN_PROTOCOL(true, cricket::NS_EMPTY, "protocol");
+const std::string GINGLE_CANDIDATE_TYPE_STUN("stun");
+const std::string GINGLE_CANDIDATE_NAME_RTP("rtp");
+const std::string GINGLE_CANDIDATE_NAME_RTCP("rtcp");
+const std::string GINGLE_CANDIDATE_NAME_VIDEO_RTP("video_rtp");
+const std::string GINGLE_CANDIDATE_NAME_VIDEO_RTCP("video_rtcp");
-// Legacy transport messages
-const buzz::QName kQnLegacyCandidate(true, cricket::NS_GOOGLESESSION,
- "candidate");
+// terminate reasons and errors
+const std::string JINGLE_ERROR_BAD_REQUEST("bad-request");
+const std::string JINGLE_ERROR_OUT_OF_ORDER("out-of-order");
+const std::string JINGLE_ERROR_UNKNOWN_SESSION("unknown-session");
+
+// Call terminate reasons from XEP-166
+const std::string STR_TERMINATE_DECLINE("decline");
+const std::string STR_TERMINATE_SUCCESS("success");
+const std::string STR_TERMINATE_ERROR("general-error");
+const std::string STR_TERMINATE_INCOMPATIBLE_PARAMETERS(
+ "incompatible-parameters");
+
+// Old terminate reasons used by cricket
+const std::string STR_TERMINATE_CALL_ENDED("call-ended");
+const std::string STR_TERMINATE_RECIPIENT_UNAVAILABLE("recipient-unavailable");
+const std::string STR_TERMINATE_RECIPIENT_BUSY("recipient-busy");
+const std::string STR_TERMINATE_INSUFFICIENT_FUNDS("insufficient-funds");
+const std::string STR_TERMINATE_NUMBER_MALFORMED("number-malformed");
+const std::string STR_TERMINATE_NUMBER_DISALLOWED("number-disallowed");
+const std::string STR_TERMINATE_PROTOCOL_ERROR("protocol-error");
+const std::string STR_TERMINATE_INTERNAL_SERVER_ERROR("internal-server-error");
+const std::string STR_TERMINATE_UNKNOWN_ERROR("unknown-error");
+
+// old stuff
+#ifdef FEATURE_ENABLE_VOICEMAIL
+const std::string NS_VOICEMAIL("http://www.google.com/session/voicemail");
+const buzz::QName QN_VOICEMAIL_REGARDING(true, NS_VOICEMAIL, "regarding");
+#endif
+
} // namespace cricket
diff --git a/talk/p2p/base/constants.h b/talk/p2p/base/constants.h
old mode 100755
new mode 100644
index 46315eb..7e33c5b
--- a/talk/p2p/base/constants.h
+++ b/talk/p2p/base/constants.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_P2P_BASE_CONSTANTS_H_
-#define _CRICKET_P2P_BASE_CONSTANTS_H_
+#ifndef TALK_P2P_BASE_CONSTANTS_H_
+#define TALK_P2P_BASE_CONSTANTS_H_
#include <string>
#include "talk/xmllite/qname.h"
@@ -36,35 +36,170 @@
namespace cricket {
+// There are 3 different types of Jingle messages or protocols: Jingle
+// (the spec in XEP-166, etc), Gingle (the legacy protocol) and hybrid
+// (both at the same time). Gingle2 is a temporary protocol that we
+// are only keeping around right now during this refactoring phase.
+// Once we finish refactoring and start implementing Jingle, we will
+// remove Gingle2.
+
+// NS_ == namespace
+// QN_ == buzz::QName (namespace + name)
+// LN_ == "local name" == QName::LocalPart()
+// these are useful when you need to find a tag
+// that has different namespaces (like <description> or <transport>)
+
extern const std::string NS_EMPTY;
-extern const std::string NS_GOOGLESESSION;
-#ifdef FEATURE_ENABLE_VOICEMAIL
-extern const std::string NS_GOOGLEVOICEMAIL;
-#endif
+extern const std::string NS_JINGLE;
+extern const std::string NS_GINGLE;
-extern const buzz::QName QN_SESSION;
+enum SignalingProtocol {
+ PROTOCOL_JINGLE,
+ PROTOCOL_GINGLE,
+ PROTOCOL_HYBRID,
+};
-extern const buzz::QName QN_REDIRECT_TARGET;
-extern const buzz::QName QN_REDIRECT_COOKIE;
-extern const buzz::QName QN_REDIRECT_REGARDING;
-#ifdef FEATURE_ENABLE_VOICEMAIL
-extern const buzz::QName QN_VOICEMAIL_REGARDING;
-#endif
-
+// actions (aka Gingle <session> or Jingle <jingle>)
+extern const buzz::QName QN_ACTION;
+extern const std::string LN_INITIATOR;
extern const buzz::QName QN_INITIATOR;
+extern const buzz::QName QN_CREATOR;
-extern const buzz::QName QN_ADDRESS;
+extern const buzz::QName QN_JINGLE;
+extern const buzz::QName QN_JINGLE_CONTENT;
+extern const buzz::QName QN_JINGLE_CONTENT_NAME;
+extern const buzz::QName QN_JINGLE_CONTENT_MEDIA;
+extern const buzz::QName QN_JINGLE_REASON;
+extern const std::string JINGLE_CONTENT_MEDIA_AUDIO;
+extern const std::string JINGLE_CONTENT_MEDIA_VIDEO;
+extern const std::string JINGLE_ACTION_SESSION_INITIATE;
+extern const std::string JINGLE_ACTION_SESSION_INFO;
+extern const std::string JINGLE_ACTION_SESSION_ACCEPT;
+extern const std::string JINGLE_ACTION_SESSION_TERMINATE;
+extern const std::string JINGLE_ACTION_TRANSPORT_INFO;
+extern const std::string JINGLE_ACTION_TRANSPORT_ACCEPT;
+
+extern const buzz::QName QN_GINGLE_SESSION;
+extern const std::string GINGLE_ACTION_INITIATE;
+extern const std::string GINGLE_ACTION_INFO;
+extern const std::string GINGLE_ACTION_ACCEPT;
+extern const std::string GINGLE_ACTION_REJECT;
+extern const std::string GINGLE_ACTION_TERMINATE;
+extern const std::string GINGLE_ACTION_CANDIDATES;
+
+
+// Session Contents (aka Gingle <session><description>
+// or Jingle <content><description>)
+extern const std::string LN_DESCRIPTION;
+extern const std::string LN_PAYLOADTYPE;
+extern const buzz::QName QN_ID;
+extern const buzz::QName QN_NAME;
+extern const buzz::QName QN_CLOCKRATE;
+extern const buzz::QName QN_BITRATE;
+extern const buzz::QName QN_CHANNELS;
+extern const buzz::QName QN_WIDTH;
+extern const buzz::QName QN_HEIGHT;
+extern const buzz::QName QN_FRAMERATE;
+extern const buzz::QName QN_PARAMETER;
+extern const std::string LN_NAME;
+extern const std::string LN_VALUE;
+extern const buzz::QName QN_PAYLOADTYPE_PARAMETER_NAME;
+extern const buzz::QName QN_PAYLOADTYPE_PARAMETER_VALUE;
+extern const std::string PAYLOADTYPE_PARAMETER_BITRATE;
+extern const std::string PAYLOADTYPE_PARAMETER_HEIGHT;
+extern const std::string PAYLOADTYPE_PARAMETER_WIDTH;
+extern const std::string PAYLOADTYPE_PARAMETER_FRAMERATE;
+
+// CN_ == "content name". When we initiate a session, we choose the
+// name, and when we receive a Gingle session, we provide default
+// names (since Gingle has no content names). But when we receive a
+// Jingle call, the content name can be anything, so don't rely on
+// these values being the same as the ones received.
+extern const std::string CN_AUDIO;
+extern const std::string CN_VIDEO;
+extern const std::string CN_OTHER;
+
+extern const std::string NS_JINGLE_RTP;
+extern const buzz::QName QN_JINGLE_RTP_CONTENT;
+extern const buzz::QName QN_JINGLE_RTP_PAYLOADTYPE;
+
+extern const std::string NS_GINGLE_AUDIO;
+extern const buzz::QName QN_GINGLE_AUDIO_CONTENT;
+extern const buzz::QName QN_GINGLE_AUDIO_PAYLOADTYPE;
+extern const buzz::QName QN_GINGLE_AUDIO_SRCID;
+extern const std::string NS_GINGLE_VIDEO;
+extern const buzz::QName QN_GINGLE_VIDEO_CONTENT;
+extern const buzz::QName QN_GINGLE_VIDEO_PAYLOADTYPE;
+extern const buzz::QName QN_GINGLE_VIDEO_SRCID;
+extern const buzz::QName QN_GINGLE_VIDEO_BANDWIDTH;
+
+// transports and candidates
+extern const std::string LN_TRANSPORT;
+extern const std::string LN_CANDIDATE;
+extern const buzz::QName QN_JINGLE_P2P_TRANSPORT;
+extern const buzz::QName QN_JINGLE_P2P_CANDIDATE;
+extern const buzz::QName QN_UFRAG;
+extern const buzz::QName QN_COMPONENT;
+extern const buzz::QName QN_PWD;
+extern const buzz::QName QN_IP;
extern const buzz::QName QN_PORT;
extern const buzz::QName QN_NETWORK;
extern const buzz::QName QN_GENERATION;
+extern const buzz::QName QN_PRIORITY;
+extern const buzz::QName QN_PROTOCOL;
+extern const std::string JINGLE_CANDIDATE_TYPE_PEER_STUN;
+extern const std::string JINGLE_CANDIDATE_TYPE_SERVER_STUN;
+extern const std::string JINGLE_CANDIDATE_NAME_RTP;
+extern const std::string JINGLE_CANDIDATE_NAME_RTCP;
+
+extern const std::string NS_GINGLE_P2P;
+extern const buzz::QName QN_GINGLE_P2P_TRANSPORT;
+extern const buzz::QName QN_GINGLE_P2P_CANDIDATE;
+extern const buzz::QName QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME;
+extern const buzz::QName QN_GINGLE_CANDIDATE;
+extern const buzz::QName QN_ADDRESS;
extern const buzz::QName QN_USERNAME;
extern const buzz::QName QN_PASSWORD;
extern const buzz::QName QN_PREFERENCE;
-extern const buzz::QName QN_PROTOCOL;
+extern const std::string GINGLE_CANDIDATE_TYPE_STUN;
+extern const std::string GINGLE_CANDIDATE_NAME_RTP;
+extern const std::string GINGLE_CANDIDATE_NAME_RTCP;
+extern const std::string GINGLE_CANDIDATE_NAME_VIDEO_RTP;
+extern const std::string GINGLE_CANDIDATE_NAME_VIDEO_RTCP;
-// Legacy transport messages
-extern const buzz::QName kQnLegacyCandidate;
+extern const std::string NS_GINGLE_RAW;
+extern const buzz::QName QN_GINGLE_RAW_TRANSPORT;
+extern const buzz::QName QN_GINGLE_RAW_CHANNEL;
+
+// terminate reasons and errors: see http://xmpp.org/extensions/xep-0166.html
+extern const std::string JINGLE_ERROR_BAD_REQUEST; // like parse error
+// got transport-info before session-initiate, for example
+extern const std::string JINGLE_ERROR_OUT_OF_ORDER;
+extern const std::string JINGLE_ERROR_UNKNOWN_SESSION;
+
+// Call terminate reasons from XEP-166
+extern const std::string STR_TERMINATE_DECLINE; // polite reject
+extern const std::string STR_TERMINATE_SUCCESS; // polite hangup
+extern const std::string STR_TERMINATE_ERROR; // something bad happened
+extern const std::string STR_TERMINATE_INCOMPATIBLE_PARAMETERS; // no codecs?
+
+// Old terminate reasons used by cricket
+extern const std::string STR_TERMINATE_CALL_ENDED;
+extern const std::string STR_TERMINATE_RECIPIENT_UNAVAILABLE;
+extern const std::string STR_TERMINATE_RECIPIENT_BUSY;
+extern const std::string STR_TERMINATE_INSUFFICIENT_FUNDS;
+extern const std::string STR_TERMINATE_NUMBER_MALFORMED;
+extern const std::string STR_TERMINATE_NUMBER_DISALLOWED;
+extern const std::string STR_TERMINATE_PROTOCOL_ERROR;
+extern const std::string STR_TERMINATE_INTERNAL_SERVER_ERROR;
+extern const std::string STR_TERMINATE_UNKNOWN_ERROR;
+
+// old stuff
+#ifdef FEATURE_ENABLE_VOICEMAIL
+extern const std::string NS_VOICEMAIL;
+extern const buzz::QName QN_VOICEMAIL_REGARDING;
+#endif
} // namespace cricket
-#endif // _CRICKET_P2P_BASE_CONSTANTS_H_
+#endif // TALK_P2P_BASE_CONSTANTS_H_
diff --git a/talk/p2p/base/p2ptransport.cc b/talk/p2p/base/p2ptransport.cc
old mode 100755
new mode 100644
index 2221d8c..dd170ff
--- a/talk/p2p/base/p2ptransport.cc
+++ b/talk/p2p/base/p2ptransport.cc
@@ -2,36 +2,43 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/p2p/base/p2ptransport.h"
+
+#include <string>
+#include <vector>
+
+#include "talk/base/base64.h"
#include "talk/base/common.h"
-#include "talk/p2p/base/candidate.h"
+#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
#include "talk/p2p/base/constants.h"
-#include "talk/base/helpers.h"
#include "talk/p2p/base/p2ptransportchannel.h"
+#include "talk/p2p/base/parsing.h"
#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/base/sessionmessages.h"
#include "talk/xmllite/qname.h"
#include "talk/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
@@ -45,111 +52,66 @@
namespace cricket {
-const std::string kNsP2pTransport("http://www.google.com/transport/p2p");
-const buzz::QName kQnP2pTransport(true, kNsP2pTransport, "transport");
-const buzz::QName kQnP2pCandidate(true, kNsP2pTransport, "candidate");
-const buzz::QName kQnP2pUnknownChannelName(true, kNsP2pTransport,
- "unknown-channel-name");
-
-P2PTransport::P2PTransport(SessionManager* session_manager)
- : Transport(session_manager, kNsP2pTransport) {
+P2PTransport::P2PTransport(talk_base::Thread* signaling_thread,
+ talk_base::Thread* worker_thread,
+ PortAllocator* allocator)
+ : Transport(signaling_thread, worker_thread,
+ NS_GINGLE_P2P, allocator) {
}
P2PTransport::~P2PTransport() {
DestroyAllChannels();
}
-buzz::XmlElement* P2PTransport::CreateTransportOffer() {
- return new buzz::XmlElement(kQnP2pTransport, true);
-}
-
-buzz::XmlElement* P2PTransport::CreateTransportAnswer() {
- return new buzz::XmlElement(kQnP2pTransport, true);
-}
-
-bool P2PTransport::OnTransportOffer(const buzz::XmlElement* elem) {
- ASSERT(elem->Name() == kQnP2pTransport);
- // We don't support any options, so we ignore them.
- return true;
-}
-
-bool P2PTransport::OnTransportAnswer(const buzz::XmlElement* elem) {
- ASSERT(elem->Name() == kQnP2pTransport);
- // We don't support any options. We fail if any are given. The other side
- // should know from our request that we expected an empty response.
- return elem->FirstChild() == NULL;
-}
-
-bool P2PTransport::OnTransportMessage(const buzz::XmlElement* msg,
- const buzz::XmlElement* stanza) {
- ASSERT(msg->Name() == kQnP2pTransport);
- for (const buzz::XmlElement* elem = msg->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- if (elem->Name() == kQnP2pCandidate) {
- // Make sure this candidate is valid.
- Candidate candidate;
- if (!ParseCandidate(stanza, elem, &candidate))
- return false;
-
- ForwardChannelMessage(elem->Attr(buzz::QN_NAME),
- new buzz::XmlElement(*elem));
- }
- }
- return true;
-}
-
-bool P2PTransport::OnTransportError(const buzz::XmlElement* session_msg,
- const buzz::XmlElement* error) {
- ASSERT(error->Name().Namespace() == kNsP2pTransport);
- if ((error->Name() == kQnP2pUnknownChannelName)
+void P2PTransport::OnTransportError(const buzz::XmlElement* error) {
+ // Need to know if it was <unknown-channel name="xxx">.
+ ASSERT(error->Name().Namespace() == type());
+ if ((error->Name() == QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME)
&& error->HasAttr(buzz::QN_NAME)) {
std::string channel_name = error->Attr(buzz::QN_NAME);
if (HasChannel(channel_name)) {
SignalChannelGone(this, channel_name);
}
}
+}
+
+
+bool P2PTransportParser::ParseCandidates(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ Candidates* candidates,
+ ParseError* error) {
+ // TODO: Once we implement standard ICE-UDP, parse the
+ // candidates according to XEP-176.
+ for (const buzz::XmlElement* candidate_elem = elem->FirstElement();
+ candidate_elem != NULL;
+ candidate_elem = candidate_elem->NextElement()) {
+ // Only look at local part because it might be <session><candidate>
+ // or <tranport><candidate>.
+ if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) {
+ Candidate candidate;
+ if (!ParseCandidate(candidate_elem, &candidate, error))
+ return false;
+ candidates->push_back(candidate);
+ }
+ }
return true;
}
-void P2PTransport::OnTransportChannelMessages(
- const std::vector<buzz::XmlElement*>& candidates) {
- buzz::XmlElement* transport =
- new buzz::XmlElement(kQnP2pTransport, true);
- for (size_t i = 0; i < candidates.size(); ++i)
- transport->AddElement(candidates[i]);
-
- std::vector<buzz::XmlElement*> elems;
- elems.push_back(transport);
- SignalTransportMessage(this, elems);
-}
-
-bool P2PTransport::ParseCandidate(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- Candidate* candidate) {
- // Check for all of the required attributes.
- if (!elem->HasAttr(buzz::QN_NAME) ||
+bool P2PTransportParser::ParseCandidate(const buzz::XmlElement* elem,
+ Candidate* candidate,
+ ParseError* error) {
+ if (!elem->HasAttr(buzz::QN_NAME) ||
!elem->HasAttr(QN_ADDRESS) ||
!elem->HasAttr(QN_PORT) ||
!elem->HasAttr(QN_USERNAME) ||
!elem->HasAttr(QN_PREFERENCE) ||
- !elem->HasAttr(QN_PROTOCOL) ||
+ !elem->HasAttr(QN_PROTOCOL) ||
!elem->HasAttr(QN_GENERATION)) {
- return BadRequest(stanza, "candidate missing required attribute", NULL);
- }
-
- // Make sure the channel named actually exists.
- if (!HasChannel(elem->Attr(buzz::QN_NAME))) {
- scoped_ptr<buzz::XmlElement>
- extra_info(new buzz::XmlElement(kQnP2pUnknownChannelName));
- extra_info->AddAttr(buzz::QN_NAME, elem->Attr(buzz::QN_NAME));
- return BadRequest(stanza, "channel named in candidate does not exist",
- extra_info.get());
+ return BadParse("candidate missing required attribute", error);
}
- // Parse the address given.
talk_base::SocketAddress address;
- if (!ParseAddress(stanza, elem, &address))
+ if (!ParseAddress(elem, QN_ADDRESS, QN_PORT, &address, error))
return false;
candidate->set_name(elem->Attr(buzz::QN_NAME));
@@ -158,16 +120,6 @@
candidate->set_preference_str(elem->Attr(QN_PREFERENCE));
candidate->set_protocol(elem->Attr(QN_PROTOCOL));
candidate->set_generation_str(elem->Attr(QN_GENERATION));
-
- // Check that the username is not too long and does not use any bad chars.
- if (candidate->username().size() > kMaxUsernameSize)
- return BadRequest(stanza, "candidate username is too long", NULL);
- if (!IsBase64Encoded(candidate->username()))
- return BadRequest(stanza,
- "candidate username has non-base64 encoded characters",
- NULL);
-
- // Look for the non-required attributes.
if (elem->HasAttr(QN_PASSWORD))
candidate->set_password(elem->Attr(QN_PASSWORD));
if (elem->HasAttr(buzz::QN_TYPE))
@@ -175,31 +127,71 @@
if (elem->HasAttr(QN_NETWORK))
candidate->set_network_name(elem->Attr(QN_NETWORK));
+ if (!VerifyUsernameFormat(candidate->username(), error))
+ return false;
+
return true;
}
-buzz::XmlElement* P2PTransport::TranslateCandidate(const Candidate& c) {
- buzz::XmlElement* candidate = new buzz::XmlElement(kQnP2pCandidate);
- candidate->SetAttr(buzz::QN_NAME, c.name());
- candidate->SetAttr(QN_ADDRESS, c.address().IPAsString());
- candidate->SetAttr(QN_PORT, c.address().PortAsString());
- candidate->SetAttr(QN_PREFERENCE, c.preference_str());
- candidate->SetAttr(QN_USERNAME, c.username());
- candidate->SetAttr(QN_PROTOCOL, c.protocol());
- candidate->SetAttr(QN_GENERATION, c.generation_str());
- if (c.password().size() > 0)
- candidate->SetAttr(QN_PASSWORD, c.password());
- if (c.type().size() > 0)
- candidate->SetAttr(buzz::QN_TYPE, c.type());
- if (c.network_name().size() > 0)
- candidate->SetAttr(QN_NETWORK, c.network_name());
- return candidate;
+bool P2PTransportParser::VerifyUsernameFormat(const std::string& username,
+ ParseError* error) {
+ if (username.size() > kMaxUsernameSize)
+ return BadParse("candidate username is too long", error);
+ if (!talk_base::Base64::IsBase64Encoded(username))
+ return BadParse(
+ "candidate username has non-base64 encoded characters", error);
+ return true;
+}
+
+const buzz::QName& GetCandidateQName(SignalingProtocol protocol) {
+ if (protocol == PROTOCOL_GINGLE) {
+ return QN_GINGLE_CANDIDATE;
+ } else {
+ // TODO: Once we implement standard ICE-UDP, use the
+ // XEP-176 namespace.
+ return QN_GINGLE_P2P_CANDIDATE;
+ }
+}
+
+bool P2PTransportParser::WriteCandidates(SignalingProtocol protocol,
+ const Candidates& candidates,
+ XmlElements* candidate_elems,
+ WriteError* error) {
+ // TODO: Once we implement standard ICE-UDP, parse the
+ // candidates according to XEP-176.
+ for (std::vector<Candidate>::const_iterator iter = candidates.begin();
+ iter != candidates.end(); ++iter) {
+ buzz::XmlElement* cand_elem =
+ new buzz::XmlElement(GetCandidateQName(protocol));
+ if (!WriteCandidate(*iter, cand_elem, error))
+ return false;
+ candidate_elems->push_back(cand_elem);
+ }
+ return true;
+}
+
+bool P2PTransportParser::WriteCandidate(const Candidate& candidate,
+ buzz::XmlElement* elem,
+ WriteError* error) {
+ elem->SetAttr(buzz::QN_NAME, candidate.name());
+ elem->SetAttr(QN_ADDRESS, candidate.address().IPAsString());
+ elem->SetAttr(QN_PORT, candidate.address().PortAsString());
+ elem->SetAttr(QN_PREFERENCE, candidate.preference_str());
+ elem->SetAttr(QN_USERNAME, candidate.username());
+ elem->SetAttr(QN_PROTOCOL, candidate.protocol());
+ elem->SetAttr(QN_GENERATION, candidate.generation_str());
+ if (candidate.password().size() > 0)
+ elem->SetAttr(QN_PASSWORD, candidate.password());
+ if (candidate.type().size() > 0)
+ elem->SetAttr(buzz::QN_TYPE, candidate.type());
+ if (candidate.network_name().size() > 0)
+ elem->SetAttr(QN_NETWORK, candidate.network_name());
+ return true;
}
TransportChannelImpl* P2PTransport::CreateTransportChannel(
- const std::string& name, const std::string &session_type) {
- return new P2PTransportChannel(
- name, session_type, this, session_manager()->port_allocator());
+ const std::string& name, const std::string& content_type) {
+ return new P2PTransportChannel(name, content_type, this, port_allocator());
}
void P2PTransport::DestroyTransportChannel(TransportChannelImpl* channel) {
diff --git a/talk/p2p/base/p2ptransport.h b/talk/p2p/base/p2ptransport.h
old mode 100755
new mode 100644
index 2027d4a..084f487
--- a/talk/p2p/base/p2ptransport.h
+++ b/talk/p2p/base/p2ptransport.h
@@ -25,62 +25,59 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_P2P_BASE_P2PTRANSPORT_H_
-#define _CRICKET_P2P_BASE_P2PTRANSPORT_H_
+#ifndef TALK_P2P_BASE_P2PTRANSPORT_H_
+#define TALK_P2P_BASE_P2PTRANSPORT_H_
+#include <string>
+#include <vector>
#include "talk/p2p/base/transport.h"
namespace cricket {
-class Candidate;
-
-// Xml names used to name this transport and create our elements
-extern const std::string kNsP2pTransport;
-extern const buzz::QName kQnP2pTransport;
-extern const buzz::QName kQnP2pCandidate;
-
class P2PTransport: public Transport {
public:
- P2PTransport(SessionManager* session_manager);
+ P2PTransport(talk_base::Thread* signaling_thread,
+ talk_base::Thread* worker_thread,
+ PortAllocator* allocator);
virtual ~P2PTransport();
- // Implements negotiation of the P2P protocol.
- virtual buzz::XmlElement* CreateTransportOffer();
- virtual buzz::XmlElement* CreateTransportAnswer();
- virtual bool OnTransportOffer(const buzz::XmlElement* elem);
- virtual bool OnTransportAnswer(const buzz::XmlElement* elem);
-
- // Forwards each candidate message to the appropriate channel.
- virtual bool OnTransportMessage(const buzz::XmlElement* msg,
- const buzz::XmlElement* stanza);
- virtual bool OnTransportError(const buzz::XmlElement* session_msg,
- const buzz::XmlElement* error);
+ virtual void OnTransportError(const buzz::XmlElement* error);
protected:
// Creates and destroys P2PTransportChannel.
- virtual TransportChannelImpl* CreateTransportChannel(const std::string& name, const std::string &session_type);
+ virtual TransportChannelImpl* CreateTransportChannel(
+ const std::string& name, const std::string& content_type);
virtual void DestroyTransportChannel(TransportChannelImpl* channel);
- // Sends a given set of channel messages, which each describe a candidate,
- // to the other client as a single transport message.
- void OnTransportChannelMessages(
- const std::vector<buzz::XmlElement*>& candidates);
-
- private:
- // Attempts to parse the given XML into a candidate. Returns true if the
- // XML is valid. If not, we will signal an error.
- bool ParseCandidate(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- Candidate* candidate);
-
- // Generates a XML element describing the given candidate.
- buzz::XmlElement* TranslateCandidate(const Candidate& c);
-
friend class P2PTransportChannel;
DISALLOW_EVIL_CONSTRUCTORS(P2PTransport);
};
+class P2PTransportParser : public TransportParser {
+ public:
+ P2PTransportParser() {}
+ virtual bool ParseCandidates(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ Candidates* candidates,
+ ParseError* error);
+ virtual bool WriteCandidates(SignalingProtocol protocol,
+ const Candidates& candidates,
+ XmlElements* candidate_elems,
+ WriteError* error);
+ private:
+ bool ParseCandidate(const buzz::XmlElement* elem,
+ Candidate* candidate,
+ ParseError* error);
+ bool WriteCandidate(const Candidate& candidate,
+ buzz::XmlElement* elem,
+ WriteError* error);
+ bool VerifyUsernameFormat(const std::string& username,
+ ParseError* error);
+
+ DISALLOW_EVIL_CONSTRUCTORS(P2PTransportParser);
+};
+
} // namespace cricket
-#endif // _CRICKET_P2P_BASE_P2PTRANSPORT_H_
+#endif // TALK_P2P_BASE_P2PTRANSPORT_H_
diff --git a/talk/p2p/base/p2ptransportchannel.cc b/talk/p2p/base/p2ptransportchannel.cc
old mode 100755
new mode 100644
index 717ae70..0cd9b71
--- a/talk/p2p/base/p2ptransportchannel.cc
+++ b/talk/p2p/base/p2ptransportchannel.cc
@@ -2,42 +2,36 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma warning(disable:4786)
-#endif
-
-#include <errno.h>
-
-#include <iostream>
-
-#include "talk/base/common.h"
-#include "talk/base/logging.h"
-#include "talk/p2p/base/common.h"
#include "talk/p2p/base/p2ptransportchannel.h"
+#include <set>
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/p2p/base/common.h"
+
namespace {
// messages for queuing up work for ourselves
@@ -51,23 +45,23 @@
// well on a 28.8K modem, which is the slowest connection on which the voice
// quality is reasonable at all.
static const uint32 PING_PACKET_SIZE = 60 * 8;
-static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms
-static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000;// 50ms
+static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms
+static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000; // 50ms
// If there is a current writable connection, then we will also try hard to
// make sure it is pinged at this rate.
-static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit
+static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit
-// The minimum improvement in MOS that justifies a switch.
+// The minimum improvement in RTT that justifies a switch.
static const double kMinImprovement = 10;
// Amount of time that we wait when *losing* writability before we try doing
// another allocation.
-static const int kAllocateDelay = 1 * 1000; // 1 second
+static const int kAllocateDelay = 1 * 1000; // 1 second
// We will try creating a new allocator from scratch after a delay of this
// length without becoming writable (or timing out).
-static const int kAllocatePeriod = 20 * 1000; // 20 seconds
+static const int kAllocatePeriod = 20 * 1000; // 20 seconds
cricket::Port::CandidateOrigin GetOrigin(cricket::Port* port,
cricket::Port* origin_port) {
@@ -85,9 +79,9 @@
// Combine local and remote preferences
ASSERT(a->local_candidate().preference() == a->port()->preference());
ASSERT(b->local_candidate().preference() == b->port()->preference());
- double a_pref = a->local_candidate().preference()
+ double a_pref = a->local_candidate().preference()
* a->remote_candidate().preference();
- double b_pref = b->local_candidate().preference()
+ double b_pref = b->local_candidate().preference()
* b->remote_candidate().preference();
// Now check combined preferences. Lower values get sorted last.
@@ -114,8 +108,8 @@
// Wraps the comparison connection into a less than operator that puts higher
// priority writable connections first.
class ConnectionCompare {
-public:
- bool operator()(const cricket::Connection *ca,
+ public:
+ bool operator()(const cricket::Connection *ca,
const cricket::Connection *cb) {
cricket::Connection* a = const_cast<cricket::Connection*>(ca);
cricket::Connection* b = const_cast<cricket::Connection*>(cb);
@@ -126,11 +120,11 @@
return true;
if (cmp < 0)
return false;
-
+
// Otherwise, sort based on latency estimate.
return a->rtt() < b->rtt();
- // Should we bother checking for the last connection that last received
+ // Should we bother checking for the last connection that last received
// data? It would help rendezvous on the connection that is also receiving
// packets.
//
@@ -149,7 +143,7 @@
if (a_conn == b_conn)
return false;
- if ((a_conn == NULL) || (b_conn == NULL)) // don't think the latter should happen
+ if (!a_conn || !b_conn) // don't think the latter should happen
return true;
int prefs_cmp = CompareConnections(a_conn, b_conn);
@@ -166,14 +160,20 @@
namespace cricket {
P2PTransportChannel::P2PTransportChannel(const std::string &name,
- const std::string &session_type,
+ const std::string &content_type,
P2PTransport* transport,
- PortAllocator *allocator)
-: TransportChannelImpl(name, session_type), transport_(transport),
- allocator_(allocator), worker_thread_(talk_base::Thread::Current()),
- waiting_for_signaling_(false), error_(0), best_connection_(NULL),
- pinging_started_(false), sort_dirty_(false), was_writable_(false),
- was_timed_out_(true) {
+ PortAllocator *allocator) :
+ TransportChannelImpl(name, content_type),
+ transport_(transport),
+ allocator_(allocator),
+ worker_thread_(talk_base::Thread::Current()),
+ waiting_for_signaling_(false),
+ error_(0),
+ best_connection_(NULL),
+ pinging_started_(false),
+ sort_dirty_(false),
+ was_writable_(false),
+ was_timed_out_(true) {
}
P2PTransportChannel::~P2PTransportChannel() {
@@ -207,7 +207,7 @@
ASSERT(worker_thread_ == talk_base::Thread::Current());
// Kick off an allocator session
- OnAllocate();
+ Allocate();
// Start pinging as the ports come in.
thread()->Post(this, MSG_PING);
@@ -242,7 +242,7 @@
// If we allocated before, start a new one now.
if (transport_->connect_requested())
- OnAllocate();
+ Allocate();
// Start pinging as the ports come in.
thread()->Clear(this);
@@ -279,7 +279,7 @@
// candidates that we were given so far.
std::vector<RemoteCandidate>::iterator iter;
- for (iter = remote_candidates_.begin(); iter != remote_candidates_.end();
+ for (iter = remote_candidates_.begin(); iter != remote_candidates_.end();
++iter)
CreateConnection(port, *iter, iter->origin_port(), false);
@@ -290,12 +290,11 @@
void P2PTransportChannel::OnCandidatesReady(
PortAllocatorSession *session, const std::vector<Candidate>& candidates) {
for (size_t i = 0; i < candidates.size(); ++i) {
- buzz::XmlElement* msg = transport_->TranslateCandidate(candidates[i]);
- SignalChannelMessage(this, msg);
+ SignalCandidateReady(this, candidates[i]);
}
}
-// Handle stun packets
+// Handle stun packets
void P2PTransportChannel::OnUnknownAddress(
Port *port, const talk_base::SocketAddress &address, StunMessage *stun_msg,
const std::string &remote_username) {
@@ -318,7 +317,7 @@
// This sometimes happens if a binding response comes in before the ACCEPT
// message. It is totally valid; the retry state machine will try again.
- port->SendBindingErrorResponse(stun_msg, address,
+ port->SendBindingErrorResponse(stun_msg, address,
STUN_ERROR_STALE_CREDENTIALS, STUN_ERROR_REASON_STALE_CREDENTIALS);
delete stun_msg;
return;
@@ -330,7 +329,7 @@
Candidate new_remote_candidate = *candidate;
new_remote_candidate.set_address(address);
- //new_remote_candidate.set_protocol(port->protocol());
+ // new_remote_candidate.set_protocol(port->protocol());
// This remote username exists. Now create connections using this candidate,
// and resort
@@ -354,24 +353,18 @@
delete stun_msg;
}
-// We received a candidate from the other side, make connections so we
-// can try to use these remote candidates with our local candidates.
-void P2PTransportChannel::OnChannelMessage(const buzz::XmlElement* msg) {
+void P2PTransportChannel::OnCandidate(const Candidate& candidate) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
- Candidate remote_candidate;
- bool valid = transport_->ParseCandidate(NULL, msg, &remote_candidate);
- ASSERT(valid);
-
// Create connections to this remote candidate.
- CreateConnections(remote_candidate, NULL, false);
+ CreateConnections(candidate, NULL, false);
// Resort the connections list, which may have new elements.
SortConnections();
}
// Creates connections from all of the ports that we care about to the given
-// remote candidate. The return value is true iff we created a connection from
+// remote candidate. The return value is true if we created a connection from
// the origin port.
bool P2PTransportChannel::CreateConnections(const Candidate &remote_candidate,
Port* origin_port,
@@ -395,7 +388,7 @@
}
if ((origin_port != NULL) &&
- find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) {
+ std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) {
if (CreateConnection(origin_port, remote_candidate, origin_port, readable))
created = true;
}
@@ -435,6 +428,9 @@
this, &P2PTransportChannel::OnConnectionStateChange);
connection->SignalDestroyed.connect(
this, &P2PTransportChannel::OnConnectionDestroyed);
+
+ LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", ("
+ << connections_.size() << " total)";
}
// If we are readable, it is because we are creating this in response to a
@@ -499,6 +495,20 @@
return sent;
}
+// Begin allocate (or immediately re-allocate, if MSG_ALLOCATE pending)
+void P2PTransportChannel::Allocate() {
+ CancelPendingAllocate();
+ // Time for a new allocator, lets make sure we have a signalling channel
+ // to communicate candidates through first.
+ waiting_for_signaling_ = true;
+ SignalRequestSignaling();
+}
+
+// Cancels the pending allocate, if any.
+void P2PTransportChannel::CancelPendingAllocate() {
+ thread()->Clear(this, MSG_ALLOCATE);
+}
+
// Monitor connection states
void P2PTransportChannel::UpdateConnectionStates() {
uint32 now = talk_base::Time();
@@ -518,7 +528,7 @@
}
// Sort the available connections to find the best one. We also monitor
-// the number of available connections and the current state so that we
+// the number of available connections and the current state so that we
// can possibly kick off more allocators (for more connections).
void P2PTransportChannel::SortConnections() {
ASSERT(worker_thread_ == talk_base::Thread::Current());
@@ -615,7 +625,7 @@
// use it.
best_connection_ = conn;
if (best_connection_) {
- LOG_J(LS_VERBOSE, this) << "New best connection: " << conn->ToString();
+ LOG_J(LS_INFO, this) << "New best connection: " << conn->ToString();
SignalRouteChange(this, best_connection_->remote_candidate().address());
}
}
@@ -623,10 +633,12 @@
void P2PTransportChannel::UpdateChannelState() {
// The Handle* functions already set the writable state. We'll just double-
// check it here.
- bool writable =
- (best_connection_ != NULL) &&
- (best_connection_->write_state() == Connection::STATE_WRITABLE);
+ bool writable = ((best_connection_ != NULL) &&
+ (best_connection_->write_state() ==
+ Connection::STATE_WRITABLE));
ASSERT(writable == this->writable());
+ if (writable != this->writable())
+ LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch";
bool readable = false;
for (uint32 i = 0; i < connections_.size(); ++i) {
@@ -650,7 +662,7 @@
}
// Stop further allocations.
- thread()->Clear(this, MSG_ALLOCATE);
+ CancelPendingAllocate();
}
// We're writable, obviously we aren't timed out
@@ -669,7 +681,7 @@
if (was_writable_) {
// If we were writable, let's kick off an allocator session immediately
was_writable_ = false;
- OnAllocate();
+ Allocate();
}
// We were connecting, obviously not ALL timed out.
@@ -687,7 +699,7 @@
// We weren't timed out before, so kick off an allocator now (we'll still
// be in the fully timed out state until the allocator actually gives back
// new ports)
- OnAllocate();
+ Allocate();
}
// NOTE: we start was_timed_out_ in the true state so that we don't get
@@ -722,7 +734,7 @@
else if (pmsg->message_id == MSG_PING)
OnPing();
else if (pmsg->message_id == MSG_ALLOCATE)
- OnAllocate();
+ Allocate();
else
ASSERT(false);
}
@@ -778,7 +790,7 @@
uint32 now = talk_base::Time();
if (best_connection_ &&
(best_connection_->write_state() == Connection::STATE_WRITABLE) &&
- (best_connection_->last_ping_sent()
+ (best_connection_->last_ping_sent()
+ MAX_CURRENT_WRITABLE_DELAY <= now)) {
return best_connection_;
}
@@ -826,7 +838,7 @@
// Remove this connection from the list.
std::vector<Connection*>::iterator iter =
- find(connections_.begin(), connections_.end(), connection);
+ std::find(connections_.begin(), connections_.end(), connection);
ASSERT(iter != connections_.end());
connections_.erase(iter);
@@ -850,7 +862,8 @@
ASSERT(worker_thread_ == talk_base::Thread::Current());
// Remove this port from the list (if we didn't drop it already).
- std::vector<Port*>::iterator iter = find(ports_.begin(), ports_.end(), port);
+ std::vector<Port*>::iterator iter =
+ std::find(ports_.begin(), ports_.end(), port);
if (iter != ports_.end())
ports_.erase(iter);
@@ -859,8 +872,8 @@
}
// We data is available, let listeners know
-void P2PTransportChannel::OnReadPacket(Connection *connection,
- const char *data, size_t len) {
+void P2PTransportChannel::OnReadPacket(Connection *connection,
+ const char *data, size_t len) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
// Let the client know of an incoming packet
@@ -892,20 +905,13 @@
return 0;
}
-// Time for a new allocator, lets make sure we have a signalling channel
-// to communicate candidates through first.
-void P2PTransportChannel::OnAllocate() {
- waiting_for_signaling_ = true;
- SignalRequestSignaling();
-}
-
// When the signalling channel is ready, we can really kick off the allocator
void P2PTransportChannel::OnSignalingReady() {
if (waiting_for_signaling_) {
waiting_for_signaling_ = false;
- AddAllocatorSession(allocator_->CreateSession(name(), session_type()));
+ AddAllocatorSession(allocator_->CreateSession(name(), content_type()));
thread()->PostDelayed(kAllocatePeriod, this, MSG_ALLOCATE);
}
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/p2ptransportchannel.h b/talk/p2p/base/p2ptransportchannel.h
old mode 100755
new mode 100644
index bea1537..805e159
--- a/talk/p2p/base/p2ptransportchannel.h
+++ b/talk/p2p/base/p2ptransportchannel.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -34,9 +34,10 @@
// When all of the available connections become invalid (non-writable), we
// kick off a process of determining more candidates and more connections.
//
-#ifndef _CRICKET_P2P_BASE_P2PTRANSPORTCHANNEL_H_
-#define _CRICKET_P2P_BASE_P2PTRANSPORTCHANNEL_H_
+#ifndef TALK_P2P_BASE_P2PTRANSPORTCHANNEL_H_
+#define TALK_P2P_BASE_P2PTRANSPORTCHANNEL_H_
+#include <map>
#include <vector>
#include <string>
#include "talk/base/sigslot.h"
@@ -63,11 +64,11 @@
// P2PTransportChannel manages the candidates and connection process to keep
// two P2P clients connected to each other.
-class P2PTransportChannel : public TransportChannelImpl,
+class P2PTransportChannel : public TransportChannelImpl,
public talk_base::MessageHandler {
public:
P2PTransportChannel(const std::string &name,
- const std::string &session_type,
+ const std::string &content_type,
P2PTransport* transport,
PortAllocator *allocator);
virtual ~P2PTransportChannel();
@@ -77,13 +78,16 @@
virtual void Connect();
virtual void Reset();
virtual void OnSignalingReady();
- virtual void OnChannelMessage(const buzz::XmlElement* msg);
// From TransportChannel:
virtual int SendPacket(const char *data, size_t len);
virtual int SetOption(talk_base::Socket::Option opt, int value);
virtual int GetError() { return error_; }
+ // This hack is here to allow the SocketMonitor to downcast to the
+ // P2PTransportChannel safely.
+ virtual P2PTransportChannel* GetP2PChannel() { return this; }
+
// These are used by the connection monitor.
sigslot::signal1<P2PTransportChannel*> SignalConnectionMonitor;
const std::vector<Connection *>& connections() const { return connections_; }
@@ -92,7 +96,11 @@
// Handler for internal messages.
virtual void OnMessage(talk_base::Message *pmsg);
+ virtual void OnCandidate(const Candidate& candidate);
+
private:
+ void Allocate();
+ void CancelPendingAllocate();
void UpdateConnectionStates();
void RequestSort();
void SortConnections();
@@ -102,22 +110,21 @@
void HandleNotWritable();
void HandleAllTimedOut();
Connection* GetBestConnectionOnNetwork(talk_base::Network* network);
- bool CreateConnections(const Candidate &remote_candidate, Port* origin_port,
+ bool CreateConnections(const Candidate &remote_candidate, Port* origin_port,
bool readable);
- bool CreateConnection(Port* port, const Candidate& remote_candidate,
+ bool CreateConnection(Port* port, const Candidate& remote_candidate,
Port* origin_port, bool readable);
- void RememberRemoteCandidate(const Candidate& remote_candidate,
+ void RememberRemoteCandidate(const Candidate& remote_candidate,
Port* origin_port);
- void OnUnknownAddress(Port *port, const talk_base::SocketAddress &addr,
- StunMessage *stun_msg,
+ void OnUnknownAddress(Port *port, const talk_base::SocketAddress &addr,
+ StunMessage *stun_msg,
const std::string &remote_username);
void OnPortReady(PortAllocatorSession *session, Port* port);
- void OnCandidatesReady(PortAllocatorSession *session,
+ void OnCandidatesReady(PortAllocatorSession *session,
const std::vector<Candidate>& candidates);
void OnConnectionStateChange(Connection *connection);
void OnConnectionDestroyed(Connection *connection);
void OnPortDestroyed(Port* port);
- void OnAllocate();
void OnReadPacket(Connection *connection, const char *data, size_t len);
void OnSort();
void OnPing();
@@ -141,8 +148,9 @@
std::vector<Connection *> connections_;
Connection *best_connection_;
std::vector<RemoteCandidate> remote_candidates_;
- bool pinging_started_; // indicates whether StartGetAllCandidates has been called
- bool sort_dirty_; // indicates whether another sort is needed right now
+ // indicates whether StartGetAllCandidates has been called
+ bool pinging_started_;
+ bool sort_dirty_; // indicates whether another sort is needed right now
bool was_writable_;
bool was_timed_out_;
typedef std::map<talk_base::Socket::Option, int> OptionMap;
@@ -151,6 +159,6 @@
DISALLOW_EVIL_CONSTRUCTORS(P2PTransportChannel);
};
-} // namespace cricket
+} // namespace cricket
-#endif // _CRICKET_P2P_BASE_P2PTRANSPORTCHANNEL_H_
+#endif // TALK_P2P_BASE_P2PTRANSPORTCHANNEL_H_
diff --git a/talk/p2p/base/parsing.cc b/talk/p2p/base/parsing.cc
new file mode 100644
index 0000000..1ece5d0
--- /dev/null
+++ b/talk/p2p/base/parsing.cc
@@ -0,0 +1,143 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/p2p/base/parsing.h"
+
+#include <stdlib.h>
+#include "talk/base/stringutils.h"
+
+namespace cricket {
+
+bool BadParse(const std::string& text, ParseError* err) {
+ if (err != NULL) {
+ err->text = text;
+ }
+ return false;
+}
+
+bool BadWrite(const std::string& text, WriteError* err) {
+ if (err != NULL) {
+ err->text = text;
+ }
+ return false;
+}
+
+std::string GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name,
+ const std::string& def) {
+ std::string val = elem->Attr(name);
+ return val.empty() ? def : val;
+}
+
+int GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name, int def) {
+ std::string val = elem->Attr(name);
+ return val.empty() ? def : atoi(val.c_str());
+}
+
+void AddXmlAttr(buzz::XmlElement* elem,
+ const buzz::QName& name, int n) {
+ char buf[32];
+ talk_base::sprintfn(buf, sizeof(buf), "%d", n);
+ elem->AddAttr(name, buf);
+}
+
+void SetXmlBody(buzz::XmlElement* elem, uint32 u) {
+ char buf[16];
+ talk_base::sprintfn(buf, sizeof(buf), "%u", u);
+ elem->SetBodyText(buf);
+}
+
+const buzz::XmlElement* GetXmlChild(const buzz::XmlElement* parent,
+ const std::string& name) {
+ for (const buzz::XmlElement* child = parent->FirstElement();
+ child != NULL;
+ child = child->NextElement()) {
+ if (child->Name().LocalPart() == name) {
+ return child;
+ }
+ }
+ return NULL;
+}
+
+bool RequireXmlChild(const buzz::XmlElement* parent,
+ const std::string& name,
+ const buzz::XmlElement** child,
+ ParseError* error) {
+ *child = GetXmlChild(parent, name);
+ if (*child == NULL) {
+ return BadParse("element '" + parent->Name().Merged() +
+ "' missing required child '" + name,
+ error);
+ } else {
+ return true;
+ }
+}
+
+bool RequireXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name,
+ std::string* value,
+ ParseError* error) {
+ if (!elem->HasAttr(name)) {
+ return BadParse("element '" + elem->Name().Merged() +
+ "' missing required attribute '"
+ + name.Merged() + "'",
+ error);
+ } else {
+ *value = elem->Attr(name);
+ return true;
+ }
+}
+
+void AddXmlChildren(buzz::XmlElement* parent,
+ const std::vector<buzz::XmlElement*>& children) {
+ for (std::vector<buzz::XmlElement*>::const_iterator iter = children.begin();
+ iter != children.end();
+ iter++) {
+ parent->AddElement(*iter);
+ }
+}
+
+void CopyXmlChildren(const buzz::XmlElement* source, buzz::XmlElement* dest) {
+ for (const buzz::XmlElement* child = source->FirstElement();
+ child != NULL;
+ child = child->NextElement()) {
+ dest->AddElement(new buzz::XmlElement(*child));
+ }
+}
+
+std::vector<buzz::XmlElement*> CopyOfXmlChildren(const buzz::XmlElement* elem) {
+ std::vector<buzz::XmlElement*> children;
+ for (const buzz::XmlElement* child = elem->FirstElement();
+ child != NULL;
+ child = child->NextElement()) {
+ children.push_back(new buzz::XmlElement(*child));
+ }
+ return children;
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/parsing.h b/talk/p2p/base/parsing.h
new file mode 100644
index 0000000..0ae7403
--- /dev/null
+++ b/talk/p2p/base/parsing.h
@@ -0,0 +1,102 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_P2P_BASE_PARSING_H_
+#define TALK_P2P_BASE_PARSING_H_
+
+#include <string>
+#include <vector>
+#include "talk/base/basictypes.h"
+#include "talk/xmllite/xmlelement.h" // Needed to delete ParseError.extra.
+
+namespace cricket {
+
+// We decided "bool Parse(in, out*, error*)" is generally the best
+// parse signature. "out Parse(in)" doesn't allow for errors.
+// "error* Parse(in, out*)" doesn't allow flexible memory management.
+
+// The error type for parsing.
+struct ParseError {
+ public:
+ // explains the error
+ std::string text;
+ // provide details about what wasn't parsable
+ const buzz::XmlElement* extra;
+
+ ParseError() : extra(NULL) {}
+
+ ~ParseError() {
+ delete extra;
+ }
+
+ void SetText(const std::string& text) {
+ this->text = text;
+ }
+};
+
+// The error type for writing.
+struct WriteError {
+ std::string text;
+
+ void SetText(const std::string& text) {
+ this->text = text;
+ }
+};
+
+// Convenience method for returning a message when parsing fails.
+bool BadParse(const std::string& text, ParseError* err);
+
+// Convenience method for returning a message when writing fails.
+bool BadWrite(const std::string& text, WriteError* error);
+
+// helper XML functions
+std::string GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name,
+ const std::string& def);
+int GetXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name, int def);
+void AddXmlAttr(buzz::XmlElement* elem,
+ const buzz::QName& name, int n);
+void SetXmlBody(buzz::XmlElement* elem, uint32 u);
+const buzz::XmlElement* GetXmlChild(const buzz::XmlElement* parent,
+ const std::string& name);
+bool RequireXmlChild(const buzz::XmlElement* parent,
+ const std::string& name,
+ const buzz::XmlElement** child,
+ ParseError* error);
+bool RequireXmlAttr(const buzz::XmlElement* elem,
+ const buzz::QName& name,
+ std::string* value,
+ ParseError* error);
+void AddXmlChildren(buzz::XmlElement* parent,
+ const std::vector<buzz::XmlElement*>& children);
+void CopyXmlChildren(const buzz::XmlElement* source, buzz::XmlElement* dest);
+std::vector<buzz::XmlElement*> CopyOfXmlChildren(const buzz::XmlElement* elem);
+
+} // namespace cricket
+
+#endif // TALK_P2P_BASE_PARSING_H_
diff --git a/talk/p2p/base/port.cc b/talk/p2p/base/port.cc
old mode 100755
new mode 100644
index b5395df..2aa66a4
--- a/talk/p2p/base/port.cc
+++ b/talk/p2p/base/port.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,10 +29,7 @@
#pragma warning(disable:4786)
#endif
-#include <errno.h>
-
#include <algorithm>
-#include <iostream>
#include <vector>
#include "talk/base/asyncudpsocket.h"
@@ -41,6 +38,7 @@
#include "talk/base/logging.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/socketadapters.h"
+#include "talk/base/stringutils.h"
#include "talk/p2p/base/common.h"
#include "talk/p2p/base/port.h"
@@ -53,19 +51,19 @@
namespace {
// The length of time we wait before timing out readability on a connection.
-const uint32 CONNECTION_READ_TIMEOUT = 30 * 1000; // 30 seconds
+const uint32 CONNECTION_READ_TIMEOUT = 30 * 1000; // 30 seconds
// The length of time we wait before timing out writability on a connection.
-const uint32 CONNECTION_WRITE_TIMEOUT = 15 * 1000; // 15 seconds
+const uint32 CONNECTION_WRITE_TIMEOUT = 15 * 1000; // 15 seconds
// The length of time we wait before we become unwritable.
-const uint32 CONNECTION_WRITE_CONNECT_TIMEOUT = 5 * 1000; // 5 seconds
+const uint32 CONNECTION_WRITE_CONNECT_TIMEOUT = 5 * 1000; // 5 seconds
// The number of pings that must fail to respond before we become unwritable.
const uint32 CONNECTION_WRITE_CONNECT_FAILURES = 5;
// This is the length of time that we wait for a ping response to come back.
-const int CONNECTION_RESPONSE_TIMEOUT = 5 * 1000; // 5 seconds
+const int CONNECTION_RESPONSE_TIMEOUT = 5 * 1000; // 5 seconds
// Determines whether we have seen at least the given maximum number of
// pings fail to have a response.
@@ -98,64 +96,56 @@
// We will restrict RTT estimates (when used for determining state) to be
// within a reasonable range.
-const uint32 MINIMUM_RTT = 100; // 0.1 seconds
-const uint32 MAXIMUM_RTT = 3000; // 3 seconds
+const uint32 MINIMUM_RTT = 100; // 0.1 seconds
+const uint32 MAXIMUM_RTT = 3000; // 3 seconds
// When we don't have any RTT data, we have to pick something reasonable. We
// use a large value just in case the connection is really slow.
const uint32 DEFAULT_RTT = MAXIMUM_RTT;
-// Computes our estimate of the RTT given the current estimate and the number
-// of data points on which it is based.
-inline uint32 ConservativeRTTEstimate(uint32 rtt, uint32 rtt_data_points) {
- if (rtt_data_points == 0)
- return DEFAULT_RTT;
- else
- return talk_base::_max(MINIMUM_RTT, talk_base::_min(MAXIMUM_RTT, 2 * rtt));
+// Computes our estimate of the RTT given the current estimate.
+inline uint32 ConservativeRTTEstimate(uint32 rtt) {
+ return talk_base::_max(MINIMUM_RTT, talk_base::_min(MAXIMUM_RTT, 2 * rtt));
}
// Weighting of the old rtt value to new data.
-const int RTT_RATIO = 3; // 3 : 1
+const int RTT_RATIO = 3; // 3 : 1
// The delay before we begin checking if this port is useless.
-const int kPortTimeoutDelay = 30 * 1000; // 30 seconds
+const int kPortTimeoutDelay = 30 * 1000; // 30 seconds
const uint32 MSG_CHECKTIMEOUT = 1;
const uint32 MSG_DELETE = 1;
-
}
namespace cricket {
-static const char * const PROTO_NAMES[PROTO_LAST+1] = { "udp", "tcp", "ssltcp" };
+static const char* const PROTO_NAMES[] = { "udp", "tcp", "ssltcp" };
-const char * ProtoToString(ProtocolType proto) {
+const char* ProtoToString(ProtocolType proto) {
return PROTO_NAMES[proto];
}
-bool StringToProto(const char * value, ProtocolType& proto) {
- for (size_t i=0; i<=PROTO_LAST; ++i) {
+bool StringToProto(const char* value, ProtocolType* proto) {
+ for (size_t i = 0; i <= PROTO_LAST; ++i) {
if (strcmp(PROTO_NAMES[i], value) == 0) {
- proto = static_cast<ProtocolType>(i);
+ *proto = static_cast<ProtocolType>(i);
return true;
}
}
return false;
}
-std::string Port::agent_;
-talk_base::ProxyInfo Port::proxy_;
-
-Port::Port(talk_base::Thread* thread, const std::string& type,
+Port::Port(talk_base::Thread* thread, const std::string& type,
talk_base::SocketFactory* factory, talk_base::Network* network)
: thread_(thread), factory_(factory), type_(type), network_(network),
preference_(-1), lifetime_(LT_PRESTART), enable_port_packets_(false) {
-
if (factory_ == NULL)
factory_ = thread_->socketserver();
- set_username_fragment(CreateRandomString(16));
- set_password(CreateRandomString(16));
+ set_username_fragment(talk_base::CreateRandomString(16));
+ set_password(talk_base::CreateRandomString(16));
+ LOG_J(LS_INFO, this) << "Port created";
}
Port::~Port() {
@@ -227,6 +217,10 @@
} else if (msg->type() == STUN_BINDING_REQUEST) {
SignalUnknownAddress(this, addr, msg, remote_username);
} else {
+ // NOTE(tschmelcher): This is benign. It occurs if we pruned a
+ // connection for this port while it had STUN requests in flight, because
+ // we then get back responses for them, which this code correctly does not
+ // handle.
LOG_J(LS_ERROR, this) << "Received unexpected STUN message type ("
<< msg->type() << ") from unknown address ("
<< addr.ToString() << ")";
@@ -235,18 +229,16 @@
}
void Port::SendBindingRequest(Connection* conn) {
-
// Construct the request message.
-
StunMessage request;
request.SetType(STUN_BINDING_REQUEST);
- request.SetTransactionID(CreateRandomString(16));
+ request.SetTransactionID(talk_base::CreateRandomString(16));
StunByteStringAttribute* username_attr =
StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
std::string username = conn->remote_candidate().username();
username.append(username_frag_);
- username_attr->CopyBytes(username.c_str(), (uint16)username.size());
+ username_attr->CopyBytes(username.c_str(), username.size());
request.AddAttribute(username_attr);
// Send the request message.
@@ -257,7 +249,7 @@
}
bool Port::GetStunMessage(const char* data, size_t size,
- const talk_base::SocketAddress& addr,
+ const talk_base::SocketAddress& addr,
StunMessage *& msg, std::string& remote_username) {
// NOTE: This could clearly be optimized to avoid allocating any memory.
// However, at the data rates we'll be looking at on the client side,
@@ -283,12 +275,15 @@
remote_frag_len -= static_cast<int>(username_frag_.size());
if (stun_msg->type() == STUN_BINDING_REQUEST) {
- if ((remote_frag_len < 0)
- || (std::memcmp(username_attr->bytes(),
- username_frag_.c_str(), username_frag_.size()) != 0)) {
+ if (remote_frag_len < 0) {
+ // Username not present or corrupted, don't reply.
+ LOG_J(LS_ERROR, this) << "Received STUN request without username";
+ return true;
+ } else if (std::memcmp(username_attr->bytes(), username_frag_.c_str(),
+ username_frag_.size()) != 0) {
LOG_J(LS_ERROR, this) << "Received STUN request with bad username";
SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST,
- STUN_ERROR_REASON_BAD_REQUEST);
+ STUN_ERROR_REASON_BAD_REQUEST);
return true;
}
@@ -296,10 +291,19 @@
username_attr->bytes() + username_attr->length());
} else if ((stun_msg->type() == STUN_BINDING_RESPONSE)
|| (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) {
- if ((remote_frag_len < 0)
- || (std::memcmp(username_attr->bytes() + remote_frag_len,
- username_frag_.c_str(), username_frag_.size()) != 0)) {
- LOG_J(LS_ERROR, this) << "Received STUN response with bad username";
+ if (remote_frag_len < 0) {
+ // NOTE(tschmelcher): This is benign. It occurs when the response to a
+ // StunBindingRequest to the real STUN server (which involves no
+ // usernames) took too long to reach us and so the base StunRequest
+ // re-sent itself, resulting in us getting an extraneous second response
+ // that gets forwarded on to this code and correctly discarded.
+ LOG_J(LS_ERROR, this) << "Received STUN response without username";
+ // Do not send error response to a response
+ return true;
+ } else if (std::memcmp(username_attr->bytes() + remote_frag_len,
+ username_frag_.c_str(),
+ username_frag_.size()) != 0) {
+ LOG_J(LS_ERROR, this) << "Received STUN response with bad username";
// Do not send error response to a response
return true;
}
@@ -335,15 +339,18 @@
void Port::SendBindingResponse(
StunMessage* request, const talk_base::SocketAddress& addr) {
- assert(request->type() == STUN_BINDING_REQUEST);
+ ASSERT(request->type() == STUN_BINDING_REQUEST);
// Retrieve the username from the request.
const StunByteStringAttribute* username_attr =
request->GetByteString(STUN_ATTR_USERNAME);
- assert(username_attr);
+ ASSERT(username_attr != NULL);
+ if (username_attr == NULL) {
+ // No valid username, skip the response.
+ return;
+ }
// Fill in the response message.
-
StunMessage response;
response.SetType(STUN_BINDING_RESPONSE);
response.SetTransactionID(request->transaction_id());
@@ -369,7 +376,7 @@
// The fact that we received a successful request means that this connection
// (if one exists) should now be readable.
Connection* conn = GetConnection(addr);
- assert(conn);
+ ASSERT(conn != NULL);
if (conn)
conn->ReceivedPing();
}
@@ -378,16 +385,19 @@
StunMessage* request, const talk_base::SocketAddress& addr, int error_code,
const std::string& reason) {
- assert(request->type() == STUN_BINDING_REQUEST);
+ ASSERT(request->type() == STUN_BINDING_REQUEST);
// Retrieve the username from the request. If it didn't have one, we
// shouldn't be responding at all.
const StunByteStringAttribute* username_attr =
request->GetByteString(STUN_ATTR_USERNAME);
- assert(username_attr);
+ ASSERT(username_attr != NULL);
+ if (username_attr == NULL) {
+ // No valid username, skip the response.
+ return;
+ }
// Fill in the response message.
-
StunMessage response;
response.SetType(STUN_BINDING_ERROR_RESPONSE);
response.SetTransactionID(request->transaction_id());
@@ -411,37 +421,42 @@
talk_base::AsyncPacketSocket* Port::CreatePacketSocket(ProtocolType proto) {
if (proto == PROTO_UDP) {
- return new talk_base::AsyncUDPSocket(
- factory_->CreateAsyncSocket(SOCK_DGRAM));
- } else if ((proto == PROTO_TCP) || (proto == PROTO_SSLTCP)) {
- talk_base::AsyncSocket * socket = factory_->CreateAsyncSocket(SOCK_STREAM);
- switch (proxy().type) {
- case talk_base::PROXY_NONE:
- break;
- case talk_base::PROXY_SOCKS5:
+ // UDP sockets are simple.
+ return talk_base::AsyncUDPSocket::Create(factory_);
+ } else if (proto == PROTO_TCP || proto == PROTO_SSLTCP) {
+ // Create the base TCP socket. Bail out if this fails.
+ talk_base::AsyncSocket* socket = factory_->CreateAsyncSocket(SOCK_STREAM);
+ if (!socket) {
+ return NULL;
+ }
+
+ // If using a proxy, wrap the socket in a proxy socket.
+ if (proxy().type == talk_base::PROXY_SOCKS5) {
socket = new talk_base::AsyncSocksProxySocket(
socket, proxy().address, proxy().username, proxy().password);
- break;
- case talk_base::PROXY_HTTPS:
- default:
+ } else if (proxy().type == talk_base::PROXY_HTTPS) {
socket = new talk_base::AsyncHttpsProxySocket(
- socket, user_agent(), proxy().address, proxy().username,
- proxy().password);
- break;
+ socket, user_agent(), proxy().address,
+ proxy().username, proxy().password);
}
+
+ // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
if (proto == PROTO_SSLTCP) {
socket = new talk_base::AsyncSSLSocket(socket);
}
+
+ // Finally, wrap that socket in a TCP packet socket.
+ // [Insert obligatory Taco Town reference here]
return new talk_base::AsyncTCPSocket(socket);
} else {
- LOG_J(LS_INFO, this) << "Unknown protocol (" << proto << ")";
- return 0;
+ LOG_J(LS_ERROR, this) << "Unknown protocol (" << proto << ")";
+ return NULL;
}
}
void Port::OnMessage(talk_base::Message *pmsg) {
- assert(pmsg->message_id == MSG_CHECKTIMEOUT);
- assert(lifetime_ == LT_PRETIMEOUT);
+ ASSERT(pmsg->message_id == MSG_CHECKTIMEOUT);
+ ASSERT(lifetime_ == LT_PRETIMEOUT);
lifetime_ = LT_POSTTIMEOUT;
CheckTimeout();
}
@@ -468,15 +483,16 @@
}
void Port::OnConnectionDestroyed(Connection* conn) {
- AddressMap::iterator iter = connections_.find(conn->remote_candidate().address());
- assert(iter != connections_.end());
+ AddressMap::iterator iter =
+ connections_.find(conn->remote_candidate().address());
+ ASSERT(iter != connections_.end());
connections_.erase(iter);
CheckTimeout();
}
void Port::Destroy() {
- assert(connections_.empty());
+ ASSERT(connections_.empty());
LOG_J(LS_INFO, this) << "Port deleted";
SignalDestroyed(this);
delete this;
@@ -494,8 +510,8 @@
// A ConnectionRequest is a simple STUN ping used to determine writability.
class ConnectionRequest : public StunRequest {
-public:
- ConnectionRequest(Connection* connection) : connection_(connection) {
+ public:
+ explicit ConnectionRequest(Connection* connection) : connection_(connection) {
}
virtual ~ConnectionRequest() {
@@ -507,7 +523,7 @@
StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
std::string username = connection_->remote_candidate().username();
username.append(connection_->port()->username_fragment());
- username_attr->CopyBytes(username.c_str(), (uint16)username.size());
+ username_attr->CopyBytes(username.c_str(), username.size());
request->AddAttribute(username_attr);
}
@@ -520,6 +536,7 @@
}
virtual void OnTimeout() {
+ LOG_J(LS_VERBOSE, connection_) << "Timing-out STUN ping " << id();
}
virtual int GetNextDelay() {
@@ -529,7 +546,7 @@
return CONNECTION_RESPONSE_TIMEOUT;
}
-private:
+ private:
Connection* connection_;
};
@@ -537,19 +554,16 @@
// Connection
//
-Connection::Connection(Port* port, size_t index, const Candidate& remote_candidate)
- : requests_(port->thread()), port_(port), local_candidate_index_(index),
+Connection::Connection(Port* port, size_t index,
+ const Candidate& remote_candidate)
+ : port_(port), local_candidate_index_(index),
remote_candidate_(remote_candidate), read_state_(STATE_READ_TIMEOUT),
write_state_(STATE_WRITE_CONNECT), connected_(true), pruned_(false),
- rtt_(0), rtt_data_points_(0), last_ping_sent_(0), last_ping_received_(0),
- recv_total_bytes_(0), recv_bytes_second_(0),
- last_recv_bytes_second_time_((uint32)-1), last_recv_bytes_second_calc_(0),
- sent_total_bytes_(0), sent_bytes_second_(0),
- last_sent_bytes_second_time_((uint32)-1), last_sent_bytes_second_calc_(0),
- reported_(false) {
-
+ requests_(port->thread()), rtt_(DEFAULT_RTT),
+ last_ping_sent_(0), last_ping_received_(0), reported_(false) {
// Wire up to send stun packets
requests_.SignalSendPacket.connect(this, &Connection::OnSendStunPacket);
+ LOG_J(LS_INFO, this) << "Connection created";
}
Connection::~Connection() {
@@ -558,7 +572,7 @@
const Candidate& Connection::local_candidate() const {
if (local_candidate_index_ < port_->candidates().size())
return port_->candidates()[local_candidate_index_];
- assert(false);
+ ASSERT(false);
static Candidate foo;
return foo;
}
@@ -602,13 +616,13 @@
const talk_base::SocketAddress& addr(remote_candidate_.address());
if (!port_->GetStunMessage(data, size, addr, msg, remote_username)) {
// The packet did not parse as a valid STUN message
-
+
// If this connection is readable, then pass along the packet.
if (read_state_ == STATE_READABLE) {
// readable means data from this address is acceptable
// Send it on!
- recv_total_bytes_ += size;
+ recv_rate_tracker_.Update(size);
SignalReadPacket(this, data, size);
// If timed out sending writability checks, start up again
@@ -657,7 +671,7 @@
break;
default:
- assert(false);
+ ASSERT(false);
break;
}
@@ -702,7 +716,17 @@
// Before timing out writability, we give a fixed amount of time. This is to
// allow for changes in network conditions.
- uint32 rtt = ConservativeRTTEstimate(rtt_, rtt_data_points_);
+ uint32 rtt = ConservativeRTTEstimate(rtt_);
+
+ std::string pings;
+ for (size_t i = 0; i < pings_since_last_response_.size(); ++i) {
+ char buf[32];
+ talk_base::sprintfn(buf, sizeof(buf), "%u",
+ pings_since_last_response_[i]);
+ pings.append(buf).append(" ");
+ }
+ LOG_J(LS_VERBOSE, this) << "UpdateState(): pings_since_last_response_ = " <<
+ pings << ", rtt = " << rtt << ", now = " << now;
if ((write_state_ == STATE_WRITABLE) &&
TooManyFailures(pings_since_last_response_,
@@ -724,10 +748,12 @@
}
void Connection::Ping(uint32 now) {
- assert(connected_);
+ ASSERT(connected_);
last_ping_sent_ = now;
pings_since_last_response_.push_back(now);
- requests_.Send(new ConnectionRequest(this));
+ ConnectionRequest *req = new ConnectionRequest(this);
+ LOG_J(LS_VERBOSE, this) << "Sending STUN ping " << req->id() << " at " << now;
+ requests_.Send(req);
}
void Connection::ReceivedPing() {
@@ -737,33 +763,36 @@
std::string Connection::ToString() const {
const char CONNECT_STATE_ABBREV[2] = {
- '-', // not connected (false)
- 'C', // connected (true)
+ '-', // not connected (false)
+ 'C', // connected (true)
};
const char READ_STATE_ABBREV[2] = {
- 'R', // STATE_READABLE
- '-', // STATE_READ_TIMEOUT
+ 'R', // STATE_READABLE
+ '-', // STATE_READ_TIMEOUT
};
const char WRITE_STATE_ABBREV[3] = {
- 'W', // STATE_WRITABLE
- 'w', // STATE_WRITE_CONNECT
- '-', // STATE_WRITE_TIMEOUT
+ 'W', // STATE_WRITABLE
+ 'w', // STATE_WRITE_CONNECT
+ '-', // STATE_WRITE_TIMEOUT
};
const Candidate& local = local_candidate();
const Candidate& remote = remote_candidate();
std::stringstream ss;
ss << "Conn[" << local.generation()
- << ":" << local.name() << ":" << local.type() << ":" << local.address().ToString()
- << "->" << remote.name() << ":" << remote.type() << ":" << remote.address().ToString()
- << "|"
+ << ":" << local.name() << ":" << local.type() << ":"
+ << local.protocol() << ":" << local.address().ToString()
+ << "->" << remote.name() << ":" << remote.type() << ":"
+ << remote.protocol() << ":" << remote.address().ToString()
+ << "|"
<< CONNECT_STATE_ABBREV[connected()]
<< READ_STATE_ABBREV[read_state()]
<< WRITE_STATE_ABBREV[write_state()]
- << "]";
+ << "|" << rtt_ << "]";
return ss.str();
}
-void Connection::OnConnectionRequestResponse(StunMessage *response, uint32 rtt) {
+void Connection::OnConnectionRequestResponse(StunMessage* response,
+ uint32 rtt) {
// We have a potentially valid reply from the remote address.
// The packet must include a username that ends with our fragment,
// since it is a response.
@@ -809,13 +838,26 @@
// it, we can always prune it again.
set_write_state(STATE_WRITABLE);
+ std::string pings;
+ for (size_t i = 0; i < pings_since_last_response_.size(); ++i) {
+ char buf[32];
+ talk_base::sprintfn(buf, sizeof(buf), "%u",
+ pings_since_last_response_[i]);
+ pings.append(buf).append(" ");
+ }
+ LOG_J(LS_VERBOSE, this) << "OnConnectionRequestResponse(): "
+ "pings_since_last_response_ = " << pings << ", rtt = " << rtt;
+
pings_since_last_response_.clear();
rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1);
- rtt_data_points_ += 1;
+
+ LOG_J(LS_VERBOSE, this) << "Received STUN ping response " <<
+ response->transaction_id() << " after rtt = " << rtt;
}
}
-void Connection::OnConnectionRequestErrorResponse(StunMessage *response, uint32 rtt) {
+void Connection::OnConnectionRequestErrorResponse(StunMessage *response,
+ uint32 rtt) {
const StunErrorCodeAttribute* error = response->GetErrorCode();
uint32 error_code = error ? error->error_code() : STUN_ERROR_GLOBAL_FAILURE;
@@ -827,6 +869,7 @@
// Race failure, retry
} else {
// This is not a valid connection.
+ LOG_J(LS_ERROR, this) << "Received STUN error response; killing connection";
set_write_state(STATE_WRITE_TIMEOUT);
}
}
@@ -843,7 +886,7 @@
}
void Connection::OnMessage(talk_base::Message *pmsg) {
- assert(pmsg->message_id == MSG_DELETE);
+ ASSERT(pmsg->message_id == MSG_DELETE);
LOG_J(LS_INFO, this) << "Connection deleted";
SignalDestroyed(this);
@@ -851,60 +894,23 @@
}
size_t Connection::recv_bytes_second() {
- // Snapshot bytes / second calculator
-
- uint32 current_time = talk_base::Time();
- if (last_recv_bytes_second_time_ != (uint32)-1) {
- int delta = talk_base::TimeDiff(current_time, last_recv_bytes_second_time_);
- if (delta >= 1000) {
- int fraction_time = delta % 1000;
- int seconds_time = delta - fraction_time;
- int fraction_bytes = (int)(recv_total_bytes_ - last_recv_bytes_second_calc_) * fraction_time / delta;
- recv_bytes_second_ = (recv_total_bytes_ - last_recv_bytes_second_calc_ - fraction_bytes) * seconds_time / delta;
- last_recv_bytes_second_time_ = current_time - fraction_time;
- last_recv_bytes_second_calc_ = recv_total_bytes_ - fraction_bytes;
- }
- }
- if (last_recv_bytes_second_time_ == (uint32)-1) {
- last_recv_bytes_second_time_ = current_time;
- last_recv_bytes_second_calc_ = recv_total_bytes_;
- }
-
- return recv_bytes_second_;
+ return recv_rate_tracker_.bytes_second();
}
size_t Connection::recv_total_bytes() {
- return recv_total_bytes_;
+ return recv_rate_tracker_.total_bytes();
}
size_t Connection::sent_bytes_second() {
- // Snapshot bytes / second calculator
-
- uint32 current_time = talk_base::Time();
- if (last_sent_bytes_second_time_ != (uint32)-1) {
- int delta = talk_base::TimeDiff(current_time, last_sent_bytes_second_time_);
- if (delta >= 1000) {
- int fraction_time = delta % 1000;
- int seconds_time = delta - fraction_time;
- int fraction_bytes = (int)(sent_total_bytes_ - last_sent_bytes_second_calc_) * fraction_time / delta;
- sent_bytes_second_ = (sent_total_bytes_ - last_sent_bytes_second_calc_ - fraction_bytes) * seconds_time / delta;
- last_sent_bytes_second_time_ = current_time - fraction_time;
- last_sent_bytes_second_calc_ = sent_total_bytes_ - fraction_bytes;
- }
- }
- if (last_sent_bytes_second_time_ == (uint32)-1) {
- last_sent_bytes_second_time_ = current_time;
- last_sent_bytes_second_calc_ = sent_total_bytes_;
- }
-
- return sent_bytes_second_;
+ return send_rate_tracker_.bytes_second();
}
size_t Connection::sent_total_bytes() {
- return sent_total_bytes_;
+ return send_rate_tracker_.total_bytes();
}
-ProxyConnection::ProxyConnection(Port* port, size_t index, const Candidate& candidate)
+ProxyConnection::ProxyConnection(Port* port, size_t index,
+ const Candidate& candidate)
: Connection(port, index, candidate), error_(0) {
}
@@ -915,12 +921,56 @@
}
int sent = port_->SendTo(data, size, remote_candidate_.address(), true);
if (sent <= 0) {
- assert(sent < 0);
+ ASSERT(sent < 0);
error_ = port_->GetError();
} else {
- sent_total_bytes_ += sent;
+ send_rate_tracker_.Update(sent);
}
return sent;
}
-} // namespace cricket
+RateTracker::RateTracker()
+ : total_bytes_(0), bytes_second_(0),
+ last_bytes_second_time_(static_cast<uint32>(-1)),
+ last_bytes_second_calc_(0) {
+}
+
+size_t RateTracker::total_bytes() const {
+ return total_bytes_;
+}
+
+size_t RateTracker::bytes_second() {
+ // Snapshot bytes / second calculator. Determine how many seconds have
+ // elapsed since our last reference point. If over 1 second, establish
+ // a new reference point that is an integer number of seconds since the
+ // last one, and compute the bytes over that interval.
+
+ uint32 current_time = talk_base::Time();
+ if (last_bytes_second_time_ != static_cast<uint32>(-1)) {
+ int delta = talk_base::TimeDiff(current_time, last_bytes_second_time_);
+ if (delta >= 1000) {
+ int fraction_time = delta % 1000;
+ int seconds = delta / 1000;
+ int fraction_bytes =
+ static_cast<int>(total_bytes_ - last_bytes_second_calc_) *
+ fraction_time / delta;
+ // Compute "bytes received during the interval" / "seconds in interval"
+ bytes_second_ =
+ (total_bytes_ - last_bytes_second_calc_ - fraction_bytes) / seconds;
+ last_bytes_second_time_ = current_time - fraction_time;
+ last_bytes_second_calc_ = total_bytes_ - fraction_bytes;
+ }
+ }
+ if (last_bytes_second_time_ == static_cast<uint32>(-1)) {
+ last_bytes_second_time_ = current_time;
+ last_bytes_second_calc_ = total_bytes_;
+ }
+
+ return bytes_second_;
+}
+
+void RateTracker::Update(size_t bytes) {
+ total_bytes_ += bytes;
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/port.h b/talk/p2p/base/port.h
old mode 100755
new mode 100644
index 57c0727..88b15c6
--- a/talk/p2p/base/port.h
+++ b/talk/p2p/base/port.h
@@ -2,31 +2,35 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __PORT_H__
-#define __PORT_H__
+#ifndef TALK_P2P_BASE_PORT_H_
+#define TALK_P2P_BASE_PORT_H_
+
+#include <string>
+#include <vector>
+#include <map>
#include "talk/base/network.h"
#include "talk/base/socketaddress.h"
@@ -37,10 +41,6 @@
#include "talk/p2p/base/stun.h"
#include "talk/p2p/base/stunrequest.h"
-#include <string>
-#include <vector>
-#include <map>
-
namespace talk_base {
class AsyncPacketSocket;
}
@@ -49,30 +49,45 @@
class Connection;
-enum ProtocolType {
- PROTO_UDP,
- PROTO_TCP,
- PROTO_SSLTCP,
- PROTO_LAST = PROTO_SSLTCP
+enum ProtocolType {
+ PROTO_UDP,
+ PROTO_TCP,
+ PROTO_SSLTCP,
+ PROTO_LAST = PROTO_SSLTCP
};
-const char * ProtoToString(ProtocolType proto);
-bool StringToProto(const char * value, ProtocolType& proto);
+const char* ProtoToString(ProtocolType proto);
+bool StringToProto(const char* value, ProtocolType* proto);
struct ProtocolAddress {
talk_base::SocketAddress address;
ProtocolType proto;
- ProtocolAddress(const talk_base::SocketAddress& a, ProtocolType p)
+ ProtocolAddress(const talk_base::SocketAddress& a, ProtocolType p)
: address(a), proto(p) { }
};
+// Computes instantaneous bytes per second.
+class RateTracker {
+ public:
+ RateTracker();
+ size_t total_bytes() const;
+ size_t bytes_second();
+ void Update(size_t bytes);
+
+ private:
+ size_t total_bytes_;
+ size_t bytes_second_;
+ uint32 last_bytes_second_time_;
+ size_t last_bytes_second_calc_;
+};
+
// Represents a local communication mechanism that can be used to create
// connections to similar mechanisms of the other client. Subclasses of this
// one add support for specific mechanisms like local UDP ports.
class Port : public talk_base::MessageHandler, public sigslot::has_slots<> {
-public:
- Port(talk_base::Thread* thread, const std::string &type,
+ public:
+ Port(talk_base::Thread* thread, const std::string &type,
talk_base::SocketFactory* factory, talk_base::Network* network);
virtual ~Port();
@@ -81,7 +96,7 @@
// The factory used to create the sockets of this port.
talk_base::SocketFactory* socket_factory() const { return factory_; }
- void set_socket_factory(talk_base::SocketFactory* factory)
+ void set_socket_factory(talk_base::SocketFactory* factory)
{ factory_ = factory; }
// Each port is identified by a name (for debugging purposes).
@@ -91,8 +106,17 @@
// In order to establish a connection to this Port (so that real data can be
// sent through), the other side must send us a STUN binding request that is
// authenticated with this username and password.
+ // Fills in the username fragment and password. These will be initially set
+ // in the constructor to random values. Subclasses or tests can override.
+ // TODO: Change this to "username" rather than "username_fragment".
const std::string& username_fragment() const { return username_frag_; }
+ void set_username_fragment(const std::string& username) {
+ username_frag_ = username;
+ }
+
const std::string& password() const { return password_; }
+ void set_password(const std::string& password) { password_ = password; }
+
// A value in [0,1] that indicates the preference for this port versus other
// ports on this client. (Larger indicates more preference.)
@@ -125,14 +149,14 @@
// Returns a map containing all of the connections of this port, keyed by the
// remote address.
typedef std::map<talk_base::SocketAddress, Connection*> AddressMap;
- const AddressMap& connections() { return connections_; }
+ const AddressMap& connections() { return connections_; }
// Returns the connection to the given address or NULL if none exists.
Connection* GetConnection(const talk_base::SocketAddress& remote_addr);
// Creates a new connection to the given address.
enum CandidateOrigin { ORIGIN_THIS_PORT, ORIGIN_OTHER_PORT, ORIGIN_MESSAGE };
- virtual Connection* CreateConnection(const Candidate& remote_candidate,
+ virtual Connection* CreateConnection(const Candidate& remote_candidate,
CandidateOrigin origin) = 0;
// Called each time a connection is created.
@@ -141,22 +165,22 @@
// Sends the given packet to the given address, provided that the address is
// that of a connection or an address that has sent to us already.
virtual int SendTo(
- const void* data, size_t size, const talk_base::SocketAddress& addr,
+ const void* data, size_t size, const talk_base::SocketAddress& addr,
bool payload) = 0;
// Indicates that we received a successful STUN binding request from an
// address that doesn't correspond to any current connection. To turn this
// into a real connection, call CreateConnection.
- sigslot::signal4<Port*, const talk_base::SocketAddress&, StunMessage*,
+ sigslot::signal4<Port*, const talk_base::SocketAddress&, StunMessage*,
const std::string&> SignalUnknownAddress;
// Sends a response message (normal or error) to the given request. One of
// these methods should be called as a response to SignalUnknownAddress.
// NOTE: You MUST call CreateConnection BEFORE SendBindingResponse.
- void SendBindingResponse(StunMessage* request,
+ void SendBindingResponse(StunMessage* request,
const talk_base::SocketAddress& addr);
void SendBindingErrorResponse(
- StunMessage* request, const talk_base::SocketAddress& addr,
+ StunMessage* request, const talk_base::SocketAddress& addr,
int error_code, const std::string& reason);
// Indicates that errors occurred when performing I/O.
@@ -167,12 +191,13 @@
virtual int SetOption(talk_base::Socket::Option opt, int value) = 0;
virtual int GetError() = 0;
- static void set_proxy(const std::string& user_agent,
- const talk_base::ProxyInfo& proxy) {
- agent_ = user_agent; proxy_ = proxy;
+ void set_proxy(const std::string& user_agent,
+ const talk_base::ProxyInfo& proxy) {
+ user_agent_ = user_agent;
+ proxy_ = proxy;
}
- static const std::string& user_agent() { return agent_; }
- static const talk_base::ProxyInfo& proxy() { return proxy_; }
+ const std::string& user_agent() { return user_agent_; }
+ const talk_base::ProxyInfo& proxy() { return proxy_; }
talk_base::AsyncPacketSocket * CreatePacketSocket(ProtocolType proto);
@@ -200,7 +225,7 @@
// Debugging description of this port
std::string ToString() const;
-protected:
+ protected:
talk_base::Thread* thread_;
talk_base::SocketFactory* factory_;
std::string type_;
@@ -215,15 +240,8 @@
enum Lifetime { LT_PRESTART, LT_PRETIMEOUT, LT_POSTTIMEOUT } lifetime_;
bool enable_port_packets_;
- // Fills in the username fragment and password. These will be initially set
- // in the constructor to random values. Subclasses can override, though.
- void set_username_fragment(const std::string& username_fragment) {
- username_frag_ = username_fragment;
- }
- void set_password(const std::string& password) { password_ = password; }
-
// Fills in the local address of the port.
- void AddAddress(const talk_base::SocketAddress& address,
+ void AddAddress(const talk_base::SocketAddress& address,
const std::string& protocol, bool final);
// Adds the given connection to the list. (Deleting removes them.)
@@ -232,7 +250,7 @@
// Called when a packet is received from an unknown address that is not
// currently a connection. If this is an authenticated STUN binding request,
// then we will signal the client.
- void OnReadPacket(const char* data, size_t size,
+ void OnReadPacket(const char* data, size_t size,
const talk_base::SocketAddress& addr);
// Constructs a STUN binding request for the given connection and sends it.
@@ -243,28 +261,29 @@
// with this port's username fragment, msg will contain the parsed STUN
// message. Otherwise, the function may send a STUN response internally.
// remote_username contains the remote fragment of the STUN username.
- bool GetStunMessage(const char* data, size_t size,
+ bool GetStunMessage(const char* data, size_t size,
const talk_base::SocketAddress& addr,
StunMessage *& msg, std::string& remote_username);
friend class Connection;
-private:
+ private:
// Called when one of our connections deletes itself.
void OnConnectionDestroyed(Connection* conn);
// Checks if this port is useless, and hence, should be destroyed.
void CheckTimeout();
- static std::string agent_;
- static talk_base::ProxyInfo proxy_;
+ // Information to use when going through a proxy.
+ std::string user_agent_;
+ talk_base::ProxyInfo proxy_;
};
// Represents a communication link between a port on the local client and a
// port on the remote client.
-class Connection : public talk_base::MessageHandler,
+class Connection : public talk_base::MessageHandler,
public sigslot::has_slots<> {
-public:
+ public:
virtual ~Connection();
// The local port where this connection sends and receives packets.
@@ -278,16 +297,16 @@
const Candidate& remote_candidate() const { return remote_candidate_; }
enum ReadState {
- STATE_READABLE = 0, // we have received pings recently
- STATE_READ_TIMEOUT = 1 // we haven't received pings in a while
+ STATE_READABLE = 0, // we have received pings recently
+ STATE_READ_TIMEOUT = 1 // we haven't received pings in a while
};
ReadState read_state() const { return read_state_; }
enum WriteState {
- STATE_WRITABLE = 0, // we have received ping responses recently
- STATE_WRITE_CONNECT = 1, // we have had a few ping failures
- STATE_WRITE_TIMEOUT = 2 // we have had a large number of ping failures
+ STATE_WRITABLE = 0, // we have received ping responses recently
+ STATE_WRITE_CONNECT = 1, // we have had a few ping failures
+ STATE_WRITE_TIMEOUT = 2 // we have had a large number of ping failures
};
WriteState write_state() const { return write_state_; }
@@ -310,7 +329,7 @@
sigslot::signal1<Connection*> SignalDestroyed;
// The connection can send and receive packets asynchronously. This matches
- // the interface of AsyncPacketSocket, which may use UDP or TCP under the
+ // the interface of AsyncPacketSocket, which may use UDP or TCP under the
// covers.
virtual int Send(const void* data, size_t size) = 0;
@@ -350,7 +369,7 @@
bool reported() { return reported_; }
void set_reported(bool reported) { reported_ = reported;}
-protected:
+ protected:
Port* port_;
size_t local_candidate_index_;
Candidate remote_candidate_;
@@ -360,21 +379,13 @@
bool pruned_;
StunRequestManager requests_;
uint32 rtt_;
- uint32 rtt_data_points_;
- uint32 last_ping_sent_; // last time we sent a ping to the other side
- uint32 last_ping_received_; // last time we received a ping from the other
- // side
+ uint32 last_ping_sent_; // last time we sent a ping to the other side
+ uint32 last_ping_received_; // last time we received a ping from the other
+ // side
std::vector<uint32> pings_since_last_response_;
- size_t recv_total_bytes_;
- size_t recv_bytes_second_;
- uint32 last_recv_bytes_second_time_;
- size_t last_recv_bytes_second_calc_;
-
- size_t sent_total_bytes_;
- size_t sent_bytes_second_;
- uint32 last_sent_bytes_second_time_;
- size_t last_sent_bytes_second_calc_;
+ RateTracker recv_rate_tracker_;
+ RateTracker send_rate_tracker_;
// Callbacks from ConnectionRequest
void OnConnectionRequestResponse(StunMessage *response, uint32 rtt);
@@ -399,23 +410,22 @@
friend class Port;
friend class ConnectionRequest;
-private:
+ private:
bool reported_;
};
// ProxyConnection defers all the interesting work to the port
-
class ProxyConnection : public Connection {
-public:
+ public:
ProxyConnection(Port* port, size_t index, const Candidate& candidate);
virtual int Send(const void* data, size_t size);
virtual int GetError() { return error_; }
-private:
+ private:
int error_;
};
-} // namespace cricket
+} // namespace cricket
-#endif // __PORT_H__
+#endif // TALK_P2P_BASE_PORT_H_
diff --git a/talk/p2p/base/port_unittest.cc b/talk/p2p/base/port_unittest.cc
deleted file mode 100755
index 4687c19..0000000
--- a/talk/p2p/base/port_unittest.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-#include "talk/base/helpers.h"
-#include "talk/base/host.h"
-#include "talk/base/natserver.h"
-#include "talk/base/natsocketfactory.h"
-#include "talk/base/socketaddress.h"
-#include "talk/base/thread.h"
-#include "talk/base/virtualsocketserver.h"
-#include "talk/p2p/base/udpport.h"
-#include "talk/p2p/base/relayport.h"
-#include "talk/p2p/base/relayserver.h"
-#include "talk/p2p/base/stunport.h"
-#include "talk/p2p/base/stunserver.h"
-#include <iostream>
-
-using namespace cricket;
-
-const uint32 MSG_CONNECT = 1;
-const uint32 MSG_PREP_ADDRESS = 2;
-const uint32 MSG_CREATE_CONN = 3;
-const uint32 MSG_ACCEPT_CONN = 4;
-const uint32 MSG_PING = 5;
-
-Candidate GetCandidate(Port* port) {
- assert(port->candidates().size() == 1);
- return port->candidates()[0];
-}
-
-talk_base::SocketAddress GetAddress(Port* port) {
- return GetCandidate(port).address();
-}
-
-struct Foo : public talk_base::MessageHandler, public sigslot::has_slots<> {
- int count;
- talk_base::SocketAddress address;
- StunMessage* request;
- std::string remote_frag;
-
- talk_base::Thread* thread;
- Port* port1;
- Port* port2;
- Connection* conn;
-
- Foo(talk_base::Thread* th, Port* p1, Port* p2)
- : count(0), thread(th), port1(p1), port2(p2), conn(0) {
- }
-
- void OnAddressReady(Port* port) {
- count += 1;
- }
-
- void OnUnknownAddress(
- Port* port, const talk_base::SocketAddress& addr, StunMessage* msg,
- const std::string& rf) {
- assert(port == port1);
- if (!address.IsAny()) {
- assert(addr == address);
- delete request;
- }
- address = addr;
- request = msg;
- remote_frag = rf;
- }
-
- void OnMessage(talk_base::Message* pmsg) {
- assert(talk_base::Thread::Current() == thread);
-
- switch (pmsg->message_id) {
- case MSG_CONNECT:
- port1->SignalAddressReady.connect(this, &Foo::OnAddressReady);
- port1->SignalUnknownAddress.connect(this, &Foo::OnUnknownAddress);
- break;
-
- case MSG_PREP_ADDRESS:
- port1->PrepareAddress();
- break;
-
- case MSG_CREATE_CONN:
- conn = port1->CreateConnection(GetCandidate(port2), Port::ORIGIN_MESSAGE);
- assert(conn);
- conn->Ping(0);
- break;
-
- case MSG_PING:
- assert(conn);
- conn->Ping(0);
- break;
-
- case MSG_ACCEPT_CONN: {
- Candidate c = GetCandidate(port2);
- c.set_address(address);
- conn = port1->CreateConnection(c, Port::ORIGIN_MESSAGE);
- assert(conn);
- port1->SendBindingResponse(request, address);
- conn->Ping(0);
- delete request;
- break;
- }
-
- default:
- assert(false);
- break;
- }
- }
-};
-
-void test(talk_base::Thread* pthMain, const char* name1, Port* port1,
- talk_base::Thread* pthBack, const char* name2, Port* port2,
- bool accept = true, bool same_addr = true) {
- Foo* foo1 = new Foo(pthMain, port1, port2);
- Foo* foo2 = new Foo(pthBack, port2, port1);
-
- std::cout << "Test: " << name1 << " to " << name2 << ": ";
- std::cout.flush();
-
- pthBack->Start();
-
- pthMain->Post(foo1, MSG_CONNECT);
- pthBack->Post(foo2, MSG_CONNECT);
- pthMain->ProcessMessages(10);
- assert(foo1->count == 0);
- assert(foo2->count == 0);
-
- pthMain->Post(foo1, MSG_PREP_ADDRESS);
- pthMain->ProcessMessages(200);
- assert(foo1->count == 1);
-
- pthBack->Post(foo2, MSG_PREP_ADDRESS);
- pthMain->ProcessMessages(200);
- assert(foo2->count == 1);
-
- pthMain->Post(foo1, MSG_CREATE_CONN);
- pthMain->ProcessMessages(200);
-
- if (accept) {
-
- assert(foo1->address.IsAny());
- assert(foo2->remote_frag == port1->username_fragment());
- assert(!same_addr || (foo2->address == GetAddress(port1)));
-
- pthBack->Post(foo2, MSG_ACCEPT_CONN);
- pthMain->ProcessMessages(200);
-
- } else {
-
- assert(foo1->address.IsAny());
- assert(foo2->address.IsAny());
-
- pthBack->Post(foo2, MSG_CREATE_CONN);
- pthMain->ProcessMessages(200);
-
- if (same_addr) {
- assert(foo1->conn->read_state() == Connection::STATE_READABLE);
- assert(foo2->conn->write_state() == Connection::STATE_WRITABLE);
-
- // First connection may not be writable if the first ping did not get
- // through. So we will have to do another.
- if (foo1->conn->write_state() == Connection::STATE_WRITE_CONNECT) {
- pthMain->Post(foo1, MSG_PING);
- pthMain->ProcessMessages(200);
- }
- } else {
- assert(foo1->address.IsAny());
- assert(foo2->address.IsAny());
-
- pthMain->Post(foo1, MSG_PING);
- pthMain->ProcessMessages(200);
-
- assert(foo1->address.IsAny());
- assert(!foo2->address.IsAny());
-
- pthBack->Post(foo2, MSG_ACCEPT_CONN);
- pthMain->ProcessMessages(200);
- }
- }
-
- assert(foo1->conn->read_state() == Connection::STATE_READABLE);
- assert(foo1->conn->write_state() == Connection::STATE_WRITABLE);
- assert(foo2->conn->read_state() == Connection::STATE_READABLE);
- assert(foo2->conn->write_state() == Connection::STATE_WRITABLE);
-
- pthBack->Stop();
-
- delete port1;
- delete port2;
- delete foo1;
- delete foo2;
-
- std::cout << "PASS" << std::endl;
-}
-
-const talk_base::SocketAddress local_addr = talk_base::SocketAddress("127.0.0.1", 0);
-const talk_base::SocketAddress relay_int_addr = talk_base::SocketAddress("127.0.0.1", 5000);
-const talk_base::SocketAddress relay_ext_addr = talk_base::SocketAddress("127.0.0.1", 5001);
-const talk_base::SocketAddress stun_addr = talk_base::SocketAddress("127.0.0.1", STUN_SERVER_PORT);
-const talk_base::SocketAddress nat_addr = talk_base::SocketAddress("127.0.0.1", talk_base::NAT_SERVER_PORT);
-
-void test_udp() {
- talk_base::Thread* pthMain = talk_base::Thread::Current();
- talk_base::Thread* pthBack = new talk_base::Thread();
- talk_base::Network* network = new talk_base::Network("network", local_addr.ip());
-
- test(pthMain, "udp", new UDPPort(pthMain, NULL, network, local_addr),
- pthBack, "udp", new UDPPort(pthBack, NULL, network, local_addr));
-
- delete pthBack;
-}
-
-void test_relay() {
- talk_base::Thread* pthMain = talk_base::Thread::Current();
- talk_base::Thread* pthBack = new talk_base::Thread();
- talk_base::Network* network = new talk_base::Network("network", local_addr.ip());
-
- RelayServer relay_server(pthBack);
-
- talk_base::AsyncUDPSocket* int_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver());
- assert(int_socket->Bind(relay_int_addr) >= 0);
- relay_server.AddInternalSocket(int_socket);
-
- talk_base::AsyncUDPSocket* ext_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver());
- assert(ext_socket->Bind(relay_ext_addr) >= 0);
- relay_server.AddExternalSocket(ext_socket);
-
- std::string username = CreateRandomString(16);
- std::string password = CreateRandomString(16);
-
- RelayPort* rport =
- new RelayPort(pthBack, NULL, network, local_addr, username, password, "");
- rport->AddServerAddress(ProtocolAddress(relay_int_addr, PROTO_UDP));
-
- test(pthMain, "udp", new UDPPort(pthMain, NULL, network, local_addr),
- pthBack, "relay", rport);
-
- delete pthBack;
-}
-
-const char* NATName(talk_base::NATType type) {
- switch (type) {
- case talk_base::NAT_OPEN_CONE: return "open cone";
- case talk_base::NAT_ADDR_RESTRICTED: return "addr restricted";
- case talk_base::NAT_PORT_RESTRICTED: return "port restricted";
- case talk_base::NAT_SYMMETRIC: return "symmetric";
- default:
- assert(false);
- return 0;
- }
-}
-
-void test_stun(talk_base::NATType nat_type) {
- talk_base::Thread* pthMain = talk_base::Thread::Current();
- talk_base::Thread* pthBack = new talk_base::Thread();
- talk_base::Network* network = new talk_base::Network("network", local_addr.ip());
-
- talk_base::NATServer* nat = new talk_base::NATServer(
- nat_type, pthMain->socketserver(), nat_addr,
- pthMain->socketserver(), nat_addr);
- talk_base::NATSocketFactory* nat_factory =
- new talk_base::NATSocketFactory(pthMain->socketserver(), nat_addr);
-
- StunPort* stun_port =
- new StunPort(pthMain, nat_factory, network, local_addr, stun_addr);
-
- talk_base::AsyncUDPSocket* stun_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver());
- assert(stun_socket->Bind(stun_addr) >= 0);
- StunServer* stun_server = new StunServer(stun_socket);
-
- char name[256];
- sprintf(name, "stun (%s)", NATName(nat_type));
-
- test(pthMain, name, stun_port,
- pthBack, "udp", new UDPPort(pthBack, NULL, network, local_addr),
- true, nat_type != talk_base::NAT_SYMMETRIC);
-
- delete stun_server;
- delete stun_socket;
- delete nat;
- delete nat_factory;
- delete pthBack;
-}
-
-void test_stun(talk_base::NATType nat1_type, talk_base::NATType nat2_type) {
-
- talk_base::Thread* pthMain = talk_base::Thread::Current();
- talk_base::Thread* pthBack = new talk_base::Thread();
- talk_base::Network* network = new talk_base::Network("network", local_addr.ip());
-
- talk_base::SocketAddress local_addr1(talk_base::LocalHost().networks()[0]->ip(), 0);
- talk_base::SocketAddress local_addr2(talk_base::LocalHost().networks()[1]->ip(), 0);
-
- talk_base::SocketAddress nat1_addr(local_addr1.ip(), talk_base::NAT_SERVER_PORT);
- talk_base::SocketAddress nat2_addr(local_addr2.ip(), talk_base::NAT_SERVER_PORT);
-
- talk_base::SocketAddress stun1_addr(local_addr1.ip(), STUN_SERVER_PORT);
- talk_base::SocketAddress stun2_addr(local_addr2.ip(), STUN_SERVER_PORT);
-
- talk_base::NATServer* nat1 = new talk_base::NATServer(
- nat1_type, pthMain->socketserver(), nat1_addr,
- pthMain->socketserver(), nat1_addr);
- talk_base::NATSocketFactory* nat1_factory =
- new talk_base::NATSocketFactory(pthMain->socketserver(), nat1_addr);
-
- StunPort* stun1_port =
- new StunPort(pthMain, nat1_factory, network, local_addr1, stun1_addr);
-
- talk_base::NATServer* nat2 = new talk_base::NATServer(
- nat2_type, pthBack->socketserver(), nat2_addr,
- pthBack->socketserver(), nat2_addr);
- talk_base::NATSocketFactory* nat2_factory =
- new talk_base::NATSocketFactory(pthBack->socketserver(), nat2_addr);
-
- StunPort* stun2_port =
- new StunPort(pthMain, nat2_factory, network, local_addr2, stun2_addr);
-
- talk_base::AsyncUDPSocket* stun1_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver());
- assert(stun1_socket->Bind(stun_addr) >= 0);
- StunServer* stun1_server = new StunServer(stun1_socket);
-
- talk_base::AsyncUDPSocket* stun2_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver());
- assert(stun2_socket->Bind(stun2_addr) >= 0);
- StunServer* stun2_server = new StunServer(stun2_socket);
-
- char name1[256], name2[256];
- sprintf(name1, "stun (%s)", NATName(nat1_type));
- sprintf(name2, "stun (%s)", NATName(nat2_type));
-
- test(pthMain, name1, stun1_port,
- pthBack, name2, stun2_port,
- nat2_type == talk_base::NAT_OPEN_CONE, nat1_type != talk_base::NAT_SYMMETRIC);
-
- delete stun1_server;
- delete stun1_socket;
- delete stun2_server;
- delete stun2_socket;
- delete nat1;
- delete nat1_factory;
- delete nat2;
- delete nat2_factory;
- delete pthBack;
-}
-
-int main(int argc, char* argv[]) {
- InitRandom(NULL, 0);
-
- test_udp();
-
- test_relay();
-
- test_stun(talk_base::NAT_OPEN_CONE);
- test_stun(talk_base::NAT_ADDR_RESTRICTED);
- test_stun(talk_base::NAT_PORT_RESTRICTED);
- test_stun(talk_base::NAT_SYMMETRIC);
-
- test_stun(talk_base::NAT_OPEN_CONE, talk_base::NAT_OPEN_CONE);
- test_stun(talk_base::NAT_ADDR_RESTRICTED, talk_base::NAT_OPEN_CONE);
- test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_OPEN_CONE);
- test_stun(talk_base::NAT_SYMMETRIC, talk_base::NAT_OPEN_CONE);
-
- test_stun(talk_base::NAT_ADDR_RESTRICTED, talk_base::NAT_ADDR_RESTRICTED);
- test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_ADDR_RESTRICTED);
- test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_PORT_RESTRICTED);
- test_stun(talk_base::NAT_SYMMETRIC, talk_base::NAT_ADDR_RESTRICTED);
-
- return 0;
-}
diff --git a/talk/p2p/base/portallocator.h b/talk/p2p/base/portallocator.h
old mode 100755
new mode 100644
index 50f52cf..332326e
--- a/talk/p2p/base/portallocator.h
+++ b/talk/p2p/base/portallocator.h
@@ -81,6 +81,7 @@
class PortAllocator {
public:
PortAllocator() : flags_(kDefaultPortAllocatorFlags) {}
+ virtual ~PortAllocator() {}
virtual PortAllocatorSession *CreateSession(const std::string &name, const std::string &session_type) = 0;
diff --git a/talk/p2p/base/pseudotcp.cc b/talk/p2p/base/pseudotcp.cc
old mode 100755
new mode 100644
index 2f52d65..c342dbc
--- a/talk/p2p/base/pseudotcp.cc
+++ b/talk/p2p/base/pseudotcp.cc
@@ -2,30 +2,34 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/basicdefs.h"
+#include "talk/p2p/base/pseudotcp.h"
+
+#include <cstdio>
+#include <cstdlib>
+
#include "talk/base/basictypes.h"
#include "talk/base/byteorder.h"
#include "talk/base/common.h"
@@ -33,15 +37,8 @@
#include "talk/base/socket.h"
#include "talk/base/stringutils.h"
#include "talk/base/time.h"
-#include "talk/p2p/base/pseudotcp.h"
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-// The following logging is for detailed (packet-level) pseudotcp analysis only.
+// The following logging is for detailed (packet-level) analysis only.
#define _DBG_NONE 0
#define _DBG_NORMAL 1
#define _DBG_VERBOSE 2
@@ -90,8 +87,8 @@
// Global Constants and Functions
//////////////////////////////////////////////////////////////////////
//
-// 0 1 2 3
-// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 0 | Conversation Number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -199,7 +196,7 @@
void ReportStats() {
char buffer[256];
size_t len = 0;
- for (int i=0; i<S_NUM_STATS; ++i) {
+ for (int i = 0; i < S_NUM_STATS; ++i) {
len += talk_base::sprintfn(buffer, ARRAY_SIZE(buffer), "%s%s:%d",
(i == 0) ? "" : ",", STAT_NAMES[i], g_stats[i]);
g_stats[i] = 0;
@@ -215,13 +212,13 @@
uint32 PseudoTcp::Now() {
#if 0 // Use this to synchronize timers with logging timestamps (easier debug)
- return talk_base::ElapsedTime();
+ return talk_base::TimeSince(StartTime());
#else
return talk_base::Time();
#endif
}
-PseudoTcp::PseudoTcp(IPseudoTcpNotify * notify, uint32 conv)
+PseudoTcp::PseudoTcp(IPseudoTcpNotify* notify, uint32 conv)
: m_notify(notify), m_shutdown(SD_NONE), m_error(0) {
// Sanity check on buffer sizes (needed for OnTcpWriteable notification logic)
@@ -264,8 +261,7 @@
PseudoTcp::~PseudoTcp() {
}
-int
-PseudoTcp::Connect() {
+int PseudoTcp::Connect() {
if (m_state != TCP_LISTEN) {
m_error = EINVAL;
return -1;
@@ -282,16 +278,14 @@
return 0;
}
-void
-PseudoTcp::NotifyMTU(uint16 mtu) {
+void PseudoTcp::NotifyMTU(uint16 mtu) {
m_mtu_advise = mtu;
if (m_state == TCP_ESTABLISHED) {
adjustMTU();
}
}
-void
-PseudoTcp::NotifyClock(uint32 now) {
+void PseudoTcp::NotifyClock(uint32 now) {
if (m_state == TCP_CLOSED)
return;
@@ -325,9 +319,9 @@
m_rto_base = now;
}
}
-
+
// Check if it's time to probe closed windows
- if ((m_snd_wnd == 0)
+ if ((m_snd_wnd == 0)
&& (talk_base::TimeDiff(m_lastsend + m_rx_rto, now) <= 0)) {
if (talk_base::TimeDiff(now, m_lastrecv) >= 15000) {
closedown(ECONNABORTED);
@@ -361,8 +355,7 @@
#endif // PSEUDO_KEEPALIVE
}
-bool
-PseudoTcp::NotifyPacket(const char * buffer, size_t len) {
+bool PseudoTcp::NotifyPacket(const char* buffer, size_t len) {
if (len > MAX_PACKET) {
LOG_F(WARNING) << "packet too large";
return false;
@@ -370,17 +363,15 @@
return parse(reinterpret_cast<const uint8 *>(buffer), uint32(len));
}
-bool
-PseudoTcp::GetNextClock(uint32 now, long& timeout) {
+bool PseudoTcp::GetNextClock(uint32 now, long& timeout) {
return clock_check(now, timeout);
}
-//
+//
// IPStream Implementation
//
-int
-PseudoTcp::Recv(char * buffer, size_t len) {
+int PseudoTcp::Recv(char* buffer, size_t len) {
if (m_state != TCP_ESTABLISHED) {
m_error = ENOTCONN;
return SOCKET_ERROR;
@@ -399,7 +390,7 @@
// !?! until we create a circular buffer, we need to move all of the rest of the buffer up!
memmove(m_rbuf, m_rbuf + read, sizeof(m_rbuf) - read/*m_rlen*/);
- if ((sizeof(m_rbuf) - m_rlen - m_rcv_wnd)
+ if ((sizeof(m_rbuf) - m_rlen - m_rcv_wnd)
>= talk_base::_min<uint32>(sizeof(m_rbuf) / 2, m_mss)) {
bool bWasClosed = (m_rcv_wnd == 0); // !?! Not sure about this was closed business
@@ -413,8 +404,7 @@
return read;
}
-int
-PseudoTcp::Send(const char * buffer, size_t len) {
+int PseudoTcp::Send(const char* buffer, size_t len) {
if (m_state != TCP_ESTABLISHED) {
m_error = ENOTCONN;
return SOCKET_ERROR;
@@ -431,8 +421,7 @@
return written;
}
-void
-PseudoTcp::Close(bool force) {
+void PseudoTcp::Close(bool force) {
LOG_F(LS_VERBOSE) << "(" << (force ? "true" : "false") << ")";
m_shutdown = force ? SD_FORCEFUL : SD_GRACEFUL;
}
@@ -445,8 +434,7 @@
// Internal Implementation
//
-uint32
-PseudoTcp::queue(const char * data, uint32 len, bool bCtrl) {
+uint32 PseudoTcp::queue(const char* data, uint32 len, bool bCtrl) {
if (len > sizeof(m_sbuf) - m_slen) {
ASSERT(!bCtrl);
len = sizeof(m_sbuf) - m_slen;
@@ -467,8 +455,8 @@
return len;
}
-IPseudoTcpNotify::WriteResult
-PseudoTcp::packet(uint32 seq, uint8 flags, const char * data, uint32 len) {
+IPseudoTcpNotify::WriteResult PseudoTcp::packet(uint32 seq, uint8 flags,
+ const char* data, uint32 len) {
ASSERT(HEADER_SIZE + len <= MAX_PACKET);
uint32 now = Now();
@@ -516,8 +504,7 @@
return IPseudoTcpNotify::WR_SUCCESS;
}
-bool
-PseudoTcp::parse(const uint8 * buffer, uint32 size) {
+bool PseudoTcp::parse(const uint8* buffer, uint32 size) {
if (size < 12)
return false;
@@ -527,7 +514,7 @@
seg.ack = bytes_to_long(buffer + 8);
seg.flags = buffer[13];
seg.wnd = bytes_to_short(buffer + 14);
-
+
seg.tsval = bytes_to_long(buffer + 16);
seg.tsecr = bytes_to_long(buffer + 20);
@@ -548,8 +535,7 @@
return process(seg);
}
-bool
-PseudoTcp::clock_check(uint32 now, long& nTimeout) {
+bool PseudoTcp::clock_check(uint32 now, long& nTimeout) {
if (m_shutdown == SD_FORCEFUL)
return false;
@@ -567,27 +553,26 @@
nTimeout = DEFAULT_TIMEOUT;
if (m_t_ack) {
- nTimeout = talk_base::_min(nTimeout,
+ nTimeout = talk_base::_min<int32>(nTimeout,
talk_base::TimeDiff(m_t_ack + ACK_DELAY, now));
}
if (m_rto_base) {
- nTimeout = talk_base::_min(nTimeout,
+ nTimeout = talk_base::_min<int32>(nTimeout,
talk_base::TimeDiff(m_rto_base + m_rx_rto, now));
}
if (m_snd_wnd == 0) {
- nTimeout = talk_base::_min(nTimeout, talk_base::TimeDiff(m_lastsend + m_rx_rto, now));
+ nTimeout = talk_base::_min<int32>(nTimeout, talk_base::TimeDiff(m_lastsend + m_rx_rto, now));
}
#if PSEUDO_KEEPALIVE
if (m_state == TCP_ESTABLISHED) {
- nTimeout = talk_base::_min(nTimeout,
+ nTimeout = talk_base::_min<int32>(nTimeout,
talk_base::TimeDiff(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3/2 : IDLE_PING), now));
}
#endif // PSEUDO_KEEPALIVE
return true;
}
-bool
-PseudoTcp::process(Segment& seg) {
+bool PseudoTcp::process(Segment& seg) {
// If this is the wrong conversation, send a reset!?! (with the correct conversation?)
if (seg.conv != m_conv) {
//if ((seg.flags & FLAG_RST) == 0) {
@@ -661,7 +646,8 @@
m_rx_rttvar = (3 * m_rx_rttvar + abs(long(rtt - m_rx_srtt))) / 4;
m_rx_srtt = (7 * m_rx_srtt + rtt) / 8;
}
- m_rx_rto = bound(MIN_RTO, m_rx_srtt + talk_base::_max(1LU, 4 * m_rx_rttvar), MAX_RTO);
+ m_rx_rto = bound(MIN_RTO, m_rx_srtt +
+ talk_base::_max<uint32>(1, 4 * m_rx_rttvar), MAX_RTO);
#if _DEBUGMSG >= _DBG_VERBOSE
LOG(LS_INFO) << "rtt: " << rtt
<< " srtt: " << m_rx_srtt
@@ -700,7 +686,7 @@
if (m_dup_acks >= 3) {
if (m_snd_una >= m_recover) { // NewReno
uint32 nInFlight = m_snd_nxt - m_snd_una;
- m_cwnd = talk_base::_min(m_ssthresh, nInFlight + m_mss); // (Fast Retransmit)
+ m_cwnd = talk_base::_min(m_ssthresh, nInFlight + m_mss); // (Fast Retransmit)
#if _DEBUGMSG >= _DBG_NORMAL
LOG(LS_INFO) << "exit recovery";
#endif // _DEBUGMSG
@@ -721,7 +707,7 @@
if (m_cwnd < m_ssthresh) {
m_cwnd += m_mss;
} else {
- m_cwnd += talk_base::_max(1LU, m_mss * m_mss / m_cwnd);
+ m_cwnd += talk_base::_max<uint32>(1, m_mss * m_mss / m_cwnd);
}
}
@@ -735,7 +721,7 @@
}
//notify(evOpen);
}
-
+
// If we make room in the send queue, notify the user
// The goal it to make sure we always have at least enough data to fill the
// window. We'd like to notify the app when we are halfway to that point.
@@ -836,7 +822,7 @@
m_rcv_nxt += seg.len;
m_rcv_wnd -= seg.len;
bNewData = true;
-
+
RList::iterator it = m_rlist.begin();
while ((it != m_rlist.end()) && (it->seq <= m_rcv_nxt)) {
if (it->seq + it->len > m_rcv_nxt) {
@@ -881,8 +867,7 @@
return true;
}
-bool
-PseudoTcp::transmit(const SList::iterator& seg, uint32 now) {
+bool PseudoTcp::transmit(const SList::iterator& seg, uint32 now) {
if (seg->xmit >= ((m_state == TCP_ESTABLISHED) ? 15 : 30)) {
LOG_F(LS_VERBOSE) << "too many retransmits";
return false;
@@ -893,7 +878,7 @@
while (true) {
uint32 seq = seg->seq;
uint8 flags = (seg->bCtrl ? FLAG_CTL : 0);
- const char * buffer = m_sbuf + (seg->seq - m_snd_una);
+ const char* buffer = m_sbuf + (seg->seq - m_snd_una);
IPseudoTcpNotify::WriteResult wres = this->packet(seq, flags, buffer, nTransmit);
if (wres == IPseudoTcpNotify::WR_SUCCESS)
@@ -949,8 +934,7 @@
return true;
}
-void
-PseudoTcp::attemptSend(SendFlags sflags) {
+void PseudoTcp::attemptSend(SendFlags sflags) {
uint32 now = Now();
if (talk_base::TimeDiff(now, m_lastsend) > static_cast<long>(m_rx_rto)) {
@@ -1005,9 +989,9 @@
} else {
m_t_ack = Now();
}
- return;
+ return;
}
-
+
// Nagle algorithm
if ((m_snd_nxt > m_snd_una) && (nAvailable < m_mss)) {
return;
@@ -1068,4 +1052,4 @@
m_cwnd = talk_base::_max(m_cwnd, m_mss);
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/pseudotcp.h b/talk/p2p/base/pseudotcp.h
old mode 100755
new mode 100644
index cce23e1..1446201
--- a/talk/p2p/base/pseudotcp.h
+++ b/talk/p2p/base/pseudotcp.h
@@ -25,10 +25,11 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __PSEUDOTCP_H__
-#define __PSEUDOTCP_H__
+#ifndef TALK_P2P_BASE_PSEUDOTCP_H_
+#define TALK_P2P_BASE_PSEUDOTCP_H_
#include <list>
+
#include "talk/base/basictypes.h"
namespace cricket {
@@ -40,16 +41,18 @@
class PseudoTcp;
class IPseudoTcpNotify {
-public:
+ public:
+ virtual ~IPseudoTcpNotify() {}
// Notification of tcp events
- virtual void OnTcpOpen(PseudoTcp * tcp) = 0;
- virtual void OnTcpReadable(PseudoTcp * tcp) = 0;
- virtual void OnTcpWriteable(PseudoTcp * tcp) = 0;
- virtual void OnTcpClosed(PseudoTcp * tcp, uint32 nError) = 0;
+ virtual void OnTcpOpen(PseudoTcp* tcp) = 0;
+ virtual void OnTcpReadable(PseudoTcp* tcp) = 0;
+ virtual void OnTcpWriteable(PseudoTcp* tcp) = 0;
+ virtual void OnTcpClosed(PseudoTcp* tcp, uint32 error) = 0;
// Write the packet onto the network
enum WriteResult { WR_SUCCESS, WR_TOO_LARGE, WR_FAIL };
- virtual WriteResult TcpWritePacket(PseudoTcp * tcp, const char * buffer, size_t len) = 0;
+ virtual WriteResult TcpWritePacket(PseudoTcp* tcp,
+ const char* buffer, size_t len) = 0;
};
//////////////////////////////////////////////////////////////////////
@@ -57,19 +60,21 @@
//////////////////////////////////////////////////////////////////////
class PseudoTcp {
-public:
+ public:
static uint32 Now();
- PseudoTcp(IPseudoTcpNotify * notify, uint32 conv);
+ PseudoTcp(IPseudoTcpNotify* notify, uint32 conv);
virtual ~PseudoTcp();
int Connect();
- int Recv(char * buffer, size_t len);
- int Send(const char * buffer, size_t len);
+ int Recv(char* buffer, size_t len);
+ int Send(const char* buffer, size_t len);
void Close(bool force);
int GetError();
- enum TcpState { TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECEIVED, TCP_ESTABLISHED, TCP_CLOSED };
+ enum TcpState {
+ TCP_LISTEN, TCP_SYN_SENT, TCP_SYN_RECEIVED, TCP_ESTABLISHED, TCP_CLOSED
+ };
TcpState State() const { return m_state; }
// Call this when the PMTU changes.
@@ -87,7 +92,7 @@
// Returns false if the socket is ready to be destroyed.
bool GetNextClock(uint32 now, long& timeout);
-protected:
+ protected:
enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck };
enum {
// Note: can't go as high as 1024 * 64, because of uint16 precision
@@ -95,7 +100,7 @@
// Note: send buffer should be larger to make sure we can always fill the
// receiver window
kSndBufSize = 1024 * 90
- };
+ };
struct Segment {
uint32 conv, seq, ack;
@@ -107,12 +112,13 @@
};
struct SSegment {
+ SSegment(uint32 s, uint32 l, bool c)
+ : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) {
+ }
uint32 seq, len;
//uint32 tstamp;
uint8 xmit;
bool bCtrl;
-
- SSegment(uint32 s, uint32 l, bool c) : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) { }
};
typedef std::list<SSegment> SList;
@@ -120,10 +126,11 @@
uint32 seq, len;
};
- uint32 queue(const char * data, uint32 len, bool bCtrl);
+ uint32 queue(const char* data, uint32 len, bool bCtrl);
- IPseudoTcpNotify::WriteResult packet(uint32 seq, uint8 flags, const char * data, uint32 len);
- bool parse(const uint8 * buffer, uint32 size);
+ IPseudoTcpNotify::WriteResult packet(uint32 seq, uint8 flags,
+ const char* data, uint32 len);
+ bool parse(const uint8* buffer, uint32 size);
void attemptSend(SendFlags sflags = sfNone);
@@ -136,8 +143,8 @@
void adjustMTU();
-private:
- IPseudoTcpNotify * m_notify;
+ private:
+ IPseudoTcpNotify* m_notify;
enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown;
int m_error;
@@ -175,8 +182,6 @@
uint32 m_t_ack;
};
-//////////////////////////////////////////////////////////////////////
+} // namespace cricket
-} // namespace cricket
-
-#endif // __PSEUDOTCP_H__
+#endif // TALK_P2P_BASE_PSEUDOTCP_H_
diff --git a/talk/p2p/base/rawtransport.cc b/talk/p2p/base/rawtransport.cc
old mode 100755
new mode 100644
index f2e230b..b07d69c
--- a/talk/p2p/base/rawtransport.cc
+++ b/talk/p2p/base/rawtransport.cc
@@ -25,122 +25,100 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <string>
+#include <vector>
#include "talk/p2p/base/rawtransport.h"
#include "talk/base/common.h"
#include "talk/p2p/base/constants.h"
+#include "talk/p2p/base/parsing.h"
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/base/rawtransportchannel.h"
#include "talk/xmllite/qname.h"
#include "talk/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
+#if defined(FEATURE_ENABLE_PSTN)
namespace cricket {
-const std::string kNsRawTransport("http://www.google.com/transport/raw-udp");
-const buzz::QName kQnRawTransport(true, kNsRawTransport, "transport");
-const buzz::QName kQnRawChannel(true, kNsRawTransport, "channel");
-const buzz::QName kQnRawBehindSymmetricNat(true, buzz::STR_EMPTY,
- "behind-symmetric-nat");
-const buzz::QName kQnRawCanReceiveFromSymmetricNat(true, buzz::STR_EMPTY,
- "can-receive-from-symmetric-nat");
-
-RawTransport::RawTransport(SessionManager* session_manager)
- : Transport(session_manager, kNsRawTransport) {
+RawTransport::RawTransport(talk_base::Thread* signaling_thread,
+ talk_base::Thread* worker_thread,
+ PortAllocator* allocator)
+ : Transport(signaling_thread, worker_thread,
+ NS_GINGLE_RAW, allocator) {
}
RawTransport::~RawTransport() {
DestroyAllChannels();
}
-buzz::XmlElement* RawTransport::CreateTransportOffer() {
- buzz::XmlElement* xml = new buzz::XmlElement(kQnRawTransport, true);
-
- // Assume that we are behind a symmetric NAT. Also note that we can't
- // handle the adjustment necessary to talk to someone else who is behind
- // a symmetric NAT.
- xml->AddAttr(kQnRawBehindSymmetricNat, "true");
- xml->AddAttr(kQnRawCanReceiveFromSymmetricNat, "false");
-
- return xml;
-}
-
-buzz::XmlElement* RawTransport::CreateTransportAnswer() {
- return new buzz::XmlElement(kQnRawTransport, true);
-}
-
-bool RawTransport::OnTransportOffer(const buzz::XmlElement* elem) {
- ASSERT(elem->Name() == kQnRawTransport);
-
- // If the other side is behind a symmetric NAT then we can't talk to him.
- // We also bail if this attribute isn't specified.
- if (!elem->HasAttr(kQnRawBehindSymmetricNat)
- || elem->Attr(kQnRawBehindSymmetricNat) != "false") {
- return false;
- }
-
- // If the other side doesn't explicitly state that he can receive from
- // someone behind a symmetric NAT, we bail.
- if (!elem->HasAttr(kQnRawCanReceiveFromSymmetricNat)
- || elem->Attr(kQnRawCanReceiveFromSymmetricNat) != "true") {
- return false;
- }
-
- // We don't support any options, so we ignore them.
- return true;
-}
-
-bool RawTransport::OnTransportAnswer(const buzz::XmlElement* elem) {
- ASSERT(elem->Name() == kQnRawTransport);
- // We don't support any options. We fail if any are given. The other side
- // should know from our request that we expected an empty response.
- return elem->FirstChild() == NULL;
-}
-
-bool RawTransport::OnTransportMessage(const buzz::XmlElement* msg,
- const buzz::XmlElement* stanza) {
- ASSERT(msg->Name() == kQnRawTransport);
- for (const buzz::XmlElement* elem = msg->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- if (elem->Name() == kQnRawChannel) {
+bool RawTransport::ParseCandidates(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ Candidates* candidates,
+ ParseError* error) {
+ ASSERT(elem->FirstChild() == NULL);
+ for (const buzz::XmlElement* cand_elem = elem->FirstElement();
+ cand_elem != NULL;
+ cand_elem = cand_elem->NextElement()) {
+ if (cand_elem->Name() == QN_GINGLE_RAW_CHANNEL) {
talk_base::SocketAddress addr;
- if (!ParseAddress(stanza, elem, &addr))
+ if (!ParseRawAddress(cand_elem, &addr, error))
return false;
- ForwardChannelMessage(elem->Attr(buzz::QN_NAME),
- new buzz::XmlElement(*elem));
+ Candidate candidate;
+ candidate.set_name(cand_elem->Attr(buzz::QN_NAME));
+ candidate.set_address(addr);
+ candidates->push_back(candidate);
}
}
return true;
}
-bool RawTransport::OnTransportError(const buzz::XmlElement* session_msg,
- const buzz::XmlElement* error) {
+bool RawTransport::WriteCandidates(SignalingProtocol protocol,
+ const Candidates& candidates,
+ XmlElements* candidate_elems,
+ WriteError* error) {
+ for (std::vector<Candidate>::const_iterator
+ cand = candidates.begin();
+ cand != candidates.end();
+ ++cand) {
+ ASSERT(cand->protocol() == "udp");
+ talk_base::SocketAddress addr = cand->address();
+
+ buzz::XmlElement* elem = new buzz::XmlElement(QN_GINGLE_RAW_CHANNEL);
+ elem->SetAttr(buzz::QN_NAME, type());
+ elem->SetAttr(QN_ADDRESS, addr.IPAsString());
+ elem->SetAttr(QN_PORT, addr.PortAsString());
+ candidate_elems->push_back(elem);
+ }
return true;
}
-bool RawTransport::ParseAddress(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- talk_base::SocketAddress* addr) {
+bool RawTransport::ParseRawAddress(const buzz::XmlElement* elem,
+ talk_base::SocketAddress* addr,
+ ParseError* error) {
// Make sure the required attributes exist
if (!elem->HasAttr(buzz::QN_NAME) ||
!elem->HasAttr(QN_ADDRESS) ||
!elem->HasAttr(QN_PORT)) {
- return BadRequest(stanza, "channel missing required attribute", NULL);
+ return BadParse("channel missing required attribute", error);
}
// Make sure the channel named actually exists.
if (!HasChannel(elem->Attr(buzz::QN_NAME)))
- return BadRequest(stanza, "channel named does not exist", NULL);
+ return BadParse("channel named does not exist", error);
// Parse the address.
- return Transport::ParseAddress(stanza, elem, addr);
+ if (!ParseAddress(elem, QN_ADDRESS, QN_PORT, addr, error))
+ return false;
+
+ return true;
}
TransportChannelImpl* RawTransport::CreateTransportChannel(
- const std::string& name, const std::string &session_type) {
- return new RawTransportChannel(
- name, session_type, this, session_manager()->port_allocator());
+ const std::string& name, const std::string& content_type) {
+ return new RawTransportChannel(name, content_type, this,
+ worker_thread(),
+ port_allocator());
}
void RawTransport::DestroyTransportChannel(TransportChannelImpl* channel) {
@@ -148,3 +126,4 @@
}
} // namespace cricket
+#endif // defined(FEATURE_ENABLE_PSTN)
diff --git a/talk/p2p/base/rawtransport.h b/talk/p2p/base/rawtransport.h
old mode 100755
new mode 100644
index d273b40..6734130
--- a/talk/p2p/base/rawtransport.h
+++ b/talk/p2p/base/rawtransport.h
@@ -25,53 +25,47 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_P2P_BASE_RAWTRANSPORT_H_
-#define _CRICKET_P2P_BASE_RAWTRANSPORT_H_
+#ifndef TALK_P2P_BASE_RAWTRANSPORT_H_
+#define TALK_P2P_BASE_RAWTRANSPORT_H_
+#include <string>
#include "talk/p2p/base/transport.h"
+#if defined(FEATURE_ENABLE_PSTN)
namespace cricket {
-// Xml names used to name this transport and create our elements
-extern const std::string kNsRawTransport;
-extern const buzz::QName kQnRawTransport;
-extern const buzz::QName kQnRawChannel;
-extern const buzz::QName kQnRawNatType;
-extern const buzz::QName kQnRawNatTypeAllowed;
-
// Implements a transport that only sends raw packets, no STUN. As a result,
// it cannot do pings to determine connectivity, so it only uses a single port
// that it thinks will work.
-class RawTransport: public Transport {
+class RawTransport: public Transport, public TransportParser {
public:
- RawTransport(SessionManager* session_manager);
+ RawTransport(talk_base::Thread* signaling_thread,
+ talk_base::Thread* worker_thread,
+ PortAllocator* allocator);
virtual ~RawTransport();
- // Handles the raw transport protocol descriptions, which are trivial.
- virtual buzz::XmlElement* CreateTransportOffer();
- virtual buzz::XmlElement* CreateTransportAnswer();
- virtual bool OnTransportOffer(const buzz::XmlElement* elem);
- virtual bool OnTransportAnswer(const buzz::XmlElement* elem);
-
- // Forwards messages containing channel addresses to the appropriate channel.
- virtual bool OnTransportMessage(const buzz::XmlElement* msg,
- const buzz::XmlElement* stanza);
- virtual bool OnTransportError(const buzz::XmlElement* session_msg,
- const buzz::XmlElement* error);
+ virtual bool ParseCandidates(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ Candidates* candidates,
+ ParseError* error);
+ virtual bool WriteCandidates(SignalingProtocol protocol,
+ const Candidates& candidates,
+ XmlElements* candidate_elems,
+ WriteError* error);
protected:
// Creates and destroys raw channels.
virtual TransportChannelImpl* CreateTransportChannel(
- const std::string& name, const std::string &session_type);
+ const std::string& name, const std::string &content_type);
virtual void DestroyTransportChannel(TransportChannelImpl* channel);
private:
// Parses the given element, which should describe the address to use for a
// given channel. This will return false and signal an error if the address
// or channel name is bad.
- bool ParseAddress(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- talk_base::SocketAddress* addr);
+ bool ParseRawAddress(const buzz::XmlElement* elem,
+ talk_base::SocketAddress* addr,
+ ParseError* error);
friend class RawTransportChannel; // For ParseAddress.
@@ -80,5 +74,6 @@
} // namespace cricket
+#endif // defined(FEATURE_ENABLE_PSTN)
-#endif // _CRICKET_P2P_BASE_RAWTRANSPORT_H_
+#endif // TALK_P2P_BASE_RAWTRANSPORT_H_
diff --git a/talk/p2p/base/rawtransportchannel.cc b/talk/p2p/base/rawtransportchannel.cc
old mode 100755
new mode 100644
index 13c1886..39db13c
--- a/talk/p2p/base/rawtransportchannel.cc
+++ b/talk/p2p/base/rawtransportchannel.cc
@@ -2,30 +2,33 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/p2p/base/rawtransportchannel.h"
+
+#include <string>
+#include <vector>
#include "talk/base/common.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/port.h"
@@ -38,20 +41,33 @@
#include "talk/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
+#if defined(FEATURE_ENABLE_PSTN)
+
namespace {
-const int MSG_DESTROY_UNUSED_PORTS = 1;
+const uint32 MSG_DESTROY_UNUSED_PORTS = 1;
} // namespace
namespace cricket {
-RawTransportChannel::RawTransportChannel(
- const std::string &name, const std::string &session_type, RawTransport* transport,
- PortAllocator *allocator)
- : TransportChannelImpl(name, session_type), raw_transport_(transport),
- allocator_(allocator), allocator_session_(NULL), stun_port_(NULL),
- relay_port_(NULL), port_(NULL), use_relay_(false) {
+RawTransportChannel::RawTransportChannel(const std::string &name,
+ const std::string &content_type,
+ RawTransport* transport,
+ talk_base::Thread *worker_thread,
+ PortAllocator *allocator)
+ : TransportChannelImpl(name, content_type),
+ raw_transport_(transport),
+ allocator_(allocator),
+ allocator_session_(NULL),
+ stun_port_(NULL),
+ relay_port_(NULL),
+ port_(NULL),
+ use_relay_(false) {
+ if (worker_thread == NULL)
+ worker_thread_ = raw_transport_->worker_thread();
+ else
+ worker_thread_ = worker_thread;
}
RawTransportChannel::~RawTransportChannel() {
@@ -79,7 +95,7 @@
void RawTransportChannel::Connect() {
// Create an allocator that only returns stun and relay ports.
- allocator_session_ = allocator_->CreateSession(name(), session_type());
+ allocator_session_ = allocator_->CreateSession(name(), content_type());
uint32 flags = PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP;
@@ -109,9 +125,8 @@
remote_address_ = talk_base::SocketAddress();
}
-void RawTransportChannel::OnChannelMessage(const buzz::XmlElement* msg) {
- bool valid = raw_transport_->ParseAddress(NULL, msg, &remote_address_);
- ASSERT(valid);
+void RawTransportChannel::OnCandidate(const Candidate& candidate) {
+ remote_address_ = candidate.address();
ASSERT(!remote_address_.IsAny());
set_readable(true);
@@ -120,11 +135,20 @@
SetWritable();
}
+void RawTransportChannel::OnRemoteAddress(
+ const talk_base::SocketAddress& remote_address) {
+ remote_address_ = remote_address;
+ set_readable(true);
+
+ if (port_ != NULL)
+ SetWritable();
+}
+
// Note about stun classification
// Code to classify our NAT type and use the relay port if we are behind an
// asymmetric NAT is under a FEATURE_ENABLE_STUN_CLASSIFICATION #define.
// To turn this one we will have to enable a second stun address and make sure
-// that the relay server works for raw UDP.
+// that the relay server works for raw UDP.
//
// Another option is to classify the NAT type early and not offer the raw
// transport type at all if we can't support it.
@@ -184,7 +208,7 @@
// to wait until one arrives.
if (relay_port_->candidates().size() > 0)
SetPort(relay_port_);
-#else // defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
+#else // defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
// Always use the stun port. We don't classify right now so just assume it
// will work fine.
SetPort(stun_port_);
@@ -203,20 +227,14 @@
// We don't need any ports other than the one we picked.
allocator_session_->StopGetAllPorts();
- raw_transport_->session_manager()->worker_thread()->Post(
+ worker_thread_->Post(
this, MSG_DESTROY_UNUSED_PORTS, NULL);
// Send a message to the other client containing our address.
ASSERT(port_->candidates().size() >= 1);
ASSERT(port_->candidates()[0].protocol() == "udp");
- talk_base::SocketAddress addr = port_->candidates()[0].address();
-
- buzz::XmlElement* msg = new buzz::XmlElement(kQnRawChannel);
- msg->SetAttr(buzz::QN_NAME, name());
- msg->SetAttr(QN_ADDRESS, addr.IPAsString());
- msg->SetAttr(QN_PORT, addr.PortAsString());
- SignalChannelMessage(this, msg);
+ SignalCandidateReady(this, port_->candidates()[0]);
// Read all packets from this port.
port_->EnablePortPackets();
@@ -237,7 +255,7 @@
}
void RawTransportChannel::OnReadPacket(
- Port* port, const char* data, size_t size,
+ Port* port, const char* data, size_t size,
const talk_base::SocketAddress& addr) {
ASSERT(port_ == port);
SignalReadPacket(this, data, size);
@@ -257,3 +275,4 @@
}
} // namespace cricket
+#endif // defined(FEATURE_ENABLE_PSTN)
diff --git a/talk/p2p/base/rawtransportchannel.h b/talk/p2p/base/rawtransportchannel.h
old mode 100755
new mode 100644
index 9dcbae2..f99c9c4
--- a/talk/p2p/base/rawtransportchannel.h
+++ b/talk/p2p/base/rawtransportchannel.h
@@ -25,14 +25,22 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_
-#define _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_
+#ifndef TALK_P2P_BASE_RAWTRANSPORTCHANNEL_H_
+#define TALK_P2P_BASE_RAWTRANSPORTCHANNEL_H_
+#include <string>
+#include <vector>
#include "talk/base/messagequeue.h"
#include "talk/p2p/base/transportchannelimpl.h"
#include "talk/p2p/base/rawtransport.h"
#include "talk/p2p/base/candidate.h"
+#if defined(FEATURE_ENABLE_PSTN)
+
+namespace talk_base {
+class Thread;
+}
+
namespace cricket {
class Port;
@@ -45,12 +53,13 @@
// Implements a channel that just sends bare packets once we have received the
// address of the other side. We pick a single address to send them based on
// a simple investigation of NAT type.
-class RawTransportChannel : public TransportChannelImpl,
+class RawTransportChannel : public TransportChannelImpl,
public talk_base::MessageHandler {
public:
RawTransportChannel(const std::string &name,
- const std::string &session_type,
+ const std::string &content_type,
RawTransport* transport,
+ talk_base::Thread *worker_thread,
PortAllocator *allocator);
virtual ~RawTransportChannel();
@@ -62,9 +71,9 @@
// Returns the raw transport that created this channel.
virtual Transport* GetTransport() { return raw_transport_; }
- // Creates an allocator session to start figuring out which type of port we
- // should send to the other client. This will send SignalChannelMessage once
- // we have decided.
+ // Creates an allocator session to start figuring out which type of
+ // port we should send to the other client. This will send
+ // SignalAvailableCandidate once we have decided.
virtual void Connect();
// Resets state back to unconnected.
@@ -75,10 +84,14 @@
// Handles a message setting the remote address. We are writable once we
// have this since we now know where to send.
- virtual void OnChannelMessage(const buzz::XmlElement* msg);
+ virtual void OnCandidate(const Candidate& candidate);
+
+ void OnRemoteAddress(const talk_base::SocketAddress& remote_address);
+
private:
RawTransport* raw_transport_;
+ talk_base::Thread *worker_thread_;
PortAllocator* allocator_;
PortAllocatorSession* allocator_session_;
StunPort* stun_port_;
@@ -114,4 +127,5 @@
} // namespace cricket
-#endif // _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_
+#endif // defined(FEATURE_ENABLE_PSTN)
+#endif // TALK_P2P_BASE_RAWTRANSPORTCHANNEL_H_
diff --git a/talk/p2p/base/relayport.cc b/talk/p2p/base/relayport.cc
old mode 100755
new mode 100644
index a8a0527..ff6d55a
--- a/talk/p2p/base/relayport.cc
+++ b/talk/p2p/base/relayport.cc
@@ -2,71 +2,102 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(_MSC_VER) && _MSC_VER < 1300
#pragma warning(disable:4786)
#endif
-#include "talk/base/logging.h"
+
#include "talk/base/asynctcpsocket.h"
#include "talk/base/helpers.h"
+#include "talk/base/logging.h"
#include "talk/p2p/base/relayport.h"
-#include <iostream>
-#include <cassert>
-#ifdef OSX
-#include <errno.h>
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::strerror;
-}
-#endif
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-namespace talk_base {
-class AsyncTCPSocket;
-};
namespace cricket {
-const int KEEPALIVE_DELAY = 10 * 60 * 1000;
-const int RETRY_DELAY = 50; // 50ms, from ICE spec
-const uint32 RETRY_TIMEOUT = 50 * 1000; // ICE says 50 secs
+static const uint32 kMessageConnectTimeout = 1;
+static const int kKeepAliveDelay = 10 * 60 * 1000;
+static const int kRetryTimeout = 50 * 1000; // ICE says 50 secs
+// How long to wait for a socket to connect to remote host in milliseconds
+// before trying another connection.
+static const int kSoftConnectTimeoutMs = 3 * 1000;
-// Manages a single connection to the relayserver. We aim to use each
-// connection for only a specific destination address so that we can avoid
-// wrapping every packet in a STUN send / data indication.
-class RelayEntry : public sigslot::has_slots<> {
-public:
- RelayEntry(RelayPort* port, const talk_base::SocketAddress& ext_addr,
- const talk_base::SocketAddress& local_addr);
+// Handles a connection to one address/port/protocol combination for a
+// particular RelayEntry.
+class RelayConnection : public sigslot::has_slots<> {
+ public:
+ RelayConnection(const ProtocolAddress* protocol_address,
+ talk_base::AsyncPacketSocket* socket,
+ talk_base::Thread* thread);
+ ~RelayConnection();
+ talk_base::AsyncPacketSocket* socket() const { return socket_; }
+
+ const ProtocolAddress* protocol_address() {
+ return protocol_address_;
+ }
+
+ talk_base::SocketAddress GetAddress() const {
+ return protocol_address_->address;
+ }
+
+ ProtocolType GetProtocol() const {
+ return protocol_address_->proto;
+ }
+
+ int SetSocketOption(talk_base::Socket::Option opt, int value);
+
+ // Validates a response to a STUN allocate request.
+ bool CheckResponse(StunMessage* msg);
+
+ // Sends data to the relay server.
+ int Send(const void* pv, size_t cb);
+
+ // Sends a STUN allocate request message to the relay server.
+ void SendAllocateRequest(RelayEntry* entry, int delay);
+
+ // Return the latest error generated by the socket.
+ int GetError() { return socket_->GetError(); }
+
+ // Called on behalf of a StunRequest to write data to the socket. This is
+ // already STUN intended for the server, so no wrapping is necessary.
+ void OnSendPacket(const void* data, size_t size, StunRequest* req);
+
+ private:
+ talk_base::AsyncPacketSocket* socket_;
+ const ProtocolAddress* protocol_address_;
+ StunRequestManager *request_manager_;
+};
+
+// Manages a number of connections to the relayserver, one for each
+// available protocol. We aim to use each connection for only a
+// specific destination address so that we can avoid wrapping every
+// packet in a STUN send / data indication.
+class RelayEntry : public talk_base::MessageHandler,
+ public sigslot::has_slots<> {
+ public:
+ RelayEntry(RelayPort* port, const talk_base::SocketAddress& ext_addr,
+ const talk_base::SocketAddress& local_addr);
~RelayEntry();
RelayPort* port() { return port_; }
@@ -74,43 +105,54 @@
const talk_base::SocketAddress& address() const { return ext_addr_; }
void set_address(const talk_base::SocketAddress& addr) { ext_addr_ = addr; }
- talk_base::AsyncPacketSocket* socket() { return socket_; }
-
bool connected() const { return connected_; }
bool locked() const { return locked_; }
// Returns the last error on the socket of this entry.
- int GetError() const { return socket_->GetError(); }
+ int GetError();
+
+ // Returns the most preferred connection of the given
+ // ones. Connections are rated based on protocol in the order of:
+ // UDP, TCP and SSLTCP, where UDP is the most preferred protocol
+ static RelayConnection* GetBestConnection(RelayConnection* conn1,
+ RelayConnection* conn2);
// Sends the STUN requests to the server to initiate this connection.
void Connect();
// Called when this entry becomes connected. The address given is the one
// exposed to the outside world on the relay server.
- void OnConnect(const talk_base::SocketAddress& mapped_addr);
+ void OnConnect(const talk_base::SocketAddress& mapped_addr,
+ RelayConnection* socket);
// Sends a packet to the given destination address using the socket of this
// entry. This will wrap the packet in STUN if necessary.
- int SendTo(const void* data, size_t size,
+ int SendTo(const void* data, size_t size,
const talk_base::SocketAddress& addr);
// Schedules a keep-alive allocate request.
void ScheduleKeepAlive();
void SetServerIndex(size_t sindex) { server_index_ = sindex; }
+
+ // Sets this option on the socket of each connection.
+ int SetSocketOption(talk_base::Socket::Option opt, int value);
+
size_t ServerIndex() const { return server_index_; }
// Try a different server address
- void HandleConnectFailure();
+ void HandleConnectFailure(talk_base::AsyncPacketSocket* socket);
-private:
+ // Implementation of the MessageHandler Interface.
+ virtual void OnMessage(talk_base::Message *pmsg);
+
+ private:
RelayPort* port_;
talk_base::SocketAddress ext_addr_, local_addr_;
size_t server_index_;
- talk_base::AsyncPacketSocket* socket_;
bool connected_;
bool locked_;
- StunRequestManager requests_;
+ RelayConnection* current_connection_;
// Called when a TCP connection is established or fails
void OnSocketConnect(talk_base::AsyncTCPSocket* socket);
@@ -118,14 +160,10 @@
// Called when a packet is received on this socket.
void OnReadPacket(
- const char* data, size_t size,
+ const char* data, size_t size,
const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket);
- // Called on behalf of a StunRequest to write data to the socket. This is
- // already STUN intended for the server, so no wrapping is necessary.
- void OnSendPacket(const void* data, size_t size, StunRequest* req);
-
// Sends the given data on the socket to the server with no wrapping. This
// returns the number of bytes written or -1 if an error occurred.
int SendPacket(const void* data, size_t size);
@@ -133,8 +171,8 @@
// Handles an allocate request for a particular RelayEntry.
class AllocateRequest : public StunRequest {
-public:
- AllocateRequest(RelayEntry* entry);
+ public:
+ AllocateRequest(RelayEntry* entry, RelayConnection* connection);
virtual ~AllocateRequest() {}
virtual void Prepare(StunMessage* request);
@@ -145,42 +183,42 @@
virtual void OnErrorResponse(StunMessage* response);
virtual void OnTimeout();
-private:
+ private:
RelayEntry* entry_;
+ RelayConnection* connection_;
uint32 start_time_;
};
const std::string RELAY_PORT_TYPE("relay");
RelayPort::RelayPort(
- talk_base::Thread* thread, talk_base::SocketFactory* factory,
- talk_base::Network* network, const talk_base::SocketAddress& local_addr,
- const std::string& username, const std::string& password,
+ talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network* network, const talk_base::SocketAddress& local_addr,
+ const std::string& username, const std::string& password,
const std::string& magic_cookie)
- : Port(thread, RELAY_PORT_TYPE, factory, network), local_addr_(local_addr),
- ready_(false), magic_cookie_(magic_cookie), error_(0) {
-
+ : Port(thread, RELAY_PORT_TYPE, factory, network), local_addr_(local_addr),
+ ready_(false), magic_cookie_(magic_cookie), error_(0) {
entries_.push_back(
- new RelayEntry(this, talk_base::SocketAddress(), local_addr_));
+ new RelayEntry(this, talk_base::SocketAddress(), local_addr_));
set_username_fragment(username);
set_password(password);
-
if (magic_cookie_.size() == 0)
magic_cookie_.append(STUN_MAGIC_COOKIE_VALUE, 4);
}
RelayPort::~RelayPort() {
- for (unsigned i = 0; i < entries_.size(); ++i)
+ for (size_t i = 0; i < entries_.size(); ++i)
delete entries_[i];
thread_->Clear(this);
}
void RelayPort::AddServerAddress(const ProtocolAddress& addr) {
- // Since HTTP proxies usually only allow 443, let's up the priority on PROTO_SSLTCP
- if ((addr.proto == PROTO_SSLTCP)
- && ((proxy().type == talk_base::PROXY_HTTPS)
- || (proxy().type == talk_base::PROXY_UNKNOWN))) {
+ // Since HTTP proxies usually only allow 443,
+ // let's up the priority on PROTO_SSLTCP
+ if (addr.proto == PROTO_SSLTCP &&
+ (proxy().type == talk_base::PROXY_HTTPS ||
+ proxy().type == talk_base::PROXY_UNKNOWN)) {
server_addr_.push_front(addr);
} else {
server_addr_.push_back(addr);
@@ -189,9 +227,11 @@
void RelayPort::AddExternalAddress(const ProtocolAddress& addr) {
std::string proto_name = ProtoToString(addr.proto);
- for (std::vector<Candidate>::const_iterator it = candidates().begin(); it != candidates().end(); ++it) {
+ for (std::vector<Candidate>::const_iterator it = candidates().begin();
+ it != candidates().end(); ++it) {
if ((it->address() == addr.address) && (it->protocol() == proto_name)) {
- LOG(INFO) << "Redundant relay address: " << proto_name << " @ " << addr.address.ToString();
+ LOG(INFO) << "Redundant relay address: " << proto_name
+ << " @ " << addr.address.ToString();
return;
}
}
@@ -206,9 +246,9 @@
}
const ProtocolAddress * RelayPort::ServerAddress(size_t index) const {
- if ((index >= 0) && (index < server_addr_.size()))
+ if (index < server_addr_.size())
return &server_addr_[index];
- return 0;
+ return NULL;
}
bool RelayPort::HasMagicCookie(const char* data, size_t size) {
@@ -224,19 +264,22 @@
void RelayPort::PrepareAddress() {
// We initiate a connect on the first entry. If this completes, it will fill
// in the server address as the address of this port.
- assert(entries_.size() == 1);
+ ASSERT(entries_.size() == 1);
entries_[0]->Connect();
ready_ = false;
}
-Connection* RelayPort::CreateConnection(const Candidate& address, CandidateOrigin origin) {
- // We only create connections to non-udp sockets if they are incoming on this port
- if ((address.protocol() != "udp") && (origin != ORIGIN_THIS_PORT))
+Connection* RelayPort::CreateConnection(const Candidate& address,
+ CandidateOrigin origin) {
+ // We only create conns to non-udp sockets if they are incoming on this port
+ if ((address.protocol() != "udp") && (origin != ORIGIN_THIS_PORT)) {
return 0;
+ }
// We don't support loopback on relays
- if (address.type() == type())
+ if (address.type() == type()) {
return 0;
+ }
size_t index = 0;
for (size_t i = 0; i < candidates().size(); ++i) {
@@ -254,14 +297,12 @@
int RelayPort::SendTo(const void* data, size_t size,
const talk_base::SocketAddress& addr, bool payload) {
-
// Try to find an entry for this specific address. Note that the first entry
// created was not given an address initially, so it can be set to the first
// address that comes along.
-
RelayEntry* entry = 0;
- for (unsigned i = 0; i < entries_.size(); ++i) {
+ for (size_t i = 0; i < entries_.size(); ++i) {
if (entries_[i]->address().IsAny() && payload) {
entry = entries_[i];
entry->set_address(addr);
@@ -277,7 +318,6 @@
if (!entry && payload) {
entry = new RelayEntry(this, addr, local_addr_);
if (!entries_.empty()) {
- // Use the same port to connect to relay server
entry->SetServerIndex(entries_[0]->ServerIndex());
}
entry->Connect();
@@ -288,7 +328,7 @@
// still be necessary). Otherwise, we can't yet use this connection, so we
// default to the first one.
if (!entry || !entry->connected()) {
- assert(!entries_.empty());
+ ASSERT(!entries_.empty());
entry = entries_[0];
if (!entry->connected()) {
error_ = EWOULDBLOCK;
@@ -299,11 +339,10 @@
// Send the actual contents to the server using the usual mechanism.
int sent = entry->SendTo(data, size, addr);
if (sent <= 0) {
- assert(sent < 0);
+ ASSERT(sent < 0);
error_ = entry->GetError();
return SOCKET_ERROR;
}
-
// The caller of the function is expecting the number of user data bytes,
// rather than the size of the packet.
return (int)size;
@@ -311,10 +350,10 @@
int RelayPort::SetOption(talk_base::Socket::Option opt, int value) {
int result = 0;
- for (unsigned i = 0; i < entries_.size(); ++i) {
- if (entries_[i]->socket()->SetOption(opt, value) < 0) {
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ if (entries_[i]->SetSocketOption(opt, value) < 0) {
result = -1;
- error_ = entries_[i]->socket()->GetError();
+ error_ = entries_[i]->GetError();
}
}
options_.push_back(OptionValue(opt, value));
@@ -326,7 +365,7 @@
}
void RelayPort::OnReadPacket(
- const char* data, size_t size,
+ const char* data, size_t size,
const talk_base::SocketAddress& remote_addr) {
if (Connection* conn = GetConnection(remote_addr)) {
conn->OnReadPacket(data, size);
@@ -335,57 +374,143 @@
}
}
-void RelayPort::DisposeSocket(talk_base::AsyncPacketSocket * socket) {
- thread_->Dispose(socket);
+RelayConnection::RelayConnection(const ProtocolAddress* protocol_address,
+ talk_base::AsyncPacketSocket* socket,
+ talk_base::Thread* thread)
+ : socket_(socket),
+ protocol_address_(protocol_address) {
+ request_manager_ = new StunRequestManager(thread);
+ request_manager_->SignalSendPacket.connect(this,
+ &RelayConnection::OnSendPacket);
}
-RelayEntry::RelayEntry(RelayPort* port,
- const talk_base::SocketAddress& ext_addr,
- const talk_base::SocketAddress& local_addr)
- : port_(port), ext_addr_(ext_addr), local_addr_(local_addr), server_index_(0),
- socket_(0), connected_(false), locked_(false), requests_(port->thread()) {
-
- requests_.SignalSendPacket.connect(this, &RelayEntry::OnSendPacket);
-}
-
-RelayEntry::~RelayEntry() {
+RelayConnection::~RelayConnection() {
+ delete request_manager_;
delete socket_;
}
-void RelayEntry::Connect() {
- assert(socket_ == 0);
- const ProtocolAddress * ra = port()->ServerAddress(server_index_);
- if (!ra) {
- LOG(INFO) << "Out of relay server connections";
- return;
+int RelayConnection::SetSocketOption(talk_base::Socket::Option opt,
+ int value) {
+ if (socket_) {
+ return socket_->SetOption(opt, value);
}
+ return 0;
+}
- LOG(INFO) << "Connecting to relay via " << ProtoToString(ra->proto) << " @ " << ra->address.ToString();
+bool RelayConnection::CheckResponse(StunMessage* msg) {
+ return request_manager_->CheckResponse(msg);
+}
- socket_ = port_->CreatePacketSocket(ra->proto);
- assert(socket_ != 0);
-
- socket_->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket);
- if (socket_->Bind(local_addr_) < 0)
- LOG(INFO) << "bind: " << std::strerror(socket_->GetError());
-
- for (unsigned i = 0; i < port_->options().size(); ++i)
- socket_->SetOption(port_->options()[i].first, port_->options()[i].second);
-
- if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) {
- talk_base::AsyncTCPSocket * tcp
- = static_cast<talk_base::AsyncTCPSocket *>(socket_);
- tcp->SignalClose.connect(this, &RelayEntry::OnSocketClose);
- tcp->SignalConnect.connect(this, &RelayEntry::OnSocketConnect);
- tcp->Connect(ra->address);
- } else {
- requests_.Send(new AllocateRequest(this));
+void RelayConnection::OnSendPacket(const void* data, size_t size,
+ StunRequest* req) {
+ int sent = socket_->SendTo(data, size, GetAddress());
+ if (sent <= 0) {
+ LOG(LS_VERBOSE) << "OnSendPacket: failed sending to " << GetAddress() <<
+ std::strerror(socket_->GetError());
+ ASSERT(sent < 0);
}
}
-void RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr) {
+int RelayConnection::Send(const void* pv, size_t cb) {
+ return socket_->SendTo(pv, cb, GetAddress());
+}
+
+void RelayConnection::SendAllocateRequest(RelayEntry* entry, int delay) {
+ request_manager_->SendDelayed(new AllocateRequest(entry, this), delay);
+}
+
+RelayEntry::RelayEntry(RelayPort* port,
+ const talk_base::SocketAddress& ext_addr,
+ const talk_base::SocketAddress& local_addr)
+ : port_(port), ext_addr_(ext_addr), local_addr_(local_addr),
+ server_index_(0), connected_(false), locked_(false),
+ current_connection_(NULL) {
+}
+
+RelayEntry::~RelayEntry() {
+ // Remove all RelayConnections and dispose sockets.
+ delete current_connection_;
+ current_connection_ = NULL;
+}
+
+void RelayEntry::Connect() {
+ // If we're already connected, return.
+ if (connected_)
+ return;
+
+ // If we've exhausted all options, bail out.
+ const ProtocolAddress* ra = port()->ServerAddress(server_index_);
+ if (!ra) {
+ LOG(LS_WARNING) << "No more relay addresses left to try";
+ return;
+ }
+
+ // Remove any previous connection.
+ if (current_connection_) {
+ port()->thread()->Dispose(current_connection_);
+ current_connection_ = NULL;
+ }
+
+ // Try to set up our new socket.
+ LOG(LS_INFO) << "Connecting to relay via " << ProtoToString(ra->proto) <<
+ " @ " << ra->address.ToString();
+
+ talk_base::AsyncPacketSocket* socket = port_->CreatePacketSocket(ra->proto);
+ if (!socket) {
+ LOG(LS_WARNING) << "Socket creation failed";
+ } else if (socket->Bind(local_addr_) < 0) {
+ LOG(LS_WARNING) << "Socket bind failed with error " << socket->GetError();
+ delete socket;
+ socket = NULL;
+ }
+
+ // If we failed to get a socket, move on to the next protocol.
+ if (!socket) {
+ port()->thread()->Post(this, kMessageConnectTimeout);
+ return;
+ }
+
+ // Otherwise, create the new connection and configure any socket options.
+ socket->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket);
+ current_connection_ = new RelayConnection(ra, socket, port()->thread());
+ for (size_t i = 0; i < port_->options().size(); ++i) {
+ current_connection_->SetSocketOption(port_->options()[i].first,
+ port_->options()[i].second);
+ }
+
+ // If we're trying UDP, start binding requests.
+ // If we're trying TCP, initiate a connection with a fixed timeout.
+ if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) {
+ talk_base::AsyncTCPSocket* tcp =
+ static_cast<talk_base::AsyncTCPSocket*>(socket);
+ tcp->SignalClose.connect(this, &RelayEntry::OnSocketClose);
+ tcp->SignalConnect.connect(this, &RelayEntry::OnSocketConnect);
+ tcp->Connect(ra->address);
+ port()->thread()->PostDelayed(kSoftConnectTimeoutMs, this,
+ kMessageConnectTimeout);
+ } else {
+ current_connection_->SendAllocateRequest(this, 0);
+ }
+}
+
+int RelayEntry::GetError() {
+ if (current_connection_ != NULL) {
+ return current_connection_->GetError();
+ }
+ return 0;
+}
+
+RelayConnection* RelayEntry::GetBestConnection(RelayConnection* conn1,
+ RelayConnection* conn2) {
+ return conn1->GetProtocol() <= conn2->GetProtocol() ? conn1 : conn2;
+}
+
+void RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr,
+ RelayConnection* connection) {
+ // We are connected, notify our parent.
ProtocolType proto = PROTO_UDP;
- LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto) << " @ " << mapped_addr.ToString();
+ LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto)
+ << " @ " << mapped_addr.ToString();
connected_ = true;
port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto));
@@ -393,8 +518,7 @@
}
int RelayEntry::SendTo(const void* data, size_t size,
- const talk_base::SocketAddress& addr) {
-
+ const talk_base::SocketAddress& addr) {
// If this connection is locked to the address given, then we can send the
// packet with no wrapper.
if (locked_ && (ext_addr_ == addr))
@@ -409,7 +533,7 @@
StunMessage request;
request.SetType(STUN_SEND_REQUEST);
- request.SetTransactionID(CreateRandomString(16));
+ request.SetTransactionID(talk_base::CreateRandomString(16));
StunByteStringAttribute* magic_cookie_attr =
StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
@@ -452,40 +576,79 @@
}
void RelayEntry::ScheduleKeepAlive() {
- requests_.SendDelayed(new AllocateRequest(this), KEEPALIVE_DELAY);
+ if (current_connection_) {
+ current_connection_->SendAllocateRequest(this, kKeepAliveDelay);
+ }
}
-void RelayEntry::HandleConnectFailure() {
- //if (GetMillisecondCount() - start_time_ > RETRY_TIMEOUT)
- // return;
- //ScheduleKeepAlive();
+int RelayEntry::SetSocketOption(talk_base::Socket::Option opt, int value) {
+ // Set the option on all available sockets.
+ int socket_error = 0;
+ if (current_connection_) {
+ socket_error = current_connection_->SetSocketOption(opt, value);
+ }
+ return socket_error;
+}
- connected_ = false;
- port()->DisposeSocket(socket_);
- socket_ = 0;
- requests_.Clear();
+void RelayEntry::HandleConnectFailure(
+ talk_base::AsyncPacketSocket* socket) {
+ // Make sure it's the current connection that has failed, it might
+ // be an old socked that has not yet been disposed.
+ if (!socket || socket == current_connection_->socket()) {
+ if (current_connection_)
+ port()->SignalConnectFailure(current_connection_->protocol_address());
- server_index_ += 1;
- Connect();
+ // Try to connect to the next server address.
+ server_index_ += 1;
+ Connect();
+ }
+}
+
+void RelayEntry::OnMessage(talk_base::Message *pmsg) {
+ ASSERT(pmsg->message_id == kMessageConnectTimeout);
+ if (current_connection_) {
+ const ProtocolAddress* ra = current_connection_->protocol_address();
+ LOG(LS_WARNING) << "Relay " << ra->proto << " connection to " <<
+ ra->address << " timed out";
+
+ // Currently we connect to each server address in sequence. If we
+ // have more addresses to try, treat this is an error and move on to
+ // the next address, otherwise give this connection more time and
+ // await the real timeout.
+ //
+ // TODO: Connect to servers in pararel to speed up connect time
+ // and to avoid giving up to early.
+ port_->SignalSoftTimeout(ra);
+ HandleConnectFailure(current_connection_->socket());
+ } else {
+ HandleConnectFailure(NULL);
+ }
}
void RelayEntry::OnSocketConnect(talk_base::AsyncTCPSocket* socket) {
- assert(socket == socket_);
- LOG(INFO) << "relay tcp connected to " << socket->GetRemoteAddress().ToString();
- requests_.Send(new AllocateRequest(this));
+ LOG(INFO) << "relay tcp connected to " <<
+ socket->GetRemoteAddress().ToString();
+ if (current_connection_ != NULL) {
+ current_connection_->SendAllocateRequest(this, 0);
+ }
}
void RelayEntry::OnSocketClose(talk_base::AsyncTCPSocket* socket, int error) {
- assert(socket == socket_);
- PLOG(LERROR, error) << "relay tcp connect failed";
- HandleConnectFailure();
+ PLOG(LERROR, error) << "Relay connection failed: socket closed";
+ HandleConnectFailure(socket);
}
void RelayEntry::OnReadPacket(const char* data, size_t size,
const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket) {
- assert(socket == socket_);
- //assert(remote_addr == port_->server_addr()); TODO: are we worried about this?
+ // ASSERT(remote_addr == port_->server_addr());
+ // TODO: are we worried about this?
+
+ if (current_connection_ == NULL || socket != current_connection_->socket()) {
+ // This packet comes from an unknown address.
+ LOG(WARNING) << "Dropping packet: unknown address";
+ return;
+ }
// If the magic cookie is not present, then this is an unwrapped packet sent
// by the server, The actual remote address is the one we recorded.
@@ -507,18 +670,18 @@
// The incoming packet should be a STUN ALLOCATE response, SEND response, or
// DATA indication.
- if (requests_.CheckResponse(&msg)) {
+ if (current_connection_->CheckResponse(&msg)) {
return;
} else if (msg.type() == STUN_SEND_RESPONSE) {
- if (const StunUInt32Attribute* options_attr = msg.GetUInt32(STUN_ATTR_OPTIONS)) {
+ if (const StunUInt32Attribute* options_attr =
+ msg.GetUInt32(STUN_ATTR_OPTIONS)) {
if (options_attr->value() & 0x1) {
locked_ = true;
}
}
return;
} else if (msg.type() != STUN_DATA_INDICATION) {
- LOG(INFO) << "Received BAD stun type from server: " << msg.type()
- ;
+ LOG(INFO) << "Received BAD stun type from server: " << msg.type();
return;
}
@@ -546,27 +709,20 @@
port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2);
}
-void RelayEntry::OnSendPacket(const void* data, size_t size, StunRequest* req) {
- SendPacket(data, size);
-}
-
int RelayEntry::SendPacket(const void* data, size_t size) {
- const ProtocolAddress * ra = port_->ServerAddress(server_index_);
- if (!ra) {
- if (socket_)
- socket_->SetError(ENOTCONN);
- return SOCKET_ERROR;
- }
- int sent = socket_->SendTo(data, size, ra->address);
- if (sent <= 0) {
- LOG(LS_VERBOSE) << "sendto: " << std::strerror(socket_->GetError());
- assert(sent < 0);
+ int sent = 0;
+ if (current_connection_) {
+ // We are connected, no need to send packets anywere else than to
+ // the current connection.
+ sent = current_connection_->Send(data, size);
}
return sent;
}
-AllocateRequest::AllocateRequest(RelayEntry* entry) : entry_(entry) {
- start_time_ = talk_base::GetMillisecondCount();
+AllocateRequest::AllocateRequest(RelayEntry* entry,
+ RelayConnection* connection) :
+ entry_(entry), connection_(connection) {
+ start_time_ = talk_base::Time();
}
void AllocateRequest::Prepare(StunMessage* request) {
@@ -604,7 +760,7 @@
LOG(INFO) << "Mapped address has bad family";
} else {
talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port());
- entry_->OnConnect(addr);
+ entry_->OnConnect(addr, connection_);
}
// We will do a keep-alive regardless of whether this request suceeds.
@@ -622,13 +778,13 @@
<< " reason='" << attr->reason() << "'";
}
- if (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)
+ if (talk_base::TimeSince(start_time_) <= kRetryTimeout)
entry_->ScheduleKeepAlive();
}
void AllocateRequest::OnTimeout() {
LOG(INFO) << "Allocate request timed out";
- entry_->HandleConnectFailure();
+ entry_->HandleConnectFailure(connection_->socket());
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/relayport.h b/talk/p2p/base/relayport.h
old mode 100755
new mode 100644
index 5691a6c..fd0f83d
--- a/talk/p2p/base/relayport.h
+++ b/talk/p2p/base/relayport.h
@@ -2,82 +2,100 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __RELAYPORT_H__
-#define __RELAYPORT_H__
+#ifndef TALK_P2P_BASE_RELAYPORT_H_
+#define TALK_P2P_BASE_RELAYPORT_H_
+#include <string>
+#include <vector>
#include "talk/p2p/base/port.h"
#include "talk/p2p/base/stunrequest.h"
-#include <vector>
namespace cricket {
extern const std::string RELAY_PORT_TYPE;
class RelayEntry;
+class RelayConnection;
-// Communicates using an allocated port on the relay server.
+// Communicates using an allocated port on the relay server. For each
+// remote candidate that we try to send data to a RelayEntry instance
+// is created. The RelayEntry will try to reach the remote destination
+// by connecting to all available server addresses in a pre defined
+// order with a small delay in between. When a connection is
+// successful all other connection attemts are aborted.
class RelayPort : public Port {
-public:
- RelayPort(
- talk_base::Thread* thread, talk_base::SocketFactory* factory,
- talk_base::Network*, const talk_base::SocketAddress& local_addr,
- const std::string& username, const std::string& password,
- const std::string& magic_cookie);
+ public:
+ typedef std::pair<talk_base::Socket::Option, int> OptionValue;
+
+ // RelayPort doesn't yet do anything fancy in the ctor.
+ static RelayPort* Create(
+ talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network* network, const talk_base::SocketAddress& local_addr,
+ const std::string& username, const std::string& password,
+ const std::string& magic_cookie) {
+ return new RelayPort(thread, factory, network, local_addr,
+ username, password, magic_cookie);
+ }
+ RelayPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network*, const talk_base::SocketAddress& local_addr,
+ const std::string& username, const std::string& password,
+ const std::string& magic_cookie);
+ bool Init();
virtual ~RelayPort();
void AddServerAddress(const ProtocolAddress& addr);
void AddExternalAddress(const ProtocolAddress& addr);
- typedef std::pair<talk_base::Socket::Option, int> OptionValue;
const std::vector<OptionValue>& options() const { return options_; }
-
const std::string& magic_cookie() const { return magic_cookie_; }
bool HasMagicCookie(const char* data, size_t size);
virtual void PrepareAddress();
- virtual Connection* CreateConnection(const Candidate& address, CandidateOrigin origin);
-
+ virtual Connection* CreateConnection(const Candidate& address,
+ CandidateOrigin origin);
virtual int SetOption(talk_base::Socket::Option opt, int value);
virtual int GetError();
const ProtocolAddress * ServerAddress(size_t index) const;
+ bool IsReady() { return ready_; }
- void DisposeSocket(talk_base::AsyncPacketSocket * socket);
+ // Used for testing.
+ sigslot::signal1<const ProtocolAddress*> SignalConnectFailure;
+ sigslot::signal1<const ProtocolAddress*> SignalSoftTimeout;
-protected:
+ protected:
void SetReady();
- virtual int SendTo(const void* data, size_t size,
- const talk_base::SocketAddress& addr, bool payload);
+ virtual int SendTo(const void* data, size_t size,
+ const talk_base::SocketAddress& addr, bool payload);
// Dispatches the given packet to the port or connection as appropriate.
- void OnReadPacket(
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ void OnReadPacket(const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr);
-private:
+ private:
friend class RelayEntry;
talk_base::SocketAddress local_addr_;
@@ -89,6 +107,6 @@
int error_;
};
-} // namespace cricket
+} // namespace cricket
-#endif // __RELAYPORT_H__
+#endif // TALK_P2P_BASE_RELAYPORT_H_
diff --git a/talk/p2p/base/relayserver.cc b/talk/p2p/base/relayserver.cc
old mode 100755
new mode 100644
index 1f4a979..525da34
--- a/talk/p2p/base/relayserver.cc
+++ b/talk/p2p/base/relayserver.cc
@@ -2,41 +2,41 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/p2p/base/relayserver.h"
-#include "talk/base/helpers.h"
-#include <algorithm>
-#include <cassert>
-#include <cstring>
-#include <iostream>
#ifdef POSIX
-extern "C" {
#include <errno.h>
-}
-#endif // POSIX
+#endif // POSIX
+
+#include <algorithm>
+
+#include "talk/base/asynctcpsocket.h"
+#include "talk/base/helpers.h"
+#include "talk/base/logging.h"
+#include "talk/base/socketadapters.h"
namespace cricket {
@@ -46,15 +46,17 @@
// The number of bytes in each of the usernames we use.
const uint32 USERNAME_LENGTH = 16;
+static const uint32 kMessageAcceptConnection = 1;
+
// Calls SendTo on the given socket and logs any bad results.
void Send(talk_base::AsyncPacketSocket* socket, const char* bytes, size_t size,
const talk_base::SocketAddress& addr) {
int result = socket->SendTo(bytes, size, addr);
- if (result < int(size)) {
- std::cerr << "SendTo wrote only " << result << " of " << int(size)
- << " bytes" << std::endl;
+ if (result < static_cast<int>(size)) {
+ LOG(LS_ERROR) << "SendTo wrote only " << result << " of " << size
+ << " bytes";
} else if (result < 0) {
- std::cerr << "SendTo: " << std::strerror(errno) << std::endl;
+ LOG_ERR(LS_ERROR) << "SendTo";
}
}
@@ -71,7 +73,6 @@
void SendStunError(const StunMessage& msg, talk_base::AsyncPacketSocket* socket,
const talk_base::SocketAddress& remote_addr, int error_code,
const char* error_desc, const std::string& magic_cookie) {
-
StunMessage err_msg;
err_msg.SetType(GetStunErrorResponseType(msg.type()));
err_msg.SetTransactionID(msg.transaction_id());
@@ -98,14 +99,22 @@
}
RelayServer::~RelayServer() {
- for (unsigned i = 0; i < internal_sockets_.size(); i++)
+ // Deleting the binding will cause it to be removed from the map.
+ while (!bindings_.empty())
+ delete bindings_.begin()->second;
+ for (size_t i = 0; i < internal_sockets_.size(); ++i)
delete internal_sockets_[i];
- for (unsigned i = 0; i < external_sockets_.size(); i++)
+ for (size_t i = 0; i < external_sockets_.size(); ++i)
delete external_sockets_[i];
+ while (!server_sockets_.empty()) {
+ talk_base::AsyncSocket* socket = server_sockets_.begin()->first;
+ server_sockets_.erase(server_sockets_.begin()->first);
+ delete socket;
+ }
}
void RelayServer::AddInternalSocket(talk_base::AsyncPacketSocket* socket) {
- assert(internal_sockets_.end() ==
+ ASSERT(internal_sockets_.end() ==
std::find(internal_sockets_.begin(), internal_sockets_.end(), socket));
internal_sockets_.push_back(socket);
socket->SignalReadPacket.connect(this, &RelayServer::OnInternalPacket);
@@ -114,13 +123,13 @@
void RelayServer::RemoveInternalSocket(talk_base::AsyncPacketSocket* socket) {
SocketList::iterator iter =
std::find(internal_sockets_.begin(), internal_sockets_.end(), socket);
- assert(iter != internal_sockets_.end());
+ ASSERT(iter != internal_sockets_.end());
internal_sockets_.erase(iter);
socket->SignalReadPacket.disconnect(this);
}
void RelayServer::AddExternalSocket(talk_base::AsyncPacketSocket* socket) {
- assert(external_sockets_.end() ==
+ ASSERT(external_sockets_.end() ==
std::find(external_sockets_.begin(), external_sockets_.end(), socket));
external_sockets_.push_back(socket);
socket->SignalReadPacket.connect(this, &RelayServer::OnExternalPacket);
@@ -129,18 +138,54 @@
void RelayServer::RemoveExternalSocket(talk_base::AsyncPacketSocket* socket) {
SocketList::iterator iter =
std::find(external_sockets_.begin(), external_sockets_.end(), socket);
- assert(iter != external_sockets_.end());
+ ASSERT(iter != external_sockets_.end());
external_sockets_.erase(iter);
socket->SignalReadPacket.disconnect(this);
}
+void RelayServer::AddInternalServerSocket(talk_base::AsyncSocket* socket,
+ cricket::ProtocolType proto) {
+ ASSERT(server_sockets_.end() ==
+ server_sockets_.find(socket));
+ server_sockets_[socket] = proto;
+ socket->SignalReadEvent.connect(this, &RelayServer::OnReadEvent);
+}
+
+void RelayServer::RemoveInternalServerSocket(
+ talk_base::AsyncSocket* socket) {
+ ServerSocketMap::iterator iter = server_sockets_.find(socket);
+ ASSERT(iter != server_sockets_.end());
+ server_sockets_.erase(iter);
+ socket->SignalReadEvent.disconnect(this);
+}
+
+int RelayServer::GetConnectionCount() {
+ return connections_.size();
+}
+
+bool RelayServer::HasConnection(const talk_base::SocketAddress& address) {
+ for (ConnectionMap::iterator it = connections_.begin();
+ it != connections_.end(); ++it) {
+ if (it->second->addr_pair().destination() == address) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void RelayServer::OnReadEvent(talk_base::AsyncSocket* socket) {
+ ServerSocketMap::iterator iter = server_sockets_.find(socket);
+ ASSERT(iter != server_sockets_.end());
+ AcceptConnection(socket);
+}
+
void RelayServer::OnInternalPacket(
const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket) {
// Get the address of the connection we just received on.
talk_base::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
- assert(!ap.destination().IsAny());
+ ASSERT(!ap.destination().IsAny());
// If this did not come from an existing connection, it should be a STUN
// allocate request.
@@ -162,7 +207,7 @@
// that this connection has been locked. (Otherwise, we would not know what
// address to forward to.)
if (!int_conn->locked()) {
- std::cerr << "Dropping packet: connection not locked" << std::endl;
+ LOG(LS_WARNING) << "Dropping packet: connection not locked";
return;
}
@@ -174,7 +219,7 @@
ext_conn->Send(bytes, size);
} else {
// This happens very often and is not an error.
- //std::cerr << "Dropping packet: no external connection" << std::endl;
+ LOG(LS_INFO) << "Dropping packet: no external connection";
}
}
@@ -184,7 +229,7 @@
// Get the address of the connection we just received on.
talk_base::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
- assert(!ap.destination().IsAny());
+ ASSERT(!ap.destination().IsAny());
// If this connection already exists, then forward the traffic.
ConnectionMap::iterator piter = connections_.find(ap);
@@ -194,7 +239,7 @@
RelayServerConnection* int_conn =
ext_conn->binding()->GetInternalConnection(
ext_conn->addr_pair().source());
- assert(int_conn);
+ ASSERT(int_conn != NULL);
int_conn->Send(bytes, size, ext_conn->addr_pair().source());
ext_conn->Lock(); // allow outgoing packets
return;
@@ -203,9 +248,9 @@
// The first packet should always be a STUN / TURN packet. If it isn't, then
// we should just ignore this packet.
StunMessage msg;
- talk_base::ByteBuffer buf = talk_base::ByteBuffer(bytes, size);
+ talk_base::ByteBuffer buf(bytes, size);
if (!msg.Read(&buf)) {
- std::cerr << "Dropping packet: first packet not STUN" << std::endl;
+ LOG(LS_WARNING) << "Dropping packet: first packet not STUN";
return;
}
@@ -213,19 +258,19 @@
const StunByteStringAttribute* username_attr =
msg.GetByteString(STUN_ATTR_USERNAME);
if (!username_attr) {
- std::cerr << "Dropping packet: no username" << std::endl;
+ LOG(LS_WARNING) << "Dropping packet: no username";
return;
}
- uint32 length = talk_base::_min(uint32(username_attr->length()), USERNAME_LENGTH);
+ uint32 length = talk_base::_min(static_cast<uint32>(username_attr->length()),
+ USERNAME_LENGTH);
std::string username(username_attr->bytes(), length);
// TODO: Check the HMAC.
// The binding should already be present.
BindingMap::iterator biter = bindings_.find(username);
if (biter == bindings_.end()) {
- // TODO: Turn this back on. This is the sign of a client bug.
- //std::cerr << "Dropping packet: no binding with username" << std::endl;
+ LOG(LS_WARNING) << "Dropping packet: no binding with username";
return;
}
@@ -242,16 +287,17 @@
// Send this message on the appropriate internal connection.
RelayServerConnection* int_conn = ext_conn->binding()->GetInternalConnection(
ext_conn->addr_pair().source());
- assert(int_conn);
+ ASSERT(int_conn != NULL);
int_conn->Send(bytes, size, ext_conn->addr_pair().source());
}
bool RelayServer::HandleStun(
const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr,
- talk_base::AsyncPacketSocket* socket, std::string* username, StunMessage* msg) {
+ talk_base::AsyncPacketSocket* socket, std::string* username,
+ StunMessage* msg) {
// Parse this into a stun message.
- talk_base::ByteBuffer buf = talk_base::ByteBuffer(bytes, size);
+ talk_base::ByteBuffer buf(bytes, size);
if (!msg->Read(&buf)) {
SendStunError(*msg, socket, remote_addr, 400, "Bad Request", "");
return false;
@@ -303,11 +349,8 @@
BindingMap::iterator biter = bindings_.find(username);
if (biter != bindings_.end()) {
-
binding = biter->second;
-
} else {
-
// NOTE: In the future, bindings will be created by the bot only. This
// else-branch will then disappear.
@@ -323,8 +366,8 @@
bindings_[username] = binding;
if (log_bindings_) {
- std::cout << "Added new binding: " << bindings_.size() << " total"
- << std::endl;
+ LOG(LS_INFO) << "Added new binding " << username << ", "
+ << bindings_.size() << " total";
}
}
@@ -382,7 +425,8 @@
response.AddAttribute(magic_cookie_attr);
size_t index = rand() % external_sockets_.size();
- talk_base::SocketAddress ext_addr = external_sockets_[index]->GetLocalAddress();
+ talk_base::SocketAddress ext_addr =
+ external_sockets_[index]->GetLocalAddress();
StunAddressAttribute* addr_attr =
StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
@@ -426,7 +470,7 @@
int_conn->binding()->GetExternalConnection(ext_addr);
if (!ext_conn) {
// Create a new connection to establish the relationship with this binding.
- assert(external_sockets_.size() == 1);
+ ASSERT(external_sockets_.size() == 1);
talk_base::AsyncPacketSocket* socket = external_sockets_[0];
talk_base::SocketAddressPair ap(ext_addr, socket->GetLocalAddress());
ext_conn = new RelayServerConnection(int_conn->binding(), ap, socket);
@@ -440,7 +484,7 @@
const StunUInt32Attribute* options_attr =
request.GetUInt32(STUN_ATTR_OPTIONS);
- if (options_attr && (options_attr->value() & 0x01 != 0)) {
+ if (options_attr && (options_attr->value() & 0x01)) {
int_conn->set_default_destination(ext_addr);
int_conn->Lock();
@@ -458,43 +502,74 @@
StunAttribute::CreateUInt32(cricket::STUN_ATTR_OPTIONS);
options2_attr->SetValue(0x01);
response.AddAttribute(options2_attr);
-
+
int_conn->SendStun(response);
}
}
void RelayServer::AddConnection(RelayServerConnection* conn) {
- assert(connections_.find(conn->addr_pair()) == connections_.end());
+ ASSERT(connections_.find(conn->addr_pair()) == connections_.end());
connections_[conn->addr_pair()] = conn;
}
void RelayServer::RemoveConnection(RelayServerConnection* conn) {
ConnectionMap::iterator iter = connections_.find(conn->addr_pair());
- assert(iter != connections_.end());
+ ASSERT(iter != connections_.end());
connections_.erase(iter);
}
void RelayServer::RemoveBinding(RelayServerBinding* binding) {
BindingMap::iterator iter = bindings_.find(binding->username());
- assert(iter != bindings_.end());
+ ASSERT(iter != bindings_.end());
bindings_.erase(iter);
if (log_bindings_) {
- std::cout << "Removed a binding: " << bindings_.size() << " remaining"
- << std::endl;
+ LOG(LS_INFO) << "Removed binding " << binding->username() << ", "
+ << bindings_.size() << " remaining";
}
}
+void RelayServer::OnMessage(talk_base::Message *pmsg) {
+ ASSERT(pmsg->message_id == kMessageAcceptConnection);
+ talk_base::MessageData* data = pmsg->pdata;
+ talk_base::AsyncSocket* socket =
+ static_cast <talk_base::TypedMessageData<talk_base::AsyncSocket*>*>
+ (data)->data();
+ AcceptConnection(socket);
+ delete data;
+}
+
void RelayServer::OnTimeout(RelayServerBinding* binding) {
- // This call will result in all of the necessary clean-up.
- delete binding;
+ // This call will result in all of the necessary clean-up. We can't call
+ // delete here, because you can't delete an object that is signaling you.
+ thread_->Dispose(binding);
+}
+
+void RelayServer::AcceptConnection(talk_base::AsyncSocket* server_socket) {
+ // Check if someone is trying to connect to us.
+ talk_base::SocketAddress accept_addr;
+ talk_base::AsyncSocket* accepted_socket =
+ server_socket->Accept(&accept_addr);
+ if (accepted_socket != NULL) {
+ // We had someone trying to connect, now check which protocol to
+ // use and create a packet socket.
+ ASSERT(server_sockets_[server_socket] == cricket::PROTO_TCP ||
+ server_sockets_[server_socket] == cricket::PROTO_SSLTCP);
+ if (server_sockets_[server_socket] == cricket::PROTO_SSLTCP) {
+ accepted_socket = new talk_base::AsyncSSLServerSocket(accepted_socket);
+ }
+ talk_base::AsyncTCPSocket* tcp_socket =
+ new talk_base::AsyncTCPSocket(accepted_socket);
+
+ // Finally add the socket so it can start communicating with the client.
+ AddInternalSocket(tcp_socket);
+ }
}
RelayServerConnection::RelayServerConnection(
RelayServerBinding* binding, const talk_base::SocketAddressPair& addrs,
talk_base::AsyncPacketSocket* socket)
: binding_(binding), addr_pair_(addrs), socket_(socket), locked_(false) {
-
// The creation of a new connection constitutes a use of the binding.
binding_->NoteUsed();
}
@@ -540,7 +615,7 @@
StunByteStringAttribute* data_attr =
StunAttribute::CreateByteString(STUN_ATTR_DATA);
- assert(size <= 65536);
+ ASSERT(size <= 65536);
data_attr->CopyBytes(data, uint16(size));
msg.AddAttribute(data_attr);
@@ -580,7 +655,6 @@
const std::string& password, uint32 lifetime)
: server_(server), username_(username), password_(password),
lifetime_(lifetime) {
-
// For now, every connection uses the standard magic cookie value.
magic_cookie_.append(
reinterpret_cast<const char*>(STUN_MAGIC_COOKIE_VALUE), 4);
@@ -638,7 +712,7 @@
}
// If one was not found, we send to the first connection.
- assert(internal_connections_.size() > 0);
+ ASSERT(internal_connections_.size() > 0);
return internal_connections_[0];
}
@@ -653,19 +727,20 @@
void RelayServerBinding::OnMessage(talk_base::Message *pmsg) {
if (pmsg->message_id == MSG_LIFETIME_TIMER) {
- assert(!pmsg->pdata);
+ ASSERT(!pmsg->pdata);
// If the lifetime timeout has been exceeded, then send a signal.
// Otherwise, just keep waiting.
if (talk_base::Time() >= last_used_ + lifetime_) {
+ LOG(LS_INFO) << "Expiring binding " << username_;
SignalTimeout(this);
} else {
server_->thread()->PostDelayed(lifetime_, this, MSG_LIFETIME_TIMER);
}
} else {
- assert(false);
+ ASSERT(false);
}
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/relayserver.h b/talk/p2p/base/relayserver.h
old mode 100755
new mode 100644
index b99c632..3337991
--- a/talk/p2p/base/relayserver.h
+++ b/talk/p2p/base/relayserver.h
@@ -32,6 +32,7 @@
#include "talk/base/socketaddresspair.h"
#include "talk/base/thread.h"
#include "talk/base/time.h"
+#include "talk/p2p/base/port.h"
#include "talk/p2p/base/stun.h"
#include <string>
@@ -45,7 +46,8 @@
// Relays traffic between connections to the server that are "bound" together.
// All connections created with the same username/password are bound together.
-class RelayServer : public sigslot::has_slots<> {
+class RelayServer : public talk_base::MessageHandler,
+ public sigslot::has_slots<> {
public:
// Creates a server, which will use this thread to post messages to itself.
RelayServer(talk_base::Thread* thread);
@@ -68,8 +70,23 @@
void AddExternalSocket(talk_base::AsyncPacketSocket* socket);
void RemoveExternalSocket(talk_base::AsyncPacketSocket* socket);
+ // Starts listening for connections on this sockets. When someone
+ // tries to connect, the connection will be accepted and a new
+ // internal socket will be added.
+ void AddInternalServerSocket(talk_base::AsyncSocket* socket,
+ cricket::ProtocolType proto);
+
+ // Removes this server socket from the list.
+ void RemoveInternalServerSocket(talk_base::AsyncSocket* socket);
+
+ int GetConnectionCount();
+
+ bool HasConnection(const talk_base::SocketAddress& address);
+
private:
typedef std::vector<talk_base::AsyncPacketSocket*> SocketList;
+ typedef std::map<talk_base::AsyncSocket*,
+ cricket::ProtocolType> ServerSocketMap;
typedef std::map<std::string,RelayServerBinding*> BindingMap;
typedef std::map<talk_base::SocketAddressPair,RelayServerConnection*> ConnectionMap;
@@ -77,6 +94,7 @@
bool log_bindings_;
SocketList internal_sockets_;
SocketList external_sockets_;
+ ServerSocketMap server_sockets_;
BindingMap bindings_;
ConnectionMap connections_;
@@ -88,6 +106,8 @@
const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket);
+ void OnReadEvent(talk_base::AsyncSocket* socket);
+
// Processes the relevant STUN request types from the client.
bool HandleStun(const char* bytes, size_t size,
const talk_base::SocketAddress& remote_addr, talk_base::AsyncPacketSocket* socket,
@@ -106,9 +126,15 @@
void RemoveConnection(RelayServerConnection* conn);
void RemoveBinding(RelayServerBinding* binding);
+ // Handle messages in our worker thread.
+ void OnMessage(talk_base::Message *pmsg);
+
// Called when the timer for checking lifetime times out.
void OnTimeout(RelayServerBinding* binding);
+ // Accept connections on this server socket.
+ void AcceptConnection(talk_base::AsyncSocket* server_socket);
+
friend class RelayServerConnection;
friend class RelayServerBinding;
};
diff --git a/talk/p2p/base/relayserver_main.cc b/talk/p2p/base/relayserver_main.cc
old mode 100755
new mode 100644
index cdd5fff..2f07458
--- a/talk/p2p/base/relayserver_main.cc
+++ b/talk/p2p/base/relayserver_main.cc
@@ -25,47 +25,52 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <cassert>
-#include <iostream>
-#include "talk/base/host.h"
+#include <iostream> // NOLINT
+
#include "talk/base/thread.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/p2p/base/relayserver.h"
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-using namespace cricket;
-
int main(int argc, char **argv) {
- if (argc != 1) {
- std::cerr << "usage: relayserver" << std::endl;
+ if (argc != 3) {
+ std::cerr << "usage: relayserver internal-address external-address"
+ << std::endl;
return 1;
}
- assert(talk_base::LocalHost().networks().size() >= 2);
- talk_base::SocketAddress int_addr(talk_base::LocalHost().networks()[1]->ip(), 5000);
- talk_base::SocketAddress ext_addr(talk_base::LocalHost().networks()[1]->ip(), 5001);
-
- talk_base::Thread *pthMain = talk_base::Thread::Current();
-
- talk_base::AsyncUDPSocket* int_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver());
+ talk_base::SocketAddress int_addr;
+ if (!int_addr.FromString(argv[1])) {
+ std::cerr << "Unable to parse IP address: " << argv[1];
+ return 1;
+ }
+
+ talk_base::SocketAddress ext_addr;
+ if (!ext_addr.FromString(argv[2])) {
+ std::cerr << "Unable to parse IP address: " << argv[2];
+ return 1;
+ }
+
+ talk_base::Thread *pthMain = talk_base::Thread::Current();
+
+ talk_base::scoped_ptr<talk_base::AsyncUDPSocket> int_socket(
+ talk_base::CreateAsyncUDPSocket(pthMain->socketserver()));
if (int_socket->Bind(int_addr) < 0) {
- std::cerr << "bind: " << std::strerror(errno) << std::endl;
+ std::cerr << "Internal socket bind(" << int_addr.ToString() << "): "
+ << std::strerror(int_socket->GetError()) << std::endl;
return 1;
}
- talk_base::AsyncUDPSocket* ext_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver());
+ talk_base::scoped_ptr<talk_base::AsyncUDPSocket> ext_socket(
+ talk_base::CreateAsyncUDPSocket(pthMain->socketserver()));
if (ext_socket->Bind(ext_addr) < 0) {
- std::cerr << "bind: " << std::strerror(errno) << std::endl;
+ std::cerr << "External socket bind(" << ext_addr.ToString() << "): "
+ << std::strerror(ext_socket->GetError()) << std::endl;
return 1;
}
- RelayServer server(pthMain);
- server.AddInternalSocket(int_socket);
- server.AddExternalSocket(ext_socket);
+ cricket::RelayServer server(pthMain);
+ server.AddInternalSocket(int_socket.get());
+ server.AddExternalSocket(ext_socket.get());
std::cout << "Listening internally at " << int_addr.ToString() << std::endl;
std::cout << "Listening externally at " << ext_addr.ToString() << std::endl;
diff --git a/talk/p2p/base/session.cc b/talk/p2p/base/session.cc
old mode 100755
new mode 100644
index 1ea0dc3..806c025
--- a/talk/p2p/base/session.cc
+++ b/talk/p2p/base/session.cc
@@ -29,12 +29,15 @@
#include "talk/base/common.h"
#include "talk/base/logging.h"
#include "talk/base/helpers.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/xmpp/constants.h"
#include "talk/xmpp/jid.h"
#include "talk/p2p/base/sessionclient.h"
#include "talk/p2p/base/transport.h"
#include "talk/p2p/base/transportchannelproxy.h"
#include "talk/p2p/base/p2ptransport.h"
+#include "talk/p2p/base/p2ptransportchannel.h"
+
#include "talk/p2p/base/constants.h"
namespace {
@@ -43,63 +46,236 @@
const uint32 MSG_ERROR = 2;
const uint32 MSG_STATE = 3;
-// This will be initialized at run time to hold the list of default transports.
-std::string* gDefaultTransports = NULL;
-size_t gNumDefaultTransports = 0;
-
} // namespace
namespace cricket {
-Session::Session(SessionManager *session_manager, const std::string& name,
- const SessionID& id, const std::string& session_type,
- SessionClient* client) {
+bool BadMessage(const buzz::QName type,
+ const std::string& text,
+ MessageError* err) {
+ err->SetType(type);
+ err->SetText(text);
+ return false;
+}
+
+TransportProxy::~TransportProxy() {
+ for (ChannelMap::iterator iter = channels_.begin();
+ iter != channels_.end(); ++iter) {
+ iter->second->SignalDestroyed(iter->second);
+ delete iter->second;
+ }
+ delete transport_;
+}
+
+std::string TransportProxy::type() const {
+ return transport_->type();
+}
+
+TransportChannel* TransportProxy::GetChannel(const std::string& name) {
+ return GetProxy(name);
+}
+
+TransportChannel* TransportProxy::CreateChannel(
+ const std::string& name, const std::string& content_type) {
+ ASSERT(GetChannel(name) == NULL);
+ ASSERT(!transport_->HasChannel(name));
+
+ // We always create a proxy in case we need to change out the transport later.
+ TransportChannelProxy* channel =
+ new TransportChannelProxy(name, content_type);
+ channels_[name] = channel;
+
+ if (state_ == STATE_NEGOTIATED) {
+ SetProxyImpl(name, channel);
+ } else if (state_ == STATE_CONNECTING) {
+ GetOrCreateImpl(name, content_type);
+ }
+ return channel;
+}
+
+void TransportProxy::DestroyChannel(const std::string& name) {
+ TransportChannel* channel = GetChannel(name);
+ if (channel) {
+ channels_.erase(name);
+ channel->SignalDestroyed(channel);
+ delete channel;
+ }
+}
+
+void TransportProxy::SpeculativelyConnectChannels() {
+ ASSERT(state_ == STATE_INIT || state_ == STATE_CONNECTING);
+ state_ = STATE_CONNECTING;
+ for (ChannelMap::iterator iter = channels_.begin();
+ iter != channels_.end(); ++iter) {
+ GetOrCreateImpl(iter->first, iter->second->content_type());
+ }
+ transport_->ConnectChannels();
+}
+
+void TransportProxy::CompleteNegotiation() {
+ if (state_ != STATE_NEGOTIATED) {
+ state_ = STATE_NEGOTIATED;
+ for (ChannelMap::iterator iter = channels_.begin();
+ iter != channels_.end(); ++iter) {
+ SetProxyImpl(iter->first, iter->second);
+ }
+ transport_->ConnectChannels();
+ }
+}
+
+void TransportProxy::AddSentCandidates(const Candidates& candidates) {
+ for (Candidates::const_iterator cand = candidates.begin();
+ cand != candidates.end(); ++cand) {
+ sent_candidates_.push_back(*cand);
+ }
+}
+
+
+TransportChannelProxy* TransportProxy::GetProxy(const std::string& name) {
+ ChannelMap::iterator iter = channels_.find(name);
+ return (iter != channels_.end()) ? iter->second : NULL;
+}
+
+TransportChannelImpl* TransportProxy::GetOrCreateImpl(
+ const std::string& name, const std::string& content_type) {
+ TransportChannelImpl* impl = transport_->GetChannel(name);
+ if (impl == NULL) {
+ impl = transport_->CreateChannel(name, content_type);
+ }
+ return impl;
+}
+
+void TransportProxy::SetProxyImpl(
+ const std::string& name, TransportChannelProxy* proxy) {
+ TransportChannelImpl* impl = GetOrCreateImpl(name, proxy->content_type());
+ ASSERT(impl != NULL);
+ proxy->SetImplementation(impl);
+}
+
+
+
+
+BaseSession::BaseSession(talk_base::Thread *signaling_thread)
+ : state_(STATE_INIT), error_(ERROR_NONE),
+ local_description_(NULL), remote_description_(NULL),
+ signaling_thread_(signaling_thread) {
+}
+
+BaseSession::~BaseSession() {
+ delete remote_description_;
+ delete local_description_;
+}
+
+void BaseSession::SetState(State state) {
+ ASSERT(signaling_thread_->IsCurrent());
+ if (state != state_) {
+ state_ = state;
+ SignalState(this, state_);
+ signaling_thread_->Post(this, MSG_STATE);
+ }
+}
+
+void BaseSession::SetError(Error error) {
+ ASSERT(signaling_thread_->IsCurrent());
+ if (error != error_) {
+ error_ = error;
+ SignalError(this, error);
+ if (error_ != ERROR_NONE)
+ signaling_thread_->Post(this, MSG_ERROR);
+ }
+}
+
+void BaseSession::OnMessage(talk_base::Message *pmsg) {
+ switch (pmsg->message_id) {
+ case MSG_TIMEOUT:
+ // Session timeout has occured.
+ SetError(ERROR_TIME);
+ break;
+
+ case MSG_ERROR:
+ TerminateWithReason(STR_TERMINATE_ERROR);
+ break;
+
+ case MSG_STATE:
+ switch (state_) {
+ case STATE_SENTACCEPT:
+ case STATE_RECEIVEDACCEPT:
+ SetState(STATE_INPROGRESS);
+ break;
+
+ case STATE_SENTREJECT:
+ case STATE_RECEIVEDREJECT:
+ // Assume clean termination.
+ Terminate();
+ break;
+
+ default:
+ // Explicitly ignoring some states here.
+ break;
+ }
+ break;
+ }
+}
+
+
+Session::Session(SessionManager *session_manager,
+ const std::string& local_name,
+ const std::string& initiator_name,
+ const std::string& sid, const std::string& content_type,
+ SessionClient* client) :
+ BaseSession(session_manager->signaling_thread()) {
ASSERT(session_manager->signaling_thread()->IsCurrent());
ASSERT(client != NULL);
session_manager_ = session_manager;
- name_ = name;
- id_ = id;
- session_type_ = session_type;
+ local_name_ = local_name;
+ sid_ = sid;
+ initiator_name_ = initiator_name;
+ content_type_ = content_type;
+ // TODO: Once we support different transport types,
+ // don't hard code this here.
+ transport_type_ = NS_GINGLE_P2P;
+ transport_parser_ = new P2PTransportParser();
client_ = client;
error_ = ERROR_NONE;
state_ = STATE_INIT;
initiator_ = false;
- description_ = NULL;
- remote_description_ = NULL;
- transport_ = NULL;
- compatibility_mode_ = false;
+ current_protocol_ = PROTOCOL_HYBRID;
}
Session::~Session() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread_->IsCurrent());
ASSERT(state_ != STATE_DEINIT);
state_ = STATE_DEINIT;
SignalState(this, state_);
- delete description_;
- delete remote_description_;
-
- for (ChannelMap::iterator iter = channels_.begin();
- iter != channels_.end();
- ++iter) {
- iter->second->SignalDestroyed(iter->second);
+ for (TransportMap::iterator iter = transports_.begin();
+ iter != transports_.end(); ++iter) {
delete iter->second;
}
- for (TransportList::iterator iter = potential_transports_.begin();
- iter != potential_transports_.end();
- ++iter) {
- delete *iter;
- }
+ delete transport_parser_;
+}
- delete transport_;
+Transport* Session::GetTransport(const std::string& content_name) {
+ TransportProxy* transproxy = GetTransportProxy(content_name);
+ if (transproxy == NULL)
+ return NULL;
+ return transproxy->impl();
+}
+
+void Session::set_allow_local_ips(bool allow) {
+ allow_local_ips_ = allow;
+ for (TransportMap::iterator iter = transports_.begin();
+ iter != transports_.end(); ++iter) {
+ iter->second->impl()->set_allow_local_ips(allow);
+ }
}
bool Session::Initiate(const std::string &to,
- std::vector<buzz::XmlElement*>* extra_xml,
- const SessionDescription *description) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ const SessionDescription* sdesc) {
+ ASSERT(signaling_thread_->IsCurrent());
+ SessionError error;
// Only from STATE_INIT
if (state_ != STATE_INIT)
@@ -108,69 +284,26 @@
// Setup for signaling.
remote_name_ = to;
initiator_ = true;
- description_ = description;
-
- // Make sure we have transports to negotiate.
- CreateTransports();
-
- // Send the initiate message, including the application and transport offers.
- XmlElements elems;
- elems.push_back(client_->TranslateSessionDescription(description));
- for (TransportList::iterator iter = potential_transports_.begin();
- iter != potential_transports_.end();
- ++iter) {
- buzz::XmlElement* elem = (*iter)->CreateTransportOffer();
- elems.push_back(elem);
+ set_local_description(sdesc);
+ if (!CreateTransportProxies(GetEmptyTransportInfos(sdesc->contents()),
+ &error)) {
+ LOG(LS_ERROR) << "Could not create transports: " << error.text;
+ return false;
}
- if (extra_xml != NULL) {
- std::vector<buzz::XmlElement*>::iterator iter = extra_xml->begin();
- for (std::vector<buzz::XmlElement*>::iterator iter = extra_xml->begin();
- iter != extra_xml->end();
- ++iter) {
- elems.push_back(new buzz::XmlElement(**iter));
- }
+ if (!SendInitiateMessage(sdesc, &error)) {
+ LOG(LS_ERROR) << "Could not send initiate message: " << error.text;
+ return false;
}
-
- SendSessionMessage("initiate", elems);
SetState(Session::STATE_SENTINITIATE);
- // We speculatively start attempting connection of the P2P transports.
- ConnectDefaultTransportChannels(true);
+ SpeculativelyConnectAllTransportChannels();
return true;
}
-void Session::ConnectDefaultTransportChannels(bool create) {
- Transport* transport = GetTransport(kNsP2pTransport);
- if (transport) {
- for (ChannelMap::iterator iter = channels_.begin();
- iter != channels_.end();
- ++iter) {
- ASSERT(create != transport->HasChannel(iter->first));
- if (create) {
- transport->CreateChannel(iter->first, session_type());
- }
- }
- transport->ConnectChannels();
- }
-}
-
-void Session::CreateDefaultTransportChannel(const std::string& name) {
- // This method is only relevant when we have created the default transport
- // but not received a transport-accept.
- ASSERT(transport_ == NULL);
- ASSERT(state_ == STATE_SENTINITIATE);
-
- Transport* p2p_transport = GetTransport(kNsP2pTransport);
- if (p2p_transport) {
- ASSERT(!p2p_transport->HasChannel(name));
- p2p_transport->CreateChannel(name, session_type());
- }
-}
-
-bool Session::Accept(const SessionDescription *description) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+bool Session::Accept(const SessionDescription* sdesc) {
+ ASSERT(signaling_thread_->IsCurrent());
// Only if just received initiate
if (state_ != STATE_RECEIVEDINITIATE)
@@ -178,23 +311,20 @@
// Setup for signaling.
initiator_ = false;
- description_ = description;
+ set_local_description(sdesc);
- // If we haven't selected a transport, wait for ChooseTransport to complete
- if (transport_ == NULL)
- return true;
+ SessionError error;
+ if (!SendAcceptMessage(sdesc, &error)) {
+ LOG(LS_ERROR) << "Could not send accept message: " << error.text;
+ return false;
+ }
- // Send the accept message.
- XmlElements elems;
- elems.push_back(client_->TranslateSessionDescription(description_));
- SendSessionMessage("accept", elems);
SetState(Session::STATE_SENTACCEPT);
-
return true;
}
-bool Session::Reject() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+bool Session::Reject(const std::string& reason) {
+ ASSERT(signaling_thread_->IsCurrent());
// Reject is sent in response to an initiate or modify, to reject the
// request
@@ -204,49 +334,18 @@
// Setup for signaling.
initiator_ = false;
- // Send the reject message.
- SendSessionMessage("reject", XmlElements());
- SetState(STATE_SENTREJECT);
-
- return true;
-}
-
-bool Session::Redirect(const std::string & target) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
-
- // Redirect is sent in response to an initiate or modify, to redirect the
- // request
- if (state_ != STATE_RECEIVEDINITIATE)
+ SessionError error;
+ if (!SendRejectMessage(reason, &error)) {
+ LOG(LS_ERROR) << "Could not send reject message: " << error.text;
return false;
+ }
- // Setup for signaling.
- initiator_ = false;
-
- // Send a redirect message to the given target. We include an element that
- // names the redirector (us), which may be useful to the other side.
-
- buzz::XmlElement* target_elem = new buzz::XmlElement(QN_REDIRECT_TARGET);
- target_elem->AddAttr(buzz::QN_NAME, target);
-
- buzz::XmlElement* cookie = new buzz::XmlElement(QN_REDIRECT_COOKIE);
- buzz::XmlElement* regarding = new buzz::XmlElement(QN_REDIRECT_REGARDING);
- regarding->AddAttr(buzz::QN_NAME, name_);
- cookie->AddElement(regarding);
-
- XmlElements elems;
- elems.push_back(target_elem);
- elems.push_back(cookie);
- SendSessionMessage("redirect", elems);
-
- // A redirect puts us in the same state as reject. It just sends a different
- // kind of reject message, if you like.
- SetState(STATE_SENTREDIRECT);
-
+ SetState(STATE_SENTREJECT);
return true;
}
-bool Session::Terminate() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+bool Session::TerminateWithReason(const std::string& reason) {
+ ASSERT(signaling_thread_->IsCurrent());
// Either side can terminate, at any time.
switch (state_) {
@@ -254,10 +353,6 @@
case STATE_RECEIVEDTERMINATE:
return false;
- case STATE_SENTREDIRECT:
- // We must not send terminate if we redirect.
- break;
-
case STATE_SENTREJECT:
case STATE_RECEIVEDREJECT:
// We don't need to send terminate if we sent or received a reject...
@@ -265,7 +360,11 @@
break;
default:
- SendSessionMessage("terminate", XmlElements());
+ SessionError error;
+ if (!SendTerminateMessage(reason, &error)) {
+ LOG(LS_ERROR) << "Could not send terminate message: " << error.text;
+ return false;
+ }
break;
}
@@ -273,245 +372,153 @@
return true;
}
-void Session::SendInfoMessage(const XmlElements& elems) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- SendSessionMessage("info", elems);
-}
-
-void Session::SetPotentialTransports(const std::string names[], size_t length) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- for (size_t i = 0; i < length; ++i) {
- Transport* transport = NULL;
- if (names[i] == kNsP2pTransport) {
- transport = new P2PTransport(session_manager_);
- } else {
- ASSERT(false);
- }
-
- if (transport) {
- ASSERT(transport->name() == names[i]);
- potential_transports_.push_back(transport);
- transport->SignalConnecting.connect(
- this, &Session::OnTransportConnecting);
- transport->SignalWritableState.connect(
- this, &Session::OnTransportWritable);
- transport->SignalRequestSignaling.connect(
- this, &Session::OnTransportRequestSignaling);
- transport->SignalTransportMessage.connect(
- this, &Session::OnTransportSendMessage);
- transport->SignalTransportError.connect(
- this, &Session::OnTransportSendError);
- transport->SignalChannelGone.connect(
- this, &Session::OnTransportChannelGone);
- }
+bool Session::SendInfoMessage(const XmlElements& elems) {
+ ASSERT(signaling_thread_->IsCurrent());
+ SessionError error;
+ if (!SendMessage(ACTION_SESSION_INFO, elems, &error)) {
+ LOG(LS_ERROR) << "Could not send info message " << error.text;
+ return false;
}
+ return true;
}
-Transport* Session::GetTransport(const std::string& name) {
- if (transport_ != NULL) {
- if (name == transport_->name())
- return transport_;
- } else {
- for (TransportList::iterator iter = potential_transports_.begin();
- iter != potential_transports_.end();
- ++iter) {
- if (name == (*iter)->name())
- return *iter;
+
+TransportProxy* Session::GetTransportProxy(const Transport* transport) {
+ for (TransportMap::iterator iter = transports_.begin();
+ iter != transports_.end(); ++iter) {
+ TransportProxy* transproxy = iter->second;
+ if (transproxy->impl() == transport) {
+ return transproxy;
}
}
return NULL;
}
-TransportChannel* Session::CreateChannel(const std::string& name) {
- //ASSERT(session_manager_->signaling_thread()->IsCurrent());
- ASSERT(channels_.find(name) == channels_.end());
- TransportChannelProxy* channel = new TransportChannelProxy(name, session_type_);
- channels_[name] = channel;
- if (transport_) {
- ASSERT(!transport_->HasChannel(name));
- channel->SetImplementation(transport_->CreateChannel(name, session_type_));
- } else if (state_ == STATE_SENTINITIATE) {
- // In this case, we have already speculatively created the default
- // transport. We should create this channel as well so that it may begin
- // early connection.
- CreateDefaultTransportChannel(name);
+TransportProxy* Session::GetTransportProxy(const std::string& content_name) {
+ TransportMap::iterator iter = transports_.find(content_name);
+ return (iter != transports_.end()) ? iter->second : NULL;
+}
+
+TransportProxy* Session::GetFirstTransportProxy() {
+ if (transports_.empty())
+ return NULL;
+ return transports_.begin()->second;
+}
+
+TransportInfos Session::GetEmptyTransportInfos(
+ const ContentInfos& contents) const {
+ TransportInfos tinfos;
+ for (ContentInfos::const_iterator content = contents.begin();
+ content != contents.end(); ++content) {
+ tinfos.push_back(
+ TransportInfo(content->name, transport_type_, Candidates()));
}
- return channel;
+ return tinfos;
}
-TransportChannel* Session::GetChannel(const std::string& name) {
- ChannelMap::iterator iter = channels_.find(name);
- return (iter != channels_.end()) ? iter->second : NULL;
+TransportProxy* Session::GetOrCreateTransportProxy(
+ const std::string& content_name) {
+ TransportProxy* transproxy = GetTransportProxy(content_name);
+ if (transproxy)
+ return transproxy;
+
+ Transport* transport =
+ new P2PTransport(signaling_thread_,
+ session_manager_->worker_thread(),
+ session_manager_->port_allocator());
+ transport->set_allow_local_ips(allow_local_ips_);
+ transport->SignalConnecting.connect(
+ this, &Session::OnTransportConnecting);
+ transport->SignalWritableState.connect(
+ this, &Session::OnTransportWritable);
+ transport->SignalRequestSignaling.connect(
+ this, &Session::OnTransportRequestSignaling);
+ transport->SignalCandidatesReady.connect(
+ this, &Session::OnTransportCandidatesReady);
+ transport->SignalTransportError.connect(
+ this, &Session::OnTransportSendError);
+ transport->SignalChannelGone.connect(
+ this, &Session::OnTransportChannelGone);
+
+ transproxy = new TransportProxy(content_name, transport);
+ transports_[content_name] = transproxy;
+
+ return transproxy;
}
-void Session::DestroyChannel(TransportChannel* channel) {
- ChannelMap::iterator iter = channels_.find(channel->name());
- ASSERT(iter != channels_.end());
- ASSERT(channel == iter->second);
- channels_.erase(iter);
- channel->SignalDestroyed(channel);
- delete channel;
-}
-
-TransportChannelImpl* Session::GetImplementation(TransportChannel* channel) {
- ChannelMap::iterator iter = channels_.find(channel->name());
- return (iter != channels_.end()) ? iter->second->impl() : NULL;
-}
-
-void Session::CreateTransports() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- ASSERT((state_ == STATE_INIT)
- || (state_ == STATE_RECEIVEDINITIATE));
- if (potential_transports_.empty()) {
- if (gDefaultTransports == NULL) {
- gNumDefaultTransports = 1;
- gDefaultTransports = new std::string[1];
- gDefaultTransports[0] = kNsP2pTransport;
+bool Session::CreateTransportProxies(const TransportInfos& tinfos,
+ SessionError* error) {
+ for (TransportInfos::const_iterator tinfo = tinfos.begin();
+ tinfo != tinfos.end(); ++tinfo) {
+ if (tinfo->transport_type != transport_type_) {
+ error->SetText("No supported transport in offer.");
+ return false;
}
- SetPotentialTransports(gDefaultTransports, gNumDefaultTransports);
+
+ GetOrCreateTransportProxy(tinfo->content_name);
}
-}
-
-bool Session::ChooseTransport(const buzz::XmlElement* stanza) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- ASSERT(state_ == STATE_RECEIVEDINITIATE);
- ASSERT(transport_ == NULL);
-
- // Make sure we have decided on our own transports.
- CreateTransports();
-
- // Retrieve the session message.
- const buzz::XmlElement* session = stanza->FirstNamed(QN_SESSION);
- ASSERT(session != NULL);
-
- // Try the offered transports until we find one that we support.
- bool found_offer = false;
- const buzz::XmlElement* elem = session->FirstElement();
- while (elem) {
- if (elem->Name().LocalPart() == "transport") {
- found_offer = true;
- Transport* transport = GetTransport(elem->Name().Namespace());
- if (transport && transport->OnTransportOffer(elem)) {
- SetTransport(transport);
- break;
- }
- }
- elem = elem->NextElement();
- }
-
- // If the offer did not include any transports, then we are talking to an
- // old client. In that case, we turn on compatibility mode, and we assume
- // an offer containing just P2P, which is all that old clients support.
- if (!found_offer) {
- compatibility_mode_ = true;
-
- Transport* transport = GetTransport(kNsP2pTransport);
- ASSERT(transport != NULL);
-
- scoped_ptr<buzz::XmlElement> transport_offer(
- new buzz::XmlElement(kQnP2pTransport, true));
- bool valid = transport->OnTransportOffer(transport_offer.get());
- ASSERT(valid);
- if (valid)
- SetTransport(transport);
- }
-
- if (!transport_) {
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ACCEPTABLE, "modify",
- "no supported transport in offer", NULL);
- return false;
- }
-
- // Get the description of the transport we picked.
- buzz::XmlElement* answer = transport_->CreateTransportAnswer();
- ASSERT(answer->Name() == buzz::QName(transport_->name(), "transport"));
-
- // Send a transport-accept message telling the other side our decision,
- // unless this is an old client that is not expecting one.
- if (!compatibility_mode_) {
- XmlElements elems;
- elems.push_back(answer);
- SendSessionMessage("transport-accept", elems);
- }
-
- // If the user wants to accept, allow that now
- if (description_) {
- Accept(description_);
- }
-
return true;
}
-void Session::SetTransport(Transport* transport) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- ASSERT(transport_ == NULL);
- transport_ = transport;
+void Session::SpeculativelyConnectAllTransportChannels() {
+ for (TransportMap::iterator iter = transports_.begin();
+ iter != transports_.end(); ++iter) {
+ iter->second->SpeculativelyConnectChannels();
+ }
+}
- // Drop the transports that were not selected.
- bool found = false;
- for (TransportList::iterator iter = potential_transports_.begin();
- iter != potential_transports_.end();
- ++iter) {
- if (*iter == transport_) {
- found = true;
- } else {
- delete *iter;
+void Session::CompleteTransportNegotiations(const TransportInfos& transports) {
+ for (TransportInfos::const_iterator transport = transports.begin();
+ transport != transports.end(); ++transport) {
+ TransportProxy* transproxy = GetTransportProxy(transport->content_name);
+ if (transproxy) {
+ transproxy->CompleteNegotiation();
}
}
- potential_transports_.clear();
-
- // We require the selected transport to be one of the potential transports
- ASSERT(found);
-
- // Create implementations for all of the channels if they don't exist.
- for (ChannelMap::iterator iter = channels_.begin();
- iter != channels_.end();
- ++iter) {
- TransportChannelProxy* channel = iter->second;
- TransportChannelImpl* impl = transport_->GetChannel(channel->name());
- if (impl == NULL)
- impl = transport_->CreateChannel(channel->name(), session_type());
- ASSERT(impl != NULL);
- channel->SetImplementation(impl);
- }
-
- // Have this transport start connecting if it is not already.
- // (We speculatively connect the most common transport right away.)
- transport_->ConnectChannels();
}
-void Session::SetState(State state) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- if (state != state_) {
- state_ = state;
- SignalState(this, state_);
- session_manager_->signaling_thread()->Post(this, MSG_STATE);
- }
+TransportParserMap Session::GetTransportParsers() {
+ TransportParserMap parsers;
+ parsers[transport_type_] = transport_parser_;
+ return parsers;
}
-void Session::SetError(Error error) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- if (error != error_) {
- error_ = error;
- SignalError(this, error);
- if (error_ != ERROR_NONE)
- session_manager_->signaling_thread()->Post(this, MSG_ERROR);
- }
+ContentParserMap Session::GetContentParsers() {
+ ContentParserMap parsers;
+ parsers[content_type_] = client_;
+ return parsers;
+}
+
+TransportChannel* Session::CreateChannel(const std::string& content_name,
+ const std::string& channel_name) {
+ // We create the proxy "on demand" here because we need to support
+ // creating channels at any time, even before we send or receive
+ // initiate messages, which is before we create the transports.
+ TransportProxy* transproxy = GetOrCreateTransportProxy(content_name);
+ return transproxy->CreateChannel(channel_name, content_type_);
+}
+
+TransportChannel* Session::GetChannel(const std::string& content_name,
+ const std::string& channel_name) {
+ TransportProxy* transproxy = GetTransportProxy(content_name);
+ if (transproxy == NULL)
+ return NULL;
+ else
+ return transproxy->GetChannel(channel_name);
+}
+
+void Session::DestroyChannel(const std::string& content_name,
+ const std::string& channel_name) {
+ TransportProxy* transproxy = GetTransportProxy(content_name);
+ ASSERT(transproxy != NULL);
+ transproxy->DestroyChannel(channel_name);
}
void Session::OnSignalingReady() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
-
- // Forward this to every transport. Those that did not request it should
- // ignore this call.
- if (transport_ != NULL) {
- transport_->OnSignalingReady();
- } else {
- for (TransportList::iterator iter = potential_transports_.begin();
- iter != potential_transports_.end();
- ++iter) {
- (*iter)->OnSignalingReady();
- }
+ ASSERT(signaling_thread_->IsCurrent());
+ for (TransportMap::iterator iter = transports_.begin();
+ iter != transports_.end(); ++iter) {
+ iter->second->impl()->OnSignalingReady();
}
}
@@ -522,60 +529,42 @@
}
void Session::OnTransportWritable(Transport* transport) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- ASSERT((NULL == transport_) || (transport == transport_));
+ ASSERT(signaling_thread_->IsCurrent());
// If the transport is not writable, start a timer to make sure that it
// becomes writable within a reasonable amount of time. If it does not, we
// terminate since we can't actually send data. If the transport is writable,
// cancel the timer. Note that writability transitions may occur repeatedly
// during the lifetime of the session.
-
- session_manager_->signaling_thread()->Clear(this, MSG_TIMEOUT);
+ signaling_thread_->Clear(this, MSG_TIMEOUT);
if (transport->HasChannels() && !transport->writable()) {
- session_manager_->signaling_thread()->PostDelayed(
+ signaling_thread_->PostDelayed(
session_manager_->session_timeout() * 1000, this, MSG_TIMEOUT);
}
}
void Session::OnTransportRequestSignaling(Transport* transport) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread_->IsCurrent());
SignalRequestSignaling(this);
}
-void Session::OnTransportSendMessage(Transport* transport,
- const XmlElements& elems) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- for (size_t i = 0; i < elems.size(); ++i)
- ASSERT(elems[i]->Name() == buzz::QName(transport->name(), "transport"));
-
- if (compatibility_mode_) {
- // In backward compatibility mode, we send a candidates message.
- XmlElements candidates;
- for (size_t i = 0; i < elems.size(); ++i) {
- for (const buzz::XmlElement* elem = elems[i]->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- ASSERT(elem->Name() == kQnP2pCandidate);
-
- // Convert this candidate to an old style candidate (namespace change)
- buzz::XmlElement* legacy_candidate = new buzz::XmlElement(*elem);
- legacy_candidate->SetName(kQnLegacyCandidate);
- candidates.push_back(legacy_candidate);
- }
- delete elems[i];
+void Session::OnTransportCandidatesReady(Transport* transport,
+ const Candidates& candidates) {
+ ASSERT(signaling_thread_->IsCurrent());
+ TransportProxy* transproxy = GetTransportProxy(transport);
+ if (transproxy != NULL) {
+ if (!transproxy->negotiated()) {
+ transproxy->AddSentCandidates(candidates);
}
-
- SendSessionMessage("candidates", candidates);
- } else {
- // If we haven't finished negotiation, then we may later discover that we
- // need compatibility mode, in which case, we will need to re-send these.
- if ((transport_ == NULL) && (transport->name() == kNsP2pTransport)) {
- for (size_t i = 0; i < elems.size(); ++i)
- candidates_.push_back(new buzz::XmlElement(*elems[i]));
+ SessionError error;
+ if (!SendTransportInfoMessage(
+ TransportInfo(transproxy->content_name(), transproxy->type(),
+ candidates),
+ &error)) {
+ LOG(LS_ERROR) << "Could not send transport info message: "
+ << error.text;
+ return;
}
-
- SendSessionMessage("transport-info", elems);
}
}
@@ -585,100 +574,77 @@
const std::string& type,
const std::string& text,
const buzz::XmlElement* extra_info) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread_->IsCurrent());
SignalErrorMessage(this, stanza, name, type, text, extra_info);
}
void Session::OnTransportChannelGone(Transport* transport,
const std::string& name) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread_->IsCurrent());
SignalChannelGone(this, name);
}
-void Session::SendSessionMessage(
- const std::string& type, const std::vector<buzz::XmlElement*>& elems) {
- scoped_ptr<buzz::XmlElement> iq(new buzz::XmlElement(buzz::QN_IQ));
- iq->SetAttr(buzz::QN_TO, remote_name_);
- iq->SetAttr(buzz::QN_TYPE, buzz::STR_SET);
+void Session::OnIncomingMessage(const SessionMessage& msg) {
+ ASSERT(signaling_thread_->IsCurrent());
+ ASSERT(state_ == STATE_INIT || msg.from == remote_name_);
- buzz::XmlElement *session = new buzz::XmlElement(QN_SESSION, true);
- session->AddAttr(buzz::QN_TYPE, type);
- session->AddAttr(buzz::QN_ID, id_.id_str());
- session->AddAttr(QN_INITIATOR, id_.initiator());
-
- for (size_t i = 0; i < elems.size(); ++i)
- session->AddElement(elems[i]);
-
- iq->AddElement(session);
- SignalOutgoingMessage(this, iq.get());
-}
-
-void Session::SendAcknowledgementMessage(const buzz::XmlElement* stanza) {
- scoped_ptr<buzz::XmlElement> ack(new buzz::XmlElement(buzz::QN_IQ));
- ack->SetAttr(buzz::QN_TO, remote_name_);
- ack->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
- ack->SetAttr(buzz::QN_TYPE, "result");
-
- SignalOutgoingMessage(this, ack.get());
-}
-
-void Session::OnIncomingMessage(const buzz::XmlElement* stanza) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- ASSERT(stanza->Name() == buzz::QN_IQ);
- buzz::Jid remote(remote_name_);
- buzz::Jid from(stanza->Attr(buzz::QN_FROM));
- ASSERT(state_ == STATE_INIT || from == remote);
-
- const buzz::XmlElement* session = stanza->FirstNamed(QN_SESSION);
- ASSERT(session != NULL);
-
- if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_SET) {
- ASSERT(false);
- return;
+ if (current_protocol_== PROTOCOL_HYBRID) {
+ if (msg.protocol == PROTOCOL_GINGLE) {
+ current_protocol_ = PROTOCOL_GINGLE;
+ } else {
+ current_protocol_ = PROTOCOL_JINGLE;
+ }
}
- ASSERT(session->HasAttr(buzz::QN_TYPE));
- std::string type = session->Attr(buzz::QN_TYPE);
-
bool valid = false;
-
- if (type == "initiate") {
- valid = OnInitiateMessage(stanza, session);
- } else if (type == "accept") {
- valid = OnAcceptMessage(stanza, session);
- } else if (type == "reject") {
- valid = OnRejectMessage(stanza, session);
- } else if (type == "redirect") {
- valid = OnRedirectMessage(stanza, session);
- } else if (type == "info") {
- valid = OnInfoMessage(stanza, session);
- } else if (type == "transport-accept") {
- valid = OnTransportAcceptMessage(stanza, session);
- } else if (type == "transport-info") {
- valid = OnTransportInfoMessage(stanza, session);
- } else if (type == "terminate") {
- valid = OnTerminateMessage(stanza, session);
- } else if (type == "candidates") {
- // This is provided for backward compatibility.
- // TODO: Remove this once old candidates are gone.
- valid = OnCandidatesMessage(stanza, session);
- } else {
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- "unknown session message type", NULL);
+ MessageError error;
+ switch (msg.type) {
+ case ACTION_SESSION_INITIATE:
+ valid = OnInitiateMessage(msg, &error);
+ break;
+ case ACTION_SESSION_INFO:
+ valid = OnInfoMessage(msg);
+ break;
+ case ACTION_SESSION_ACCEPT:
+ valid = OnAcceptMessage(msg, &error);
+ break;
+ case ACTION_SESSION_REJECT:
+ valid = OnRejectMessage(msg, &error);
+ break;
+ case ACTION_SESSION_TERMINATE:
+ valid = OnTerminateMessage(msg, &error);
+ break;
+ case ACTION_TRANSPORT_INFO:
+ valid = OnTransportInfoMessage(msg, &error);
+ break;
+ case ACTION_TRANSPORT_ACCEPT:
+ valid = OnTransportAcceptMessage(msg, &error);
+ break;
+ default:
+ valid = BadMessage(buzz::QN_STANZA_BAD_REQUEST,
+ "unknown session message type",
+ &error);
}
- // If the message was not valid, we should have sent back an error above.
- // If it was valid, then we send an acknowledgement here.
- if (valid)
- SendAcknowledgementMessage(stanza);
+ if (valid) {
+ SendAcknowledgementMessage(msg.stanza);
+ } else {
+ SignalErrorMessage(this, msg.stanza, error.type,
+ "modify", error.text, NULL);
+ }
}
void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
const buzz::XmlElement* error_stanza) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread_->IsCurrent());
- const buzz::XmlElement* orig_session = orig_stanza->FirstNamed(QN_SESSION);
- ASSERT(orig_session != NULL);
+ SessionMessage msg;
+ ParseError parse_error;
+ if (!ParseSessionMessage(orig_stanza, &msg, &parse_error)) {
+ LOG(LS_ERROR) << "Error parsing failed send: " << parse_error.text
+ << ":" << orig_stanza;
+ return;
+ }
std::string error_type = "cancel";
@@ -688,331 +654,180 @@
ASSERT(error->HasAttr(buzz::QN_TYPE));
error_type = error->Attr(buzz::QN_TYPE);
- LOG(LERROR) << "Session error:\n" << error->Str() << "\n"
- << "in response to:\n" << orig_session->Str();
+ LOG(LS_ERROR) << "Session error:\n" << error->Str() << "\n"
+ << "in response to:\n" << orig_stanza->Str();
}
- bool fatal_error = false;
-
- ASSERT(orig_session->HasAttr(buzz::QN_TYPE));
- if ((orig_session->Attr(buzz::QN_TYPE) == "transport-info")
- || (orig_session->Attr(buzz::QN_TYPE) == "candidates")) {
+ if (msg.type == ACTION_TRANSPORT_INFO) {
// Transport messages frequently generate errors because they are sent right
// when we detect a network failure. For that reason, we ignore such
// errors, because if we do not establish writability again, we will
// terminate anyway. The exceptions are transport-specific error tags,
// which we pass on to the respective transport.
+
+ // TODO: This is only used for unknown channel name.
+ // For Jingle, find a stanard-compliant way of doing this. For
+ // Gingle, guess the content name based on the channel name.
for (const buzz::XmlElement* elem = error->FirstElement();
NULL != elem; elem = elem->NextElement()) {
- if (Transport* transport = GetTransport(elem->Name().Namespace())) {
- if (!transport->OnTransportError(orig_session, elem)) {
- fatal_error = true;
- break;
- }
+ TransportProxy* transproxy = GetFirstTransportProxy();
+ if (transproxy && transproxy->type() == error->Name().Namespace()) {
+ transproxy->impl()->OnTransportError(elem);
}
}
} else if ((error_type != "continue") && (error_type != "wait")) {
// We do not set an error if the other side said it is okay to continue
// (possibly after waiting). These errors can be ignored.
- fatal_error = true;
- }
-
- if (fatal_error) {
SetError(ERROR_RESPONSE);
}
}
-bool Session::OnInitiateMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- if (!CheckState(stanza, STATE_INIT))
+bool Session::OnInitiateMessage(const SessionMessage& msg,
+ MessageError* error) {
+ if (!CheckState(STATE_INIT, error))
return false;
- if (!FindRemoteSessionDescription(stanza, session))
+
+ SessionInitiate init;
+ if (!ParseSessionInitiate(msg.protocol, msg.action_elem,
+ GetContentParsers(), GetTransportParsers(),
+ &init, error))
return false;
+ SessionError session_error;
+ if (!CreateTransportProxies(init.transports, &session_error)) {
+ return BadMessage(buzz::QN_STANZA_NOT_ACCEPTABLE,
+ session_error.text, error);
+ }
+
initiator_ = false;
- remote_name_ = stanza->Attr(buzz::QN_FROM);
+ remote_name_ = msg.from;
+ set_remote_description(new SessionDescription(init.ClearContents()));
SetState(STATE_RECEIVEDINITIATE);
+
+ // Users of Session may listen to state change and call Reject().
+ if (state_ != STATE_SENTREJECT) {
+ // TODO: Jingle spec allows candidates to be in the
+ // initiate. We should support receiving them.
+ CompleteTransportNegotiations(init.transports);
+ }
return true;
}
-bool Session::OnAcceptMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- if (!CheckState(stanza, STATE_SENTINITIATE))
- return false;
- if (!FindRemoteSessionDescription(stanza, session))
+bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) {
+ if (!CheckState(STATE_SENTINITIATE, error))
return false;
+ SessionAccept accept;
+ if (!ParseSessionAccept(msg.protocol, msg.action_elem,
+ GetContentParsers(), GetTransportParsers(),
+ &accept, error))
+ return false;
+
+ set_remote_description(new SessionDescription(accept.ClearContents()));
SetState(STATE_RECEIVEDACCEPT);
+
+ // Users of Session may listen to state change and call Reject().
+ if (state_ != STATE_SENTREJECT) {
+ // TODO: Jingle spec allows candidates to be in the
+ // accept. We should support receiving them.
+ CompleteTransportNegotiations(accept.transports);
+ }
+
return true;
}
-bool Session::OnRejectMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- if (!CheckState(stanza, STATE_SENTINITIATE))
+bool Session::OnRejectMessage(const SessionMessage& msg, MessageError* error) {
+ if (!CheckState(STATE_SENTINITIATE, error))
return false;
SetState(STATE_RECEIVEDREJECT);
return true;
}
-bool Session::OnRedirectMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- if (!CheckState(stanza, STATE_SENTINITIATE))
- return false;
-
- const buzz::XmlElement *redirect_target;
- if (!FindRequiredElement(stanza, session, QN_REDIRECT_TARGET,
- &redirect_target))
- return false;
-
- if (!FindRequiredAttribute(stanza, redirect_target, buzz::QN_NAME,
- &remote_name_))
- return false;
-
- const buzz::XmlElement* redirect_cookie =
- session->FirstNamed(QN_REDIRECT_COOKIE);
-
- XmlElements elems;
- elems.push_back(client_->TranslateSessionDescription(description_));
- if (redirect_cookie)
- elems.push_back(new buzz::XmlElement(*redirect_cookie));
- SendSessionMessage("initiate", elems);
-
- // Clear the connection timeout (if any). We will start the connection
- // timer from scratch when SignalConnecting fires.
- session_manager_->signaling_thread()->Clear(this, MSG_TIMEOUT);
-
- // Reset all of the sockets back into the initial state.
- for (TransportList::iterator iter = potential_transports_.begin();
- iter != potential_transports_.end();
- ++iter) {
- (*iter)->ResetChannels();
- }
-
- ConnectDefaultTransportChannels(false);
+// Only used by app/win32/fileshare.cc.
+bool Session::OnInfoMessage(const SessionMessage& msg) {
+ SignalInfoMessage(this, CopyOfXmlChildren(msg.action_elem));
return true;
}
-bool Session::OnInfoMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- XmlElements elems;
- for (const buzz::XmlElement* elem = session->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- elems.push_back(new buzz::XmlElement(*elem));
- }
-
- SignalInfoMessage(this, elems);
- return true;
-}
-
-bool Session::OnTransportAcceptMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- if (!CheckState(stanza, STATE_SENTINITIATE))
+bool Session::OnTerminateMessage(const SessionMessage& msg,
+ MessageError* error) {
+ SessionTerminate term;
+ if (!ParseSessionTerminate(msg.protocol, msg.action_elem, &term, error))
return false;
- Transport* transport = NULL;
- const buzz::XmlElement* transport_elem = NULL;
-
- for(const buzz::XmlElement* elem = session->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- if (elem->Name().LocalPart() == "transport") {
- Transport* transport = GetTransport(elem->Name().Namespace());
- if (transport) {
- if (transport_elem) { // trying to accept two transport?
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST,
- "modify", "transport-accept has two answers",
- NULL);
- return false;
- }
-
- transport_elem = elem;
- if (!transport->OnTransportAnswer(transport_elem)) {
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST,
- "modify", "transport-accept is not acceptable",
- NULL);
- return false;
- }
- SetTransport(transport);
- }
- }
+ SignalReceivedTerminateReason(this, term.reason);
+ if (term.debug_reason != buzz::STR_EMPTY) {
+ LOG(LS_VERBOSE) << "Received error on call: " << term.debug_reason;
}
- if (!transport_elem) {
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ALLOWED, "modify",
- "no supported transport in answer", NULL);
- return false;
- }
-
- // If we discovered that we need compatibility mode and we have sent some
- // candidates already (using transport-info), then we need to re-send them
- // using the candidates message.
- if (compatibility_mode_ && (candidates_.size() > 0)) {
- ASSERT(transport_ != NULL);
- ASSERT(transport_->name() == kNsP2pTransport);
- OnTransportSendMessage(transport_, candidates_);
- } else {
- for (size_t i = 0; i < candidates_.size(); ++i)
- delete candidates_[i];
- }
- candidates_.clear();
-
- return true;
-}
-
-bool Session::OnTransportInfoMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- for(const buzz::XmlElement* elem = session->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- if (elem->Name().LocalPart() == "transport") {
- Transport* transport = GetTransport(elem->Name().Namespace());
- if (transport) {
- if (!transport->OnTransportMessage(elem, stanza))
- return false;
- }
- }
- }
- return true;
-}
-
-bool Session::OnTerminateMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- for (const buzz::XmlElement *elem = session->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- // elem->Name().LocalPart() is the reason for termination
- SignalReceivedTerminateReason(this, elem->Name().LocalPart());
- // elem->FirstElement() might contain a debug string for termination
- const buzz::XmlElement *debugElement = elem->FirstElement();
- if (debugElement != NULL) {
- LOG(LS_VERBOSE) << "Received error on call: "
- << debugElement->Name().LocalPart();
- }
- }
SetState(STATE_RECEIVEDTERMINATE);
return true;
}
-bool Session::OnCandidatesMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- // If we don't have a transport, then this is the first candidates message.
- // We first create a fake transport-accept message in order to finish the
- // negotiation and create a transport.
- if (!transport_) {
- compatibility_mode_ = true;
+bool Session::OnTransportInfoMessage(const SessionMessage& msg,
+ MessageError* error) {
+ TransportInfos tinfos;
+ if (!ParseTransportInfos(msg.protocol, msg.action_elem,
+ initiator_description()->contents(),
+ GetTransportParsers(), &tinfos, error))
+ return false;
- scoped_ptr<buzz::XmlElement> transport_accept(
- new buzz::XmlElement(QN_SESSION));
- transport_accept->SetAttr(buzz::QN_TYPE, "transport-accept");
+ for (TransportInfos::iterator tinfo = tinfos.begin();
+ tinfo != tinfos.end(); ++tinfo) {
+ TransportProxy* transproxy = GetTransportProxy(tinfo->content_name);
+ if (transproxy == NULL)
+ return BadParse("Unknown content name: " + tinfo->content_name, error);
- buzz::XmlElement* transport_offer =
- new buzz::XmlElement(kQnP2pTransport, true);
- transport_accept->AddElement(transport_offer);
+ for (Candidates::const_iterator cand = tinfo->candidates.begin();
+ cand != tinfo->candidates.end(); ++cand) {
+ if (!transproxy->impl()->VerifyCandidate(*cand, error))
+ return false;
- // It is okay to pass the original stanza here. That is only used if we
- // send an error message. Normal processing looks only at transport_accept.
- bool valid = OnTransportAcceptMessage(stanza, transport_accept.get());
- ASSERT(valid);
+ if (!transproxy->impl()->HasChannel(cand->name())) {
+ buzz::XmlElement* extra_info =
+ new buzz::XmlElement(QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME);
+ extra_info->AddAttr(buzz::QN_NAME, cand->name());
+ error->extra = extra_info;
+ return BadParse("channel named in candidate does not exist: " +
+ cand->name() + " for content: "+ tinfo->content_name,
+ error);
+ }
+ }
+
+ transproxy->impl()->OnRemoteCandidates(tinfo->candidates);
+ transproxy->CompleteNegotiation();
}
- ASSERT(transport_ != NULL);
- ASSERT(transport_->name() == kNsP2pTransport);
-
- // Wrap the candidates in a transport element as they would appear in a
- // transport-info message and send this to the transport.
- scoped_ptr<buzz::XmlElement> transport_info(
- new buzz::XmlElement(kQnP2pTransport, true));
- for (const buzz::XmlElement* elem = session->FirstNamed(kQnLegacyCandidate);
- elem != NULL;
- elem = elem->NextNamed(kQnLegacyCandidate)) {
- buzz::XmlElement* new_candidate = new buzz::XmlElement(*elem);
- new_candidate->SetName(kQnP2pCandidate);
- transport_info->AddElement(new_candidate);
- }
- return transport_->OnTransportMessage(transport_info.get(), stanza);
+ return true;
}
-bool Session::CheckState(const buzz::XmlElement* stanza, State state) {
+bool Session::OnTransportAcceptMessage(const SessionMessage& msg,
+ MessageError* error) {
+ // TODO: Currently here only for compatibility with
+ // Gingle 1.1 clients (notably, Google Voice).
+ return true;
+}
+
+bool Session::CheckState(State state, MessageError* error) {
ASSERT(state_ == state);
if (state_ != state) {
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ALLOWED, "modify",
- "message not allowed in current state", NULL);
- return false;
+ return BadMessage(buzz::QN_STANZA_NOT_ALLOWED,
+ "message not allowed in current state",
+ error);
}
return true;
}
-bool Session::FindRequiredElement(const buzz::XmlElement* stanza,
- const buzz::XmlElement* parent,
- const buzz::QName& name,
- const buzz::XmlElement** elem) {
- *elem = parent->FirstNamed(name);
- if (*elem == NULL) {
- std::string text;
- text += "element '" + parent->Name().Merged() +
- "' missing required child '" + name.Merged() + "'";
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- text, NULL);
- return false;
- }
- return true;
-}
-
-bool Session::FindRemoteSessionDescription(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session) {
- buzz::QName qn_session(session_type_, "description");
- const buzz::XmlElement* desc;
- if (!FindRequiredElement(stanza, session, qn_session, &desc))
- return false;
- remote_description_ = client_->CreateSessionDescription(desc);
- return true;
-}
-
-bool Session::FindRequiredAttribute(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- const buzz::QName& name,
- std::string* value) {
- if (!elem->HasAttr(name)) {
- std::string text;
- text += "element '" + elem->Name().Merged() +
- "' missing required attribute '" + name.Merged() + "'";
- SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- text, NULL);
- return false;
- } else {
- *value = elem->Attr(name);
- return true;
- }
-}
-
void Session::OnMessage(talk_base::Message *pmsg) {
- switch(pmsg->message_id) {
- case MSG_TIMEOUT:
- // Session timeout has occured.
- SetError(ERROR_TIME);
- break;
+ // preserve this because BaseSession::OnMessage may modify it
+ BaseSession::State orig_state = state_;
- case MSG_ERROR:
- // Any of the defined errors is most likely fatal.
- Terminate();
- break;
+ BaseSession::OnMessage(pmsg);
+ switch (pmsg->message_id) {
case MSG_STATE:
- switch (state_) {
- case STATE_SENTACCEPT:
- case STATE_RECEIVEDACCEPT:
- SetState(STATE_INPROGRESS);
- ASSERT(transport_ != NULL);
- break;
-
- case STATE_SENTREJECT:
- case STATE_SENTREDIRECT:
- case STATE_RECEIVEDREJECT:
- Terminate();
- break;
-
+ switch (orig_state) {
case STATE_SENTTERMINATE:
case STATE_RECEIVEDTERMINATE:
session_manager_->DestroySession(this);
@@ -1026,4 +841,138 @@
}
}
-} // namespace cricket
+bool Session::SendInitiateMessage(const SessionDescription* sdesc,
+ SessionError* error) {
+ SessionInitiate init;
+ init.contents = sdesc->contents();
+ init.transports = GetEmptyTransportInfos(init.contents);
+ return SendMessage(ACTION_SESSION_INITIATE, init, error);
+}
+
+bool Session::WriteSessionAction(
+ SignalingProtocol protocol, const SessionInitiate& init,
+ XmlElements* elems, WriteError* error) {
+ ContentParserMap content_parsers = GetContentParsers();
+ TransportParserMap trans_parsers = GetTransportParsers();
+
+ return WriteSessionInitiate(protocol, init.contents, init.transports,
+ content_parsers, trans_parsers,
+ elems, error);
+}
+
+bool Session::SendAcceptMessage(const SessionDescription* sdesc,
+ SessionError* error) {
+ XmlElements elems;
+ if (!WriteSessionAccept(current_protocol_,
+ sdesc->contents(),
+ GetEmptyTransportInfos(sdesc->contents()),
+ GetContentParsers(), GetTransportParsers(),
+ &elems, error)) {
+ return false;
+ }
+ return SendMessage(ACTION_SESSION_ACCEPT, elems, error);
+}
+
+bool Session::SendRejectMessage(const std::string& reason,
+ SessionError* error) {
+ XmlElements elems;
+ return SendMessage(ACTION_SESSION_REJECT, elems, error);
+}
+
+
+bool Session::SendTerminateMessage(const std::string& reason,
+ SessionError* error) {
+ SessionTerminate term(reason);
+ return SendMessage(ACTION_SESSION_TERMINATE, term, error);
+}
+
+bool Session::WriteSessionAction(SignalingProtocol protocol,
+ const SessionTerminate& term,
+ XmlElements* elems, WriteError* error) {
+ WriteSessionTerminate(protocol, term, elems);
+ return true;
+}
+
+bool Session::SendTransportInfoMessage(const TransportInfo& tinfo,
+ SessionError* error) {
+ return SendMessage(ACTION_TRANSPORT_INFO, tinfo, error);
+}
+
+bool Session::WriteSessionAction(SignalingProtocol protocol,
+ const TransportInfo& tinfo,
+ XmlElements* elems, WriteError* error) {
+ TransportInfos tinfos;
+ tinfos.push_back(tinfo);
+ TransportParserMap parsers = GetTransportParsers();
+
+ return WriteTransportInfos(protocol, tinfos, parsers,
+ elems, error);
+}
+
+bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
+ SessionError* error) {
+ talk_base::scoped_ptr<buzz::XmlElement> stanza(
+ new buzz::XmlElement(buzz::QN_IQ));
+
+ SessionMessage msg(current_protocol_, type, sid_, initiator_name_);
+ msg.to = remote_name_;
+ WriteSessionMessage(msg, action_elems, stanza.get());
+
+ SignalOutgoingMessage(this, stanza.get());
+ return true;
+}
+
+template <typename Action>
+bool Session::SendMessage(ActionType type, const Action& action,
+ SessionError* error) {
+ talk_base::scoped_ptr<buzz::XmlElement> stanza(
+ new buzz::XmlElement(buzz::QN_IQ));
+ if (!WriteActionMessage(type, action, stanza.get(), error))
+ return false;
+
+ SignalOutgoingMessage(this, stanza.get());
+ return true;
+}
+
+template <typename Action>
+bool Session::WriteActionMessage(ActionType type, const Action& action,
+ buzz::XmlElement* stanza,
+ WriteError* error) {
+ if (current_protocol_ == PROTOCOL_HYBRID) {
+ if (!WriteActionMessage(PROTOCOL_JINGLE, type, action, stanza, error))
+ return false;
+ if (!WriteActionMessage(PROTOCOL_GINGLE, type, action, stanza, error))
+ return false;
+ } else {
+ if (!WriteActionMessage(current_protocol_, type, action, stanza, error))
+ return false;
+ }
+ return true;
+}
+
+template <typename Action>
+bool Session::WriteActionMessage(SignalingProtocol protocol,
+ ActionType type, const Action& action,
+ buzz::XmlElement* stanza, WriteError* error) {
+ XmlElements action_elems;
+ if (!WriteSessionAction(protocol, action, &action_elems, error))
+ return false;
+
+ SessionMessage msg(protocol, type, sid_, initiator_name_);
+ msg.to = remote_name_;
+
+ WriteSessionMessage(msg, action_elems, stanza);
+ return true;
+}
+
+void Session::SendAcknowledgementMessage(const buzz::XmlElement* stanza) {
+ talk_base::scoped_ptr<buzz::XmlElement> ack(
+ new buzz::XmlElement(buzz::QN_IQ));
+ ack->SetAttr(buzz::QN_TO, remote_name_);
+ ack->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
+ ack->SetAttr(buzz::QN_TYPE, "result");
+
+ SignalOutgoingMessage(this, ack.get());
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/session.h b/talk/p2p/base/session.h
old mode 100755
new mode 100644
index 5146ea0..64bb83a
--- a/talk/p2p/base/session.h
+++ b/talk/p2p/base/session.h
@@ -25,196 +25,148 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _SESSION_H_
-#define _SESSION_H_
+#ifndef TALK_P2P_BASE_SESSION_H_
+#define TALK_P2P_BASE_SESSION_H_
-#include "talk/base/socketaddress.h"
-#include "talk/p2p/base/sessiondescription.h"
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "talk/p2p/base/sessionmessages.h"
#include "talk/p2p/base/sessionmanager.h"
+#include "talk/base/socketaddress.h"
#include "talk/p2p/base/sessionclient.h"
-#include "talk/p2p/base/sessionid.h"
+#include "talk/p2p/base/parsing.h"
#include "talk/p2p/base/port.h"
#include "talk/xmllite/xmlelement.h"
-#include <string>
+#include "talk/xmpp/constants.h"
+
+class JingleMessageHandler;
namespace cricket {
-class SessionManager;
+class P2PTransportChannel;
class Transport;
class TransportChannel;
class TransportChannelProxy;
class TransportChannelImpl;
-// A specific Session created by the SessionManager. A Session manages
-// signaling for session setup and tear down. This setup includes negotiation
+// Used for errors that will send back a specific error message to the
+// remote peer. We add "type" to the errors because it's needed for
+// SignalErrorMessage.
+struct MessageError : ParseError {
+ buzz::QName type;
+
+ // if unset, assume type is a parse error
+ MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {}
+
+ void SetType(const buzz::QName type) {
+ this->type = type;
+ }
+};
+
+// Used for errors that may be returned by public session methods that
+// can fail.
+// TODO: Use this error in Session::Initiate and
+// Session::Accept.
+struct SessionError : WriteError {
+};
+
+// Bundles a Transport and ChannelMap together. ChannelMap is used to
+// create transport channels before receiving or sending a session
+// initiate, and for speculatively connecting channels. Previously, a
+// session had one ChannelMap and transport. Now, with multiple
+// transports per session, we need multiple ChannelMaps as well.
+class TransportProxy {
+ public:
+ TransportProxy(const std::string& content_name, Transport* transport)
+ : content_name_(content_name),
+ transport_(transport),
+ state_(STATE_INIT),
+ sent_candidates_(false) {}
+ ~TransportProxy();
+
+ std::string content_name() const { return content_name_; }
+ Transport* impl() const { return transport_; }
+ std::string type() const;
+ bool negotiated() const { return state_ == STATE_NEGOTIATED; }
+ const Candidates& sent_candidates() const { return sent_candidates_; }
+
+ TransportChannel* GetChannel(const std::string& name);
+ TransportChannel* CreateChannel(const std::string& name,
+ const std::string& content_type);
+ void DestroyChannel(const std::string& name);
+ void AddSentCandidates(const Candidates& candidates);
+ void ClearSentCandidates() { sent_candidates_.clear(); }
+ void SpeculativelyConnectChannels();
+ void CompleteNegotiation();
+
+ private:
+ enum TransportState {
+ STATE_INIT,
+ STATE_CONNECTING,
+ STATE_NEGOTIATED
+ };
+
+ typedef std::map<std::string, TransportChannelProxy*> ChannelMap;
+
+ TransportChannelProxy* GetProxy(const std::string& name);
+ TransportChannelImpl* GetOrCreateImpl(const std::string& name,
+ const std::string& content_type);
+ void SetProxyImpl(const std::string& name, TransportChannelProxy* proxy);
+
+ std::string content_name_;
+ Transport* transport_;
+ TransportState state_;
+ ChannelMap channels_;
+ Candidates sent_candidates_;
+};
+
+typedef std::map<std::string, TransportProxy*> TransportMap;
+
+// TODO: Consider simplifying the dependency from Voice/VideoChannel
+// on Session. Right now the Channel class requires a BaseSession, but it only
+// uses CreateChannel/DestroyChannel. Perhaps something like a
+// TransportChannelFactory could be hoisted up out of BaseSession, or maybe
+// the transports could be passed in directly.
+
+// A BaseSession manages general session state. This includes negotiation
// of both the application-level and network-level protocols: the former
// defines what will be sent and the latter defines how it will be sent. Each
// network-level protocol is represented by a Transport object. Each Transport
// participates in the network-level negotiation. The individual streams of
-// packets are represented by TransportChannels.
-class Session : public talk_base::MessageHandler, public sigslot::has_slots<> {
+// packets are represented by TransportChannels. The application-level protocol
+// is represented by SessionDecription objects.
+class BaseSession : public sigslot::has_slots<>,
+ public talk_base::MessageHandler {
public:
enum State {
STATE_INIT = 0,
- STATE_SENTINITIATE, // sent initiate, waiting for Accept or Reject
- STATE_RECEIVEDINITIATE, // received an initiate. Call Accept or Reject
- STATE_SENTACCEPT, // sent accept. begin connecting transport
- STATE_RECEIVEDACCEPT, // received accept. begin connecting transport
- STATE_SENTMODIFY, // sent modify, waiting for Accept or Reject
- STATE_RECEIVEDMODIFY, // received modify, call Accept or Reject
- STATE_SENTREJECT, // sent reject after receiving initiate
- STATE_RECEIVEDREJECT, // received reject after sending initiate
- STATE_SENTREDIRECT, // sent direct after receiving initiate
- STATE_SENTTERMINATE, // sent terminate (any time / either side)
- STATE_RECEIVEDTERMINATE, // received terminate (any time / either side)
- STATE_INPROGRESS, // session accepted and in progress
- STATE_DEINIT, // session is being destroyed
+ STATE_SENTINITIATE, // sent initiate, waiting for Accept or Reject
+ STATE_RECEIVEDINITIATE, // received an initiate. Call Accept or Reject
+ STATE_SENTACCEPT, // sent accept. begin connecting transport
+ STATE_RECEIVEDACCEPT, // received accept. begin connecting transport
+ STATE_SENTMODIFY, // sent modify, waiting for Accept or Reject
+ STATE_RECEIVEDMODIFY, // received modify, call Accept or Reject
+ STATE_SENTREJECT, // sent reject after receiving initiate
+ STATE_RECEIVEDREJECT, // received reject after sending initiate
+ STATE_SENTREDIRECT, // sent direct after receiving initiate
+ STATE_SENTTERMINATE, // sent terminate (any time / either side)
+ STATE_RECEIVEDTERMINATE, // received terminate (any time / either side)
+ STATE_INPROGRESS, // session accepted and in progress
+ STATE_DEINIT, // session is being destroyed
};
enum Error {
- ERROR_NONE = 0, // no error
- ERROR_TIME, // no response to signaling
- ERROR_RESPONSE, // error during signaling
- ERROR_NETWORK, // network error, could not allocate network resources
+ ERROR_NONE = 0, // no error
+ ERROR_TIME = 1, // no response to signaling
+ ERROR_RESPONSE = 2, // error during signaling
+ ERROR_NETWORK = 3, // network error, could not allocate network resources
};
- // Returns the manager that created and owns this session.
- SessionManager* session_manager() const { return session_manager_; }
-
- // Returns the XML namespace identifying the type of this session.
- const std::string& session_type() const { return session_type_; }
-
- // Returns the client that is handling the application data of this session.
- SessionClient* client() const { return client_; }
-
- // Returns the JID this client.
- const std::string &name() const { return name_; }
-
- // Returns the JID of the other peer in this session.
- const std::string &remote_name() const { return remote_name_; }
-
- // Indicates whether we initiated this session.
- bool initiator() const { return initiator_; }
-
- // Holds the ID of this session, which should be unique across the world.
- const SessionID& id() const { return id_; }
-
- // Returns the applicication-level description given by our client. This
- // will be null until Initiate or Accept.
- const SessionDescription *description() const { return description_; }
-
- // Returns the applicication-level description given by the other client.
- // If we are the initiator, this will be null until we receive an accept.
- const SessionDescription *remote_description() const {
- return remote_description_;
- }
-
- // Returns the current state of the session. See the enum above for details.
- // Each time the state changes, we will fire this signal.
- State state() const { return state_; }
- sigslot::signal2<Session *, State> SignalState;
-
- // Fired whenever we receive a terminate message along with a reason
- sigslot::signal2<Session *, const std::string &> SignalReceivedTerminateReason;
-
- // Returns the last error in the session. See the enum above for details.
- // Each time the an error occurs, we will fire this signal.
- Error error() const { return error_; }
- sigslot::signal2<Session *, Error> SignalError;
-
- // Returns the transport that has been negotiated or NULL if negotiation is
- // still in progress.
- Transport* transport() const { return transport_; }
-
- // When a session was created by us, we are the initiator, and we send the
- // initiate message when this method is invoked. The extra_xml parameter is
- // a list of elements that will get inserted inside <Session> ... </Session>
- bool Initiate(const std::string &to, std::vector<buzz::XmlElement*>* extra_xml,
- const SessionDescription *description);
-
- // When we receive a session initiation from another client, we create a
- // session in the RECEIVEDINITIATE state. We respond by accepting,
- // rejecting, or redirecting the session somewhere else.
- bool Accept(const SessionDescription *description);
- bool Reject();
- bool Redirect(const std::string& target);
-
- // At any time, we may terminate an outstanding session.
- bool Terminate();
-
- // The two clients in the session may also send one another arbitrary XML
- // messages, which are called "info" messages. Both of these functions take
- // ownership of the XmlElements and delete them when done.
- typedef std::vector<buzz::XmlElement*> XmlElements;
- void SendInfoMessage(const XmlElements& elems);
- sigslot::signal2<Session*, const XmlElements&> SignalInfoMessage;
-
- // Controls the set of transports that will be allowed for this session. If
- // we are initiating, then this list will be used to construct the transports
- // that we will offer to the other side. In that case, the order of the
- // transport names indicates our preference (first has highest preference).
- // If we are receiving, then this list indicates the set of transports that
- // we will allow. We will choose the first transport in the offered list
- // (1) whose name appears in the given list and (2) that can accept the offer
- // provided (which may include parameters particular to the transport).
- //
- // If this function is not called (or if it is called with a NULL array),
- // then we will use a default set of transports.
- void SetPotentialTransports(const std::string names[], size_t length);
-
- // Once transports have been created (by SetTransports), this function will
- // return the transport with the given name or NULL if none was created.
- // Once a particular transport has been chosen, only that transport will be
- // returned.
- Transport* GetTransport(const std::string& name);
-
- // Creates a new channel with the given name. This method may be called
- // immediately after creating the session. However, the actual
- // implementation may not be fixed until transport negotiation completes.
- TransportChannel* CreateChannel(const std::string& name);
-
- // Returns the channel with the given name.
- TransportChannel* GetChannel(const std::string& name);
-
- // Destroys the given channel.
- void DestroyChannel(TransportChannel* channel);
-
- // Note: This function is a hack and should not be used.
- TransportChannelImpl* GetImplementation(TransportChannel* channel);
-
- // Invoked when we notice that there is no matching channel on our peer.
- sigslot::signal2<Session*, const std::string&> SignalChannelGone;
-
- private:
- typedef std::list<Transport*> TransportList;
- typedef std::map<std::string, TransportChannelProxy*> ChannelMap;
-
- SessionManager *session_manager_;
- std::string name_;
- std::string remote_name_;
- bool initiator_;
- SessionID id_;
- std::string session_type_;
- SessionClient* client_;
- const SessionDescription *description_;
- const SessionDescription *remote_description_;
- State state_;
- Error error_;
- std::string redirect_target_;
- // Note that the following two members are mutually exclusive
- TransportList potential_transports_; // order implies preference
- Transport* transport_; // negotiated transport
- ChannelMap channels_;
- bool compatibility_mode_; // indicates talking to an old client
- XmlElements candidates_; // holds candidates sent in case of compat-mode
-
- // Creates or destroys a session. (These are called only SessionManager.)
- Session(SessionManager *session_manager,
- const std::string& name,
- const SessionID& id,
- const std::string& session_type,
- SessionClient* client);
- ~Session();
+ explicit BaseSession(talk_base::Thread *signaling_thread);
+ virtual ~BaseSession();
// Updates the state, signaling if necessary.
void SetState(State state);
@@ -222,26 +174,221 @@
// Updates the error state, signaling if necessary.
void SetError(Error error);
- // To improve connection time, this creates the channels on the most common
- // transport type and initiates connection.
- void ConnectDefaultTransportChannels(bool create);
+ // Handles messages posted to us.
+ virtual void OnMessage(talk_base::Message *pmsg);
- // If a new channel is created after we have created the default transport,
- // then we should create this channel as well and let it connect.
- void CreateDefaultTransportChannel(const std::string& name);
+ // Returns the current state of the session. See the enum above for details.
+ // Each time the state changes, we will fire this signal.
+ State state() const { return state_; }
+ sigslot::signal2<BaseSession *, State> SignalState;
- // Creates a default set of transports if the client did not specify some.
- void CreateTransports();
+ // Returns the last error in the session. See the enum above for details.
+ // Each time the an error occurs, we will fire this signal.
+ Error error() const { return error_; }
+ sigslot::signal2<BaseSession *, Error> SignalError;
- // Attempts to choose a transport that is in both our list and the other
- // clients. This will examine the children of the given XML element to find
- // the descriptions of the other client's transports. We will pick the first
- // transport in the other client's list that we also support.
- // (This is called only by SessionManager.)
- bool ChooseTransport(const buzz::XmlElement* msg);
+ // Creates a new channel with the given names. This method may be called
+ // immediately after creating the session. However, the actual
+ // implementation may not be fixed until transport negotiation completes.
+ // This will usually be called from the worker thread, but that
+ // shouldn't be an issue since the main thread will be blocked in
+ // Send when doing so.
+ virtual TransportChannel* CreateChannel(const std::string& content_name,
+ const std::string& channel_name) = 0;
- // Called when a single transport has been negotiated.
- void SetTransport(Transport* transport);
+ // Returns the channel with the given names.
+ virtual TransportChannel* GetChannel(const std::string& content_name,
+ const std::string& channel_name) = 0;
+
+ // Destroys the channel with the given names.
+ // This will usually be called from the worker thread, but that
+ // shouldn't be an issue since the main thread will be blocked in
+ // Send when doing so.
+ virtual void DestroyChannel(const std::string& content_name,
+ const std::string& channel_name) = 0;
+
+ // Invoked when we notice that there is no matching channel on our peer.
+ sigslot::signal2<Session*, const std::string&> SignalChannelGone;
+
+ // Returns the application-level description given by our client.
+ // If we are the recipient, this will be NULL until we send an accept.
+ const SessionDescription* local_description() const {
+ return local_description_;
+ }
+ // Takes ownership of SessionDescription*
+ bool set_local_description(const SessionDescription* sdesc) {
+ if (sdesc != local_description_) {
+ delete local_description_;
+ local_description_ = sdesc;
+ }
+ return true;
+ }
+
+ // Returns the application-level description given by the other client.
+ // If we are the initiator, this will be NULL until we receive an accept.
+ const SessionDescription* remote_description() const {
+ return remote_description_;
+ }
+ // Takes ownership of SessionDescription*
+ bool set_remote_description(const SessionDescription* sdesc) {
+ if (sdesc != remote_description_) {
+ delete remote_description_;
+ remote_description_ = sdesc;
+ }
+ return true;
+ }
+
+ // When we receive an initiate, we create a session in the
+ // RECEIVEDINITIATE state and respond by accepting or rejecting.
+ // Takes ownership of session description.
+ virtual bool Accept(const SessionDescription* sdesc) = 0;
+ virtual bool Reject(const std::string& reason) = 0;
+ bool Terminate() {
+ return TerminateWithReason(STR_TERMINATE_SUCCESS);
+ }
+ virtual bool TerminateWithReason(const std::string& reason) = 0;
+
+ // The worker thread used by the session manager
+ virtual talk_base::Thread *worker_thread() = 0;
+
+ // Returns the JID of this client.
+ const std::string& local_name() const { return local_name_; }
+
+ // Returns the JID of the other peer in this session.
+ const std::string& remote_name() const { return remote_name_; }
+
+ // Set the JID of the other peer in this session.
+ // Typically the remote_name_ is set when the session is initiated.
+ // However, sometimes (e.g when a proxy is used) the peer name is
+ // known after the BaseSession has been initiated and it must be updated
+ // explicitly.
+ void set_remote_name(const std::string& name) { remote_name_ = name; }
+
+ const std::string& id() const { return sid_; }
+
+ protected:
+ State state_;
+ Error error_;
+ const SessionDescription* local_description_;
+ const SessionDescription* remote_description_;
+ std::string sid_;
+ // We don't use buzz::Jid because changing to buzz:Jid here has a
+ // cascading effect that requires an enormous number places to
+ // change to buzz::Jid as well.
+ std::string local_name_;
+ std::string remote_name_;
+ talk_base::Thread *signaling_thread_;
+};
+
+// A specific Session created by the SessionManager, using XMPP for protocol.
+class Session : public BaseSession {
+ public:
+ // Returns the manager that created and owns this session.
+ SessionManager* session_manager() const { return session_manager_; }
+
+ // the worker thread used by the session manager
+ talk_base::Thread *worker_thread() {
+ return session_manager_->worker_thread();
+ }
+
+ // Returns the XML namespace identifying the type of this session.
+ const std::string& content_type() const { return content_type_; }
+
+ // Returns the client that is handling the application data of this session.
+ SessionClient* client() const { return client_; }
+
+ SignalingProtocol current_protocol() const { return current_protocol_; }
+
+ void set_current_protocol(SignalingProtocol protocol) {
+ current_protocol_ = protocol;
+ }
+
+ // Indicates whether we initiated this session.
+ bool initiator() const { return initiator_; }
+
+ const SessionDescription* initiator_description() const {
+ if (initiator_) {
+ return local_description_;
+ } else {
+ return remote_description_;
+ }
+ }
+
+ // Fired whenever we receive a terminate message along with a reason
+ sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason;
+
+ void set_allow_local_ips(bool allow);
+
+ // Returns the transport that has been negotiated or NULL if
+ // negotiation is still in progress.
+ Transport* GetTransport(const std::string& content_name);
+
+ // Takes ownership of session description.
+ // TODO: Add an error argument to pass back to the caller.
+ bool Initiate(const std::string& to,
+ const SessionDescription* sdesc);
+
+ // When we receive an initiate, we create a session in the
+ // RECEIVEDINITIATE state and respond by accepting or rejecting.
+ // Takes ownership of session description.
+ // TODO: Add an error argument to pass back to the caller.
+ virtual bool Accept(const SessionDescription* sdesc);
+ virtual bool Reject(const std::string& reason);
+ virtual bool TerminateWithReason(const std::string& reason);
+
+ // The two clients in the session may also send one another arbitrary XML
+ // messages, which are called "info" messages. Both of these functions take
+ // ownership of the XmlElements and delete them when done.
+ bool SendInfoMessage(const XmlElements& elems);
+ sigslot::signal2<Session*, const XmlElements&> SignalInfoMessage;
+
+ // Maps passed to serialization functions.
+ TransportParserMap GetTransportParsers();
+ ContentParserMap GetContentParsers();
+
+ // Creates a new channel with the given names. This method may be called
+ // immediately after creating the session. However, the actual
+ // implementation may not be fixed until transport negotiation completes.
+ virtual TransportChannel* CreateChannel(const std::string& content_name,
+ const std::string& channel_name);
+
+ // Returns the channel with the given names.
+ virtual TransportChannel* GetChannel(const std::string& content_name,
+ const std::string& channel_name);
+
+ // Destroys the channel with the given names.
+ virtual void DestroyChannel(const std::string& content_name,
+ const std::string& channel_name);
+
+ // Handles messages posted to us.
+ virtual void OnMessage(talk_base::Message *pmsg);
+
+ private:
+ // Creates or destroys a session. (These are called only SessionManager.)
+ Session(SessionManager *session_manager,
+ const std::string& local_name, const std::string& initiator_name,
+ const std::string& sid, const std::string& content_type,
+ SessionClient* client);
+ ~Session();
+
+ // Get a TransportProxy by content_name or transport. NULL if not found.
+ TransportProxy* GetTransportProxy(const std::string& content_name);
+ TransportProxy* GetTransportProxy(const Transport* transport);
+ TransportProxy* GetFirstTransportProxy();
+ // TransportProxy is owned by session. Return proxy just for convenience.
+ TransportProxy* GetOrCreateTransportProxy(const std::string& content_name);
+ // For each transport info, create a transport proxy. Can fail for
+ // incompatible transport types.
+ bool CreateTransportProxies(const TransportInfos& tinfos,
+ SessionError* error);
+ void SpeculativelyConnectAllTransportChannels();
+ // For each transport proxy with a matching content name, complete
+ // the transport negotiation.
+ void CompleteTransportNegotiations(const TransportInfos& tinfos);
+ // Returns a TransportInfo without candidates for each content name.
+ // Uses the transport_type_ of the session.
+ TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const;
+
// Called when the first channel of a transport begins connecting. We use
// this to start a timer, to make sure that the connection completes in a
@@ -259,7 +406,8 @@
// Called when a transport signals that it has a message to send. Note that
// these messages are just the transport part of the stanza; they need to be
// wrapped in the appropriate session tags.
- void OnTransportSendMessage(Transport* transport, const XmlElements& elems);
+ void OnTransportCandidatesReady(Transport* transport,
+ const Candidates& candidates);
// Called when a transport signals that it found an error in an incoming
// message.
@@ -281,10 +429,51 @@
sigslot::signal1<Session*> SignalRequestSignaling;
void OnSignalingReady();
- // Sends a message of the given type to the other client. The body will
- // contain the given list of elements (which are consumed by the function).
- void SendSessionMessage(const std::string& type,
- const XmlElements& elems);
+ // Send various kinds of session messages.
+ bool SendInitiateMessage(const SessionDescription* sdesc,
+ SessionError* error);
+ bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error);
+ bool SendRejectMessage(const std::string& reason, SessionError* error);
+ bool SendTerminateMessage(const std::string& reason, SessionError* error);
+ bool SendTransportInfoMessage(const TransportInfo& tinfo,
+ SessionError* error);
+
+ // Both versions of SendMessage send a message of the given type to
+ // the other client. Can pass either a set of elements or an
+ // "action", which must have a WriteSessionAction method to go along
+ // with it. Sending with an action supports sending a "hybrid"
+ // message. Sending with elements must be sent as Jingle or Gingle.
+
+ // When passing elems, must be either Jingle or Gingle protocol.
+ // Takes ownership of action_elems.
+ bool SendMessage(ActionType type, const XmlElements& action_elems,
+ SessionError* error);
+ // When passing an action, may be Hybrid protocol.
+ template <typename Action>
+ bool SendMessage(ActionType type, const Action& action,
+ SessionError* error);
+
+ // Helper methods to write the session message stanza.
+ template <typename Action>
+ bool WriteActionMessage(ActionType type, const Action& action,
+ buzz::XmlElement* stanza, WriteError* error);
+ template <typename Action>
+ bool WriteActionMessage(SignalingProtocol protocol,
+ ActionType type, const Action& action,
+ buzz::XmlElement* stanza, WriteError* error);
+
+ // Sending messages in hybrid form requires being able to write them
+ // on a per-protocol basis with a common method signature, which all
+ // of these have.
+ bool WriteSessionAction(SignalingProtocol protocol,
+ const SessionInitiate& init,
+ XmlElements* elems, WriteError* error);
+ bool WriteSessionAction(SignalingProtocol protocol,
+ const TransportInfo& tinfo,
+ XmlElements* elems, WriteError* error);
+ bool WriteSessionAction(SignalingProtocol protocol,
+ const SessionTerminate& term,
+ XmlElements* elems, WriteError* error);
// Sends a message back to the other client indicating that we have received
// and accepted their message.
@@ -295,14 +484,14 @@
// they should be handed to OnIncomingMessage.
// (These are called only by SessionManager.)
sigslot::signal2<Session *, const buzz::XmlElement*> SignalOutgoingMessage;
- void OnIncomingMessage(const buzz::XmlElement* stanza);
+ void OnIncomingMessage(const SessionMessage& msg);
void OnFailedSend(const buzz::XmlElement* orig_stanza,
const buzz::XmlElement* error_stanza);
// Invoked when an error is found in an incoming message. This is translated
// into the appropriate XMPP response by SessionManager.
- sigslot::signal6<Session*,
+ sigslot::signal6<BaseSession*,
const buzz::XmlElement*,
const buzz::QName&,
const std::string&,
@@ -311,47 +500,35 @@
// Handlers for the various types of messages. These functions may take
// pointers to the whole stanza or to just the session element.
- bool OnInitiateMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnAcceptMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnRejectMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnRedirectMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnInfoMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnTransportAcceptMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnTransportInfoMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnTerminateMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool OnCandidatesMessage(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
+ bool OnInitiateMessage(const SessionMessage& msg, MessageError* error);
+ bool OnAcceptMessage(const SessionMessage& msg, MessageError* error);
+ bool OnRejectMessage(const SessionMessage& msg, MessageError* error);
+ bool OnInfoMessage(const SessionMessage& msg);
+ bool OnTerminateMessage(const SessionMessage& msg, MessageError* error);
+ bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error);
+ bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error);
- // Helper functions for parsing various message types. CheckState verifies
- // that we are in the appropriate state to receive this message. The latter
- // three verify that an element has the required child or attribute.
- bool CheckState(const buzz::XmlElement* stanza, State state);
- bool FindRequiredElement(const buzz::XmlElement* stanza,
- const buzz::XmlElement* parent,
- const buzz::QName& name,
- const buzz::XmlElement** elem);
- bool FindRemoteSessionDescription(const buzz::XmlElement* stanza,
- const buzz::XmlElement* session);
- bool FindRequiredAttribute(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- const buzz::QName& name,
- std::string* value);
+ // Verifies that we are in the appropriate state to receive this message.
+ bool CheckState(State state, MessageError* error);
- // Handles messages posted to us.
- void OnMessage(talk_base::Message *pmsg);
+ SessionManager *session_manager_;
+ bool initiator_;
+ std::string initiator_name_;
+ std::string content_type_;
+ SessionClient* client_;
+ std::string transport_type_;
+ TransportParser* transport_parser_;
+ // This is transport-specific but required so much by unit tests
+ // that it's much easier to put it here.
+ bool allow_local_ips_;
+ TransportMap transports_;
+ // Keeps track of what protocol we are speaking.
+ SignalingProtocol current_protocol_;
friend class SessionManager; // For access to constructor, destructor,
// and signaling related methods.
};
-} // namespace cricket
+} // namespace cricket
-#endif // _SESSION_H_
+#endif // TALK_P2P_BASE_SESSION_H_
diff --git a/talk/p2p/base/session_unittest.cc b/talk/p2p/base/session_unittest.cc
deleted file mode 100755
index 972ed9d..0000000
--- a/talk/p2p/base/session_unittest.cc
+++ /dev/null
@@ -1,1039 +0,0 @@
-#include <iostream>
-#include <sstream>
-#include <deque>
-#include <map>
-
-#include "talk/base/common.h"
-#include "talk/base/logging.h"
-#include "talk/base/host.h"
-#include "talk/base/natserver.h"
-#include "talk/base/natsocketfactory.h"
-#include "talk/base/helpers.h"
-#include "talk/xmpp/constants.h"
-#include "talk/p2p/base/constants.h"
-#include "talk/p2p/base/sessionmanager.h"
-#include "talk/p2p/base/sessionclient.h"
-#include "talk/p2p/base/session.h"
-#include "talk/p2p/base/portallocator.h"
-#include "talk/p2p/base/transportchannel.h"
-#include "talk/p2p/base/udpport.h"
-#include "talk/p2p/base/stunport.h"
-#include "talk/p2p/base/relayport.h"
-#include "talk/p2p/base/p2ptransport.h"
-#include "talk/p2p/base/rawtransport.h"
-#include "talk/p2p/base/stunserver.h"
-#include "talk/p2p/base/relayserver.h"
-
-using namespace cricket;
-using namespace buzz;
-
-const std::string kSessionType = "http://oink.splat/session";
-
-const talk_base::SocketAddress kStunServerAddress("127.0.0.1", 7000);
-const talk_base::SocketAddress kStunServerAddress2("127.0.0.1", 7001);
-
-const talk_base::SocketAddress kRelayServerIntAddress("127.0.0.1", 7002);
-const talk_base::SocketAddress kRelayServerExtAddress("127.0.0.1", 7003);
-
-const int kNumPorts = 2;
-
-int gPort = 28653;
-int GetNextPort() {
- int p = gPort;
- gPort += 5;
- return p;
-}
-
-int gID = 0;
-std::string GetNextID() {
- std::ostringstream ost;
- ost << gID++;
- return ost.str();
-}
-
-class TestPortAllocatorSession : public PortAllocatorSession {
-public:
- TestPortAllocatorSession(talk_base::Thread* worker_thread, talk_base::SocketFactory* factory,
- const std::string& name, const std::string& session_type)
- : PortAllocatorSession(0), worker_thread_(worker_thread),
- factory_(factory), name_(name), ports_(kNumPorts),
- address_("127.0.0.1", 0), network_("network", address_.ip()),
- running_(false) {
- }
-
- ~TestPortAllocatorSession() {
- for (int i = 0; i < ports_.size(); i++)
- delete ports_[i];
- }
-
- virtual void GetInitialPorts() {
- // These are the flags set by the raw transport.
- uint32 raw_flags = PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP;
-
- // If the client doesn't care, just give them two UDP ports.
- if (flags() == 0) {
- for (int i = 0; i < kNumPorts; i++) {
- ports_[i] = new UDPPort(worker_thread_, factory_, &network_,
- GetAddress());
- AddPort(ports_[i]);
- }
-
- // If the client requested just stun and relay, we have to oblidge.
- } else if (flags() == raw_flags) {
- StunPort* sport = new StunPort(worker_thread_, factory_, &network_,
- GetAddress(), kStunServerAddress);
- sport->set_server_addr2(kStunServerAddress2);
- ports_[0] = sport;
- AddPort(sport);
-
- std::string username = CreateRandomString(16);
- std::string password = CreateRandomString(16);
- RelayPort* rport = new RelayPort(worker_thread_, factory_, &network_,
- GetAddress(), username, password, "");
- rport->AddServerAddress(
- ProtocolAddress(kRelayServerIntAddress, PROTO_UDP));
- ports_[1] = rport;
- AddPort(rport);
- } else {
- ASSERT(false);
- }
- }
-
- virtual void StartGetAllPorts() { running_ = true; }
- virtual void StopGetAllPorts() { running_ = false; }
- virtual bool IsGettingAllPorts() { return running_; }
-
- talk_base::SocketAddress GetAddress() const {
- talk_base::SocketAddress addr(address_);
- addr.SetPort(GetNextPort());
- return addr;
- }
-
- void AddPort(Port* port) {
- port->set_name(name_);
- port->set_preference(1.0);
- port->set_generation(0);
- port->SignalDestroyed.connect(
- this, &TestPortAllocatorSession::OnPortDestroyed);
- port->SignalAddressReady.connect(
- this, &TestPortAllocatorSession::OnAddressReady);
- port->PrepareAddress();
- SignalPortReady(this, port);
- }
-
- void OnPortDestroyed(Port* port) {
- for (int i = 0; i < ports_.size(); i++) {
- if (ports_[i] == port)
- ports_[i] = NULL;
- }
- }
-
- void OnAddressReady(Port* port) {
- SignalCandidatesReady(this, port->candidates());
- }
-
-private:
- talk_base::Thread* worker_thread_;
- talk_base::SocketFactory* factory_;
- std::string name_;
- std::vector<Port*> ports_;
- talk_base::SocketAddress address_;
- talk_base::Network network_;
- bool running_;
-};
-
-class TestPortAllocator : public PortAllocator {
-public:
- TestPortAllocator(talk_base::Thread* worker_thread, talk_base::SocketFactory* factory)
- : worker_thread_(worker_thread), factory_(factory) {
- if (factory_ == NULL)
- factory_ = worker_thread_->socketserver();
- }
-
- virtual PortAllocatorSession *CreateSession(const std::string &name, const std::string &session_type) {
- return new TestPortAllocatorSession(worker_thread_, factory_, name, session_type);
- }
-
-private:
- talk_base::Thread* worker_thread_;
- talk_base::SocketFactory* factory_;
-};
-
-struct SessionManagerHandler : sigslot::has_slots<> {
- SessionManagerHandler(SessionManager* m, const std::string& u)
- : manager(m), username(u), create_count(0), destroy_count(0) {
- manager->SignalSessionCreate.connect(
- this, &SessionManagerHandler::OnSessionCreate);
- manager->SignalSessionDestroy.connect(
- this, &SessionManagerHandler::OnSessionDestroy);
- manager->SignalOutgoingMessage.connect(
- this, &SessionManagerHandler::OnOutgoingMessage);
- manager->SignalRequestSignaling.connect(
- this, &SessionManagerHandler::OnRequestSignaling);
- }
-
- void OnSessionCreate(Session *session, bool initiate) {
- create_count += 1;
- last_id = session->id();
- }
-
- void OnSessionDestroy(Session *session) {
- destroy_count += 1;
- last_id = session->id();
- }
-
- void OnOutgoingMessage(const XmlElement* stanza) {
- XmlElement* elem = new XmlElement(*stanza);
- ASSERT(elem->Name() == QN_IQ);
- ASSERT(elem->HasAttr(QN_TO));
- ASSERT(!elem->HasAttr(QN_FROM));
- ASSERT(elem->HasAttr(QN_TYPE));
- ASSERT((elem->Attr(QN_TYPE) == "set") ||
- (elem->Attr(QN_TYPE) == "result") ||
- (elem->Attr(QN_TYPE) == "error"));
-
- // Add in the appropriate "from".
- elem->SetAttr(QN_FROM, username);
-
- // Add in the appropriate IQ ID.
- if (elem->Attr(QN_TYPE) == "set") {
- ASSERT(!elem->HasAttr(QN_ID));
- elem->SetAttr(QN_ID, GetNextID());
- }
-
- stanzas_.push_back(elem);
- }
-
- void OnRequestSignaling() {
- manager->OnSignalingReady();
- }
-
-
- XmlElement* CheckNextStanza(const std::string& expected) {
- // Get the next stanza, which should exist.
- ASSERT(stanzas_.size() > 0);
- XmlElement* stanza = stanzas_.front();
- stanzas_.pop_front();
-
- // Make sure the stanza is correct.
- std::string actual = stanza->Str();
- if (actual != expected) {
- LOG(LERROR) << "Incorrect stanza: expected=\"" << expected
- << "\" actual=\"" << actual << "\"";
- ASSERT(actual == expected);
- }
-
- return stanza;
- }
-
- void CheckNoStanza() {
- ASSERT(stanzas_.size() == 0);
- }
-
- void PrintNextStanza() {
- ASSERT(stanzas_.size() > 0);
- printf("Stanza: %s\n", stanzas_.front()->Str().c_str());
- }
-
- SessionManager* manager;
- std::string username;
- SessionID last_id;
- uint32 create_count;
- uint32 destroy_count;
- std::deque<XmlElement*> stanzas_;
-};
-
-struct SessionHandler : sigslot::has_slots<> {
- SessionHandler(Session* s) : session(s) {
- session->SignalState.connect(this, &SessionHandler::OnState);
- session->SignalError.connect(this, &SessionHandler::OnError);
- }
-
- void PrepareTransport() {
- Transport* transport = session->GetTransport(kNsP2pTransport);
- if (transport != NULL)
- transport->set_allow_local_ips(true);
- }
-
- void OnState(Session* session, Session::State state) {
- ASSERT(session == this->session);
- last_state = state;
- }
-
- void OnError(Session* session, Session::Error error) {
- ASSERT(session == this->session);
- ASSERT(false); // errors are bad!
- }
-
- Session* session;
- Session::State last_state;
-};
-
-struct MySessionClient: public SessionClient, public sigslot::has_slots<> {
- MySessionClient() : create_count(0), a(NULL), b(NULL) { }
-
- void AddManager(SessionManager* manager) {
- manager->AddClient(kSessionType, this);
- ASSERT(manager->GetClient(kSessionType) == this);
- manager->SignalSessionCreate.connect(
- this, &MySessionClient::OnSessionCreate);
- }
-
- const SessionDescription* CreateSessionDescription(
- const XmlElement* element) {
- return new SessionDescription();
- }
-
- XmlElement* TranslateSessionDescription(
- const SessionDescription* description) {
- return new XmlElement(QName(kSessionType, "description"));
- }
-
- void OnSessionCreate(Session *session, bool initiate) {
- create_count += 1;
- a = session->CreateChannel("a");
- b = session->CreateChannel("b");
-
- if (transport_name.size() > 0)
- session->SetPotentialTransports(&transport_name, 1);
- }
-
- void OnSessionDestroy(Session *session)
- {
- }
-
- void SetTransports(bool p2p, bool raw) {
- if (p2p && raw)
- return; // this is the default
-
- if (p2p) {
- transport_name = kNsP2pTransport;
- }
- }
-
- int create_count;
- TransportChannel* a;
- TransportChannel* b;
- std::string transport_name;
-};
-
-struct ChannelHandler : sigslot::has_slots<> {
- ChannelHandler(TransportChannel* p)
- : channel(p), last_readable(false), last_writable(false), data_count(0),
- last_size(0) {
- p->SignalReadableState.connect(this, &ChannelHandler::OnReadableState);
- p->SignalWritableState.connect(this, &ChannelHandler::OnWritableState);
- p->SignalReadPacket.connect(this, &ChannelHandler::OnReadPacket);
- }
-
- void OnReadableState(TransportChannel* p) {
- ASSERT(p == channel);
- last_readable = channel->readable();
- }
-
- void OnWritableState(TransportChannel* p) {
- ASSERT(p == channel);
- last_writable = channel->writable();
- }
-
- void OnReadPacket(TransportChannel* p, const char* buf, size_t size) {
- ASSERT(p == channel);
- ASSERT(size <= sizeof(last_data));
- data_count += 1;
- last_size = size;
- std::memcpy(last_data, buf, size);
- }
-
- void Send(const char* data, size_t size) {
- int result = channel->SendPacket(data, size);
- ASSERT(result == static_cast<int>(size));
- }
-
- TransportChannel* channel;
- bool last_readable, last_writable;
- int data_count;
- char last_data[4096];
- size_t last_size;
-};
-
-char* Reverse(const char* str) {
- int len = strlen(str);
- char* rev = new char[len+1];
- for (int i = 0; i < len; i++)
- rev[i] = str[len-i-1];
- rev[len] = '\0';
- return rev;
-}
-
-// Sets up values that should be the same for every test.
-void InitTest() {
- SetRandomSeed(7);
- gPort = 28653;
- gID = 0;
-}
-
-// Tests having client2 accept the session.
-void TestAccept(talk_base::Thread* signaling_thread,
- Session* session1, Session* session2,
- SessionHandler* handler1, SessionHandler* handler2,
- SessionManager* manager1, SessionManager* manager2,
- SessionManagerHandler* manhandler1,
- SessionManagerHandler* manhandler2) {
- // Make sure the IQ ID is 5.
- ASSERT(gID <= 5);
- while (gID < 5) GetNextID();
-
- // Accept the session.
- SessionDescription* desc2 = new SessionDescription();
- bool valid = session2->Accept(desc2);
- ASSERT(valid);
-
- scoped_ptr<buzz::XmlElement> stanza;
- stanza.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"5\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"accept\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<ses:description xmlns:ses=\"http://oink.splat/session\"/>"
- "</session>"
- "</cli:iq>"));
- manhandler2->CheckNoStanza();
-
- // Simulate a tiny delay in sending.
- signaling_thread->ProcessMessages(10);
-
- // Delivery the accept.
- manager1->OnIncomingMessage(stanza.get());
- stanza.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" id=\"5\" type=\"result\" from=\"foo@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
- manhandler1->CheckNoStanza();
-
- // Both sessions should be in progress after a short wait.
- signaling_thread->ProcessMessages(10);
- ASSERT(handler1->last_state == Session::STATE_INPROGRESS);
- ASSERT(handler2->last_state == Session::STATE_INPROGRESS);
-}
-
-// Tests sending data between two clients, over two channels.
-void TestSendRecv(ChannelHandler* chanhandler1a, ChannelHandler* chanhandler1b,
- ChannelHandler* chanhandler2a, ChannelHandler* chanhandler2b,
- talk_base::Thread* signaling_thread, bool first_dropped) {
- const char* dat1a = "spamspamspamspamspamspamspambakedbeansspam";
- const char* dat1b = "Lobster Thermidor a Crevette with a mornay sauce...";
- const char* dat2a = Reverse(dat1a);
- const char* dat2b = Reverse(dat1b);
-
- // Sending from 2 -> 1 will enable 1 to send to 2 below. That will then
- // enable 2 to send back to 1. So the code below will just work.
- if (first_dropped) {
- chanhandler2a->Send(dat2a, strlen(dat2a));
- chanhandler2b->Send(dat2b, strlen(dat2b));
- }
-
- for (int i = 0; i < 20; i++) {
- chanhandler1a->Send(dat1a, strlen(dat1a));
- chanhandler1b->Send(dat1b, strlen(dat1b));
- chanhandler2a->Send(dat2a, strlen(dat2a));
- chanhandler2b->Send(dat2b, strlen(dat2b));
-
- signaling_thread->ProcessMessages(10);
-
- ASSERT(chanhandler1a->data_count == i + 1);
- ASSERT(chanhandler1b->data_count == i + 1);
- ASSERT(chanhandler2a->data_count == i + 1);
- ASSERT(chanhandler2b->data_count == i + 1);
-
- ASSERT(chanhandler1a->last_size == strlen(dat2a));
- ASSERT(chanhandler1b->last_size == strlen(dat2b));
- ASSERT(chanhandler2a->last_size == strlen(dat1a));
- ASSERT(chanhandler2b->last_size == strlen(dat1b));
-
- ASSERT(std::memcmp(chanhandler1a->last_data, dat2a, strlen(dat2a)) == 0);
- ASSERT(std::memcmp(chanhandler1b->last_data, dat2b, strlen(dat2b)) == 0);
- ASSERT(std::memcmp(chanhandler2a->last_data, dat1a, strlen(dat1a)) == 0);
- ASSERT(std::memcmp(chanhandler2b->last_data, dat1b, strlen(dat1b)) == 0);
- }
-}
-
-// Tests a session between two clients. The inputs indicate whether we should
-// replace each client's output with what we would see from an old client.
-void TestP2PCompatibility(const std::string& test_name, bool old1, bool old2) {
- InitTest();
-
- talk_base::Thread* signaling_thread = talk_base::Thread::Current();
- scoped_ptr<talk_base::Thread> worker_thread(new talk_base::Thread());
- worker_thread->Start();
-
- scoped_ptr<PortAllocator> allocator(
- new TestPortAllocator(worker_thread.get(), NULL));
- scoped_ptr<MySessionClient> client(new MySessionClient());
- client->SetTransports(true, false);
-
- scoped_ptr<SessionManager> manager1(
- new SessionManager(allocator.get(), worker_thread.get()));
- scoped_ptr<SessionManagerHandler> manhandler1(
- new SessionManagerHandler(manager1.get(), "foo@baz.com"));
- client->AddManager(manager1.get());
-
- Session* session1 = manager1->CreateSession("foo@baz.com", kSessionType);
- ASSERT(manhandler1->create_count == 1);
- ASSERT(manhandler1->last_id == session1->id());
- scoped_ptr<SessionHandler> handler1(new SessionHandler(session1));
-
- ASSERT(client->create_count == 1);
- TransportChannel* chan1a = client->a;
- ASSERT(chan1a->name() == "a");
- ASSERT(session1->GetChannel("a") == chan1a);
- scoped_ptr<ChannelHandler> chanhandler1a(new ChannelHandler(chan1a));
- TransportChannel* chan1b = client->b;
- ASSERT(chan1b->name() == "b");
- ASSERT(session1->GetChannel("b") == chan1b);
- scoped_ptr<ChannelHandler> chanhandler1b(new ChannelHandler(chan1b));
-
- SessionDescription* desc1 = new SessionDescription();
- ASSERT(session1->state() == Session::STATE_INIT);
- bool valid = session1->Initiate("bar@baz.com", NULL, desc1);
- ASSERT(valid);
- handler1->PrepareTransport();
-
- signaling_thread->ProcessMessages(100);
-
- ASSERT(handler1->last_state == Session::STATE_SENTINITIATE);
- scoped_ptr<XmlElement> stanza1, stanza2;
- stanza1.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"initiate\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<ses:description xmlns:ses=\"http://oink.splat/session\"/>"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>"
- "</session>"
- "</cli:iq>"));
- stanza2.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"1\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\""
- " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\""
- " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\""
- " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\""
- " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\""
- " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\""
- " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\""
- " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\""
- " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\""
- " network=\"network\"/>"
- "</p:transport>"
- "</session>"
- "</cli:iq>"));
- manhandler1->CheckNoStanza();
-
- // If the first client were old, the initiate would have no transports and
- // the candidates would be sent in a candidates message.
- if (old1) {
- stanza1.reset(XmlElement::ForStr(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"initiate\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<ses:description xmlns:ses=\"http://oink.splat/session\"/>"
- "</session>"
- "</cli:iq>"));
- stanza2.reset(XmlElement::ForStr(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"1\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"candidates\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\""
- " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\""
- " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\""
- " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\""
- " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\""
- " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\""
- " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\""
- " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\""
- " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\""
- " network=\"network\"/>"
- "</session>"
- "</cli:iq>"));
- }
-
- scoped_ptr<SessionManager> manager2(
- new SessionManager(allocator.get(), worker_thread.get()));
- scoped_ptr<SessionManagerHandler> manhandler2(
- new SessionManagerHandler(manager2.get(), "bar@baz.com"));
- client->AddManager(manager2.get());
-
- // Deliver the initiate.
- manager2->OnIncomingMessage(stanza1.get());
- stanza1.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" id=\"0\" type=\"result\" from=\"bar@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
-
- // If client1 is old, we will not see a transport-accept. If client2 is old,
- // then we should act as if it did not send one.
- if (!old1) {
- stanza1.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"2\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\""
- " type=\"transport-accept\" id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>"
- "</session>"
- "</cli:iq>"));
- } else {
- GetNextID(); // Advance the ID count to be the same in all cases.
- stanza1.reset(NULL);
- }
- if (old2) {
- stanza1.reset(NULL);
- }
- manhandler2->CheckNoStanza();
- ASSERT(manhandler2->create_count == 1);
- ASSERT(manhandler2->last_id == session1->id());
-
- Session* session2 = manager2->GetSession(session1->id());
- ASSERT(session2);
- ASSERT(session1->id() == session2->id());
- ASSERT(manhandler2->last_id == session2->id());
- ASSERT(session2->state() == Session::STATE_RECEIVEDINITIATE);
- scoped_ptr<SessionHandler> handler2(new SessionHandler(session2));
- handler2->PrepareTransport();
-
- ASSERT(session2->name() == session1->remote_name());
- ASSERT(session1->name() == session2->remote_name());
-
- ASSERT(session2->transport() != NULL);
- ASSERT(session2->transport()->name() == kNsP2pTransport);
-
- ASSERT(client->create_count == 2);
- TransportChannel* chan2a = client->a;
- scoped_ptr<ChannelHandler> chanhandler2a(new ChannelHandler(chan2a));
- TransportChannel* chan2b = client->b;
- scoped_ptr<ChannelHandler> chanhandler2b(new ChannelHandler(chan2b));
-
- // Deliver the candidates.
- manager2->OnIncomingMessage(stanza2.get());
- stanza2.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" id=\"1\" type=\"result\" from=\"bar@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
-
- signaling_thread->ProcessMessages(10);
-
- // If client1 is old, we should see a candidates message instead of a
- // transport-info. If client2 is old, we should act as if we did.
- const char* kCandidates2 =
- "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"3\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"candidates\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28673\""
- " preference=\"1\" username=\"FJDz3iuXjbQJDRjs\" protocol=\"udp\""
- " generation=\"0\" password=\"Ca5daV9m6G91qhlM\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28678\""
- " preference=\"1\" username=\"xlN53r3Jn/R5XuCt\" protocol=\"udp\""
- " generation=\"0\" password=\"rgik2pKsjaPSUdJd\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28683\""
- " preference=\"1\" username=\"IBZ8CSq8ot2+pSMp\" protocol=\"udp\""
- " generation=\"0\" password=\"i7RcDsGntMI6fzdd\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28688\""
- " preference=\"1\" username=\"SEtih9PYtMHCAlMI\" protocol=\"udp\""
- " generation=\"0\" password=\"wROrHJ3+gDxUUMp1\" type=\"local\""
- " network=\"network\"/>"
- "</session>"
- "</cli:iq>";
- if (old1) {
- stanza2.reset(manhandler2->CheckNextStanza(kCandidates2));
- } else {
- stanza2.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"3\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28673\""
- " preference=\"1\" username=\"FJDz3iuXjbQJDRjs\" protocol=\"udp\""
- " generation=\"0\" password=\"Ca5daV9m6G91qhlM\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28678\""
- " preference=\"1\" username=\"xlN53r3Jn/R5XuCt\" protocol=\"udp\""
- " generation=\"0\" password=\"rgik2pKsjaPSUdJd\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28683\""
- " preference=\"1\" username=\"IBZ8CSq8ot2+pSMp\" protocol=\"udp\""
- " generation=\"0\" password=\"i7RcDsGntMI6fzdd\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28688\""
- " preference=\"1\" username=\"SEtih9PYtMHCAlMI\" protocol=\"udp\""
- " generation=\"0\" password=\"wROrHJ3+gDxUUMp1\" type=\"local\""
- " network=\"network\"/>"
- "</p:transport>"
- "</session>"
- "</cli:iq>"));
- }
- if (old2) {
- stanza2.reset(XmlElement::ForStr(kCandidates2));
- }
- manhandler2->CheckNoStanza();
-
- // Deliver the transport-accept if one exists.
- if (stanza1.get() != NULL) {
- manager1->OnIncomingMessage(stanza1.get());
- stanza1.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" id=\"2\" type=\"result\" from=\"foo@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
- manhandler1->CheckNoStanza();
-
- // The first session should now have a transport.
- ASSERT(session1->transport() != NULL);
- ASSERT(session1->transport()->name() == kNsP2pTransport);
- }
-
- // Deliver the candidates. If client2 is old (or is acting old because
- // client1 is), then client1 will correct its earlier mistake of sending
- // transport-info by sending a candidates message. If client1 is supposed to
- // be old, then it sent candidates earlier, so we drop this.
- manager1->OnIncomingMessage(stanza2.get());
- if (old1 || old2) {
- stanza2.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"4\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"candidates\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\""
- " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\""
- " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\""
- " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\""
- " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\""
- " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\""
- " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\""
- " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\""
- " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\""
- " network=\"network\"/>"
- "</session>"
- "</cli:iq>"));
- } else {
- GetNextID(); // Advance the ID count to be the same in all cases.
- stanza2.reset(NULL);
- }
- if (old1) {
- stanza2.reset(NULL);
- }
- stanza1.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" id=\"3\" type=\"result\" from=\"foo@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
- manhandler1->CheckNoStanza();
-
- // The first session must have a transport in either case now.
- ASSERT(session1->transport() != NULL);
- ASSERT(session1->transport()->name() == kNsP2pTransport);
-
- // If client1 just generated a candidates message, then we must deliver it.
- if (stanza2.get() != NULL) {
- manager2->OnIncomingMessage(stanza2.get());
- stanza2.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" id=\"4\" type=\"result\" from=\"bar@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
- manhandler2->CheckNoStanza();
- }
-
- // The channels should be able to become writable at this point. This
- // requires pinging, so it may take a little while.
- signaling_thread->ProcessMessages(500);
- ASSERT(chan1a->writable() && chan1a->readable());
- ASSERT(chan1b->writable() && chan1b->readable());
- ASSERT(chan2a->writable() && chan2a->readable());
- ASSERT(chan2b->writable() && chan2b->readable());
- ASSERT(chanhandler1a->last_writable);
- ASSERT(chanhandler1b->last_writable);
- ASSERT(chanhandler2a->last_writable);
- ASSERT(chanhandler2b->last_writable);
-
- // Accept the session.
- TestAccept(signaling_thread, session1, session2,
- handler1.get(), handler2.get(),
- manager1.get(), manager2.get(),
- manhandler1.get(), manhandler2.get());
-
- // Send a bunch of data between them.
- TestSendRecv(chanhandler1a.get(), chanhandler1b.get(), chanhandler2a.get(),
- chanhandler2b.get(), signaling_thread, false);
-
- manager1->DestroySession(session1);
- manager2->DestroySession(session2);
-
- ASSERT(manhandler1->create_count == 1);
- ASSERT(manhandler2->create_count == 1);
- ASSERT(manhandler1->destroy_count == 1);
- ASSERT(manhandler2->destroy_count == 1);
-
- worker_thread->Stop();
-
- std::cout << "P2P Compatibility: " << test_name << ": PASS" << std::endl;
-}
-
-// Tests the P2P transport. The flags indicate whether they clients will
-// advertise support for raw as well.
-void TestP2P(const std::string& test_name, bool raw1, bool raw2) {
- InitTest();
-
- talk_base::Thread* signaling_thread = talk_base::Thread::Current();
- scoped_ptr<talk_base::Thread> worker_thread(new talk_base::Thread());
- worker_thread->Start();
-
- scoped_ptr<PortAllocator> allocator(
- new TestPortAllocator(worker_thread.get(), NULL));
- scoped_ptr<MySessionClient> client1(new MySessionClient());
- client1->SetTransports(true, raw1);
- scoped_ptr<MySessionClient> client2(new MySessionClient());
- client2->SetTransports(true, raw2);
-
- scoped_ptr<SessionManager> manager1(
- new SessionManager(allocator.get(), worker_thread.get()));
- scoped_ptr<SessionManagerHandler> manhandler1(
- new SessionManagerHandler(manager1.get(), "foo@baz.com"));
- client1->AddManager(manager1.get());
-
- Session* session1 = manager1->CreateSession("foo@baz.com", kSessionType);
- ASSERT(manhandler1->create_count == 1);
- ASSERT(manhandler1->last_id == session1->id());
- scoped_ptr<SessionHandler> handler1(new SessionHandler(session1));
-
- ASSERT(client1->create_count == 1);
- TransportChannel* chan1a = client1->a;
- ASSERT(chan1a->name() == "a");
- ASSERT(session1->GetChannel("a") == chan1a);
- scoped_ptr<ChannelHandler> chanhandler1a(new ChannelHandler(chan1a));
- TransportChannel* chan1b = client1->b;
- ASSERT(chan1b->name() == "b");
- ASSERT(session1->GetChannel("b") == chan1b);
- scoped_ptr<ChannelHandler> chanhandler1b(new ChannelHandler(chan1b));
-
- SessionDescription* desc1 = new SessionDescription();
- ASSERT(session1->state() == Session::STATE_INIT);
- bool valid = session1->Initiate("bar@baz.com", NULL, desc1);
- ASSERT(valid);
- handler1->PrepareTransport();
-
- signaling_thread->ProcessMessages(100);
-
- ASSERT(handler1->last_state == Session::STATE_SENTINITIATE);
- scoped_ptr<XmlElement> stanza1, stanza2;
- if (raw1) {
- stanza1.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"initiate\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<ses:description xmlns:ses=\"http://oink.splat/session\"/>"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>"
- "<raw:transport xmlns:raw=\"http://www.google.com/transport/raw\"/>"
- "</session>"
- "</cli:iq>"));
- } else {
- stanza1.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"0\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"initiate\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<ses:description xmlns:ses=\"http://oink.splat/session\"/>"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>"
- "</session>"
- "</cli:iq>"));
- }
- stanza2.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" type=\"set\" from=\"foo@baz.com\" id=\"1\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28653\""
- " preference=\"1\" username=\"h0ISP4S5SJKH/9EY\" protocol=\"udp\""
- " generation=\"0\" password=\"UhnAmO5C89dD2dZ+\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28658\""
- " preference=\"1\" username=\"yid4vfB3zXPvrRB9\" protocol=\"udp\""
- " generation=\"0\" password=\"SqLXTvcEyriIo+Mj\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28663\""
- " preference=\"1\" username=\"NvT78D7WxPWM1KL8\" protocol=\"udp\""
- " generation=\"0\" password=\"+mV/QhOapXu4caPX\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28668\""
- " preference=\"1\" username=\"8EzB7MH+TYpIlSp/\" protocol=\"udp\""
- " generation=\"0\" password=\"h+MelLXupoK5aYqC\" type=\"local\""
- " network=\"network\"/>"
- "</p:transport>"
- "</session>"
- "</cli:iq>"));
- manhandler1->CheckNoStanza();
-
- scoped_ptr<SessionManager> manager2(
- new SessionManager(allocator.get(), worker_thread.get()));
- scoped_ptr<SessionManagerHandler> manhandler2(
- new SessionManagerHandler(manager2.get(), "bar@baz.com"));
- client2->AddManager(manager2.get());
-
- // Deliver the initiate.
- manager2->OnIncomingMessage(stanza1.get());
- stanza1.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" id=\"0\" type=\"result\" from=\"bar@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
- stanza1.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"2\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\""
- " type=\"transport-accept\" id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\"/>"
- "</session>"
- "</cli:iq>"));
- manhandler2->CheckNoStanza();
- ASSERT(manhandler2->create_count == 1);
- ASSERT(manhandler2->last_id == session1->id());
-
- Session* session2 = manager2->GetSession(session1->id());
- ASSERT(session2);
- ASSERT(session1->id() == session2->id());
- ASSERT(manhandler2->last_id == session2->id());
- ASSERT(session2->state() == Session::STATE_RECEIVEDINITIATE);
- scoped_ptr<SessionHandler> handler2(new SessionHandler(session2));
- handler2->PrepareTransport();
-
- ASSERT(session2->name() == session1->remote_name());
- ASSERT(session1->name() == session2->remote_name());
-
- ASSERT(session2->transport() != NULL);
- ASSERT(session2->transport()->name() == kNsP2pTransport);
-
- ASSERT(client2->create_count == 1);
- TransportChannel* chan2a = client2->a;
- scoped_ptr<ChannelHandler> chanhandler2a(new ChannelHandler(chan2a));
- TransportChannel* chan2b = client2->b;
- scoped_ptr<ChannelHandler> chanhandler2b(new ChannelHandler(chan2b));
-
- // Deliver the candidates.
- manager2->OnIncomingMessage(stanza2.get());
- stanza2.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" id=\"1\" type=\"result\" from=\"bar@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
-
- signaling_thread->ProcessMessages(10);
-
- stanza2.reset(manhandler2->CheckNextStanza(
- "<cli:iq to=\"foo@baz.com\" type=\"set\" from=\"bar@baz.com\" id=\"3\""
- " xmlns:cli=\"jabber:client\">"
- "<session xmlns=\"http://www.google.com/session\" type=\"transport-info\""
- " id=\"2154761789\" initiator=\"foo@baz.com\">"
- "<p:transport xmlns:p=\"http://www.google.com/transport/p2p\">"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28673\""
- " preference=\"1\" username=\"FJDz3iuXjbQJDRjs\" protocol=\"udp\""
- " generation=\"0\" password=\"Ca5daV9m6G91qhlM\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"a\" address=\"127.0.0.1\" port=\"28678\""
- " preference=\"1\" username=\"xlN53r3Jn/R5XuCt\" protocol=\"udp\""
- " generation=\"0\" password=\"rgik2pKsjaPSUdJd\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28683\""
- " preference=\"1\" username=\"IBZ8CSq8ot2+pSMp\" protocol=\"udp\""
- " generation=\"0\" password=\"i7RcDsGntMI6fzdd\" type=\"local\""
- " network=\"network\"/>"
- "<candidate name=\"b\" address=\"127.0.0.1\" port=\"28688\""
- " preference=\"1\" username=\"SEtih9PYtMHCAlMI\" protocol=\"udp\""
- " generation=\"0\" password=\"wROrHJ3+gDxUUMp1\" type=\"local\""
- " network=\"network\"/>"
- "</p:transport>"
- "</session>"
- "</cli:iq>"));
- manhandler2->CheckNoStanza();
-
- // Deliver the transport-accept.
- manager1->OnIncomingMessage(stanza1.get());
- stanza1.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" id=\"2\" type=\"result\" from=\"foo@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
- manhandler1->CheckNoStanza();
-
- // The first session should now have a transport.
- ASSERT(session1->transport() != NULL);
- ASSERT(session1->transport()->name() == kNsP2pTransport);
-
- // Deliver the candidates.
- manager1->OnIncomingMessage(stanza2.get());
- stanza1.reset(manhandler1->CheckNextStanza(
- "<cli:iq to=\"bar@baz.com\" id=\"3\" type=\"result\" from=\"foo@baz.com\""
- " xmlns:cli=\"jabber:client\"/>"));
- manhandler1->CheckNoStanza();
-
- // The channels should be able to become writable at this point. This
- // requires pinging, so it may take a little while.
- signaling_thread->ProcessMessages(500);
- ASSERT(chan1a->writable() && chan1a->readable());
- ASSERT(chan1b->writable() && chan1b->readable());
- ASSERT(chan2a->writable() && chan2a->readable());
- ASSERT(chan2b->writable() && chan2b->readable());
- ASSERT(chanhandler1a->last_writable);
- ASSERT(chanhandler1b->last_writable);
- ASSERT(chanhandler2a->last_writable);
- ASSERT(chanhandler2b->last_writable);
-
- // Accept the session.
- TestAccept(signaling_thread, session1, session2,
- handler1.get(), handler2.get(),
- manager1.get(), manager2.get(),
- manhandler1.get(), manhandler2.get());
-
- // Send a bunch of data between them.
- TestSendRecv(chanhandler1a.get(), chanhandler1b.get(), chanhandler2a.get(),
- chanhandler2b.get(), signaling_thread, false);
-
- manager1->DestroySession(session1);
- manager2->DestroySession(session2);
-
- ASSERT(manhandler1->create_count == 1);
- ASSERT(manhandler2->create_count == 1);
- ASSERT(manhandler1->destroy_count == 1);
- ASSERT(manhandler2->destroy_count == 1);
-
- worker_thread->Stop();
-
- std::cout << "P2P: " << test_name << ": PASS" << std::endl;
-}
-//
-int main(int argc, char* argv[]) {
- talk_base::LogMessage::LogToDebug(talk_base::LS_WARNING);
-
- TestP2P("{p2p} => {p2p}", false, false);
- TestP2P("{p2p} => {p2p,raw}", false, true);
- TestP2P("{p2p,raw} => {p2p}", true, false);
- TestP2P("{p2p,raw} => {p2p,raw}", true, true);
- TestP2PCompatibility("New => New", false, false);
- TestP2PCompatibility("Old => New", true, false);
- TestP2PCompatibility("New => Old", false, true);
- TestP2PCompatibility("Old => Old", true, true);
-
- return 0;
-}
diff --git a/talk/p2p/base/sessionclient.h b/talk/p2p/base/sessionclient.h
old mode 100755
new mode 100644
index a92df1d..d6604a9
--- a/talk/p2p/base/sessionclient.h
+++ b/talk/p2p/base/sessionclient.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_P2P_BASE_SESSIONCLIENT_H_
-#define _CRICKET_P2P_BASE_SESSIONCLIENT_H_
+#ifndef TALK_P2P_BASE_SESSIONCLIENT_H_
+#define TALK_P2P_BASE_SESSIONCLIENT_H_
namespace buzz {
class XmlElement;
@@ -34,14 +34,28 @@
namespace cricket {
+struct ParseError;
class Session;
class SessionDescription;
+class ContentParser {
+ public:
+ virtual bool ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ const ContentDescription** content,
+ ParseError* error) = 0;
+ virtual bool WriteContent(SignalingProtocol protocol,
+ const ContentDescription* content,
+ buzz::XmlElement** elem,
+ WriteError* error) = 0;
+ virtual ~ContentParser() {}
+};
+
// A SessionClient exists in 1-1 relation with each session. The implementor
// of this interface is the one that understands *what* the two sides are
// trying to send to one another. The lower-level layers only know how to send
// data; they do not know what is being sent.
-class SessionClient {
+class SessionClient : public ContentParser {
public:
// Notifies the client of the creation / destruction of sessions of this type.
//
@@ -53,19 +67,19 @@
virtual void OnSessionCreate(Session* session, bool received_initiate) = 0;
virtual void OnSessionDestroy(Session* session) = 0;
- // Provides functions to convert between the XML description of the session
- // and the data structures useful to the client. The resulting objects are
- // held by the Session for easy access.
- virtual const SessionDescription* CreateSessionDescription(
- const buzz::XmlElement* element) = 0;
- virtual buzz::XmlElement* TranslateSessionDescription(
- const SessionDescription* description) = 0;
-
-protected:
+ virtual bool ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ const ContentDescription** content,
+ ParseError* error) = 0;
+ virtual bool WriteContent(SignalingProtocol protocol,
+ const ContentDescription* content,
+ buzz::XmlElement** elem,
+ WriteError* error) = 0;
+ protected:
// The SessionClient interface explicitly does not include destructor
virtual ~SessionClient() { }
};
} // namespace cricket
-#endif // _CRICKET_P2P_BASE_SESSIONCLIENT_H_
+#endif // TALK_P2P_BASE_SESSIONCLIENT_H_
diff --git a/talk/p2p/base/sessiondescription.cc b/talk/p2p/base/sessiondescription.cc
new file mode 100644
index 0000000..872358e
--- /dev/null
+++ b/talk/p2p/base/sessiondescription.cc
@@ -0,0 +1,72 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/p2p/base/sessiondescription.h"
+
+#include "talk/xmllite/xmlelement.h"
+
+namespace cricket {
+
+const ContentInfo* FindContentInfoByName(
+ const ContentInfos& contents, const std::string& name) {
+ for (ContentInfos::const_iterator content = contents.begin();
+ content != contents.end(); content++) {
+ if (content->name == name) {
+ return &(*content);
+ }
+ }
+ return NULL;
+}
+
+const ContentInfo* FindContentInfoByType(
+ const ContentInfos& contents, const std::string& type) {
+ for (ContentInfos::const_iterator content = contents.begin();
+ content != contents.end(); content++) {
+ if (content->type == type) {
+ return &(*content);
+ }
+ }
+ return NULL;
+}
+
+const ContentInfo* SessionDescription::GetContentByName(
+ const std::string& name) const {
+ return FindContentInfoByName(contents_, name);
+}
+
+const ContentInfo* SessionDescription::FirstContentByType(
+ const std::string& type) const {
+ return FindContentInfoByType(contents_, type);
+}
+
+void SessionDescription::AddContent(const std::string& name,
+ const std::string& type,
+ const ContentDescription* description) {
+ contents_.push_back(ContentInfo(name, type, description));
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/sessiondescription.h b/talk/p2p/base/sessiondescription.h
old mode 100755
new mode 100644
index 28b7084..fe575fa
--- a/talk/p2p/base/sessiondescription.h
+++ b/talk/p2p/base/sessiondescription.h
@@ -2,41 +2,109 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _SESSIONDESCRIPTION_H_
-#define _SESSIONDESCRIPTION_H_
+#ifndef TALK_P2P_BASE_SESSIONDESCRIPTION_H_
+#define TALK_P2P_BASE_SESSIONDESCRIPTION_H_
+
+#include <string>
+#include <vector>
namespace cricket {
-// The client overrides this with whatever
-
-class SessionDescription {
-public:
- virtual ~SessionDescription() {}
+// Describes a session content. Individual content types inherit from
+// this class. Analagous to a <jingle><content><description> or
+// <session><description>.
+class ContentDescription {
+ public:
+ virtual ~ContentDescription() {}
};
-} // namespace cricket
+// Analagous to a <jingle><content> or <session><description>.
+// name = name of <content name="...">
+// type = xmlns of <content>
+struct ContentInfo {
+ ContentInfo() : description(NULL) {}
+ ContentInfo(const std::string& name,
+ const std::string& type,
+ const ContentDescription* description) :
+ name(name), type(type), description(description) {}
+ std::string name;
+ std::string type;
+ const ContentDescription* description;
+};
-#endif // _SESSIONDESCRIPTION_H_
+typedef std::vector<ContentInfo> ContentInfos;
+const ContentInfo* FindContentInfoByName(
+ const ContentInfos& contents, const std::string& name);
+const ContentInfo* FindContentInfoByType(
+ const ContentInfos& contents, const std::string& type);
+
+// Describes a collection of contents, each with its own name and
+// type. Analgous to a <jingle> or <session> stanza. Assumes that
+// contents are unique be name, but doesn't enforce that.
+class SessionDescription {
+ public:
+ SessionDescription() {}
+ explicit SessionDescription(const ContentInfos& contents) :
+ contents_(contents) {}
+ const ContentInfo* GetContentByName(const std::string& name) const;
+ const ContentInfo* FirstContentByType(const std::string& type) const;
+ // Takes ownership of ContentDescription*.
+ void AddContent(const std::string& name,
+ const std::string& type,
+ const ContentDescription* description);
+ // TODO: Implement RemoveContent when it's needed for
+ // content-remove Jingle messages.
+ // void RemoveContent(const std::string& name);
+ const ContentInfos& contents() const { return contents_; }
+
+ ~SessionDescription() {
+ for (ContentInfos::iterator content = contents_.begin();
+ content != contents_.end(); content++) {
+ delete content->description;
+ }
+ }
+
+ private:
+ ContentInfos contents_;
+};
+
+// Indicates whether a ContentDescription was an offer or an answer, as
+// described in http://www.ietf.org/rfc/rfc3264.txt. CA_UPDATE
+// indicates a jingle update message which contains a subset of a full
+// session description
+enum ContentAction {
+ CA_OFFER, CA_ANSWER, CA_UPDATE
+};
+
+// Indicates whether a ContentDescription was sent by the local client
+// or received from the remote client.
+enum ContentSource {
+ CS_LOCAL, CS_REMOTE
+};
+
+} // namespace cricket
+
+#endif // TALK_P2P_BASE_SESSIONDESCRIPTION_H_
diff --git a/talk/p2p/base/sessionid.h b/talk/p2p/base/sessionid.h
old mode 100755
new mode 100644
index a12535c..6942942
--- a/talk/p2p/base/sessionid.h
+++ b/talk/p2p/base/sessionid.h
@@ -25,70 +25,13 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _SESSIONID_H_
-#define _SESSIONID_H_
+#ifndef TALK_P2P_BASE_SESSIONID_H_
+#define TALK_P2P_BASE_SESSIONID_H_
-#include "talk/base/basictypes.h"
-#include <string>
-#include <sstream>
+// TODO: Remove this file.
namespace cricket {
-// Each session is identified by a pair (from,id), where id is only
-// assumed to be unique to the machine identified by from.
-class SessionID {
-public:
- SessionID() : id_str_("0") {
- }
- SessionID(const std::string& initiator, uint32 id)
- : initiator_(initiator) {
- set_id(id);
- }
- SessionID(const SessionID& sid)
- : id_str_(sid.id_str_), initiator_(sid.initiator_) {
- }
+} // namespace cricket
- void set_id(uint32 id) {
- std::stringstream st;
- st << id;
- st >> id_str_;
- }
- const std::string id_str() const {
- return id_str_;
- }
- void set_id_str(const std::string &id_str) {
- id_str_ = id_str;
- }
-
- const std::string &initiator() const {
- return initiator_;
- }
- void set_initiator(const std::string &initiator) {
- initiator_ = initiator;
- }
-
- bool operator <(const SessionID& sid) const {
- int r = initiator_.compare(sid.initiator_);
- if (r == 0)
- r = id_str_.compare(sid.id_str_);
- return r < 0;
- }
-
- bool operator ==(const SessionID& sid) const {
- return (id_str_ == sid.id_str_) && (initiator_ == sid.initiator_);
- }
-
- SessionID& operator =(const SessionID& sid) {
- id_str_ = sid.id_str_;
- initiator_ = sid.initiator_;
- return *this;
- }
-
-private:
- std::string id_str_;
- std::string initiator_;
-};
-
-} // namespace cricket
-
-#endif // _SESSIONID_H_
+#endif // TALK_P2P_BASE_SESSIONID_H_
diff --git a/talk/p2p/base/sessionmanager.cc b/talk/p2p/base/sessionmanager.cc
old mode 100755
new mode 100644
index ae71a75..61a4c4a
--- a/talk/p2p/base/sessionmanager.cc
+++ b/talk/p2p/base/sessionmanager.cc
@@ -26,15 +26,19 @@
*/
#include "talk/p2p/base/sessionmanager.h"
+
#include "talk/base/common.h"
#include "talk/base/helpers.h"
+#include "talk/base/stringencode.h"
#include "talk/p2p/base/constants.h"
+#include "talk/p2p/base/session.h"
+#include "talk/p2p/base/sessionmessages.h"
#include "talk/xmpp/constants.h"
#include "talk/xmpp/jid.h"
namespace cricket {
-SessionManager::SessionManager(PortAllocator *allocator,
+SessionManager::SessionManager(PortAllocator *allocator,
talk_base::Thread *worker) {
allocator_ = allocator;
signaling_thread_ = talk_base::Thread::Current();
@@ -50,39 +54,42 @@
// Note: Session::Terminate occurs asynchronously, so it's too late to
// delete them now. They better be all gone.
ASSERT(session_map_.empty());
- //TerminateAll();
+ // TerminateAll();
}
-void SessionManager::AddClient(const std::string& session_type,
+void SessionManager::AddClient(const std::string& content_type,
SessionClient* client) {
- ASSERT(client_map_.find(session_type) == client_map_.end());
- client_map_[session_type] = client;
+ ASSERT(client_map_.find(content_type) == client_map_.end());
+ client_map_[content_type] = client;
}
-void SessionManager::RemoveClient(const std::string& session_type) {
- ClientMap::iterator iter = client_map_.find(session_type);
+void SessionManager::RemoveClient(const std::string& content_type) {
+ ClientMap::iterator iter = client_map_.find(content_type);
ASSERT(iter != client_map_.end());
client_map_.erase(iter);
}
-SessionClient* SessionManager::GetClient(const std::string& session_type) {
- ClientMap::iterator iter = client_map_.find(session_type);
+SessionClient* SessionManager::GetClient(const std::string& content_type) {
+ ClientMap::iterator iter = client_map_.find(content_type);
return (iter != client_map_.end()) ? iter->second : NULL;
}
-Session *SessionManager::CreateSession(const std::string& name,
- const std::string& session_type) {
- return CreateSession(name, SessionID(name, CreateRandomId()), session_type,
- false);
+Session* SessionManager::CreateSession(const std::string& local_name,
+ const std::string& content_type) {
+ return CreateSession(local_name, local_name,
+ talk_base::ToString(talk_base::CreateRandomId()),
+ content_type, false);
}
-Session *SessionManager::CreateSession(
- const std::string &name, const SessionID& id,
- const std::string& session_type, bool received_initiate) {
- SessionClient* client = GetClient(session_type);
+Session* SessionManager::CreateSession(
+ const std::string& local_name, const std::string& initiator_name,
+ const std::string& sid, const std::string& content_type,
+ bool received_initiate) {
+ SessionClient* client = GetClient(content_type);
ASSERT(client != NULL);
- Session *session = new Session(this, name, id, session_type, client);
+ Session* session = new Session(this, local_name, initiator_name,
+ sid, content_type, client);
session_map_[session->id()] = session;
session->SignalRequestSignaling.connect(
this, &SessionManager::OnRequestSignaling);
@@ -94,7 +101,7 @@
return session;
}
-void SessionManager::DestroySession(Session *session) {
+void SessionManager::DestroySession(Session* session) {
if (session != NULL) {
SessionMap::iterator it = session_map_.find(session->id());
if (it != session_map_.end()) {
@@ -106,8 +113,8 @@
}
}
-Session *SessionManager::GetSession(const SessionID& id) {
- SessionMap::iterator it = session_map_.find(id);
+Session* SessionManager::GetSession(const std::string& sid) {
+ SessionMap::iterator it = session_map_.find(sid);
if (it != session_map_.end())
return it->second;
return NULL;
@@ -115,97 +122,66 @@
void SessionManager::TerminateAll() {
while (session_map_.begin() != session_map_.end()) {
- Session *session = session_map_.begin()->second;
+ Session* session = session_map_.begin()->second;
session->Terminate();
}
}
bool SessionManager::IsSessionMessage(const buzz::XmlElement* stanza) {
- if (stanza->Name() != buzz::QN_IQ)
- return false;
- if (!stanza->HasAttr(buzz::QN_TYPE))
- return false;
- if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_SET)
- return false;
-
- const buzz::XmlElement* session = stanza->FirstNamed(QN_SESSION);
- if (!session)
- return false;
- if (!session->HasAttr(buzz::QN_TYPE))
- return false;
- if (!session->HasAttr(buzz::QN_ID) || !session->HasAttr(QN_INITIATOR))
- return false;
-
- return true;
+ return cricket::IsSessionMessage(stanza);
}
-Session* SessionManager::FindSessionForStanza(const buzz::XmlElement* stanza,
- bool incoming) {
- const buzz::XmlElement* session_xml = stanza->FirstNamed(QN_SESSION);
- ASSERT(session_xml != NULL);
-
- SessionID id;
- id.set_id_str(session_xml->Attr(buzz::QN_ID));
- id.set_initiator(session_xml->Attr(QN_INITIATOR));
-
- // Pass this message to the session in question.
- SessionMap::iterator iter = session_map_.find(id);
+Session* SessionManager::FindSession(const std::string& sid,
+ const std::string& remote_name) {
+ SessionMap::iterator iter = session_map_.find(sid);
if (iter == session_map_.end())
return NULL;
Session* session = iter->second;
+ if (buzz::Jid(remote_name) != buzz::Jid(session->remote_name()))
+ return NULL;
- // match on "from"? or "to"?
- buzz::QName attr = buzz::QN_TO;
- if (incoming) {
- attr = buzz::QN_FROM;
- }
- buzz::Jid remote(session->remote_name());
- buzz::Jid match(stanza->Attr(attr));
- if (remote == match) {
- return session;
- }
- return NULL;
+ return session;
}
void SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) {
- ASSERT(stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET);
+ SessionMessage msg;
+ ParseError error;
- Session* session = FindSessionForStanza(stanza, true);
+ if (!ParseSessionMessage(stanza, &msg, &error)) {
+ SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
+ error.text, NULL);
+ return;
+ }
+
+ Session* session = FindSession(msg.sid, msg.from);
if (session) {
- session->OnIncomingMessage(stanza);
+ session->OnIncomingMessage(msg);
+ return;
+ }
+ if (msg.type != ACTION_SESSION_INITIATE) {
+ SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
+ "unknown session", NULL);
return;
}
- const buzz::XmlElement* session_xml = stanza->FirstNamed(QN_SESSION);
- ASSERT(session_xml != NULL);
- if (session_xml->Attr(buzz::QN_TYPE) == "initiate") {
- std::string session_type = FindClient(session_xml);
- if (session_type.size() == 0) {
- SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- "unknown session description type", NULL);
- } else {
- SessionID id;
- id.set_id_str(session_xml->Attr(buzz::QN_ID));
- id.set_initiator(session_xml->Attr(QN_INITIATOR));
-
- session = CreateSession(stanza->Attr(buzz::QN_TO),
- id,
- session_type, true);
- session->OnIncomingMessage(stanza);
-
- // If we haven't rejected, and we haven't selected a transport yet,
- // let's do it now.
- if ((session->state() != Session::STATE_SENTREJECT) &&
- (session->transport() == NULL)) {
- session->ChooseTransport(stanza);
- }
- }
+ std::string content_type;
+ if (!ParseContentType(msg.protocol, msg.action_elem,
+ &content_type, &error)) {
+ SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
+ error.text, NULL);
return;
}
- SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- "unknown session", NULL);
+ if (!GetClient(content_type)) {
+ SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
+ "unknown content type: " + content_type, NULL);
+ return;
+ }
+
+ session = CreateSession(msg.to, msg.initiator, msg.sid,
+ content_type, true);
+ session->OnIncomingMessage(msg);
}
void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
@@ -215,16 +191,22 @@
return;
}
-void SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza,
+void SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza,
const buzz::XmlElement* error_stanza) {
- Session* session = FindSessionForStanza(orig_stanza, false);
+ SessionMessage msg;
+ ParseError error;
+ if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
+ return; // TODO: log somewhere?
+ }
+
+ Session* session = FindSession(msg.sid, msg.to);
if (session) {
- scoped_ptr<buzz::XmlElement> synthetic_error;
+ talk_base::scoped_ptr<buzz::XmlElement> synthetic_error;
if (!error_stanza) {
- // A failed send is semantically equivalent to an error response, so we
+ // A failed send is semantically equivalent to an error response, so we
// can just turn the former into the latter.
synthetic_error.reset(
- CreateErrorMessage(orig_stanza, buzz::QN_STANZA_ITEM_NOT_FOUND,
+ CreateErrorMessage(orig_stanza, buzz::QN_STANZA_ITEM_NOT_FOUND,
"cancel", "Recipient did not respond", NULL));
error_stanza = synthetic_error.get();
}
@@ -233,27 +215,14 @@
}
}
-std::string SessionManager::FindClient(const buzz::XmlElement* session) {
- for (const buzz::XmlElement* elem = session->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- if (elem->Name().LocalPart() == "description") {
- ClientMap::iterator iter = client_map_.find(elem->Name().Namespace());
- if (iter != client_map_.end())
- return iter->first;
- }
- }
- return "";
-}
-
void SessionManager::SendErrorMessage(const buzz::XmlElement* stanza,
const buzz::QName& name,
const std::string& type,
const std::string& text,
const buzz::XmlElement* extra_info) {
- scoped_ptr<buzz::XmlElement> msg(
+ talk_base::scoped_ptr<buzz::XmlElement> msg(
CreateErrorMessage(stanza, name, type, text, extra_info));
- SignalOutgoingMessage(msg.get());
+ SignalOutgoingMessage(this, msg.get());
}
buzz::XmlElement* SessionManager::CreateErrorMessage(
@@ -267,11 +236,7 @@
iq->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
iq->SetAttr(buzz::QN_TYPE, "error");
- for (const buzz::XmlElement* elem = stanza->FirstElement();
- elem != NULL;
- elem = elem->NextElement()) {
- iq->AddElement(new buzz::XmlElement(*elem));
- }
+ CopyXmlChildren(stanza, iq);
buzz::XmlElement* error = new buzz::XmlElement(buzz::QN_ERROR);
error->SetAttr(buzz::QN_TYPE, type);
@@ -304,10 +269,10 @@
void SessionManager::OnOutgoingMessage(Session* session,
const buzz::XmlElement* stanza) {
- SignalOutgoingMessage(stanza);
+ SignalOutgoingMessage(this, stanza);
}
-void SessionManager::OnErrorMessage(Session* session,
+void SessionManager::OnErrorMessage(BaseSession* session,
const buzz::XmlElement* stanza,
const buzz::QName& name,
const std::string& type,
@@ -328,4 +293,4 @@
SignalRequestSignaling();
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/sessionmanager.h b/talk/p2p/base/sessionmanager.h
old mode 100755
new mode 100644
index 423af65..9bc1019
--- a/talk/p2p/base/sessionmanager.h
+++ b/talk/p2p/base/sessionmanager.h
@@ -25,18 +25,17 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _SESSIONMANAGER_H_
-#define _SESSIONMANAGER_H_
+#ifndef TALK_P2P_BASE_SESSIONMANAGER_H_
+#define TALK_P2P_BASE_SESSIONMANAGER_H_
-#include "talk/base/thread.h"
-#include "talk/p2p/base/portallocator.h"
-#include "talk/p2p/base/session.h"
-#include "talk/p2p/base/sessionid.h"
-#include "talk/base/sigslot.h"
-
+#include <map>
#include <string>
#include <utility>
-#include <map>
+#include <vector>
+
+#include "talk/base/sigslot.h"
+#include "talk/base/thread.h"
+#include "talk/p2p/base/portallocator.h"
namespace buzz {
class QName;
@@ -46,13 +45,14 @@
namespace cricket {
class Session;
+class BaseSession;
class SessionClient;
// SessionManager manages session instances
class SessionManager : public sigslot::has_slots<> {
public:
- SessionManager(PortAllocator *allocator,
+ SessionManager(PortAllocator *allocator,
talk_base::Thread *worker_thread = NULL);
virtual ~SessionManager();
@@ -67,20 +67,20 @@
// describing a session of the given type, we will automatically create a
// Session object and notify this client. The client may then accept or
// reject the session.
- void AddClient(const std::string& session_type, SessionClient* client);
- void RemoveClient(const std::string& session_type);
- SessionClient* GetClient(const std::string& session_type);
+ void AddClient(const std::string& content_type, SessionClient* client);
+ void RemoveClient(const std::string& content_type);
+ SessionClient* GetClient(const std::string& content_type);
// Creates a new session. The given name is the JID of the client on whose
// behalf we initiate the session.
- Session *CreateSession(const std::string& name,
- const std::string& session_type);
+ Session *CreateSession(const std::string& local_name,
+ const std::string& content_type);
// Destroys the given session.
void DestroySession(Session *session);
// Returns the session with the given ID or NULL if none exists.
- Session *GetSession(const SessionID& id);
+ Session *GetSession(const std::string& sid);
// Terminates all of the sessions created by this manager.
void TerminateAll();
@@ -92,12 +92,13 @@
// Determines whether the given stanza is intended for some session.
bool IsSessionMessage(const buzz::XmlElement* stanza);
- // Given a stanza, this find the Session associated with that stanza
- Session* FindSessionForStanza(const buzz::XmlElement* stanza, bool incoming);
+ // Given a sid, initiator, and remote_name, this finds the matching Session
+ Session* FindSession(const std::string& sid,
+ const std::string& remote_name);
// Called when we receive a stanza for which IsSessionMessage is true.
void OnIncomingMessage(const buzz::XmlElement* stanza);
-
+
// Called when we get a response to a message that we sent.
void OnIncomingResponse(const buzz::XmlElement* orig_stanza,
const buzz::XmlElement* response_stanza);
@@ -108,7 +109,9 @@
const buzz::XmlElement* error_stanza);
// Signalled each time a session generates a signaling message to send.
- sigslot::signal1<const buzz::XmlElement*> SignalOutgoingMessage;
+ // Also signalled on errors, but with a NULL session.
+ sigslot::signal2<SessionManager*,
+ const buzz::XmlElement*> SignalOutgoingMessage;
// Signaled before sessions try to send certain signaling messages. The
// client should call OnSignalingReady once it is safe to send them. These
@@ -122,7 +125,7 @@
void OnSignalingReady();
private:
- typedef std::map<SessionID, Session *> SessionMap;
+ typedef std::map<std::string, Session*> SessionMap;
typedef std::map<std::string, SessionClient*> ClientMap;
PortAllocator *allocator_;
@@ -134,9 +137,10 @@
// Helper function for CreateSession. This is also invoked when we receive
// a message attempting to initiate a session with this client.
- Session *CreateSession(const std::string& name,
- const SessionID& id,
- const std::string& session_type,
+ Session *CreateSession(const std::string& local_name,
+ const std::string& initiator,
+ const std::string& sid,
+ const std::string& content_type,
bool received_initiate);
// Attempts to find a registered session type whose description appears as
@@ -156,7 +160,7 @@
// Creates and returns an error message from the given components. The
// caller is responsible for deleting this.
- buzz::XmlElement* SessionManager::CreateErrorMessage(
+ buzz::XmlElement* CreateErrorMessage(
const buzz::XmlElement* stanza,
const buzz::QName& name,
const std::string& type,
@@ -170,12 +174,14 @@
void OnOutgoingMessage(Session* session, const buzz::XmlElement* stanza);
// Called each time a session has an error to send.
- void OnErrorMessage(Session* session, const buzz::XmlElement* stanza,
- const buzz::QName& name, const std::string& type,
+ void OnErrorMessage(BaseSession* session,
+ const buzz::XmlElement* stanza,
+ const buzz::QName& name,
+ const std::string& type,
const std::string& text,
const buzz::XmlElement* extra_info);
};
-} // namespace cricket
+} // namespace cricket
-#endif // _SESSIONMANAGER_H_
+#endif // TALK_P2P_BASE_SESSIONMANAGER_H_
diff --git a/talk/p2p/base/sessionmessages.cc b/talk/p2p/base/sessionmessages.cc
new file mode 100644
index 0000000..f7c424e
--- /dev/null
+++ b/talk/p2p/base/sessionmessages.cc
@@ -0,0 +1,821 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/p2p/base/sessionmessages.h"
+
+#include "talk/base/logging.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/xmpp/constants.h"
+#include "talk/p2p/base/constants.h"
+#include "talk/p2p/base/p2ptransport.h"
+#include "talk/p2p/base/parsing.h"
+#include "talk/p2p/base/sessionclient.h"
+#include "talk/p2p/base/sessiondescription.h"
+#include "talk/p2p/base/transport.h"
+
+namespace cricket {
+
+ActionType ToActionType(const std::string& type) {
+ if (type == GINGLE_ACTION_INITIATE)
+ return ACTION_SESSION_INITIATE;
+ if (type == GINGLE_ACTION_INFO)
+ return ACTION_SESSION_INFO;
+ if (type == GINGLE_ACTION_ACCEPT)
+ return ACTION_SESSION_ACCEPT;
+ if (type == GINGLE_ACTION_REJECT)
+ return ACTION_SESSION_REJECT;
+ if (type == GINGLE_ACTION_TERMINATE)
+ return ACTION_SESSION_TERMINATE;
+ if (type == GINGLE_ACTION_CANDIDATES)
+ return ACTION_TRANSPORT_INFO;
+ if (type == JINGLE_ACTION_SESSION_INITIATE)
+ return ACTION_SESSION_INITIATE;
+ if (type == JINGLE_ACTION_TRANSPORT_INFO)
+ return ACTION_TRANSPORT_INFO;
+ if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
+ return ACTION_TRANSPORT_ACCEPT;
+ if (type == JINGLE_ACTION_SESSION_INFO)
+ return ACTION_SESSION_INFO;
+ if (type == JINGLE_ACTION_SESSION_ACCEPT)
+ return ACTION_SESSION_ACCEPT;
+ if (type == JINGLE_ACTION_SESSION_TERMINATE)
+ return ACTION_SESSION_TERMINATE;
+ if (type == JINGLE_ACTION_TRANSPORT_INFO)
+ return ACTION_TRANSPORT_INFO;
+ if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
+ return ACTION_TRANSPORT_ACCEPT;
+
+ return ACTION_UNKNOWN;
+}
+
+std::string ToJingleString(ActionType type) {
+ switch (type) {
+ case ACTION_SESSION_INITIATE:
+ return JINGLE_ACTION_SESSION_INITIATE;
+ case ACTION_SESSION_INFO:
+ return JINGLE_ACTION_SESSION_INFO;
+ case ACTION_SESSION_ACCEPT:
+ return JINGLE_ACTION_SESSION_ACCEPT;
+ // Notice that reject and terminate both go to
+ // "session-terminate", but there is no "session-reject".
+ case ACTION_SESSION_REJECT:
+ case ACTION_SESSION_TERMINATE:
+ return JINGLE_ACTION_SESSION_TERMINATE;
+ case ACTION_TRANSPORT_INFO:
+ return JINGLE_ACTION_TRANSPORT_INFO;
+ case ACTION_TRANSPORT_ACCEPT:
+ return JINGLE_ACTION_TRANSPORT_ACCEPT;
+ default:
+ return "";
+ }
+}
+
+std::string ToGingleString(ActionType type) {
+ switch (type) {
+ case ACTION_SESSION_INITIATE:
+ return GINGLE_ACTION_INITIATE;
+ case ACTION_SESSION_INFO:
+ return GINGLE_ACTION_INFO;
+ case ACTION_SESSION_ACCEPT:
+ return GINGLE_ACTION_ACCEPT;
+ case ACTION_SESSION_REJECT:
+ return GINGLE_ACTION_REJECT;
+ case ACTION_SESSION_TERMINATE:
+ return GINGLE_ACTION_TERMINATE;
+ case ACTION_TRANSPORT_INFO:
+ return GINGLE_ACTION_CANDIDATES;
+ default:
+ return "";
+ }
+}
+
+
+bool IsJingleMessage(const buzz::XmlElement* stanza) {
+ const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
+ if (jingle == NULL)
+ return false;
+
+ return (jingle->HasAttr(buzz::QN_ACTION) &&
+ jingle->HasAttr(buzz::QN_ID));
+}
+
+bool IsGingleMessage(const buzz::XmlElement* stanza) {
+ const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
+ if (session == NULL)
+ return false;
+
+ return (session->HasAttr(buzz::QN_TYPE) &&
+ session->HasAttr(buzz::QN_ID) &&
+ session->HasAttr(QN_INITIATOR));
+}
+
+bool IsSessionMessage(const buzz::XmlElement* stanza) {
+ return (stanza->Name() == buzz::QN_IQ &&
+ stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET &&
+ (IsJingleMessage(stanza) ||
+ IsGingleMessage(stanza)));
+}
+
+bool ParseGingleSessionMessage(const buzz::XmlElement* session,
+ SessionMessage* msg,
+ ParseError* error) {
+ msg->protocol = PROTOCOL_GINGLE;
+ std::string type_string = session->Attr(buzz::QN_TYPE);
+ msg->type = ToActionType(type_string);
+ msg->sid = session->Attr(buzz::QN_ID);
+ msg->initiator = session->Attr(QN_INITIATOR);
+ msg->action_elem = session;
+
+ if (msg->type == ACTION_UNKNOWN)
+ return BadParse("unknown action: " + type_string, error);
+
+ return true;
+}
+
+bool ParseJingleSessionMessage(const buzz::XmlElement* jingle,
+ SessionMessage* msg,
+ ParseError* error) {
+ msg->protocol = PROTOCOL_JINGLE;
+ std::string type_string = jingle->Attr(buzz::QN_ACTION);
+ msg->type = ToActionType(type_string);
+ msg->sid = jingle->Attr(buzz::QN_ID);
+ msg->initiator = GetXmlAttr(jingle, QN_INITIATOR, "");
+ msg->action_elem = jingle;
+
+ if (msg->type == ACTION_UNKNOWN)
+ return BadParse("unknown action: " + type_string, error);
+
+ return true;
+}
+
+bool ParseHybridSessionMessage(const buzz::XmlElement* jingle,
+ SessionMessage* msg,
+ ParseError* error) {
+ if (!ParseJingleSessionMessage(jingle, msg, error))
+ return false;
+ msg->protocol = PROTOCOL_HYBRID;
+
+ return true;
+}
+
+bool ParseSessionMessage(const buzz::XmlElement* stanza,
+ SessionMessage* msg,
+ ParseError* error) {
+ msg->id = stanza->Attr(buzz::QN_ID);
+ msg->from = stanza->Attr(buzz::QN_FROM);
+ msg->to = stanza->Attr(buzz::QN_TO);
+ msg->stanza = stanza;
+
+ const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
+ const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
+ if (jingle && session)
+ return ParseHybridSessionMessage(jingle, msg, error);
+ if (jingle != NULL)
+ return ParseJingleSessionMessage(jingle, msg, error);
+ if (session != NULL)
+ return ParseGingleSessionMessage(session, msg, error);
+ return false;
+}
+
+buzz::XmlElement* WriteGingleAction(const SessionMessage& msg,
+ const XmlElements& action_elems) {
+ buzz::XmlElement* session = new buzz::XmlElement(QN_GINGLE_SESSION, true);
+ session->AddAttr(buzz::QN_TYPE, ToGingleString(msg.type));
+ session->AddAttr(buzz::QN_ID, msg.sid);
+ session->AddAttr(QN_INITIATOR, msg.initiator);
+ AddXmlChildren(session, action_elems);
+ return session;
+}
+
+buzz::XmlElement* WriteJingleAction(const SessionMessage& msg,
+ const XmlElements& action_elems) {
+ buzz::XmlElement* jingle = new buzz::XmlElement(QN_JINGLE, true);
+ jingle->AddAttr(buzz::QN_ACTION, ToJingleString(msg.type));
+ jingle->AddAttr(buzz::QN_ID, msg.sid);
+ // TODO: Right now, the XMPP server rejects a jingle-only
+ // (non hybrid) message with "feature-not-implemented" if there is
+ // no initiator. Fix the server, and then only set the initiator on
+ // session-initiate messages here.
+ jingle->AddAttr(QN_INITIATOR, msg.initiator);
+ AddXmlChildren(jingle, action_elems);
+ return jingle;
+}
+
+void WriteSessionMessage(const SessionMessage& msg,
+ const XmlElements& action_elems,
+ buzz::XmlElement* stanza) {
+ stanza->SetAttr(buzz::QN_TO, msg.to);
+ stanza->SetAttr(buzz::QN_TYPE, buzz::STR_SET);
+
+ if (msg.protocol == PROTOCOL_GINGLE) {
+ stanza->AddElement(WriteGingleAction(msg, action_elems));
+ } else {
+ stanza->AddElement(WriteJingleAction(msg, action_elems));
+ }
+}
+
+
+TransportParser* GetTransportParser(const TransportParserMap& trans_parsers,
+ const std::string& name) {
+ TransportParserMap::const_iterator map = trans_parsers.find(name);
+ if (map == trans_parsers.end()) {
+ return NULL;
+ } else {
+ return map->second;
+ }
+}
+
+bool ParseCandidates(SignalingProtocol protocol,
+ const buzz::XmlElement* candidates_elem,
+ const TransportParserMap& trans_parsers,
+ const std::string& transport_type,
+ Candidates* candidates,
+ ParseError* error) {
+ TransportParser* trans_parser =
+ GetTransportParser(trans_parsers, transport_type);
+ if (trans_parser == NULL)
+ return BadParse("unknown transport type: " + transport_type, error);
+
+ return trans_parser->ParseCandidates(protocol, candidates_elem,
+ candidates, error);
+}
+
+bool ParseGingleTransportInfos(const buzz::XmlElement* action_elem,
+ const ContentInfos& contents,
+ const TransportParserMap& trans_parsers,
+ TransportInfos* tinfos,
+ ParseError* error) {
+ TransportInfo tinfo(CN_OTHER, NS_GINGLE_P2P, Candidates());
+ if (!ParseCandidates(PROTOCOL_GINGLE, action_elem,
+ trans_parsers, NS_GINGLE_P2P,
+ &tinfo.candidates, error))
+ return false;
+
+ bool has_audio = FindContentInfoByName(contents, CN_AUDIO) != NULL;
+ bool has_video = FindContentInfoByName(contents, CN_VIDEO) != NULL;
+
+ // If we don't have media, no need to separate the candidates.
+ if (!has_audio && !has_audio) {
+ tinfos->push_back(tinfo);
+ return true;
+ }
+
+ // If we have media, separate the candidates. Create the
+ // TransportInfo here to avoid copying the candidates.
+ TransportInfo audio_tinfo(CN_AUDIO, NS_GINGLE_P2P, Candidates());
+ TransportInfo video_tinfo(CN_VIDEO, NS_GINGLE_P2P, Candidates());
+ for (Candidates::iterator cand = tinfo.candidates.begin();
+ cand != tinfo.candidates.end(); cand++) {
+ if (cand->name() == GINGLE_CANDIDATE_NAME_RTP ||
+ cand->name() == GINGLE_CANDIDATE_NAME_RTCP) {
+ audio_tinfo.candidates.push_back(*cand);
+ } else if (cand->name() == GINGLE_CANDIDATE_NAME_VIDEO_RTP ||
+ cand->name() == GINGLE_CANDIDATE_NAME_VIDEO_RTCP) {
+ video_tinfo.candidates.push_back(*cand);
+ }
+ }
+
+ if (has_audio) {
+ tinfos->push_back(audio_tinfo);
+ }
+
+ if (has_video) {
+ tinfos->push_back(video_tinfo);
+ }
+
+ return true;
+}
+
+bool ParseJingleTransportInfo(const buzz::XmlElement* trans_elem,
+ const ContentInfo& content,
+ const TransportParserMap& trans_parsers,
+ TransportInfos* tinfos,
+ ParseError* error) {
+ std::string transport_type = trans_elem->Name().Namespace();
+ TransportInfo tinfo(content.name, transport_type, Candidates());
+ if (!ParseCandidates(PROTOCOL_JINGLE, trans_elem,
+ trans_parsers, transport_type,
+ &tinfo.candidates, error))
+ return false;
+
+ tinfos->push_back(tinfo);
+ return true;
+}
+
+bool ParseJingleTransportInfos(const buzz::XmlElement* jingle,
+ const ContentInfos& contents,
+ const TransportParserMap trans_parsers,
+ TransportInfos* tinfos,
+ ParseError* error) {
+ for (const buzz::XmlElement* pair_elem
+ = jingle->FirstNamed(QN_JINGLE_CONTENT);
+ pair_elem != NULL;
+ pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
+ std::string content_name;
+ if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
+ &content_name, error))
+ return false;
+
+ const ContentInfo* content = FindContentInfoByName(contents, content_name);
+ if (!content)
+ return BadParse("Unknown content name: " + content_name, error);
+
+ const buzz::XmlElement* trans_elem;
+ if (!RequireXmlChild(pair_elem, LN_TRANSPORT, &trans_elem, error))
+ return false;
+
+ if (!ParseJingleTransportInfo(trans_elem, *content, trans_parsers,
+ tinfos, error))
+ return false;
+ }
+
+ return true;
+}
+
+buzz::XmlElement* NewTransportElement(const std::string& name) {
+ return new buzz::XmlElement(buzz::QName(true, name, LN_TRANSPORT), true);
+}
+
+bool WriteCandidates(SignalingProtocol protocol,
+ const std::string& trans_type,
+ const Candidates& candidates,
+ const TransportParserMap& trans_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ TransportParser* trans_parser = GetTransportParser(trans_parsers, trans_type);
+ if (trans_parser == NULL)
+ return BadWrite("unknown transport type: " + trans_type, error);
+
+ return trans_parser->WriteCandidates(protocol, candidates, elems, error);
+}
+
+bool WriteGingleTransportInfos(const TransportInfos& tinfos,
+ const TransportParserMap& trans_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ for (TransportInfos::const_iterator tinfo = tinfos.begin();
+ tinfo != tinfos.end(); ++tinfo) {
+ if (!WriteCandidates(PROTOCOL_GINGLE,
+ tinfo->transport_type, tinfo->candidates,
+ trans_parsers, elems, error))
+ return false;
+ }
+
+ return true;
+}
+
+bool WriteJingleTransportInfo(const TransportInfo& tinfo,
+ const TransportParserMap& trans_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ XmlElements candidate_elems;
+ if (!WriteCandidates(PROTOCOL_JINGLE,
+ tinfo.transport_type, tinfo.candidates, trans_parsers,
+ &candidate_elems, error))
+ return false;
+
+ buzz::XmlElement* trans_elem = NewTransportElement(tinfo.transport_type);
+ AddXmlChildren(trans_elem, candidate_elems);
+ elems->push_back(trans_elem);
+ return true;
+}
+
+void WriteJingleContentPair(const std::string name,
+ const XmlElements& pair_elems,
+ XmlElements* elems) {
+ buzz::XmlElement* pair_elem = new buzz::XmlElement(QN_JINGLE_CONTENT);
+ pair_elem->SetAttr(QN_JINGLE_CONTENT_NAME, name);
+ pair_elem->SetAttr(QN_CREATOR, LN_INITIATOR);
+ AddXmlChildren(pair_elem, pair_elems);
+
+ elems->push_back(pair_elem);
+}
+
+bool WriteJingleTransportInfos(const TransportInfos& tinfos,
+ const TransportParserMap& trans_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ for (TransportInfos::const_iterator tinfo = tinfos.begin();
+ tinfo != tinfos.end(); ++tinfo) {
+ XmlElements pair_elems;
+ if (!WriteJingleTransportInfo(*tinfo, trans_parsers,
+ &pair_elems, error))
+ return false;
+
+ WriteJingleContentPair(tinfo->content_name, pair_elems, elems);
+ }
+
+ return true;
+}
+
+ContentParser* GetContentParser(const ContentParserMap& content_parsers,
+ const std::string& type) {
+ ContentParserMap::const_iterator map = content_parsers.find(type);
+ if (map == content_parsers.end()) {
+ return NULL;
+ } else {
+ return map->second;
+ }
+}
+
+bool ParseContentInfo(SignalingProtocol protocol,
+ const std::string& name,
+ const std::string& type,
+ const buzz::XmlElement* elem,
+ const ContentParserMap& parsers,
+ ContentInfos* contents,
+ ParseError* error) {
+ ContentParser* parser = GetContentParser(parsers, type);
+ if (parser == NULL)
+ return BadParse("unknown application content: " + type, error);
+
+ const ContentDescription* desc;
+ if (!parser->ParseContent(protocol, elem, &desc, error))
+ return false;
+
+ contents->push_back(ContentInfo(name, type, desc));
+ return true;
+}
+
+bool ParseContentType(const buzz::XmlElement* parent_elem,
+ std::string* content_type,
+ const buzz::XmlElement** content_elem,
+ ParseError* error) {
+ if (!RequireXmlChild(parent_elem, LN_DESCRIPTION, content_elem, error))
+ return false;
+
+ *content_type = (*content_elem)->Name().Namespace();
+ return true;
+}
+
+bool ParseGingleContentInfos(const buzz::XmlElement* session,
+ const ContentParserMap& content_parsers,
+ ContentInfos* contents,
+ ParseError* error) {
+ std::string content_type;
+ const buzz::XmlElement* content_elem;
+ if (!ParseContentType(session, &content_type, &content_elem, error))
+ return false;
+
+ if (content_type == NS_GINGLE_VIDEO) {
+ // A parser parsing audio or video content should look at the
+ // namespace and only parse the codecs relevant to that namespace.
+ // We use this to control which codecs get parsed: first audio,
+ // then video.
+ talk_base::scoped_ptr<buzz::XmlElement> audio_elem(
+ new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT));
+ CopyXmlChildren(content_elem, audio_elem.get());
+ if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
+ audio_elem.get(), content_parsers,
+ contents, error))
+ return false;
+
+ if (!ParseContentInfo(PROTOCOL_GINGLE, CN_VIDEO, NS_JINGLE_RTP,
+ content_elem, content_parsers,
+ contents, error))
+ return false;
+ } else if (content_type == NS_GINGLE_AUDIO) {
+ if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
+ content_elem, content_parsers,
+ contents, error))
+ return false;
+ } else {
+ if (!ParseContentInfo(PROTOCOL_GINGLE, CN_OTHER, content_type,
+ content_elem, content_parsers,
+ contents, error))
+ return false;
+ }
+ return true;
+}
+
+bool ParseJingleContentInfos(const buzz::XmlElement* jingle,
+ const ContentParserMap& content_parsers,
+ ContentInfos* contents,
+ ParseError* error) {
+ for (const buzz::XmlElement* pair_elem
+ = jingle->FirstNamed(QN_JINGLE_CONTENT);
+ pair_elem != NULL;
+ pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
+ std::string content_name;
+ if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
+ &content_name, error))
+ return false;
+
+ std::string content_type;
+ const buzz::XmlElement* content_elem;
+ if (!ParseContentType(pair_elem, &content_type, &content_elem, error))
+ return false;
+
+ if (!ParseContentInfo(PROTOCOL_JINGLE, content_name, content_type,
+ content_elem, content_parsers,
+ contents, error))
+ return false;
+ }
+ return true;
+}
+
+buzz::XmlElement* WriteContentInfo(SignalingProtocol protocol,
+ const ContentInfo& content,
+ const ContentParserMap& parsers,
+ WriteError* error) {
+ ContentParser* parser = GetContentParser(parsers, content.type);
+ if (parser == NULL) {
+ BadWrite("unknown content type: " + content.type, error);
+ return NULL;
+ }
+
+ buzz::XmlElement* elem = NULL;
+ if (!parser->WriteContent(protocol, content.description, &elem, error))
+ return NULL;
+
+ return elem;
+}
+
+bool WriteGingleContentInfos(const ContentInfos& contents,
+ const ContentParserMap& parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ if (contents.size() == 1) {
+ buzz::XmlElement* elem = WriteContentInfo(
+ PROTOCOL_GINGLE, contents.front(), parsers, error);
+ if (!elem)
+ return false;
+
+ elems->push_back(elem);
+ } else if (contents.size() == 2 &&
+ contents.at(0).type == NS_JINGLE_RTP &&
+ contents.at(1).type == NS_JINGLE_RTP) {
+ // Special-case audio + video contents so that they are "merged"
+ // into one "video" content.
+ buzz::XmlElement* audio = WriteContentInfo(
+ PROTOCOL_GINGLE, contents.at(0), parsers, error);
+ if (!audio)
+ return false;
+
+ buzz::XmlElement* video = WriteContentInfo(
+ PROTOCOL_GINGLE, contents.at(1), parsers, error);
+ if (!video) {
+ delete audio;
+ return false;
+ }
+
+ CopyXmlChildren(audio, video);
+ elems->push_back(video);
+ delete audio;
+ } else {
+ return BadWrite("Gingle protocol may only have one content.", error);
+ }
+
+ return true;
+}
+
+const TransportInfo* GetTransportInfoByContentName(
+ const TransportInfos& tinfos, const std::string& content_name) {
+ for (TransportInfos::const_iterator tinfo = tinfos.begin();
+ tinfo != tinfos.end(); ++tinfo) {
+ if (content_name == tinfo->content_name) {
+ return &*tinfo;
+ }
+ }
+ return NULL;
+}
+
+bool WriteJingleContentPairs(const ContentInfos& contents,
+ const ContentParserMap& content_parsers,
+ const TransportInfos& tinfos,
+ const TransportParserMap& trans_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ for (ContentInfos::const_iterator content = contents.begin();
+ content != contents.end(); ++content) {
+ const TransportInfo* tinfo =
+ GetTransportInfoByContentName(tinfos, content->name);
+ if (!tinfo)
+ return BadWrite("No transport for content: " + content->name, error);
+
+ XmlElements pair_elems;
+ buzz::XmlElement* elem = WriteContentInfo(
+ PROTOCOL_JINGLE, *content, content_parsers, error);
+ if (!elem)
+ return false;
+ pair_elems.push_back(elem);
+
+ if (!WriteJingleTransportInfo(*tinfo, trans_parsers,
+ &pair_elems, error))
+ return false;
+
+ WriteJingleContentPair(content->name, pair_elems, elems);
+ }
+ return true;
+}
+
+bool ParseContentType(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ std::string* content_type,
+ ParseError* error) {
+ const buzz::XmlElement* content_elem;
+ if (protocol == PROTOCOL_GINGLE) {
+ if (!ParseContentType(action_elem, content_type, &content_elem, error))
+ return false;
+
+ // Internally, we only use NS_JINGLE_RTP.
+ if (*content_type == NS_GINGLE_AUDIO ||
+ *content_type == NS_GINGLE_VIDEO)
+ *content_type = NS_JINGLE_RTP;
+ } else {
+ const buzz::XmlElement* pair_elem
+ = action_elem->FirstNamed(QN_JINGLE_CONTENT);
+ if (pair_elem == NULL)
+ return BadParse("No contents found", error);
+
+ if (!ParseContentType(pair_elem, content_type, &content_elem, error))
+ return false;
+
+ // If there is more than one content type, return an error.
+ for (; pair_elem != NULL;
+ pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
+ std::string content_type2;
+ if (!ParseContentType(pair_elem, &content_type2, &content_elem, error))
+ return false;
+
+ if (content_type2 != *content_type)
+ return BadParse("More than one content type found", error);
+ }
+ }
+
+ return true;
+}
+
+bool ParseSessionInitiate(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& trans_parsers,
+ SessionInitiate* init,
+ ParseError* error) {
+ init->owns_contents = true;
+ if (protocol == PROTOCOL_GINGLE) {
+ if (!ParseGingleContentInfos(action_elem, content_parsers,
+ &init->contents, error))
+ return false;
+
+ if (!ParseGingleTransportInfos(action_elem, init->contents, trans_parsers,
+ &init->transports, error))
+ return false;
+ } else {
+ if (!ParseJingleContentInfos(action_elem, content_parsers,
+ &init->contents, error))
+ return false;
+
+ if (!ParseJingleTransportInfos(action_elem, init->contents, trans_parsers,
+ &init->transports, error))
+ return false;
+ }
+
+ return true;
+}
+
+
+bool WriteSessionInitiate(SignalingProtocol protocol,
+ const ContentInfos& contents,
+ const TransportInfos& tinfos,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& transport_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ if (protocol == PROTOCOL_GINGLE) {
+ if (!WriteGingleContentInfos(contents, content_parsers, elems, error))
+ return false;
+
+ if (!WriteGingleTransportInfos(tinfos, transport_parsers,
+ elems, error))
+ return false;
+ } else {
+ if (!WriteJingleContentPairs(contents, content_parsers,
+ tinfos, transport_parsers,
+ elems, error))
+ return false;
+ }
+
+ return true;
+}
+
+bool ParseSessionAccept(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& transport_parsers,
+ SessionAccept* accept,
+ ParseError* error) {
+ return ParseSessionInitiate(protocol, action_elem,
+ content_parsers, transport_parsers,
+ accept, error);
+}
+
+bool WriteSessionAccept(SignalingProtocol protocol,
+ const ContentInfos& contents,
+ const TransportInfos& tinfos,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& transport_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ return WriteSessionInitiate(protocol, contents, tinfos,
+ content_parsers, transport_parsers,
+ elems, error);
+}
+
+bool ParseSessionTerminate(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ SessionTerminate* term,
+ ParseError* error) {
+ if (protocol == PROTOCOL_GINGLE) {
+ const buzz::XmlElement* reason_elem = action_elem->FirstElement();
+ if (reason_elem != NULL) {
+ term->reason = reason_elem->Name().LocalPart();
+ const buzz::XmlElement *debug_elem = reason_elem->FirstElement();
+ if (debug_elem != NULL) {
+ term->debug_reason = debug_elem->Name().LocalPart();
+ }
+ }
+ return true;
+ } else {
+ const buzz::XmlElement* reason_elem =
+ action_elem->FirstNamed(QN_JINGLE_REASON);
+ if (reason_elem) {
+ reason_elem = reason_elem->FirstElement();
+ if (reason_elem) {
+ term->reason = reason_elem->Name().LocalPart();
+ }
+ }
+ return true;
+ }
+}
+
+void WriteSessionTerminate(SignalingProtocol protocol,
+ const SessionTerminate& term,
+ XmlElements* elems) {
+ if (protocol == PROTOCOL_GINGLE) {
+ elems->push_back(new buzz::XmlElement(
+ buzz::QName(true, NS_GINGLE, term.reason)));
+ } else {
+ if (!term.reason.empty()) {
+ buzz::XmlElement* reason_elem = new buzz::XmlElement(QN_JINGLE_REASON);
+ reason_elem->AddElement(new buzz::XmlElement(
+ buzz::QName(true, NS_JINGLE, term.reason)));
+ elems->push_back(reason_elem);
+ }
+ }
+}
+
+bool ParseTransportInfos(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ const ContentInfos& contents,
+ const TransportParserMap& trans_parsers,
+ TransportInfos* tinfos,
+ ParseError* error) {
+ if (protocol == PROTOCOL_GINGLE) {
+ return ParseGingleTransportInfos(
+ action_elem, contents, trans_parsers, tinfos, error);
+ } else {
+ return ParseJingleTransportInfos(
+ action_elem, contents, trans_parsers, tinfos, error);
+ }
+}
+
+bool WriteTransportInfos(SignalingProtocol protocol,
+ const TransportInfos& tinfos,
+ const TransportParserMap& trans_parsers,
+ XmlElements* elems,
+ WriteError* error) {
+ if (protocol == PROTOCOL_GINGLE) {
+ return WriteGingleTransportInfos(tinfos, trans_parsers,
+ elems, error);
+ } else {
+ return WriteJingleTransportInfos(tinfos, trans_parsers,
+ elems, error);
+ }
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/sessionmessages.h b/talk/p2p/base/sessionmessages.h
new file mode 100644
index 0000000..ff8641c
--- /dev/null
+++ b/talk/p2p/base/sessionmessages.h
@@ -0,0 +1,213 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_P2P_BASE_SESSIONMESSAGES_H_
+#define TALK_P2P_BASE_SESSIONMESSAGES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "talk/xmllite/xmlelement.h"
+#include "talk/p2p/base/constants.h"
+#include "talk/p2p/base/sessiondescription.h" // Needed to delete contents.
+
+namespace cricket {
+
+struct ParseError;
+struct WriteError;
+class Candidate;
+class ContentParser;
+class TransportParser;
+
+typedef std::vector<buzz::XmlElement*> XmlElements;
+typedef std::vector<Candidate> Candidates;
+typedef std::map<std::string, ContentParser*> ContentParserMap;
+typedef std::map<std::string, TransportParser*> TransportParserMap;
+
+enum ActionType {
+ ACTION_UNKNOWN,
+
+ ACTION_SESSION_INITIATE,
+ ACTION_SESSION_INFO,
+ ACTION_SESSION_ACCEPT,
+ ACTION_SESSION_REJECT,
+ ACTION_SESSION_TERMINATE,
+
+ ACTION_TRANSPORT_INFO,
+ ACTION_TRANSPORT_ACCEPT,
+};
+
+// Abstraction of a <jingle> element within an <iq> stanza, per XMPP
+// standard XEP-166. Can be serialized into multiple protocols,
+// including the standard (Jingle) and the draft standard (Gingle).
+// In general, used to communicate actions related to a p2p session,
+// such accept, initiate, terminate, etc.
+
+struct SessionMessage {
+ SessionMessage() : action_elem(NULL), stanza(NULL) {}
+
+ SessionMessage(SignalingProtocol protocol, ActionType type,
+ const std::string& sid, const std::string& initiator) :
+ protocol(protocol), type(type), sid(sid), initiator(initiator),
+ action_elem(NULL), stanza(NULL) {}
+
+ std::string id;
+ std::string from;
+ std::string to;
+ SignalingProtocol protocol;
+ ActionType type;
+ std::string sid; // session id
+ std::string initiator;
+
+ // Used for further parsing when necessary.
+ // Represents <session> or <jingle>.
+ const buzz::XmlElement* action_elem;
+ // Mostly used for debugging.
+ const buzz::XmlElement* stanza;
+};
+
+// A TransportInfo is NOT a transport-info message. It is comparable
+// to a "ContentInfo". A transport-info message is basically just a
+// collection of TransportInfos.
+struct TransportInfo {
+ TransportInfo() {}
+
+ TransportInfo(const std::string& content_name,
+ const std::string& transport_type,
+ const Candidates& candidates)
+ : content_name(content_name),
+ transport_type(transport_type),
+ candidates(candidates) {}
+
+ std::string content_name;
+ std::string transport_type; // xmlns of <transport>
+ Candidates candidates;
+};
+
+typedef std::vector<TransportInfo> TransportInfos;
+
+struct SessionInitiate {
+ SessionInitiate() : owns_contents(false) {}
+
+ ~SessionInitiate() {
+ if (owns_contents) {
+ for (ContentInfos::iterator content = contents.begin();
+ content != contents.end(); content++) {
+ delete content->description;
+ }
+ }
+ }
+
+ // Caller takes ownership of contents.
+ ContentInfos ClearContents() {
+ ContentInfos out;
+ contents.swap(out);
+ owns_contents = false;
+ return out;
+ }
+
+ bool owns_contents;
+ ContentInfos contents;
+ TransportInfos transports;
+};
+
+// Right now, a SessionAccept is functionally equivalent to a SessionInitiate.
+typedef SessionInitiate SessionAccept;
+
+struct SessionTerminate {
+ SessionTerminate() {}
+
+ explicit SessionTerminate(const std::string& reason) :
+ reason(reason) {}
+
+ std::string reason;
+ std::string debug_reason;
+};
+
+bool IsSessionMessage(const buzz::XmlElement* stanza);
+bool ParseSessionMessage(const buzz::XmlElement* stanza,
+ SessionMessage* msg,
+ ParseError* error);
+// Will return an error if there is more than one content type.
+bool ParseContentType(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ std::string* content_type,
+ ParseError* error);
+void WriteSessionMessage(const SessionMessage& msg,
+ const XmlElements& action_elems,
+ buzz::XmlElement* stanza);
+bool ParseSessionInitiate(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& transport_parsers,
+ SessionInitiate* init,
+ ParseError* error);
+bool WriteSessionInitiate(SignalingProtocol protocol,
+ const ContentInfos& contents,
+ const TransportInfos& tinfos,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& transport_parsers,
+ XmlElements* elems,
+ WriteError* error);
+bool ParseSessionAccept(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& transport_parsers,
+ SessionAccept* accept,
+ ParseError* error);
+bool WriteSessionAccept(SignalingProtocol protocol,
+ const ContentInfos& contents,
+ const TransportInfos& tinfos,
+ const ContentParserMap& content_parsers,
+ const TransportParserMap& transport_parsers,
+ XmlElements* elems,
+ WriteError* error);
+bool ParseSessionTerminate(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ SessionTerminate* term,
+ ParseError* error);
+void WriteSessionTerminate(SignalingProtocol protocol,
+ const SessionTerminate& term,
+ XmlElements* elems);
+// Since a TransportInfo is not a transport-info message, and a
+// transport-info message is just a collection of TransportInfos, we
+// say Parse/Write TransportInfos for transport-info messages.
+bool ParseTransportInfos(SignalingProtocol protocol,
+ const buzz::XmlElement* action_elem,
+ const ContentInfos& contents,
+ const TransportParserMap& trans_parsers,
+ TransportInfos* tinfos,
+ ParseError* error);
+bool WriteTransportInfos(SignalingProtocol protocol,
+ const TransportInfos& tinfos,
+ const TransportParserMap& trans_parsers,
+ XmlElements* elems,
+ WriteError* error);
+} // namespace cricket
+
+#endif // TALK_P2P_BASE_SESSIONMESSAGES_H_
diff --git a/talk/p2p/base/stun.cc b/talk/p2p/base/stun.cc
old mode 100755
new mode 100644
index c4a89e8..ad8b5ce
--- a/talk/p2p/base/stun.cc
+++ b/talk/p2p/base/stun.cc
@@ -2,39 +2,35 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/logging.h"
#include "talk/p2p/base/stun.h"
-#include <iostream>
-#include <cassert>
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::memcpy;
-}
-#endif
+#include <cstring>
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
using talk_base::ByteBuffer;
@@ -52,7 +48,7 @@
StunMessage::StunMessage() : type_(0), length_(0),
transaction_id_("0000000000000000") {
- assert(transaction_id_.size() == 16);
+ ASSERT(transaction_id_.size() == 16);
attrs_ = new std::vector<StunAttribute*>();
}
@@ -63,7 +59,7 @@
}
void StunMessage::SetTransactionID(const std::string& str) {
- assert(str.size() == 16);
+ ASSERT(str.size() == 16);
transaction_id_ = str;
}
@@ -86,7 +82,7 @@
return reinterpret_cast<const StunAddressAttribute*>(GetAttribute(type));
default:
- assert(0);
+ ASSERT(0);
return 0;
}
}
@@ -101,7 +97,7 @@
return reinterpret_cast<const StunUInt32Attribute*>(GetAttribute(type));
default:
- assert(0);
+ ASSERT(0);
return 0;
}
}
@@ -117,7 +113,7 @@
return reinterpret_cast<const StunByteStringAttribute*>(GetAttribute(type));
default:
- assert(0);
+ ASSERT(0);
return 0;
}
}
@@ -146,16 +142,22 @@
}
bool StunMessage::Read(ByteBuffer* buf) {
- if (!buf->ReadUInt16(type_))
+ if (!buf->ReadUInt16(&type_))
return false;
- if (!buf->ReadUInt16(length_))
+ if (type_ & 0x8000) {
+ // rtp and rtcp set MSB of first byte, since first two bits are version,
+ // and version is always 2 (10). If set, this is not a stun packet.
+ return false;
+ }
+
+ if (!buf->ReadUInt16(&length_))
return false;
std::string transaction_id;
- if (!buf->ReadString(transaction_id, 16))
+ if (!buf->ReadString(&transaction_id, 16))
return false;
- assert(transaction_id.size() == 16);
+ ASSERT(transaction_id.size() == 16);
transaction_id_ = transaction_id;
if (length_ > buf->Length())
@@ -166,9 +168,9 @@
size_t rest = buf->Length() - length_;
while (buf->Length() > rest) {
uint16 attr_type, attr_length;
- if (!buf->ReadUInt16(attr_type))
+ if (!buf->ReadUInt16(&attr_type))
return false;
- if (!buf->ReadUInt16(attr_length))
+ if (!buf->ReadUInt16(&attr_length))
return false;
StunAttribute* attr = StunAttribute::Create(attr_type, attr_length);
@@ -180,8 +182,8 @@
if (buf->Length() != rest) {
// fixme: shouldn't be doing this
- LOG(LERROR) << "wrong message length"
- << " (" << (int)rest << " != " << (int)buf->Length() << ")";
+ LOG(LERROR) << "wrong message length (" << rest << " != " << buf->Length()
+ << ")";
return false;
}
@@ -247,7 +249,7 @@
case STUN_ATTR_TRANSPORT_PREFERENCES:
if ((length != StunTransportPrefsAttribute::SIZE1) &&
- (length != StunTransportPrefsAttribute::SIZE2))
+ (length != StunTransportPrefsAttribute::SIZE2))
return 0;
return new StunTransportPrefsAttribute(type, length);
@@ -269,7 +271,7 @@
return new StunAddressAttribute(type);
default:
- assert(false);
+ ASSERT(false);
return 0;
}
}
@@ -283,7 +285,7 @@
return new StunUInt32Attribute(type);
default:
- assert(false);
+ ASSERT(false);
return 0;
}
}
@@ -298,7 +300,7 @@
return new StunByteStringAttribute(type, 0);
default:
- assert(false);
+ ASSERT(false);
return 0;
}
}
@@ -323,13 +325,13 @@
bool StunAddressAttribute::Read(ByteBuffer* buf) {
uint8 dummy;
- if (!buf->ReadUInt8(dummy))
+ if (!buf->ReadUInt8(&dummy))
return false;
- if (!buf->ReadUInt8(family_))
+ if (!buf->ReadUInt8(&family_))
return false;
- if (!buf->ReadUInt16(port_))
+ if (!buf->ReadUInt16(&port_))
return false;
- if (!buf->ReadUInt32(ip_))
+ if (!buf->ReadUInt32(&ip_))
return false;
return true;
}
@@ -346,18 +348,18 @@
}
bool StunUInt32Attribute::GetBit(int index) const {
- assert((0 <= index) && (index < 32));
+ ASSERT((0 <= index) && (index < 32));
return static_cast<bool>((bits_ >> index) & 0x1);
}
void StunUInt32Attribute::SetBit(int index, bool value) {
- assert((0 <= index) && (index < 32));
+ ASSERT((0 <= index) && (index < 32));
bits_ &= ~(1 << index);
bits_ |= value ? (1 << index) : 0;
}
bool StunUInt32Attribute::Read(ByteBuffer* buf) {
- if (!buf->ReadUInt32(bits_))
+ if (!buf->ReadUInt32(&bits_))
return false;
return true;
}
@@ -381,7 +383,7 @@
}
void StunByteStringAttribute::CopyBytes(const char* bytes) {
- CopyBytes(bytes, (uint16)strlen(bytes));
+ CopyBytes(bytes, static_cast<uint16>(strlen(bytes)));
}
void StunByteStringAttribute::CopyBytes(const void* bytes, uint16 length) {
@@ -391,14 +393,14 @@
}
uint8 StunByteStringAttribute::GetByte(int index) const {
- assert(bytes_);
- assert((0 <= index) && (index < length()));
+ ASSERT(bytes_ != NULL);
+ ASSERT((0 <= index) && (index < length()));
return static_cast<uint8>(bytes_[index]);
}
void StunByteStringAttribute::SetByte(int index, uint8 value) {
- assert(bytes_);
- assert((0 <= index) && (index < length()));
+ ASSERT(bytes_ != NULL);
+ ASSERT((0 <= index) && (index < length()));
bytes_[index] = value;
}
@@ -426,13 +428,13 @@
}
void StunErrorCodeAttribute::SetReason(const std::string& reason) {
- SetLength(MIN_SIZE + (uint16)reason.size());
+ SetLength(MIN_SIZE + static_cast<uint16>(reason.size()));
reason_ = reason;
}
bool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
uint32 val;
- if (!buf->ReadUInt32(val))
+ if (!buf->ReadUInt32(&val))
return false;
if ((val >> 11) != 0)
@@ -440,7 +442,7 @@
SetErrorCode(val);
- if (!buf->ReadString(reason_, length() - 4))
+ if (!buf->ReadString(&reason_, length() - 4))
return false;
return true;
@@ -474,13 +476,13 @@
void StunUInt16ListAttribute::AddType(uint16 value) {
attr_types_->push_back(value);
- SetLength((uint16)attr_types_->size() * 2);
+ SetLength(static_cast<uint16>(attr_types_->size() * 2));
}
bool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
for (int i = 0; i < length() / 2; i++) {
uint16 attr;
- if (!buf->ReadUInt16(attr))
+ if (!buf->ReadUInt16(&attr))
return false;
attr_types_->push_back(attr);
}
@@ -494,7 +496,7 @@
StunTransportPrefsAttribute::StunTransportPrefsAttribute(
uint16 type, uint16 length)
- : StunAttribute(type, length), preallocate_(false), prefs_(0), addr_(0) {
+ : StunAttribute(type, length), preallocate_(false), prefs_(0), addr_(0) {
}
StunTransportPrefsAttribute::~StunTransportPrefsAttribute() {
@@ -516,7 +518,7 @@
bool StunTransportPrefsAttribute::Read(ByteBuffer* buf) {
uint32 val;
- if (!buf->ReadUInt32(val))
+ if (!buf->ReadUInt32(&val))
return false;
if ((val >> 3) != 0)
diff --git a/talk/p2p/base/stun.h b/talk/p2p/base/stun.h
old mode 100755
new mode 100644
index 4c0459b..2282fed
--- a/talk/p2p/base/stun.h
+++ b/talk/p2p/base/stun.h
@@ -31,11 +31,12 @@
// This file contains classes for dealing with the STUN and TURN protocols.
// Both protocols use the same wire format.
-#include "talk/base/basictypes.h"
-#include "talk/base/bytebuffer.h"
#include <string>
#include <vector>
+#include "talk/base/basictypes.h"
+#include "talk/base/bytebuffer.h"
+
namespace cricket {
// These are the types of STUN & TURN messages as of last check.
diff --git a/talk/p2p/base/stunport.cc b/talk/p2p/base/stunport.cc
old mode 100755
new mode 100644
index 8fa3fd8..7f5dad7
--- a/talk/p2p/base/stunport.cc
+++ b/talk/p2p/base/stunport.cc
@@ -2,62 +2,51 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma warning(disable:4786)
-#endif
-#include <iostream>
-#include <cassert>
+#include "talk/p2p/base/stunport.h"
+
#include "talk/base/common.h"
#include "talk/base/logging.h"
#include "talk/base/helpers.h"
-#include "talk/p2p/base/stunport.h"
-
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::strerror;
-}
-#endif
-
-#ifdef POSIX
-#include <errno.h>
-#endif // POSIX
+#include "talk/base/nethelpers.h"
+#include "talk/p2p/base/common.h"
namespace cricket {
-const int KEEPALIVE_DELAY = 10 * 1000; // 10 seconds - sort timeouts
-const int RETRY_DELAY = 50; // 50ms, from ICE spec
-const uint32 RETRY_TIMEOUT = 50 * 1000; // ICE says 50 secs
+// TODO: Move these to a common place (used in relayport too)
+const int KEEPALIVE_DELAY = 10 * 1000; // 10 seconds - sort timeouts
+const int RETRY_DELAY = 50; // 50ms, from ICE spec
+const int RETRY_TIMEOUT = 50 * 1000; // ICE says 50 secs
// Handles a binding request sent to the STUN server.
class StunPortBindingRequest : public StunRequest {
-public:
+ public:
StunPortBindingRequest(StunPort* port, bool keep_alive,
const talk_base::SocketAddress& addr)
: port_(port), keep_alive_(keep_alive), server_addr_(addr) {
- start_time_ = talk_base::GetMillisecondCount();
+ start_time_ = talk_base::Time();
}
virtual ~StunPortBindingRequest() {
@@ -73,9 +62,9 @@
const StunAddressAttribute* addr_attr =
response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
if (!addr_attr) {
- LOG(LERROR) << "Binding response missing mapped address.";
+ LOG(LS_ERROR) << "Binding response missing mapped address.";
} else if (addr_attr->family() != 1) {
- LOG(LERROR) << "Binding address has bad family";
+ LOG(LS_ERROR) << "Binding address has bad family";
} else {
talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port());
port_->AddAddress(addr, "udp", true);
@@ -93,9 +82,9 @@
virtual void OnErrorResponse(StunMessage* response) {
const StunErrorCodeAttribute* attr = response->GetErrorCode();
if (!attr) {
- LOG(LERROR) << "Bad allocate response error code";
+ LOG(LS_ERROR) << "Bad allocate response error code";
} else {
- LOG(LERROR) << "Binding error response:"
+ LOG(LS_ERROR) << "Binding error response:"
<< " class=" << attr->error_class()
<< " number=" << attr->number()
<< " reason='" << attr->reason() << "'";
@@ -103,8 +92,8 @@
port_->SignalAddressError(port_);
- if (keep_alive_
- && (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)) {
+ if (keep_alive_
+ && (talk_base::TimeSince(start_time_) <= RETRY_TIMEOUT)) {
port_->requests_.SendDelayed(
new StunPortBindingRequest(port_, true, server_addr_),
KEEPALIVE_DELAY);
@@ -112,21 +101,21 @@
}
virtual void OnTimeout() {
- LOG(LERROR) << "Binding request timed out from "
- << port_->GetLocalAddress().ToString()
+ LOG(LS_ERROR) << "Binding request timed out from "
+ << port_->GetLocalAddress().ToString()
<< " (" << port_->network()->name() << ")";
port_->SignalAddressError(port_);
- if (keep_alive_
- && (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)) {
+ if (keep_alive_
+ && (talk_base::TimeSince(start_time_) <= RETRY_TIMEOUT)) {
port_->requests_.SendDelayed(
new StunPortBindingRequest(port_, true, server_addr_),
RETRY_DELAY);
}
}
-private:
+ private:
StunPort* port_;
bool keep_alive_;
talk_base::SocketAddress server_addr_;
@@ -135,42 +124,71 @@
const std::string STUN_PORT_TYPE("stun");
-StunPort::StunPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
+StunPort::StunPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
talk_base::Network* network,
- const talk_base::SocketAddress& local_addr,
const talk_base::SocketAddress& server_addr)
- : UDPPort(thread, STUN_PORT_TYPE, factory, network),
- server_addr_(server_addr), requests_(thread), error_(0) {
-
- socket_ = CreatePacketSocket(PROTO_UDP);
- socket_->SignalReadPacket.connect(this, &StunPort::OnReadPacket);
- if (socket_->Bind(local_addr) < 0)
- PLOG(LERROR, socket_->GetError()) << "bind";
-
+ : Port(thread, STUN_PORT_TYPE, factory, network),
+ server_addr_(server_addr), requests_(thread), socket_(NULL), error_(0),
+ resolver_(NULL) {
requests_.SignalSendPacket.connect(this, &StunPort::OnSendPacket);
}
+bool StunPort::Init(const talk_base::SocketAddress& local_addr) {
+ socket_ = CreatePacketSocket(PROTO_UDP);
+ if (!socket_) {
+ LOG_J(LS_WARNING, this) << "UDP socket creation failed";
+ return false;
+ }
+ if (socket_->Bind(local_addr) < 0) {
+ LOG_J(LS_WARNING, this) << "UDP bind failed with error "
+ << socket_->GetError();
+ return false;
+ }
+ socket_->SignalReadPacket.connect(this, &StunPort::OnReadPacket);
+ return true;
+}
+
StunPort::~StunPort() {
+ if (resolver_) {
+ resolver_->Destroy(false);
+ }
delete socket_;
}
void StunPort::PrepareAddress() {
// We will keep pinging the stun server to make sure our NAT pin-hole stays
// open during the call.
- requests_.Send(new StunPortBindingRequest(this, true, server_addr_));
+ if (server_addr_.IsUnresolved()) {
+ ResolveStunAddress();
+ } else {
+ requests_.Send(new StunPortBindingRequest(this, true, server_addr_));
+ }
}
void StunPort::PrepareSecondaryAddress() {
+ // DNS resolution of the secondary address is not currently supported.
ASSERT(!server_addr2_.IsAny());
requests_.Send(new StunPortBindingRequest(this, false, server_addr2_));
}
-int StunPort::SendTo(
- const void* data, size_t size, const talk_base::SocketAddress& addr,
- bool payload) {
+Connection* StunPort::CreateConnection(const Candidate& address,
+ CandidateOrigin origin) {
+ if (address.protocol() != "udp")
+ return NULL;
+
+ Connection* conn = new ProxyConnection(this, 0, address);
+ AddConnection(conn);
+ return conn;
+}
+
+int StunPort::SendTo(const void* data, size_t size,
+ const talk_base::SocketAddress& addr, bool payload) {
int sent = socket_->SendTo(data, size, addr);
- if (sent < 0)
+ if (sent < 0) {
error_ = socket_->GetError();
+ LOG_J(LS_ERROR, this) << "UDP send of " << size
+ << " bytes failed with error " << error_;
+ }
return sent;
}
@@ -185,20 +203,46 @@
void StunPort::OnReadPacket(
const char* data, size_t size, const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket) {
- assert(socket == socket_);
+ ASSERT(socket == socket_);
// Look for a response to a binding request.
if (requests_.CheckResponse(data, size))
return;
- // Process this data packet in the normal manner.
- UDPPort::OnReadPacket(data, size, remote_addr);
+ if (Connection* conn = GetConnection(remote_addr)) {
+ conn->OnReadPacket(data, size);
+ } else {
+ Port::OnReadPacket(data, size, remote_addr);
+ }
}
+void StunPort::ResolveStunAddress() {
+ if (resolver_)
+ return;
+
+ resolver_ = new talk_base::AsyncResolver();
+ resolver_->SignalWorkDone.connect(this, &StunPort::OnResolveResult);
+ resolver_->set_address(server_addr_);
+ resolver_->Start();
+}
+
+void StunPort::OnResolveResult(talk_base::SignalThread* t) {
+ ASSERT(t == resolver_);
+ if (resolver_->error() != 0) {
+ LOG_J(LS_WARNING, this) << "StunPort: stun host lookup received error "
+ << resolver_->error();
+ SignalAddressError(this);
+ }
+
+ server_addr_ = resolver_->address();
+ PrepareAddress();
+}
+
+// TODO: merge this with SendTo above.
void StunPort::OnSendPacket(const void* data, size_t size, StunRequest* req) {
StunPortBindingRequest* sreq = static_cast<StunPortBindingRequest*>(req);
if (socket_->SendTo(data, size, sreq->server_addr()) < 0)
PLOG(LERROR, socket_->GetError()) << "sendto";
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/stunport.h b/talk/p2p/base/stunport.h
old mode 100755
new mode 100644
index 4b62181..569e229
--- a/talk/p2p/base/stunport.h
+++ b/talk/p2p/base/stunport.h
@@ -2,56 +2,80 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __STUNPORT_H__
-#define __STUNPORT_H__
+#ifndef TALK_P2P_BASE_STUNPORT_H_
+#define TALK_P2P_BASE_STUNPORT_H_
+#include <string>
#include "talk/base/asyncudpsocket.h"
#include "talk/p2p/base/udpport.h"
#include "talk/p2p/base/stunrequest.h"
+namespace talk_base {
+class AsyncResolver;
+class SignalThread;
+}
+
namespace cricket {
extern const std::string STUN_PORT_TYPE;
// Communicates using the address on the outside of a NAT.
-class StunPort : public UDPPort {
-public:
- StunPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
- talk_base::Network* network,
- const talk_base::SocketAddress& local_addr,
+class StunPort : public Port {
+ public:
+ static StunPort* Create(talk_base::Thread* thread,
+ talk_base::SocketFactory* factory,
+ talk_base::Network* network,
+ const talk_base::SocketAddress& local_addr,
+ const talk_base::SocketAddress& server_addr) {
+ StunPort* port = new StunPort(thread, factory, network, server_addr);
+ if (!port->Init(local_addr)) {
+ delete port;
+ port = NULL;
+ }
+ return port;
+ }
+ StunPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network* network,
const talk_base::SocketAddress& server_addr);
+ bool Init(const talk_base::SocketAddress& local_addr);
virtual ~StunPort();
+ talk_base::SocketAddress GetLocalAddress() const {
+ return socket_->GetLocalAddress();
+ }
+
const talk_base::SocketAddress& server_addr() const { return server_addr_; }
- void set_server_addr(const talk_base::SocketAddress& addr)
- { server_addr_ = addr; }
+ void set_server_addr(const talk_base::SocketAddress& addr) {
+ server_addr_ = addr;
+ }
const talk_base::SocketAddress& server_addr2() const { return server_addr2_; }
- void set_server_addr2(const talk_base::SocketAddress& addr)
- { server_addr2_ = addr; }
+ void set_server_addr2(const talk_base::SocketAddress& addr) {
+ server_addr2_ = addr;
+ }
virtual void PrepareAddress();
@@ -59,36 +83,37 @@
// address for this port (which may be the same as the first address).
void PrepareSecondaryAddress();
- talk_base::SocketAddress GetLocalAddress() const {
- if (socket_)
- return socket_->GetLocalAddress();
- return talk_base::SocketAddress();
- }
-
+ virtual Connection* CreateConnection(const Candidate& address,
+ CandidateOrigin origin);
virtual int SetOption(talk_base::Socket::Option opt, int value);
virtual int GetError();
-protected:
- virtual int SendTo(const void* data, size_t size,
+ protected:
+ virtual int SendTo(const void* data, size_t size,
const talk_base::SocketAddress& addr, bool payload);
void OnReadPacket(
- const char* data, size_t size, const talk_base::SocketAddress& remote_addr,
+ const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket);
-private:
- talk_base::AsyncPacketSocket* socket_;
+ private:
+ // DNS resolution of the STUN server.
+ void ResolveStunAddress();
+ void OnResolveResult(talk_base::SignalThread* thread);
+ // Sends STUN requests to the server.
+ void OnSendPacket(const void* data, size_t size, StunRequest* req);
+
talk_base::SocketAddress server_addr_;
talk_base::SocketAddress server_addr2_;
StunRequestManager requests_;
+ talk_base::AsyncPacketSocket* socket_;
int error_;
+ talk_base::AsyncResolver* resolver_;
friend class StunPortBindingRequest;
-
- // Sends STUN requests to the server.
- void OnSendPacket(const void* data, size_t size, StunRequest* req);
};
-} // namespace cricket
+} // namespace cricket
-#endif // __STUNPORT_H__
+#endif // TALK_P2P_BASE_STUNPORT_H_
diff --git a/talk/p2p/base/stunrequest.cc b/talk/p2p/base/stunrequest.cc
old mode 100755
new mode 100644
index 66b8ef6..1ad121e
--- a/talk/p2p/base/stunrequest.cc
+++ b/talk/p2p/base/stunrequest.cc
@@ -2,49 +2,46 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma warning(disable:4786)
-#endif
-#include "talk/base/logging.h"
-#include "talk/base/helpers.h"
#include "talk/p2p/base/stunrequest.h"
-#include <iostream>
-#include <cassert>
+
+#include "talk/base/common.h"
+#include "talk/base/helpers.h"
+#include "talk/base/logging.h"
namespace cricket {
const uint32 MSG_STUN_SEND = 1;
const int MAX_SENDS = 9;
-const int DELAY_UNIT = 100; // 100 milliseconds
+const int DELAY_UNIT = 100; // 100 milliseconds
const int DELAY_MAX_FACTOR = 16;
-StunRequestManager::StunRequestManager(talk_base::Thread* thread)
+StunRequestManager::StunRequestManager(talk_base::Thread* thread)
: thread_(thread) {
- }
+}
StunRequestManager::~StunRequestManager() {
while (requests_.begin() != requests_.end()) {
@@ -60,16 +57,17 @@
void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
request->set_manager(this);
- assert(requests_.find(request->id()) == requests_.end());
+ ASSERT(requests_.find(request->id()) == requests_.end());
+ request->Construct();
requests_[request->id()] = request;
thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL);
}
void StunRequestManager::Remove(StunRequest* request) {
- assert(request->manager() == this);
+ ASSERT(request->manager() == this);
RequestMap::iterator iter = requests_.find(request->id());
if (iter != requests_.end()) {
- assert(iter->second == request);
+ ASSERT(iter->second == request);
requests_.erase(iter);
thread_->Clear(request);
}
@@ -88,6 +86,7 @@
RequestMap::iterator iter = requests_.find(msg->transaction_id());
if (iter == requests_.end())
return false;
+
StunRequest* request = iter->second;
if (msg->type() == GetStunResponseType(request->type())) {
request->OnResponse(msg);
@@ -128,17 +127,19 @@
}
StunRequest::StunRequest()
- : manager_(0), id_(CreateRandomString(16)), msg_(0), count_(0),
- timeout_(false), tstamp_(0) {
+ : count_(0), timeout_(false), manager_(0),
+ id_(talk_base::CreateRandomString(16)), msg_(new StunMessage()),
+ tstamp_(0) {
+ msg_->SetTransactionID(id_);
}
StunRequest::StunRequest(StunMessage* request)
- : manager_(0), id_(request->transaction_id()), msg_(request),
- count_(0), timeout_(false) {
+ : count_(0), timeout_(false), manager_(0),
+ id_(request->transaction_id()), msg_(request) {
}
StunRequest::~StunRequest() {
- assert(manager_ != NULL);
+ ASSERT(manager_ != NULL);
if (manager_) {
manager_->Remove(this);
manager_->thread_->Clear(this);
@@ -146,26 +147,27 @@
delete msg_;
}
-const StunMessageType StunRequest::type() {
- assert(msg_);
+void StunRequest::Construct() {
+ if (msg_->type() == 0) {
+ Prepare(msg_);
+ ASSERT(msg_->transaction_id() == id_);
+ ASSERT(msg_->type() != 0);
+ }
+}
+
+StunMessageType StunRequest::type() {
+ ASSERT(msg_ != NULL);
return msg_->type();
}
void StunRequest::set_manager(StunRequestManager* manager) {
- assert(!manager_);
+ ASSERT(!manager_);
manager_ = manager;
}
void StunRequest::OnMessage(talk_base::Message* pmsg) {
- assert(manager_);
- assert(pmsg->message_id == MSG_STUN_SEND);
-
- if (!msg_) {
- msg_ = new StunMessage();
- msg_->SetTransactionID(id_);
- Prepare(msg_);
- assert(msg_->transaction_id() == id_);
- }
+ ASSERT(manager_ != NULL);
+ ASSERT(pmsg->message_id == MSG_STUN_SEND);
if (timeout_) {
OnTimeout();
@@ -173,7 +175,7 @@
return;
}
- tstamp_ = talk_base::GetMillisecondCount();
+ tstamp_ = talk_base::Time();
talk_base::ByteBuffer buf;
msg_->Write(&buf);
@@ -184,7 +186,7 @@
}
uint32 StunRequest::Elapsed() const {
- return (talk_base::GetMillisecondCount() - tstamp_);
+ return talk_base::TimeSince(tstamp_);
}
int StunRequest::GetNextDelay() {
@@ -195,4 +197,4 @@
return delay;
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/stunrequest.h b/talk/p2p/base/stunrequest.h
old mode 100755
new mode 100644
index b36861c..fea2c99
--- a/talk/p2p/base/stunrequest.h
+++ b/talk/p2p/base/stunrequest.h
@@ -2,31 +2,31 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __STUNREQUESTMANAGER_H__
-#define __STUNREQUESTMANAGER_H__
+#ifndef TALK_P2P_BASE_STUNREQUEST_H_
+#define TALK_P2P_BASE_STUNREQUEST_H_
#include "talk/base/sigslot.h"
#include "talk/base/thread.h"
@@ -81,6 +81,9 @@
StunRequest(StunMessage* request);
virtual ~StunRequest();
+ // Causes our wrapped StunMessage to be Prepared
+ void Construct();
+
// The manager handling this request (if it has been scheduled for sending).
StunRequestManager* manager() { return manager_; }
@@ -88,7 +91,7 @@
const std::string& id() { return id_; }
// Returns the STUN type of the request message.
- const StunMessageType type();
+ StunMessageType type();
// Handles messages for sending and timeout.
void OnMessage(talk_base::Message* pmsg);
@@ -100,8 +103,8 @@
int count_;
bool timeout_;
- // Fills in the actual request to be sent. Note that the transaction ID will
- // already be set and cannot be changed.
+ // Fills in a request object to be sent. Note that request's transaction ID
+ // will already be set and cannot be changed.
virtual void Prepare(StunMessage* request) {}
// Called when the message receives a response or times out.
@@ -121,6 +124,6 @@
friend class StunRequestManager;
};
-} // namespace cricket
+} // namespace cricket
-#endif // __STUNREQUESTMANAGER_H__
+#endif // TALK_P2P_BASE_STUNREQUEST_H_
diff --git a/talk/p2p/base/stunserver.cc b/talk/p2p/base/stunserver.cc
old mode 100755
new mode 100644
index 5fc61ac..1ff02ee
--- a/talk/p2p/base/stunserver.cc
+++ b/talk/p2p/base/stunserver.cc
@@ -2,38 +2,36 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/bytebuffer.h"
-#include "talk/p2p/base/stunserver.h"
-#include <iostream>
-
#ifdef POSIX
-extern "C" {
#include <errno.h>
-}
-#endif // POSIX
+#endif // POSIX
+
+#include "talk/p2p/base/stunserver.h"
+#include "talk/base/bytebuffer.h"
+#include "talk/base/logging.h"
namespace cricket {
@@ -124,13 +122,14 @@
SendErrorResponse(*msg, addr, 600, "Operation Not Supported");
}
-void StunServer::OnSendRequest(StunMessage* msg, const talk_base::SocketAddress& addr) {
+void StunServer::OnSendRequest(StunMessage* msg,
+ const talk_base::SocketAddress& addr) {
SendErrorResponse(*msg, addr, 600, "Operation Not Supported");
}
void StunServer::SendErrorResponse(
- const StunMessage& msg, const talk_base::SocketAddress& addr, int error_code,
- const char* error_desc) {
+ const StunMessage& msg, const talk_base::SocketAddress& addr,
+ int error_code, const char* error_desc) {
StunMessage err_msg;
err_msg.SetType(GetStunErrorResponseType(msg.type()));
@@ -154,7 +153,7 @@
// TODO: Allow response addr attribute if sent from another stun server.
if (socket_->SendTo(buf.Data(), buf.Length(), addr) < 0)
- std::cerr << "sendto: " << std::strerror(errno) << std::endl;
+ LOG_ERR(LS_ERROR) << "sendto";
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/stunserver.h b/talk/p2p/base/stunserver.h
old mode 100755
new mode 100644
index 0e57a18..83ac174
--- a/talk/p2p/base/stunserver.h
+++ b/talk/p2p/base/stunserver.h
@@ -2,33 +2,34 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __STUNSERVER_H__
-#define __STUNSERVER_H__
+#ifndef TALK_P2P_BASE_STUNSERVER_H_
+#define TALK_P2P_BASE_STUNSERVER_H_
#include "talk/base/asyncudpsocket.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/p2p/base/stun.h"
namespace cricket {
@@ -36,38 +37,41 @@
const int STUN_SERVER_PORT = 3478;
class StunServer : public sigslot::has_slots<> {
-public:
+ public:
// Creates a STUN server, which will listen on the given socket.
- StunServer(talk_base::AsyncUDPSocket* socket);
-
- // Removes the STUN server from the socket, but does not delete the socket.
+ explicit StunServer(talk_base::AsyncUDPSocket* socket);
+ // Removes the STUN server from the socket and deletes the socket.
~StunServer();
-protected:
-
+ protected:
// Slot for AsyncSocket.PacketRead:
void OnPacket(
const char* buf, size_t size, const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket);
// Handlers for the different types of STUN/TURN requests:
- void OnBindingRequest(StunMessage* msg, const talk_base::SocketAddress& addr);
- void OnAllocateRequest(StunMessage* msg, const talk_base::SocketAddress& addr);
- void OnSharedSecretRequest(StunMessage* msg, const talk_base::SocketAddress& addr);
- void OnSendRequest(StunMessage* msg, const talk_base::SocketAddress& addr);
+ void OnBindingRequest(StunMessage* msg,
+ const talk_base::SocketAddress& addr);
+ void OnAllocateRequest(StunMessage* msg,
+ const talk_base::SocketAddress& addr);
+ void OnSharedSecretRequest(StunMessage* msg,
+ const talk_base::SocketAddress& addr);
+ void OnSendRequest(StunMessage* msg,
+ const talk_base::SocketAddress& addr);
// Sends an error response to the given message back to the user.
void SendErrorResponse(
- const StunMessage& msg, const talk_base::SocketAddress& addr, int error_code,
- const char* error_desc);
+ const StunMessage& msg, const talk_base::SocketAddress& addr,
+ int error_code, const char* error_desc);
// Sends the given message to the appropriate destination.
- void SendResponse(const StunMessage& msg, const talk_base::SocketAddress& addr);
+ void SendResponse(const StunMessage& msg,
+ const talk_base::SocketAddress& addr);
-private:
- talk_base::AsyncUDPSocket* socket_;
+ private:
+ talk_base::scoped_ptr<talk_base::AsyncUDPSocket> socket_;
};
-} // namespace cricket
+} // namespace cricket
-#endif // __STUNSERVER_H__
+#endif // TALK_P2P_BASE_STUNSERVER_H_
diff --git a/talk/p2p/base/stunserver_main.cc b/talk/p2p/base/stunserver_main.cc
old mode 100755
new mode 100644
index 8aa200e..e4a2df6
--- a/talk/p2p/base/stunserver_main.cc
+++ b/talk/p2p/base/stunserver_main.cc
@@ -2,53 +2,57 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef POSIX
+#include <errno.h>
+#endif // POSIX
+
+#include <iostream>
+
#include "talk/base/host.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/stunserver.h"
-#include <iostream>
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
using namespace cricket;
int main(int argc, char* argv[]) {
- if (argc != 1) {
- std::cerr << "usage: stunserver" << std::endl;
+ if (argc != 2) {
+ std::cerr << "usage: stunserver address" << std::endl;
return 1;
}
- talk_base::SocketAddress server_addr(talk_base::LocalHost().networks()[1]->ip(), 7000);
+ talk_base::SocketAddress server_addr;
+ if (!server_addr.FromString(argv[1])) {
+ std::cerr << "Unable to parse IP address: " << argv[1];
+ return 1;
+ }
- talk_base::Thread *pthMain = talk_base::Thread::Current();
-
- talk_base::AsyncUDPSocket* server_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver());
+ talk_base::Thread *pthMain = talk_base::Thread::Current();
+
+ talk_base::AsyncUDPSocket* server_socket =
+ talk_base::CreateAsyncUDPSocket(pthMain->socketserver());
if (server_socket->Bind(server_addr) < 0) {
std::cerr << "bind: " << std::strerror(errno) << std::endl;
return 1;
@@ -61,6 +65,5 @@
pthMain->Run();
delete server;
- delete server_socket;
return 0;
}
diff --git a/talk/p2p/base/stunserver_unittest.cc b/talk/p2p/base/stunserver_unittest.cc
deleted file mode 100755
index b56da4e..0000000
--- a/talk/p2p/base/stunserver_unittest.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "talk/base/testclient.h"
-#include "talk/base/thread.h"
-#include "talk/base/physicalsocketserver.h"
-#include "talk/base/host.h"
-#include "talk/p2p/base/stunserver.h"
-#include <cstring>
-#include <iostream>
-#include <cassert>
-
-using namespace cricket;
-
-StunMessage* GetResponse(talk_base::TestClient* client) {
- talk_base::TestClient::Packet* packet = client->NextPacket();
- assert(packet);
- talk_base::ByteBuffer buf(packet->buf, packet->size);
- StunMessage* msg = new StunMessage();
- assert(msg->Read(&buf));
- delete packet;
- return msg;
-}
-
-int main(int argc, char* argv[]) {
- assert(talk_base::LocalHost().networks().size() >= 2);
- talk_base::SocketAddress server_addr(talk_base::LocalHost().networks()[1]->ip(), 7000);
- talk_base::SocketAddress client_addr(talk_base::LocalHost().networks()[1]->ip(), 6000);
-
- talk_base::Thread th;
-
- talk_base::AsyncUDPSocket* server_socket = 0;
- StunServer* server = 0;
- if (argc >= 2) {
- server_addr.SetIP(argv[1]);
- client_addr.SetIP(0);
- if (argc == 3)
- server_addr.SetPort(atoi(argv[2]));
- std::cout << "Using server at " << server_addr.ToString() << std::endl;
- } else {
- server_socket = talk_base::CreateAsyncUDPSocket(th.socketserver());
- assert(server_socket->Bind(server_addr) >= 0);
- server = new StunServer(server_socket);
- }
-
- talk_base::AsyncUDPSocket* client_socket = talk_base::CreateAsyncUDPSocket(th.socketserver());
- assert(client_socket->Bind(client_addr) >= 0);
- talk_base::TestClient* client = new talk_base::TestClient(client_socket, &th);
-
- th.Start();
-
- const char* bad = "this is a completely nonsensical message whose only "
- "purpose is to make the parser go 'ack'. it doesn't "
- "look anything like a normal stun message";
-
- client->SendTo(bad, std::strlen(bad), server_addr);
- StunMessage* msg = GetResponse(client);
- assert(msg->type() == STUN_BINDING_ERROR_RESPONSE);
-
- const StunErrorCodeAttribute* err = msg->GetErrorCode();
- assert(err);
- assert(err->error_class() == 4);
- assert(err->number() == 0);
- assert(err->reason() == std::string("Bad Request"));
-
- delete msg;
-
- std::string transaction_id = "0123456789abcdef";
-
- StunMessage req;
- req.SetType(STUN_BINDING_REQUEST);
- req.SetTransactionID(transaction_id);
-
- talk_base::ByteBuffer buf;
- req.Write(&buf);
-
- client->SendTo(buf.Data(), buf.Length(), server_addr);
- StunMessage* msg2 = GetResponse(client);
- assert(msg2->type() == STUN_BINDING_RESPONSE);
- assert(msg2->transaction_id() == transaction_id);
-
- const StunAddressAttribute* mapped_addr =
- msg2->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
- assert(mapped_addr);
- assert(mapped_addr->family() == 1);
- assert(mapped_addr->port() == client_addr.port());
- if (mapped_addr->ip() != client_addr.ip()) {
- printf("Warning: mapped IP (%s) != local IP (%s)\n",
- talk_base::SocketAddress::IPToString(mapped_addr->ip()).c_str(),
- client_addr.IPAsString().c_str());
- }
-
- const StunAddressAttribute* source_addr =
- msg2->GetAddress(STUN_ATTR_SOURCE_ADDRESS);
- assert(source_addr);
- assert(source_addr->family() == 1);
- assert(source_addr->port() == server_addr.port());
- assert(source_addr->ip() == server_addr.ip());
-
- delete msg2;
-
- th.Stop();
-
- delete server;
- delete server_socket;
- delete client;
-
- std::cout << "PASS" << std::endl;
- return 0;
-}
diff --git a/talk/p2p/base/tcpport.cc b/talk/p2p/base/tcpport.cc
old mode 100755
new mode 100644
index 57e2a4f..806c258
--- a/talk/p2p/base/tcpport.cc
+++ b/talk/p2p/base/tcpport.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,38 +29,39 @@
#pragma warning(disable:4786)
#endif
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
-
-#include <cassert>
-#include <iostream>
+#include "talk/p2p/base/tcpport.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
-#ifdef WIN32
-#include "talk/base/winfirewall.h"
-#endif // WIN32
-#include "talk/p2p/base/tcpport.h"
+#include "talk/p2p/base/common.h"
namespace cricket {
-#ifdef WIN32
-static talk_base::WinFirewall win_firewall;
-#endif // WIN32
-
-TCPPort::TCPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
- talk_base::Network* network,
- const talk_base::SocketAddress& address)
+TCPPort::TCPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network* network,
+ const talk_base::SocketAddress& address,
+ bool allow_listen)
: Port(thread, LOCAL_PORT_TYPE, factory, network), address_(address),
- incoming_only_(address_.port() != 0), error_(0) {
- socket_ = thread->socketserver()->CreateAsyncSocket(SOCK_STREAM);
- socket_->SignalReadEvent.connect(this, &TCPPort::OnAcceptEvent);
- if (socket_->Bind(address_) < 0) {
- LOG_F(LS_ERROR) << "Bind error: " << socket_->GetError();
+ incoming_only_(address_.port() != 0), allow_listen_(allow_listen),
+ socket_(NULL), error_(0) {
+}
+
+bool TCPPort::Init() {
+ // We don't use CreatePacketSocket here since we're creating a listen socket.
+ // However we will treat failure to create or bind a TCP socket as fatal.
+ // This should never happen.
+ socket_ = factory_->CreateAsyncSocket(SOCK_STREAM);
+ if (!socket_) {
+ LOG_J(LS_ERROR, this) << "TCP socket creation failed.";
+ return false;
}
+ if (socket_->Bind(address_) < 0) {
+ LOG_J(LS_ERROR, this) << "TCP bind failed with error "
+ << socket_->GetError();
+ return false;
+ }
+ socket_->SignalReadEvent.connect(this, &TCPPort::OnAcceptEvent);
+ return true;
}
TCPPort::~TCPPort() {
@@ -71,22 +72,22 @@
CandidateOrigin origin) {
// We only support TCP protocols
if ((address.protocol() != "tcp") && (address.protocol() != "ssltcp"))
- return 0;
+ return NULL;
// We can't accept TCP connections incoming on other ports
if (origin == ORIGIN_OTHER_PORT)
- return 0;
+ return NULL;
// Check if we are allowed to make outgoing TCP connections
if (incoming_only_ && (origin == ORIGIN_MESSAGE))
- return 0;
+ return NULL;
// We don't know how to act as an ssl server yet
if ((address.protocol() == "ssltcp") && (origin == ORIGIN_THIS_PORT))
- return 0;
+ return NULL;
- TCPConnection* conn = 0;
- if (talk_base::AsyncTCPSocket * socket
+ TCPConnection* conn = NULL;
+ if (talk_base::AsyncTCPSocket * socket
= GetIncoming(address.address(), true)) {
socket->SignalReadPacket.disconnect(this);
conn = new TCPConnection(this, address, socket);
@@ -98,49 +99,36 @@
}
void TCPPort::PrepareAddress() {
- assert(socket_);
-
- bool allow_listen = true;
-#ifdef WIN32
- if (win_firewall.Initialize()) {
- char module_path[MAX_PATH + 1] = { 0 };
- ::GetModuleFileNameA(NULL, module_path, MAX_PATH);
- if (win_firewall.Enabled() && !win_firewall.Authorized(module_path)) {
- allow_listen = false;
- }
- }
-#endif // WIN32
- if (!allow_listen) {
- LOG_F(LS_VERBOSE) << "Not listening due to firewall restrictions";
+ if (!allow_listen_) {
+ LOG_J(LS_INFO, this) << "Not listening due to firewall restrictions.";
} else if (socket_->Listen(5) < 0) {
- LOG_F(LS_ERROR) << "Listen error: " << socket_->GetError();
+ LOG_J(LS_WARNING, this) << "TCP listen failed with error "
+ << socket_->GetError();
}
// Note: We still add the address, since otherwise the remote side won't
// recognize our incoming TCP connections.
AddAddress(socket_->GetLocalAddress(), "tcp", true);
}
-int TCPPort::SendTo(const void* data, size_t size,
+int TCPPort::SendTo(const void* data, size_t size,
const talk_base::SocketAddress& addr, bool payload) {
- talk_base::AsyncTCPSocket * socket = 0;
-
+ talk_base::AsyncTCPSocket * socket = NULL;
if (TCPConnection * conn = static_cast<TCPConnection*>(GetConnection(addr))) {
socket = conn->socket();
} else {
socket = GetIncoming(addr);
}
if (!socket) {
- LOG_F(LS_ERROR) << "Unknown destination: " << addr.ToString();
- return -1; // TODO: Set error_
+ LOG_J(LS_ERROR, this) << "Attempted to send to an unknown destination, "
+ << addr.ToString();
+ return -1; // TODO: Set error_
}
- //LOG_F(INFO) << "(" << size << ", " << addr.ToString() << ")";
-
int sent = socket->Send(data, size);
if (sent < 0) {
error_ = socket->GetError();
- LOG_F(LS_ERROR) << "(" << size << ", " << addr.ToString()
- << ") Send error: " << error_;
+ LOG_J(LS_ERROR, this) << "TCP send of " << size
+ << " bytes failed with error " << error_;
}
return sent;
}
@@ -150,35 +138,35 @@
}
int TCPPort::GetError() {
- assert(socket_);
return error_;
}
void TCPPort::OnAcceptEvent(talk_base::AsyncSocket* socket) {
- assert(socket == socket_);
+ ASSERT(socket == socket_);
Incoming incoming;
- talk_base::AsyncSocket * newsocket
- = static_cast<talk_base::AsyncSocket *>(socket->Accept(&incoming.addr));
+ talk_base::AsyncSocket* newsocket = socket->Accept(&incoming.addr);
if (!newsocket) {
// TODO: Do something better like forwarding the error to the user.
- LOG_F(LS_ERROR) << "Accept error: " << socket_->GetError();
+ LOG_J(LS_ERROR, this) << "TCP accept failed with error "
+ << socket_->GetError();
return;
}
incoming.socket = new talk_base::AsyncTCPSocket(newsocket);
incoming.socket->SignalReadPacket.connect(this, &TCPPort::OnReadPacket);
- LOG_F(LS_VERBOSE) << "(" << incoming.addr.ToString() << ")";
+ LOG_J(LS_VERBOSE, this) << "Accepted connection from "
+ << incoming.addr.ToString();
incoming_.push_back(incoming);
// Prime a read event in case data is waiting
newsocket->SignalReadEvent(newsocket);
}
-talk_base::AsyncTCPSocket * TCPPort::GetIncoming(
+talk_base::AsyncTCPSocket* TCPPort::GetIncoming(
const talk_base::SocketAddress& addr, bool remove) {
- talk_base::AsyncTCPSocket * socket = 0;
- for (std::list<Incoming>::iterator it = incoming_.begin();
+ talk_base::AsyncTCPSocket* socket = NULL;
+ for (std::list<Incoming>::iterator it = incoming_.begin();
it != incoming_.end(); ++it) {
if (it->addr == addr) {
socket = it->socket;
@@ -190,19 +178,20 @@
return socket;
}
-void TCPPort::OnReadPacket(const char* data, size_t size,
+void TCPPort::OnReadPacket(const char* data, size_t size,
const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket) {
Port::OnReadPacket(data, size, remote_addr);
}
-TCPConnection::TCPConnection(TCPPort* port, const Candidate& candidate,
+TCPConnection::TCPConnection(TCPPort* port, const Candidate& candidate,
talk_base::AsyncTCPSocket* socket)
: Connection(port, 0, candidate), socket_(socket), error_(0) {
- bool outgoing = (socket_ == 0);
+ bool outgoing = (socket_ == NULL);
if (outgoing) {
- socket_ = static_cast<talk_base::AsyncTCPSocket *>(port->CreatePacketSocket(
- (candidate.protocol() == "ssltcp") ? PROTO_SSLTCP : PROTO_TCP));
+ // TODO: Handle failures here (unlikely since TCP)
+ socket_ = static_cast<talk_base::AsyncTCPSocket*>(port->CreatePacketSocket(
+ (candidate.protocol() == "ssltcp") ? PROTO_SSLTCP : PROTO_TCP));
} else {
// Incoming connections should match the network address
ASSERT(socket_->GetLocalAddress().EqualIPs(port->address_));
@@ -215,8 +204,8 @@
socket_->SignalConnect.connect(this, &TCPConnection::OnConnect);
socket_->Bind(local_address);
socket_->Connect(candidate.address());
- LOG_F(LS_VERBOSE) << "Connecting from " << local_address.ToString()
- << " to " << candidate.address().ToString();
+ LOG_J(LS_VERBOSE, this) << "Connecting from " << local_address.ToString()
+ << " to " << candidate.address().ToString();
}
}
@@ -234,7 +223,7 @@
if (sent < 0) {
error_ = socket_->GetError();
} else {
- sent_total_bytes_ += sent;
+ send_rate_tracker_.Update(sent);
}
return sent;
}
@@ -243,29 +232,25 @@
return error_;
}
-TCPPort* TCPConnection::tcpport() {
- return static_cast<TCPPort*>(port_);
-}
-
void TCPConnection::OnConnect(talk_base::AsyncTCPSocket* socket) {
- assert(socket == socket_);
- LOG_F(LS_VERBOSE) << "(" << socket->GetRemoteAddress().ToString() << ")";
+ ASSERT(socket == socket_);
+ LOG_J(LS_VERBOSE, this) << "Connection established to "
+ << socket->GetRemoteAddress().ToString();
set_connected(true);
}
void TCPConnection::OnClose(talk_base::AsyncTCPSocket* socket, int error) {
- assert(socket == socket_);
- LOG_F(LS_VERBOSE) << "(" << error << ")";
+ ASSERT(socket == socket_);
+ LOG_J(LS_VERBOSE, this) << "Connection closed with error " << error;
set_connected(false);
set_write_state(STATE_WRITE_TIMEOUT);
}
-void TCPConnection::OnReadPacket(const char* data, size_t size,
+void TCPConnection::OnReadPacket(const char* data, size_t size,
const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket) {
- assert(socket == socket_);
- //LOG_F(LS_INFO) << "(" << size << ", " << remote_addr.ToString() << ")";
+ ASSERT(socket == socket_);
Connection::OnReadPacket(data, size);
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/tcpport.h b/talk/p2p/base/tcpport.h
old mode 100755
new mode 100644
index 24555ae..d4ce575
--- a/talk/p2p/base/tcpport.h
+++ b/talk/p2p/base/tcpport.h
@@ -2,32 +2,33 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __TCPPORT_H__
-#define __TCPPORT_H__
+#ifndef TALK_P2P_BASE_TCPPORT_H_
+#define TALK_P2P_BASE_TCPPORT_H_
+#include <string>
#include <list>
#include "talk/base/asynctcpsocket.h"
#include "talk/p2p/base/port.h"
@@ -36,7 +37,7 @@
class TCPConnection;
-extern const std::string LOCAL_PORT_TYPE; // type of TCP ports
+extern const std::string LOCAL_PORT_TYPE; // type of TCP ports
// Communicates using a local TCP port.
//
@@ -45,56 +46,72 @@
// packet sending and preparation, but when a packet is received, it should
// call this TCPPort::OnReadPacket (3 arg) to dispatch to a connection.
class TCPPort : public Port {
-public:
- TCPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
- talk_base::Network* network, const talk_base::SocketAddress& address);
+ public:
+ static TCPPort* Create(talk_base::Thread* thread,
+ talk_base::SocketFactory* factory,
+ talk_base::Network* network,
+ const talk_base::SocketAddress& local_addr,
+ bool allow_listen) {
+ TCPPort* port = new TCPPort(thread, factory, network, local_addr,
+ allow_listen);
+ if (!port->Init()) {
+ delete port;
+ port = NULL;
+ }
+ return port;
+ }
+ bool Init();
virtual ~TCPPort();
- virtual Connection* CreateConnection(const Candidate& address, CandidateOrigin origin);
+ virtual Connection* CreateConnection(const Candidate& address,
+ CandidateOrigin origin);
virtual void PrepareAddress();
virtual int SetOption(talk_base::Socket::Option opt, int value);
virtual int GetError();
-protected:
+ protected:
+ TCPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network* network, const talk_base::SocketAddress& address,
+ bool allow_listen);
+
// Handles sending using the local TCP socket.
- virtual int SendTo(const void* data, size_t size,
- const talk_base::SocketAddress& addr, bool payload);
+ virtual int SendTo(const void* data, size_t size,
+ const talk_base::SocketAddress& addr, bool payload);
// Creates TCPConnection for incoming sockets
void OnAcceptEvent(talk_base::AsyncSocket* socket);
- talk_base::AsyncSocket* socket() { return socket_; }
-
-private:
- // Note: use this until Network ips are stable, then use network->ip
- talk_base::SocketAddress address_;
- bool incoming_only_;
- talk_base::AsyncSocket* socket_;
- int error_;
-
+ private:
struct Incoming {
talk_base::SocketAddress addr;
talk_base::AsyncTCPSocket * socket;
};
- std::list<Incoming> incoming_;
- talk_base::AsyncTCPSocket * GetIncoming(const talk_base::SocketAddress& addr,
- bool remove = false);
+ talk_base::AsyncTCPSocket* GetIncoming(const talk_base::SocketAddress& addr,
+ bool remove = false);
// Receives packet signal from the local TCP Socket.
- void OnReadPacket(const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr,
- talk_base::AsyncPacketSocket* socket);
+ void OnReadPacket(const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ talk_base::AsyncPacketSocket* socket);
+
+ // Note: use this until Network ips are stable, then use network->ip
+ talk_base::SocketAddress address_;
+ bool incoming_only_;
+ bool allow_listen_;
+ talk_base::AsyncSocket* socket_;
+ int error_;
+ std::list<Incoming> incoming_;
friend class TCPConnection;
};
class TCPConnection : public Connection {
-public:
+ public:
// Connection is outgoing unless socket is specified
- TCPConnection(TCPPort* port, const Candidate& candidate,
+ TCPConnection(TCPPort* port, const Candidate& candidate,
talk_base::AsyncTCPSocket* socket = 0);
virtual ~TCPConnection();
@@ -103,20 +120,19 @@
talk_base::AsyncTCPSocket * socket() { return socket_; }
-private:
- TCPPort* tcpport();
- talk_base::AsyncTCPSocket* socket_;
- int error_;
-
+ private:
void OnConnect(talk_base::AsyncTCPSocket* socket);
void OnClose(talk_base::AsyncTCPSocket* socket, int error);
- void OnReadPacket(const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr,
- talk_base::AsyncPacketSocket* socket);
+ void OnReadPacket(const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ talk_base::AsyncPacketSocket* socket);
+
+ talk_base::AsyncTCPSocket* socket_;
+ int error_;
friend class TCPPort;
};
-} // namespace cricket
+} // namespace cricket
-#endif // __TCPPORT_H__
+#endif // TALK_P2P_BASE_TCPPORT_H_
diff --git a/talk/p2p/base/transport.cc b/talk/p2p/base/transport.cc
old mode 100755
new mode 100644
index dfa2dfd..663a608
--- a/talk/p2p/base/transport.cc
+++ b/talk/p2p/base/transport.cc
@@ -2,96 +2,114 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/common.h"
#include "talk/p2p/base/transport.h"
-#include "talk/p2p/base/sessionmanager.h"
-#include "talk/p2p/base/transportchannelimpl.h"
+
+#include "talk/base/common.h"
+#include "talk/p2p/base/candidate.h"
#include "talk/p2p/base/constants.h"
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/base/parsing.h"
+#include "talk/p2p/base/transportchannelimpl.h"
#include "talk/xmllite/xmlelement.h"
#include "talk/xmpp/constants.h"
-namespace {
+namespace cricket {
struct ChannelParams {
- std::string name;
- std::string session_type;
- cricket::TransportChannelImpl* channel;
- buzz::XmlElement* elem;
+ ChannelParams() : channel(NULL), candidate(NULL) {}
+ explicit ChannelParams(const std::string& name)
+ : name(name), channel(NULL), candidate(NULL) {}
+ ChannelParams(const std::string& name,
+ const std::string& content_type)
+ : name(name), content_type(content_type),
+ channel(NULL), candidate(NULL) {}
+ explicit ChannelParams(cricket::Candidate* candidate) :
+ channel(NULL), candidate(candidate) {
+ name = candidate->name();
+ }
- ChannelParams() : channel(NULL), elem(NULL) {}
+ ~ChannelParams() {
+ delete candidate;
+ }
+
+ std::string name;
+ std::string content_type;
+ cricket::TransportChannelImpl* channel;
+ cricket::Candidate* candidate;
};
typedef talk_base::TypedMessageData<ChannelParams*> ChannelMessage;
-const int MSG_CREATECHANNEL = 1;
-const int MSG_DESTROYCHANNEL = 2;
-const int MSG_DESTROYALLCHANNELS = 3;
-const int MSG_CONNECTCHANNELS = 4;
-const int MSG_RESETCHANNELS = 5;
-const int MSG_ONSIGNALINGREADY = 6;
-const int MSG_FORWARDCHANNELMESSAGE = 7;
-const int MSG_READSTATE = 8;
-const int MSG_WRITESTATE = 9;
-const int MSG_REQUESTSIGNALING = 10;
-const int MSG_ONCHANNELMESSAGE = 11;
-const int MSG_CONNECTING = 12;
+enum {
+ MSG_CREATECHANNEL = 1,
+ MSG_DESTROYCHANNEL = 2,
+ MSG_DESTROYALLCHANNELS = 3,
+ MSG_CONNECTCHANNELS = 4,
+ MSG_RESETCHANNELS = 5,
+ MSG_ONSIGNALINGREADY = 6,
+ MSG_ONREMOTECANDIDATE = 7,
+ MSG_READSTATE = 8,
+ MSG_WRITESTATE = 9,
+ MSG_REQUESTSIGNALING = 10,
+ MSG_ONCHANNELCANDIDATEREADY = 11,
+ MSG_CONNECTING = 12,
+};
-} // namespace
-
-namespace cricket {
-
-Transport::Transport(SessionManager* session_manager, const std::string& name)
- : session_manager_(session_manager), name_(name), destroyed_(false),
- readable_(false), writable_(false), connect_requested_(false),
- allow_local_ips_(false) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+Transport::Transport(talk_base::Thread* signaling_thread,
+ talk_base::Thread* worker_thread,
+ const std::string& type,
+ PortAllocator* allocator)
+ : signaling_thread_(signaling_thread),
+ worker_thread_(worker_thread), type_(type), allocator_(allocator),
+ destroyed_(false), readable_(false), writable_(false),
+ connect_requested_(false), allow_local_ips_(false) {
}
Transport::~Transport() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread_->IsCurrent());
ASSERT(destroyed_);
}
-TransportChannelImpl* Transport::CreateChannel(const std::string& name, const std::string &session_type) {
- ChannelParams params;
- params.name = name;
- params.session_type = session_type;
+TransportChannelImpl* Transport::CreateChannel(
+ const std::string& name, const std::string& content_type) {
+ ChannelParams params(name, content_type);
ChannelMessage msg(¶ms);
- session_manager_->worker_thread()->Send(this, MSG_CREATECHANNEL, &msg);
+ worker_thread()->Send(this, MSG_CREATECHANNEL, &msg);
return msg.data()->channel;
}
-TransportChannelImpl* Transport::CreateChannel_w(const std::string& name, const std::string &session_type) {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
+TransportChannelImpl* Transport::CreateChannel_w(
+ const std::string& name, const std::string& content_type) {
+ ASSERT(worker_thread()->IsCurrent());
- TransportChannelImpl* impl = CreateTransportChannel(name, session_type);
+ TransportChannelImpl* impl = CreateTransportChannel(name, content_type);
impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState);
impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState);
impl->SignalRequestSignaling.connect(
this, &Transport::OnChannelRequestSignaling);
- impl->SignalChannelMessage.connect(this, &Transport::OnChannelMessage);
+ impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady);
talk_base::CritScope cs(&crit_);
ASSERT(channels_.find(name) == channels_.end());
@@ -102,7 +120,7 @@
if (channels_.size() == 1) {
// If this is the first channel, then indicate that we have started
// connecting.
- session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL);
+ signaling_thread()->Post(this, MSG_CONNECTING, NULL);
}
}
return impl;
@@ -120,14 +138,13 @@
}
void Transport::DestroyChannel(const std::string& name) {
- ChannelParams params;
- params.name = name;
+ ChannelParams params(name);
ChannelMessage msg(¶ms);
- session_manager_->worker_thread()->Send(this, MSG_DESTROYCHANNEL, &msg);
+ worker_thread()->Send(this, MSG_DESTROYCHANNEL, &msg);
}
void Transport::DestroyChannel_w(const std::string& name) {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
+ ASSERT(worker_thread()->IsCurrent());
TransportChannelImpl* impl = NULL;
{
talk_base::CritScope cs(&crit_);
@@ -139,7 +156,7 @@
if (connect_requested_ && channels_.empty()) {
// We're not longer attempting to connect.
- session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL);
+ signaling_thread()->Post(this, MSG_CONNECTING, NULL);
}
if (impl)
@@ -147,35 +164,36 @@
}
void Transport::ConnectChannels() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- session_manager_->worker_thread()->Post(this, MSG_CONNECTCHANNELS, NULL);
+ ASSERT(signaling_thread()->IsCurrent());
+ worker_thread()->Post(this, MSG_CONNECTCHANNELS, NULL);
}
void Transport::ConnectChannels_w() {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
+ ASSERT(worker_thread()->IsCurrent());
if (connect_requested_)
return;
connect_requested_ = true;
- session_manager_->signaling_thread()->Post(this, MSG_ONCHANNELMESSAGE, NULL);
+ signaling_thread()->Post(
+ this, MSG_ONCHANNELCANDIDATEREADY, NULL);
CallChannels_w(&TransportChannelImpl::Connect);
if (!channels_.empty()) {
- session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL);
+ signaling_thread()->Post(this, MSG_CONNECTING, NULL);
}
}
void Transport::OnConnecting_s() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread()->IsCurrent());
SignalConnecting(this);
}
-
+
void Transport::DestroyAllChannels() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- session_manager_->worker_thread()->Send(this, MSG_DESTROYALLCHANNELS, NULL);
+ ASSERT(signaling_thread()->IsCurrent());
+ worker_thread()->Send(this, MSG_DESTROYALLCHANNELS, NULL);
destroyed_ = true;
}
void Transport::DestroyAllChannels_w() {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
+ ASSERT(worker_thread()->IsCurrent());
std::vector<TransportChannelImpl*> impls;
{
talk_base::CritScope cs(&crit_);
@@ -192,37 +210,34 @@
}
void Transport::ResetChannels() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- session_manager_->worker_thread()->Post(this, MSG_RESETCHANNELS, NULL);
+ ASSERT(signaling_thread()->IsCurrent());
+ worker_thread()->Post(this, MSG_RESETCHANNELS, NULL);
}
void Transport::ResetChannels_w() {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
+ ASSERT(worker_thread()->IsCurrent());
// We are no longer attempting to connect
connect_requested_ = false;
// Clear out the old messages, they aren't relevant
talk_base::CritScope cs(&crit_);
- for (size_t i=0; i<messages_.size(); ++i) {
- delete messages_[i];
- }
- messages_.clear();
+ ready_candidates_.clear();
// Reset all of the channels
CallChannels_w(&TransportChannelImpl::Reset);
}
void Transport::OnSignalingReady() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- session_manager_->worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL);
+ ASSERT(signaling_thread()->IsCurrent());
+ worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL);
// Notify the subclass.
OnTransportSignalingReady();
}
void Transport::CallChannels_w(TransportChannelFunc func) {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
+ ASSERT(worker_thread()->IsCurrent());
talk_base::CritScope cs(&crit_);
for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end();
@@ -231,35 +246,63 @@
}
}
-void Transport::ForwardChannelMessage(const std::string& name,
- buzz::XmlElement* elem) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
- ASSERT(HasChannel(name));
- ChannelParams* params = new ChannelParams();
- params->name = name;
- params->elem = elem;
- ChannelMessage* msg = new ChannelMessage(params);
- session_manager_->worker_thread()->Post(this, MSG_FORWARDCHANNELMESSAGE, msg);
+bool Transport::VerifyCandidate(const Candidate& cand, ParseError* error) {
+ if (cand.address().IsLocalIP() && !allow_local_ips_)
+ return BadParse("candidate has local IP address", error);
+
+ // No address zero.
+ if (cand.address().IsAny()) {
+ return BadParse("candidate has address of zero", error);
+ }
+
+ // Disallow all ports below 1024, except for 80 and 443 on public addresses.
+ int port = cand.address().port();
+ if (port < 1024) {
+ if ((port != 80) && (port != 443))
+ return BadParse(
+ "candidate has port below 1024, but not 80 or 443", error);
+ if (cand.address().IsPrivateIP()) {
+ return BadParse(
+ "candidate has port of 80 or 443 with private IP address", error);
+ }
+ }
+
+ return true;
}
-void Transport::ForwardChannelMessage_w(const std::string& name,
- buzz::XmlElement* elem) {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
- ChannelMap::iterator iter = channels_.find(name);
+void Transport::OnRemoteCandidates(const std::vector<Candidate>& candidates) {
+ for (std::vector<Candidate>::const_iterator iter = candidates.begin();
+ iter != candidates.end();
+ ++iter) {
+ OnRemoteCandidate(*iter);
+ }
+}
+
+void Transport::OnRemoteCandidate(const Candidate& candidate) {
+ ASSERT(signaling_thread()->IsCurrent());
+ ASSERT(HasChannel(candidate.name()));
+ // new candidate deleted when params is deleted
+ ChannelParams* params = new ChannelParams(new Candidate(candidate));
+ ChannelMessage* msg = new ChannelMessage(params);
+ worker_thread()->Post(this, MSG_ONREMOTECANDIDATE, msg);
+}
+
+void Transport::OnRemoteCandidate_w(const Candidate& candidate) {
+ ASSERT(worker_thread()->IsCurrent());
+ ChannelMap::iterator iter = channels_.find(candidate.name());
// It's ok for a channel to go away while this message is in transit.
if (iter != channels_.end()) {
- iter->second->OnChannelMessage(elem);
+ iter->second->OnCandidate(candidate);
}
- delete elem;
}
void Transport::OnChannelReadableState(TransportChannel* channel) {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
- session_manager_->signaling_thread()->Post(this, MSG_READSTATE, NULL);
+ ASSERT(worker_thread()->IsCurrent());
+ signaling_thread()->Post(this, MSG_READSTATE, NULL);
}
void Transport::OnChannelReadableState_s() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread()->IsCurrent());
bool readable = GetTransportState_s(true);
if (readable_ != readable) {
readable_ = readable;
@@ -268,12 +311,12 @@
}
void Transport::OnChannelWritableState(TransportChannel* channel) {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
- session_manager_->signaling_thread()->Post(this, MSG_WRITESTATE, NULL);
+ ASSERT(worker_thread()->IsCurrent());
+ signaling_thread()->Post(this, MSG_WRITESTATE, NULL);
}
void Transport::OnChannelWritableState_s() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread()->IsCurrent());
bool writable = GetTransportState_s(false);
if (writable_ != writable) {
writable_ = writable;
@@ -282,7 +325,7 @@
}
bool Transport::GetTransportState_s(bool read) {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread()->IsCurrent());
bool result = false;
talk_base::CritScope cs(&crit_);
for (ChannelMap::iterator iter = channels_.begin();
@@ -295,52 +338,43 @@
}
void Transport::OnChannelRequestSignaling() {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
- session_manager_->signaling_thread()->Post(this, MSG_REQUESTSIGNALING, NULL);
+ ASSERT(worker_thread()->IsCurrent());
+ signaling_thread()->Post(this, MSG_REQUESTSIGNALING, NULL);
}
void Transport::OnChannelRequestSignaling_s() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+ ASSERT(signaling_thread()->IsCurrent());
SignalRequestSignaling(this);
}
-void Transport::OnChannelMessage(TransportChannelImpl* impl,
- buzz::XmlElement* elem) {
- ASSERT(session_manager_->worker_thread()->IsCurrent());
+void Transport::OnChannelCandidateReady(TransportChannelImpl* channel,
+ const Candidate& candidate) {
+ ASSERT(worker_thread()->IsCurrent());
talk_base::CritScope cs(&crit_);
- messages_.push_back(elem);
+ ready_candidates_.push_back(candidate);
// We hold any messages until the client lets us connect.
if (connect_requested_) {
- session_manager_->signaling_thread()->Post(
- this, MSG_ONCHANNELMESSAGE, NULL);
+ signaling_thread()->Post(
+ this, MSG_ONCHANNELCANDIDATEREADY, NULL);
}
}
-void Transport::OnChannelMessage_s() {
- ASSERT(session_manager_->signaling_thread()->IsCurrent());
+void Transport::OnChannelCandidateReady_s() {
+ ASSERT(signaling_thread()->IsCurrent());
ASSERT(connect_requested_);
- std::vector<buzz::XmlElement*> msgs;
+ std::vector<Candidate> candidates;
{
talk_base::CritScope cs(&crit_);
- msgs.swap(messages_);
+ candidates.swap(ready_candidates_);
}
- if (!msgs.empty())
- OnTransportChannelMessages(msgs);
-}
-
-void Transport::OnTransportChannelMessages(
- const std::vector<buzz::XmlElement*>& msgs) {
- std::vector<buzz::XmlElement*> elems;
- for (size_t i = 0; i < msgs.size(); ++i) {
- buzz::XmlElement* elem =
- new buzz::XmlElement(buzz::QName(name(), "transport"));
- elem->AddElement(msgs[i]);
- elems.push_back(elem);
+ // we do the deleting of Candidate* here to keep the new above and
+ // delete below close to each other
+ if (!candidates.empty()) {
+ SignalCandidatesReady(this, candidates);
}
- SignalTransportMessage(this, elems);
}
void Transport::OnMessage(talk_base::Message* msg) {
@@ -348,7 +382,7 @@
case MSG_CREATECHANNEL:
{
ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data();
- params->channel = CreateChannel_w(params->name, params->session_type);
+ params->channel = CreateChannel_w(params->name, params->content_type);
}
break;
case MSG_DESTROYCHANNEL:
@@ -369,11 +403,13 @@
case MSG_ONSIGNALINGREADY:
CallChannels_w(&TransportChannelImpl::OnSignalingReady);
break;
- case MSG_FORWARDCHANNELMESSAGE:
+ case MSG_ONREMOTECANDIDATE:
{
- ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data();
- ForwardChannelMessage_w(params->name, params->elem);
+ ChannelMessage* channel_msg = static_cast<ChannelMessage*>(msg->pdata);
+ ChannelParams* params = channel_msg->data();
+ OnRemoteCandidate_w(*(params->candidate));
delete params;
+ delete channel_msg;
}
break;
case MSG_CONNECTING:
@@ -388,52 +424,27 @@
case MSG_REQUESTSIGNALING:
OnChannelRequestSignaling_s();
break;
- case MSG_ONCHANNELMESSAGE:
- OnChannelMessage_s();
+ case MSG_ONCHANNELCANDIDATEREADY:
+ OnChannelCandidateReady_s();
break;
}
}
-bool Transport::BadRequest(const buzz::XmlElement* stanza,
- const std::string& text,
- const buzz::XmlElement* extra_info) {
- SignalTransportError(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- text, extra_info);
- return false;
-}
+bool TransportParser::ParseAddress(const buzz::XmlElement* elem,
+ const buzz::QName& address_name,
+ const buzz::QName& port_name,
+ talk_base::SocketAddress* address,
+ ParseError* error) {
+ if (!elem->HasAttr(address_name))
+ return BadParse("address does not have " + address_name.LocalPart(), error);
+ if (!elem->HasAttr(port_name))
+ return BadParse("address does not have " + port_name.LocalPart(), error);
-bool Transport::ParseAddress(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- talk_base::SocketAddress* address) {
- ASSERT(elem->HasAttr(QN_ADDRESS));
- ASSERT(elem->HasAttr(QN_PORT));
-
- // Record the parts of the address.
- address->SetIP(elem->Attr(QN_ADDRESS));
- std::istringstream ist(elem->Attr(QN_PORT));
+ address->SetIP(elem->Attr(address_name));
+ std::istringstream ist(elem->Attr(port_name));
int port;
ist >> port;
address->SetPort(port);
-
- // No address zero.
- if (address->IsAny())
- return BadRequest(stanza, "candidate has address of zero", NULL);
-
- // Always disallow addresses that refer to the local host.
- if (address->IsLocalIP() && !allow_local_ips_)
- return BadRequest(stanza, "candidate has local IP address", NULL);
-
- // Disallow all ports below 1024, except for 80 and 443 on public addresses.
- if (port < 1024) {
- if ((port != 80) && (port != 443))
- return BadRequest(stanza,
- "candidate has port below 1024, but not 80 or 443",
- NULL);
- if (address->IsPrivateIP()) {
- return BadRequest(stanza, "candidate has port of 80 or 443 with private "
- "IP address", NULL);
- }
- }
return true;
}
diff --git a/talk/p2p/base/transport.h b/talk/p2p/base/transport.h
old mode 100755
new mode 100644
index 826fd26..d9a2d94
--- a/talk/p2p/base/transport.h
+++ b/talk/p2p/base/transport.h
@@ -37,14 +37,14 @@
// be made on the signaling thread and all channel related calls (including
// signaling for a channel) will be made on the worker thread. When
// information needs to be sent between the two threads, this class should do
-// the work (e.g., ForwardChannelMessage).
+// the work (e.g., OnRemoteCandidate).
//
// Note: Subclasses must call DestroyChannels() in their own constructors.
// It is not possible to do so here because the subclass constructor will
// already have run.
-#ifndef _CRICKET_P2P_BASE_TRANSPORT_H_
-#define _CRICKET_P2P_BASE_TRANSPORT_H_
+#ifndef TALK_P2P_BASE_TRANSPORT_H_
+#define TALK_P2P_BASE_TRANSPORT_H_
#include <string>
#include <map>
@@ -52,6 +52,12 @@
#include "talk/base/criticalsection.h"
#include "talk/base/messagequeue.h"
#include "talk/base/sigslot.h"
+#include "talk/p2p/base/candidate.h"
+#include "talk/p2p/base/constants.h"
+
+namespace talk_base {
+class Thread;
+}
namespace buzz {
class QName;
@@ -60,21 +66,63 @@
namespace cricket {
+struct ParseError;
+struct WriteError;
+class PortAllocator;
class SessionManager;
class Session;
class TransportChannel;
class TransportChannelImpl;
-class Transport : public talk_base::MessageHandler, public sigslot::has_slots<> {
+typedef std::vector<buzz::XmlElement*> XmlElements;
+typedef std::vector<Candidate> Candidates;
+
+// Used to parse and serialize (write) transport candidates. For
+// convenience of old code, Transports will implement TransportParser.
+// Parse/Write seems better than Serialize/Deserialize or
+// Create/Translate.
+class TransportParser {
public:
- Transport(SessionManager* session_manager, const std::string& name);
+ virtual bool ParseCandidates(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ Candidates* candidates,
+ ParseError* error) = 0;
+ virtual bool WriteCandidates(SignalingProtocol protocol,
+ const Candidates& candidates,
+ XmlElements* candidate_elems,
+ WriteError* error) = 0;
+
+ // Helper function to parse an element describing an address. This
+ // retrieves the IP and port from the given element and verifies
+ // that they look like plausible values.
+ bool ParseAddress(const buzz::XmlElement* elem,
+ const buzz::QName& address_name,
+ const buzz::QName& port_name,
+ talk_base::SocketAddress* address,
+ ParseError* error);
+
+ virtual ~TransportParser() {}
+};
+
+class Transport : public talk_base::MessageHandler,
+ public sigslot::has_slots<> {
+ public:
+ Transport(talk_base::Thread* signaling_thread,
+ talk_base::Thread* worker_thread,
+ const std::string& type,
+ PortAllocator* allocator);
virtual ~Transport();
- // Returns a pointer to the singleton session manager.
- SessionManager* session_manager() const { return session_manager_; }
+ // Returns the signaling thread. The app talks to Transport on this thread.
+ talk_base::Thread* signaling_thread() { return signaling_thread_; }
+ // Returns the worker thread. The actual networking is done on this thread.
+ talk_base::Thread* worker_thread() { return worker_thread_; }
- // Returns the name of this transport.
- const std::string& name() const { return name_; }
+ // Returns the type of this transport.
+ const std::string& type() const { return type_; }
+
+ // Returns the port allocator object for this transport.
+ PortAllocator* port_allocator() { return allocator_; }
// Returns the readable and states of this manager. These bits are the ORs
// of the corresponding bits on the managed channels. Each time one of these
@@ -88,12 +136,15 @@
bool connect_requested() const { return connect_requested_; }
// Create, destroy, and lookup the channels of this type by their names.
- TransportChannelImpl* CreateChannel(const std::string& name, const std::string &session_type);
+ TransportChannelImpl* CreateChannel(const std::string& name,
+ const std::string& content_type);
// Note: GetChannel may lead to race conditions, since the mutex is not held
// after the pointer is returned.
TransportChannelImpl* GetChannel(const std::string& name);
// Note: HasChannel does not lead to race conditions, unlike GetChannel.
- bool HasChannel(const std::string& name) { return (NULL != GetChannel(name)); }
+ bool HasChannel(const std::string& name) {
+ return (NULL != GetChannel(name));
+ }
bool HasChannels();
void DestroyChannel(const std::string& name);
@@ -109,32 +160,6 @@
// Destroys every channel created so far.
void DestroyAllChannels();
- // The session handshake includes negotiation of both the application and the
- // transport. The initiating transport creates an "offer" describing what
- // options it supports and the responding transport creates an "answer"
- // describing which options it has accepted. If OnTransport* returns false,
- // that indicates that no acceptable options given and this transport cannot
- // be negotiated.
- //
- // The transport negotiation operates as follows. When the initiating client
- // creates the session, but before they send the initiate, we create the
- // supported transports. The client may override these, but otherwise they
- // get a default set. When the initiate is sent, we ask each transport to
- // produce an offer. When the receiving client gets the initiate, they will
- // iterate through the transport offers in order of their own preference.
- // For each one, they create the transport (if they know what it is) and
- // call OnTransportOffer. If this returns true, then we're good; otherwise,
- // we continue iterating. If no transport works, then we reject the session.
- // Otherwise, we have a single transport, and we send back a transport-accept
- // message that contains the answer. When this arrives at the initiating
- // client, we destroy all transports but the one in the answer and then pass
- // the answer to it. If this transport cannot be found or it cannot accept
- // the answer, then we reject the session. Otherwise, we're in good shape.
- virtual buzz::XmlElement* CreateTransportOffer() = 0;
- virtual buzz::XmlElement* CreateTransportAnswer() = 0;
- virtual bool OnTransportOffer(const buzz::XmlElement* elem) = 0;
- virtual bool OnTransportAnswer(const buzz::XmlElement* elem) = 0;
-
// Before any stanza is sent, the manager will request signaling. Once
// signaling is available, the client should call OnSignalingReady. Once
// this occurs, the transport (or its channels) can send any waiting stanzas.
@@ -143,25 +168,24 @@
sigslot::signal1<Transport*> SignalRequestSignaling;
void OnSignalingReady();
- // Handles sending and receiving of stanzas related to negotiating the
- // connections of the channels. Different transports may have very different
- // signaling, so the XML is handled by the subclass. The msg variable holds
- // the element whose name matches this transport, while stanza holds the
- // entire stanza. The latter is needed when sending an error response.
- // SignalTransportMessage is given the elements that will become the children
- // of the transport-info message. Each element must have a name that matches
- // the transport's name.
- virtual bool OnTransportMessage(const buzz::XmlElement* msg,
- const buzz::XmlElement* stanza) = 0;
- sigslot::signal2<Transport*, const std::vector<buzz::XmlElement*>&>
- SignalTransportMessage;
+ // Handles sending of ready candidates and receiving of remote candidates.
+ sigslot::signal2<Transport*,
+ const std::vector<Candidate>&> SignalCandidatesReady;
+ void OnRemoteCandidates(const std::vector<Candidate>& candidates);
+
+ // If candidate is not acceptable, returns false and sets error.
+ // Call this before calling OnRemoteCandidates.
+ virtual bool VerifyCandidate(const Candidate& candidate,
+ ParseError* error);
// A transport message has generated an transport-specific error. The
// stanza that caused the error is available in session_msg. If false is
// returned, the error is considered unrecoverable, and the session is
// terminated.
- virtual bool OnTransportError(const buzz::XmlElement* session_msg,
- const buzz::XmlElement* error) = 0;
+ // TODO: Make OnTransportError take an abstract data type
+ // rather than an XmlElement. It isn't needed yet, but it might be
+ // later for Jingle compliance.
+ virtual void OnTransportError(const buzz::XmlElement* error) {}
sigslot::signal6<Transport*, const buzz::XmlElement*, const buzz::QName&,
const std::string&, const std::string&,
const buzz::XmlElement*>
@@ -175,60 +199,17 @@
void set_allow_local_ips(bool value) { allow_local_ips_ = value; }
protected:
- // Helper function to bad-request error for a stanza passed to
- // OnTransportMessage. Returns false.
- bool BadRequest(const buzz::XmlElement* stanza, const std::string& text,
- const buzz::XmlElement* extra_info);
-
- // Helper function to parse an element describing an address. This retrieves
- // the IP and port from the given element (using QN_ADDRESS and QN_PORT) and
- // verifies that they look like plausible values.
- bool ParseAddress(const buzz::XmlElement* stanza,
- const buzz::XmlElement* elem,
- talk_base::SocketAddress* address);
-
// These are called by Create/DestroyChannel above in order to create or
// destroy the appropriate type of channel.
virtual TransportChannelImpl* CreateTransportChannel(
- const std::string& name, const std::string &session_type) = 0;
+ const std::string& name, const std::string &content_type) = 0;
virtual void DestroyTransportChannel(TransportChannelImpl* channel) = 0;
// Informs the subclass that we received the signaling ready message.
virtual void OnTransportSignalingReady() {}
- // Forwards the given XML element to the channel on the worker thread. This
- // occurs asynchronously, so we take ownership of the element. Furthermore,
- // the channel will not be able to return an error if the XML is invalid, so
- // the transport should have checked its validity already.
- void ForwardChannelMessage(const std::string& name,
- buzz::XmlElement* elem);
-
- // Handles a set of messages sent by the channels. The default
- // implementation simply forwards each as its own transport message by
- // wrapping it in an element identifying this transport and then invoking
- // SignalTransportMessage. Smarter transports may be able to place multiple
- // channel messages within one transport message.
- //
- // Note: The implementor of this method is responsible for deleting the XML
- // elements passed in, unless they are sent to SignalTransportMessage, where
- // the receiver will delete them.
- virtual void OnTransportChannelMessages(
- const std::vector<buzz::XmlElement*>& msgs);
-
private:
typedef std::map<std::string, TransportChannelImpl*> ChannelMap;
- typedef std::vector<buzz::XmlElement*> XmlElementList;
-
- SessionManager* session_manager_;
- std::string name_;
- bool destroyed_;
- bool readable_;
- bool writable_;
- bool connect_requested_;
- ChannelMap channels_;
- XmlElementList messages_;
- talk_base::CriticalSection crit_; // Protects changes to channels and messages
- bool allow_local_ips_;
// Called when the state of a channel changes.
void OnChannelReadableState(TransportChannel* channel);
@@ -237,8 +218,11 @@
// Called when a channel requests signaling.
void OnChannelRequestSignaling();
- // Called when a channel wishes to send a transport message.
- void OnChannelMessage(TransportChannelImpl* impl, buzz::XmlElement* elem);
+ // Called when a candidate is ready from remote peer.
+ void OnRemoteCandidate(const Candidate& candidate);
+ // Called when a candidate is ready from channel.
+ void OnChannelCandidateReady(TransportChannelImpl* channel,
+ const Candidate& candidate);
// Dispatches messages to the appropriate handler (below).
void OnMessage(talk_base::Message* msg);
@@ -246,13 +230,13 @@
// These are versions of the above methods that are called only on a
// particular thread (s = signaling, w = worker). The above methods post or
// send a message to invoke this version.
- TransportChannelImpl* CreateChannel_w(const std::string& name, const std::string& session_type);
+ TransportChannelImpl* CreateChannel_w(const std::string& name,
+ const std::string& content_type);
void DestroyChannel_w(const std::string& name);
void ConnectChannels_w();
void ResetChannels_w();
void DestroyAllChannels_w();
- void ForwardChannelMessage_w(const std::string& name,
- buzz::XmlElement* elem);
+ void OnRemoteCandidate_w(const Candidate& candidate);
void OnChannelReadableState_s();
void OnChannelWritableState_s();
void OnChannelRequestSignaling_s();
@@ -265,13 +249,27 @@
// Computes the OR of the channel's read or write state (argument picks).
bool GetTransportState_s(bool read);
- // Invoked when there are messages waiting to send in the messages_ list.
- // We wait to send any messages until the client asks us to connect.
- void OnChannelMessage_s();
+ void OnChannelCandidateReady_s();
+
+ talk_base::Thread* signaling_thread_;
+ talk_base::Thread* worker_thread_;
+ std::string type_;
+ PortAllocator* allocator_;
+ bool destroyed_;
+ bool readable_;
+ bool writable_;
+ bool connect_requested_;
+ ChannelMap channels_;
+ // Buffers the ready_candidates so that SignalCanidatesReady can
+ // provide them in multiples.
+ std::vector<Candidate> ready_candidates_;
+ // Protects changes to channels and messages
+ talk_base::CriticalSection crit_;
+ bool allow_local_ips_;
DISALLOW_EVIL_CONSTRUCTORS(Transport);
};
} // namespace cricket
-#endif // _CRICKET_P2P_BASE_TRANSPORT_H_
+#endif // TALK_P2P_BASE_TRANSPORT_H_
diff --git a/talk/p2p/base/transportchannel.cc b/talk/p2p/base/transportchannel.cc
old mode 100755
new mode 100644
diff --git a/talk/p2p/base/transportchannel.h b/talk/p2p/base/transportchannel.h
old mode 100755
new mode 100644
index 68b8fd1..ff252bf
--- a/talk/p2p/base/transportchannel.h
+++ b/talk/p2p/base/transportchannel.h
@@ -2,31 +2,31 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_
-#define _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_
+#ifndef TALK_P2P_BASE_TRANSPORTCHANNEL_H_
+#define TALK_P2P_BASE_TRANSPORTCHANNEL_H_
#include <string>
#include "talk/base/basictypes.h"
@@ -35,17 +35,20 @@
namespace cricket {
+class P2PTransportChannel;
+
// A TransportChannel represents one logical stream of packets that are sent
// between the two sides of a session.
class TransportChannel: public sigslot::has_slots<> {
public:
- TransportChannel(const std::string& name, const std::string &session_type)
- : name_(name), session_type_(session_type), readable_(false), writable_(false) {}
+ TransportChannel(const std::string& name, const std::string &content_type)
+ : name_(name), content_type_(content_type),
+ readable_(false), writable_(false) {}
virtual ~TransportChannel() {}
// Returns the name of this channel.
const std::string& name() const { return name_; }
- const std::string& session_type() const { return session_type_; }
+ const std::string& content_type() const { return content_type_; }
// Returns the readable and states of this channel. Each time one of these
// states changes, a signal is raised. These states are aggregated by the
@@ -65,6 +68,11 @@
// Returns the most recent error that occurred on this channel.
virtual int GetError() = 0;
+ // This hack is here to allow the SocketMonitor to downcast to the
+ // P2PTransportChannel safely.
+ // TODO: Generalize network monitoring.
+ virtual P2PTransportChannel* GetP2PChannel() { return NULL; }
+
// Signalled each time a packet is received on this channel.
sigslot::signal3<TransportChannel*, const char*, size_t> SignalReadPacket;
@@ -72,14 +80,12 @@
// being routed. The address indicates the address of the first hop in the
// new route, if this is known. If this cannot be determined or is not well-
// defined, then the channel may give an address of 0.
- sigslot::signal2<TransportChannel*, const talk_base::SocketAddress&>
+ sigslot::signal2<TransportChannel*, const talk_base::SocketAddress&>
SignalRouteChange;
// Invoked when the channel is being destroyed.
sigslot::signal1<TransportChannel*> SignalDestroyed;
- // TODO: Generalize network monitoring.
-
// Debugging description of this transport channel.
std::string ToString() const;
@@ -92,7 +98,7 @@
private:
std::string name_;
- std::string session_type_;
+ std::string content_type_;
bool readable_;
bool writable_;
@@ -101,4 +107,4 @@
} // namespace cricket
-#endif // _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_
+#endif // TALK_P2P_BASE_TRANSPORTCHANNEL_H_
diff --git a/talk/p2p/base/transportchannelimpl.h b/talk/p2p/base/transportchannelimpl.h
old mode 100755
new mode 100644
index 742d307..39e4288
--- a/talk/p2p/base/transportchannelimpl.h
+++ b/talk/p2p/base/transportchannelimpl.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_
-#define _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_
+#ifndef TALK_P2P_BASE_TRANSPORTCHANNELIMPL_H_
+#define TALK_P2P_BASE_TRANSPORTCHANNELIMPL_H_
#include <string>
#include "talk/p2p/base/transportchannel.h"
@@ -36,14 +36,15 @@
namespace cricket {
class Transport;
+class Candidate;
// Base class for real implementations of TransportChannel. This includes some
// methods called only by Transport, which do not need to be exposed to the
// client.
-class TransportChannelImpl: public TransportChannel {
+class TransportChannelImpl : public TransportChannel {
public:
- TransportChannelImpl(const std::string& name, const std::string& session_type)
- : TransportChannel(name, session_type) {}
+ TransportChannelImpl(const std::string& name, const std::string& content_type)
+ : TransportChannel(name, content_type) {}
// Returns the transport that created this channel.
virtual Transport* GetTransport() = 0;
@@ -60,22 +61,21 @@
sigslot::signal0<> SignalRequestSignaling;
virtual void OnSignalingReady() = 0;
- // Handles sending and receiving of stanzas related to this particular
- // channel. Any channel may send whatever messages it wants. The Transport
- // receives all incoming messages and may forward them to the relevant
- // channel. The transport will delete signaled messages.
+ // Handles sending and receiving of candidates. The Transport
+ // receives the candidates and may forward them to the relevant
+ // channel.
//
- // Note: Since these messages are delivered asynchronously to the channel,
- // they cannot return an error if the message is invalid. It is assumed that
- // the Transport will have checked validity before forwarding.
- virtual void OnChannelMessage(const buzz::XmlElement* msg) = 0;
+ // Note: Since candidates are delivered asynchronously to the
+ // channel, they cannot return an error if the message is invalid.
+ // It is assumed that the Transport will have checked validity
+ // before forwarding.
sigslot::signal2<TransportChannelImpl*,
- buzz::XmlElement*> SignalChannelMessage;
-
+ const Candidate&> SignalCandidateReady;
+ virtual void OnCandidate(const Candidate& candidate) = 0;
private:
DISALLOW_EVIL_CONSTRUCTORS(TransportChannelImpl);
};
} // namespace cricket
-#endif // _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_
+#endif // TALK_P2P_BASE_TRANSPORTCHANNELIMPL_H_
diff --git a/talk/p2p/base/transportchannelproxy.cc b/talk/p2p/base/transportchannelproxy.cc
old mode 100755
new mode 100644
index bc94d67..405ed76
--- a/talk/p2p/base/transportchannelproxy.cc
+++ b/talk/p2p/base/transportchannelproxy.cc
@@ -32,8 +32,9 @@
namespace cricket {
-TransportChannelProxy::TransportChannelProxy(const std::string& name, const std::string &session_type)
- : TransportChannel(name, session_type), impl_(NULL) {
+TransportChannelProxy::TransportChannelProxy(const std::string& name,
+ const std::string &content_type)
+ : TransportChannel(name, content_type), impl_(NULL) {
}
TransportChannelProxy::~TransportChannelProxy() {
@@ -58,8 +59,8 @@
}
int TransportChannelProxy::SendPacket(const char *data, size_t len) {
- ASSERT(impl_ != NULL); // should not be used until channel is writable
- return impl_->SendPacket(data, len);
+ // Fail if we don't have an impl yet.
+ return (impl_) ? impl_->SendPacket(data, len) : -1;
}
int TransportChannelProxy::SetOption(talk_base::Socket::Option opt, int value) {
@@ -84,8 +85,8 @@
set_writable(impl_->writable());
}
-void TransportChannelProxy::OnReadPacket(
- TransportChannel* channel, const char* data, size_t size) {
+void TransportChannelProxy::OnReadPacket(TransportChannel* channel,
+ const char* data, size_t size) {
ASSERT(channel == impl_);
SignalReadPacket(this, data, size);
}
diff --git a/talk/p2p/base/transportchannelproxy.h b/talk/p2p/base/transportchannelproxy.h
old mode 100755
new mode 100644
index 46d8a44..2184477
--- a/talk/p2p/base/transportchannelproxy.h
+++ b/talk/p2p/base/transportchannelproxy.h
@@ -42,7 +42,7 @@
// when negotiation completes, connect the proxy to the implementaiton.
class TransportChannelProxy: public TransportChannel {
public:
- TransportChannelProxy(const std::string& name, const std::string &session_type);
+ TransportChannelProxy(const std::string& name, const std::string &content_type);
virtual ~TransportChannelProxy();
TransportChannelImpl* impl() const { return impl_; }
diff --git a/talk/p2p/base/udpport.cc b/talk/p2p/base/udpport.cc
old mode 100755
new mode 100644
index fa47eba..a34c17e
--- a/talk/p2p/base/udpport.cc
+++ b/talk/p2p/base/udpport.cc
@@ -2,66 +2,57 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma warning(disable:4786)
-#endif
-#include "talk/base/logging.h"
#include "talk/p2p/base/udpport.h"
-#include <iostream>
-#include <cassert>
-#if defined(_MSC_VER) && _MSC_VER < 1300
-namespace std {
- using ::strerror;
-}
-#endif
-
-#ifdef POSIX
-extern "C" {
-#include <errno.h>
-}
-#endif // POSIX
+#include "talk/base/logging.h"
+#include "talk/p2p/base/common.h"
namespace cricket {
const std::string LOCAL_PORT_TYPE("local");
-UDPPort::UDPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
- talk_base::Network* network,
- const talk_base::SocketAddress& address)
- : Port(thread, LOCAL_PORT_TYPE, factory, network), error_(0) {
- socket_ = CreatePacketSocket(PROTO_UDP);
- socket_->SignalReadPacket.connect(this, &UDPPort::OnReadPacketSlot);
- if (socket_->Bind(address) < 0)
- PLOG(LERROR, socket_->GetError()) << "bind";
+UDPPort::UDPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network* network)
+ : Port(thread, LOCAL_PORT_TYPE, factory, network),
+ socket_(NULL), error_(0) {
}
-UDPPort::UDPPort(talk_base::Thread* thread, const std::string &type,
- talk_base::SocketFactory* factory, talk_base::Network* network)
- : Port(thread, type, factory, network), socket_(0), error_(0) {
+bool UDPPort::Init(const talk_base::SocketAddress& local_addr) {
+ socket_ = CreatePacketSocket(PROTO_UDP);
+ if (!socket_) {
+ LOG_J(LS_WARNING, this) << "UDP socket creation failed";
+ return false;
+ }
+ if (socket_->Bind(local_addr) < 0) {
+ LOG_J(LS_WARNING, this) << "UDP bind failed with error "
+ << socket_->GetError();
+ return false;
+ }
+ socket_->SignalReadPacket.connect(this, &UDPPort::OnReadPacket);
+ return true;
}
UDPPort::~UDPPort() {
@@ -69,26 +60,27 @@
}
void UDPPort::PrepareAddress() {
- assert(socket_);
AddAddress(socket_->GetLocalAddress(), "udp", true);
}
-Connection* UDPPort::CreateConnection(const Candidate& address,
+Connection* UDPPort::CreateConnection(const Candidate& address,
CandidateOrigin origin) {
if (address.protocol() != "udp")
- return 0;
+ return NULL;
- Connection * conn = new ProxyConnection(this, 0, address);
+ Connection* conn = new ProxyConnection(this, 0, address);
AddConnection(conn);
return conn;
}
-int UDPPort::SendTo(const void* data, size_t size,
+int UDPPort::SendTo(const void* data, size_t size,
const talk_base::SocketAddress& addr, bool payload) {
- assert(socket_);
int sent = socket_->SendTo(data, size, addr);
- if (sent < 0)
+ if (sent < 0) {
error_ = socket_->GetError();
+ LOG_J(LS_ERROR, this) << "UDP send of " << size
+ << " bytes failed with error " << error_;
+ }
return sent;
}
@@ -97,20 +89,13 @@
}
int UDPPort::GetError() {
- assert(socket_);
return error_;
}
-void UDPPort::OnReadPacketSlot(
+void UDPPort::OnReadPacket(
const char* data, size_t size, const talk_base::SocketAddress& remote_addr,
talk_base::AsyncPacketSocket* socket) {
- assert(socket == socket_);
- OnReadPacket(data, size, remote_addr);
-}
-
-void UDPPort::OnReadPacket(
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ ASSERT(socket == socket_);
if (Connection* conn = GetConnection(remote_addr)) {
conn->OnReadPacket(data, size);
} else {
@@ -118,4 +103,4 @@
}
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/base/udpport.h b/talk/p2p/base/udpport.h
old mode 100755
new mode 100644
index 9fcfa69..7fcad6c
--- a/talk/p2p/base/udpport.h
+++ b/talk/p2p/base/udpport.h
@@ -25,66 +25,65 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __UDPPORT_H__
-#define __UDPPORT_H__
+#ifndef TALK_P2P_BASE_UDPPORT_H_
+#define TALK_P2P_BASE_UDPPORT_H_
+
+#include <string>
#include "talk/base/asyncudpsocket.h"
#include "talk/p2p/base/port.h"
namespace talk_base {
- class Thread;
- class Network;
- class SocketAddress;
-} // namespace talk_base
+class Thread;
+class Network;
+class SocketAddress;
+}
namespace cricket {
-extern const std::string LOCAL_PORT_TYPE; // type of UDP ports
+extern const std::string LOCAL_PORT_TYPE; // type of UDP ports
// Communicates using a local UDP port.
-//
-// This class is designed to allow subclasses to take advantage of the
-// connection management provided by this class. A subclass should take of all
-// packet sending and preparation, but when a packet is received, it should
-// call this UDPPort::OnReadPacket (3 arg) to dispatch to a connection.
class UDPPort : public Port {
-public:
- UDPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
- talk_base::Network* network, const talk_base::SocketAddress& address);
+ public:
+ static UDPPort* Create(talk_base::Thread* thread,
+ talk_base::SocketFactory* factory,
+ talk_base::Network* network,
+ const talk_base::SocketAddress& local_addr) {
+ UDPPort* port = new UDPPort(thread, factory, network);
+ if (!port->Init(local_addr)) {
+ delete port;
+ port = NULL;
+ }
+ return port;
+ }
+ UDPPort(talk_base::Thread* thread, talk_base::SocketFactory* factory,
+ talk_base::Network* network);
+ bool Init(const talk_base::SocketAddress& local_addr);
virtual ~UDPPort();
virtual void PrepareAddress();
- virtual Connection* CreateConnection(const Candidate& address, CandidateOrigin origin);
+ virtual Connection* CreateConnection(const Candidate& address,
+ CandidateOrigin origin);
virtual int SetOption(talk_base::Socket::Option opt, int value);
virtual int GetError();
-protected:
- UDPPort(talk_base::Thread* thread, const std::string &type,
- talk_base::SocketFactory* factory, talk_base::Network* network);
-
+ protected:
// Handles sending using the local UDP socket.
- virtual int SendTo(const void* data, size_t size,
- const talk_base::SocketAddress& addr, bool payload);
+ virtual int SendTo(const void* data, size_t size,
+ const talk_base::SocketAddress& remote_addr, bool payload);
// Dispatches the given packet to the port or connection as appropriate.
- void OnReadPacket(
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ void OnReadPacket(const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ talk_base::AsyncPacketSocket* socket);
- talk_base::AsyncPacketSocket* socket() { return socket_; }
-
-private:
+ private:
talk_base::AsyncPacketSocket* socket_;
int error_;
-
- // Receives packet signal from the local UDP Socket.
- void OnReadPacketSlot(
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr,
- talk_base::AsyncPacketSocket* socket);
};
-} // namespace cricket
+} // namespace cricket
-#endif // __UDPPORT_H__
+#endif // TALK_P2P_BASE_UDPPORT_H_
diff --git a/talk/p2p/client/Makefile.am b/talk/p2p/client/Makefile.am
deleted file mode 100755
index 11447f7..0000000
--- a/talk/p2p/client/Makefile.am
+++ /dev/null
@@ -1,13 +0,0 @@
-libcricketp2pclient_la_SOURCES = basicportallocator.cc \
- httpportallocator.cc \
- socketmonitor.cc
-
-noinst_HEADERS = basicportallocator.h \
- socketmonitor.h \
- sessionmanagertask.h \
- sessionsendtask.h \
- httpportallocator.h
-
-AM_CPPFLAGS = -I../../.. -DLINUX -DPOSIX -DINTERNAL_BUILD
-
-noinst_LTLIBRARIES = libcricketp2pclient.la
diff --git a/talk/p2p/client/basicportallocator.cc b/talk/p2p/client/basicportallocator.cc
old mode 100755
new mode 100644
index b7960f4..3762b34
--- a/talk/p2p/client/basicportallocator.cc
+++ b/talk/p2p/client/basicportallocator.cc
@@ -2,32 +2,31 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma warning(disable:4786)
-#endif
+#include <string>
+#include <vector>
#include "talk/base/common.h"
#include "talk/base/helpers.h"
@@ -41,6 +40,9 @@
#include "talk/p2p/base/tcpport.h"
#include "talk/p2p/base/udpport.h"
+using talk_base::CreateRandomId;
+using talk_base::CreateRandomString;
+
namespace {
const uint32 MSG_CONFIG_START = 1;
@@ -63,21 +65,21 @@
const float PREF_LOCAL_TCP = 0.8f;
const float PREF_RELAY = 0.5f;
-const float RELAY_PRIMARY_PREF_MODIFIER = 0.0f; // modifiers of the above constants
+// Modifiers of the above constants
+const float RELAY_PRIMARY_PREF_MODIFIER = 0.0f;
const float RELAY_BACKUP_PREF_MODIFIER = -0.2f;
-
// Returns the phase in which a given local candidate (or rather, the port that
// gave rise to that local candidate) would have been created.
int LocalCandidateToPhase(const cricket::Candidate& candidate) {
cricket::ProtocolType proto;
- bool result = cricket::StringToProto(candidate.protocol().c_str(), proto);
+ bool result = cricket::StringToProto(candidate.protocol().c_str(), &proto);
if (result) {
if (candidate.type() == cricket::LOCAL_PORT_TYPE) {
switch (proto) {
case cricket::PROTO_UDP: return PHASE_UDP;
case cricket::PROTO_TCP: return PHASE_TCP;
- default: assert(false);
+ default: ASSERT(false);
}
} else if (candidate.type() == cricket::STUN_PORT_TYPE) {
return PHASE_UDP;
@@ -86,54 +88,69 @@
case cricket::PROTO_UDP: return PHASE_RELAY;
case cricket::PROTO_TCP: return PHASE_TCP;
case cricket::PROTO_SSLTCP: return PHASE_SSLTCP;
- default: assert(false);
+ default: ASSERT(false);
}
} else {
- assert(false);
+ ASSERT(false);
}
} else {
- assert(false);
+ ASSERT(false);
}
- return PHASE_UDP; // reached only with assert failure
+ return PHASE_UDP; // reached only with assert failure
}
-const int SHAKE_MIN_DELAY = 45 * 1000; // 45 seconds
-const int SHAKE_MAX_DELAY = 90 * 1000; // 90 seconds
+const int SHAKE_MIN_DELAY = 45 * 1000; // 45 seconds
+const int SHAKE_MAX_DELAY = 90 * 1000; // 90 seconds
int ShakeDelay() {
int range = SHAKE_MAX_DELAY - SHAKE_MIN_DELAY + 1;
- return SHAKE_MIN_DELAY + cricket::CreateRandomId() % range;
+ return SHAKE_MIN_DELAY + CreateRandomId() % range;
}
-}
+} // namespace
namespace cricket {
+const uint32 DISABLE_ALL_PHASES =
+ PORTALLOCATOR_DISABLE_UDP
+ | PORTALLOCATOR_DISABLE_TCP
+ | PORTALLOCATOR_DISABLE_STUN
+ | PORTALLOCATOR_DISABLE_RELAY;
+
// Performs the allocation of ports, in a sequenced (timed) manner, for a given
// network and IP address.
class AllocationSequence : public talk_base::MessageHandler {
-public:
+ public:
AllocationSequence(BasicPortAllocatorSession* session,
talk_base::Network* network,
- PortConfiguration* config);
+ PortConfiguration* config,
+ uint32 flags);
~AllocationSequence();
- // Determines whether this sequence is operating on an equivalent network
- // setup to the one given.
- bool IsEquivalent(talk_base::Network* network);
+ // Disables the phases for a new sequence that this one already covers for an
+ // equivalent network setup.
+ void DisableEquivalentPhases(talk_base::Network* network,
+ PortConfiguration* config, uint32* flags);
// Starts and stops the sequence. When started, it will continue allocating
// new ports on its own timed schedule.
void Start();
void Stop();
- // MessageHandler:
+ // MessageHandler
void OnMessage(talk_base::Message* msg);
void EnableProtocol(ProtocolType proto);
bool ProtocolEnabled(ProtocolType proto) const;
-private:
+ private:
+ typedef std::vector<ProtocolType> ProtocolList;
+
+ void CreateUDPPorts();
+ void CreateTCPPorts();
+ void CreateStunPorts();
+ void CreateRelayPorts();
+
BasicPortAllocatorSession* session_;
talk_base::Network* network_;
uint32 ip_;
@@ -141,14 +158,8 @@
bool running_;
int step_;
int step_of_phase_[kNumPhases];
-
- typedef std::vector<ProtocolType> ProtocolList;
+ uint32 flags_;
ProtocolList protocols_;
-
- void CreateUDPPorts();
- void CreateTCPPorts();
- void CreateStunPorts();
- void CreateRelayPorts();
};
@@ -156,16 +167,22 @@
BasicPortAllocator::BasicPortAllocator(
talk_base::NetworkManager* network_manager)
- : network_manager_(network_manager), best_writable_phase_(-1),
- stun_address_(NULL), relay_address_(NULL) {
+ : network_manager_(network_manager), best_writable_phase_(-1) {
}
BasicPortAllocator::BasicPortAllocator(
- talk_base::NetworkManager* network_manager,
- talk_base::SocketAddress* stun_address,
- talk_base::SocketAddress *relay_address)
- : network_manager_(network_manager), best_writable_phase_(-1),
- stun_address_(stun_address), relay_address_(relay_address) {
+ talk_base::NetworkManager* network_manager,
+ const talk_base::SocketAddress& stun_address,
+ const talk_base::SocketAddress& relay_address_udp,
+ const talk_base::SocketAddress& relay_address_tcp,
+ const talk_base::SocketAddress& relay_address_ssl)
+ : network_manager_(network_manager),
+ stun_address_(stun_address),
+ relay_address_udp_(relay_address_udp),
+ relay_address_tcp_(relay_address_tcp),
+ relay_address_ssl_(relay_address_ssl),
+ best_writable_phase_(-1),
+ allow_tcp_listen_(true) {
}
BasicPortAllocator::~BasicPortAllocator() {
@@ -174,7 +191,7 @@
int BasicPortAllocator::best_writable_phase() const {
// If we are configured with an HTTP proxy, the best bet is to use the relay
if ((best_writable_phase_ == -1)
- && ((proxy().type == talk_base::PROXY_HTTPS)
+ && ((proxy().type == talk_base::PROXY_HTTPS)
|| (proxy().type == talk_base::PROXY_UNKNOWN))) {
return PHASE_RELAY;
}
@@ -182,9 +199,8 @@
}
PortAllocatorSession *BasicPortAllocator::CreateSession(
- const std::string &name, const std::string &session_type) {
- return new BasicPortAllocatorSession(this, name, session_type, stun_address_,
- relay_address_);
+ const std::string &name, const std::string &session_type) {
+ return new BasicPortAllocatorSession(this, name, session_type);
}
void BasicPortAllocator::AddWritablePhase(int phase) {
@@ -193,27 +209,13 @@
}
// BasicPortAllocatorSession
-
BasicPortAllocatorSession::BasicPortAllocatorSession(
BasicPortAllocator *allocator,
const std::string &name,
const std::string &session_type)
- : PortAllocatorSession(allocator->flags()), allocator_(allocator),
- name_(name), network_thread_(NULL), session_type_(session_type),
- allocation_started_(false), running_(false), stun_address_(NULL),
- relay_address_(NULL) {
-}
-
-BasicPortAllocatorSession::BasicPortAllocatorSession(
- BasicPortAllocator *allocator,
- const std::string &name,
- const std::string &session_type,
- talk_base::SocketAddress *stun_address,
- talk_base::SocketAddress *relay_address)
- : PortAllocatorSession(allocator->flags()), allocator_(allocator),
- name_(name), session_type_(session_type), network_thread_(NULL),
- allocation_started_(false), running_(false), stun_address_(stun_address),
- relay_address_(relay_address) {
+ : PortAllocatorSession(allocator->flags()), allocator_(allocator),
+ name_(name), session_type_(session_type), network_thread_(NULL),
+ allocation_started_(false), running_(false) {
}
BasicPortAllocatorSession::~BasicPortAllocatorSession() {
@@ -241,7 +243,7 @@
}
void BasicPortAllocatorSession::StartGetAllPorts() {
- assert(talk_base::Thread::Current() == network_thread_);
+ ASSERT(talk_base::Thread::Current() == network_thread_);
running_ = true;
if (allocation_started_)
network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE);
@@ -252,7 +254,7 @@
}
void BasicPortAllocatorSession::StopGetAllPorts() {
- assert(talk_base::Thread::Current() == network_thread_);
+ ASSERT(talk_base::Thread::Current() == network_thread_);
running_ = false;
network_thread_->Clear(this, MSG_ALLOCATE);
for (uint32 i = 0; i < sequences_.size(); ++i)
@@ -262,42 +264,46 @@
void BasicPortAllocatorSession::OnMessage(talk_base::Message *message) {
switch (message->message_id) {
case MSG_CONFIG_START:
- assert(talk_base::Thread::Current() == network_thread_);
+ ASSERT(talk_base::Thread::Current() == network_thread_);
GetPortConfigurations();
break;
case MSG_CONFIG_READY:
- assert(talk_base::Thread::Current() == network_thread_);
+ ASSERT(talk_base::Thread::Current() == network_thread_);
OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
break;
case MSG_ALLOCATE:
- assert(talk_base::Thread::Current() == network_thread_);
+ ASSERT(talk_base::Thread::Current() == network_thread_);
OnAllocate();
break;
case MSG_SHAKE:
- assert(talk_base::Thread::Current() == network_thread_);
+ ASSERT(talk_base::Thread::Current() == network_thread_);
OnShake();
break;
default:
- assert(false);
+ ASSERT(false);
}
}
void BasicPortAllocatorSession::GetPortConfigurations() {
- PortConfiguration* config = NULL;
- if (stun_address_ != NULL)
- config = new PortConfiguration(*stun_address_,
- CreateRandomString(16),
- CreateRandomString(16),
- "");
+ PortConfiguration* config = new PortConfiguration(allocator_->stun_address(),
+ CreateRandomString(16),
+ CreateRandomString(16),
+ "");
PortConfiguration::PortList ports;
- if (relay_address_ != NULL) {
- ports.push_back(ProtocolAddress(*relay_address_, PROTO_UDP));
- config->AddRelay(ports, RELAY_PRIMARY_PREF_MODIFIER);
- }
+ if (!allocator_->relay_address_udp().IsAny())
+ ports.push_back(ProtocolAddress(
+ allocator_->relay_address_udp(), PROTO_UDP));
+ if (!allocator_->relay_address_tcp().IsAny())
+ ports.push_back(ProtocolAddress(
+ allocator_->relay_address_tcp(), PROTO_TCP));
+ if (!allocator_->relay_address_ssl().IsAny())
+ ports.push_back(ProtocolAddress(
+ allocator_->relay_address_ssl(), PROTO_SSLTCP));
+ config->AddRelay(ports, RELAY_PRIMARY_PREF_MODIFIER);
ConfigReady(config);
}
@@ -315,11 +321,7 @@
}
void BasicPortAllocatorSession::AllocatePorts() {
- assert(talk_base::Thread::Current() == network_thread_);
-
- if (allocator_->proxy().type != talk_base::PROXY_NONE)
- Port::set_proxy(allocator_->user_agent(), allocator_->proxy());
-
+ ASSERT(talk_base::Thread::Current() == network_thread_);
network_thread_->Post(this, MSG_ALLOCATE);
}
@@ -327,22 +329,45 @@
// create a new sequence to create the appropriate ports.
void BasicPortAllocatorSession::OnAllocate() {
std::vector<talk_base::Network*> networks;
- allocator_->network_manager()->GetNetworks(networks);
- for (uint32 i = 0; i < networks.size(); ++i) {
- if (HasEquivalentSequence(networks[i]))
- continue;
+ if (!allocator_->network_manager()->GetNetworks(&networks)) {
+ LOG(LS_ERROR) << "Failed to enumerate networks";
+ } else if (networks.empty()) {
+ LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
+ } else {
+ for (uint32 i = 0; i < networks.size(); ++i) {
+ PortConfiguration* config = NULL;
+ if (configs_.size() > 0)
+ config = configs_.back();
- PortConfiguration* config = NULL;
- if (configs_.size() > 0)
- config = configs_.back();
+ uint32 sequence_flags = flags();
- AllocationSequence* sequence =
- new AllocationSequence(this, networks[i], config);
- if (running_)
- sequence->Start();
+ // Disables phases that are not specified in this config.
+ if (!config || config->stun_address.IsNil()) {
+ // No STUN ports specified in this config.
+ sequence_flags |= PORTALLOCATOR_DISABLE_STUN;
+ }
+ if (!config || config->relays.empty()) {
+ // No relay ports specified in this config.
+ sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
+ }
- sequences_.push_back(sequence);
+ // Disable phases that would only create ports equivalent to ones that we
+ // have already made.
+ DisableEquivalentPhases(networks[i], config, &sequence_flags);
+
+ if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
+ // New AllocationSequence would have nothing to do, so don't make it.
+ continue;
+ }
+
+ AllocationSequence* sequence =
+ new AllocationSequence(this, networks[i], config, sequence_flags);
+ if (running_)
+ sequence->Start();
+
+ sequences_.push_back(sequence);
+ }
}
allocation_started_ = true;
@@ -350,12 +375,12 @@
network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE);
}
-bool BasicPortAllocatorSession::HasEquivalentSequence(
- talk_base::Network* network) {
- for (uint32 i = 0; i < sequences_.size(); ++i)
- if (sequences_[i]->IsEquivalent(network))
- return true;
- return false;
+void BasicPortAllocatorSession::DisableEquivalentPhases(
+ talk_base::Network* network, PortConfiguration* config, uint32* flags) {
+ for (uint32 i = 0; i < sequences_.size() &&
+ (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES; ++i) {
+ sequences_[i]->DisableEquivalentPhases(network, config, flags);
+ }
}
void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
@@ -368,15 +393,23 @@
port->set_name(name_);
port->set_preference(pref);
port->set_generation(generation());
+ if (allocator_->proxy().type != talk_base::PROXY_NONE)
+ port->set_proxy(allocator_->user_agent(), allocator_->proxy());
+
PortData data;
data.port = port;
data.sequence = seq;
data.ready = false;
ports_.push_back(data);
- port->SignalAddressReady.connect(this, &BasicPortAllocatorSession::OnAddressReady);
- port->SignalConnectionCreated.connect(this, &BasicPortAllocatorSession::OnConnectionCreated);
- port->SignalDestroyed.connect(this, &BasicPortAllocatorSession::OnPortDestroyed);
+
+ port->SignalAddressReady.connect(this,
+ &BasicPortAllocatorSession::OnAddressReady);
+ port->SignalConnectionCreated.connect(this,
+ &BasicPortAllocatorSession::OnConnectionCreated);
+ port->SignalDestroyed.connect(this,
+ &BasicPortAllocatorSession::OnPortDestroyed);
LOG_J(LS_INFO, port) << "Added port to allocator";
+
if (prepare_address)
port->PrepareAddress();
if (running_)
@@ -384,10 +417,10 @@
}
void BasicPortAllocatorSession::OnAddressReady(Port *port) {
- assert(talk_base::Thread::Current() == network_thread_);
- std::vector<PortData>::iterator it
+ ASSERT(talk_base::Thread::Current() == network_thread_);
+ std::vector<PortData>::iterator it
= std::find(ports_.begin(), ports_.end(), port);
- assert(it != ports_.end());
+ ASSERT(it != ports_.end());
if (it->ready)
return;
it->ready = true;
@@ -396,9 +429,9 @@
// Only accumulate the candidates whose protocol has been enabled
std::vector<Candidate> candidates;
const std::vector<Candidate>& potentials = port->candidates();
- for (size_t i=0; i<potentials.size(); ++i) {
+ for (size_t i = 0; i < potentials.size(); ++i) {
ProtocolType pvalue;
- if (!StringToProto(potentials[i].protocol().c_str(), pvalue))
+ if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
continue;
if (it->sequence->ProtocolEnabled(pvalue)) {
candidates.push_back(potentials[i]);
@@ -409,17 +442,18 @@
}
}
-void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence * seq,
+void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence * seq,
ProtocolType proto) {
std::vector<Candidate> candidates;
- for (std::vector<PortData>::iterator it = ports_.begin(); it != ports_.end(); ++it) {
+ for (std::vector<PortData>::iterator it = ports_.begin();
+ it != ports_.end(); ++it) {
if (!it->ready || (it->sequence != seq))
continue;
const std::vector<Candidate>& potentials = it->port->candidates();
- for (size_t i=0; i<potentials.size(); ++i) {
+ for (size_t i = 0; i < potentials.size(); ++i) {
ProtocolType pvalue;
- if (!StringToProto(potentials[i].protocol().c_str(), pvalue))
+ if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
continue;
if (pvalue == proto) {
candidates.push_back(potentials[i]);
@@ -432,19 +466,19 @@
}
void BasicPortAllocatorSession::OnPortDestroyed(Port* port) {
- assert(talk_base::Thread::Current() == network_thread_);
+ ASSERT(talk_base::Thread::Current() == network_thread_);
std::vector<PortData>::iterator iter =
- find(ports_.begin(), ports_.end(), port);
- assert(iter != ports_.end());
+ std::find(ports_.begin(), ports_.end(), port);
+ ASSERT(iter != ports_.end());
ports_.erase(iter);
LOG_J(LS_INFO, port) << "Removed port from allocator ("
<< static_cast<int>(ports_.size()) << " remaining)";
}
-void BasicPortAllocatorSession::OnConnectionCreated(Port* port,
+void BasicPortAllocatorSession::OnConnectionCreated(Port* port,
Connection* conn) {
- conn->SignalStateChange.connect(this,
+ conn->SignalStateChange.connect(this,
&BasicPortAllocatorSession::OnConnectionStateChange);
}
@@ -474,8 +508,8 @@
}
}
- LOG(INFO) << ">>>>> Destroying " << (int)ports.size() << " ports and "
- << (int)connections.size() << " connections";
+ LOG(INFO) << ">>>>> Destroying " << ports.size() << " ports and "
+ << connections.size() << " connections";
for (size_t i = 0; i < connections.size(); ++i)
connections[i]->Destroy();
@@ -488,10 +522,10 @@
AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
talk_base::Network* network,
- PortConfiguration* config)
+ PortConfiguration* config,
+ uint32 flags)
: session_(session), network_(network), ip_(network->ip()), config_(config),
- running_(false), step_(0) {
-
+ running_(false), step_(0), flags_(flags) {
// All of the phases up until the best-writable phase so far run in step 0.
// The other phases follow sequentially in the steps after that. If there is
// no best-writable so far, then only phase 0 occurs in step 0.
@@ -508,8 +542,33 @@
session_->network_thread()->Clear(this);
}
-bool AllocationSequence::IsEquivalent(talk_base::Network* network) {
- return (network == network_) && (ip_ == network->ip());
+void AllocationSequence::DisableEquivalentPhases(talk_base::Network* network,
+ PortConfiguration* config, uint32* flags) {
+ if (!((network == network_) && (ip_ == network->ip()))) {
+ // Different network setup; nothing is equivalent.
+ return;
+ }
+
+ // Else turn off the stuff that we've already got covered.
+
+ // Every config implicitly specifies local, so turn that off right away.
+ *flags |= PORTALLOCATOR_DISABLE_UDP;
+ *flags |= PORTALLOCATOR_DISABLE_TCP;
+
+ if (config_ && config) {
+ if (config_->stun_address == config->stun_address) {
+ // Already got this STUN server covered.
+ *flags |= PORTALLOCATOR_DISABLE_STUN;
+ }
+ if (!config_->relays.empty()) {
+ // Already got relays covered.
+ // NOTE: This will even skip a _different_ set of relay servers if we
+ // were to be given one, but that never happens in our codebase. Should
+ // probably get rid of the list in PortConfiguration and just keep a
+ // single relay server in each one.
+ *flags |= PORTALLOCATOR_DISABLE_RELAY;
+ }
+ }
}
void AllocationSequence::Start() {
@@ -525,9 +584,9 @@
}
void AllocationSequence::OnMessage(talk_base::Message* msg) {
- assert(talk_base::Thread::Current() == session_->network_thread());
+ ASSERT(talk_base::Thread::Current() == session_->network_thread());
if (msg)
- assert(msg->message_id == MSG_ALLOCATION_PHASE);
+ ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);
const char* const PHASE_NAMES[kNumPhases] = {
"Udp", "Relay", "Tcp", "SslTcp"
@@ -583,7 +642,8 @@
}
bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
- for (ProtocolList::const_iterator it = protocols_.begin(); it != protocols_.end(); ++it) {
+ for (ProtocolList::const_iterator it = protocols_.begin();
+ it != protocols_.end(); ++it) {
if (*it == proto)
return true;
}
@@ -591,81 +651,105 @@
}
void AllocationSequence::CreateUDPPorts() {
- if (session_->flags() & PORTALLOCATOR_DISABLE_UDP)
+ if (flags_ & PORTALLOCATOR_DISABLE_UDP) {
+ LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
return;
+ }
- Port* port = new UDPPort(session_->network_thread(), NULL, network_,
- talk_base::SocketAddress(ip_, 0));
- session_->AddAllocatedPort(port, this, PREF_LOCAL_UDP);
+ Port* port = UDPPort::Create(session_->network_thread(), NULL, network_,
+ talk_base::SocketAddress(ip_, 0));
+ if (port)
+ session_->AddAllocatedPort(port, this, PREF_LOCAL_UDP);
}
void AllocationSequence::CreateTCPPorts() {
- if (session_->flags() & PORTALLOCATOR_DISABLE_TCP)
+ if (flags_ & PORTALLOCATOR_DISABLE_TCP) {
+ LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
return;
+ }
- Port* port = new TCPPort(session_->network_thread(), NULL, network_,
- talk_base::SocketAddress(ip_, 0));
- session_->AddAllocatedPort(port, this, PREF_LOCAL_TCP);
+ Port* port = TCPPort::Create(session_->network_thread(), NULL, network_,
+ talk_base::SocketAddress(ip_, 0),
+ session_->allocator()->allow_tcp_listen());
+ if (port)
+ session_->AddAllocatedPort(port, this, PREF_LOCAL_TCP);
}
void AllocationSequence::CreateStunPorts() {
- if (session_->flags() & PORTALLOCATOR_DISABLE_STUN)
+ if (flags_ & PORTALLOCATOR_DISABLE_STUN) {
+ LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
return;
+ }
- if (!config_ || config_->stun_address.IsAny())
+ // If BasicPortAllocatorSession::OnAllocate left STUN ports enabled then we
+ // ought to have an address for them here.
+ ASSERT(config_ && !config_->stun_address.IsNil());
+ if (!(config_ && !config_->stun_address.IsNil())) {
+ LOG(LS_WARNING)
+ << "AllocationSequence: No STUN server configured, skipping.";
return;
+ }
- Port* port = new StunPort(session_->network_thread(), NULL, network_,
- talk_base::SocketAddress(ip_, 0),
- config_->stun_address);
- session_->AddAllocatedPort(port, this, PREF_LOCAL_STUN);
+ Port* port = StunPort::Create(session_->network_thread(), NULL, network_,
+ talk_base::SocketAddress(ip_, 0),
+ config_->stun_address);
+ if (port)
+ session_->AddAllocatedPort(port, this, PREF_LOCAL_STUN);
}
void AllocationSequence::CreateRelayPorts() {
- if (session_->flags() & PORTALLOCATOR_DISABLE_RELAY)
- return;
+ if (flags_ & PORTALLOCATOR_DISABLE_RELAY) {
+ LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
+ return;
+ }
- if (!config_)
+ // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
+ // ought to have a relay list for them here.
+ ASSERT(config_ && !config_->relays.empty());
+ if (!(config_ && !config_->relays.empty())) {
+ LOG(LS_WARNING)
+ << "AllocationSequence: No relay server configured, skipping.";
return;
+ }
PortConfiguration::RelayList::const_iterator relay;
for (relay = config_->relays.begin();
- relay != config_->relays.end();
- ++relay) {
+ relay != config_->relays.end(); ++relay) {
+ RelayPort* port = RelayPort::Create(session_->network_thread(), NULL,
+ network_,
+ talk_base::SocketAddress(ip_, 0),
+ config_->username, config_->password,
+ config_->magic_cookie);
+ if (port) {
+ // Note: We must add the allocated port before we add addresses because
+ // the latter will create candidates that need name and preference
+ // settings. However, we also can't prepare the address (normally
+ // done by AddAllocatedPort) until we have these addresses. So we
+ // wait to do that until below.
+ session_->AddAllocatedPort(port, this, PREF_RELAY + relay->pref_modifier,
+ false);
- RelayPort *port = new RelayPort(session_->network_thread(), NULL, network_,
- talk_base::SocketAddress(ip_, 0),
- config_->username, config_->password,
- config_->magic_cookie);
- // Note: We must add the allocated port before we add addresses because
- // the latter will create candidates that need name and preference
- // settings. However, we also can't prepare the address (normally
- // done by AddAllocatedPort) until we have these addresses. So we
- // wait to do that until below.
- session_->AddAllocatedPort(port, this, PREF_RELAY + relay->pref_modifier,
- false);
+ // Add the addresses of this protocol.
+ PortConfiguration::PortList::const_iterator relay_port;
+ for (relay_port = relay->ports.begin();
+ relay_port != relay->ports.end();
+ ++relay_port) {
+ port->AddServerAddress(*relay_port);
+ port->AddExternalAddress(*relay_port);
+ }
- // Add the addresses of this protocol.
- PortConfiguration::PortList::const_iterator relay_port;
- for (relay_port = relay->ports.begin();
- relay_port != relay->ports.end();
- ++relay_port) {
- port->AddServerAddress(*relay_port);
- port->AddExternalAddress(*relay_port);
+ // Start fetching an address for this port.
+ port->PrepareAddress();
}
-
- // Start fetching an address for this port.
- port->PrepareAddress();
}
}
// PortConfiguration
-
PortConfiguration::PortConfiguration(const talk_base::SocketAddress& sa,
const std::string& un,
const std::string& pw,
const std::string& mc)
- : stun_address(sa), username(un), password(pw), magic_cookie(mc) {
+ : stun_address(sa), username(un), password(pw), magic_cookie(mc) {
}
void PortConfiguration::AddRelay(const PortList& ports, float pref_modifier) {
@@ -675,6 +759,16 @@
relays.push_back(relay);
}
+bool PortConfiguration::ResolveStunAddress() {
+ int err = 0;
+ if (!stun_address.ResolveIP(true, &err)) {
+ LOG(LS_ERROR) << "Unable to resolve STUN host "
+ << stun_address.hostname() << ". Error " << err;
+ return false;
+ }
+ return true;
+}
+
bool PortConfiguration::SupportsProtocol(
const PortConfiguration::RelayServer& relay, ProtocolType type) {
PortConfiguration::PortList::const_iterator relay_port;
@@ -687,4 +781,4 @@
return false;
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/client/basicportallocator.h b/talk/p2p/client/basicportallocator.h
old mode 100755
new mode 100644
index 0e3d313..0891e86
--- a/talk/p2p/client/basicportallocator.h
+++ b/talk/p2p/client/basicportallocator.h
@@ -2,85 +2,108 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _BASICPORTALLOCATOR_H_
-#define _BASICPORTALLOCATOR_H_
+#ifndef TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_
+#define TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_
-#include "talk/base/thread.h"
-#include "talk/base/messagequeue.h"
-#include "talk/base/network.h"
-#include "talk/p2p/base/portallocator.h"
#include <string>
#include <vector>
+#include "talk/base/messagequeue.h"
+#include "talk/base/network.h"
+#include "talk/base/thread.h"
+#include "talk/p2p/base/portallocator.h"
+
namespace cricket {
class BasicPortAllocator : public PortAllocator {
-public:
- BasicPortAllocator(talk_base::NetworkManager* network_manager);
- BasicPortAllocator(talk_base::NetworkManager* network_manager,
- talk_base::SocketAddress *stun_server, talk_base::SocketAddress *relay_server);
+ public:
+ explicit BasicPortAllocator(talk_base::NetworkManager* network_manager);
+ BasicPortAllocator(talk_base::NetworkManager* network_manager,
+ const talk_base::SocketAddress& stun_server,
+ const talk_base::SocketAddress& relay_server_udp,
+ const talk_base::SocketAddress& relay_server_tcp,
+ const talk_base::SocketAddress& relay_server_ssl);
virtual ~BasicPortAllocator();
talk_base::NetworkManager* network_manager() { return network_manager_; }
+ const talk_base::SocketAddress& stun_address() const {
+ return stun_address_;
+ }
+ const talk_base::SocketAddress& relay_address_udp() const {
+ return relay_address_udp_;
+ }
+ const talk_base::SocketAddress& relay_address_tcp() const {
+ return relay_address_tcp_;
+ }
+ const talk_base::SocketAddress& relay_address_ssl() const {
+ return relay_address_ssl_;
+ }
+
// Returns the best (highest preference) phase that has produced a port that
// produced a writable connection. If no writable connections have been
// produced, this returns -1.
int best_writable_phase() const;
- virtual PortAllocatorSession *CreateSession(const std::string &name, const std::string &session_type);
+ virtual PortAllocatorSession* CreateSession(const std::string& name,
+ const std::string& session_type);
// Called whenever a connection becomes writable with the argument being the
// phase that the corresponding port was created in.
void AddWritablePhase(int phase);
-private:
+ bool allow_tcp_listen() const {
+ return allow_tcp_listen_;
+ }
+ void set_allow_tcp_listen(bool allow_tcp_listen) {
+ allow_tcp_listen_ = allow_tcp_listen;
+ }
+
+ private:
talk_base::NetworkManager* network_manager_;
- talk_base::SocketAddress* stun_address_;
- talk_base::SocketAddress* relay_address_;
+ const talk_base::SocketAddress stun_address_;
+ const talk_base::SocketAddress relay_address_udp_;
+ const talk_base::SocketAddress relay_address_tcp_;
+ const talk_base::SocketAddress relay_address_ssl_;
int best_writable_phase_;
+ bool allow_tcp_listen_;
};
struct PortConfiguration;
class AllocationSequence;
-class BasicPortAllocatorSession: public PortAllocatorSession,
+class BasicPortAllocatorSession : public PortAllocatorSession,
public talk_base::MessageHandler {
-public:
- BasicPortAllocatorSession(BasicPortAllocator *allocator,
- const std::string &name,
- const std::string &session_type);
- BasicPortAllocatorSession(BasicPortAllocator *allocator,
- const std::string &name,
- const std::string &session_type,
- talk_base::SocketAddress *stun_address,
- talk_base::SocketAddress *relay_address);
+ public:
+ BasicPortAllocatorSession(BasicPortAllocator* allocator,
+ const std::string& name,
+ const std::string& session_type);
~BasicPortAllocatorSession();
- BasicPortAllocator* allocator() { return allocator_; }
+ virtual BasicPortAllocator* allocator() { return allocator_; }
const std::string& name() const { return name_; }
const std::string& session_type() const { return session_type_; }
talk_base::Thread* network_thread() { return network_thread_; }
@@ -90,7 +113,7 @@
virtual void StopGetAllPorts();
virtual bool IsGettingAllPorts() { return running_; }
-protected:
+ protected:
// Starts the process of getting the port configurations.
virtual void GetPortConfigurations();
@@ -101,39 +124,38 @@
// MessageHandler. Can be overriden if message IDs do not conflict.
virtual void OnMessage(talk_base::Message *message);
-private:
+ private:
void OnConfigReady(PortConfiguration* config);
void OnConfigTimeout();
void AllocatePorts();
void OnAllocate();
- bool HasEquivalentSequence(talk_base::Network* network);
- void AddAllocatedPort(Port* port, AllocationSequence * seq, float pref,
+ void DisableEquivalentPhases(talk_base::Network* network,
+ PortConfiguration* config, uint32* flags);
+ void AddAllocatedPort(Port* port, AllocationSequence* seq, float pref,
bool prepare_address = true);
- void OnAddressReady(Port *port);
- void OnProtocolEnabled(AllocationSequence * seq, ProtocolType proto);
+ void OnAddressReady(Port* port);
+ void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto);
void OnPortDestroyed(Port* port);
void OnConnectionCreated(Port* port, Connection* conn);
void OnConnectionStateChange(Connection* conn);
void OnShake();
- BasicPortAllocator *allocator_;
+ BasicPortAllocator* allocator_;
std::string name_;
std::string session_type_;
talk_base::Thread* network_thread_;
bool configuration_done_;
bool allocation_started_;
- bool running_; // set when StartGetAllPorts is called
+ bool running_; // set when StartGetAllPorts is called
std::vector<PortConfiguration*> configs_;
std::vector<AllocationSequence*> sequences_;
- talk_base::SocketAddress *stun_address_;
- talk_base::SocketAddress *relay_address_;
struct PortData {
- Port * port;
- AllocationSequence * sequence;
+ Port* port;
+ AllocationSequence* sequence;
bool ready;
- bool operator==(Port * rhs) const { return (port == rhs); }
+ bool operator==(Port* rhs) const { return (port == rhs); }
};
std::vector<PortData> ports_;
@@ -150,8 +172,8 @@
typedef std::vector<ProtocolAddress> PortList;
struct RelayServer {
PortList ports;
- float pref_modifier; // added to the protocol modifier to get the
- // preference for this particular server
+ float pref_modifier; // added to the protocol modifier to get the
+ // preference for this particular server
};
typedef std::vector<RelayServer> RelayList;
@@ -165,11 +187,13 @@
// Adds another relay server, with the given ports and modifier, to the list.
void AddRelay(const PortList& ports, float pref_modifier);
+ bool ResolveStunAddress();
+
// Determines whether the given relay server supports the given protocol.
static bool SupportsProtocol(const PortConfiguration::RelayServer& relay,
ProtocolType type);
};
-} // namespace cricket
+} // namespace cricket
-#endif // _BASICPORTALLOCATOR_H_
+#endif // TALK_P2P_CLIENT_BASICPORTALLOCATOR_H_
diff --git a/talk/p2p/client/httpportallocator.cc b/talk/p2p/client/httpportallocator.cc
old mode 100755
new mode 100644
index de8edaf..c9cce12
--- a/talk/p2p/client/httpportallocator.cc
+++ b/talk/p2p/client/httpportallocator.cc
@@ -1,31 +1,46 @@
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma warning(disable:4786)
-#endif
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/p2p/client/httpportallocator.h"
+
+#include <map>
+
#include "talk/base/asynchttprequest.h"
#include "talk/base/basicdefs.h"
#include "talk/base/common.h"
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
+#include "talk/base/nethelpers.h"
#include "talk/base/signalthread.h"
-#include "talk/p2p/client/httpportallocator.h"
-#include <cassert>
-#include <ctime>
namespace {
-// Records the port on the hosts that will receive HTTP requests.
-const uint16 kHostPort = 80;
-
-// Records the URL that we will GET in order to create a session.
-const std::string kCreateSessionURL = "/create_session";
-
-// The number of HTTP requests we should attempt before giving up.
-const size_t kNumRetries = 5;
-
-// The delay before we give up on an HTTP request;
-const int TIMEOUT = 5 * 1000; // 5 seconds
-
-const uint32 MSG_TIMEOUT = 100; // must not conflict with BasicPortAllocator.cpp
+const uint32 MSG_TIMEOUT = 100; // must not conflict
+ // with BasicPortAllocator.cpp
// Helper routine to remove whitespace from the ends of a string.
void Trim(std::string& str) {
@@ -35,18 +50,17 @@
return;
}
- size_t last = str.find_last_not_of(" \t\r\n");
- ASSERT(last != std::string::npos);
+ ASSERT(str.find_last_not_of(" \t\r\n") != std::string::npos);
}
// Parses the lines in the result of the HTTP request that are of the form
// 'a=b' and returns them in a map.
-typedef std::map<std::string,std::string> StringMap;
+typedef std::map<std::string, std::string> StringMap;
void ParseMap(const std::string& string, StringMap& map) {
size_t start_of_line = 0;
size_t end_of_line = 0;
- for (;;) { // for each line
+ for (;;) { // for each line
start_of_line = string.find_first_not_of("\r\n", end_of_line);
if (start_of_line == std::string::npos)
break;
@@ -71,85 +85,129 @@
}
}
-}
+} // namespace
namespace cricket {
// HttpPortAllocator
-HttpPortAllocator::HttpPortAllocator(talk_base::NetworkManager* network_manager, const std::string &user_agent)
- : BasicPortAllocator(network_manager), agent_(user_agent) {
- relay_hosts_.push_back("relay.l.google.com");
- stun_hosts_.push_back(talk_base::SocketAddress("stun.l.google.com",19302));
+const int HttpPortAllocator::kHostPort = 80;
+const int HttpPortAllocator::kNumRetries = 5;
+
+const std::string HttpPortAllocator::kCreateSessionURL = "/create_session";
+
+HttpPortAllocator::HttpPortAllocator(talk_base::NetworkManager* network_manager,
+ const std::string &user_agent)
+ : BasicPortAllocator(network_manager), agent_(user_agent) {
+ relay_hosts_.push_back("relay.google.com");
+ stun_hosts_.push_back(
+ talk_base::SocketAddress("stun.l.google.com", 19302));
}
HttpPortAllocator::~HttpPortAllocator() {
}
-PortAllocatorSession *HttpPortAllocator::CreateSession(const std::string &name, const std::string &session_type) {
- return new HttpPortAllocatorSession(this, name, session_type, stun_hosts_, relay_hosts_, relay_token_, agent_);
+PortAllocatorSession *HttpPortAllocator::CreateSession(
+ const std::string& name, const std::string& session_type) {
+ return new HttpPortAllocatorSession(this, name, session_type, stun_hosts_,
+ relay_hosts_, relay_token_, agent_);
}
// HttpPortAllocatorSession
-HttpPortAllocatorSession::HttpPortAllocatorSession(HttpPortAllocator* allocator, const std::string &name,
- const std::string &session_type,
- const std::vector<talk_base::SocketAddress> &stun_hosts,
- const std::vector<std::string> &relay_hosts,
- const std::string &relay_token,
- const std::string &user_agent)
- : BasicPortAllocatorSession(allocator, name, session_type),
- attempts_(0), relay_hosts_(relay_hosts), stun_hosts_(stun_hosts), relay_token_(relay_token), agent_(user_agent) {
+HttpPortAllocatorSession::HttpPortAllocatorSession(
+ HttpPortAllocator* allocator, const std::string &name,
+ const std::string& session_type,
+ const std::vector<talk_base::SocketAddress>& stun_hosts,
+ const std::vector<std::string>& relay_hosts,
+ const std::string& relay_token,
+ const std::string& user_agent)
+ : BasicPortAllocatorSession(allocator, name, session_type),
+ relay_hosts_(relay_hosts), stun_hosts_(stun_hosts),
+ relay_token_(relay_token), agent_(user_agent), attempts_(0) {
}
void HttpPortAllocatorSession::GetPortConfigurations() {
+ // Creating relay sessions can take time and is done asynchronously.
+ // Creating stun sessions could also take time and could be done aysnc also,
+ // but for now is done here and added to the initial config. Note any later
+ // configs will have unresolved stun ips and will be discarded by the
+ // AllocationSequence.
+ PortConfiguration* config = new PortConfiguration(stun_hosts_[0], "", "", "");
+ ConfigReady(config);
+ TryCreateRelaySession();
+}
- if (attempts_ == kNumRetries) {
- LOG(WARNING) << "HttpPortAllocator: maximum number of requests reached";
+void HttpPortAllocatorSession::TryCreateRelaySession() {
+ if (attempts_ == HttpPortAllocator::kNumRetries) {
+ LOG(LS_ERROR) << "HttpPortAllocator: maximum number of requests reached; "
+ << "giving up on relay.";
+ return;
+ }
+
+ if (relay_hosts_.size() == 0) {
+ LOG(LS_ERROR) << "HttpPortAllocator: no relay hosts configured.";
return;
}
// Choose the next host to try.
std::string host = relay_hosts_[attempts_ % relay_hosts_.size()];
attempts_++;
- LOG(INFO) << "HTTPPortAllocator: sending to host " << host;
+ LOG(LS_INFO) << "HTTPPortAllocator: sending to relay host " << host;
+ if (relay_token_.empty()) {
+ LOG(LS_WARNING) << "No relay auth token found.";
+ }
+ SendSessionRequest(host, HttpPortAllocator::kHostPort);
+}
+
+void HttpPortAllocatorSession::SendSessionRequest(const std::string& host,
+ int port) {
// Initiate an HTTP request to create a session through the chosen host.
-
- talk_base::AsyncHttpRequest* request = new talk_base::AsyncHttpRequest(agent_);
- request->SignalWorkDone.connect(this, &HttpPortAllocatorSession::OnRequestDone);
+ talk_base::AsyncHttpRequest* request =
+ new talk_base::AsyncHttpRequest(agent_);
+ request->SignalWorkDone.connect(this,
+ &HttpPortAllocatorSession::OnRequestDone);
- request->set_proxy(allocator()->proxy());
+ request->set_proxy(allocator()->proxy());
request->response().document.reset(new talk_base::MemoryStream);
request->request().verb = talk_base::HV_GET;
- request->request().path = kCreateSessionURL;
+ request->request().path = HttpPortAllocator::kCreateSessionURL;
request->request().addHeader("X-Talk-Google-Relay-Auth", relay_token_, true);
request->request().addHeader("X-Google-Relay-Auth", relay_token_, true);
request->request().addHeader("X-Session-Type", session_type(), true);
+ request->request().addHeader("X-Stream-Type", name(), true);
request->set_host(host);
- request->set_port(kHostPort);
- request->Start();
+ request->set_port(port);
+ request->Start();
request->Release();
}
void HttpPortAllocatorSession::OnRequestDone(talk_base::SignalThread* data) {
- talk_base::AsyncHttpRequest *request =
- static_cast<talk_base::AsyncHttpRequest*> (data);
+ talk_base::AsyncHttpRequest* request =
+ static_cast<talk_base::AsyncHttpRequest*>(data);
if (request->response().scode != 200) {
- LOG(WARNING) << "HTTPPortAllocator: request "
- << " received error " << request->response().scode;
- GetPortConfigurations();
+ LOG(LS_WARNING) << "HTTPPortAllocator: request "
+ << " received error " << request->response().scode;
+ TryCreateRelaySession();
return;
}
- LOG(INFO) << "HTTPPortAllocator: request succeeded";
+ LOG(LS_INFO) << "HTTPPortAllocator: request succeeded";
- StringMap map;
- talk_base::MemoryStream *stream = static_cast<talk_base::MemoryStream*>(request->response().document.get());
+ talk_base::MemoryStream* stream =
+ static_cast<talk_base::MemoryStream*>(request->response().document.get());
stream->Rewind();
size_t length;
stream->GetSize(&length);
std::string resp = std::string(stream->GetBuffer(), length);
- ParseMap(resp, map);
+ ReceiveSessionResponse(resp);
+}
+
+void HttpPortAllocatorSession::ReceiveSessionResponse(
+ const std::string& response) {
+
+ StringMap map;
+ ParseMap(response, map);
std::string username = map["username"];
std::string password = map["password"];
@@ -182,4 +240,4 @@
ConfigReady(config);
}
-} // namespace cricket
+} // namespace cricket
diff --git a/talk/p2p/client/httpportallocator.h b/talk/p2p/client/httpportallocator.h
old mode 100755
new mode 100644
index 96f3e72..d695062
--- a/talk/p2p/client/httpportallocator.h
+++ b/talk/p2p/client/httpportallocator.h
@@ -1,26 +1,89 @@
-#ifndef _HTTPPORTALLOCATOR_H_
-#define _HTTPPORTALLOCATOR_H_
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TALK_P2P_CLIENT_HTTPPORTALLOCATOR_H_
+#define TALK_P2P_CLIENT_HTTPPORTALLOCATOR_H_
+
+#include <string>
+#include <vector>
#include "talk/p2p/client/basicportallocator.h"
namespace talk_base {
- class SignalThread;
+class SignalThread;
}
namespace cricket {
class HttpPortAllocator : public BasicPortAllocator {
-public:
- HttpPortAllocator(talk_base::NetworkManager* network_manager, const std::string &user_agent);
+ public:
+ // Records the port on the hosts that will receive HTTP requests.
+ static const int kHostPort;
+
+ // The number of HTTP requests we should attempt before giving up.
+ static const int kNumRetries;
+
+ // Records the URL that we will GET in order to create a session.
+ static const std::string kCreateSessionURL;
+
+ HttpPortAllocator(talk_base::NetworkManager* network_manager,
+ const std::string& user_agent);
virtual ~HttpPortAllocator();
- virtual PortAllocatorSession *CreateSession(const std::string &name,
- const std::string &session_type);
- void SetStunHosts(const std::vector<talk_base::SocketAddress> &hosts) {stun_hosts_ = hosts;}
- void SetRelayHosts(const std::vector<std::string> &hosts) {relay_hosts_ = hosts;}
- void SetRelayToken(const std::string &relay) {relay_token_ = relay;}
- std::string relay_token() const { return relay_token_; }
-private:
+ virtual PortAllocatorSession* CreateSession(const std::string& name,
+ const std::string& session_type);
+ void SetStunHosts(const std::vector<talk_base::SocketAddress>& hosts) {
+ if (!hosts.empty()) {
+ stun_hosts_ = hosts;
+ }
+ }
+ void SetRelayHosts(const std::vector<std::string>& hosts) {
+ if (!hosts.empty()) {
+ relay_hosts_ = hosts;
+ }
+ }
+ void SetRelayToken(const std::string& relay) { relay_token_ = relay; }
+
+ const std::vector<talk_base::SocketAddress>& stun_hosts() const {
+ return stun_hosts_;
+ }
+
+ const std::vector<std::string>& relay_hosts() const {
+ return relay_hosts_;
+ }
+
+ const std::string& relay_token() const {
+ return relay_token_;
+ }
+
+ const std::string& user_agent() const {
+ return agent_;
+ }
+
+ private:
std::vector<talk_base::SocketAddress> stun_hosts_;
std::vector<std::string> relay_hosts_;
std::string relay_token_;
@@ -31,31 +94,41 @@
class HttpPortAllocatorSession : public BasicPortAllocatorSession {
public:
- HttpPortAllocatorSession(HttpPortAllocator *allocator,
- const std::string &name,
- const std::string &session_type,
- const std::vector<talk_base::SocketAddress> &stun_hosts,
- const std::vector<std::string> &relay_hosts,
- const std::string &relay,
- const std::string &agent);
- ~HttpPortAllocatorSession() {};
+ HttpPortAllocatorSession(
+ HttpPortAllocator* allocator,
+ const std::string& name,
+ const std::string& session_type,
+ const std::vector<talk_base::SocketAddress>& stun_hosts,
+ const std::vector<std::string>& relay_hosts,
+ const std::string& relay,
+ const std::string& agent);
+ virtual ~HttpPortAllocatorSession() {}
-protected:
+ const std::string& relay_token() const {
+ return relay_token_;
+ }
+ virtual void SendSessionRequest(const std::string& host, int port);
+ virtual void ReceiveSessionResponse(const std::string& response);
+
+ protected:
virtual void GetPortConfigurations();
+ void TryCreateRelaySession();
-private:
+ private:
+ virtual HttpPortAllocator* allocator() {
+ return static_cast<HttpPortAllocator*>(
+ BasicPortAllocatorSession::allocator());
+ }
+
+ void OnRequestDone(talk_base::SignalThread* request);
+
std::vector<std::string> relay_hosts_;
std::vector<talk_base::SocketAddress> stun_hosts_;
std::string relay_token_;
std::string agent_;
-
- void OnRequestDone(talk_base::SignalThread* request);
- HttpPortAllocator* http_allocator() {
- return static_cast<HttpPortAllocator*>(allocator());
- }
int attempts_;
};
-} // namespace cricket
+} // namespace cricket
-#endif // _XMPPPORTALLOCATOR_H_
+#endif // TALK_P2P_CLIENT_HTTPPORTALLOCATOR_H_
diff --git a/talk/p2p/client/sessionmanagertask.h b/talk/p2p/client/sessionmanagertask.h
old mode 100755
new mode 100644
index 2a05357..2026bf6
--- a/talk/p2p/client/sessionmanagertask.h
+++ b/talk/p2p/client/sessionmanagertask.h
@@ -40,7 +40,7 @@
class SessionManagerTask : public buzz::XmppTask {
public:
- SessionManagerTask(Task *parent, SessionManager *session_manager)
+ SessionManagerTask(TaskParent *parent, SessionManager *session_manager)
: buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE) {
session_manager_ = session_manager;
}
@@ -78,7 +78,8 @@
private:
SessionManager* session_manager_;
- void OnOutgoingMessage(const buzz::XmlElement* stanza) {
+ void OnOutgoingMessage(SessionManager* manager,
+ const buzz::XmlElement* stanza) {
cricket::SessionSendTask* sender =
new cricket::SessionSendTask(GetParent(), session_manager_);
sender->Send(stanza);
diff --git a/talk/p2p/client/sessionsendtask.h b/talk/p2p/client/sessionsendtask.h
old mode 100755
new mode 100644
index 3beb9d4..7bdc067
--- a/talk/p2p/client/sessionsendtask.h
+++ b/talk/p2p/client/sessionsendtask.h
@@ -45,7 +45,7 @@
class SessionSendTask : public buzz::XmppTask {
public:
- SessionSendTask(Task *parent, SessionManager *session_manager)
+ SessionSendTask(TaskParent *parent, SessionManager *session_manager)
: buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE),
session_manager_(session_manager) {
set_timeout_seconds(15);
diff --git a/talk/p2p/client/socketmonitor.cc b/talk/p2p/client/socketmonitor.cc
old mode 100755
new mode 100644
index 88d37ce..bf32d84
--- a/talk/p2p/client/socketmonitor.cc
+++ b/talk/p2p/client/socketmonitor.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -35,12 +35,11 @@
const uint32 MSG_MONITOR_STOP = 3;
const uint32 MSG_MONITOR_SIGNAL = 4;
-SocketMonitor::SocketMonitor(Session* session,
- TransportChannel* channel,
- talk_base::Thread *monitor_thread) {
- session_ = session;
+SocketMonitor::SocketMonitor(TransportChannel* channel,
+ talk_base::Thread* worker_thread,
+ talk_base::Thread* monitor_thread) {
channel_ = channel;
- channel_thread_ = session->session_manager()->worker_thread();
+ channel_thread_ = worker_thread;
monitoring_thread_ = monitor_thread;
monitoring_ = false;
}
@@ -115,7 +114,6 @@
talk_base::CritScope cs(&crit_);
// Gather connection infos
-
P2PTransportChannel* p2p_channel = GetP2PChannel();
if (p2p_channel != NULL) {
connection_infos_.clear();
@@ -125,9 +123,12 @@
Connection *connection = *it;
ConnectionInfo info;
info.best_connection = p2p_channel->best_connection() == connection;
- info.readable = connection->read_state() == Connection::STATE_READABLE;
- info.writable = connection->write_state() == Connection::STATE_WRITABLE;
- info.timeout = connection->write_state() == Connection::STATE_WRITE_TIMEOUT;
+ info.readable =
+ (connection->read_state() == Connection::STATE_READABLE);
+ info.writable =
+ (connection->write_state() == Connection::STATE_WRITABLE);
+ info.timeout =
+ (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
info.new_connection = !connection->reported();
connection->set_reported(true);
info.rtt = connection->rtt();
@@ -138,7 +139,7 @@
info.local_candidate = connection->local_candidate();
info.remote_candidate = connection->remote_candidate();
info.est_quality = connection->port()->network()->quality();
- info.key = reinterpret_cast<void *>(connection);
+ info.key = connection;
connection_infos_.push_back(info);
}
}
@@ -150,15 +151,4 @@
channel_thread_->PostDelayed(rate_, this, MSG_MONITOR_POLL);
}
-P2PTransportChannel* SocketMonitor::GetP2PChannel() {
- if (session_->transport() == NULL)
- return NULL;
- if (session_->transport()->name() != kNsP2pTransport)
- return NULL;
- TransportChannelImpl* impl = session_->GetImplementation(channel_);
- if (impl == NULL)
- return NULL;
- return static_cast<P2PTransportChannel*>(impl);
-}
-
}
diff --git a/talk/p2p/client/socketmonitor.h b/talk/p2p/client/socketmonitor.h
old mode 100755
new mode 100644
index ced86b8..cf29d9d
--- a/talk/p2p/client/socketmonitor.h
+++ b/talk/p2p/client/socketmonitor.h
@@ -2,39 +2,39 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _SOCKETMONITOR_H_
-#define _SOCKETMONITOR_H_
+#ifndef TALK_P2P_CLIENT_SOCKETMONITOR_H_
+#define TALK_P2P_CLIENT_SOCKETMONITOR_H_
-#include "talk/base/thread.h"
-#include "talk/base/sigslot.h"
+#include <vector>
+
#include "talk/base/criticalsection.h"
-#include "talk/p2p/base/session.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/thread.h"
#include "talk/p2p/base/p2ptransportchannel.h"
#include "talk/p2p/base/port.h"
-#include <vector>
namespace cricket {
@@ -55,11 +55,12 @@
void *key;
};
-class SocketMonitor : public talk_base::MessageHandler,
+class SocketMonitor : public talk_base::MessageHandler,
public sigslot::has_slots<> {
-public:
- SocketMonitor(Session* session, TransportChannel* channel,
- talk_base::Thread *monitor_thread);
+ public:
+ SocketMonitor(TransportChannel* channel,
+ talk_base::Thread* worker_thread,
+ talk_base::Thread* monitor_thread);
~SocketMonitor();
void Start(int cms);
@@ -70,14 +71,13 @@
sigslot::signal2<SocketMonitor *,
const std::vector<ConnectionInfo> &> SignalUpdate;
-protected:
+ protected:
+ P2PTransportChannel* GetP2PChannel() { return channel_->GetP2PChannel(); }
void OnMessage(talk_base::Message *message);
void OnConnectionMonitor(P2PTransportChannel* channel);
void PollSocket(bool poll);
- P2PTransportChannel* GetP2PChannel();
std::vector<ConnectionInfo> connection_infos_;
- Session* session_;
TransportChannel* channel_;
talk_base::Thread* channel_thread_;
talk_base::Thread* monitoring_thread_;
@@ -86,6 +86,6 @@
bool monitoring_;
};
-}
+} // namespace cricket
-#endif // _SOCKETMONITOR_H_
+#endif // TALK_P2P_CLIENT_SOCKETMONITOR_H_
diff --git a/talk/pkg.m4 b/talk/pkg.m4
deleted file mode 100755
index c80e0ac..0000000
--- a/talk/pkg.m4
+++ /dev/null
@@ -1,57 +0,0 @@
-
-dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
-dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
-dnl also defines GSTUFF_PKG_ERRORS on error
-AC_DEFUN(PKG_CHECK_MODULES, [
- succeeded=no
-
- if test -z "$PKG_CONFIG"; then
- AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
- fi
-
- if test "$PKG_CONFIG" = "no" ; then
- echo "*** The pkg-config script could not be found. Make sure it is"
- echo "*** in your path, or set the PKG_CONFIG environment variable"
- echo "*** to the full path to pkg-config."
- echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
- else
- PKG_CONFIG_MIN_VERSION=0.9.0
- if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
- AC_MSG_CHECKING(for $2)
-
- if $PKG_CONFIG --exists "$2" ; then
- AC_MSG_RESULT(yes)
- succeeded=yes
-
- AC_MSG_CHECKING($1_CFLAGS)
- $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
- AC_MSG_RESULT($$1_CFLAGS)
-
- AC_MSG_CHECKING($1_LIBS)
- $1_LIBS=`$PKG_CONFIG --libs "$2"`
- AC_MSG_RESULT($$1_LIBS)
- else
- $1_CFLAGS=""
- $1_LIBS=""
- ## If we have a custom action on failure, don't print errors, but
- ## do set a variable so people can do so.
- $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
- ifelse([$4], ,echo $$1_PKG_ERRORS,)
- fi
-
- AC_SUBST($1_CFLAGS)
- AC_SUBST($1_LIBS)
- else
- echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
- echo "*** See http://www.freedesktop.org/software/pkgconfig"
- fi
- fi
-
- if test $succeeded = yes; then
- ifelse([$3], , :, [$3])
- else
- ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
- fi
-])
-
-
diff --git a/talk/session/Makefile.am b/talk/session/Makefile.am
deleted file mode 100755
index e55f7f1..0000000
--- a/talk/session/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-if PHONE
-SUBDIRS = phone tunnel fileshare
-else
-SUBDIRS = tunnel fileshare
-endif
diff --git a/talk/session/fileshare/Makefile.am b/talk/session/fileshare/Makefile.am
deleted file mode 100755
index a6eebf6..0000000
--- a/talk/session/fileshare/Makefile.am
+++ /dev/null
@@ -1,7 +0,0 @@
-libcricketsessionfileshare_la_SOURCES = fileshare.cc
-
-noinst_HEADERS = fileshare.h
-
-AM_CPPFLAGS := -DPOSIX
-noinst_LTLIBRARIES = libcricketsessionfileshare.la
-
diff --git a/talk/session/fileshare/fileshare.cc b/talk/session/fileshare/fileshare.cc
deleted file mode 100755
index 863c352..0000000
--- a/talk/session/fileshare/fileshare.cc
+++ /dev/null
@@ -1,1313 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2006, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "talk/session/fileshare/fileshare.h"
-
-#include "talk/base/httpcommon-inl.h"
-
-#include "talk/base/fileutils.h"
-#include "talk/base/streamutils.h"
-#include "talk/base/event.h"
-#include "talk/base/helpers.h"
-#include "talk/base/httpclient.h"
-#include "talk/base/httpserver.h"
-#include "talk/base/pathutils.h"
-#include "talk/base/socketstream.h"
-#include "talk/base/stringdigest.h"
-#include "talk/base/stringencode.h"
-#include "talk/base/stringutils.h"
-#include "talk/base/tarstream.h"
-#include "talk/base/thread.h"
-#include "talk/session/tunnel/pseudotcpchannel.h"
-#include "talk/session/tunnel/tunnelsessionclient.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// <description xmlns="http://www.google.com/session/share">
-// <manifest>
-// <file size='341'>
-// <name>foo.txt</name>
-// </file>
-// <file size='51321'>
-// <name>foo.jpg</name>
-// <image width='480' height='320'/>
-// </file>
-// <folder>
-// <name>stuff</name>
-// </folder>
-// </manifest>
-// <protocol>
-// <http>
-// <url name='source-path'>/temporary/23A53F01/</url>
-// <url name='preview-path'>/temporary/90266EA1/</url>
-// </http>
-// <raw/>
-// </protocol>
-// </description>
-// <p:transport xmns:p="p2p"/>
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Constants and private functions
-///////////////////////////////////////////////////////////////////////////////
-
-const std::string NS_GOOGLE_SHARE("http://www.google.com/session/share");
-
-namespace {
-
-const buzz::QName QN_SHARE_DESCRIPTION(true, NS_GOOGLE_SHARE, "description");
-const buzz::QName QN_SHARE_MANIFEST(true, NS_GOOGLE_SHARE, "manifest");
-const buzz::QName QN_SHARE_FOLDER(true, NS_GOOGLE_SHARE, "folder");
-const buzz::QName QN_SHARE_FILE(true, NS_GOOGLE_SHARE, "file");
-const buzz::QName QN_SHARE_NAME(true, NS_GOOGLE_SHARE, "name");
-const buzz::QName QN_SHARE_IMAGE(true, NS_GOOGLE_SHARE, "image");
-const buzz::QName QN_SHARE_PROTOCOL(true, NS_GOOGLE_SHARE, "protocol");
-const buzz::QName QN_SHARE_HTTP(true, NS_GOOGLE_SHARE, "http");
-const buzz::QName QN_SHARE_URL(true, NS_GOOGLE_SHARE, "url");
-const buzz::QName QN_SHARE_CHANNEL(true, NS_GOOGLE_SHARE, "channel");
-const buzz::QName QN_SHARE_COMPLETE(true, NS_GOOGLE_SHARE, "complete");
-
-const buzz::QName QN_SIZE(true, buzz::STR_EMPTY, "size");
-const buzz::QName QN_WIDTH(true, buzz::STR_EMPTY, "width");
-const buzz::QName QN_HEIGHT(true, buzz::STR_EMPTY, "height");
-
-const std::string kHttpSourcePath("source-path");
-const std::string kHttpPreviewPath("preview-path");
-
-const size_t kMinImageSize = 16U;
-const size_t kMaxImageSize = 0x8000U; // (32k)
-const size_t kMaxPreviewSize = 1024;
-// Wait 10 seconds to see if any new proxies get established
-const uint32 kProxyWait = 10000;
-
-const int MSG_RETRY = 1;
-const uint32 kFileTransferEnableRetryMs = 1000 * 60 * 4; // 4 minutes
-
-const std::string MIME_OCTET_STREAM("application/octet-stream");
-
-enum {
- MSG_PROXY_WAIT,
-};
-
-bool AllowedImageDimensions(size_t width, size_t height) {
- return (width >= kMinImageSize) && (width <= kMaxImageSize)
- && (height >= kMinImageSize) && (height <= kMaxImageSize);
-}
-
-} // anon namespace
-
-namespace cricket {
-
-///////////////////////////////////////////////////////////////////////////////
-// FileShareManifest
-///////////////////////////////////////////////////////////////////////////////
-
-void
-FileShareManifest::AddFile(const std::string& name, size_t size) {
- Item i = { T_FILE, name, size };
- items_.push_back(i);
-}
-
-void
-FileShareManifest::AddImage(const std::string& name, size_t size,
- size_t width, size_t height) {
- Item i = { T_IMAGE, name, size, width, height };
- items_.push_back(i);
-}
-
-void
-FileShareManifest::AddFolder(const std::string& name, size_t size) {
- Item i = { T_FOLDER, name, size };
- items_.push_back(i);
-}
-
-size_t
-FileShareManifest::GetItemCount(Type t) const {
- size_t count = 0;
- for (size_t i=0; i<items_.size(); ++i) {
- if (items_[i].type == t)
- ++count;
- }
- return count;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// FileShareSession
-///////////////////////////////////////////////////////////////////////////////
-
-FileShareSession::FileShareSession(cricket::Session* session, const std::string &user_agent)
- : session_(session), state_(FS_NONE),
- is_closed_(false),
- is_sender_(false), manifest_(NULL), pool_(this), http_client_(NULL),
- http_server_(NULL),
- transfer_connection_id_(talk_base::HTTP_INVALID_CONNECTION_ID),
- counter_(NULL), item_transferring_(0), bytes_transferred_(0),
- local_cancel_(false), local_listener_(NULL), remote_listener_(NULL),
- next_channel_id_(1), user_agent_(user_agent) {
- session_->SignalState.connect(this, &FileShareSession::OnSessionState);
- session_->SignalInfoMessage.connect(this,
- &FileShareSession::OnSessionInfoMessage);
- session_->SignalChannelGone.connect(this,
- &FileShareSession::OnSessionChannelGone);
-}
-
-FileShareSession::~FileShareSession() {
- ASSERT(FS_NONE != state_);
- // If we haven't closed, do cleanup now.
- if (!IsClosed()) {
- if (!IsComplete()) {
- state_ = FS_FAILURE;
- }
- DoClose(true);
- }
- if (session_) {
- // Make sure we don't get future state changes on this session.
- session_->SignalState.disconnect(this);
- session_->SignalInfoMessage.disconnect(this);
- session_ = NULL;
- }
-
- for (TransactionList::const_iterator trans_it = transactions_.begin();
- trans_it != transactions_.end(); ++trans_it) {
- (*trans_it)->response()->set_error(talk_base::HC_NOT_FOUND);
- http_server_->Respond(*trans_it);
- }
-
- delete http_client_;
- delete http_server_;
- delete manifest_;
- delete local_listener_;
- delete remote_listener_;
-}
-
-bool
-FileShareSession::IsComplete() const {
- return (state_ >= FS_COMPLETE);
-}
-
-bool
-FileShareSession::IsClosed() const {
- return is_closed_;
-}
-
-FileShareState
-FileShareSession::state() const {
- return state_;
-}
-
-bool
-FileShareSession::is_sender() const {
- ASSERT(FS_NONE != state_);
- return is_sender_;
-}
-
-const buzz::Jid&
-FileShareSession::jid() const {
- ASSERT(FS_NONE != state_);
- return jid_;
-}
-
-const FileShareManifest*
-FileShareSession::manifest() const {
- ASSERT(FS_NONE != state_);
- return manifest_;
-}
-
-const std::string&
-FileShareSession::local_folder() const {
- ASSERT(!local_folder_.empty());
- return local_folder_;
-}
-
-void
-FileShareSession::Share(const buzz::Jid& jid, FileShareManifest* manifest) {
- ASSERT(FS_NONE == state_);
- ASSERT(NULL != session_);
-
- http_server_ = new talk_base::HttpServer;
- http_server_->SignalHttpRequest.connect(this,
- &FileShareSession::OnHttpRequest);
- http_server_->SignalHttpRequestComplete.connect(this,
- &FileShareSession::OnHttpRequestComplete);
- http_server_->SignalConnectionClosed.connect(this,
- &FileShareSession::OnHttpConnectionClosed);
-
- FileShareDescription* desc = new FileShareDescription;
- desc->supports_http = true;
- desc->manifest = *manifest;
- GenerateTemporaryPrefix(&desc->source_path);
- GenerateTemporaryPrefix(&desc->preview_path);
- session_->Initiate(jid.Str(), NULL, desc);
-
- delete manifest;
-}
-
-void
-FileShareSession::Accept() {
- ASSERT(FS_OFFER == state_);
- ASSERT(NULL != session_);
- ASSERT(NULL != manifest_);
-
- ASSERT(!http_client_);
- ASSERT(item_transferring_ == 0);
- http_client_ = new talk_base::HttpClient(user_agent_,
- &pool_);
- http_client_->SignalHttpClientComplete.connect(this,
- &FileShareSession::OnHttpClientComplete);
- http_client_->SignalHttpClientClosed.connect(this,
- &FileShareSession::OnHttpClientClosed);
-
- // The receiver now has a need for the http_server_, when previewing already
- // downloaded content.
- http_server_ = new talk_base::HttpServer;
- http_server_->SignalHttpRequest.connect(this,
- &FileShareSession::OnHttpRequest);
- http_server_->SignalHttpRequestComplete.connect(this,
- &FileShareSession::OnHttpRequestComplete);
- http_server_->SignalConnectionClosed.connect(this,
- &FileShareSession::OnHttpConnectionClosed);
-
- FileShareDescription* desc = new FileShareDescription;
- desc->supports_http = description()->supports_http;
- session_->Accept(desc);
-
- SetState(FS_TRANSFER, false);
- NextDownload();
-}
-
-void
-FileShareSession::Decline() {
- ASSERT(FS_OFFER == state_);
- ASSERT(NULL != session_);
- local_cancel_ = true;
- session_->Reject();
-}
-
-void
-FileShareSession::Cancel() {
- ASSERT(!IsComplete());
- ASSERT(NULL != session_);
- local_cancel_ = true;
- session_->Terminate();
-}
-
-bool
-FileShareSession::GetItemUrl(size_t index, std::string* url) {
- return GetItemBaseUrl(index, false, url);
-}
-
-bool FileShareSession::GetImagePreviewUrl(size_t index, size_t width,
- size_t height, std::string* url) {
- if (!GetItemBaseUrl(index, true, url))
- return false;
-
- if (FileShareManifest::T_IMAGE != manifest_->item(index).type) {
- ASSERT(false);
- return false;
- }
-
- char query[256];
- talk_base::sprintfn(query, ARRAY_SIZE(query), "?width=%u&height=%u",
- width, height);
- url->append(query);
- return true;
-}
-
-void FileShareSession::ResampleComplete(talk_base::StreamInterface *i, talk_base::HttpTransaction *trans, bool success) {
- bool found = false;
- for (TransactionList::const_iterator trans_it = transactions_.begin();
- trans_it != transactions_.end(); ++trans_it) {
- if (*trans_it == trans) {
- found = true;
- break;
- }
- }
-
- if (!found)
- return;
-
- transactions_.remove(trans);
-
- if (success) {
- trans->response()->set_success(MIME_OCTET_STREAM, i);
- http_server_->Respond(trans);
-
- }
- trans->response()->set_error(talk_base::HC_NOT_FOUND);
- http_server_->Respond(trans);
-}
-
-bool FileShareSession::GetProgress(size_t& bytes) const {
- bool known = true;
- bytes = bytes_transferred_;
- if (counter_) {
- size_t current_size = manifest_->item(item_transferring_).size;
- size_t current_pos = counter_->GetByteCount();
- if (current_size == FileShareManifest::SIZE_UNKNOWN) {
- known = false;
- } else if (current_pos > current_size) {
- // Don't allow the size of a 'known' item to be reported as larger than
- // it claimed to be.
- ASSERT(false);
- current_pos = current_size;
- }
- bytes += current_pos;
- }
- return known;
-}
-
-bool FileShareSession::GetTotalSize(size_t& bytes) const {
- bool known = true;
- bytes = 0;
- for (size_t i=0; i<manifest_->size(); ++i) {
- if (manifest_->item(i).size == FileShareManifest::SIZE_UNKNOWN) {
- // We make files of unknown length worth a single byte.
- known = false;
- bytes += 1;
- } else {
- bytes += manifest_->item(i).size;
- }
- }
- return known;
-}
-
-bool FileShareSession::GetCurrentItemName(std::string* name) {
- if (FS_TRANSFER != state_) {
- name->clear();
- return false;
- }
- ASSERT(item_transferring_ < manifest_->size());
- if (transfer_name_.empty()) {
- const FileShareManifest::Item& item = manifest_->item(item_transferring_);
- *name = item.name;
- } else {
- *name = transfer_name_;
- }
- return !name->empty();
-}
-
-// StreamPool Implementation
-
-talk_base::StreamInterface* FileShareSession::RequestConnectedStream(
- const talk_base::SocketAddress& remote, int* err) {
- ASSERT(remote.IPAsString() == jid_.Str());
- ASSERT(!IsClosed());
- ASSERT(NULL != session_);
- if (!session_) {
- if (err)
- *err = -1;
- return NULL;
- }
-
- char channel_name[64];
- talk_base::sprintfn(channel_name, ARRAY_SIZE(channel_name),
- "private-%u", next_channel_id_++);
- if (err)
- *err = 0;
- return CreateChannel(channel_name);
-}
-
-void FileShareSession::ReturnConnectedStream(
- talk_base::StreamInterface* stream) {
- talk_base::Thread::Current()->Dispose(stream);
-}
-
-// MessageHandler Implementation
-
-void FileShareSession::OnMessage(talk_base::Message* msg) {
- if (MSG_PROXY_WAIT == msg->message_id) {
- LOG_F(LS_INFO) << "MSG_PROXY_WAIT";
- if (proxies_.empty() && IsComplete() && !IsClosed()) {
- DoClose(true);
- }
- }
-}
-
-// Session Signals
-
-void FileShareSession::OnSessionState(cricket::Session* session,
- cricket::Session::State state) {
- // Once we are complete, state changes are meaningless.
- if (!IsComplete()) {
- switch (state) {
- case cricket::Session::STATE_SENTINITIATE:
- case cricket::Session::STATE_RECEIVEDINITIATE:
- OnInitiate();
- break;
- case cricket::Session::STATE_SENTACCEPT:
- case cricket::Session::STATE_RECEIVEDACCEPT:
- case cricket::Session::STATE_INPROGRESS:
- SetState(FS_TRANSFER, false);
- break;
- case cricket::Session::STATE_SENTREJECT:
- case cricket::Session::STATE_SENTTERMINATE:
- case cricket::Session::STATE_DEINIT:
- if (local_cancel_) {
- SetState(FS_LOCAL_CANCEL, false);
- } else {
- SetState(FS_REMOTE_CANCEL, false);
- }
- break;
- case cricket::Session::STATE_RECEIVEDTERMINATE:
- if (is_sender()) {
- // If we are the sender, and the receiver downloaded the correct number
- // of bytes, then we assume the transfer was successful. We've
- // introduced support for explicit completion notification
- // (QN_SHARE_COMPLETE), but it's not mandatory at this point, so we need
- // this as a fallback.
- size_t total_bytes;
- GetTotalSize(total_bytes);
- if (bytes_transferred_ >= total_bytes) {
- SetState(FS_COMPLETE, false);
- break;
- }
- }
- // Fall through
- case cricket::Session::STATE_RECEIVEDREJECT:
- SetState(FS_REMOTE_CANCEL, false);
- break;
- case cricket::Session::STATE_INIT:
- case cricket::Session::STATE_SENTMODIFY:
- case cricket::Session::STATE_RECEIVEDMODIFY:
- case cricket::Session::STATE_SENTREDIRECT:
- default:
- // These states should not occur.
- ASSERT(false);
- break;
- }
- }
-
- if (state == cricket::Session::STATE_DEINIT) {
- if (!IsClosed()) {
- DoClose(false);
- }
- session_ = NULL;
- }
-}
-
-void FileShareSession::OnSessionInfoMessage(cricket::Session* session,
- const cricket::Session::XmlElements& els) {
- if (IsClosed())
- return;
- ASSERT(NULL != session_);
- for (size_t i=0; i<els.size(); ++i) {
- if (is_sender() && (els[i]->Name() == QN_SHARE_CHANNEL)) {
- if (els[i]->HasAttr(buzz::QN_NAME)) {
- cricket::PseudoTcpChannel* channel =
- new cricket::PseudoTcpChannel(talk_base::Thread::Current(), session_);
- VERIFY(channel->Connect(els[i]->Attr(buzz::QN_NAME)));
- talk_base::StreamInterface* stream = channel->GetStream();
- http_server_->HandleConnection(stream);
- }
- } else if (is_sender() && (els[i]->Name() == QN_SHARE_COMPLETE)) {
- // Normal file transfer has completed, but receiver may still be getting
- // previews.
- if (!IsComplete()) {
- SetState(FS_COMPLETE, true);
- }
- } else {
- LOG(LS_WARNING) << "Unknown FileShareSession info message: "
- << els[i]->Name().Merged();
- }
- }
-}
-
-void FileShareSession::OnSessionChannelGone(cricket::Session* session,
- const std::string& name) {
- LOG_F(LS_WARNING) << "(" << name << ")";
- ASSERT(session == session_);
- if (cricket::TransportChannel* channel = session->GetChannel(name)) {
- session->DestroyChannel(channel);
- }
-}
-
-// HttpClient Signals
-
-void FileShareSession::OnHttpClientComplete(talk_base::HttpClient* http,
- int err) {
- LOG_F(LS_INFO) << "(" << err << ", " << http->response().scode << ")";
- ASSERT(http == http_client_);
- ASSERT(NULL != session_);
-
- transfer_name_.clear();
- counter_ = NULL; // counter_ is deleted by HttpClient
- http->response().document.reset();
- bool success = (err == 0) && (http->response().scode == talk_base::HC_OK);
-
- const FileShareManifest::Item& item = manifest_->item(item_transferring_);
- talk_base::Pathname local_name;
- local_name.SetFilename(item.name);
- local_name.SetFolder(local_folder_);
-
- if (local_name.pathname() != transfer_path_) {
- const bool is_folder = (item.type == FileShareManifest::T_FOLDER);
- if (success && !talk_base::CreateUniqueFile(local_name, false)) {
- LOG(LS_ERROR) << "Couldn't rename downloaded file: "
- << local_name.pathname();
- success = false;
- }
-
- talk_base::Pathname temp_name(transfer_path_);
- if (is_folder) {
- // The folder we want is a subdirectory of the transfer_path_.
- temp_name.AppendFolder(item.name);
- }
-
- if (!talk_base::Filesystem::MoveFile(temp_name.pathname(), local_name.pathname())) {
- success = false;
- LOG(LS_ERROR) << "Couldn't move downloaded file from '"
- << temp_name.pathname() << "' to '"
- << local_name.pathname();
- }
-
- if (success && is_folder) {
- talk_base::Filesystem::DeleteFile(transfer_path_);
- }
- }
-
- if (!success) {
- if (!talk_base::Filesystem::DeleteFile(transfer_path_)) {
- LOG(LS_ERROR) << "Couldn't delete downloaded file: " << transfer_path_;
- }
- if (!IsComplete()) {
- SetState(FS_FAILURE, false);
- }
- return;
- }
-
- // We may have skipped over some items (if they are directories, or otherwise
- // failed. resize ensures that we populate the skipped entries with empty
- // strings.
- stored_location_.resize(item_transferring_ + 1);
- stored_location_[item_transferring_] = local_name.pathname();
-
- // bytes_transferred_ represents the size of items which have completely
- // transferred, and is added to the progress of the currently transferring
- // items.
- if (item.size == FileShareManifest::SIZE_UNKNOWN) {
- bytes_transferred_ += 1;
- } else {
- bytes_transferred_ += item.size;
- }
- item_transferring_ += 1;
- NextDownload();
-}
-
-void FileShareSession::OnHttpClientClosed(talk_base::HttpClient* http,
- int err) {
- LOG_F(LS_INFO) << "(" << err << ")";
-}
-
-// HttpServer Signals
-
-void FileShareSession::OnHttpRequest(talk_base::HttpServer* server,
- talk_base::HttpTransaction* transaction) {
- LOG_F(LS_INFO) << "(" << transaction->request()->path << ")";
- ASSERT(server == http_server_);
-
- std::string path, query;
- size_t query_start = transaction->request()->path.find('?');
- if (query_start != std::string::npos) {
- path = transaction->request()->path.substr(0, query_start);
- query = transaction->request()->path.substr(query_start + 1);
- } else {
- path = transaction->request()->path;
- }
-
- talk_base::Pathname remote_name(path);
- bool preview = (preview_path_ == remote_name.folder());
- bool original = (source_path_ == remote_name.folder());
-
- std::string requested_file(remote_name.filename());
- talk_base::transform(requested_file, requested_file.size(), requested_file,
- talk_base::url_decode);
-
- size_t item_index;
- const FileShareManifest::Item* item = NULL;
- if (preview || original) {
- for (size_t i=0; i<manifest_->size(); ++i) {
- LOG(LS_INFO) << "++++ " << manifest_->item(i).name + " " << requested_file;
- if (manifest_->item(i).name == requested_file) {
- item_index = i;
- item = &manifest_->item(item_index);
- break;
- }
- }
- }
-
- talk_base::StreamInterface* stream = NULL;
- std::string mime_type(MIME_OCTET_STREAM);
-
- if (!item) {
- // Fall through
- } else if (preview) {
- // Only image previews allowed
- unsigned int width = 0, height = 0;
- if ((item->type == FileShareManifest::T_IMAGE)
- && !query.empty()
- && (sscanf(query.c_str(), "width=%u&height=%u",
- &width, &height) == 2)) {
- width = talk_base::_max<unsigned int>(1, talk_base::_min(width, kMaxPreviewSize));
- height = talk_base::_max<unsigned int>(1, talk_base::_min(height, kMaxPreviewSize));
- std::string pathname;
- if (is_sender_) {
- talk_base::Pathname local_path;
- local_path.SetFolder(local_folder_);
- local_path.SetFilename(item->name);
- pathname = local_path.pathname();
- } else if ((item_index < stored_location_.size())
- && !stored_location_[item_index].empty()) {
- pathname = stored_location_[item_index];
- }
- if (!pathname.empty()) {
- transactions_.push_back(transaction);
- SignalResampleImage(pathname, width, height, transaction);
- }
- }
- } else if (item->type == FileShareManifest::T_FOLDER) {
- talk_base::Pathname local_path;
- local_path.SetFolder(local_folder_);
- local_path.AppendFolder(item->name);
- talk_base::TarStream* tar = new talk_base::TarStream;
- VERIFY(tar->AddFilter(local_path.folder_name()));
- if (tar->Open(local_path.parent_folder(), true)) {
- stream = tar;
- tar->SignalNextEntry.connect(this, &FileShareSession::OnNextEntry);
- mime_type = "application/x-tar";
- } else {
- delete tar;
- }
- } else if ((item->type == FileShareManifest::T_FILE)
- || (item->type == FileShareManifest::T_IMAGE)) {
- talk_base::Pathname local_path;
- local_path.SetFolder(local_folder_);
- local_path.SetFilename(item->name);
- talk_base::FileStream* file = new talk_base::FileStream;
- LOG(LS_INFO) << "opening file " << local_path.pathname();
- if (file->Open(local_path.pathname().c_str(), "rb")) {
- LOG(LS_INFO) << "File opened";
- stream = file;
- } else {
- delete file;
- }
- }
-
- if (!stream) {
- transaction->response()->set_error(talk_base::HC_NOT_FOUND);
- } else if (original) {
- // We should never have more than one original request pending at a time
- ASSERT(NULL == counter_);
- StreamCounter* counter = new StreamCounter(stream);
- counter->SignalUpdateByteCount.connect(this, &FileShareSession::OnUpdateBytes);
- transaction->response()->set_success(mime_type.c_str(), counter);
- transfer_connection_id_ = transaction->connection_id();
- item_transferring_ = item_index;
- counter_ = counter;
- } else {
- // Note: in the preview case, we don't set counter_, so the transferred
- // bytes won't be shown as progress, and won't trigger a state change.
- transaction->response()->set_success(mime_type.c_str(), stream);
- }
-
- LOG_F(LS_INFO) << "Result: " << transaction->response()->scode;
- http_server_->Respond(transaction);
-}
-
-void FileShareSession::OnHttpRequestComplete(talk_base::HttpServer* server,
- talk_base::HttpTransaction* transaction, int err) {
- LOG_F(LS_INFO) << "(" << transaction->request()->path << ", " << err << ")";
- ASSERT(server == http_server_);
-
- // We only care about transferred originals
- if (transfer_connection_id_ != transaction->connection_id())
- return;
-
- ASSERT(item_transferring_ < manifest_->size());
- ASSERT(NULL != counter_);
-
- transfer_connection_id_ = talk_base::HTTP_INVALID_CONNECTION_ID;
- transfer_name_.clear();
- counter_ = NULL;
-
- if (err == 0) {
- const FileShareManifest::Item& item = manifest_->item(item_transferring_);
- if (item.size == FileShareManifest::SIZE_UNKNOWN) {
- bytes_transferred_ += 1;
- } else {
- bytes_transferred_ += item.size;
- }
- }
-}
-
-void FileShareSession::OnHttpConnectionClosed(talk_base::HttpServer* server,
- int err, talk_base::StreamInterface* stream) {
- LOG_F(LS_INFO) << "(" << err << ")";
- talk_base::Thread::Current()->Dispose(stream);
-}
-
-// TarStream Signals
-
-void FileShareSession::OnNextEntry(const std::string& name, size_t size) {
- LOG_F(LS_VERBOSE) << "(" << name << ", " << size << ")";
- transfer_name_ = name;
- SignalNextFile(this);
-}
-
-// Socket Signals
-
-void FileShareSession::OnProxyAccept(talk_base::AsyncSocket* socket) {
- bool is_remote;
- if (socket == remote_listener_) {
- is_remote = true;
- ASSERT(NULL != session_);
- } else if (socket == local_listener_) {
- is_remote = false;
- } else {
- ASSERT(false);
- return;
- }
-
- while (talk_base::AsyncSocket* accepted =
- static_cast<talk_base::AsyncSocket*>(socket->Accept(NULL))) {
-
- // Check if connection is from localhost.
- if (accepted->GetRemoteAddress().ip() != 0x7F000001) {
- delete accepted;
- continue;
- }
-
- LOG_F(LS_VERBOSE) << (is_remote ? "[remote]" : "[local]");
-
- if (is_remote) {
- char channel_name[64];
- talk_base::sprintfn(channel_name, ARRAY_SIZE(channel_name),
- "proxy-%u", next_channel_id_++);
- talk_base::StreamInterface* remote =
- (NULL != session_) ? CreateChannel(channel_name) : NULL;
- if (!remote) {
- LOG_F(LS_WARNING) << "CreateChannel(" << channel_name << ") failed";
- delete accepted;
- continue;
- }
-
- talk_base::StreamInterface* local = new talk_base::SocketStream(accepted);
- StreamRelay* proxy = new StreamRelay(local, remote, 64 * 1024);
- proxy->SignalClosed.connect(this, &FileShareSession::OnProxyClosed);
- proxies_.push_back(proxy);
- proxy->Circulate();
- talk_base::Thread::Current()->Clear(this, MSG_PROXY_WAIT);
- } else {
- talk_base::StreamInterface* local = new talk_base::SocketStream(accepted);
- http_server_->HandleConnection(local);
- }
- }
-}
-
-void FileShareSession::OnProxyClosed(StreamRelay* proxy, int error) {
- ProxyList::iterator it = std::find(proxies_.begin(), proxies_.end(), proxy);
- if (it == proxies_.end()) {
- ASSERT(false);
- return;
- }
-
- LOG_F(LS_VERBOSE) << "(" << error << ")";
-
- proxies_.erase(it);
- talk_base::Thread::Current()->Dispose(proxy);
-
- if (proxies_.empty() && IsComplete() && !IsClosed()) {
- talk_base::Thread::Current()->PostDelayed(kProxyWait, this, MSG_PROXY_WAIT);
- }
-}
-
-
-void FileShareSession::OnUpdateBytes(size_t count) {
- SignalUpdateProgress(this);
-}
-
-// Internal Helpers
-
-void FileShareSession::GenerateTemporaryPrefix(std::string* prefix) {
- std::string data = cricket::CreateRandomString(32);
- ASSERT(NULL != prefix);
- prefix->assign("/temporary/");
- prefix->append(talk_base::MD5(data));
- prefix->append("/");
-}
-
-void FileShareSession::GetItemNetworkPath(size_t index, bool preview,
- std::string* path) {
- ASSERT(index < manifest_->size());
- ASSERT(NULL != path);
-
- // preview_path_ and source_path_ are url path segments, which are composed
- // with the address of the localhost p2p proxy to provide a url which IE can
- // use.
-
- std::string ue_name;
- const std::string& name = manifest_->item(index).name;
- talk_base::transform(ue_name, name.length() * 3, name, talk_base::url_encode);
-
- talk_base::Pathname pathname;
- pathname.SetFolder(preview ? preview_path_ : source_path_);
- pathname.SetFilename(ue_name);
- *path = pathname.pathname();
-}
-
-bool FileShareSession::GetItemBaseUrl(size_t index, bool preview,
- std::string* url) {
- // This function composes a URL to the referenced item. It may be a local
- // file url (file:///...), or a remote peer url relayed through localhost
- // (http://...)
-
- ASSERT(NULL != url);
- if (index >= manifest_->size()) {
- ASSERT(false);
- return false;
- }
-
- const FileShareManifest::Item& item = manifest_->item(index);
-
- bool is_remote;
- if (is_sender_) {
- if (!preview) {
- talk_base::Pathname path(local_folder_);
- path.SetFilename(item.name);
- *url = path.url();
- return true;
- }
- is_remote = false;
- } else {
- if ((index < stored_location_.size()) && !stored_location_[index].empty()) {
- if (!preview) {
- *url = talk_base::Pathname(stored_location_[index]).url();
- return true;
- }
- // Note: Using the local downloaded files as a source for previews is
- // desireable, because it means that previews can be regenerated if IE's
- // cached versions get flushed for some reason, and the remote side is
- // not available. However, it has the downside that IE _must_ regenerate
- // the preview locally, which takes time, memory and CPU. Eventually,
- // we will unify the remote and local cached copy through some sort of
- // smart http proxying. In the meantime, always use the remote url, to
- // eliminate the annoying transition from remote to local caching.
- //is_remote = false;
- is_remote = true;
- } else {
- is_remote = true;
- }
- }
-
- talk_base::SocketAddress address;
- if (!GetProxyAddress(address, is_remote))
- return false;
-
- std::string path;
- GetItemNetworkPath(index, preview, &path);
- talk_base::Url<char> make_url(path.c_str(),
- address.IPAsString().c_str(),
- address.port());
- *url = make_url.url();
- return true;
-}
-
-bool FileShareSession::GetProxyAddress(talk_base::SocketAddress& address,
- bool is_remote) {
- talk_base::AsyncSocket*& proxy_listener =
- is_remote ? remote_listener_ : local_listener_;
-
- if (!proxy_listener) {
- talk_base::AsyncSocket* listener =
- talk_base::Thread::Current()->socketserver()
- ->CreateAsyncSocket(SOCK_STREAM);
- if (!listener)
- return false;
-
- talk_base::SocketAddress bind_address("127.0.0.1", 0);
-
- if ((listener->Bind(bind_address) != 0)
- || (listener->Listen(5) != 0)) {
- delete listener;
- return false;
- }
-
- LOG(LS_INFO) << "Proxy listener available @ "
- << listener->GetLocalAddress().ToString();
-
- listener->SignalReadEvent.connect(this, &FileShareSession::OnProxyAccept);
- proxy_listener = listener;
- }
-
- if (proxy_listener->GetState() == talk_base::Socket::CS_CLOSED) {
- if (is_remote) {
- address = remote_listener_address_;
- return true;
- }
- return false;
- }
-
- address = proxy_listener->GetLocalAddress();
- return !address.IsAny();
-}
-
-talk_base::StreamInterface* FileShareSession::CreateChannel(
- const std::string& channel_name) {
- ASSERT(NULL != session_);
-
- // Send a heads-up for our new channel
- cricket::Session::XmlElements els;
- buzz::XmlElement* xel_channel = new buzz::XmlElement(QN_SHARE_CHANNEL, true);
- xel_channel->AddAttr(buzz::QN_NAME, channel_name);
- els.push_back(xel_channel);
- session_->SendInfoMessage(els);
-
- cricket::PseudoTcpChannel* channel =
- new cricket::PseudoTcpChannel(talk_base::Thread::Current(), session_);
- VERIFY(channel->Connect(channel_name));
- return channel->GetStream();
-}
-
-void FileShareSession::SetState(FileShareState state, bool prevent_close) {
- if (state == state_)
- return;
-
- if (IsComplete()) {
- // Entering a completion state is permanent.
- ASSERT(false);
- return;
- }
-
- state_ = state;
- if (IsComplete()) {
- // All completion states auto-close except for FS_COMPLETE
- bool close = (state_ > FS_COMPLETE) || !prevent_close;
- if (close) {
- DoClose(true);
- }
- }
-
- SignalState(state_);
-}
-
-void FileShareSession::OnInitiate() {
- // Cache the variables we will need, in case session_ goes away
- is_sender_ = session_->initiator();
- jid_ = buzz::Jid(session_->remote_name());
- manifest_ = new FileShareManifest(description()->manifest);
- source_path_ = description()->source_path;
- preview_path_ = description()->preview_path;
-
- if (local_folder_.empty()) {
- LOG(LS_ERROR) << "FileShareSession - no local folder, using temp";
- talk_base::Pathname temp_folder;
- talk_base::Filesystem::GetTemporaryFolder(temp_folder, true, NULL);
- local_folder_ = temp_folder.pathname();
- }
- LOG(LS_INFO) << session_->state();
- SetState(FS_OFFER, false);
-}
-
-void FileShareSession::NextDownload() {
- if (FS_TRANSFER != state_)
- return;
-
- if (item_transferring_ >= manifest_->size()) {
- // Notify the other side that transfer has completed
- cricket::Session::XmlElements els;
- els.push_back(new buzz::XmlElement(QN_SHARE_COMPLETE, true));
- session_->SendInfoMessage(els);
- SetState(FS_COMPLETE, !proxies_.empty());
- return;
- }
-
- const FileShareManifest::Item& item = manifest_->item(item_transferring_);
- if ((item.type != FileShareManifest::T_FILE)
- && (item.type != FileShareManifest::T_IMAGE)
- && (item.type != FileShareManifest::T_FOLDER)) {
- item_transferring_ += 1;
- NextDownload();
- return;
- }
-
- const bool is_folder = (item.type == FileShareManifest::T_FOLDER);
- talk_base::Pathname temp_name;
- temp_name.SetFilename(item.name);
- if (!talk_base::CreateUniqueFile(temp_name, !is_folder)) {
- SetState(FS_FAILURE, false);
- return;
- }
-
- talk_base::StreamInterface* stream = NULL;
- if (is_folder) {
- // Convert unique filename into unique foldername
- temp_name.AppendFolder(temp_name.filename());
- temp_name.SetFilename("");
- talk_base::TarStream* tar = new talk_base::TarStream;
- // Note: the 'target' directory will be a subdirectory of the transfer_path_
- talk_base::Pathname target;
- target.SetFolder(item.name);
- tar->AddFilter(target.pathname());
- if (!tar->Open(temp_name.pathname(), false)) {
- delete tar;
- SetState(FS_FAILURE, false);
- return;
- }
- stream = tar;
- tar->SignalNextEntry.connect(this, &FileShareSession::OnNextEntry);
- } else {
- talk_base::FileStream* file = new talk_base::FileStream;
- if (!file->Open(temp_name.pathname().c_str(), "wb")) {
- delete file;
- talk_base::Filesystem::DeleteFile(temp_name);
- SetState(FS_FAILURE, false);
- return;
- }
- stream = file;
- }
-
- ASSERT(NULL != stream);
- transfer_path_ = temp_name.pathname();
-
- std::string remote_path;
- GetItemNetworkPath(item_transferring_, false, &remote_path);
-
- StreamCounter* counter = new StreamCounter(stream);
- counter->SignalUpdateByteCount.connect(this, &FileShareSession::OnUpdateBytes);
- counter_ = counter;
-
- http_client_->reset();
- http_client_->set_server(talk_base::SocketAddress(jid_.Str(), 0, false));
- http_client_->request().verb = talk_base::HV_GET;
- http_client_->request().path = remote_path;
- http_client_->response().document.reset(counter);
- http_client_->start();
-}
-
-
-const FileShareSession::FileShareDescription* FileShareSession::description()
-const {
- ASSERT(NULL != session_);
- const cricket::SessionDescription* desc =
- session_->initiator() ? session_->description()
- : session_->remote_description();
- return static_cast<const FileShareDescription*>(desc);
-}
-
-void FileShareSession::DoClose(bool terminate) {
- ASSERT(!is_closed_);
- ASSERT(IsComplete());
- ASSERT(NULL != session_);
-
- is_closed_ = true;
-
- if (http_client_) {
- http_client_->reset();
- }
- if (http_server_) {
- http_server_->CloseAll(true);
- // Currently, CloseAll doesn't result in OnHttpRequestComplete callback.
- // If we change that, the following resetting won't be necessary.
- transfer_connection_id_ = talk_base::HTTP_INVALID_CONNECTION_ID;
- transfer_name_.clear();
- counter_ = NULL;
- }
- // 'reset' and 'CloseAll' cause counter_ to clear.
- ASSERT(NULL == counter_);
-
- if (remote_listener_) {
- // Cache the address for the remote_listener_, so that we can continue to
- // present a consistent URL for remote previews, which is necessary for IE
- // to continue using its cached copy.
- remote_listener_address_ = remote_listener_->GetLocalAddress();
- remote_listener_->Close();
- LOG(LS_INFO) << "Proxy listener closed @ "
- << remote_listener_address_.ToString();
- }
-
- if (terminate) {
- session_->Terminate();
- }
-}
-
-//////////////////////////////
-/// FileShareSessionClient //
-////////////////////////////
-
-void FileShareSessionClient::OnSessionCreate(cricket::Session* session,
- bool received_initiate) {
- VERIFY(sessions_.insert(session).second);
- if (received_initiate) {
- FileShareSession* share = new FileShareSession(session, user_agent_);
- SignalFileShareSessionCreate(share);
- UNUSED(share); // FileShareSession registers itself with the UI
- }
-}
-
-void FileShareSessionClient::OnSessionDestroy(cricket::Session* session) {
- VERIFY(1 == sessions_.erase(session));
-}
-
-const cricket::SessionDescription* FileShareSessionClient::CreateSessionDescription(
- const buzz::XmlElement* element) {
- FileShareSession::FileShareDescription* share_desc =
- new FileShareSession::FileShareDescription;
-
- if (element->Name() != QN_SHARE_DESCRIPTION)
- return share_desc;
-
- const buzz::XmlElement* manifest = element->FirstNamed(QN_SHARE_MANIFEST);
- const buzz::XmlElement* protocol = element->FirstNamed(QN_SHARE_PROTOCOL);
-
- if (!manifest || !protocol)
- return share_desc;
-
- for (const buzz::XmlElement* item = manifest->FirstElement();
- item != NULL; item = item->NextElement()) {
- bool is_folder;
- if (item->Name() == QN_SHARE_FOLDER) {
- is_folder = true;
- } else if (item->Name() == QN_SHARE_FILE) {
- is_folder = false;
- } else {
- continue;
- }
- std::string name;
- if (const buzz::XmlElement* el_name = item->FirstNamed(QN_SHARE_NAME)) {
- name = el_name->BodyText();
- }
- if (name.empty()) {
- continue;
- }
- size_t size = FileShareManifest::SIZE_UNKNOWN;
- if (item->HasAttr(QN_SIZE)) {
- size = strtoul(item->Attr(QN_SIZE).c_str(), NULL, 10);
- }
- if (is_folder) {
- share_desc->manifest.AddFolder(name, size);
- } else {
- // Check if there is a valid image description for this file.
- if (const buzz::XmlElement* image = item->FirstNamed(QN_SHARE_IMAGE)) {
- if (image->HasAttr(QN_WIDTH) && image->HasAttr(QN_HEIGHT)) {
- size_t width = strtoul(image->Attr(QN_WIDTH).c_str(), NULL, 10);
- size_t height = strtoul(image->Attr(QN_HEIGHT).c_str(), NULL, 10);
- if (AllowedImageDimensions(width, height)) {
- share_desc->manifest.AddImage(name, size, width, height);
- continue;
- }
- }
- }
- share_desc->manifest.AddFile(name, size);
- }
- }
-
- if (const buzz::XmlElement* http = protocol->FirstNamed(QN_SHARE_HTTP)) {
- share_desc->supports_http = true;
- for (const buzz::XmlElement* url = http->FirstNamed(QN_SHARE_URL);
- url != NULL; url = url->NextNamed(QN_SHARE_URL)) {
- if (url->Attr(buzz::QN_NAME) == kHttpSourcePath) {
- share_desc->source_path = url->BodyText();
- } else if (url->Attr(buzz::QN_NAME) == kHttpPreviewPath) {
- share_desc->preview_path = url->BodyText();
- }
- }
- }
-
- return share_desc;
-}
-
-buzz::XmlElement* FileShareSessionClient::TranslateSessionDescription(
- const cricket::SessionDescription* description) {
-
- const FileShareSession::FileShareDescription* share_desc =
- static_cast<const FileShareSession::FileShareDescription*>(description);
-
- scoped_ptr<buzz::XmlElement> el(new buzz::XmlElement(QN_SHARE_DESCRIPTION,
- true));
-
- const FileShareManifest& manifest = share_desc->manifest;
- el->AddElement(new buzz::XmlElement(QN_SHARE_MANIFEST));
- for (size_t i=0; i<manifest.size(); ++i) {
- const FileShareManifest::Item& item = manifest.item(i);
- buzz::QName qname;
- if (item.type == FileShareManifest::T_FOLDER) {
- qname = QN_SHARE_FOLDER;
- } else if ((item.type == FileShareManifest::T_FILE)
- || (item.type == FileShareManifest::T_IMAGE)) {
- qname = QN_SHARE_FILE;
- } else {
- ASSERT(false);
- continue;
- }
- el->AddElement(new buzz::XmlElement(qname), 1);
- if (item.size != FileShareManifest::SIZE_UNKNOWN) {
- char buffer[256];
- talk_base::sprintfn(buffer, sizeof(buffer), "%lu", item.size);
- el->AddAttr(QN_SIZE, buffer, 2);
- }
- buzz::XmlElement* el_name = new buzz::XmlElement(QN_SHARE_NAME);
- el_name->SetBodyText(item.name);
- el->AddElement(el_name, 2);
- if ((item.type == FileShareManifest::T_IMAGE)
- && AllowedImageDimensions(item.width, item.height)) {
- el->AddElement(new buzz::XmlElement(QN_SHARE_IMAGE), 2);
- char buffer[256];
- talk_base::sprintfn(buffer, sizeof(buffer), "%lu", item.width);
- el->AddAttr(QN_WIDTH, buffer, 3);
- talk_base::sprintfn(buffer, sizeof(buffer), "%lu", item.height);
- el->AddAttr(QN_HEIGHT, buffer, 3);
- }
- }
-
- el->AddElement(new buzz::XmlElement(QN_SHARE_PROTOCOL));
- if (share_desc->supports_http) {
- el->AddElement(new buzz::XmlElement(QN_SHARE_HTTP), 1);
- if (!share_desc->source_path.empty()) {
- buzz::XmlElement* url = new buzz::XmlElement(QN_SHARE_URL);
- url->SetAttr(buzz::QN_NAME, kHttpSourcePath);
- url->SetBodyText(share_desc->source_path);
- el->AddElement(url, 2);
- }
- if (!share_desc->preview_path.empty()) {
- buzz::XmlElement* url = new buzz::XmlElement(QN_SHARE_URL);
- url->SetAttr(buzz::QN_NAME, kHttpPreviewPath);
- url->SetBodyText(share_desc->preview_path);
- el->AddElement(url, 2);
- }
- }
-
- return el.release();
-}
-
-FileShareSession *FileShareSessionClient::CreateFileShareSession() {
- cricket::Session* session = sm_->CreateSession(jid_.Str(),
- NS_GOOGLE_SHARE);
- FileShareSession* share = new FileShareSession(session, user_agent_);
- SignalFileShareSessionCreate(share);
- return share;
-}
-
-
-} // namespace cricket
diff --git a/talk/session/fileshare/fileshare.h b/talk/session/fileshare/fileshare.h
deleted file mode 100755
index b0802b4..0000000
--- a/talk/session/fileshare/fileshare.h
+++ /dev/null
@@ -1,250 +0,0 @@
-#ifndef TALK_APP_WIN32_FILESHARE_H__
-#define TALK_APP_WIN32_FILESHARE_H__
-#include "talk/base/messagequeue.h"
-#include "talk/base/socketpool.h"
-#include "talk/base/stringutils.h"
-#include "talk/base/sigslot.h"
-#include "talk/p2p/base/session.h"
-#include "talk/p2p/base/sessiondescription.h"
-#include "talk/xmpp/jid.h"
-
-class StreamCounter;
-class StreamRelay;
-
-namespace talk_base {
- class HttpClient;
- class HttpServer;
- class HttpTransaction;
-}
-
-extern const std::string NS_GOOGLE_SHARE;
-
-
-namespace cricket {
-
-///////////////////////////////////////////////////////////////////////////////
-// FileShareManifest
-///////////////////////////////////////////////////////////////////////////////
-
-class FileShareManifest {
-public:
- enum Type { T_FILE, T_IMAGE, T_FOLDER };
- enum { SIZE_UNKNOWN = talk_base::SIZE_UNKNOWN };
-
- struct Item {
- Type type;
- std::string name;
- size_t size, width, height;
- };
- typedef std::vector<Item> ItemList;
-
- inline bool empty() const { return items_.empty(); }
- inline size_t size() const { return items_.size(); }
- inline const Item& item(size_t index) const { return items_[index]; }
-
- void AddFile(const std::string& name, size_t size);
- void AddImage(const std::string& name, size_t size,
- size_t width, size_t height);
- void AddFolder(const std::string& name, size_t size);
-
- size_t GetItemCount(Type t) const;
- inline size_t GetFileCount() const { return GetItemCount(T_FILE); }
- inline size_t GetImageCount() const { return GetItemCount(T_IMAGE); }
- inline size_t GetFolderCount() const { return GetItemCount(T_FOLDER); }
-
-private:
- ItemList items_;
-};
-
-
-enum FileShareState {
- FS_NONE, // Initialization
- FS_OFFER, // Offer extended
- FS_TRANSFER, // In progress
- FS_COMPLETE, // Completed successfully
- FS_LOCAL_CANCEL, // Local side cancelled
- FS_REMOTE_CANCEL, // Remote side cancelled
- FS_FAILURE // An error occurred during transfer
-};
-
-
-class FileShareSession
- : public talk_base::StreamPool,
- public talk_base::MessageHandler,
- public sigslot::has_slots<> {
-public:
- struct FileShareDescription : public cricket::SessionDescription {
- FileShareManifest manifest;
- bool supports_http;
- std::string source_path;
- std::string preview_path;
- FileShareDescription() : supports_http(false) { }
- };
-
- FileShareSession(cricket::Session* session, const std::string &user_agent);
- virtual ~FileShareSession();
-
- bool IsComplete() const;
- bool IsClosed() const;
- FileShareState state() const;
- sigslot::signal1<FileShareState> SignalState;
- sigslot::signal1<FileShareSession*> SignalNextFile;
- sigslot::signal1<FileShareSession*> SignalUpdateProgress;
- sigslot::signal4<std::string, int, int, talk_base::HttpTransaction*> SignalResampleImage;
-
- void ResampleComplete(talk_base::StreamInterface *si, talk_base::HttpTransaction *trans, bool success);
-
- bool is_sender() const;
- const buzz::Jid& jid() const;
- const FileShareManifest* manifest() const;
- const std::string& local_folder() const;
-
- void SetLocalFolder(const std::string& folder) { local_folder_ = folder; }
- void Share(const buzz::Jid& jid, FileShareManifest* manifest);
-
- void Accept();
- void Decline();
- void Cancel();
-
- bool GetItemUrl(size_t index, std::string* url);
- bool GetImagePreviewUrl(size_t index, size_t width, size_t height,
- std::string* url);
- // Returns true if the transferring item size is known
- bool GetProgress(size_t& bytes) const;
- // Returns true if the total size is known
- bool GetTotalSize(size_t& bytes) const;
- // Returns true if currently transferring item name is known
- bool GetCurrentItemName(std::string* name);
-
- // TODO: Eliminate this eventually?
- cricket::Session* session() { return session_; }
-
- // StreamPool Interface
- virtual talk_base::StreamInterface*
- RequestConnectedStream(const talk_base::SocketAddress& remote, int* err);
- virtual void ReturnConnectedStream(talk_base::StreamInterface* stream);
-
- // MessageHandler Interface
- virtual void OnMessage(talk_base::Message* msg);
-
- void GetItemNetworkPath(size_t index, bool preview, std::string* path);
-
-private:
- typedef std::list<StreamRelay*> ProxyList;
- typedef std::list<talk_base::HttpTransaction*> TransactionList;
-
- // Session Signals
- void OnSessionState(cricket::Session* session, cricket::Session::State state);
- void OnSessionInfoMessage(cricket::Session* session,
- const cricket::Session::XmlElements& els);
- void OnSessionChannelGone(cricket::Session* session,
- const std::string& name);
-
- // HttpClient Signals
- void OnHttpClientComplete(talk_base::HttpClient* http, int err);
- void OnHttpClientClosed(talk_base::HttpClient* http, int err);
-
- // HttpServer Signals
- void OnHttpRequest(talk_base::HttpServer* server,
- talk_base::HttpTransaction* transaction);
- void OnHttpRequestComplete(talk_base::HttpServer* server,
- talk_base::HttpTransaction* transaction,
- int err);
- void OnHttpConnectionClosed(talk_base::HttpServer* server,
- int err,
- talk_base::StreamInterface* stream);
-
- // TarStream Signals
- void OnNextEntry(const std::string& name, size_t size);
-
- // Socket Signals
- void OnProxyAccept(talk_base::AsyncSocket* socket);
- void OnProxyClosed(StreamRelay* proxy, int error);
-
- // StreamCounterSignals
- void OnUpdateBytes(size_t count);
-
- // Internal Helpers
- void GenerateTemporaryPrefix(std::string* prefix);
- bool GetItemBaseUrl(size_t index, bool preview, std::string* url);
- bool GetProxyAddress(talk_base::SocketAddress& address, bool is_remote);
- talk_base::StreamInterface* CreateChannel(const std::string& channel_name);
- void SetState(FileShareState state, bool prevent_close);
- void OnInitiate();
- void NextDownload();
- const FileShareDescription* description() const;
- void DoClose(bool terminate);
-
- cricket::Session* session_;
- FileShareState state_;
- bool is_closed_;
- bool is_sender_;
- buzz::Jid jid_;
- FileShareManifest* manifest_;
- std::string source_path_;
- std::string preview_path_;
- std::string local_folder_;
-
- // The currently active p2p streams to our peer
- talk_base::StreamCache pool_;
- // The http client state (client only)
- talk_base::HttpClient* http_client_;
- // The http server state (server only)
- talk_base::HttpServer* http_server_;
- // The connection id of the currently transferring file (server)
- int transfer_connection_id_;
- // The counter for the currently transferring file
- const StreamCounter* counter_;
- // The number of manifest items that have successfully transferred
- size_t item_transferring_;
- // The byte count of successfully transferred items
- size_t bytes_transferred_;
- // Where the currently transferring item is being (temporarily) saved (client)
- std::string transfer_path_;
- // The name of the currently transferring item
- std::string transfer_name_;
- // Where the files are saved after transfer (client)
- std::vector<std::string> stored_location_;
- // Was it a local cancel? Or a remote cancel?
- bool local_cancel_;
- // Proxy socket for local IE http requests
- talk_base::AsyncSocket* local_listener_;
- // Proxy socket for remote IE http requests
- talk_base::AsyncSocket* remote_listener_;
- // Cached address of remote_listener_
- talk_base::SocketAddress remote_listener_address_;
- // Uniqueness for channel names
- size_t next_channel_id_;
- // Proxy relays
- ProxyList proxies_;
- std::string user_agent_;
- TransactionList transactions_;
-};
-
-class FileShareSessionClient : public SessionClient
-{
- public:
- FileShareSessionClient(SessionManager *sm, buzz::Jid jid, const std::string &user_agent) : sm_(sm), jid_(jid),
- user_agent_(user_agent) {}
- virtual void OnSessionCreate(cricket::Session* session,
- bool received_initiate);
- virtual void OnSessionDestroy(cricket::Session* session);
- virtual const cricket::SessionDescription* CreateSessionDescription(const buzz::XmlElement* element);
- virtual buzz::XmlElement* TranslateSessionDescription(const cricket::SessionDescription* description);
- FileShareSession *CreateFileShareSession();
-
- sigslot::signal1<FileShareSession*> SignalFileShareSessionCreate;
- sigslot::signal1<FileShareSession*> SignalFileShareSessionDestroy;
-
- private:
- SessionManager *sm_;
- buzz::Jid jid_;
- friend class FileShareSession;
- typedef std::set<cricket::Session*> SessionSet;
- SessionSet sessions_;
- std::string user_agent_;
-};
-
-} // namespace cricket
-
-#endif // TALK_APP_WIN32_FILESHARE_H__
diff --git a/talk/session/phone/Makefile.am b/talk/session/phone/Makefile.am
deleted file mode 100755
index 5d489b6..0000000
--- a/talk/session/phone/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-EXTRA_DIST=gipslitemediaengine.cc gipslitemediaengine.h
-if GIPS
-nodist_libcricketsessionphone_la_SOURCES=gipsmediaengine.cc \
- gipsstatsmonitor.cc
-else
-dist_libcricketsessionphone_la_SOURCES=linphonemediaengine.cc
-endif
-
-libcricketsessionphone_la_SOURCES = audiomonitor.cc \
- channelmanager.cc \
- voicechannel.cc \
- call.cc \
- phonesessionclient.cc
-
-noinst_HEADERS = audiomonitor.h \
- channelmanager.h \
- linphonemediaengine.h \
- mediaengine.h \
- phonesessionclient.h \
- voicechannel.h \
- call.h \
- mediachannel.h \
- codec.h
-
-AM_CPPFLAGS := -DPOSIX $(ORTP_CFLAGS) $(ILBC_CFLAGS) -I$(top_srcdir)/talk/third_party/mediastreamer $(GLIB_CFLAGS)
-noinst_LTLIBRARIES = libcricketsessionphone.la
-
diff --git a/talk/session/phone/audiomonitor.cc b/talk/session/phone/audiomonitor.cc
old mode 100755
new mode 100644
index c1f3614..d980ded
--- a/talk/session/phone/audiomonitor.cc
+++ b/talk/session/phone/audiomonitor.cc
@@ -89,7 +89,7 @@
assert(talk_base::Thread::Current() == monitoring_thread_);
AudioInfo info = audio_info_;
crit_.Leave();
- SignalUpdate(this, audio_info_);
+ SignalUpdate(this, info);
crit_.Enter();
}
break;
@@ -103,6 +103,7 @@
// Gather connection infos
audio_info_.input_level = voice_channel_->GetInputLevel_w();
audio_info_.output_level = voice_channel_->GetOutputLevel_w();
+ voice_channel_->GetActiveStreams_w(&audio_info_.active_streams);
// Signal the monitoring thread, start another poll timer
monitoring_thread_->Post(this, MSG_MONITOR_SIGNAL);
diff --git a/talk/session/phone/audiomonitor.h b/talk/session/phone/audiomonitor.h
old mode 100755
new mode 100644
index 2bfd784..e94ea68
--- a/talk/session/phone/audiomonitor.h
+++ b/talk/session/phone/audiomonitor.h
@@ -37,10 +37,11 @@
class VoiceChannel;
-
struct AudioInfo {
int input_level;
int output_level;
+ typedef std::vector<std::pair<uint32, int> > StreamList;
+ StreamList active_streams; // ssrcs contributing to output_level
};
class AudioMonitor : public talk_base::MessageHandler,
diff --git a/talk/session/phone/call.cc b/talk/session/phone/call.cc
old mode 100755
new mode 100644
index 1676945..c85be6a
--- a/talk/session/phone/call.cc
+++ b/talk/session/phone/call.cc
@@ -1,30 +1,31 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2007, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <string>
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/thread.h"
@@ -34,18 +35,20 @@
const uint32 MSG_CHECKAUTODESTROY = 1;
const uint32 MSG_TERMINATECALL = 2;
+const uint32 MSG_PLAYDTMF = 3;
namespace {
+const int kDTMFDelay = 300; // msec
+const size_t kMaxDTMFDigits = 30;
const int kSendToVoicemailTimeout = 1000*20;
const int kNoVoicemailTimeout = 1000*180;
const int kMediaMonitorInterval = 1000*15;
}
-Call::Call(PhoneSessionClient *session_client)
- : muted_(false), send_to_voicemail_(true)
-{
- session_client_ = session_client;
- id_ = CreateRandomId();
+Call::Call(MediaSessionClient *session_client, bool video, bool mux)
+ : id_(talk_base::CreateRandomId()), session_client_(session_client),
+ local_renderer_(NULL), video_(video), mux_(mux),
+ muted_(false), send_to_voicemail_(true), playing_dtmf_(false) {
}
Call::~Call() {
@@ -57,60 +60,57 @@
talk_base::Thread::Current()->Clear(this);
}
-Session *Call::InitiateSession(const buzz::Jid &jid,
- std::vector<buzz::XmlElement*>* extra_xml) {
- Session *session = session_client_->CreateSession(this);
- AddSession(session);
- session->Initiate(jid.Str(), extra_xml,
- session_client_->CreateOfferSessionDescription());
+Session *Call::InitiateSession(const buzz::Jid &jid) {
+ const SessionDescription* offer = session_client_->CreateOffer(video_, mux_);
- // After this timeout, terminate the call because the callee isn't
+ Session *session = session_client_->CreateSession(this);
+ AddSession(session, offer);
+ session->Initiate(jid.Str(), offer);
+
+ // After this timeout, terminate the call because the callee isn't
// answering
- session_client_->session_manager()->signaling_thread()->Clear(this,
+ session_client_->session_manager()->signaling_thread()->Clear(this,
MSG_TERMINATECALL);
session_client_->session_manager()->signaling_thread()->PostDelayed(
- send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
+ send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
this, MSG_TERMINATECALL);
return session;
}
-void Call::AcceptSession(Session *session) {
+void Call::IncomingSession(
+ Session* session, const SessionDescription* offer) {
+ AddSession(session, offer);
+
+ // Missed the first state, the initiate, which is needed by
+ // call_client.
+ SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE);
+}
+
+void Call::AcceptSession(BaseSession *session) {
std::vector<Session *>::iterator it;
it = std::find(sessions_.begin(), sessions_.end(), session);
- assert(it != sessions_.end());
+ ASSERT(it != sessions_.end());
if (it != sessions_.end()) {
- session->Accept(session_client_->CreateAcceptSessionDescription(
- session->remote_description()));
+ session->Accept(
+ session_client_->CreateAnswer(session->remote_description()));
}
}
-void Call::RedirectSession(Session *session, const buzz::Jid &to) {
+void Call::RejectSession(BaseSession *session) {
std::vector<Session *>::iterator it;
it = std::find(sessions_.begin(), sessions_.end(), session);
- assert(it != sessions_.end());
+ ASSERT(it != sessions_.end());
+ // Assume polite decline.
if (it != sessions_.end())
- session->Redirect(to.Str());
-
- session_client_->session_manager()->signaling_thread()->Clear(this,
- MSG_TERMINATECALL);
- session_client_->session_manager()->signaling_thread()->PostDelayed(
- send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
- this, MSG_TERMINATECALL);
+ session->Reject(STR_TERMINATE_DECLINE);
}
-void Call::RejectSession(Session *session) {
- std::vector<Session *>::iterator it;
- it = std::find(sessions_.begin(), sessions_.end(), session);
- assert(it != sessions_.end());
- if (it != sessions_.end())
- session->Reject();
-}
-
-void Call::TerminateSession(Session *session) {
- assert(std::find(sessions_.begin(), sessions_.end(), session)
+void Call::TerminateSession(BaseSession *session) {
+ ASSERT(std::find(sessions_.begin(), sessions_.end(), session)
!= sessions_.end());
std::vector<Session *>::iterator it;
it = std::find(sessions_.begin(), sessions_.end(), session);
+ // Assume polite terminations.
if (it != sessions_.end())
(*it)->Terminate();
}
@@ -123,7 +123,45 @@
std::vector<Session *>::iterator it;
for (it = sessions.begin(); it != sessions.end(); it++)
TerminateSession(*it);
-
+}
+
+void Call::SetLocalRenderer(VideoRenderer* renderer) {
+ local_renderer_ = renderer;
+ if (session_client_->GetFocus() == this) {
+ session_client_->channel_manager()->SetLocalRenderer(renderer);
+ }
+}
+
+void Call::SetVideoRenderer(BaseSession *session, uint32 ssrc,
+ VideoRenderer* renderer) {
+ VideoChannel *video_channel = GetVideoChannel(session);
+ if (video_channel) {
+ video_channel->SetRenderer(ssrc, renderer);
+ }
+}
+
+void Call::AddStream(BaseSession *session,
+ uint32 voice_ssrc, uint32 video_ssrc) {
+ VoiceChannel *voice_channel = GetVoiceChannel(session);
+ VideoChannel *video_channel = GetVideoChannel(session);
+ if (voice_channel && voice_ssrc) {
+ voice_channel->AddStream(voice_ssrc);
+ }
+ if (video_channel && video_ssrc) {
+ video_channel->AddStream(video_ssrc, voice_ssrc);
+ }
+}
+
+void Call::RemoveStream(BaseSession *session,
+ uint32 voice_ssrc, uint32 video_ssrc) {
+ VoiceChannel *voice_channel = GetVoiceChannel(session);
+ VideoChannel *video_channel = GetVideoChannel(session);
+ if (voice_channel && voice_ssrc) {
+ voice_channel->RemoveStream(voice_ssrc);
+ }
+ if (video_channel && video_ssrc) {
+ video_channel->RemoveStream(video_ssrc);
+ }
}
void Call::OnMessage(talk_base::Message *message) {
@@ -143,6 +181,8 @@
// Callee didn't answer - terminate call
Terminate();
break;
+ case MSG_PLAYDTMF:
+ ContinuePlayDTMF();
}
}
@@ -150,28 +190,64 @@
return sessions_;
}
-void Call::AddSession(Session *session) {
- // Add session to list, create voice channel for this session
- sessions_.push_back(session);
- session->SignalState.connect(this, &Call::OnSessionState);
- session->SignalError.connect(this, &Call::OnSessionError);
- session->SignalReceivedTerminateReason
- .connect(this, &Call::OnReceivedTerminateReason);
+bool Call::AddSession(Session *session, const SessionDescription* offer) {
+ bool succeeded = true;
+ VoiceChannel *voice_channel = NULL;
+ VideoChannel *video_channel = NULL;
- VoiceChannel *channel
- = session_client_->channel_manager()->CreateVoiceChannel(session);
- channel_map_[session->id()] = channel;
+ const ContentInfo* audio_offer = GetFirstAudioContent(offer);
+ ASSERT(audio_offer != NULL);
+ // Create voice channel and start a media monitor
+ voice_channel = session_client_->channel_manager()->CreateVoiceChannel(
+ session, audio_offer->name, video_);
+ // voice_channel can be NULL in case of NullVoiceEngine.
+ if (voice_channel) {
+ voice_channel_map_[session->id()] = voice_channel;
- // Start the media monitor for this voicechannel
- channel->SignalMediaMonitor.connect(this, &Call::OnMediaMonitor);
- channel->StartMediaMonitor(kMediaMonitorInterval);
+ voice_channel->SignalMediaMonitor.connect(this, &Call::OnMediaMonitor);
+ voice_channel->StartMediaMonitor(kMediaMonitorInterval);
+ } else {
+ succeeded = false;
+ }
- // If this call has the focus, enable this channel
- if (session_client_->GetFocus() == this)
- channel->Enable(true);
+ // If desired, create video channel and start a media monitor
+ if (video_ && succeeded) {
+ const ContentInfo* video_offer = GetFirstVideoContent(offer);
+ ASSERT(video_offer != NULL);
+ video_channel = session_client_->channel_manager()->CreateVideoChannel(
+ session, video_offer->name, true, voice_channel);
+ // video_channel can be NULL in case of NullVideoEngine.
+ if (video_channel) {
+ video_channel_map_[session->id()] = video_channel;
- // Signal client
- SignalAddSession(this, session);
+ video_channel->SignalMediaMonitor.connect(this, &Call::OnMediaMonitor);
+ video_channel->StartMediaMonitor(kMediaMonitorInterval);
+ } else {
+ succeeded = false;
+ }
+ }
+
+ if (succeeded) {
+ // Add session to list, create channels for this session
+ sessions_.push_back(session);
+ session->SignalState.connect(this, &Call::OnSessionState);
+ session->SignalError.connect(this, &Call::OnSessionError);
+ session->SignalReceivedTerminateReason
+ .connect(this, &Call::OnReceivedTerminateReason);
+
+ // If this call has the focus, enable this channel
+ if (session_client_->GetFocus() == this) {
+ voice_channel->Enable(true);
+ if (video_channel) {
+ video_channel->Enable(true);
+ }
+ }
+
+ // Signal client
+ SignalAddSession(this, session);
+ }
+
+ return succeeded;
}
void Call::RemoveSession(Session *session) {
@@ -182,51 +258,104 @@
return;
sessions_.erase(it_session);
- // Destroy session channel
- std::map<SessionID, VoiceChannel *>::iterator it_channel;
- it_channel = channel_map_.find(session->id());
- if (it_channel != channel_map_.end()) {
- VoiceChannel *channel = it_channel->second;
- channel_map_.erase(it_channel);
- channel->StopMediaMonitor();
- session_client_->channel_manager()->DestroyVoiceChannel(channel);
+ // Destroy video channel
+ std::map<std::string, VideoChannel *>::iterator it_vchannel;
+ it_vchannel = video_channel_map_.find(session->id());
+ if (it_vchannel != video_channel_map_.end()) {
+ VideoChannel *video_channel = it_vchannel->second;
+ video_channel_map_.erase(it_vchannel);
+ session_client_->channel_manager()->DestroyVideoChannel(video_channel);
+ }
+
+ // Destroy voice channel
+ std::map<std::string, VoiceChannel *>::iterator it_channel;
+ it_channel = voice_channel_map_.find(session->id());
+ if (it_channel != voice_channel_map_.end()) {
+ VoiceChannel *voice_channel = it_channel->second;
+ voice_channel_map_.erase(it_channel);
+ session_client_->channel_manager()->DestroyVoiceChannel(voice_channel);
}
// Signal client
SignalRemoveSession(this, session);
-
-
- // The call auto destroys when the lass session is removed
+ // The call auto destroys when the last session is removed
talk_base::Thread::Current()->Post(this, MSG_CHECKAUTODESTROY);
}
-VoiceChannel* Call::GetChannel(Session* session) {
- std::map<SessionID, VoiceChannel *>::iterator it
- = channel_map_.find(session->id());
- assert(it != channel_map_.end());
- return it->second;
+VoiceChannel* Call::GetVoiceChannel(BaseSession* session) {
+ std::map<std::string, VoiceChannel *>::iterator it
+ = voice_channel_map_.find(session->id());
+ return (it != voice_channel_map_.end()) ? it->second : NULL;
+}
+
+VideoChannel* Call::GetVideoChannel(BaseSession* session) {
+ std::map<std::string, VideoChannel *>::iterator it
+ = video_channel_map_.find(session->id());
+ return (it != video_channel_map_.end()) ? it->second : NULL;
}
void Call::EnableChannels(bool enable) {
std::vector<Session *>::iterator it;
for (it = sessions_.begin(); it != sessions_.end(); it++) {
- VoiceChannel *channel = channel_map_[(*it)->id()];
- if (channel != NULL)
- channel->Enable(enable);
+ VoiceChannel *voice_channel = GetVoiceChannel(*it);
+ VideoChannel *video_channel = GetVideoChannel(*it);
+ if (voice_channel != NULL)
+ voice_channel->Enable(enable);
+ if (video_channel != NULL)
+ video_channel->Enable(enable);
}
+ session_client_->channel_manager()->SetLocalRenderer(
+ (enable) ? local_renderer_ : NULL);
}
void Call::Mute(bool mute) {
muted_ = mute;
std::vector<Session *>::iterator it;
for (it = sessions_.begin(); it != sessions_.end(); it++) {
- VoiceChannel *channel = channel_map_[(*it)->id()];
- if (channel != NULL)
- channel->Mute(mute);
+ VoiceChannel *voice_channel = voice_channel_map_[(*it)->id()];
+ if (voice_channel != NULL)
+ voice_channel->Mute(mute);
}
}
+void Call::PressDTMF(int event) {
+ // Queue up this digit
+ if (queued_dtmf_.size() < kMaxDTMFDigits) {
+ LOG(LS_INFO) << "Call::PressDTMF(" << event << ")";
+
+ queued_dtmf_.push_back(event);
+
+ if (!playing_dtmf_) {
+ ContinuePlayDTMF();
+ }
+ }
+}
+
+void Call::ContinuePlayDTMF() {
+ playing_dtmf_ = false;
+
+ // Check to see if we have a queued tone
+ if (queued_dtmf_.size() > 0) {
+ playing_dtmf_ = true;
+
+ int tone = queued_dtmf_.front();
+ queued_dtmf_.pop_front();
+
+ LOG(LS_INFO) << "Call::ContinuePlayDTMF(" << tone << ")";
+ std::vector<Session *>::iterator it;
+ for (it = sessions_.begin(); it != sessions_.end(); it++) {
+ VoiceChannel *voice_channel = voice_channel_map_[(*it)->id()];
+ if (voice_channel != NULL) {
+ voice_channel->PressDTMF(tone, true);
+ }
+ }
+
+ // Post a message to play the next tone or at least clear the playing_dtmf_
+ // bit.
+ talk_base::Thread::Current()->PostDelayed(kDTMFDelay, this, MSG_PLAYDTMF);
+ }
+}
void Call::Join(Call *call, bool enable) {
while (call->sessions_.size() != 0) {
@@ -239,98 +368,125 @@
session->SignalReceivedTerminateReason
.connect(this, &Call::OnReceivedTerminateReason);
- // Move channel
- std::map<SessionID, VoiceChannel *>::iterator it_channel;
- it_channel = call->channel_map_.find(session->id());
- if (it_channel != call->channel_map_.end()) {
- VoiceChannel *channel = (*it_channel).second;
- call->channel_map_.erase(it_channel);
- channel_map_[session->id()] = channel;
- channel->Enable(enable);
+ // Move voice channel
+ std::map<std::string, VoiceChannel *>::iterator it_channel;
+ it_channel = call->voice_channel_map_.find(session->id());
+ if (it_channel != call->voice_channel_map_.end()) {
+ VoiceChannel *voice_channel = (*it_channel).second;
+ call->voice_channel_map_.erase(it_channel);
+ voice_channel_map_[session->id()] = voice_channel;
+ voice_channel->Enable(enable);
+ }
+
+ // Move video channel
+ std::map<std::string, VideoChannel *>::iterator it_vchannel;
+ it_vchannel = call->video_channel_map_.find(session->id());
+ if (it_vchannel != call->video_channel_map_.end()) {
+ VideoChannel *video_channel = (*it_vchannel).second;
+ call->video_channel_map_.erase(it_vchannel);
+ video_channel_map_[session->id()] = video_channel;
+ video_channel->Enable(enable);
}
}
}
-void Call::StartConnectionMonitor(Session *session, int cms) {
- std::map<SessionID, VoiceChannel *>::iterator it_channel;
- it_channel = channel_map_.find(session->id());
- if (it_channel != channel_map_.end()) {
- VoiceChannel *channel = (*it_channel).second;
- channel->SignalConnectionMonitor.connect(this, &Call::OnConnectionMonitor);
- channel->StartConnectionMonitor(cms);
+void Call::StartConnectionMonitor(BaseSession *session, int cms) {
+ VoiceChannel *voice_channel = GetVoiceChannel(session);
+ if (voice_channel) {
+ voice_channel->SignalConnectionMonitor.connect(this,
+ &Call::OnConnectionMonitor);
+ voice_channel->StartConnectionMonitor(cms);
+ }
+
+ VideoChannel *video_channel = GetVideoChannel(session);
+ if (video_channel) {
+ video_channel->SignalConnectionMonitor.connect(this,
+ &Call::OnConnectionMonitor);
+ video_channel->StartConnectionMonitor(cms);
}
}
-void Call::StopConnectionMonitor(Session *session) {
- std::map<SessionID, VoiceChannel *>::iterator it_channel;
- it_channel = channel_map_.find(session->id());
- if (it_channel != channel_map_.end()) {
- VoiceChannel *channel = (*it_channel).second;
- channel->StopConnectionMonitor();
- channel->SignalConnectionMonitor.disconnect(this);
+void Call::StopConnectionMonitor(BaseSession *session) {
+ VoiceChannel *voice_channel = GetVoiceChannel(session);
+ if (voice_channel) {
+ voice_channel->StopConnectionMonitor();
+ voice_channel->SignalConnectionMonitor.disconnect(this);
+ }
+
+ VideoChannel *video_channel = GetVideoChannel(session);
+ if (video_channel) {
+ video_channel->StopConnectionMonitor();
+ video_channel->SignalConnectionMonitor.disconnect(this);
}
}
-void Call::StartAudioMonitor(Session *session, int cms) {
- std::map<SessionID, VoiceChannel *>::iterator it_channel;
- it_channel = channel_map_.find(session->id());
- if (it_channel != channel_map_.end()) {
- VoiceChannel *channel = (*it_channel).second;
- channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor);
- channel->StartAudioMonitor(cms);
+void Call::StartAudioMonitor(BaseSession *session, int cms) {
+ VoiceChannel *voice_channel = GetVoiceChannel(session);
+ if (voice_channel) {
+ voice_channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor);
+ voice_channel->StartAudioMonitor(cms);
}
}
-void Call::StopAudioMonitor(Session *session) {
- std::map<SessionID, VoiceChannel *>::iterator it_channel;
- it_channel = channel_map_.find(session->id());
- if (it_channel != channel_map_.end()) {
- VoiceChannel *channel = (*it_channel).second;
- channel->StopAudioMonitor();
- channel->SignalAudioMonitor.disconnect(this);
+void Call::StopAudioMonitor(BaseSession *session) {
+ VoiceChannel *voice_channel = GetVoiceChannel(session);
+ if (voice_channel) {
+ voice_channel->StopAudioMonitor();
+ voice_channel->SignalAudioMonitor.disconnect(this);
}
}
-
-void Call::OnConnectionMonitor(VoiceChannel *channel,
+void Call::OnConnectionMonitor(VoiceChannel *channel,
const std::vector<ConnectionInfo> &infos) {
- SignalConnectionMonitor(this, channel->session(), infos);
-}
-
-void Call::OnAudioMonitor(VoiceChannel *channel, const AudioInfo& info) {
- SignalAudioMonitor(this, channel->session(), info);
+ SignalConnectionMonitor(this, infos);
}
void Call::OnMediaMonitor(VoiceChannel *channel, const MediaInfo& info) {
- SignalMediaMonitor(this, channel->session(), info);
+ SignalMediaMonitor(this, info);
+}
+
+void Call::OnAudioMonitor(VoiceChannel *channel, const AudioInfo& info) {
+ SignalAudioMonitor(this, info);
+}
+
+void Call::OnConnectionMonitor(VideoChannel *channel,
+ const std::vector<ConnectionInfo> &infos) {
+ SignalVideoConnectionMonitor(this, infos);
+}
+
+void Call::OnMediaMonitor(VideoChannel *channel, const MediaInfo& info) {
+ SignalVideoMediaMonitor(this, info);
}
uint32 Call::id() {
return id_;
}
-void Call::OnSessionState(Session *session, Session::State state) {
+void Call::OnSessionState(BaseSession *session, BaseSession::State state) {
switch (state) {
case Session::STATE_RECEIVEDACCEPT:
case Session::STATE_RECEIVEDREJECT:
case Session::STATE_RECEIVEDTERMINATE:
- session_client_->session_manager()->signaling_thread()->Clear(this,
+ session_client_->session_manager()->signaling_thread()->Clear(this,
MSG_TERMINATECALL);
break;
+ default:
+ break;
}
SignalSessionState(this, session, state);
}
-void Call::OnSessionError(Session *session, Session::Error error) {
- session_client_->session_manager()->signaling_thread()->Clear(this,
+void Call::OnSessionError(BaseSession *session, Session::Error error) {
+ session_client_->session_manager()->signaling_thread()->Clear(this,
MSG_TERMINATECALL);
SignalSessionError(this, session, error);
}
-void Call::OnReceivedTerminateReason(Session *session, const std::string &reason) {
+void Call::OnReceivedTerminateReason(Session *session,
+ const std::string &reason) {
session_client_->session_manager()->signaling_thread()->Clear(this,
MSG_TERMINATECALL);
SignalReceivedTerminateReason(this, session, reason);
}
-}
+} // namespace cricket
diff --git a/talk/session/phone/call.h b/talk/session/phone/call.h
old mode 100755
new mode 100644
index 7b8d9b6..de92086
--- a/talk/session/phone/call.h
+++ b/talk/session/phone/call.h
@@ -2,69 +2,74 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CALL_H_
-#define _CALL_H_
+#ifndef TALK_SESSION_PHONE_CALL_H_
+#define TALK_SESSION_PHONE_CALL_H_
+#include <string>
+#include <map>
+#include <vector>
+#include <deque>
#include "talk/base/messagequeue.h"
#include "talk/p2p/base/session.h"
#include "talk/p2p/client/socketmonitor.h"
#include "talk/xmpp/jid.h"
-#include "talk/session/phone/phonesessionclient.h"
+#include "talk/session/phone/mediasessionclient.h"
#include "talk/session/phone/voicechannel.h"
#include "talk/session/phone/audiomonitor.h"
-#include <map>
-#include <vector>
-#include <deque>
-
namespace cricket {
-class PhoneSessionClient;
+class MediaSessionClient;
class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
-public:
- Call(PhoneSessionClient *session_client);
+ public:
+ Call(MediaSessionClient *session_client,
+ bool video = false, bool mux = false);
~Call();
- Session *InitiateSession(const buzz::Jid &jid,
- std::vector<buzz::XmlElement*>* extra_xml);
- void AcceptSession(Session *session);
- void RedirectSession(Session *session, const buzz::Jid &to);
- void RejectSession(Session *session);
- void TerminateSession(Session *session);
+ Session *InitiateSession(const buzz::Jid &jid);
+ void AcceptSession(BaseSession *session);
+ void RejectSession(BaseSession *session);
+ void TerminateSession(BaseSession *session);
void Terminate();
- void StartConnectionMonitor(Session *session, int cms);
- void StopConnectionMonitor(Session *session);
- void StartAudioMonitor(Session *session, int cms);
- void StopAudioMonitor(Session *session);
+ void SetLocalRenderer(VideoRenderer* renderer);
+ void SetVideoRenderer(BaseSession *session, uint32 ssrc,
+ VideoRenderer* renderer);
+ void AddStream(BaseSession *session, uint32 voice_ssrc, uint32 video_ssrc);
+ void RemoveStream(BaseSession *session, uint32 voice_ssrc, uint32 video_ssrc);
+ void StartConnectionMonitor(BaseSession *session, int cms);
+ void StopConnectionMonitor(BaseSession *session);
+ void StartAudioMonitor(BaseSession *session, int cms);
+ void StopAudioMonitor(BaseSession *session);
void Mute(bool mute);
-
+ void PressDTMF(int event);
const std::vector<Session *> &sessions();
uint32 id();
+ bool video() const { return video_; }
bool muted() const { return muted_; }
// Setting this to false will cause the call to have a longer timeout and
@@ -73,44 +78,69 @@
send_to_voicemail_ = send_to_voicemail;
}
bool send_to_voicemail() { return send_to_voicemail_; }
-
+
// Sets a flag on the chatapp that will redirect the call to voicemail once
// the call has been terminated
sigslot::signal0<> SignalSetupToCallVoicemail;
sigslot::signal2<Call *, Session *> SignalAddSession;
sigslot::signal2<Call *, Session *> SignalRemoveSession;
- sigslot::signal3<Call *, Session *, Session::State> SignalSessionState;
- sigslot::signal3<Call *, Session *, Session::Error> SignalSessionError;
- sigslot::signal3<Call *, Session *, const std::string &> SignalReceivedTerminateReason;
- sigslot::signal3<Call *, Session *, const std::vector<ConnectionInfo> &> SignalConnectionMonitor;
- sigslot::signal3<Call *, Session *, const AudioInfo&> SignalAudioMonitor;
- sigslot::signal3<Call *, Session *, const MediaInfo&> SignalMediaMonitor;
+ sigslot::signal3<Call *, BaseSession *, BaseSession::State>
+ SignalSessionState;
+ sigslot::signal3<Call *, BaseSession *, Session::Error>
+ SignalSessionError;
+ sigslot::signal3<Call *, Session *, const std::string &>
+ SignalReceivedTerminateReason;
+ sigslot::signal2<Call *, const std::vector<ConnectionInfo> &>
+ SignalConnectionMonitor;
+ sigslot::signal2<Call *, const MediaInfo&> SignalMediaMonitor;
+ sigslot::signal2<Call *, const AudioInfo&> SignalAudioMonitor;
+ sigslot::signal2<Call *, const std::vector<ConnectionInfo> &>
+ SignalVideoConnectionMonitor;
+ sigslot::signal2<Call *, const MediaInfo&> SignalVideoMediaMonitor;
-private:
+ private:
void OnMessage(talk_base::Message *message);
- void OnSessionState(Session *session, Session::State state);
- void OnSessionError(Session *session, Session::Error error);
+ void OnSessionState(BaseSession *session, BaseSession::State state);
+ void OnSessionError(BaseSession *session, Session::Error error);
void OnReceivedTerminateReason(Session *session, const std::string &reason);
- void AddSession(Session *session);
+ void IncomingSession(Session *session, const SessionDescription* offer);
+ // Returns true on success.
+ bool AddSession(Session *session, const SessionDescription* offer);
void RemoveSession(Session *session);
void EnableChannels(bool enable);
void Join(Call *call, bool enable);
- void OnConnectionMonitor(VoiceChannel *channel, const std::vector<ConnectionInfo> &infos);
- void OnAudioMonitor(VoiceChannel *channel, const AudioInfo& info);
+ void OnConnectionMonitor(VoiceChannel *channel,
+ const std::vector<ConnectionInfo> &infos);
void OnMediaMonitor(VoiceChannel *channel, const MediaInfo& info);
- VoiceChannel* GetChannel(Session* session);
+ void OnAudioMonitor(VoiceChannel *channel, const AudioInfo& info);
+ void OnConnectionMonitor(VideoChannel *channel,
+ const std::vector<ConnectionInfo> &infos);
+ void OnMediaMonitor(VideoChannel *channel, const MediaInfo& info);
+ VoiceChannel* GetVoiceChannel(BaseSession* session);
+ VideoChannel* GetVideoChannel(BaseSession* session);
+ void ContinuePlayDTMF();
uint32 id_;
- PhoneSessionClient *session_client_;
+ MediaSessionClient *session_client_;
std::vector<Session *> sessions_;
- std::map<SessionID, VoiceChannel *> channel_map_;
+ std::map<std::string, VoiceChannel *> voice_channel_map_;
+ std::map<std::string, VideoChannel *> video_channel_map_;
+ VideoRenderer* local_renderer_;
+ bool video_;
+ bool mux_;
bool muted_;
bool send_to_voicemail_;
+ // DTMF tones have to be queued up so that we don't flood the call. We
+ // keep a deque (doubely ended queue) of them around. While one is playing we
+ // set the playing_dtmf_ bit and schedule a message in XX msec to clear that
+ // bit or start the next tone playing.
+ std::deque<int> queued_dtmf_;
+ bool playing_dtmf_;
- friend class PhoneSessionClient;
+ friend class MediaSessionClient;
};
-}
+} // namespace cricket
-#endif // _CALL_H_
+#endif // TALK_SESSION_PHONE_CALL_H_
diff --git a/talk/session/phone/channel.cc b/talk/session/phone/channel.cc
new file mode 100644
index 0000000..5fb1dab
--- /dev/null
+++ b/talk/session/phone/channel.cc
@@ -0,0 +1,1007 @@
+/*
+ * libjingle
+ * Copyright 2004--2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/phone/channel.h"
+#include "talk/base/byteorder.h"
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/p2p/base/transportchannel.h"
+#include "talk/session/phone/channelmanager.h"
+#include "talk/session/phone/mediasessionclient.h"
+
+namespace cricket {
+
+static const size_t kMaxPacketLen = 2048;
+
+static const char* PacketType(bool rtcp) {
+ return (!rtcp) ? "RTP" : "RTCP";
+}
+
+BaseChannel::BaseChannel(talk_base::Thread* thread, MediaEngine* media_engine,
+ MediaChannel* media_channel, BaseSession* session,
+ const std::string& content_name,
+ TransportChannel* transport_channel)
+ : worker_thread_(thread), media_engine_(media_engine),
+ session_(session), media_channel_(media_channel),
+ content_name_(content_name),
+ transport_channel_(transport_channel), rtcp_transport_channel_(NULL),
+ enabled_(false), writable_(false), has_codec_(false), muted_(false) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ media_channel_->SetInterface(this);
+ transport_channel_->SignalWritableState.connect(
+ this, &BaseChannel::OnWritableState);
+ transport_channel_->SignalReadPacket.connect(
+ this, &BaseChannel::OnChannelRead);
+
+ LOG(LS_INFO) << "Created channel";
+
+ session->SignalState.connect(this, &BaseChannel::OnSessionState);
+}
+
+BaseChannel::~BaseChannel() {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ StopConnectionMonitor();
+ Clear();
+ // We must destroy the media channel before the transport channel, otherwise
+ // the media channel may try to send on the dead transport channel. NULLing
+ // is not an effective strategy since the sends will come on another thread.
+ delete media_channel_;
+ set_rtcp_transport_channel(NULL);
+ if (transport_channel_ != NULL)
+ session_->DestroyChannel(content_name_, transport_channel_->name());
+ LOG(LS_INFO) << "Destroyed channel";
+}
+
+bool BaseChannel::Enable(bool enable) {
+ // Can be called from thread other than worker thread
+ Send(enable ? MSG_ENABLE : MSG_DISABLE);
+ return true;
+}
+
+bool BaseChannel::Mute(bool mute) {
+ // Can be called from thread other than worker thread
+ Send(mute ? MSG_MUTE : MSG_UNMUTE);
+ return true;
+}
+
+bool BaseChannel::RemoveStream(uint32 ssrc) {
+ StreamMessageData data(ssrc, 0);
+ Send(MSG_REMOVESTREAM, &data);
+ return true;
+}
+
+bool BaseChannel::SetRtcpCName(const std::string& cname) {
+ SetRtcpCNameData data(cname);
+ Send(MSG_SETRTCPCNAME, &data);
+ return data.result;
+}
+
+bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
+ ContentAction action) {
+ SetContentData data(content, action);
+ Send(MSG_SETLOCALCONTENT, &data);
+ return data.result;
+}
+
+bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
+ ContentAction action) {
+ SetContentData data(content, action);
+ Send(MSG_SETREMOTECONTENT, &data);
+ return data.result;
+}
+
+bool BaseChannel::SetMaxSendBandwidth(int max_bandwidth) {
+ SetBandwidthData data(max_bandwidth);
+ Send(MSG_SETMAXSENDBANDWIDTH, &data);
+ return data.result;
+}
+
+void BaseChannel::StartConnectionMonitor(int cms) {
+ socket_monitor_.reset(new SocketMonitor(transport_channel_,
+ worker_thread(),
+ talk_base::Thread::Current()));
+ socket_monitor_->SignalUpdate.connect(
+ this, &BaseChannel::OnConnectionMonitorUpdate);
+ socket_monitor_->Start(cms);
+}
+
+void BaseChannel::StopConnectionMonitor() {
+ if (socket_monitor_.get()) {
+ socket_monitor_->Stop();
+ socket_monitor_.reset();
+ }
+}
+
+void BaseChannel::set_rtcp_transport_channel(TransportChannel* channel) {
+ if (rtcp_transport_channel_ != channel) {
+ if (rtcp_transport_channel_) {
+ session_->DestroyChannel(content_name_, rtcp_transport_channel_->name());
+ }
+ rtcp_transport_channel_ = channel;
+ if (rtcp_transport_channel_) {
+ rtcp_transport_channel_->SignalWritableState.connect(
+ this, &BaseChannel::OnWritableState);
+ rtcp_transport_channel_->SignalReadPacket.connect(
+ this, &BaseChannel::OnChannelRead);
+ }
+ }
+}
+
+int BaseChannel::SendPacket(const void *data, size_t len) {
+ // SendPacket gets called from MediaEngine; send to socket
+ // MediaEngine will call us on a random thread. The Send operation on the
+ // socket is special in that it can handle this.
+ // TODO: Actually, SendPacket cannot handle this. Need to fix ASAP.
+
+ return SendPacket(false, data, len);
+}
+
+int BaseChannel::SendRtcp(const void *data, size_t len) {
+ return SendPacket(true, data, len);
+}
+
+int BaseChannel::SetOption(SocketType type, talk_base::Socket::Option opt,
+ int value) {
+ switch (type) {
+ case ST_RTP: return transport_channel_->SetOption(opt, value);
+ case ST_RTCP: return rtcp_transport_channel_->SetOption(opt, value);
+ default: return -1;
+ }
+}
+
+void BaseChannel::OnWritableState(TransportChannel* channel) {
+ ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
+ if (transport_channel_->writable()
+ && (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
+ ChannelWritable_w();
+ } else {
+ ChannelNotWritable_w();
+ }
+}
+
+void BaseChannel::OnChannelRead(TransportChannel* channel,
+ const char* data, size_t len) {
+ // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+ // When using RTCP multiplexing we might get RTCP packets on the RTP
+ // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
+ bool rtcp = (channel == rtcp_transport_channel_ ||
+ rtcp_mux_filter_.DemuxRtcp(data, len));
+ HandlePacket(rtcp, data, len);
+}
+
+int BaseChannel::SendPacket(bool rtcp, const void* data, size_t len) {
+ // Protect ourselves against crazy data.
+ if (len > kMaxPacketLen) {
+ LOG(LS_ERROR) << "Dropping outgoing large "
+ << PacketType(rtcp) << " packet, size " << len;
+ return -1;
+ }
+
+ // Make sure we have a place to send this packet before doing anything.
+ // (We might get RTCP packets that we don't intend to send.)
+ // If we've negotiated RTCP mux, send RTCP over the RTP transport.
+ TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
+ transport_channel_ : rtcp_transport_channel_;
+ if (!channel) {
+ return -1;
+ }
+
+ // Protect if needed.
+ uint8 work[kMaxPacketLen];
+ const char* real_data = static_cast<const char*>(data);
+ int real_len = len;
+ if (srtp_filter_.IsActive()) {
+ bool res;
+ memcpy(work, data, len);
+ if (!rtcp) {
+ res = srtp_filter_.ProtectRtp(work, len, sizeof(work), &real_len);
+ } else {
+ res = srtp_filter_.ProtectRtcp(work, len, sizeof(work), &real_len);
+ }
+ if (!res) {
+ LOG(LS_ERROR) << "Failed to protect "
+ << PacketType(rtcp) << " packet, size " << len;
+ return -1;
+ }
+
+ real_data = reinterpret_cast<const char*>(work);
+ }
+
+ // Bon voyage. Return a number that the caller can understand.
+ return (channel->SendPacket(real_data, real_len) == real_len) ? len : -1;
+}
+
+void BaseChannel::HandlePacket(bool rtcp, const char* data, size_t len) {
+ // Protect ourselvs against crazy data.
+ if (len > kMaxPacketLen) {
+ LOG(LS_ERROR) << "Dropping incoming large "
+ << PacketType(rtcp) << " packet, size " << len;
+ return;
+ }
+
+ // Unprotect the packet, if needed.
+ uint8 work[kMaxPacketLen];
+ const char* real_data = data;
+ int real_len = len;
+ if (srtp_filter_.IsActive()) {
+ bool res;
+ memcpy(work, data, len);
+ if (!rtcp) {
+ res = srtp_filter_.UnprotectRtp(work, len, &real_len);
+ } else {
+ res = srtp_filter_.UnprotectRtcp(work, len, &real_len);
+ }
+ if (!res) {
+ LOG(LS_ERROR) << "Failed to unprotect "
+ << PacketType(rtcp) << " packet, size " << len;
+ return;
+ }
+ real_data = reinterpret_cast<const char*>(work);
+ }
+
+ // Push it down to the media channel.
+ if (!rtcp) {
+ media_channel_->OnPacketReceived(real_data, real_len);
+ } else {
+ media_channel_->OnRtcpReceived(real_data, real_len);
+ }
+}
+
+void BaseChannel::OnSessionState(BaseSession* session,
+ BaseSession::State state) {
+ // TODO: tear down the call via session->SetError() if the
+ // SetXXXXDescription calls fail.
+ const MediaContentDescription* content = NULL;
+ switch (state) {
+ case Session::STATE_SENTINITIATE:
+ content = GetFirstContent(session->local_description());
+ if (content) {
+ SetLocalContent(content, CA_OFFER);
+ }
+ break;
+ case Session::STATE_SENTACCEPT:
+ content = GetFirstContent(session->local_description());
+ if (content) {
+ SetLocalContent(content, CA_ANSWER);
+ }
+ break;
+ case Session::STATE_RECEIVEDINITIATE:
+ content = GetFirstContent(session->remote_description());
+ if (content) {
+ SetRemoteContent(content, CA_OFFER);
+ }
+ break;
+ case Session::STATE_RECEIVEDACCEPT:
+ content = GetFirstContent(session->remote_description());
+ if (content) {
+ SetRemoteContent(content, CA_ANSWER);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void BaseChannel::EnableMedia_w() {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ if (enabled_)
+ return;
+
+ LOG(LS_INFO) << "Channel enabled";
+ enabled_ = true;
+ ChangeState();
+}
+
+void BaseChannel::DisableMedia_w() {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ if (!enabled_)
+ return;
+
+ LOG(LS_INFO) << "Channel disabled";
+ enabled_ = false;
+ ChangeState();
+}
+
+void BaseChannel::MuteMedia_w() {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ if (muted_)
+ return;
+
+ if (media_channel()->Mute(true)) {
+ LOG(LS_INFO) << "Channel muted";
+ muted_ = true;
+ }
+}
+
+void BaseChannel::UnmuteMedia_w() {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ if (!muted_)
+ return;
+
+ if (media_channel()->Mute(false)) {
+ LOG(LS_INFO) << "Channel unmuted";
+ muted_ = false;
+ }
+}
+
+void BaseChannel::ChannelWritable_w() {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ if (writable_)
+ return;
+ LOG(LS_INFO) << "Channel socket writable ("
+ << transport_channel_->name().c_str() << ")";
+ writable_ = true;
+ ChangeState();
+}
+
+void BaseChannel::ChannelNotWritable_w() {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ if (!writable_)
+ return;
+
+ LOG(LS_INFO) << "Channel socket not writable ("
+ << transport_channel_->name().c_str() << ")";
+ writable_ = false;
+ ChangeState();
+}
+
+bool BaseChannel::SetMaxSendBandwidth_w(int max_bandwidth) {
+ return media_channel()->SetMaxSendBandwidth(max_bandwidth);
+}
+
+bool BaseChannel::SetRtcpCName_w(const std::string& cname) {
+ return media_channel()->SetRtcpCName(cname);
+}
+
+bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
+ ContentAction action, ContentSource src) {
+ bool ret;
+ if (action == CA_OFFER) {
+ ret = srtp_filter_.SetOffer(cryptos, src);
+ } else if (action == CA_ANSWER) {
+ ret = srtp_filter_.SetAnswer(cryptos, src);
+ } else {
+ // CA_UPDATE, no crypto params.
+ ret = true;
+ }
+ return ret;
+}
+
+bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
+ ContentSource src) {
+ bool ret;
+ if (action == CA_OFFER) {
+ ret = rtcp_mux_filter_.SetOffer(enable, src);
+ } else if (action == CA_ANSWER) {
+ ret = rtcp_mux_filter_.SetAnswer(enable, src);
+ if (ret && rtcp_mux_filter_.IsActive()) {
+ // We activated RTCP mux, close down the RTCP transport.
+ set_rtcp_transport_channel(NULL);
+ // If the RTP transport is already writable, then so are we.
+ if (transport_channel_->writable()) {
+ ChannelWritable_w();
+ }
+ }
+ } else {
+ // CA_UPDATE, no RTCP mux info.
+ ret = true;
+ }
+ return ret;
+}
+
+void BaseChannel::OnMessage(talk_base::Message *pmsg) {
+ switch (pmsg->message_id) {
+ case MSG_ENABLE:
+ EnableMedia_w();
+ break;
+ case MSG_DISABLE:
+ DisableMedia_w();
+ break;
+
+ case MSG_MUTE:
+ MuteMedia_w();
+ break;
+ case MSG_UNMUTE:
+ UnmuteMedia_w();
+ break;
+
+ case MSG_SETRTCPCNAME: {
+ SetRtcpCNameData* data = static_cast<SetRtcpCNameData*>(pmsg->pdata);
+ data->result = SetRtcpCName_w(data->cname);
+ break;
+ }
+
+ case MSG_SETLOCALCONTENT: {
+ SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
+ data->result = SetLocalContent_w(data->content, data->action);
+ break;
+ }
+ case MSG_SETREMOTECONTENT: {
+ SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
+ data->result = SetRemoteContent_w(data->content, data->action);
+ break;
+ }
+
+ case MSG_REMOVESTREAM: {
+ StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
+ RemoveStream_w(data->ssrc1);
+ break;
+ }
+
+ case MSG_SETMAXSENDBANDWIDTH: {
+ SetBandwidthData* data = static_cast<SetBandwidthData*>(pmsg->pdata);
+ data->result = SetMaxSendBandwidth_w(data->value);
+ break;
+ }
+ }
+}
+
+void BaseChannel::Send(uint32 id, talk_base::MessageData *pdata) {
+ worker_thread_->Send(this, id, pdata);
+}
+
+void BaseChannel::Post(uint32 id, talk_base::MessageData *pdata) {
+ worker_thread_->Post(this, id, pdata);
+}
+
+void BaseChannel::PostDelayed(int cmsDelay, uint32 id,
+ talk_base::MessageData *pdata) {
+ worker_thread_->PostDelayed(cmsDelay, this, id, pdata);
+}
+
+void BaseChannel::Clear(uint32 id, talk_base::MessageList* removed) {
+ worker_thread_->Clear(this, id, removed);
+}
+
+VoiceChannel::VoiceChannel(talk_base::Thread* thread,
+ MediaEngine* media_engine,
+ VoiceMediaChannel* media_channel,
+ BaseSession* session,
+ const std::string& content_name,
+ bool rtcp)
+ : BaseChannel(thread, media_engine, media_channel, session, content_name,
+ session->CreateChannel(content_name, "rtp")),
+ received_media_(false) {
+ if (rtcp) {
+ set_rtcp_transport_channel(session->CreateChannel(content_name, "rtcp"));
+ }
+ // Can't go in BaseChannel because certain session states will
+ // trigger pure virtual functions, such as GetFirstContent().
+ OnSessionState(session, session->state());
+}
+
+VoiceChannel::~VoiceChannel() {
+ StopAudioMonitor();
+ StopMediaMonitor();
+ // this can't be done in the base class, since it calls a virtual
+ DisableMedia_w();
+}
+
+bool VoiceChannel::AddStream(uint32 ssrc) {
+ StreamMessageData data(ssrc, 0);
+ Send(MSG_ADDSTREAM, &data);
+ return true;
+}
+
+bool VoiceChannel::SetRingbackTone(const void* buf, int len) {
+ SetRingbackToneMessageData data(buf, len);
+ Send(MSG_SETRINGBACKTONE, &data);
+ return true;
+}
+
+// TODO: Handle early media the right way. We should get an explicit
+// ringing message telling us to start playing local ringback, which we cancel
+// if any early media actually arrives. For now, we do the opposite, which is
+// to wait 1 second for early media, and start playing local ringback if none
+// arrives.
+void VoiceChannel::SetEarlyMedia(bool enable) {
+ if (enable) {
+ // Start the early media timeout
+ PostDelayed(kEarlyMediaTimeout, MSG_EARLYMEDIATIMEOUT);
+ } else {
+ // Stop the timeout if currently going.
+ Clear(MSG_EARLYMEDIATIMEOUT);
+ }
+}
+
+bool VoiceChannel::PlayRingbackTone(bool play, bool loop) {
+ PlayRingbackToneMessageData data(play, loop);
+ Send(MSG_PLAYRINGBACKTONE, &data);
+ return data.result;
+}
+
+bool VoiceChannel::PressDTMF(int digit, bool playout) {
+ DtmfMessageData data(digit, playout);
+ Send(MSG_PRESSDTMF, &data);
+ return data.result;
+}
+
+void VoiceChannel::StartMediaMonitor(int cms) {
+ media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
+ talk_base::Thread::Current()));
+ media_monitor_->SignalUpdate.connect(
+ this, &VoiceChannel::OnMediaMonitorUpdate);
+ media_monitor_->Start(cms);
+}
+
+void VoiceChannel::StopMediaMonitor() {
+ if (media_monitor_.get()) {
+ media_monitor_->Stop();
+ media_monitor_->SignalUpdate.disconnect(this);
+ media_monitor_.reset();
+ }
+}
+
+void VoiceChannel::StartAudioMonitor(int cms) {
+ audio_monitor_.reset(new AudioMonitor(this, talk_base::Thread::Current()));
+ audio_monitor_
+ ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
+ audio_monitor_->Start(cms);
+}
+
+void VoiceChannel::StopAudioMonitor() {
+ if (audio_monitor_.get()) {
+ audio_monitor_->Stop();
+ audio_monitor_.reset();
+ }
+}
+
+int VoiceChannel::GetInputLevel_w() {
+ return media_engine()->GetInputLevel();
+}
+
+int VoiceChannel::GetOutputLevel_w() {
+ return media_channel()->GetOutputLevel();
+}
+
+void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
+ media_channel()->GetActiveStreams(actives);
+}
+
+void VoiceChannel::OnChannelRead(TransportChannel* channel,
+ const char* data, size_t len) {
+ BaseChannel::OnChannelRead(channel, data, len);
+
+ // Set a flag when we've received an RTP packet. If we're waiting for early
+ // media, this will disable the timeout.
+ // If we were playing out our local ringback, make sure it is stopped to
+ // prevent it from interfering with the incoming media.
+ if (!received_media_) {
+ received_media_ = false;
+ PlayRingbackTone_w(false, false);
+ }
+}
+
+void VoiceChannel::ChangeState() {
+ // render incoming data if we are the active call
+ // we receive data on the default channel and multiplexed streams
+ bool recv = enabled();
+ media_channel()->SetPlayout(recv);
+
+ // send outgoing data if we are the active call, have the
+ // remote party's codec, and have a writable transport
+ // we only send data on the default channel
+ bool send = enabled() && has_codec() && writable();
+ media_channel()->SetSend(send ? SEND_MICROPHONE : SEND_NOTHING);
+
+ LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
+}
+
+const MediaContentDescription* VoiceChannel::GetFirstContent(
+ const SessionDescription* sdesc) {
+ const ContentInfo* cinfo = GetFirstAudioContent(sdesc);
+ if (cinfo == NULL)
+ return NULL;
+
+ return static_cast<const MediaContentDescription*>(cinfo->description);
+}
+
+bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
+ ContentAction action) {
+ ASSERT(worker_thread() == talk_base::Thread::Current());
+ LOG(LS_INFO) << "Setting local voice description";
+
+ const AudioContentDescription* audio =
+ static_cast<const AudioContentDescription*>(content);
+ ASSERT(audio != NULL);
+
+ bool ret;
+ // set SRTP
+ ret = SetSrtp_w(audio->cryptos(), action, CS_LOCAL);
+ // set RTCP mux
+ if (ret) {
+ ret = SetRtcpMux_w(audio->rtcp_mux(), action, CS_LOCAL);
+ }
+ // set payload type and config for voice codecs
+ if (ret) {
+ ret = media_channel()->SetRecvCodecs(audio->codecs());
+ }
+ return ret;
+}
+
+bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
+ ContentAction action) {
+ ASSERT(worker_thread() == talk_base::Thread::Current());
+ LOG(LS_INFO) << "Setting remote voice description";
+
+ const AudioContentDescription* audio =
+ static_cast<const AudioContentDescription*>(content);
+ ASSERT(audio != NULL);
+
+ bool ret;
+ // set the sending SSRC, if the remote side gave us one
+ if (audio->ssrc_set()) {
+ media_channel()->SetSendSsrc(audio->ssrc());
+ }
+ // set SRTP
+ ret = SetSrtp_w(audio->cryptos(), action, CS_REMOTE);
+ // set RTCP mux
+ if (ret) {
+ ret = SetRtcpMux_w(audio->rtcp_mux(), action, CS_REMOTE);
+ }
+ // set codecs and payload types
+ if (ret) {
+ ret = media_channel()->SetSendCodecs(audio->codecs());
+ }
+
+
+ // update state
+ if (ret) {
+ set_has_codec(true);
+ ChangeState();
+ }
+ return ret;
+}
+
+void VoiceChannel::AddStream_w(uint32 ssrc) {
+ ASSERT(worker_thread() == talk_base::Thread::Current());
+ media_channel()->AddStream(ssrc);
+}
+
+void VoiceChannel::RemoveStream_w(uint32 ssrc) {
+ media_channel()->RemoveStream(ssrc);
+}
+
+void VoiceChannel::SetRingbackTone_w(const void* buf, int len) {
+ ASSERT(worker_thread() == talk_base::Thread::Current());
+ media_channel()->SetRingbackTone(static_cast<const char*>(buf), len);
+}
+
+bool VoiceChannel::PlayRingbackTone_w(bool play, bool loop) {
+ ASSERT(worker_thread() == talk_base::Thread::Current());
+ if (play) {
+ LOG(LS_INFO) << "Playing ringback tone, loop=" << loop;
+ } else {
+ LOG(LS_INFO) << "Stopping ringback tone";
+ }
+ return media_channel()->PlayRingbackTone(play, loop);
+}
+
+void VoiceChannel::HandleEarlyMediaTimeout() {
+ // This occurs on the main thread, not the worker thread.
+ if (!received_media_) {
+ LOG(LS_INFO) << "No early media received before timeout";
+ SignalEarlyMediaTimeout(this);
+ }
+}
+
+bool VoiceChannel::PressDTMF_w(int digit, bool playout) {
+ if (!enabled() || !writable()) {
+ return false;
+ }
+
+ return media_channel()->PressDTMF(digit, playout);
+}
+
+void VoiceChannel::OnMessage(talk_base::Message *pmsg) {
+ switch (pmsg->message_id) {
+ case MSG_ADDSTREAM: {
+ StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
+ AddStream_w(data->ssrc1);
+ break;
+ }
+ case MSG_SETRINGBACKTONE: {
+ SetRingbackToneMessageData* data =
+ static_cast<SetRingbackToneMessageData*>(pmsg->pdata);
+ SetRingbackTone_w(data->buf, data->len);
+ break;
+ }
+ case MSG_PLAYRINGBACKTONE: {
+ PlayRingbackToneMessageData* data =
+ static_cast<PlayRingbackToneMessageData*>(pmsg->pdata);
+ data->result = PlayRingbackTone_w(data->play, data->loop);
+ break;
+ }
+ case MSG_EARLYMEDIATIMEOUT:
+ HandleEarlyMediaTimeout();
+ break;
+ case MSG_PRESSDTMF: {
+ DtmfMessageData* data = static_cast<DtmfMessageData*>(pmsg->pdata);
+ data->result = PressDTMF_w(data->digit, data->playout);
+ break;
+ }
+
+ default:
+ BaseChannel::OnMessage(pmsg);
+ break;
+ }
+}
+
+void VoiceChannel::OnConnectionMonitorUpdate(
+ SocketMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
+ SignalConnectionMonitor(this, infos);
+}
+
+void VoiceChannel::OnMediaMonitorUpdate(
+ VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
+ ASSERT(media_channel == this->media_channel());
+ SignalMediaMonitor(this, info);
+}
+
+void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
+ const AudioInfo& info) {
+ SignalAudioMonitor(this, info);
+}
+
+VideoChannel::VideoChannel(talk_base::Thread* thread,
+ MediaEngine* media_engine,
+ VideoMediaChannel* media_channel,
+ BaseSession* session,
+ const std::string& content_name,
+ bool rtcp,
+ VoiceChannel* voice_channel)
+ : BaseChannel(thread, media_engine, media_channel, session, content_name,
+ session->CreateChannel(content_name, "video_rtp")),
+ voice_channel_(voice_channel), renderer_(NULL) {
+ if (rtcp) {
+ set_rtcp_transport_channel(
+ session->CreateChannel(content_name, "video_rtcp"));
+ }
+ // Can't go in BaseChannel because certain session states will
+ // trigger pure virtual functions, such as GetFirstContent()
+ OnSessionState(session, session->state());
+}
+
+VideoChannel::~VideoChannel() {
+ StopMediaMonitor();
+ // this can't be done in the base class, since it calls a virtual
+ DisableMedia_w();
+}
+
+bool VideoChannel::AddStream(uint32 ssrc, uint32 voice_ssrc) {
+ StreamMessageData data(ssrc, voice_ssrc);
+ Send(MSG_ADDSTREAM, &data);
+ return true;
+}
+
+bool VideoChannel::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
+ RenderMessageData data(ssrc, renderer);
+ Send(MSG_SETRENDERER, &data);
+ return true;
+}
+
+
+void VideoChannel::ChangeState() {
+ // render incoming data if we are the active call
+ // we receive data on the default channel and multiplexed streams
+ bool recv = enabled();
+ media_channel()->SetRender(recv);
+
+ // send outgoing data if we are the active call, have the
+ // remote party's codec, and have a writable transport
+ // we only send data on the default channel
+ bool send = enabled() && has_codec() && writable();
+ media_channel()->SetSend(send);
+
+ LOG(LS_INFO) << "Changing video state, recv=" << recv << " send=" << send;
+}
+
+void VideoChannel::StartMediaMonitor(int cms) {
+ media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
+ talk_base::Thread::Current()));
+ media_monitor_->SignalUpdate.connect(
+ this, &VideoChannel::OnMediaMonitorUpdate);
+ media_monitor_->Start(cms);
+}
+
+void VideoChannel::StopMediaMonitor() {
+ if (media_monitor_.get()) {
+ media_monitor_->Stop();
+ media_monitor_.reset();
+ }
+}
+
+const MediaContentDescription* VideoChannel::GetFirstContent(
+ const SessionDescription* sdesc) {
+ const ContentInfo* cinfo = GetFirstVideoContent(sdesc);
+ if (cinfo == NULL)
+ return NULL;
+
+ return static_cast<const MediaContentDescription*>(cinfo->description);
+}
+
+bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
+ ContentAction action) {
+ ASSERT(worker_thread() == talk_base::Thread::Current());
+ LOG(LS_INFO) << "Setting local video description";
+
+ const VideoContentDescription* video =
+ static_cast<const VideoContentDescription*>(content);
+ ASSERT(video != NULL);
+
+ bool ret;
+ // set SRTP
+ ret = SetSrtp_w(video->cryptos(), action, CS_LOCAL);
+ // set RTCP mux
+ if (ret) {
+ ret = SetRtcpMux_w(video->rtcp_mux(), action, CS_LOCAL);
+ }
+ // set payload types and config for receiving video
+ if (ret) {
+ ret = media_channel()->SetRecvCodecs(video->codecs());
+ }
+ return ret;
+}
+
+bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
+ ContentAction action) {
+ ASSERT(worker_thread() == talk_base::Thread::Current());
+ LOG(LS_INFO) << "Setting remote video description";
+
+ const VideoContentDescription* video =
+ static_cast<const VideoContentDescription*>(content);
+ ASSERT(video != NULL);
+
+ bool ret;
+ // set the sending SSRC, if the remote side gave us one
+ // TODO: remove this, since it's not needed.
+ if (video->ssrc_set()) {
+ media_channel()->SetSendSsrc(video->ssrc());
+ }
+ // set SRTP
+ ret = SetSrtp_w(video->cryptos(), action, CS_REMOTE);
+ // set RTCP mux
+ if (ret) {
+ ret = SetRtcpMux_w(video->rtcp_mux(), action, CS_REMOTE);
+ }
+ // TODO: Set bandwidth appropriately here.
+ if (ret) {
+ ret = media_channel()->SetSendCodecs(video->codecs());
+ }
+ media_channel()->SetRtpExtensionHeaders(!video->rtp_headers_disabled());
+ if (ret) {
+ set_has_codec(true);
+ ChangeState();
+ }
+ return ret;
+}
+
+void VideoChannel::AddStream_w(uint32 ssrc, uint32 voice_ssrc) {
+ media_channel()->AddStream(ssrc, voice_ssrc);
+}
+
+void VideoChannel::RemoveStream_w(uint32 ssrc) {
+ media_channel()->RemoveStream(ssrc);
+}
+
+void VideoChannel::SetRenderer_w(uint32 ssrc, VideoRenderer* renderer) {
+ media_channel()->SetRenderer(ssrc, renderer);
+}
+
+
+void VideoChannel::OnMessage(talk_base::Message *pmsg) {
+ switch (pmsg->message_id) {
+ case MSG_ADDSTREAM: {
+ StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
+ AddStream_w(data->ssrc1, data->ssrc2);
+ break;
+ }
+ case MSG_SETRENDERER: {
+ RenderMessageData* data = static_cast<RenderMessageData*>(pmsg->pdata);
+ SetRenderer_w(data->ssrc, data->renderer);
+ break;
+ }
+ default:
+ BaseChannel::OnMessage(pmsg);
+ break;
+ }
+}
+
+void VideoChannel::OnConnectionMonitorUpdate(
+ SocketMonitor *monitor, const std::vector<ConnectionInfo> &infos) {
+ SignalConnectionMonitor(this, infos);
+}
+
+void VideoChannel::OnMediaMonitorUpdate(
+ VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
+ ASSERT(media_channel == this->media_channel());
+ SignalMediaMonitor(this, info);
+}
+
+// TODO: Move to own file in a future CL.
+// Leaving here for now to avoid having to mess with the Mac build.
+RtcpMuxFilter::RtcpMuxFilter() : state_(ST_INIT), offer_enable_(false) {
+}
+
+bool RtcpMuxFilter::IsActive() const {
+ // We can receive muxed media prior to the accept, so we have to be able to
+ // deal with that.
+ return (state_ == ST_SENTOFFER || state_ == ST_ACTIVE);
+}
+
+bool RtcpMuxFilter::SetOffer(bool offer_enable, ContentSource source) {
+ bool ret = false;
+ if (state_ == ST_INIT) {
+ offer_enable_ = offer_enable;
+ state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
+ ret = true;
+ } else {
+ LOG(LS_ERROR) << "Invalid state for RTCP mux offer";
+ }
+ return ret;
+}
+
+bool RtcpMuxFilter::SetAnswer(bool answer_enable, ContentSource source) {
+ bool ret = false;
+ if ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
+ (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL)) {
+ if (offer_enable_) {
+ state_ = (answer_enable) ? ST_ACTIVE : ST_INIT;
+ ret = true;
+ } else {
+ // If the offer didn't specify RTCP mux, the answer shouldn't either.
+ if (!answer_enable) {
+ ret = true;
+ state_ = ST_INIT;
+ } else {
+ LOG(LS_WARNING) << "Invalid parameters in RTCP mux answer";
+ }
+ }
+ } else {
+ LOG(LS_ERROR) << "Invalid state for RTCP mux answer";
+ }
+ return ret;
+}
+
+bool RtcpMuxFilter::DemuxRtcp(const char* data, int len) {
+ // If we're muxing RTP/RTCP, we must inspect each packet delivered and
+ // determine whether it is RTP or RTCP. We do so by checking the packet type,
+ // and assuming RTP if type is 0-63 or 96-127. For additional details, see
+ // http://tools.ietf.org/html/draft-ietf-avt-rtp-and-rtcp-mux-07.
+ // Note that if we offer RTCP mux, we may receive muxed RTCP before we
+ // receive the answer, so we operate in that state too.
+ if (!IsActive()) {
+ return false;
+ }
+
+ int type = (len >= 2) ? (static_cast<uint8>(data[1]) & 0x7F) : 0;
+ return (type >= 64 && type < 96);
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/channel.h b/talk/session/phone/channel.h
new file mode 100644
index 0000000..b7981d9
--- /dev/null
+++ b/talk/session/phone/channel.h
@@ -0,0 +1,413 @@
+/*
+ * libjingle
+ * Copyright 2004--2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_SESSION_PHONE_CHANNEL_H_
+#define TALK_SESSION_PHONE_CHANNEL_H_
+
+#include <string>
+#include <vector>
+
+#include "talk/base/asyncudpsocket.h"
+#include "talk/base/network.h"
+#include "talk/base/sigslot.h"
+#include "talk/p2p/client/socketmonitor.h"
+#include "talk/p2p/base/session.h"
+#include "talk/session/phone/audiomonitor.h"
+#include "talk/session/phone/mediaengine.h"
+#include "talk/session/phone/mediachannel.h"
+#include "talk/session/phone/mediamonitor.h"
+#include "talk/session/phone/srtpfilter.h"
+
+namespace cricket {
+
+class MediaContentDescription;
+struct CryptoParams;
+
+enum {
+ MSG_ENABLE = 1,
+ MSG_DISABLE = 2,
+ MSG_MUTE = 3,
+ MSG_UNMUTE = 4,
+ MSG_SETREMOTECONTENT = 5,
+ MSG_SETLOCALCONTENT = 6,
+ MSG_EARLYMEDIATIMEOUT = 8,
+ MSG_PRESSDTMF = 9,
+ MSG_SETRENDERER = 10,
+ MSG_ADDSTREAM = 11,
+ MSG_REMOVESTREAM = 12,
+ MSG_SETRINGBACKTONE = 13,
+ MSG_PLAYRINGBACKTONE = 14,
+ MSG_SETMAXSENDBANDWIDTH = 15,
+ MSG_ADDSCREENCAST = 16,
+ MSG_REMOVESCREENCAST = 17,
+ MSG_SETRTCPCNAME = 18
+};
+
+// TODO: Move to own file.
+class RtcpMuxFilter {
+ public:
+ RtcpMuxFilter();
+
+ // Whether the filter is active, i.e. has RTCP mux been properly negotiated.
+ bool IsActive() const;
+
+ // Specifies whether the offer indicates the use of RTCP mux.
+ bool SetOffer(bool offer_enable, ContentSource src);
+
+ // Specifies whether the answer indicates the use of RTCP mux.
+ bool SetAnswer(bool answer_enable, ContentSource src);
+
+ // Determines whether the specified packet is RTCP.
+ bool DemuxRtcp(const char* data, int len);
+
+ private:
+ enum State { ST_INIT, ST_SENTOFFER, ST_RECEIVEDOFFER, ST_ACTIVE };
+ State state_;
+ bool offer_enable_;
+};
+
+// BaseChannel contains logic common to voice and video, including
+// enable/mute, marshaling calls to a worker thread, and
+// connection and media monitors.
+// TODO: Break the dependency on BaseSession. The only thing we need
+// it for is to Create/Destroy TransportChannels, and set codecs, both of which
+// could be done by the calling class.
+class BaseChannel
+ : public talk_base::MessageHandler, public sigslot::has_slots<>,
+ public MediaChannel::NetworkInterface {
+ public:
+ BaseChannel(talk_base::Thread* thread, MediaEngine* media_engine,
+ MediaChannel* channel, BaseSession* session,
+ const std::string& content_name,
+ TransportChannel* transport_channel);
+ ~BaseChannel();
+
+ talk_base::Thread* worker_thread() const { return worker_thread_; }
+ BaseSession* session() const { return session_; }
+ TransportChannel* transport_channel() const {
+ return transport_channel_;
+ }
+ TransportChannel* rtcp_transport_channel() const {
+ return rtcp_transport_channel_;
+ }
+ bool secure() const { return srtp_filter_.IsActive(); }
+
+ // Channel control
+ bool SetRtcpCName(const std::string& cname);
+ bool SetLocalContent(const MediaContentDescription* content,
+ ContentAction action);
+ bool SetRemoteContent(const MediaContentDescription* content,
+ ContentAction action);
+ bool SetMaxSendBandwidth(int max_bandwidth);
+
+ bool Enable(bool enable);
+ bool Mute(bool mute);
+
+ // Multiplexing
+ bool RemoveStream(uint32 ssrc);
+
+ // Monitoring
+ void StartConnectionMonitor(int cms);
+ void StopConnectionMonitor();
+
+ protected:
+ MediaEngine* media_engine() const { return media_engine_; }
+ virtual MediaChannel* media_channel() const { return media_channel_; }
+ void set_rtcp_transport_channel(TransportChannel* transport);
+ bool enabled() const { return enabled_; }
+ bool writable() const { return writable_; }
+ bool has_codec() const { return has_codec_; }
+ void set_has_codec(bool has_codec) { has_codec_ = has_codec; }
+ bool muted() const { return muted_; }
+
+ void Send(uint32 id, talk_base::MessageData *pdata = NULL);
+ void Post(uint32 id, talk_base::MessageData *pdata = NULL);
+ void PostDelayed(int cmsDelay, uint32 id = 0,
+ talk_base::MessageData *pdata = NULL);
+ void Clear(uint32 id = talk_base::MQID_ANY,
+ talk_base::MessageList* removed = NULL);
+
+ // NetworkInterface implementation, called by MediaEngine
+ virtual int SendPacket(const void *data, size_t len);
+ virtual int SendRtcp(const void *data, size_t len);
+ virtual int SetOption(SocketType type, talk_base::Socket::Option o, int val);
+
+ // From TransportChannel
+ void OnWritableState(TransportChannel* channel);
+ void OnChannelRead(TransportChannel* channel, const char *data, size_t len);
+
+ int SendPacket(bool rtcp, const void* data, size_t len);
+ void HandlePacket(bool rtcp, const char* data, size_t len);
+
+ // Setting the send codec based on the remote description.
+ void OnSessionState(BaseSession* session, BaseSession::State state);
+
+ void EnableMedia_w();
+ void DisableMedia_w();
+ void MuteMedia_w();
+ void UnmuteMedia_w();
+ void ChannelWritable_w();
+ void ChannelNotWritable_w();
+
+ struct StreamMessageData : public talk_base::MessageData {
+ StreamMessageData(uint32 s1, uint32 s2) : ssrc1(s1), ssrc2(s2) {}
+ uint32 ssrc1;
+ uint32 ssrc2;
+ };
+ virtual void RemoveStream_w(uint32 ssrc) = 0;
+
+ virtual void ChangeState() = 0;
+
+ struct SetRtcpCNameData : public talk_base::MessageData {
+ explicit SetRtcpCNameData(const std::string& cname)
+ : cname(cname), result(false) {}
+ std::string cname;
+ bool result;
+ };
+ bool SetRtcpCName_w(const std::string& cname);
+
+ struct SetContentData : public talk_base::MessageData {
+ SetContentData(const MediaContentDescription* content,
+ ContentAction action)
+ : content(content), action(action), result(false) {}
+ const MediaContentDescription* content;
+ ContentAction action;
+ bool result;
+ };
+
+ // Gets the content appropriate to the channel (audio or video).
+ virtual const MediaContentDescription* GetFirstContent(
+ const SessionDescription* sdesc) = 0;
+ virtual bool SetLocalContent_w(const MediaContentDescription* content,
+ ContentAction action) = 0;
+ virtual bool SetRemoteContent_w(const MediaContentDescription* content,
+ ContentAction action) = 0;
+
+ bool SetSrtp_w(const std::vector<CryptoParams>& params, ContentAction action,
+ ContentSource src);
+ bool SetRtcpMux_w(bool enable, ContentAction action, ContentSource src);
+
+ struct SetBandwidthData : public talk_base::MessageData {
+ explicit SetBandwidthData(int value) : value(value), result(false) {}
+ int value;
+ bool result;
+ };
+ bool SetMaxSendBandwidth_w(int max_bandwidth);
+
+ // From MessageHandler
+ virtual void OnMessage(talk_base::Message *pmsg);
+
+ // Handled in derived classes
+ virtual void OnConnectionMonitorUpdate(SocketMonitor *monitor,
+ const std::vector<ConnectionInfo> &infos) = 0;
+
+ private:
+ talk_base::Thread *worker_thread_;
+ MediaEngine *media_engine_;
+ BaseSession *session_;
+ MediaChannel *media_channel_;
+ std::string content_name_;
+ TransportChannel *transport_channel_;
+ TransportChannel *rtcp_transport_channel_;
+ SrtpFilter srtp_filter_;
+ RtcpMuxFilter rtcp_mux_filter_;
+ talk_base::scoped_ptr<SocketMonitor> socket_monitor_;
+ bool enabled_;
+ bool writable_;
+ bool has_codec_;
+ bool muted_;
+};
+
+// VoiceChannel is a specialization that adds support for early media, DTMF,
+// and input/output level monitoring.
+class VoiceChannel : public BaseChannel {
+ public:
+ VoiceChannel(talk_base::Thread *thread, MediaEngine *media_engine,
+ VoiceMediaChannel *channel, BaseSession *session,
+ const std::string& content_name, bool rtcp);
+ ~VoiceChannel();
+
+ // downcasts a MediaChannel
+ virtual VoiceMediaChannel* media_channel() const {
+ return static_cast<VoiceMediaChannel*>(BaseChannel::media_channel());
+ }
+
+ // Add an incoming stream with the specified SSRC.
+ bool AddStream(uint32 ssrc);
+
+ bool SetRingbackTone(const void* buf, int len);
+ void SetEarlyMedia(bool enable);
+ // This signal is emitted when we have gone a period of time without
+ // receiving early media. When received, a UI should start playing its
+ // own ringing sound
+ sigslot::signal1<VoiceChannel*> SignalEarlyMediaTimeout;
+
+ bool PlayRingbackTone(bool play, bool loop);
+ bool PressDTMF(int digit, bool playout);
+
+ // Monitoring functions
+ sigslot::signal2<VoiceChannel*, const std::vector<ConnectionInfo> &>
+ SignalConnectionMonitor;
+
+ void StartMediaMonitor(int cms);
+ void StopMediaMonitor();
+ sigslot::signal2<VoiceChannel*, const VoiceMediaInfo&> SignalMediaMonitor;
+
+ void StartAudioMonitor(int cms);
+ void StopAudioMonitor();
+ sigslot::signal2<VoiceChannel*, const AudioInfo&> SignalAudioMonitor;
+
+ int GetInputLevel_w();
+ int GetOutputLevel_w();
+ void GetActiveStreams_w(AudioInfo::StreamList* actives);
+
+ private:
+ struct SetRingbackToneMessageData : public talk_base::MessageData {
+ SetRingbackToneMessageData(const void* b, int l)
+ : buf(b),
+ len(l) {
+ }
+ const void* buf;
+ int len;
+ };
+ struct PlayRingbackToneMessageData : public talk_base::MessageData {
+ PlayRingbackToneMessageData(bool p, bool l)
+ : play(p),
+ loop(l),
+ result(false) {
+ }
+ bool play;
+ bool loop;
+ bool result;
+ };
+ struct DtmfMessageData : public talk_base::MessageData {
+ DtmfMessageData(int d, bool p)
+ : digit(d),
+ playout(p),
+ result(false) {
+ }
+ int digit;
+ bool playout;
+ bool result;
+ };
+
+ // overrides from BaseChannel
+ virtual void OnChannelRead(TransportChannel* channel,
+ const char *data, size_t len);
+ virtual void ChangeState();
+ virtual const MediaContentDescription* GetFirstContent(
+ const SessionDescription* sdesc);
+ virtual bool SetLocalContent_w(const MediaContentDescription* content,
+ ContentAction action);
+ virtual bool SetRemoteContent_w(const MediaContentDescription* content,
+ ContentAction action);
+
+ void AddStream_w(uint32 ssrc);
+ void RemoveStream_w(uint32 ssrc);
+
+ void SetRingbackTone_w(const void* buf, int len);
+ bool PlayRingbackTone_w(bool play, bool loop);
+ void HandleEarlyMediaTimeout();
+ bool PressDTMF_w(int digit, bool playout);
+
+ virtual void OnMessage(talk_base::Message *pmsg);
+ virtual void OnConnectionMonitorUpdate(
+ SocketMonitor *monitor, const std::vector<ConnectionInfo> &infos);
+ virtual void OnMediaMonitorUpdate(
+ VoiceMediaChannel *media_channel, const VoiceMediaInfo& info);
+ void OnAudioMonitorUpdate(AudioMonitor *monitor, const AudioInfo& info);
+
+ static const int kEarlyMediaTimeout = 1000;
+ bool received_media_;
+ talk_base::scoped_ptr<VoiceMediaMonitor> media_monitor_;
+ talk_base::scoped_ptr<AudioMonitor> audio_monitor_;
+};
+
+// VideoChannel is a specialization for video.
+class VideoChannel : public BaseChannel {
+ public:
+ VideoChannel(talk_base::Thread *thread, MediaEngine *media_engine,
+ VideoMediaChannel *channel, BaseSession *session,
+ const std::string& content_name, bool rtcp,
+ VoiceChannel *voice_channel);
+ ~VideoChannel();
+
+ // downcasts a MediaChannel
+ virtual VideoMediaChannel* media_channel() const {
+ return static_cast<VideoMediaChannel*>(BaseChannel::media_channel());
+ }
+
+ // Add an incoming stream with the specified SSRC.
+ bool AddStream(uint32 ssrc, uint32 voice_ssrc);
+
+ bool SetRenderer(uint32 ssrc, VideoRenderer* renderer);
+
+
+ sigslot::signal2<VideoChannel*, const std::vector<ConnectionInfo> &>
+ SignalConnectionMonitor;
+
+ void StartMediaMonitor(int cms);
+ void StopMediaMonitor();
+ sigslot::signal2<VideoChannel*, const VideoMediaInfo&> SignalMediaMonitor;
+
+ private:
+ // overrides from BaseChannel
+ virtual void ChangeState();
+ virtual const MediaContentDescription* GetFirstContent(
+ const SessionDescription* sdesc);
+ virtual bool SetLocalContent_w(const MediaContentDescription* content,
+ ContentAction action);
+ virtual bool SetRemoteContent_w(const MediaContentDescription* content,
+ ContentAction action);
+
+ void AddStream_w(uint32 ssrc, uint32 voice_ssrc);
+ void RemoveStream_w(uint32 ssrc);
+
+ struct RenderMessageData : public talk_base::MessageData {
+ RenderMessageData(uint32 s, VideoRenderer* r) : ssrc(s), renderer(r) {}
+ uint32 ssrc;
+ VideoRenderer* renderer;
+ };
+
+
+ void SetRenderer_w(uint32 ssrc, VideoRenderer* renderer);
+
+
+ virtual void OnMessage(talk_base::Message *pmsg);
+ virtual void OnConnectionMonitorUpdate(
+ SocketMonitor *monitor, const std::vector<ConnectionInfo> &infos);
+ virtual void OnMediaMonitorUpdate(
+ VideoMediaChannel *media_channel, const VideoMediaInfo& info);
+
+ VoiceChannel *voice_channel_;
+ VideoRenderer *renderer_;
+ talk_base::scoped_ptr<VideoMediaMonitor> media_monitor_;
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_CHANNEL_H_
diff --git a/talk/session/phone/channelmanager.cc b/talk/session/phone/channelmanager.cc
old mode 100755
new mode 100644
index 77b7a73..901a20a
--- a/talk/session/phone/channelmanager.cc
+++ b/talk/session/phone/channelmanager.cc
@@ -1,219 +1,778 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2008, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "talk/session/phone/channelmanager.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-#ifdef HAVE_GIPS
-#include "talk/session/phone/gipsmediaengine.h"
-#elif HAVE_GIPSLITE
-#include "talk/session/phone/gipslitemediaengine.h"
-#else
-#include "talk/session/phone/linphonemediaengine.h"
+#include <algorithm>
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/sigslotrepeater.h"
+#include "talk/base/stringencode.h"
+#include "talk/session/phone/mediaengine.h"
+#include "talk/session/phone/soundclip.h"
+#ifdef USE_TALK_SOUND
+#include "talk/sound/platformsoundsystemfactory.h"
+#include "talk/sound/soundsysteminterface.h"
#endif
-#include "channelmanager.h"
-#include <cassert>
-#include <iostream>
+
namespace cricket {
-const uint32 MSG_CREATEVOICECHANNEL = 1;
-const uint32 MSG_DESTROYVOICECHANNEL = 2;
-const uint32 MSG_SETAUDIOOPTIONS = 3;
+enum {
+ MSG_CREATEVOICECHANNEL = 1,
+ MSG_DESTROYVOICECHANNEL = 2,
+ MSG_SETAUDIOOPTIONS = 3,
+ MSG_SETOUTPUTVOLUME = 4,
+ MSG_SETLOCALMONITOR = 5,
+ MSG_SETVOICELOGGING = 6,
+ MSG_CREATEVIDEOCHANNEL = 11,
+ MSG_DESTROYVIDEOCHANNEL = 12,
+ MSG_SETVIDEOOPTIONS = 13,
+ MSG_SETLOCALRENDERER = 14,
+ MSG_SETDEFAULTVIDEOENCODERCONFIG = 15,
+ MSG_SETVIDEOLOGGING = 16,
+ MSG_CREATESOUNDCLIP = 17,
+ MSG_DESTROYSOUNDCLIP = 18,
+ MSG_CAMERASTARTED = 19,
+ MSG_SETVIDEOCAPTURE = 20,
+};
-ChannelManager::ChannelManager(talk_base::Thread *worker_thread) {
-#ifdef HAVE_GIPS
- media_engine_ = new GipsMediaEngine();
-#elif HAVE_GIPSLITE
- media_engine_ = new GipsLiteMediaEngine();
-#else
- media_engine_ = new LinphoneMediaEngine();
+struct CreationParams : public talk_base::MessageData {
+ CreationParams(BaseSession* session, const std::string& content_name,
+ bool rtcp, VoiceChannel* voice_channel)
+ : session(session),
+ content_name(content_name),
+ rtcp(rtcp),
+ voice_channel(voice_channel),
+ video_channel(NULL) {}
+ BaseSession* session;
+ std::string content_name;
+ bool rtcp;
+ VoiceChannel* voice_channel;
+ VideoChannel* video_channel;
+};
+
+struct AudioOptions : public talk_base::MessageData {
+ AudioOptions(int o, const Device* in, const Device* out)
+ : options(o), in_device(in), out_device(out) {}
+ int options;
+ const Device* in_device;
+ const Device* out_device;
+ bool result;
+};
+
+struct VolumeLevel : public talk_base::MessageData {
+ explicit VolumeLevel(int l) : level(l), result(false) {}
+ int level;
+ bool result;
+};
+
+struct VideoOptions : public talk_base::MessageData {
+ explicit VideoOptions(const Device* d) : cam_device(d), result(false) {}
+ const Device* cam_device;
+ bool result;
+};
+
+struct DefaultVideoEncoderConfig : public talk_base::MessageData {
+ explicit DefaultVideoEncoderConfig(const VideoEncoderConfig& c)
+ : config(c), result(false) {}
+ VideoEncoderConfig config;
+ bool result;
+};
+
+struct LocalMonitor : public talk_base::MessageData {
+ explicit LocalMonitor(bool e) : enable(e), result(false) {}
+ bool enable;
+ bool result;
+};
+
+struct LocalRenderer : public talk_base::MessageData {
+ explicit LocalRenderer(VideoRenderer* r) : renderer(r), result(false) {}
+ VideoRenderer* renderer;
+ bool result;
+};
+
+struct LoggingOptions : public talk_base::MessageData {
+ explicit LoggingOptions(int lev, const char* f) : level(lev), filter(f) {}
+ int level;
+ std::string filter;
+};
+
+struct CaptureParams : public talk_base::MessageData {
+ explicit CaptureParams(bool c) : capture(c), result(CR_FAILURE) {}
+
+ bool capture;
+ CaptureResult result;
+};
+
+ChannelManager::ChannelManager(talk_base::Thread* worker_thread)
+ :
+#ifdef USE_TALK_SOUND
+ sound_system_factory_(new PlatformSoundSystemFactory()),
#endif
- worker_thread_ = worker_thread;
- initialized_ = false;
- Init();
+ media_engine_(MediaEngine::Create(
+#ifdef USE_TALK_SOUND
+ sound_system_factory_.get()
+#endif
+ )),
+ device_manager_(new DeviceManager(
+#ifdef USE_TALK_SOUND
+ sound_system_factory_.get()
+#endif
+ )),
+ initialized_(false),
+ main_thread_(talk_base::Thread::Current()),
+ worker_thread_(worker_thread),
+ audio_options_(MediaEngine::DEFAULT_AUDIO_OPTIONS),
+ local_renderer_(NULL),
+ capturing_(false),
+ monitoring_(false) {
+ Construct();
+}
+
+ChannelManager::ChannelManager(MediaEngine* me, DeviceManager* dm,
+ talk_base::Thread* worker_thread)
+ :
+#ifdef USE_TALK_SOUND
+ sound_system_factory_(NULL),
+#endif
+ media_engine_(me),
+ device_manager_(dm),
+ initialized_(false),
+ main_thread_(talk_base::Thread::Current()),
+ worker_thread_(worker_thread),
+ audio_options_(MediaEngine::DEFAULT_AUDIO_OPTIONS),
+ local_renderer_(NULL),
+ capturing_(false),
+ monitoring_(false) {
+ Construct();
+}
+
+void ChannelManager::Construct() {
+ // Init the device manager immediately, and set up our default video device.
+ SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
+ device_manager_->Init();
+ SetVideoOptions("");
+
+ // Camera is started asynchronously, request callbacks when startup
+ // completes to be able to forward them to the rendering manager.
+ media_engine_->SignalVideoCaptureResult.connect(
+ this, &ChannelManager::OnVideoCaptureResult);
}
ChannelManager::~ChannelManager() {
- Exit();
+ if (initialized_)
+ Terminate();
}
-MediaEngine *ChannelManager::media_engine() {
- return media_engine_;
+int ChannelManager::GetCapabilities() {
+ return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
+}
+
+void ChannelManager::GetSupportedAudioCodecs(
+ std::vector<AudioCodec>* codecs) const {
+ codecs->clear();
+
+ for (std::vector<AudioCodec>::const_iterator it =
+ media_engine_->audio_codecs().begin();
+ it != media_engine_->audio_codecs().end(); ++it) {
+ codecs->push_back(*it);
+ }
+}
+
+void ChannelManager::GetSupportedVideoCodecs(
+ std::vector<VideoCodec>* codecs) const {
+ codecs->clear();
+
+ std::vector<VideoCodec>::const_iterator it;
+ for (it = media_engine_->video_codecs().begin();
+ it != media_engine_->video_codecs().end(); ++it) {
+ codecs->push_back(*it);
+ }
}
bool ChannelManager::Init() {
- initialized_ = media_engine_->Init();
+ ASSERT(!initialized_);
+ if (initialized_) {
+ return false;
+ }
+
+ ASSERT(worker_thread_ != NULL);
+ if (worker_thread_ && worker_thread_->started()) {
+ if (media_engine_->Init()) {
+ initialized_ = true;
+
+ // Now that we're initialized, apply any stored preferences.
+ if (!SetAudioOptions(audio_in_device_, audio_out_device_,
+ audio_options_)) {
+ audio_in_device_.clear();
+ audio_out_device_.clear();
+ }
+ if (!SetVideoOptions(camera_device_)) {
+ // TODO: Consider resetting to the default cam here.
+ camera_device_.clear();
+ }
+ // Now apply the default video codec that has been set earlier.
+ if (default_video_encoder_config_.max_codec.id != 0) {
+ SetDefaultVideoEncoderConfig(default_video_encoder_config_);
+ }
+ // And the local renderer.
+ if (local_renderer_) {
+ SetLocalRenderer(local_renderer_);
+ }
+ }
+ }
return initialized_;
}
-void ChannelManager::Exit() {
- if (!initialized_)
+void ChannelManager::Terminate() {
+ ASSERT(initialized_);
+ if (!initialized_) {
return;
-
- // Need to destroy the voice channels
-
- while (true) {
- crit_.Enter();
- VoiceChannel *channel = NULL;
- if (channels_.begin() != channels_.end())
- channel = channels_[0];
- crit_.Leave();
- if (channel == NULL)
- break;
- delete channel;
}
+
+ // Need to destroy the voice/video channels
+ while (!video_channels_.empty()) {
+ DestroyVideoChannel_w(video_channels_.back());
+ }
+ while (!voice_channels_.empty()) {
+ DestroyVoiceChannel_w(voice_channels_.back());
+ }
+ while (!soundclips_.empty()) {
+ DestroySoundclip_w(soundclips_.back());
+ }
+
media_engine_->Terminate();
+ initialized_ = false;
}
-struct CreateParams {
- Session *session;
- VoiceChannel *channel;
-};
-
-VoiceChannel *ChannelManager::CreateVoiceChannel(Session *session) {
- CreateParams params;
- params.session = session;
- params.channel = NULL;
- talk_base::TypedMessageData<CreateParams *> data(¶ms);
- worker_thread_->Send(this, MSG_CREATEVOICECHANNEL, &data);
- return params.channel;
+VoiceChannel* ChannelManager::CreateVoiceChannel(
+ BaseSession* session, const std::string& content_name, bool rtcp) {
+ CreationParams params(session, content_name, rtcp, NULL);
+ return (Send(MSG_CREATEVOICECHANNEL, ¶ms)) ? params.voice_channel : NULL;
}
-VoiceChannel *ChannelManager::CreateVoiceChannel_w(Session *session) {
+VoiceChannel* ChannelManager::CreateVoiceChannel_w(
+ BaseSession* session, const std::string& content_name, bool rtcp) {
talk_base::CritScope cs(&crit_);
// This is ok to alloc from a thread other than the worker thread
- assert(initialized_);
- MediaChannel *channel = media_engine_->CreateChannel();
- if (channel == NULL)
+ ASSERT(initialized_);
+ VoiceMediaChannel* media_channel = media_engine_->CreateChannel();
+ if (media_channel == NULL)
return NULL;
- VoiceChannel *voice_channel = new VoiceChannel(this, session, channel);
- channels_.push_back(voice_channel);
+ VoiceChannel* voice_channel = new VoiceChannel(
+ worker_thread_, media_engine_.get(), media_channel,
+ session, content_name, rtcp);
+ voice_channels_.push_back(voice_channel);
return voice_channel;
}
-void ChannelManager::DestroyVoiceChannel(VoiceChannel *voice_channel) {
- talk_base::TypedMessageData<VoiceChannel *> data(voice_channel);
- worker_thread_->Send(this, MSG_DESTROYVOICECHANNEL, &data);
+void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
+ if (voice_channel) {
+ talk_base::TypedMessageData<VoiceChannel *> data(voice_channel);
+ Send(MSG_DESTROYVOICECHANNEL, &data);
+ }
}
-void ChannelManager::DestroyVoiceChannel_w(VoiceChannel *voice_channel) {
+void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
talk_base::CritScope cs(&crit_);
// Destroy voice channel.
- assert(initialized_);
- std::vector<VoiceChannel *>::iterator it = std::find(channels_.begin(),
- channels_.end(), voice_channel);
- assert(it != channels_.end());
- if (it == channels_.end())
+ ASSERT(initialized_);
+ VoiceChannels::iterator it = std::find(voice_channels_.begin(),
+ voice_channels_.end(), voice_channel);
+ ASSERT(it != voice_channels_.end());
+ if (it == voice_channels_.end())
return;
-
- channels_.erase(it);
- MediaChannel *channel = voice_channel->channel();
+
+ voice_channels_.erase(it);
delete voice_channel;
- delete channel;
}
-void ChannelManager::SetAudioOptions(bool auto_gain_control, int wave_in_device,
- int wave_out_device) {
- AudioOptions options;
- options.auto_gain_control = auto_gain_control;
- options.wave_in_device = wave_in_device;
- options.wave_out_device = wave_out_device;
- talk_base::TypedMessageData<AudioOptions> data(options);
- worker_thread_->Send(this, MSG_SETAUDIOOPTIONS, &data);
+VideoChannel* ChannelManager::CreateVideoChannel(
+ BaseSession* session, const std::string& content_name, bool rtcp,
+ VoiceChannel* voice_channel) {
+ CreationParams params(session, content_name, rtcp, voice_channel);
+ return (Send(MSG_CREATEVIDEOCHANNEL, ¶ms)) ? params.video_channel : NULL;
}
-void ChannelManager::SetAudioOptions_w(AudioOptions options) {
- assert(worker_thread_ == talk_base::Thread::Current());
+VideoChannel* ChannelManager::CreateVideoChannel_w(
+ BaseSession* session, const std::string& content_name, bool rtcp,
+ VoiceChannel* voice_channel) {
+ talk_base::CritScope cs(&crit_);
- // Set auto gain control on
- if (media_engine_->SetAudioOptions(
- options.auto_gain_control ? MediaEngine::AUTO_GAIN_CONTROL : 0) != 0) {
- // TODO: We need to log these failures.
+ // This is ok to alloc from a thread other than the worker thread
+ ASSERT(initialized_);
+ VideoMediaChannel* media_channel =
+ // voice_channel can be NULL in case of NullVoiceEngine.
+ media_engine_->CreateVideoChannel(voice_channel ?
+ voice_channel->media_channel() : NULL);
+ if (media_channel == NULL)
+ return NULL;
+
+ VideoChannel* video_channel = new VideoChannel(
+ worker_thread_, media_engine_.get(), media_channel,
+ session, content_name, rtcp, voice_channel);
+ video_channels_.push_back(video_channel);
+ return video_channel;
+}
+
+void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
+ if (video_channel) {
+ talk_base::TypedMessageData<VideoChannel *> data(video_channel);
+ Send(MSG_DESTROYVIDEOCHANNEL, &data);
}
+}
+
+void ChannelManager::DestroyVideoChannel_w(VideoChannel *video_channel) {
+ talk_base::CritScope cs(&crit_);
+ // Destroy voice channel.
+ ASSERT(initialized_);
+ VideoChannels::iterator it = std::find(video_channels_.begin(),
+ video_channels_.end(), video_channel);
+ ASSERT(it != video_channels_.end());
+ if (it == video_channels_.end())
+ return;
+
+ video_channels_.erase(it);
+ delete video_channel;
+}
+
+Soundclip* ChannelManager::CreateSoundclip() {
+ talk_base::TypedMessageData<Soundclip*> data(NULL);
+ Send(MSG_CREATESOUNDCLIP, &data);
+ return data.data();
+}
+
+Soundclip* ChannelManager::CreateSoundclip_w() {
+ talk_base::CritScope cs(&crit_);
+
+ ASSERT(initialized_);
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+ SoundclipMedia* soundclip_media = media_engine_->CreateSoundclip();
+ if (!soundclip_media) {
+ return NULL;
+ }
+
+ Soundclip* soundclip = new Soundclip(worker_thread_, soundclip_media);
+ soundclips_.push_back(soundclip);
+ return soundclip;
+}
+
+void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
+ if (soundclip) {
+ talk_base::TypedMessageData<Soundclip*> data(soundclip);
+ Send(MSG_DESTROYSOUNDCLIP, &data);
+ }
+}
+
+void ChannelManager::DestroySoundclip_w(Soundclip* soundclip) {
+ talk_base::CritScope cs(&crit_);
+ // Destroy soundclip.
+ ASSERT(initialized_);
+ Soundclips::iterator it = std::find(soundclips_.begin(),
+ soundclips_.end(), soundclip);
+ ASSERT(it != soundclips_.end());
+ if (it == soundclips_.end())
+ return;
+
+ soundclips_.erase(it);
+ delete soundclip;
+}
+
+bool ChannelManager::GetAudioOptions(std::string* in_name,
+ std::string* out_name, int* opts) {
+ *in_name = audio_in_device_;
+ *out_name = audio_out_device_;
+ *opts = audio_options_;
+ return true;
+}
+
+bool ChannelManager::SetAudioOptions(const std::string& in_name,
+ const std::string& out_name, int opts) {
+ // Get device ids from DeviceManager.
+ Device in_dev, out_dev;
+ if (!device_manager_->GetAudioInputDevice(in_name, &in_dev) ||
+ !device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
+ LOG(LS_WARNING) << "Device manager can't find selected device";
+ return false;
+ }
+
+ // If we're initialized, pass the settings to the media engine.
+ bool ret = true;
+ if (initialized_) {
+ AudioOptions options(opts, &in_dev, &out_dev);
+ ret = (Send(MSG_SETAUDIOOPTIONS, &options) && options.result);
+ }
+
+ // If all worked well, save the values for use in GetAudioOptions.
+ if (ret) {
+ audio_options_ = opts;
+ audio_in_device_ = in_name;
+ audio_out_device_ = out_name;
+ }
+ return ret;
+}
+
+bool ChannelManager::SetAudioOptions_w(int opts, const Device* in_dev,
+ const Device* out_dev) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ ASSERT(initialized_);
+
+ // Set audio options
+ bool ret = media_engine_->SetAudioOptions(opts);
// Set the audio devices
- // This will fail if audio is already playing. Stop all of the media
- // start it up again after changing the setting.
- {
+ if (ret) {
talk_base::CritScope cs(&crit_);
- for (VoiceChannels::iterator it = channels_.begin();
- it < channels_.end();
- ++it) {
- (*it)->PauseMedia_w();
- }
+ ret = media_engine_->SetSoundDevices(in_dev, out_dev);
+ }
- if (media_engine_->SetSoundDevices(options.wave_in_device,
- options.wave_out_device) == -1) {
- // TODO: We need to log these failures.
- }
+ return ret;
+}
- for (VoiceChannels::iterator it = channels_.begin();
- it < channels_.end();
- ++it) {
- (*it)->UnpauseMedia_w();
+bool ChannelManager::SetOutputVolume(int level) {
+ VolumeLevel volume(level);
+ return (Send(MSG_SETOUTPUTVOLUME, &volume) && volume.result);
+}
+
+bool ChannelManager::SetOutputVolume_w(int level) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ ASSERT(initialized_);
+ return media_engine_->SetOutputVolume(level);
+}
+
+bool ChannelManager::GetVideoOptions(std::string* cam_name) {
+ *cam_name = camera_device_;
+ return true;
+}
+
+bool ChannelManager::SetVideoOptions(const std::string& cam_name) {
+ bool ret;
+ Device device;
+
+ if (cam_name.empty()) {
+ // If we're passed the default device name, get the default device.
+ ret = device_manager_->GetDefaultVideoCaptureDevice(&device);
+ } else {
+ // Convert the camera name to a device, fail if it can't be found.
+ std::vector<Device> devices;
+ ret = device_manager_->GetVideoCaptureDevices(&devices);
+ if (ret) {
+ for (size_t i = 0; i < devices.size(); ++i) {
+ if (devices[i].name == cam_name) {
+ device = devices[i];
+ break;
+ }
+ }
+ ret = !device.name.empty();
}
}
+
+ // If we're running, tell the media engine about it.
+ if (ret && initialized_) {
+#ifdef OSX
+ Device sg_device;
+ ret = device_manager_->QtKitToSgDevice(device.name, &sg_device);
+ if (ret) {
+ device = sg_device;
+ } else {
+ LOG(LS_ERROR) << "Unable to find SG Component for qtkit device "
+ << device.name;
+ }
+#endif
+ if (ret) {
+ VideoOptions options(&device);
+ ret = (Send(MSG_SETVIDEOOPTIONS, &options) && options.result);
+ }
+ }
+
+ // If everything worked, retain the name of the selected camera.
+ if (ret) {
+ camera_device_ = device.name;
+ }
+ return ret;
+}
+
+bool ChannelManager::SetVideoOptions_w(const Device* cam_device) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ ASSERT(initialized_);
+
+ // Set the video input device
+ return media_engine_->SetVideoCaptureDevice(cam_device);
+}
+
+bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
+ bool ret = true;
+ if (initialized_) {
+ DefaultVideoEncoderConfig config(c);
+ ret = Send(MSG_SETDEFAULTVIDEOENCODERCONFIG, &config) && config.result;
+ }
+ if (ret) {
+ default_video_encoder_config_ = c;
+ }
+ return ret;
+}
+
+bool ChannelManager::SetDefaultVideoEncoderConfig_w(
+ const VideoEncoderConfig& c) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ ASSERT(initialized_);
+ return media_engine_->SetDefaultVideoEncoderConfig(c);
+}
+
+bool ChannelManager::SetLocalMonitor(bool enable) {
+ LocalMonitor monitor(enable);
+ bool ret = Send(MSG_SETLOCALMONITOR, &monitor) && monitor.result;
+ if (ret) {
+ monitoring_ = enable;
+ }
+ return ret;
+}
+
+bool ChannelManager::SetLocalMonitor_w(bool enable) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ ASSERT(initialized_);
+ return media_engine_->SetLocalMonitor(enable);
+}
+
+bool ChannelManager::SetLocalRenderer(VideoRenderer* renderer) {
+ bool ret = true;
+ if (initialized_) {
+ LocalRenderer local(renderer);
+ ret = (Send(MSG_SETLOCALRENDERER, &local) && local.result);
+ }
+ if (ret) {
+ local_renderer_ = renderer;
+ }
+ return ret;
+}
+
+bool ChannelManager::SetLocalRenderer_w(VideoRenderer* renderer) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ ASSERT(initialized_);
+ return media_engine_->SetLocalRenderer(renderer);
+}
+
+CaptureResult ChannelManager::SetVideoCapture(bool capture) {
+ bool ret;
+ CaptureParams capture_params(capture);
+ ret = (Send(MSG_SETVIDEOCAPTURE, &capture_params) &&
+ (capture_params.result != CR_FAILURE));
+ if (ret) {
+ capturing_ = capture;
+ }
+ return capture_params.result;
+}
+
+CaptureResult ChannelManager::SetVideoCapture_w(bool capture) {
+ ASSERT(worker_thread_ == talk_base::Thread::Current());
+ ASSERT(initialized_);
+ return media_engine_->SetVideoCapture(capture);
+}
+
+void ChannelManager::SetVoiceLogging(int level, const char* filter) {
+ SetMediaLogging(false, level, filter);
+}
+
+void ChannelManager::SetVideoLogging(int level, const char* filter) {
+ SetMediaLogging(true, level, filter);
+}
+
+void ChannelManager::SetMediaLogging(bool video, int level,
+ const char* filter) {
+ // Can be called before initialization; in this case, the worker function
+ // is simply called on the main thread.
+ if (initialized_) {
+ LoggingOptions options(level, filter);
+ Send((video) ? MSG_SETVIDEOLOGGING : MSG_SETVOICELOGGING, &options);
+ } else {
+ SetMediaLogging_w(video, level, filter);
+ }
}
-talk_base::Thread *ChannelManager::worker_thread() {
- return worker_thread_;
+void ChannelManager::SetMediaLogging_w(bool video, int level,
+ const char* filter) {
+ // Can be called before initialization
+ ASSERT(worker_thread_ == talk_base::Thread::Current() || !initialized_);
+ if (video) {
+ media_engine_->SetVideoLogging(level, filter);
+ } else {
+ media_engine_->SetVoiceLogging(level, filter);
+ }
}
-void ChannelManager::OnMessage(talk_base::Message *message) {
+bool ChannelManager::Send(uint32 id, talk_base::MessageData* data) {
+ if (!worker_thread_ || !initialized_) return false;
+ worker_thread_->Send(this, id, data);
+ return true;
+}
+
+void ChannelManager::OnVideoCaptureResult(bool result) {
+ capturing_ = result;
+ main_thread_->Post(this, MSG_CAMERASTARTED,
+ new talk_base::TypedMessageData<bool>(result));
+}
+
+void ChannelManager::OnMessage(talk_base::Message* message) {
+ talk_base::MessageData* data = message->pdata;
switch (message->message_id) {
- case MSG_CREATEVOICECHANNEL:
- {
- talk_base::TypedMessageData<CreateParams *> *data
- = static_cast<talk_base::TypedMessageData<CreateParams *> *>(
- message->pdata);
- data->data()->channel = CreateVoiceChannel_w(data->data()->session);
+ case MSG_CREATEVOICECHANNEL: {
+ CreationParams* p = static_cast<CreationParams*>(data);
+ p->voice_channel =
+ CreateVoiceChannel_w(p->session, p->content_name, p->rtcp);
+ break;
}
- break;
-
- case MSG_DESTROYVOICECHANNEL:
- {
- talk_base::TypedMessageData<VoiceChannel *> *data
- = static_cast<talk_base::TypedMessageData<VoiceChannel *> *>(
- message->pdata);
- DestroyVoiceChannel_w(data->data());
+ case MSG_DESTROYVOICECHANNEL: {
+ VoiceChannel* p = static_cast<talk_base::TypedMessageData<VoiceChannel*>*>
+ (data)->data();
+ DestroyVoiceChannel_w(p);
+ break;
}
- break;
- case MSG_SETAUDIOOPTIONS:
- {
- talk_base::TypedMessageData<AudioOptions> *data
- = static_cast<talk_base::TypedMessageData<AudioOptions> *>(
- message->pdata);
- SetAudioOptions_w(data->data());
+ case MSG_CREATEVIDEOCHANNEL: {
+ CreationParams* p = static_cast<CreationParams*>(data);
+ p->video_channel = CreateVideoChannel_w(p->session, p->content_name,
+ p->rtcp, p->voice_channel);
+ break;
}
- break;
+ case MSG_DESTROYVIDEOCHANNEL: {
+ VideoChannel* p = static_cast<talk_base::TypedMessageData<VideoChannel*>*>
+ (data)->data();
+ DestroyVideoChannel_w(p);
+ break;
+ }
+ case MSG_CREATESOUNDCLIP: {
+ talk_base::TypedMessageData<Soundclip*> *p =
+ static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
+ p->data() = CreateSoundclip_w();
+ break;
+ }
+ case MSG_DESTROYSOUNDCLIP: {
+ talk_base::TypedMessageData<Soundclip*> *p =
+ static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
+ DestroySoundclip_w(p->data());
+ break;
+ }
+ case MSG_SETAUDIOOPTIONS: {
+ AudioOptions* p = static_cast<AudioOptions*>(data);
+ p->result = SetAudioOptions_w(p->options,
+ p->in_device, p->out_device);
+ break;
+ }
+ case MSG_SETOUTPUTVOLUME: {
+ VolumeLevel* p = static_cast<VolumeLevel*>(data);
+ p->result = SetOutputVolume_w(p->level);
+ break;
+ }
+ case MSG_SETLOCALMONITOR: {
+ LocalMonitor* p = static_cast<LocalMonitor*>(data);
+ p->result = SetLocalMonitor_w(p->enable);
+ break;
+ }
+ case MSG_SETVIDEOOPTIONS: {
+ VideoOptions* p = static_cast<VideoOptions*>(data);
+ p->result = SetVideoOptions_w(p->cam_device);
+ break;
+ }
+ case MSG_SETDEFAULTVIDEOENCODERCONFIG: {
+ DefaultVideoEncoderConfig* p =
+ static_cast<DefaultVideoEncoderConfig*>(data);
+ p->result = SetDefaultVideoEncoderConfig_w(p->config);
+ break;
+ }
+ case MSG_SETLOCALRENDERER: {
+ LocalRenderer* p = static_cast<LocalRenderer*>(data);
+ p->result = SetLocalRenderer_w(p->renderer);
+ break;
+ }
+ case MSG_SETVIDEOCAPTURE: {
+ CaptureParams* p = static_cast<CaptureParams*>(data);
+ p->result = SetVideoCapture_w(p->capture);
+ break;
+ }
+ case MSG_SETVOICELOGGING:
+ case MSG_SETVIDEOLOGGING: {
+ LoggingOptions* p = static_cast<LoggingOptions*>(data);
+ bool video = (message->message_id == MSG_SETVIDEOLOGGING);
+ SetMediaLogging_w(video, p->level, p->filter.c_str());
+ break;
+ }
+ case MSG_CAMERASTARTED: {
+ talk_base::TypedMessageData<bool> *data =
+ static_cast<talk_base::TypedMessageData<bool>*>(message->pdata);
+ SignalVideoCaptureResult(data->data());
+ delete data;
+ break;
+ }
}
}
+static void GetDeviceNames(const std::vector<Device>& devs,
+ std::vector<std::string>* names) {
+ names->clear();
+ for (size_t i = 0; i < devs.size(); ++i) {
+ names->push_back(devs[i].name);
+ }
}
+
+bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
+ names->clear();
+ std::vector<Device> devs;
+ bool ret = device_manager_->GetAudioInputDevices(&devs);
+ if (ret)
+ GetDeviceNames(devs, names);
+
+ return ret;
+}
+
+bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
+ names->clear();
+ std::vector<Device> devs;
+ bool ret = device_manager_->GetAudioOutputDevices(&devs);
+ if (ret)
+ GetDeviceNames(devs, names);
+
+ return ret;
+}
+
+bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
+ names->clear();
+ std::vector<Device> devs;
+ bool ret = device_manager_->GetVideoCaptureDevices(&devs);
+ if (ret)
+ GetDeviceNames(devs, names);
+
+ return ret;
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/channelmanager.h b/talk/session/phone/channelmanager.h
old mode 100755
new mode 100644
index c17d5bb..c5ff45a
--- a/talk/session/phone/channelmanager.h
+++ b/talk/session/phone/channelmanager.h
@@ -1,80 +1,218 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2008, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CHANNELMANAGER_H_
-#define _CHANNELMANAGER_H_
+#ifndef TALK_SESSION_PHONE_CHANNELMANAGER_H_
+#define TALK_SESSION_PHONE_CHANNELMANAGER_H_
-#include "talk/base/thread.h"
+#include <string>
+#include <vector>
+
#include "talk/base/criticalsection.h"
+#include "talk/base/sigslotrepeater.h"
+#include "talk/base/thread.h"
#include "talk/p2p/base/session.h"
#include "talk/session/phone/voicechannel.h"
#include "talk/session/phone/mediaengine.h"
-#include <vector>
+#include "talk/session/phone/devicemanager.h"
+#ifdef USE_TALK_SOUND
+#include "talk/sound/soundsystemfactory.h"
+#endif
namespace cricket {
+class Soundclip;
class VoiceChannel;
-class ChannelManager : public talk_base::MessageHandler {
-public:
- ChannelManager(talk_base::Thread *worker_thread);
+// ChannelManager allows the MediaEngine to run on a separate thread, and takes
+// care of marshalling calls between threads. It also creates and keeps track of
+// voice and video channels; by doing so, it can temporarily pause all the
+// channels when a new audio or video device is chosen. The voice and video
+// channels are stored in separate vectors, to easily allow operations on just
+// voice or just video channels.
+// ChannelManager also allows the application to discover what devices it has
+// using device manager.
+class ChannelManager : public talk_base::MessageHandler,
+ public sigslot::has_slots<> {
+ public:
+ // Creates the channel manager, and specifies the worker thread to use.
+ explicit ChannelManager(talk_base::Thread* worker);
+ // For testing purposes. Allows the media engine and dev manager to be mocks.
+ // The ChannelManager takes ownership of these objects.
+ ChannelManager(MediaEngine* me, DeviceManager* dm, talk_base::Thread* worker);
~ChannelManager();
- VoiceChannel *CreateVoiceChannel(Session *session);
- void DestroyVoiceChannel(VoiceChannel *voice_channel);
- void SetAudioOptions(bool auto_gain_control, int wave_in_device,
- int wave_out_device);
+ // Accessors for the worker thread, allowing it to be set after construction,
+ // but before Init. set_worker_thread will return false if called after Init.
+ talk_base::Thread* worker_thread() const { return worker_thread_; }
+ bool set_worker_thread(talk_base::Thread* thread) {
+ if (initialized_) return false;
+ worker_thread_ = thread;
+ return true;
+ }
- MediaEngine *media_engine();
- talk_base::Thread *worker_thread();
+ // Gets capabilities. Can be called prior to starting the media engine.
+ int GetCapabilities();
-private:
- VoiceChannel *CreateVoiceChannel_w(Session *session);
- void DestroyVoiceChannel_w(VoiceChannel *voice_channel);
- void OnMessage(talk_base::Message *message);
+ // Retrieves the list of supported audio & video codec types.
+ // Can be called before starting the media engine.
+ void GetSupportedAudioCodecs(std::vector<AudioCodec>* codecs) const;
+ void GetSupportedVideoCodecs(std::vector<VideoCodec>* codecs) const;
+
+ // Determines if a specific audio or video codec is supported.
+ // Can be called before starting the media engine.
+ bool FindAudioCodec(const AudioCodec& codec) const {
+ return media_engine_->FindAudioCodec(codec);
+ }
+ bool FindVideoCodec(const VideoCodec& video_codec) const {
+ return media_engine_->FindVideoCodec(video_codec);
+ }
+
+ // Indicates whether the media engine is started.
+ bool initialized() const { return initialized_; }
+ // Starts up the media engine.
bool Init();
- void Exit();
+ // TODO: Remove this temporary API once Flute is updated.
+ bool Init(talk_base::Thread* thread) {
+ return set_worker_thread(thread) && Init();
+ }
+ // Shuts down the media engine.
+ void Terminate();
- struct AudioOptions {
- bool auto_gain_control;
- int wave_in_device;
- int wave_out_device;
- };
- void SetAudioOptions_w(AudioOptions options);
+ // The operations below all occur on the worker thread.
- talk_base::Thread *worker_thread_;
- MediaEngine *media_engine_;
- bool initialized_;
- talk_base::CriticalSection crit_;
+ // Creates a voice channel, to be associated with the specified session.
+ VoiceChannel* CreateVoiceChannel(
+ BaseSession* session, const std::string& content_name, bool rtcp);
+ // Destroys a voice channel created with the Create API.
+ void DestroyVoiceChannel(VoiceChannel* voice_channel);
+ // Creates a video channel, synced with the specified voice channel, and
+ // associated with the specified session.
+ VideoChannel* CreateVideoChannel(
+ BaseSession* session, const std::string& content_name, bool rtcp,
+ VoiceChannel* voice_channel);
+ // Destroys a video channel created with the Create API.
+ void DestroyVideoChannel(VideoChannel* video_channel);
+ // Creates a soundclip.
+ Soundclip* CreateSoundclip();
+ // Destroys a soundclip created with the Create API.
+ void DestroySoundclip(Soundclip* soundclip);
+
+ // Indicates whether any channels exist.
+ bool has_channels() const {
+ return (!voice_channels_.empty() || !video_channels_.empty() ||
+ !soundclips_.empty());
+ }
+
+ // Configures the audio and video devices.
+ bool GetAudioOptions(std::string* wave_in_device,
+ std::string* wave_out_device, int* opts);
+ bool SetAudioOptions(const std::string& wave_in_device,
+ const std::string& wave_out_device, int opts);
+ bool SetOutputVolume(int level);
+ bool GetVideoOptions(std::string* cam_device);
+ bool SetVideoOptions(const std::string& cam_device);
+ bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config);
+
+ // Starts/stops the local microphone and enables polling of the input level.
+ bool SetLocalMonitor(bool enable);
+ bool monitoring() const { return monitoring_; }
+ // Sets the local renderer where to renderer the local camera.
+ bool SetLocalRenderer(VideoRenderer* renderer);
+ // Starts and stops the local camera and renders it to the local renderer.
+ CaptureResult SetVideoCapture(bool capture);
+ bool capturing() const { return capturing_; }
+
+ // Configures the logging output of the mediaengine(s).
+ void SetVoiceLogging(int level, const char* filter);
+ void SetVideoLogging(int level, const char* filter);
+
+ // The operations below occur on the main thread.
+
+ bool GetAudioInputDevices(std::vector<std::string>* names);
+ bool GetAudioOutputDevices(std::vector<std::string>* names);
+ bool GetVideoCaptureDevices(std::vector<std::string>* names);
+ sigslot::repeater0<> SignalDevicesChange;
+ sigslot::signal1<bool> SignalVideoCaptureResult;
+
+ private:
typedef std::vector<VoiceChannel*> VoiceChannels;
- VoiceChannels channels_;
+ typedef std::vector<VideoChannel*> VideoChannels;
+ typedef std::vector<Soundclip*> Soundclips;
+
+ void Construct();
+ bool Send(uint32 id, talk_base::MessageData* pdata);
+ VoiceChannel* CreateVoiceChannel_w(
+ BaseSession* session, const std::string& content_name, bool rtcp);
+ void DestroyVoiceChannel_w(VoiceChannel* voice_channel);
+ VideoChannel* CreateVideoChannel_w(
+ BaseSession* session, const std::string& content_name, bool rtcp,
+ VoiceChannel* voice_channel);
+ void DestroyVideoChannel_w(VideoChannel* video_channel);
+ Soundclip* CreateSoundclip_w();
+ void DestroySoundclip_w(Soundclip* soundclip);
+ bool SetAudioOptions_w(int opts, const Device* in_dev,
+ const Device* out_dev);
+ bool SetOutputVolume_w(int level);
+ bool SetLocalMonitor_w(bool enable);
+ bool SetVideoOptions_w(const Device* cam_device);
+ bool SetDefaultVideoEncoderConfig_w(const VideoEncoderConfig& config);
+ bool SetLocalRenderer_w(VideoRenderer* renderer);
+ CaptureResult SetVideoCapture_w(bool capture);
+ void SetMediaLogging(bool video, int level, const char* filter);
+ void SetMediaLogging_w(bool video, int level, const char* filter);
+ void OnVideoCaptureResult(bool result);
+ void OnMessage(talk_base::Message *message);
+
+ talk_base::CriticalSection crit_;
+#ifdef USE_TALK_SOUND
+ talk_base::scoped_ptr<SoundSystemFactory> sound_system_factory_;
+#endif
+ talk_base::scoped_ptr<MediaEngine> media_engine_;
+ talk_base::scoped_ptr<DeviceManager> device_manager_;
+ bool initialized_;
+ talk_base::Thread* main_thread_;
+ talk_base::Thread* worker_thread_;
+
+ VoiceChannels voice_channels_;
+ VideoChannels video_channels_;
+ Soundclips soundclips_;
+
+ std::string audio_in_device_;
+ std::string audio_out_device_;
+ int audio_options_;
+ std::string camera_device_;
+ VideoEncoderConfig default_video_encoder_config_;
+ VideoRenderer* local_renderer_;
+
+ bool capturing_;
+ bool monitoring_;
};
-}
+} // namespace cricket
-#endif // _CHANNELMANAGER_H_
+#endif // TALK_SESSION_PHONE_CHANNELMANAGER_H_
diff --git a/talk/session/phone/codec.cc b/talk/session/phone/codec.cc
new file mode 100644
index 0000000..01d1a7b
--- /dev/null
+++ b/talk/session/phone/codec.cc
@@ -0,0 +1,78 @@
+/*
+ * libjingle
+ * Copyright 2004--2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/phone/codec.h"
+#include <sstream>
+
+namespace cricket {
+
+static const int kMaxStaticPayloadId = 95;
+
+bool AudioCodec::Matches(int payload, const std::string& nm) const {
+ // Match the codec id/name based on the typical static/dynamic name rules.
+ return (payload <= kMaxStaticPayloadId) ? (id == payload) : (name == nm);
+}
+
+bool AudioCodec::Matches(const AudioCodec& codec) const {
+ // If a nonzero clockrate is specified, it must match the actual clockrate.
+ // If a nonzero bitrate is specified, it must match the actual bitrate,
+ // unless the codec is VBR (-1), where we just force the supplied value.
+ // The number of channels must match exactly.
+ // Preference is ignored.
+ // TODO: Treat a zero clockrate as 8000Hz, the RTP default clockrate.
+ return Matches(codec.id, codec.name) &&
+ ((codec.clockrate == 0 /*&& clockrate == 8000*/) ||
+ clockrate == codec.clockrate) &&
+ (codec.bitrate == 0 || bitrate == -1 || bitrate == codec.bitrate) &&
+ (codec.channels == 0 || channels == codec.channels);
+}
+
+std::string AudioCodec::ToString() const {
+ std::ostringstream os;
+ os << "AudioCodec[" << id << ":" << name << ":" << clockrate << ":" << bitrate
+ << ":" << channels << ":" << preference << "]";
+ return os.str();
+}
+
+bool VideoCodec::Matches(int payload, const std::string& nm) const {
+ // Match the codec id/name based on the typical static/dynamic name rules.
+ return (payload <= kMaxStaticPayloadId) ? (id == payload) : (name == nm);
+}
+
+bool VideoCodec::Matches(const VideoCodec& codec) const {
+ // Only the id and name are matched.
+ return Matches(codec.id, codec.name);
+}
+
+std::string VideoCodec::ToString() const {
+ std::ostringstream os;
+ os << "VideoCodec[" << id << ":" << name << ":" << width << ":" << height
+ << ":" << framerate << ":" << preference << "]";
+ return os.str();
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/codec.h b/talk/session/phone/codec.h
old mode 100755
new mode 100644
index ef99c2b..8536dbb
--- a/talk/session/phone/codec.h
+++ b/talk/session/phone/codec.h
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2007, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,11 +25,14 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef TALK_SESSION_PHONE_CODEC_H_
+#define TALK_SESSION_PHONE_CODEC_H_
-#ifndef _CODEC_H_
-#define _CODEC_H_
+#include <string>
-struct Codec {
+namespace cricket {
+
+struct AudioCodec {
int id;
std::string name;
int clockrate;
@@ -38,10 +41,142 @@
int preference;
- // Creates a codec with the given parameters.
- Codec(int pt, const std::string& nm, int cr, int br, int cs, int pr) :
- id(pt), name(nm), clockrate(cr), preference(pr), bitrate(br), channels(cs) {}
- // Ranks codecs by their preferences.
+ // Creates a codec with the given parameters.
+ AudioCodec(int pt, const std::string& nm, int cr, int br, int cs, int pr)
+ : id(pt), name(nm), clockrate(cr), bitrate(br),
+ channels(cs), preference(pr) {}
+
+ // Creates an empty codec.
+ AudioCodec() : id(0), clockrate(0), bitrate(0), channels(0), preference(0) {}
+
+ // Indicates if this codec is compatible with the specified codec.
+ bool Matches(int payload, const std::string& nm) const;
+ bool Matches(const AudioCodec& codec) const;
+
+ static bool Preferable(const AudioCodec& first, const AudioCodec& other) {
+ return first.preference > other.preference;
+ }
+
+ std::string ToString() const;
+
+ AudioCodec& operator=(const AudioCodec& c) {
+ this->id = c.id; // id is reserved in objective-c
+ name = c.name;
+ clockrate = c.clockrate;
+ bitrate = c.bitrate;
+ channels = c.channels;
+ preference = c.preference;
+ return *this;
+ }
+
+ bool operator==(const AudioCodec& c) const {
+ return this->id == c.id && // id is reserved in objective-c
+ name == c.name &&
+ clockrate == c.clockrate &&
+ bitrate == c.bitrate &&
+ channels == c.channels &&
+ preference == c.preference;
+ }
+
+ bool operator!=(const AudioCodec& c) const {
+ return !(*this == c);
+ }
};
-#endif // CODEC_H_
+struct VideoCodec {
+ int id;
+ std::string name;
+ int width;
+ int height;
+ int framerate;
+
+ int preference;
+
+ // Creates a codec with the given parameters.
+ VideoCodec(int pt, const std::string& nm, int w, int h, int fr, int pr)
+ : id(pt), name(nm), width(w), height(h), framerate(fr), preference(pr) {}
+
+ // Creates an empty codec.
+ VideoCodec()
+ : id(0), width(0), height(0), framerate(0), preference(0) {}
+
+ bool Matches(int payload, const std::string& nm) const;
+ bool Matches(const VideoCodec& codec) const;
+
+ static bool Preferable(const VideoCodec& first, const VideoCodec& other) {
+ return first.preference > other.preference;
+ }
+
+ std::string ToString() const;
+
+ VideoCodec& operator=(const VideoCodec& c) {
+ this->id = c.id; // id is reserved in objective-c
+ name = c.name;
+ width = c.width;
+ height = c.height;
+ framerate = c.framerate;
+ preference = c.preference;
+ return *this;
+ }
+
+ bool operator==(const VideoCodec& c) const {
+ return this->id == c.id && // id is reserved in objective-c
+ name == c.name &&
+ width == c.width &&
+ height == c.height &&
+ framerate == c.framerate &&
+ preference == c.preference;
+ }
+
+ bool operator!=(const VideoCodec& c) const {
+ return !(*this == c);
+ }
+};
+
+struct VideoEncoderConfig {
+ static const int kDefaultMaxThreads = -1;
+ static const int kDefaultCpuProfile = -1;
+
+ VideoEncoderConfig()
+ : max_codec(),
+ num_threads(kDefaultMaxThreads),
+ cpu_profile(kDefaultCpuProfile) {
+ }
+
+ VideoEncoderConfig(const VideoCodec& c)
+ : max_codec(c),
+ num_threads(kDefaultMaxThreads),
+ cpu_profile(kDefaultCpuProfile) {
+ }
+
+ VideoEncoderConfig(const VideoCodec& c, int t, int p)
+ : max_codec(c),
+ num_threads(t),
+ cpu_profile(p) {
+ }
+
+ VideoEncoderConfig& operator=(const VideoEncoderConfig& config) {
+ max_codec = config.max_codec;
+ num_threads = config.num_threads;
+ cpu_profile = config.cpu_profile;
+ return *this;
+ }
+
+ bool operator==(const VideoEncoderConfig& config) const {
+ return max_codec == config.max_codec &&
+ num_threads == config.num_threads &&
+ cpu_profile == config.cpu_profile;
+ }
+
+ bool operator!=(const VideoEncoderConfig& config) const {
+ return !(*this == config);
+ }
+
+ VideoCodec max_codec;
+ int num_threads;
+ int cpu_profile;
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_CODEC_H_
diff --git a/talk/base/natsocketfactory.h b/talk/session/phone/cryptoparams.h
old mode 100755
new mode 100644
similarity index 63%
copy from talk/base/natsocketfactory.h
copy to talk/session/phone/cryptoparams.h
index a689158..8891659
--- a/talk/base/natsocketfactory.h
+++ b/talk/session/phone/cryptoparams.h
@@ -2,50 +2,53 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_NATSOCKETFACTORY_H__
-#define TALK_BASE_NATSOCKETFACTORY_H__
+#ifndef TALK_SESSION_PHONE_CRYPTOPARAMS_H_
+#define TALK_SESSION_PHONE_CRYPTOPARAMS_H_
-#include "talk/base/socketfactory.h"
+#include <string>
-namespace talk_base {
+namespace cricket {
-// Creates sockets that will send all traffic through a NAT. The actual data
-// is sent using sockets from a socket factory, given to the constructor.
-class NATSocketFactory : public SocketFactory {
-public:
- NATSocketFactory(SocketFactory* factory, const SocketAddress& nat_addr);
+// Parameters for SRTP negotiation, as described in RFC 4586.
+struct CryptoParams {
+ CryptoParams() : tag(0) {}
+ CryptoParams(int t, const std::string& cs,
+ const std::string& kp, const std::string& sp)
+ : tag(t), cipher_suite(cs), key_params(kp), session_params(sp) {}
- virtual Socket* CreateSocket(int type);
- virtual AsyncSocket* CreateAsyncSocket(int type);
+ bool Matches(const CryptoParams& params) const {
+ return (tag == params.tag && cipher_suite == params.cipher_suite);
+ }
-private:
- SocketFactory* factory_;
- SocketAddress nat_addr_;
+ int tag;
+ std::string cipher_suite;
+ std::string key_params;
+ std::string session_params;
};
-} // namespace talk_base
+} // namespace cricket
-#endif // TALK_BASE_NATSOCKETFACTORY_H__
+#endif // TALK_SESSION_PHONE_CRYPTOPARAMS_H_
diff --git a/talk/session/phone/devicemanager.cc b/talk/session/phone/devicemanager.cc
new file mode 100644
index 0000000..e32ed63
--- /dev/null
+++ b/talk/session/phone/devicemanager.cc
@@ -0,0 +1,931 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/phone/devicemanager.h"
+
+#if WIN32
+#include <atlbase.h>
+#include <dbt.h>
+#include <strmif.h> // must come before ks.h
+#include <ks.h>
+#include <ksmedia.h>
+#define INITGUID // For PKEY_AudioEndpoint_GUID
+#include <mmdeviceapi.h>
+#include <functiondiscoverykeys_devpkey.h>
+#include <uuids.h>
+#include "talk/base/win32.h" // ToUtf8
+#include "talk/base/win32window.h"
+#elif OSX
+#include <CoreAudio/CoreAudio.h>
+#include <QuickTime/QuickTime.h>
+#elif LINUX
+#include <unistd.h>
+#ifndef USE_TALK_SOUND
+#include <alsa/asoundlib.h>
+#endif
+#include "talk/base/linux.h"
+#include "talk/base/fileutils.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/stream.h"
+#include "talk/session/phone/v4llookup.h"
+#endif
+
+#include "talk/base/logging.h"
+#include "talk/base/stringutils.h"
+#include "talk/session/phone/mediaengine.h"
+#if USE_TALK_SOUND
+#include "talk/sound/platformsoundsystem.h"
+#include "talk/sound/sounddevicelocator.h"
+#include "talk/sound/soundsysteminterface.h"
+#endif
+
+namespace cricket {
+// Initialize to empty string.
+const std::string DeviceManager::kDefaultDeviceName;
+
+#if WIN32
+class DeviceWatcher : public talk_base::Win32Window {
+ public:
+ explicit DeviceWatcher(DeviceManager* dm);
+ bool Start();
+ void Stop();
+ private:
+ HDEVNOTIFY Register(REFGUID guid);
+ void Unregister(HDEVNOTIFY notify);
+ virtual bool OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT& result);
+ DeviceManager* manager_;
+ HDEVNOTIFY audio_notify_;
+ HDEVNOTIFY video_notify_;
+};
+#else
+// TODO: Implement this for other platforms.
+class DeviceWatcher {
+ public:
+ explicit DeviceWatcher(DeviceManager* dm) {}
+ bool Start() { return true; }
+ void Stop() {}
+};
+#endif
+
+#ifndef LINUX
+static bool ShouldDeviceBeIgnored(const std::string& device_name);
+#endif
+#ifndef OSX
+static bool GetVideoDevices(std::vector<Device>* out);
+#endif
+#if WIN32
+static const wchar_t kFriendlyName[] = L"FriendlyName";
+static const wchar_t kDevicePath[] = L"DevicePath";
+static const char kUsbDevicePathPrefix[] = "\\\\?\\usb";
+static bool GetDevices(const CLSID& catid, std::vector<Device>* out);
+static bool GetCoreAudioDevices(bool input, std::vector<Device>* devs);
+static bool GetWaveDevices(bool input, std::vector<Device>* devs);
+#elif OSX
+static const int kVideoDeviceOpenAttempts = 3;
+static const UInt32 kAudioDeviceNameLength = 64;
+// Obj-C function defined in devicemanager-mac.mm
+extern bool GetQTKitVideoDevices(std::vector<Device>* out);
+static bool GetAudioDeviceIDs(bool inputs, std::vector<AudioDeviceID>* out);
+static bool GetAudioDeviceName(AudioDeviceID id, bool input, std::string* out);
+#endif
+
+DeviceManager::DeviceManager(
+#ifdef USE_TALK_SOUND
+ SoundSystemFactory *factory
+#endif
+ )
+ : initialized_(false),
+ watcher_(new DeviceWatcher(this))
+#ifdef USE_TALK_SOUND
+ , sound_system_(factory)
+#endif
+ {
+}
+
+DeviceManager::~DeviceManager() {
+ if (initialized_) {
+ Terminate();
+ }
+ delete watcher_;
+}
+
+bool DeviceManager::Init() {
+ if (!initialized_) {
+ if (!watcher_->Start()) {
+ return false;
+ }
+ initialized_ = true;
+ }
+ return true;
+}
+
+void DeviceManager::Terminate() {
+ if (initialized_) {
+ watcher_->Stop();
+ initialized_ = false;
+ }
+}
+
+int DeviceManager::GetCapabilities() {
+ std::vector<Device> devices;
+ int caps = MediaEngine::VIDEO_RECV;
+ if (GetAudioInputDevices(&devices) && !devices.empty()) {
+ caps |= MediaEngine::AUDIO_SEND;
+ }
+ if (GetAudioOutputDevices(&devices) && !devices.empty()) {
+ caps |= MediaEngine::AUDIO_RECV;
+ }
+ if (GetVideoCaptureDevices(&devices) && !devices.empty()) {
+ caps |= MediaEngine::VIDEO_SEND;
+ }
+ return caps;
+}
+
+bool DeviceManager::GetAudioInputDevices(std::vector<Device>* devices) {
+ return GetAudioDevicesByPlatform(true, devices);
+}
+
+bool DeviceManager::GetAudioOutputDevices(std::vector<Device>* devices) {
+ return GetAudioDevicesByPlatform(false, devices);
+}
+
+bool DeviceManager::GetAudioInputDevice(const std::string& name, Device* out) {
+ return GetAudioDevice(true, name, out);
+}
+
+bool DeviceManager::GetAudioOutputDevice(const std::string& name, Device* out) {
+ return GetAudioDevice(false, name, out);
+}
+
+#ifdef OSX
+static bool FilterDevice(const Device& d) {
+ return ShouldDeviceBeIgnored(d.name);
+}
+#endif
+
+bool DeviceManager::GetVideoCaptureDevices(std::vector<Device>* devices) {
+ devices->clear();
+#ifdef OSX
+ if (GetQTKitVideoDevices(devices)) {
+ // Now filter out any known incompatible devices
+ devices->erase(remove_if(devices->begin(), devices->end(), FilterDevice),
+ devices->end());
+ return true;
+ }
+ return false;
+#else
+ return GetVideoDevices(devices);
+#endif
+}
+
+#ifdef OSX
+bool DeviceManager::QtKitToSgDevice(const std::string& qtkit_name,
+ Device* out) {
+ out->name.clear();
+
+ ComponentDescription only_vdig;
+ memset(&only_vdig, 0, sizeof(only_vdig));
+ only_vdig.componentType = videoDigitizerComponentType;
+ only_vdig.componentSubType = kAnyComponentSubType;
+ only_vdig.componentManufacturer = kAnyComponentManufacturer;
+
+ // Enumerate components (drivers).
+ Component component = 0;
+ while ((component = FindNextComponent(component, &only_vdig)) &&
+ out->name.empty()) {
+ // Get the name of the component and see if we want to open it.
+ Handle name_handle = NewHandle(0);
+ GetComponentInfo(component, NULL, name_handle, NULL, NULL);
+ Ptr name_ptr = *name_handle;
+ std::string comp_name(name_ptr + 1, static_cast<size_t>(*name_ptr));
+ DisposeHandle(name_handle);
+
+ if (!ShouldDeviceBeIgnored(comp_name)) {
+ // Try to open the component.
+ // DV Video will fail with err=-9408 (deviceCantMeetRequest)
+ // IIDC FireWire Video and USB Video Class Video will fail with err=704
+ // if no cameras are present, or there is contention for the camera.
+ // We can't tell the scenarios apart, so we will retry a few times if
+ // we get a 704 to make sure we detect the cam if one is really there.
+ int attempts = 0;
+ ComponentInstance vdig;
+ OSErr err;
+ do {
+ err = OpenAComponent(component, &vdig);
+ ++attempts;
+ } while (!vdig && err == 704 && attempts < kVideoDeviceOpenAttempts);
+
+ if (vdig) {
+ // We were able to open the component.
+ LOG(LS_INFO) << "Opened component \"" << comp_name
+ << "\", tries=" << attempts;
+
+ // Enumerate cameras on the component.
+ // Note, that due to QT strangeness VDGetNumberOfInputs really returns
+ // the number of inputs minus one. If no inputs are available -1 is
+ // returned.
+ short num_inputs; // NOLINT
+ VideoDigitizerError err = VDGetNumberOfInputs(vdig, &num_inputs);
+ if (err == 0 && num_inputs >= 0) {
+ LOG(LS_INFO) << "Found " << num_inputs + 1 << " webcams attached.";
+ Str255 pname;
+ for (int i = 0; i <= num_inputs; ++i) {
+ err = VDGetInputName(vdig, i, pname);
+ if (err == 0) {
+ // The format for camera ids is <component>:<camera index>.
+ char id_buf[256];
+ talk_base::sprintfn(id_buf, ARRAY_SIZE(id_buf), "%s:%d",
+ comp_name.c_str(), i);
+ std::string name(reinterpret_cast<const char*>(pname + 1),
+ static_cast<size_t>(*pname)), id(id_buf);
+ LOG(LS_INFO) << " Webcam " << i << ": " << name;
+ if (name == qtkit_name) {
+ out->name = name;
+ out->id = id;
+ break;
+ }
+ }
+ }
+ }
+ CloseComponent(vdig);
+ } else {
+ LOG(LS_INFO) << "Failed to open component \"" << comp_name
+ << "\", err=" << err;
+ }
+ }
+ }
+ return !out->name.empty();
+}
+#endif
+
+bool DeviceManager::GetDefaultVideoCaptureDevice(Device* device) {
+ bool ret = false;
+#if WIN32
+ // If there are multiple capture devices, we want the first USB one.
+ // This avoids issues with defaulting to virtual cameras or grabber cards.
+ std::vector<Device> devices;
+ ret = (GetVideoDevices(&devices) && !devices.empty());
+ if (ret) {
+ *device = devices[0];
+ for (size_t i = 0; i < devices.size(); ++i) {
+ if (strnicmp(devices[i].id.c_str(), kUsbDevicePathPrefix,
+ ARRAY_SIZE(kUsbDevicePathPrefix) - 1) == 0) {
+ *device = devices[i];
+ break;
+ }
+ }
+ }
+#else
+ // We just return the first device.
+ std::vector<Device> devices;
+ ret = (GetVideoCaptureDevices(&devices) && !devices.empty());
+ if (ret) {
+ *device = devices[0];
+ }
+#endif
+ return ret;
+}
+
+
+bool DeviceManager::GetAudioDevice(bool is_input, const std::string& name,
+ Device* out) {
+ // If the name is empty, return the default device id.
+ if (name.empty() || name == kDefaultDeviceName) {
+ *out = Device(name, -1);
+ return true;
+ }
+
+ std::vector<Device> devices;
+ bool ret = is_input ? GetAudioInputDevices(&devices) :
+ GetAudioOutputDevices(&devices);
+ if (ret) {
+ ret = false;
+ for (size_t i = 0; i < devices.size(); ++i) {
+ if (devices[i].name == name) {
+ *out = devices[i];
+ ret = true;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+bool DeviceManager::GetAudioDevicesByPlatform(bool input,
+ std::vector<Device>* devs) {
+ devs->clear();
+#if defined(USE_TALK_SOUND)
+ if (!sound_system_.get()) {
+ return false;
+ }
+ SoundSystemInterface::SoundDeviceLocatorList list;
+ bool success;
+ if (input) {
+ success = sound_system_->EnumerateCaptureDevices(&list);
+ } else {
+ success = sound_system_->EnumeratePlaybackDevices(&list);
+ }
+ if (!success) {
+ LOG(LS_ERROR) << "Can't enumerate devices";
+ sound_system_.release();
+ return false;
+ }
+ int index = 0;
+ for (SoundSystemInterface::SoundDeviceLocatorList::iterator i = list.begin();
+ i != list.end();
+ ++i, ++index) {
+ devs->push_back(Device((*i)->name(), index));
+ }
+ SoundSystemInterface::ClearSoundDeviceLocatorList(&list);
+ sound_system_.release();
+ return true;
+
+#elif defined(WIN32)
+ if (talk_base::IsWindowsVistaOrLater()) {
+ return GetCoreAudioDevices(input, devs);
+ } else {
+ return GetWaveDevices(input, devs);
+ }
+
+#elif defined(OSX)
+ std::vector<AudioDeviceID> dev_ids;
+ bool ret = GetAudioDeviceIDs(input, &dev_ids);
+ if (ret) {
+ for (size_t i = 0; i < dev_ids.size(); ++i) {
+ std::string name;
+ if (GetAudioDeviceName(dev_ids[i], input, &name)) {
+ devs->push_back(Device(name, dev_ids[i]));
+ }
+ }
+ }
+ return ret;
+
+#elif defined(LINUX)
+ int card = -1, dev = -1;
+ snd_ctl_t *handle = NULL;
+ snd_pcm_info_t *pcminfo = NULL;
+
+ snd_pcm_info_malloc(&pcminfo);
+
+ while (true) {
+ if (snd_card_next(&card) != 0 || card < 0)
+ break;
+
+ char *card_name;
+ if (snd_card_get_name(card, &card_name) != 0)
+ continue;
+
+ char card_string[7];
+ snprintf(card_string, sizeof(card_string), "hw:%d", card);
+ if (snd_ctl_open(&handle, card_string, 0) != 0)
+ continue;
+
+ while (true) {
+ if (snd_ctl_pcm_next_device(handle, &dev) < 0 || dev < 0)
+ break;
+ snd_pcm_info_set_device(pcminfo, dev);
+ snd_pcm_info_set_subdevice(pcminfo, 0);
+ snd_pcm_info_set_stream(pcminfo, input ? SND_PCM_STREAM_CAPTURE :
+ SND_PCM_STREAM_PLAYBACK);
+ if (snd_ctl_pcm_info(handle, pcminfo) != 0)
+ continue;
+
+ char name[128];
+ talk_base::sprintfn(name, sizeof(name), "%s (%s)", card_name,
+ snd_pcm_info_get_name(pcminfo));
+ // TODO: We might want to identify devices with something
+ // more specific than just their card number (e.g., the PCM names that
+ // aplay -L prints out).
+ devs->push_back(Device(name, card));
+
+ LOG(LS_INFO) << "Found device: id = " << card << ", name = "
+ << name;
+ }
+ snd_ctl_close(handle);
+ }
+ snd_pcm_info_free(pcminfo);
+ return true;
+#else
+ return false;
+#endif
+}
+
+#if defined(WIN32)
+bool GetVideoDevices(std::vector<Device>* devices) {
+ // TODO: Move the CoInit stuff to Initialize/Terminate.
+ HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ if (FAILED(hr)) {
+ LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr;
+ if (hr != RPC_E_CHANGED_MODE) {
+ return false;
+ }
+ }
+
+ bool ret = GetDevices(CLSID_VideoInputDeviceCategory, devices);
+ if (SUCCEEDED(hr)) {
+ CoUninitialize();
+ }
+ return ret;
+}
+
+bool GetDevices(const CLSID& catid, std::vector<Device>* devices) {
+ HRESULT hr;
+
+ // CComPtr is a scoped pointer that will be auto released when going
+ // out of scope. CoUninitialize must not be called before the
+ // release.
+ CComPtr<ICreateDevEnum> sys_dev_enum;
+ CComPtr<IEnumMoniker> cam_enum;
+ if (FAILED(hr = sys_dev_enum.CoCreateInstance(CLSID_SystemDeviceEnum)) ||
+ FAILED(hr = sys_dev_enum->CreateClassEnumerator(catid, &cam_enum, 0))) {
+ LOG(LS_ERROR) << "Failed to create device enumerator, hr=" << hr;
+ return false;
+ }
+
+ // Only enum devices if CreateClassEnumerator returns S_OK. If there are no
+ // devices available, S_FALSE will be returned, but enumMk will be NULL.
+ if (hr == S_OK) {
+ CComPtr<IMoniker> mk;
+ while (cam_enum->Next(1, &mk, NULL) == S_OK) {
+ CComPtr<IPropertyBag> bag;
+ if (SUCCEEDED(mk->BindToStorage(NULL, NULL,
+ __uuidof(bag), reinterpret_cast<void**>(&bag)))) {
+ CComVariant name, path;
+ std::string name_str, path_str;
+ if (SUCCEEDED(bag->Read(kFriendlyName, &name, 0)) &&
+ name.vt == VT_BSTR) {
+ name_str = talk_base::ToUtf8(name.bstrVal);
+ if (!ShouldDeviceBeIgnored(name_str)) {
+ // Get the device id if one exists.
+ if (SUCCEEDED(bag->Read(kDevicePath, &path, 0)) &&
+ path.vt == VT_BSTR) {
+ path_str = talk_base::ToUtf8(path.bstrVal);
+ }
+
+ devices->push_back(Device(name_str, path_str));
+ }
+ }
+ }
+ mk = NULL;
+ }
+ }
+
+ return true;
+}
+
+HRESULT GetStringProp(IPropertyStore* bag, PROPERTYKEY key, std::string* out) {
+ out->clear();
+ PROPVARIANT var;
+ PropVariantInit(&var);
+
+ HRESULT hr = bag->GetValue(key, &var);
+ if (SUCCEEDED(hr)) {
+ if (var.pwszVal)
+ *out = talk_base::ToUtf8(var.pwszVal);
+ else
+ hr = E_FAIL;
+ }
+
+ PropVariantClear(&var);
+ return hr;
+}
+
+// Adapted from http://msdn.microsoft.com/en-us/library/dd370812(v=VS.85).aspx
+HRESULT CricketDeviceFromImmDevice(IMMDevice* device, Device* out) {
+ CComPtr<IPropertyStore> props;
+
+ HRESULT hr = device->OpenPropertyStore(STGM_READ, &props);
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ // Get the endpoint's name and id.
+ std::string name, guid;
+ hr = GetStringProp(props, PKEY_Device_FriendlyName, &name);
+ if (SUCCEEDED(hr)) {
+ hr = GetStringProp(props, PKEY_AudioEndpoint_GUID, &guid);
+
+ if (SUCCEEDED(hr)) {
+ out->name = name;
+ out->id = guid;
+ }
+ }
+ return hr;
+}
+
+bool GetCoreAudioDevices(bool input, std::vector<Device>* devs) {
+ HRESULT hr = S_OK;
+ CComPtr<IMMDeviceEnumerator> enumerator;
+
+ hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
+ __uuidof(IMMDeviceEnumerator), reinterpret_cast<void**>(&enumerator));
+ if (SUCCEEDED(hr)) {
+ CComPtr<IMMDeviceCollection> devices;
+ hr = enumerator->EnumAudioEndpoints((input ? eCapture : eRender),
+ DEVICE_STATE_ACTIVE, &devices);
+ if (SUCCEEDED(hr)) {
+ unsigned int count;
+ hr = devices->GetCount(&count);
+
+ if (SUCCEEDED(hr)) {
+ for (unsigned int i = 0; i < count; i++) {
+ CComPtr<IMMDevice> device;
+
+ // Get pointer to endpoint number i.
+ hr = devices->Item(i, &device);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ Device dev;
+ hr = CricketDeviceFromImmDevice(device, &dev);
+ if (SUCCEEDED(hr)) {
+ devs->push_back(dev);
+ } else {
+ LOG(LS_WARNING) << "Unable to query IMM Device, skipping. HR="
+ << hr;
+ hr = S_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ if (!SUCCEEDED(hr)) {
+ LOG(LS_WARNING) << "GetCoreAudioDevices failed with hr " << hr;
+ return false;
+ }
+ return true;
+}
+
+bool GetWaveDevices(bool input, std::vector<Device>* devs) {
+ // Note, we don't use the System Device Enumerator interface here since it
+ // adds lots of pseudo-devices to the list, such as DirectSound and Wave
+ // variants of the same device.
+ if (input) {
+ int num_devs = waveInGetNumDevs();
+ for (int i = 0; i < num_devs; ++i) {
+ WAVEINCAPS caps;
+ if (waveInGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR &&
+ caps.wChannels > 0) {
+ devs->push_back(Device(talk_base::ToUtf8(caps.szPname),
+ talk_base::ToString(i)));
+ }
+ }
+ } else {
+ int num_devs = waveOutGetNumDevs();
+ for (int i = 0; i < num_devs; ++i) {
+ WAVEOUTCAPS caps;
+ if (waveOutGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR &&
+ caps.wChannels > 0) {
+ devs->push_back(Device(talk_base::ToUtf8(caps.szPname), i));
+ }
+ }
+ }
+ return true;
+}
+
+DeviceWatcher::DeviceWatcher(DeviceManager* manager)
+ : manager_(manager), audio_notify_(NULL), video_notify_(NULL) {
+}
+
+bool DeviceWatcher::Start() {
+ if (!Create(NULL, _T("libjingle DeviceWatcher Window"),
+ 0, 0, 0, 0, 0, 0)) {
+ return false;
+ }
+
+ audio_notify_ = Register(KSCATEGORY_AUDIO);
+ if (!audio_notify_) {
+ Stop();
+ return false;
+ }
+
+ video_notify_ = Register(KSCATEGORY_VIDEO);
+ if (!video_notify_) {
+ Stop();
+ return false;
+ }
+
+ return true;
+}
+
+void DeviceWatcher::Stop() {
+ UnregisterDeviceNotification(video_notify_);
+ video_notify_ = NULL;
+ UnregisterDeviceNotification(audio_notify_);
+ audio_notify_ = NULL;
+ Destroy();
+}
+
+HDEVNOTIFY DeviceWatcher::Register(REFGUID guid) {
+ DEV_BROADCAST_DEVICEINTERFACE dbdi;
+ dbdi.dbcc_size = sizeof(dbdi);
+ dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ dbdi.dbcc_classguid = guid;
+ dbdi.dbcc_name[0] = '\0';
+ return RegisterDeviceNotification(handle(), &dbdi,
+ DEVICE_NOTIFY_WINDOW_HANDLE);
+}
+
+void DeviceWatcher::Unregister(HDEVNOTIFY handle) {
+ UnregisterDeviceNotification(handle);
+}
+
+bool DeviceWatcher::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
+ LRESULT& result) {
+ if (uMsg == WM_DEVICECHANGE) {
+ if (wParam == DBT_DEVICEARRIVAL ||
+ wParam == DBT_DEVICEREMOVECOMPLETE) {
+ DEV_BROADCAST_DEVICEINTERFACE* dbdi =
+ reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(lParam);
+ if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO ||
+ dbdi->dbcc_classguid == KSCATEGORY_VIDEO) {
+ manager_->OnDevicesChange();
+ }
+ }
+ result = 0;
+ return true;
+ }
+
+ return false;
+}
+#elif defined(OSX)
+static bool GetAudioDeviceIDs(bool input,
+ std::vector<AudioDeviceID>* out_dev_ids) {
+ UInt32 propsize;
+ OSErr err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
+ &propsize, NULL);
+ if (0 != err) {
+ LOG(LS_ERROR) << "Couldn't get information about property, "
+ << "so no device list acquired.";
+ return false;
+ }
+
+ size_t num_devices = propsize / sizeof(AudioDeviceID);
+ talk_base::scoped_array<AudioDeviceID> device_ids(
+ new AudioDeviceID[num_devices]);
+
+ err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
+ &propsize, device_ids.get());
+ if (0 != err) {
+ LOG(LS_ERROR) << "Failed to get device ids, "
+ << "so no device listing acquired.";
+ return false;
+ }
+
+ for (size_t i = 0; i < num_devices; ++i) {
+ AudioDeviceID an_id = device_ids[i];
+ // find out the number of channels for this direction
+ // (input/output) on this device -
+ // we'll ignore anything with no channels.
+ err = AudioDeviceGetPropertyInfo(an_id, 0, input,
+ kAudioDevicePropertyStreams,
+ &propsize, NULL);
+ if (0 == err) {
+ unsigned num_channels = propsize / sizeof(AudioStreamID);
+ if (0 < num_channels) {
+ out_dev_ids->push_back(an_id);
+ }
+ } else {
+ LOG(LS_ERROR) << "No property info for stream property for device id "
+ << an_id << "(is_input == " << input
+ << "), so not including it in the list.";
+ }
+ }
+
+ return true;
+}
+
+static bool GetAudioDeviceName(AudioDeviceID id,
+ bool input,
+ std::string* out_name) {
+ UInt32 nameLength = kAudioDeviceNameLength;
+ char name[kAudioDeviceNameLength + 1];
+ OSErr err = AudioDeviceGetProperty(id, 0, input,
+ kAudioDevicePropertyDeviceName,
+ &nameLength, name);
+ if (0 != err) {
+ LOG(LS_ERROR) << "No name acquired for device id " << id;
+ return false;
+ }
+
+ *out_name = name;
+ return true;
+}
+
+#elif defined(LINUX)
+static const std::string kVideoMetaPathK2_4("/proc/video/dev/");
+static const std::string kVideoMetaPathK2_6("/sys/class/video4linux/");
+
+enum MetaType { M2_4, M2_6, NONE };
+
+static void ScanDeviceDirectory(const std::string& devdir,
+ std::vector<Device>* devices) {
+ talk_base::scoped_ptr<talk_base::DirectoryIterator> directoryIterator(
+ talk_base::Filesystem::IterateDirectory());
+
+ if (directoryIterator->Iterate(talk_base::Pathname(devdir))) {
+ do {
+ std::string filename = directoryIterator->Name();
+ std::string device_name = devdir + filename;
+ if (!directoryIterator->IsDots()) {
+ if (filename.find("video") == 0 &&
+ V4LLookup::IsV4L2Device(device_name)) {
+ devices->push_back(Device(device_name, device_name));
+ }
+ }
+ } while (directoryIterator->Next());
+ }
+}
+
+static std::string GetVideoDeviceNameK2_6(const std::string& device_meta_path) {
+ std::string device_name;
+
+ talk_base::scoped_ptr<talk_base::FileStream> device_meta_stream(
+ talk_base::Filesystem::OpenFile(device_meta_path, "r"));
+
+ if (device_meta_stream.get() != NULL) {
+ if (device_meta_stream->ReadLine(&device_name) != talk_base::SR_SUCCESS) {
+ LOG(LS_ERROR) << "Failed to read V4L2 device meta " << device_meta_path;
+ }
+ device_meta_stream->Close();
+ }
+
+ return device_name;
+}
+
+static std::string Trim(const std::string& s, const std::string& drop = " \t") {
+ std::string::size_type first = s.find_first_not_of(drop);
+ std::string::size_type last = s.find_last_not_of(drop);
+
+ if (first == std::string::npos || last == std::string::npos)
+ return std::string("");
+
+ return s.substr(first, last - first + 1);
+}
+
+static std::string GetVideoDeviceNameK2_4(const std::string& device_meta_path) {
+ talk_base::ConfigParser::MapVector all_values;
+
+ talk_base::ConfigParser config_parser;
+ talk_base::FileStream* file_stream =
+ talk_base::Filesystem::OpenFile(device_meta_path, "r");
+
+ if (file_stream == NULL) return "";
+
+ config_parser.Attach(file_stream);
+ config_parser.Parse(&all_values);
+
+ for (talk_base::ConfigParser::MapVector::iterator i = all_values.begin();
+ i != all_values.end(); ++i) {
+ talk_base::ConfigParser::SimpleMap::iterator device_name_i =
+ i->find("name");
+
+ if (device_name_i != i->end()) {
+ return device_name_i->second;
+ }
+ }
+
+ return "";
+}
+
+static std::string GetVideoDeviceName(MetaType meta,
+ const std::string& device_file_name) {
+ std::string device_meta_path;
+ std::string device_name;
+ std::string meta_file_path;
+
+ if (meta == M2_6) {
+ meta_file_path = kVideoMetaPathK2_6 + device_file_name + "/name";
+
+ LOG(LS_INFO) << "Trying " + meta_file_path;
+ device_name = GetVideoDeviceNameK2_6(meta_file_path);
+
+ if (device_name.empty()) {
+ meta_file_path = kVideoMetaPathK2_6 + device_file_name + "/model";
+
+ LOG(LS_INFO) << "Trying " << meta_file_path;
+ device_name = GetVideoDeviceNameK2_6(meta_file_path);
+ }
+ } else {
+ meta_file_path = kVideoMetaPathK2_4 + device_file_name;
+ LOG(LS_INFO) << "Trying " << meta_file_path;
+ device_name = GetVideoDeviceNameK2_4(meta_file_path);
+ }
+
+ if (device_name.empty()) {
+ device_name = "/dev/" + device_file_name;
+ LOG(LS_ERROR)
+ << "Device name not found, defaulting to device path " << device_name;
+ }
+
+ LOG(LS_INFO) << "Name for " << device_file_name << " is " << device_name;
+
+ return Trim(device_name);
+}
+
+static void ScanV4L2Devices(std::vector<Device>* devices) {
+ LOG(LS_INFO) << ("Enumerating V4L2 devices");
+
+ MetaType meta;
+ std::string metadata_dir;
+
+ talk_base::scoped_ptr<talk_base::DirectoryIterator> directoryIterator(
+ talk_base::Filesystem::IterateDirectory());
+
+ // Try and guess kernel version
+ if (directoryIterator->Iterate(kVideoMetaPathK2_6)) {
+ meta = M2_6;
+ metadata_dir = kVideoMetaPathK2_6;
+ } else if (directoryIterator->Iterate(kVideoMetaPathK2_4)) {
+ meta = M2_4;
+ metadata_dir = kVideoMetaPathK2_4;
+ } else {
+ meta = NONE;
+ }
+
+ if (meta != NONE) {
+ LOG(LS_INFO) << "V4L2 device metadata found at " << metadata_dir;
+
+ do {
+ std::string filename = directoryIterator->Name();
+
+ if (filename.find("video") == 0) {
+ std::string device_path = "/dev/" + filename;
+
+ if (V4LLookup::IsV4L2Device(device_path)) {
+ devices->push_back(
+ Device(GetVideoDeviceName(meta, filename), device_path));
+ }
+ }
+ } while (directoryIterator->Next());
+ } else {
+ LOG(LS_ERROR) << "Unable to detect v4l2 metadata directory";
+ }
+
+ if (devices->size() == 0) {
+ LOG(LS_INFO) << "Plan B. Scanning all video devices in /dev directory";
+ ScanDeviceDirectory("/dev/", devices);
+ }
+
+ LOG(LS_INFO) << "Total V4L2 devices found : " << devices->size();
+}
+
+static bool GetVideoDevices(std::vector<Device>* devices) {
+ ScanV4L2Devices(devices);
+ return true;
+}
+#endif
+
+// TODO: Try to get hold of a copy of Final Cut to understand why we
+// crash while scanning their components on OS X.
+#ifndef LINUX
+static bool ShouldDeviceBeIgnored(const std::string& device_name) {
+ static const char* const kFilteredDevices[] = {
+ "Google Camera Adapter", // Our own magiccams
+#ifdef WIN32
+ "Asus virtual Camera", // Bad Asus desktop virtual cam
+ "Bluetooth Video", // Bad Sony viao bluetooth sharing driver
+#elif OSX
+ "DVCPRO HD", // Final cut
+ "Sonix SN9C201p", // Crashes in OpenAComponent and CloseComponent
+#endif
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(kFilteredDevices); ++i) {
+ if (strnicmp(device_name.c_str(), kFilteredDevices[i],
+ strlen(kFilteredDevices[i])) == 0) {
+ LOG(LS_INFO) << "Ignoring device " << device_name;
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
+}; // namespace cricket
diff --git a/talk/session/phone/devicemanager.h b/talk/session/phone/devicemanager.h
new file mode 100644
index 0000000..594e9bd
--- /dev/null
+++ b/talk/session/phone/devicemanager.h
@@ -0,0 +1,111 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_SESSION_PHONE_DEVICEMANAGER_H_
+#define TALK_SESSION_PHONE_DEVICEMANAGER_H_
+
+#include <string>
+#include <vector>
+
+#include "talk/base/sigslot.h"
+#include "talk/base/stringencode.h"
+#ifdef USE_TALK_SOUND
+#include "talk/sound/soundsystemfactory.h"
+#endif
+
+namespace cricket {
+
+class DeviceWatcher;
+
+// Used to represent an audio or video capture or render device.
+struct Device {
+ Device() {}
+ Device(const std::string& first, int second)
+ : name(first),
+ id(talk_base::ToString(second)) {
+ }
+ Device(const std::string& first, const std::string& second)
+ : name(first), id(second) {}
+
+ std::string name;
+ std::string id;
+};
+
+// DeviceManager manages the audio and video devices on the system.
+// Methods are virtual to allow for easy stubbing/mocking in tests.
+class DeviceManager {
+ public:
+ DeviceManager(
+#ifdef USE_TALK_SOUND
+ SoundSystemFactory *factory
+#endif
+ );
+ virtual ~DeviceManager();
+
+ // Initialization
+ virtual bool Init();
+ virtual void Terminate();
+ bool initialized() const { return initialized_; }
+
+ // Capabilities
+ virtual int GetCapabilities();
+
+ // Device enumeration
+ virtual bool GetAudioInputDevices(std::vector<Device>* devices);
+ virtual bool GetAudioOutputDevices(std::vector<Device>* devices);
+
+ bool GetAudioInputDevice(const std::string& name, Device* out);
+ bool GetAudioOutputDevice(const std::string& name, Device* out);
+
+ virtual bool GetVideoCaptureDevices(std::vector<Device>* devs);
+ virtual bool GetDefaultVideoCaptureDevice(Device* device);
+#ifdef OSX
+ virtual bool QtKitToSgDevice(const std::string& qtkit_name, Device* out);
+#endif
+
+ sigslot::signal0<> SignalDevicesChange;
+
+ void OnDevicesChange() { SignalDevicesChange(); }
+
+ static const std::string kDefaultDeviceName;
+
+ protected:
+ virtual bool GetAudioDevice(bool is_input, const std::string& name,
+ Device* out);
+ private:
+ bool GetAudioDevicesByPlatform(bool input, std::vector<Device>* devs);
+
+ bool initialized_;
+ DeviceWatcher* watcher_;
+#ifdef USE_TALK_SOUND
+ SoundSystemHandle sound_system_;
+#endif
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_DEVICEMANAGER_H_
diff --git a/talk/session/phone/devicemanager_mac.mm b/talk/session/phone/devicemanager_mac.mm
new file mode 100644
index 0000000..1a14e95
--- /dev/null
+++ b/talk/session/phone/devicemanager_mac.mm
@@ -0,0 +1,68 @@
+/*
+ * libjingle
+ * Copyright 2004--2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/phone/devicemanager.h"
+
+#import <QTKit/QTKit.h>
+
+#include "talk/base/logging.h"
+
+namespace cricket {
+
+bool GetQTKitVideoDevices(std::vector<Device>* devices) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray* qt_capture_devices =
+ [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo];
+ NSUInteger count = [qt_capture_devices count];
+ LOG(LS_INFO) << count << " capture device(s) found:";
+ for (NSUInteger i = 0; i < count; ++i) {
+ QTCaptureDevice* qt_capture_device = [qt_capture_devices objectAtIndex:i];
+
+ static const NSString* kFormat = @"localizedDisplayName: \"%@\", "
+ "modelUniqueID: \"%@\", isConnected: %d, isOpen: %d, "
+ "isInUseByAnotherApplication: %d";
+ NSString* info = [NSString stringWithFormat:kFormat,
+ [qt_capture_device localizedDisplayName],
+ [qt_capture_device modelUniqueID],
+ [qt_capture_device isConnected],
+ [qt_capture_device isOpen],
+ [qt_capture_device isInUseByAnotherApplication]];
+ LOG(LS_INFO) << [info cStringUsingEncoding:NSUTF8StringEncoding];
+
+ std::string name([[qt_capture_device localizedDisplayName]
+ cStringUsingEncoding:NSUTF8StringEncoding]);
+ devices->push_back(Device(name,
+ [[qt_capture_device modelUniqueID]
+ cStringUsingEncoding:NSUTF8StringEncoding]));
+ }
+
+ [pool drain];
+ return true;
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/filemediaengine.cc b/talk/session/phone/filemediaengine.cc
new file mode 100644
index 0000000..4929933
--- /dev/null
+++ b/talk/session/phone/filemediaengine.cc
@@ -0,0 +1,230 @@
+// libjingle
+// Copyright 2004--2005, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "talk/session/phone/filemediaengine.h"
+
+#include "talk/base/event.h"
+#include "talk/base/logging.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/stream.h"
+#include "talk/session/phone/rtpdump.h"
+
+namespace cricket {
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation of FileMediaEngine.
+///////////////////////////////////////////////////////////////////////////
+int FileMediaEngine::GetCapabilities() {
+ int capabilities = 0;
+ if (!voice_input_filename_.empty()) {
+ capabilities |= MediaEngine::AUDIO_SEND;
+ }
+ if (!voice_output_filename_.empty()) {
+ capabilities |= MediaEngine::AUDIO_RECV;
+ }
+ if (!video_input_filename_.empty()) {
+ capabilities |= MediaEngine::VIDEO_SEND;
+ }
+ if (!video_output_filename_.empty()) {
+ capabilities |= MediaEngine::VIDEO_RECV;
+ }
+ return capabilities;
+}
+
+VoiceMediaChannel* FileMediaEngine::CreateChannel() {
+ if (!voice_input_filename_.empty() || !voice_output_filename_.empty()) {
+ return new FileVoiceChannel(voice_input_filename_, voice_output_filename_);
+ } else {
+ return NULL;
+ }
+}
+
+VideoMediaChannel* FileMediaEngine::CreateVideoChannel(
+ VoiceMediaChannel* voice_ch) {
+ if (!video_input_filename_.empty() || !video_output_filename_.empty()) {
+ return new FileVideoChannel(video_input_filename_, video_output_filename_);
+ } else {
+ return NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Definition of RtpSenderReceiver.
+///////////////////////////////////////////////////////////////////////////
+class RtpSenderReceiver
+ : public talk_base::Thread, public talk_base::MessageHandler {
+ public:
+ RtpSenderReceiver(MediaChannel* channel, const std::string& in_file,
+ const std::string& out_file);
+
+ // Called by media channel. Context: media channel thread.
+ bool SetSend(bool send);
+ void OnPacketReceived(const void* data, int len);
+
+ // Override virtual method of parent MessageHandler. Context: Worker Thread.
+ virtual void OnMessage(talk_base::Message* pmsg);
+
+ private:
+ // Send a RTP packet to the network. The input parameter data points to the
+ // start of the RTP packet and len is the packet size. Return true if the sent
+ // size is equal to len.
+ bool SendRtpPacket(const void* data, size_t len);
+
+ MediaChannel* media_channel_;
+ talk_base::scoped_ptr<talk_base::StreamInterface> input_stream_;
+ talk_base::scoped_ptr<talk_base::StreamInterface> output_stream_;
+ talk_base::scoped_ptr<RtpDumpLoopReader> rtp_dump_reader_;
+ talk_base::scoped_ptr<RtpDumpWriter> rtp_dump_writer_;
+ // RTP dump packet read from the input stream.
+ RtpDumpPacket rtp_dump_packet_;
+ bool sending_;
+ bool first_packet_;
+
+ DISALLOW_COPY_AND_ASSIGN(RtpSenderReceiver);
+};
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation of RtpSenderReceiver.
+///////////////////////////////////////////////////////////////////////////
+RtpSenderReceiver::RtpSenderReceiver(MediaChannel* channel,
+ const std::string& in_file,
+ const std::string& out_file)
+ : media_channel_(channel),
+ sending_(false),
+ first_packet_(true) {
+ input_stream_.reset(talk_base::Filesystem::OpenFile(
+ talk_base::Pathname(in_file), "rb"));
+ if (input_stream_.get()) {
+ rtp_dump_reader_.reset(new RtpDumpLoopReader(input_stream_.get()));
+ // Start the sender thread, which reads rtp dump records, waits based on
+ // the record timestamps, and sends the RTP packets to the network.
+ Thread::Start();
+ }
+
+ // Create a rtp dump writer for the output RTP dump stream.
+ output_stream_.reset(talk_base::Filesystem::OpenFile(
+ talk_base::Pathname(out_file), "wb"));
+ if (output_stream_.get()) {
+ rtp_dump_writer_.reset(new RtpDumpWriter(output_stream_.get()));
+ }
+}
+
+bool RtpSenderReceiver::SetSend(bool send) {
+ bool was_sending = sending_;
+ sending_ = send;
+ if (!was_sending && sending_) {
+ PostDelayed(0, this); // Wake up the send thread.
+ }
+ return true;
+}
+
+void RtpSenderReceiver::OnPacketReceived(const void* data, int len) {
+ if (rtp_dump_writer_.get()) {
+ rtp_dump_writer_->WriteRtpPacket(data, len);
+ }
+}
+
+void RtpSenderReceiver::OnMessage(talk_base::Message* pmsg) {
+ if (!sending_) {
+ // If the sender thread is not sending, ignore this message. The thread goes
+ // to sleep until SetSend(true) wakes it up.
+ return;
+ }
+
+ uint32 prev_elapsed_time = 0xFFFFFFFF;
+ if (!first_packet_) {
+ prev_elapsed_time = rtp_dump_packet_.elapsed_time;
+ SendRtpPacket(&rtp_dump_packet_.data[0], rtp_dump_packet_.data.size());
+ } else {
+ first_packet_ = false;
+ }
+
+ // Read a dump packet and wait for the elapsed time.
+ if (talk_base::SR_SUCCESS ==
+ rtp_dump_reader_->ReadPacket(&rtp_dump_packet_)) {
+ int waiting_time_ms = rtp_dump_packet_.elapsed_time > prev_elapsed_time ?
+ rtp_dump_packet_.elapsed_time - prev_elapsed_time : 0;
+ PostDelayed(waiting_time_ms, this);
+ } else {
+ Quit();
+ }
+}
+
+bool RtpSenderReceiver::SendRtpPacket(const void* data, size_t len) {
+ if (!media_channel_ || !media_channel_->network_interface()) {
+ return false;
+ }
+
+ return media_channel_->network_interface()->SendPacket(data, len) ==
+ static_cast<int>(len);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation of FileVoiceChannel.
+///////////////////////////////////////////////////////////////////////////
+FileVoiceChannel::FileVoiceChannel(const std::string& in_file,
+ const std::string& out_file)
+ : rtp_sender_receiver_(new RtpSenderReceiver(this, in_file, out_file)) {
+}
+
+FileVoiceChannel::~FileVoiceChannel() {}
+
+bool FileVoiceChannel::SetSendCodecs(const std::vector<AudioCodec>& codecs) {
+ // TODO: Check the format of RTP dump input.
+ return true;
+}
+
+bool FileVoiceChannel::SetSend(SendFlags flag) {
+ return rtp_sender_receiver_->SetSend(flag != SEND_NOTHING);
+}
+
+void FileVoiceChannel::OnPacketReceived(const void* data, int len) {
+ rtp_sender_receiver_->OnPacketReceived(data, len);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation of FileVideoChannel.
+///////////////////////////////////////////////////////////////////////////
+FileVideoChannel::FileVideoChannel(const std::string& in_file,
+ const std::string& out_file)
+ : rtp_sender_receiver_(new RtpSenderReceiver(this, in_file, out_file)) {
+}
+
+FileVideoChannel::~FileVideoChannel() {}
+
+bool FileVideoChannel::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
+ // TODO: Check the format of RTP dump input.
+ return true;
+}
+
+bool FileVideoChannel::SetSend(bool send) {
+ return rtp_sender_receiver_->SetSend(send);
+}
+
+void FileVideoChannel::OnPacketReceived(const void* data, int len) {
+ rtp_sender_receiver_->OnPacketReceived(data, len);
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/filemediaengine.h b/talk/session/phone/filemediaengine.h
new file mode 100644
index 0000000..272449a
--- /dev/null
+++ b/talk/session/phone/filemediaengine.h
@@ -0,0 +1,195 @@
+// libjingle
+// Copyright 2004--2005, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TALK_SESSION_PHONE_FILEMEDIAENGINE_H_
+#define TALK_SESSION_PHONE_FILEMEDIAENGINE_H_
+
+#include <string>
+#include <vector>
+
+#include "talk/base/scoped_ptr.h"
+#include "talk/session/phone/codec.h"
+#include "talk/session/phone/mediachannel.h"
+#include "talk/session/phone/mediaengine.h"
+
+namespace talk_base {
+class StreamInterface;
+}
+
+namespace cricket {
+
+// A media engine contains a capturer, an encoder, and a sender in the sender
+// side and a receiver, a decoder, and a renderer in the receiver side.
+// FileMediaEngine simulates the capturer and the encoder via an input RTP dump
+// stream and simulates the decoder and the renderer via an output RTP dump
+// stream. Depending on the parameters of the constructor, FileMediaEngine can
+// act as file voice engine, file video engine, or both. Currently, we use
+// only the RTP dump packets. TODO: Enable RTCP packets.
+class FileMediaEngine : public MediaEngine {
+ public:
+ FileMediaEngine() {}
+ virtual ~FileMediaEngine() {}
+
+ // Set the file name of the input or output RTP dump for voice or video.
+ // Should be called before the channel is created.
+ void set_voice_input_filename(const std::string& filename) {
+ voice_input_filename_ = filename;
+ }
+ void set_voice_output_filename(const std::string& filename) {
+ voice_output_filename_ = filename;
+ }
+ void set_video_input_filename(const std::string& filename) {
+ video_input_filename_ = filename;
+ }
+ void set_video_output_filename(const std::string& filename) {
+ video_output_filename_ = filename;
+ }
+
+ // Should be called before codecs() and video_codecs() are called. We need to
+ // set the voice and video codecs; otherwise, Jingle initiation will fail.
+ void set_voice_codecs(const std::vector<AudioCodec>& codecs) {
+ voice_codecs_ = codecs;
+ }
+ void set_video_codecs(const std::vector<VideoCodec>& codecs) {
+ video_codecs_ = codecs;
+ }
+
+ // Implement pure virtual methods of MediaEngine.
+ virtual bool Init() { return true; }
+ virtual void Terminate() {}
+ virtual int GetCapabilities();
+ virtual VoiceMediaChannel* CreateChannel();
+ virtual VideoMediaChannel* CreateVideoChannel(VoiceMediaChannel* voice_ch);
+ virtual SoundclipMedia* CreateSoundclip() { return NULL; }
+ virtual bool SetAudioOptions(int options) { return true; }
+ virtual bool SetVideoOptions(int options) { return true; }
+ virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) {
+ return true;
+ }
+ virtual bool SetSoundDevices(const Device* in_dev, const Device* out_dev) {
+ return true;
+ }
+ virtual bool SetVideoCaptureDevice(const Device* cam_device) { return true; }
+ virtual bool SetOutputVolume(int level) { return true; }
+ virtual int GetInputLevel() { return 0; }
+ virtual bool SetLocalMonitor(bool enable) { return true; }
+ virtual bool SetLocalRenderer(VideoRenderer* renderer) { return true; }
+ // TODO: control channel send?
+ virtual CaptureResult SetVideoCapture(bool capture) { return CR_SUCCESS; }
+ virtual const std::vector<AudioCodec>& audio_codecs() {
+ return voice_codecs_;
+ }
+ virtual const std::vector<VideoCodec>& video_codecs() {
+ return video_codecs_;
+ }
+ virtual bool FindAudioCodec(const AudioCodec& codec) { return true; }
+ virtual bool FindVideoCodec(const VideoCodec& codec) { return true; }
+ virtual void SetVoiceLogging(int min_sev, const char* filter) {}
+ virtual void SetVideoLogging(int min_sev, const char* filter) {}
+
+ private:
+ std::string voice_input_filename_;
+ std::string voice_output_filename_;
+ std::string video_input_filename_;
+ std::string video_output_filename_;
+ std::vector<AudioCodec> voice_codecs_;
+ std::vector<VideoCodec> video_codecs_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileMediaEngine);
+};
+
+class RtpSenderReceiver; // Forward declaration. Defined in the .cc file.
+
+class FileVoiceChannel : public VoiceMediaChannel {
+ public:
+ FileVoiceChannel(const std::string& in_file, const std::string& out_file);
+ virtual ~FileVoiceChannel();
+
+ // Implement pure virtual methods of VoiceMediaChannel.
+ virtual bool SetRecvCodecs(const std::vector<AudioCodec>& codecs) {
+ return true;
+ }
+ virtual bool SetSendCodecs(const std::vector<AudioCodec>& codecs);
+ virtual bool SetPlayout(bool playout) { return true; }
+ virtual bool SetSend(SendFlags flag);
+ virtual bool AddStream(uint32 ssrc) { return true; }
+ virtual bool RemoveStream(uint32 ssrc) { return true; }
+ virtual bool GetActiveStreams(AudioInfo::StreamList* actives) { return true; }
+ virtual int GetOutputLevel() { return 0; }
+ virtual void SetRingbackTone(const char* buf, int len) {}
+ virtual bool PlayRingbackTone(bool play, bool loop) { return true; }
+ virtual bool PressDTMF(int event, bool playout) { return true; }
+ virtual bool GetStats(VoiceMediaInfo* info) { return true; }
+
+ // Implement pure virtual methods of MediaChannel.
+ virtual void OnPacketReceived(const void* data, int len);
+ virtual void OnRtcpReceived(const void* data, int len) {}
+ virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
+ virtual bool SetRtcpCName(const std::string& cname) { return true; }
+ virtual bool Mute(bool on) { return false; }
+ virtual bool SetMaxSendBandwidth(int max_bandwidth) { return true; }
+ virtual bool SetOptions(int options) { return true; }
+
+ private:
+ talk_base::scoped_ptr<RtpSenderReceiver> rtp_sender_receiver_;
+ DISALLOW_COPY_AND_ASSIGN(FileVoiceChannel);
+};
+
+class FileVideoChannel : public VideoMediaChannel {
+ public:
+ FileVideoChannel(const std::string& in_file, const std::string& out_file);
+ virtual ~FileVideoChannel();
+
+ // Implement pure virtual methods of VideoMediaChannel.
+ virtual bool SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
+ return true;
+ }
+ virtual bool SetSendCodecs(const std::vector<VideoCodec>& codecs);
+ virtual bool SetRender(bool render) { return true; }
+ virtual bool SetSend(bool send);
+ virtual bool AddStream(uint32 ssrc, uint32 voice_ssrc) { return true; }
+ virtual bool RemoveStream(uint32 ssrc) { return true; }
+ virtual bool SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
+ return true;
+ }
+ virtual bool GetStats(VoiceMediaInfo* info) { return true; }
+
+ // Implement pure virtual methods of MediaChannel.
+ virtual void OnPacketReceived(const void* data, int len);
+ virtual void OnRtcpReceived(const void* data, int len) {}
+ virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
+ virtual bool SetRtcpCName(const std::string& cname) { return true; }
+ virtual bool Mute(bool on) { return false; }
+ virtual bool SetMaxSendBandwidth(int max_bandwidth) { return true; }
+ virtual bool SetOptions(int options) { return true; }
+
+ private:
+ talk_base::scoped_ptr<RtpSenderReceiver> rtp_sender_receiver_;
+ DISALLOW_COPY_AND_ASSIGN(FileVideoChannel);
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_FILEMEDIAENGINE_H_
diff --git a/talk/session/phone/gipslitemediaengine.cc b/talk/session/phone/gipslitemediaengine.cc
deleted file mode 100755
index 87ff5c4..0000000
--- a/talk/session/phone/gipslitemediaengine.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-// GipsLiteMediaEngine is a GIPS Voice Engine Lite implementation of MediaEngine
-#include "talk/base/logging.h"
-#include <cassert>
-#include <iostream>
-#include "gipslitemediaengine.h"
-using namespace cricket;
-
-#if 0
-#define TRACK(x) LOG(LS_VERBOSE) << x
-#else
-#define TRACK(x)
-#endif
-
-//#define GIPS_TRACING
-
-namespace {
-struct CodecPref { const char* name; int clockrate; int pref; };
-const CodecPref kGIPSCodecPrefs[] = {
- { "ISAC", 1600, 7 },
- { "speex", 1600, 6 },
- { "IPCMWB", 1600, 6},
- { "speex", 8000, 4},
- { "iLBC", 8000, 1 },
- { "G723", 8000, 4 },
- { "EG711U", 8000, 3 },
- { "EG711A", 8000, 3 },
- { "PCMU", 8000, 2 },
- { "PCMA", 8000, 2 },
- { "CN", 8000, 2 },
- { "red", 8000, -1 },
- { "telephone-event", 8000, -1 }
-};
-const size_t kNumGIPSCodecs = sizeof(kGIPSCodecPrefs) / sizeof(CodecPref);
-}
-
-
-void GipsLiteMediaChannel::SetCodecs(const std::vector<Codec> &codecs) {
- GIPS_CodecInst c;
- std::vector<Codec>::const_iterator i;
-
-
- bool first = true;
- for (i = codecs.begin(); i < codecs.end(); i++) {
- if (engine_->FindGIPSCodec(*i, &c) == false)
- continue;
-
- if (c.pltype != i->id) {
- c.pltype = i->id;
- engine_->gips().GIPSVE_SetRecPayloadType(gips_channel_, &c);
- }
-
- if (first) {
- LOG(LS_INFO) << "Using " << c.plname << "/" << c.plfreq;
- engine_->gips().GIPSVE_SetSendCodec(gips_channel_, &c);
- first = false;
- }
- }
- if (first) {
- // We're being asked to set an empty list of codecs. This will only happen when
- // dealing with a buggy client. We'll send them the most common format: PCMU
- Codec codec(0, "PCMU", 8000, 0, 1, 0);
- LOG(LS_WARNING) << "Received empty list of codces; using PCMU/8000";
- engine_->FindGIPSCodec(codec, &c);
- engine_->gips().GIPSVE_SetSendCodec(gips_channel_, &c);
- }
-}
-
-
-void GipsLiteMediaChannel::OnPacketReceived(const void *data, int len) {
- engine_->gips().GIPSVE_ReceivedRTPPacket(gips_channel_, data, (int)len);
-}
-
-void GipsLiteMediaChannel::SetPlayout(bool playout) {
- if (playout)
- engine_->gips().GIPSVE_StartPlayout(gips_channel_);
- else
- engine_->gips().GIPSVE_StopPlayout(gips_channel_);
-}
-
-void GipsLiteMediaChannel::SetSend(bool send) {
- if (send)
- engine_->gips().GIPSVE_StartSend(gips_channel_);
- else
- engine_->gips().GIPSVE_StopSend(gips_channel_);
-}
-
-GipsLiteMediaChannel::GipsLiteMediaChannel(GipsLiteMediaEngine *engine) {
- network_interface_ = NULL;
- engine_ = engine;
- gips_channel_ = engine_->gips().GIPSVE_CreateChannel();
- engine_->gips().GIPSVE_SetSendTransport(gips_channel_, *this);
-}
-
-
-int GipsLiteMediaEngine::GetGIPSCodecPreference(const char *name, int clockrate) {
- for (size_t i = 0; i < kNumGIPSCodecs; ++i) {
- if ((strcmp(kGIPSCodecPrefs[i].name, name) == 0) &&
- (kGIPSCodecPrefs[i].clockrate == clockrate))
- return kGIPSCodecPrefs[i].pref;
- }
- assert(false);
- return -1;
-}
-
-GipsLiteMediaEngine::GipsLiteMediaEngine() :
- gips_(GetGipsVoiceEngineLite()) {}
-
-bool GipsLiteMediaEngine::Init() {
-
- TRACK("GIPSVE_Init");
- if (gips_.GIPSVE_Init() == -1)
- return false;
-
- char buffer[1024];
- TRACK("GIPSVE_GetVersion");
- int r = gips_.GIPSVE_GetVersion(buffer, sizeof(buffer));
- LOG(LS_INFO) << "GIPS Version: " << r << ": " << buffer;
-
- // Set auto gain control on
- TRACK("GIPSVE_SetAGCStatus");
- if (gips_.GIPSVE_SetAGCStatus(1) == -1)
- return false;
-
- TRACK("GIPSVE_GetNofCodecs");
- int ncodecs = gips_.GIPSVE_GetNofCodecs();
- for (int i = 0; i < ncodecs; ++i) {
- GIPS_CodecInst gips_codec;
- if (gips_.GIPSVE_GetCodec(i, &gips_codec) >= 0) {
- Codec codec(gips_codec.pltype, gips_codec.plname, gips_codec.plfreq, gips_codec.rate,
- gips_codec.channels, GetGIPSCodecPreference(gips_codec.plname, gips_codec.plfreq));
- LOG(LS_INFO) << gips_codec.plname << "/" << gips_codec.plfreq << "/" << gips_codec.channels << " " << gips_codec.pltype;
- codecs_.push_back(codec);
- }
- }
- return true;
-}
-
-void GipsLiteMediaEngine::Terminate() {
- gips_.GIPSVE_Terminate();
-}
-
-MediaChannel * GipsLiteMediaEngine::CreateChannel() {
- return new GipsLiteMediaChannel(this);
-}
-
-bool GipsLiteMediaEngine::FindGIPSCodec(Codec codec, GIPS_CodecInst* gips_codec) {
- int ncodecs = gips_.GIPSVE_GetNofCodecs();
- for (int i = 0; i < ncodecs; ++i) {
- GIPS_CodecInst gc;
- if (gips_.GIPSVE_GetCodec(i, &gc) >= 0) {
- if (codec.id < 96) {
- // Compare by id
- if (codec.id != gc.pltype)
- continue;
- } else {
- // Compare by name
- if (strcmp(codec.name.c_str(), gc.plname) != 0)
- continue;
- }
-
- // If the clockrate is specified, make sure it matches
- if (codec.clockrate > 0 && codec.clockrate != gc.plfreq)
- continue;
-
- // If the bitrate is specified, make sure it matches
- if (codec.bitrate > 0 && codec.bitrate != gc.rate)
- continue;
-
- // Make sure the channels match
- if (codec.channels != gc.channels)
- continue;
-
- // If we got this far, we match.
- if (gips_codec)
- *gips_codec = gc;
- return true;
- }
- }
- return false;
-}
-
-int GipsLiteMediaEngine::SetAudioOptions(int options) {
- // Set auto gain control on
- if (gips_.GIPSVE_SetAGCStatus(options & AUTO_GAIN_CONTROL ? 1 : 0) == -1) {
- return -1;
- // TODO: We need to log these failures.
- }
- return 0;
-}
-
-int GipsLiteMediaEngine::SetSoundDevices(int wave_in_device, int wave_out_device) {
- if (gips_.GIPSVE_SetSoundDevices(wave_in_device, wave_out_device) == -1) {
- int error = gips_.GIPSVE_GetLastError();
- // TODO: We need to log these failures.
- return error;
- }
- return 0;
-}
-
-bool GipsLiteMediaEngine::FindCodec(const Codec &codec)
-{
- return FindGIPSCodec(codec, NULL);
-}
-
-std::vector<Codec> GipsLiteMediaEngine::codecs()
-{
- return codecs_;
-}
\ No newline at end of file
diff --git a/talk/session/phone/gipslitemediaengine.h b/talk/session/phone/gipslitemediaengine.h
deleted file mode 100755
index ea144d8..0000000
--- a/talk/session/phone/gipslitemediaengine.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// GipsLiteMediaEngine is a GIPS Voice Engine Lite implementation of MediaEngine
-
-#ifndef TALK_SESSION_PHONE_GIPSLITEMEDIAENGINE_H_
-#define TALK_SESSION_PHONE_GIPSLITEMEDIAENGINE_H_
-
-#include "talk/third_party/gips/Interface/GipsVoiceEngineLite.h"
-#include "talk/third_party/gips/expiration.h"
-#include "talk/session/phone/mediaengine.h"
-
-namespace cricket {
-
-class GipsLiteMediaEngine : public MediaEngine {
- public:
- GipsLiteMediaEngine();
- ~GipsLiteMediaEngine() {}
- virtual bool Init();
- virtual void Terminate();
-
- virtual MediaChannel *CreateChannel();
-
- virtual int SetAudioOptions(int options);
- virtual int SetSoundDevices(int wave_in_device, int wave_out_device);
-
- virtual int GetInputLevel() {return gips_.GIPSVE_GetInputLevel();}
- virtual bool FindCodec(const Codec &codec);
- virtual std::vector<Codec> codecs();
- bool FindGIPSCodec(Codec codec, GIPS_CodecInst* gips_codec);
- GipsVoiceEngineLite &gips() {return gips_;};
-
- private:
- GipsVoiceEngineLite & gips_;
- int GetGIPSCodecPreference(const char *name, int clockrate);
- std::vector<Codec> codecs_;
-};
-
-class GipsLiteMediaChannel : public MediaChannel, public GIPS_transport {
- public:
- GipsLiteMediaChannel(GipsLiteMediaEngine *me);
- virtual ~GipsLiteMediaChannel() {
- StopMediaMonitor();
- engine_->gips().GIPSVE_DeleteChannel(gips_channel_);
- }
- virtual void SetCodecs(const std::vector<Codec> &codecs);
- virtual void OnPacketReceived(const void *data, int len);
-
- virtual void SetPlayout(bool playout);
- virtual void SetSend(bool send);
-
-
- virtual int GetOutputLevel() {return engine_->gips().GIPSVE_GetOutputLevel(gips_channel_);}
- GipsLiteMediaEngine *engine();
-
- virtual void StartMediaMonitor(VoiceChannel *voice_channel, uint32 cms) {}
- virtual void StopMediaMonitor() {}
-
- private:
- GipsLiteMediaEngine *engine_;
- int gips_channel_;
-
- virtual int SendPacket(int channel, const void *data, int len) {if (network_interface_) network_interface_->SendPacket(data, len); return 1;}
- virtual int SendRTCPPacket(int channel, const void *data, int len) {return 1;}
-};
-
-} // namespace cricket
-
-#endif // TALK_SESSION_PHONE_GIPSLITEMEDIAENGINE_H_
diff --git a/talk/session/phone/linphonemediaengine.cc b/talk/session/phone/linphonemediaengine.cc
deleted file mode 100755
index 8b285f6..0000000
--- a/talk/session/phone/linphonemediaengine.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Jingle call example
- * Copyright 2004--2005, Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// LinphoneMediaEngine is a Linphone implementation of MediaEngine
-extern "C" {
-#include "talk/third_party/mediastreamer/mediastream.h"
-#ifdef HAVE_ILBC
-#include "talk/third_party/mediastreamer/msilbcdec.h"
-#endif
-#ifdef HAVE_SPEEX
-#include "talk/third_party/mediastreamer/msspeexdec.h"
-#endif
-}
-#include <ortp/ortp.h>
-#include <ortp/telephonyevents.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <iostream>
-#include "talk/base/logging.h"
-#include "talk/base/thread.h"
-#include "talk/session/phone/codec.h"
-#include "talk/session/phone/linphonemediaengine.h"
-
-using namespace cricket;
-
-void LinphoneMediaChannel::OnIncomingData(talk_base::AsyncSocket *s)
-{
- char *buf[2048];
- int len;
- len = s->Recv(buf, sizeof(buf));
- if (network_interface_ && !mute_)
- network_interface_->SendPacket(buf, len);
-}
-
-LinphoneMediaChannel::LinphoneMediaChannel(LinphoneMediaEngine*eng) :
- pt_(-1),
- audio_stream_(0),
- engine_(eng) {
-
- talk_base::Thread *thread = talk_base::ThreadManager::CurrentThread();
- talk_base::SocketServer *ss = thread->socketserver();
- socket_.reset(ss->CreateAsyncSocket(SOCK_DGRAM));
-
- socket_->Bind(talk_base::SocketAddress("localhost",3000));
- socket_->SignalReadEvent.connect(this, &LinphoneMediaChannel::OnIncomingData);
-}
-
-LinphoneMediaChannel::~LinphoneMediaChannel() {
- audio_stream_stop(audio_stream_);
-}
-
-void LinphoneMediaChannel::SetCodecs(const std::vector<Codec> &codecs) {
- bool first = true;
- std::vector<Codec>::const_iterator i;
-
- for (i = codecs.begin(); i < codecs.end(); i++) {
-
- if (!engine_->FindCodec(*i))
- continue;
-#ifdef HAVE_ILBC
- if (i->name == payload_type_ilbc.mime_type) {
- rtp_profile_set_payload(&av_profile, i->id, &payload_type_ilbc);
- }
-#endif
-#ifdef HAVE_SPEEX
- if (i->name == speex_wb.mime_type && i->clockrate == speex_wb.clock_rate) {
- rtp_profile_set_payload(&av_profile, i->id, &speex_wb);
- } else if (i->name == speex_nb.mime_type && i->clockrate == speex_nb.clock_rate) {
- rtp_profile_set_payload(&av_profile, i->id, &speex_nb);
- }
-#endif
-
- if (i->id == 0)
- rtp_profile_set_payload(&av_profile, 0, &pcmu8000);
-
- if (i->name == telephone_event.mime_type) {
- rtp_profile_set_payload(&av_profile, i->id, &telephone_event);
- }
-
- if (first) {
- LOG(LS_INFO) << "Using " << i->name << "/" << i->clockrate;
- pt_ = i->id;
- audio_stream_ = audio_stream_start(&av_profile, 2000, "127.0.0.1", 3000, i->id, 250);
- first = false;
- }
- }
-
- if (first) {
- // We're being asked to set an empty list of codecs. This will only happen when
- // working with a buggy client; let's try PCMU.
- LOG(LS_WARNING) << "Received empty list of codces; using PCMU/8000";
- audio_stream_ = audio_stream_start(&av_profile, 2000, "127.0.0.1", 3000, 0, 250);
- }
-
-}
-
-bool LinphoneMediaEngine::FindCodec(const Codec &c) {
- if (c.id == 0)
- return true;
- if (c.name == telephone_event.mime_type)
- return true;
-#ifdef HAVE_SPEEX
- if (c.name == speex_wb.mime_type && c.clockrate == speex_wb.clock_rate)
- return true;
- if (c.name == speex_nb.mime_type && c.clockrate == speex_nb.clock_rate)
- return true;
-#endif
-#ifdef HAVE_ILBC
- if (c.name == payload_type_ilbc.mime_type)
- return true;
-#endif
-return false;
-}
-
-void LinphoneMediaChannel::OnPacketReceived(const void *data, int len) {
- uint8 buf[2048];
- memcpy(buf, data, len);
-
- /* We may receive packets with payload type 13: comfort noise. Linphone can't
- * handle them, so let's ignore those packets.
- */
- int payloadtype = buf[1] & 0x7f;
- if (play_ && payloadtype != 13)
- socket_->SendTo(buf, len, talk_base::SocketAddress("localhost",2000));
-}
-
-void LinphoneMediaChannel::SetPlayout(bool playout) {
- play_ = playout;
-}
-
-void LinphoneMediaChannel::SetSend(bool send) {
- mute_ = !send;
-}
-
-int LinphoneMediaChannel::GetOutputLevel() {}
-
-LinphoneMediaEngine::LinphoneMediaEngine() {}
-LinphoneMediaEngine::~LinphoneMediaEngine() {}
-
-static void null_log_handler(const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer user_data) {
- LOG(LS_INFO) << log_domain << " " << message;
-}
-
-bool LinphoneMediaEngine::Init() {
- g_log_set_handler("MediaStreamer", G_LOG_LEVEL_MASK, null_log_handler, this);
- g_log_set_handler("oRTP", G_LOG_LEVEL_MASK, null_log_handler, this);
- g_log_set_handler("oRTP-stats", G_LOG_LEVEL_MASK, null_log_handler, this);
- ortp_init();
- ms_init();
-
-#ifdef HAVE_SPEEX
- ms_speex_codec_init();
-
- codecs_.push_back(Codec(110, speex_wb.mime_type, speex_wb.clock_rate, 0, 1, 8));
- codecs_.push_back(Codec(111, speex_nb.mime_type, speex_nb.clock_rate, 0, 1, 7));
-
-#endif
-
-#ifdef HAVE_ILBC
- ms_ilbc_codec_init();
- codecs_.push_back(Codec(102, payload_type_ilbc.mime_type, payload_type_ilbc.clock_rate, 0, 1, 4));
-#endif
-
- codecs_.push_back(Codec(0, pcmu8000.mime_type, pcmu8000.clock_rate, 0, 1, 2));
- codecs_.push_back(Codec(101, telephone_event.mime_type, telephone_event.clock_rate, 0, 1, 1));
- return true;
-}
-
-void LinphoneMediaEngine::Terminate() {
-
-}
-
-MediaChannel *LinphoneMediaEngine::CreateChannel() {
- return new LinphoneMediaChannel(this);
-}
-
-int LinphoneMediaEngine::SetAudioOptions(int options) {}
-int LinphoneMediaEngine::SetSoundDevices(int wave_in_device, int wave_out_device) {}
-
-float LinphoneMediaEngine::GetCurrentQuality() {}
-int LinphoneMediaEngine::GetInputLevel() {}
diff --git a/talk/session/phone/linphonemediaengine.h b/talk/session/phone/linphonemediaengine.h
deleted file mode 100755
index 5a12693..0000000
--- a/talk/session/phone/linphonemediaengine.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Jingle call example
- * Copyright 2004--2005, Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// LinphoneMediaEngine is a Linphone implementation of MediaEngine
-
-#ifndef TALK_SESSION_PHONE_LINPHONEMEDIAENGINE_H_
-#define TALK_SESSION_PHONE_LINPHONEMEDIAENGINE_H_
-
-extern "C" {
-#include "talk/third_party/mediastreamer/mediastream.h"
-}
-#include "talk/base/asyncsocket.h"
-#include "talk/base/scoped_ptr.h"
-#include "talk/session/phone/mediaengine.h"
-
-namespace cricket {
-
-class LinphoneMediaEngine;
-
-class LinphoneMediaChannel : public MediaChannel {
- public:
- LinphoneMediaChannel(LinphoneMediaEngine *eng);
- virtual ~LinphoneMediaChannel();
-
- virtual void SetCodecs(const std::vector<Codec> &codecs);
- virtual void OnPacketReceived(const void *data, int len);
-
- virtual void SetPlayout(bool playout);
- virtual void SetSend(bool send);
-
-
- virtual int GetOutputLevel();
- bool mute() {return mute_;}
-
- virtual void StartMediaMonitor(VoiceChannel * voice_channel, uint32 cms) {}
- virtual void StopMediaMonitor() {}
-
- private:
- LinphoneMediaEngine *engine_;
- AudioStream *audio_stream_;
- talk_base::scoped_ptr<talk_base::AsyncSocket> socket_;
- void OnIncomingData(talk_base::AsyncSocket *s);
- int pt_;
- bool mute_;
- bool play_;
-};
-
-class LinphoneMediaEngine : public MediaEngine {
- public:
- LinphoneMediaEngine();
- ~LinphoneMediaEngine();
- virtual bool Init();
- virtual void Terminate();
-
- virtual MediaChannel *CreateChannel();
-
- virtual int SetAudioOptions(int options);
- virtual int SetSoundDevices(int wave_in_device, int wave_out_device);
-
- virtual float GetCurrentQuality();
- virtual int GetInputLevel();
-
- virtual std::vector<Codec, std::allocator<Codec> > codecs() {return codecs_;}
- virtual bool FindCodec(const Codec&);
-
- private:
- std::vector<Codec, std::allocator<Codec> > codecs_;
-};
-
-} // namespace cricket
-
-#endif // TALK_SESSION_PHONE_LINPHONEMEDIAENGINE_H_
diff --git a/talk/session/phone/mediachannel.h b/talk/session/phone/mediachannel.h
old mode 100755
new mode 100644
index 65463a5..ee9d3c7
--- a/talk/session/phone/mediachannel.h
+++ b/talk/session/phone/mediachannel.h
@@ -1,78 +1,341 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2007, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_SESSION_PHONE_MEDIACHANNEL_H_
#define TALK_SESSION_PHONE_MEDIACHANNEL_H_
+#include <string>
+#include <vector>
+
#include "talk/base/basictypes.h"
#include "talk/base/sigslot.h"
+#include "talk/base/socket.h"
#include "talk/session/phone/codec.h"
+// TODO: re-evaluate this include
+#include "talk/session/phone/audiomonitor.h"
+
+namespace flute {
+ class MagicCamVideoRenderer;
+}
namespace cricket {
-class VoiceChannel;
-
-struct MediaInfo {
- unsigned short fraction_lost;
- unsigned long cum_lost;
- unsigned long ext_max;
- unsigned long jitter;
- int RTT;
- int bytesSent;
- int packetsSent;
- int bytesReceived;
- int packetsReceived;
+enum VoiceMediaChannelOptions {
+ OPT_CONFERENCE = 0x10000, // tune the audio stream for conference mode
+ OPT_ENERGYLEVEL = 0x20000, // include the energy level in RTP packets, as
+ // defined in https://datatracker.ietf.org/drafts/
+ // draft-lennox-avt-rtp-audio-level-exthdr/
+
+};
+
+enum VideoMediaChannelOptions {
};
class MediaChannel : public sigslot::has_slots<> {
public:
class NetworkInterface {
- public:
- virtual void SendPacket(const void *data, size_t len) = 0;
+ public:
+ enum SocketType { ST_RTP, ST_RTCP };
+ virtual int SendPacket(const void *data, size_t len) = 0;
+ virtual int SendRtcp(const void *data, size_t len) = 0;
+ virtual int SetOption(SocketType type, talk_base::Socket::Option opt,
+ int option) = 0;
+ virtual ~NetworkInterface() {}
};
- MediaChannel() {network_interface_ = NULL;}
- virtual ~MediaChannel() {};
- void SetInterface(NetworkInterface *iface) {network_interface_ = iface;}
- virtual void SetCodecs(const std::vector<Codec> &codecs) = 0;
+
+ MediaChannel() : network_interface_(NULL) {}
+ virtual ~MediaChannel() {}
+
+ // Gets/sets the abstract inteface class for sending RTP/RTCP data.
+ NetworkInterface *network_interface() { return network_interface_; }
+ virtual void SetInterface(NetworkInterface *iface) {
+ network_interface_ = iface;
+ }
+
+ // Called when a RTP packet is received.
virtual void OnPacketReceived(const void *data, int len) = 0;
- virtual void SetPlayout(bool playout) = 0;
- virtual void SetSend(bool send) = 0;
- virtual int GetOutputLevel() = 0;
+ // Called when a RTCP packet is received.
+ virtual void OnRtcpReceived(const void *data, int len) = 0;
+ // Sets the SSRC to be used for outgoing data.
+ virtual void SetSendSsrc(uint32 id) = 0;
+ // Set the CNAME of RTCP
+ virtual bool SetRtcpCName(const std::string& cname) = 0;
+ // Mutes the channel.
+ virtual bool Mute(bool on) = 0;
- virtual void StartMediaMonitor(VoiceChannel * voice_channel, uint32 cms) = 0;
- virtual void StopMediaMonitor() = 0;
- sigslot::signal2<MediaChannel *, const MediaInfo &> SignalMediaMonitor;
+ virtual bool SetRtpExtensionHeaders(bool enable_all) { return true; }
+ virtual bool SetMaxSendBandwidth(int max_bandwidth) = 0;
+ virtual bool SetOptions(int options) = 0;
-
- NetworkInterface *network_interface() {return network_interface_;}
protected:
NetworkInterface *network_interface_;
};
-}; // namespace cricket
+enum SendFlags {
+ SEND_NOTHING,
+ SEND_RINGBACKTONE,
+ SEND_MICROPHONE
+};
+
+// TODO: separate into VoiceMediaInfo and VideoMediaInfo
+struct MediaInfo {
+ int fraction_lost;
+ int cum_lost;
+ int ext_max;
+ int jitter;
+ int RTT;
+ int bytesSent;
+ int packetsSent;
+ int bytesReceived;
+ int packetsReceived;
+};
+
+typedef MediaInfo VoiceMediaInfo;
+typedef MediaInfo VideoMediaInfo;
+
+class VoiceMediaChannel : public MediaChannel {
+ public:
+ VoiceMediaChannel() {}
+ virtual ~VoiceMediaChannel() {}
+ // Sets the codecs/payload types to be used for incoming media.
+ virtual bool SetRecvCodecs(const std::vector<AudioCodec>& codecs) = 0;
+ // Sets the codecs/payload types to be used for outgoing media.
+ virtual bool SetSendCodecs(const std::vector<AudioCodec>& codecs) = 0;
+ // Starts or stops playout of received audio.
+ virtual bool SetPlayout(bool playout) = 0;
+ // Starts or stops sending (and potentially capture) of local audio.
+ virtual bool SetSend(SendFlags flag) = 0;
+ // Adds a new receive-only stream with the specified SSRC.
+ virtual bool AddStream(uint32 ssrc) = 0;
+ // Removes a stream added with AddStream.
+ virtual bool RemoveStream(uint32 ssrc) = 0;
+ // Gets current energy levels for all incoming streams.
+ virtual bool GetActiveStreams(AudioInfo::StreamList* actives) = 0;
+ // Get the current energy level for the outgoing stream.
+ virtual int GetOutputLevel() = 0;
+ // Specifies a ringback tone to be played during call setup.
+ virtual void SetRingbackTone(const char *buf, int len) = 0;
+ // Plays or stops the aforementioned ringback tone
+ virtual bool PlayRingbackTone(bool play, bool loop) = 0;
+ // Sends a out-of-band DTMF signal using the specified event.
+ virtual bool PressDTMF(int event, bool playout) = 0;
+ // Gets quality stats for the channel.
+ virtual bool GetStats(VoiceMediaInfo* info) = 0;
+};
+
+// Represents a YUV420 (a.k.a. I420) video frame.
+class VideoFrame {
+ friend class flute::MagicCamVideoRenderer;
+
+ public:
+ VideoFrame() : rendered_(false) {}
+
+ virtual ~VideoFrame() {}
+
+ virtual size_t GetWidth() const = 0;
+ virtual size_t GetHeight() const = 0;
+ virtual const uint8 *GetYPlane() const = 0;
+ virtual const uint8 *GetUPlane() const = 0;
+ virtual const uint8 *GetVPlane() const = 0;
+ virtual uint8 *GetYPlane() = 0;
+ virtual uint8 *GetUPlane() = 0;
+ virtual uint8 *GetVPlane() = 0;
+ virtual int32 GetYPitch() const = 0;
+ virtual int32 GetUPitch() const = 0;
+ virtual int32 GetVPitch() const = 0;
+
+ // For retrieving the aspect ratio of each pixel. Usually this is 1x1, but
+ // the aspect_ratio_idc parameter of H.264 can specify non-square pixels.
+ virtual size_t GetPixelWidth() const = 0;
+ virtual size_t GetPixelHeight() const = 0;
+
+ // TODO: Add a fourcc format here and probably combine VideoFrame
+ // with CapturedFrame.
+ virtual int64 GetElapsedTime() const = 0;
+ virtual int64 GetTimeStamp() const = 0;
+ virtual void SetElapsedTime(int64 elapsed_time) = 0;
+ virtual void SetTimeStamp(int64 time_stamp) = 0;
+
+ // Writes the frame into the given frame buffer, provided that it is of
+ // sufficient size. Returns the frame's actual size, regardless of whether
+ // it was written or not (like snprintf). If there is insufficient space,
+ // nothing is written.
+ virtual size_t CopyToBuffer(uint8 *buffer, size_t size) const = 0;
+
+ // Converts the I420 data to RGB of a certain type such as BGRA and RGBA.
+ // Returns the frame's actual size, regardless of whether it was written or
+ // not (like snprintf). Parameters size and pitch_rgb are in units of bytes.
+ // If there is insufficient space, nothing is written.
+ virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, uint8 *buffer,
+ size_t size, size_t pitch_rgb) const = 0;
+
+ // Writes the frame into the given planes, stretched to the given width and
+ // height. The parameter "interpolate" controls whether to interpolate or just
+ // take the nearest-point. The parameter "crop" controls whether to crop this
+ // frame to the aspect ratio of the given dimensions before stretching.
+ virtual void StretchToPlanes(uint8 *y, uint8 *u, uint8 *v,
+ int32 pitchY, int32 pitchU, int32 pitchV,
+ size_t width, size_t height,
+ bool interpolate, bool crop) const = 0;
+
+ // Writes the frame into the given frame buffer, stretched to the given width
+ // and height, provided that it is of sufficient size. Returns the frame's
+ // actual size, regardless of whether it was written or not (like snprintf).
+ // If there is insufficient space, nothing is written. The parameter
+ // "interpolate" controls whether to interpolate or just take the
+ // nearest-point. The parameter "crop" controls whether to crop this frame to
+ // the aspect ratio of the given dimensions before stretching.
+ virtual size_t StretchToBuffer(size_t w, size_t h, uint8 *buffer, size_t size,
+ bool interpolate, bool crop) const = 0;
+
+ // Writes the frame into the target VideoFrame, stretched to the size of that
+ // frame. The parameter "interpolate" controls whether to interpolate or just
+ // take the nearest-point. The parameter "crop" controls whether to crop this
+ // frame to the aspect ratio of the target frame before stretching.
+ virtual void StretchToFrame(VideoFrame *target, bool interpolate,
+ bool crop) const = 0;
+
+ // Stretches the frame to the given size, creating a new VideoFrame object to
+ // hold it. The parameter "interpolate" controls whether to interpolate or
+ // just take the nearest-point. The parameter "crop" controls whether to crop
+ // this frame to the aspect ratio of the given dimensions before stretching.
+ virtual VideoFrame *Stretch(size_t w, size_t h, bool interpolate,
+ bool crop) const = 0;
+
+ // Size of an I420 image of given dimensions when stored as a frame buffer.
+ static size_t SizeOf(size_t w, size_t h) {
+ return w * h * 3 / 2;
+ }
+
+ protected:
+ // The frame needs to be rendered to magiccam only once.
+ // TODO: Remove this flag once magiccam rendering is fully replaced
+ // by client3d rendering.
+ mutable bool rendered_;
+};
+
+// Simple subclass for use in mocks.
+class NullVideoFrame : public VideoFrame {
+ public:
+ virtual size_t GetWidth() const { return 0; }
+ virtual size_t GetHeight() const { return 0; }
+ virtual const uint8 *GetYPlane() const { return NULL; }
+ virtual const uint8 *GetUPlane() const { return NULL; }
+ virtual const uint8 *GetVPlane() const { return NULL; }
+ virtual uint8 *GetYPlane() { return NULL; }
+ virtual uint8 *GetUPlane() { return NULL; }
+ virtual uint8 *GetVPlane() { return NULL; }
+ virtual int32 GetYPitch() const { return 0; }
+ virtual int32 GetUPitch() const { return 0; }
+ virtual int32 GetVPitch() const { return 0; }
+
+ virtual size_t GetPixelWidth() const { return 1; }
+ virtual size_t GetPixelHeight() const { return 1; }
+ virtual int64 GetElapsedTime() const { return 0; }
+ virtual int64 GetTimeStamp() const { return 0; }
+ virtual void SetElapsedTime(int64 elapsed_time) {}
+ virtual void SetTimeStamp(int64 time_stamp) {}
+
+ virtual size_t CopyToBuffer(uint8 *buffer, size_t size) const {
+ return 0;
+ }
+
+ virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, uint8 *buffer,
+ size_t size, size_t pitch_rgb) const {
+ return 0;
+ }
+
+ virtual void StretchToPlanes(uint8 *y, uint8 *u, uint8 *v,
+ int32 pitchY, int32 pitchU, int32 pitchV,
+ size_t width, size_t height,
+ bool interpolate, bool crop) const {
+ }
+
+ virtual size_t StretchToBuffer(size_t w, size_t h, uint8 *buffer, size_t size,
+ bool interpolate, bool crop) const {
+ return 0;
+ }
+
+ virtual void StretchToFrame(VideoFrame *target, bool interpolate,
+ bool crop) const {
+ }
+
+ virtual VideoFrame *Stretch(size_t w, size_t h, bool interpolate,
+ bool crop) const {
+ return NULL;
+ }
+};
+
+// Abstract interface for rendering VideoFrames.
+class VideoRenderer {
+ public:
+ virtual ~VideoRenderer() {}
+ // Called when the video has changed size.
+ virtual bool SetSize(int width, int height, int reserved) = 0;
+ // Called when a new frame is available for display.
+ virtual bool RenderFrame(const VideoFrame *frame) = 0;
+};
+
+// Simple implementation for use in tests.
+class NullVideoRenderer : public VideoRenderer {
+ virtual bool SetSize(int width, int height, int reserved) {
+ return true;
+ }
+ // Called when a new frame is available for display.
+ virtual bool RenderFrame(const VideoFrame *frame) {
+ return true;
+ }
+};
+
+class VideoMediaChannel : public MediaChannel {
+ public:
+ VideoMediaChannel() { renderer_ = NULL; }
+ virtual ~VideoMediaChannel() {}
+ // Sets the codecs/payload types to be used for incoming media.
+ virtual bool SetRecvCodecs(const std::vector<VideoCodec> &codecs) = 0;
+ // Sets the codecs/payload types to be used for outgoing media.
+ virtual bool SetSendCodecs(const std::vector<VideoCodec> &codecs) = 0;
+ // Starts or stops playout of received video.
+ virtual bool SetRender(bool render) = 0;
+ // Starts or stops transmission (and potentially capture) of local video.
+ virtual bool SetSend(bool send) = 0;
+ // Adds a new receive-only stream with the specified SSRC.
+ virtual bool AddStream(uint32 ssrc, uint32 voice_ssrc) = 0;
+ // Removes a stream added with AddStream.
+ virtual bool RemoveStream(uint32 ssrc) = 0;
+ // Sets the renderer object to be used for the specified stream.
+ // If SSRC is 0, the renderer is used for the 'default' stream.
+ virtual bool SetRenderer(uint32 ssrc, VideoRenderer* renderer) = 0;
+ // Gets quality stats for the channel.
+ virtual bool GetStats(VideoMediaInfo* info) = 0;
+ protected:
+ VideoRenderer *renderer_;
+};
+
+} // namespace cricket
#endif // TALK_SESSION_PHONE_MEDIACHANNEL_H_
diff --git a/talk/session/phone/mediaengine.cc b/talk/session/phone/mediaengine.cc
new file mode 100644
index 0000000..66eb18e
--- /dev/null
+++ b/talk/session/phone/mediaengine.cc
@@ -0,0 +1,44 @@
+//
+// libjingle
+// Copyright 2004--2007, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "talk/session/phone/mediaengine.h"
+
+
+namespace cricket {
+
+// TODO: according to thaloun, HAVE_GIPSVIDEO will always
+// be false, so we can get rid of it.
+
+MediaEngine* MediaEngine::Create(
+#ifdef USE_TALK_SOUND
+ SoundSystemFactory *factory
+#endif
+ ) {
+ return new NullMediaEngine();
+}
+
+}; // namespace cricket
diff --git a/talk/session/phone/mediaengine.h b/talk/session/phone/mediaengine.h
old mode 100755
new mode 100644
index e8081db..c42e8ef
--- a/talk/session/phone/mediaengine.h
+++ b/talk/session/phone/mediaengine.h
@@ -1,69 +1,315 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2007, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// MediaEngine is an abstraction of a media engine which can be subclassed
-// to support different media componentry backends.
-
#ifndef TALK_SESSION_PHONE_MEDIAENGINE_H_
#define TALK_SESSION_PHONE_MEDIAENGINE_H_
-#include <string>
+#ifdef OSX
+#include <CoreAudio/CoreAudio.h>
+#endif
+
+#include <string>
#include <vector>
+#include "talk/base/sigslotrepeater.h"
#include "talk/session/phone/codec.h"
+#include "talk/session/phone/devicemanager.h"
#include "talk/session/phone/mediachannel.h"
+#ifdef USE_TALK_SOUND
+#include "talk/sound/soundsystemfactory.h"
+#endif
+#include "talk/session/phone/videocommon.h"
namespace cricket {
-class MediaEngine {
- public:
-
- MediaEngine() {}
-
- // Bitmask flags for options that may be supported by the media engine implementation
- enum MediaEngineOptions {
- AUTO_GAIN_CONTROL = 1 << 1,
+// A class for playing out soundclips.
+class SoundclipMedia {
+ public:
+ enum SoundclipFlags {
+ SF_LOOP = 1,
};
- // Initialize
+ virtual ~SoundclipMedia() {}
+
+ // Plays a sound out to the speakers with the given audio stream. The stream
+ // must be 16-bit little-endian 16 kHz PCM. If a stream is already playing
+ // on this SoundclipMedia, it is stopped. If clip is NULL, nothing is played.
+ // Returns whether it was successful.
+ virtual bool PlaySound(const char *clip, int len, int flags) = 0;
+};
+
+// MediaEngine is an abstraction of a media engine which can be subclassed
+// to support different media componentry backends. It supports voice and
+// video operations in the same class to facilitate proper synchronization
+// between both media types.
+class MediaEngine {
+ public:
+ // TODO: Move this to a global location (also used in DeviceManager)
+ // Capabilities of the media engine.
+ enum Capabilities {
+ AUDIO_RECV = 1 << 0,
+ AUDIO_SEND = 1 << 1,
+ VIDEO_RECV = 1 << 2,
+ VIDEO_SEND = 1 << 3,
+ };
+
+ // Bitmask flags for options that may be supported by the media engine
+ // implementation
+ enum AudioOptions {
+ ECHO_CANCELLATION = 1 << 0,
+ AUTO_GAIN_CONTROL = 1 << 1,
+ DEFAULT_AUDIO_OPTIONS = ECHO_CANCELLATION | AUTO_GAIN_CONTROL
+ };
+ enum VideoOptions {
+ };
+
+ virtual ~MediaEngine() {}
+ static MediaEngine* Create(
+#ifdef USE_TALK_SOUND
+ SoundSystemFactory *factory
+#endif
+ );
+
+ // Initialization
+ // Starts the engine.
virtual bool Init() = 0;
+ // Shuts down the engine.
virtual void Terminate() = 0;
- virtual MediaChannel *CreateChannel() = 0;
+ // Returns what the engine is capable of, as a set of Capabilities, above.
+ virtual int GetCapabilities() = 0;
- virtual int SetAudioOptions(int options) = 0;
- virtual int SetSoundDevices(int wave_in_device, int wave_out_device) = 0;
+ // MediaChannel creation
+ // Creates a voice media channel. Returns NULL on failure.
+ virtual VoiceMediaChannel *CreateChannel() = 0;
+ // Creates a video media channel, paired with the specified voice channel.
+ // Returns NULL on failure.
+ virtual VideoMediaChannel *CreateVideoChannel(
+ VoiceMediaChannel* voice_media_channel) = 0;
+
+ // Creates a soundclip object for playing sounds on. Returns NULL on failure.
+ virtual SoundclipMedia *CreateSoundclip() = 0;
+
+ // Configuration
+ // Sets global audio options. "options" are from AudioOptions, above.
+ virtual bool SetAudioOptions(int options) = 0;
+ // Sets global video options. "options" are from VideoOptions, above.
+ virtual bool SetVideoOptions(int options) = 0;
+ // Sets the default (maximum) codec/resolution and encoder option to capture
+ // and encode video.
+ virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config)
+ = 0;
+
+ // Device selection
+ // TODO: Add method for selecting the soundclip device.
+ virtual bool SetSoundDevices(const Device* in_device,
+ const Device* out_device) = 0;
+ virtual bool SetVideoCaptureDevice(const Device* cam_device) = 0;
+
+ // Device configuration
+ // Sets the current speaker volume, as a value between 0 and 255.
+ virtual bool SetOutputVolume(int level) = 0;
+
+ // Local monitoring
+ // Gets the current microphone level, as a value between 0 and 10.
virtual int GetInputLevel() = 0;
+ // Starts or stops the local microphone. Useful if local mic info is needed
+ // prior to a call being connected; the mic will be started automatically
+ // when a VoiceMediaChannel starts sending.
+ virtual bool SetLocalMonitor(bool enable) = 0;
+ // Installs a callback for raw frames from the local camera.
+ virtual bool SetLocalRenderer(VideoRenderer* renderer) = 0;
+ // Starts/stops local camera.
+ virtual CaptureResult SetVideoCapture(bool capture) = 0;
- virtual std::vector<Codec> codecs() = 0;
+ virtual const std::vector<AudioCodec>& audio_codecs() = 0;
+ virtual const std::vector<VideoCodec>& video_codecs() = 0;
+ virtual bool FindAudioCodec(const AudioCodec &codec) = 0;
+ virtual bool FindVideoCodec(const VideoCodec &codec) = 0;
- virtual bool FindCodec(const Codec &codec) = 0;
-
- int GetCodecPreference (Codec codec);
-};
+ // Logging control
+ virtual void SetVoiceLogging(int min_sev, const char* filter) = 0;
+ virtual void SetVideoLogging(int min_sev, const char* filter) = 0;
+
+ sigslot::repeater1<bool> SignalVideoCaptureResult;
+};
+
+// CompositeMediaEngine constructs a MediaEngine from separate
+// voice and video engine classes.
+template<class VOICE, class VIDEO>
+class CompositeMediaEngine : public MediaEngine {
+ public:
+#ifdef USE_TALK_SOUND
+ explicit CompositeMediaEngine(SoundSystemFactory *factory)
+ : voice_(factory) {
+ }
+#endif
+ CompositeMediaEngine() {}
+ virtual bool Init() {
+ if (!voice_.Init())
+ return false;
+ if (!video_.Init()) {
+ voice_.Terminate();
+ return false;
+ }
+ SignalVideoCaptureResult.repeat(video_.SignalCaptureResult);
+ return true;
+ }
+ virtual void Terminate() {
+ video_.Terminate();
+ voice_.Terminate();
+ }
+
+ virtual int GetCapabilities() {
+ return (voice_.GetCapabilities() | video_.GetCapabilities());
+ }
+ virtual VoiceMediaChannel *CreateChannel() {
+ return voice_.CreateChannel();
+ }
+ virtual VideoMediaChannel *CreateVideoChannel(VoiceMediaChannel* channel) {
+ return video_.CreateChannel(channel);
+ }
+ virtual SoundclipMedia *CreateSoundclip() {
+ return voice_.CreateSoundclip();
+ }
+
+ virtual bool SetAudioOptions(int o) {
+ return voice_.SetOptions(o);
+ }
+ virtual bool SetVideoOptions(int o) {
+ return video_.SetOptions(o);
+ }
+ virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) {
+ return video_.SetDefaultEncoderConfig(config);
+ }
+
+ virtual bool SetSoundDevices(const Device* in_device,
+ const Device* out_device) {
+ return voice_.SetDevices(in_device, out_device);
+ }
+ virtual bool SetVideoCaptureDevice(const Device* cam_device) {
+ return video_.SetCaptureDevice(cam_device);
+ }
+
+ virtual bool SetOutputVolume(int level) {
+ return voice_.SetOutputVolume(level);
+ }
+
+ virtual int GetInputLevel() {
+ return voice_.GetInputLevel();
+ }
+ virtual bool SetLocalMonitor(bool enable) {
+ return voice_.SetLocalMonitor(enable);
+ }
+ virtual bool SetLocalRenderer(VideoRenderer* renderer) {
+ return video_.SetLocalRenderer(renderer);
+ }
+ virtual CaptureResult SetVideoCapture(bool capture) {
+ return video_.SetCapture(capture);
+ }
+
+ virtual const std::vector<AudioCodec>& audio_codecs() {
+ return voice_.codecs();
+ }
+ virtual const std::vector<VideoCodec>& video_codecs() {
+ return video_.codecs();
+ }
+
+ virtual bool FindAudioCodec(const AudioCodec &codec) {
+ return voice_.FindCodec(codec);
+ }
+ virtual bool FindVideoCodec(const VideoCodec &codec) {
+ return video_.FindCodec(codec);
+ }
+
+ virtual void SetVoiceLogging(int min_sev, const char* filter) {
+ return voice_.SetLogging(min_sev, filter);
+ }
+ virtual void SetVideoLogging(int min_sev, const char* filter) {
+ return video_.SetLogging(min_sev, filter);
+ }
+
+ private:
+ VOICE voice_;
+ VIDEO video_;
+};
+
+// NullVoiceEngine can be used with CompositeMediaEngine in the case where only
+// a video engine is desired.
+class NullVoiceEngine {
+ public:
+ bool Init() { return true; }
+ void Terminate() {}
+ int GetCapabilities() { return 0; }
+ VoiceMediaChannel* CreateChannel() {
+ return NULL;
+ }
+ SoundclipMedia* CreateSoundclip() {
+ return NULL;
+ }
+ bool SetOptions(int opts) { return true; }
+ bool SetDevices(const Device* in_device, const Device* out_device) {
+ return true;
+ }
+ bool SetOutputVolume(int level) { return true; }
+ int GetInputLevel() { return 0; }
+ bool SetLocalMonitor(bool enable) { return true; }
+ const std::vector<AudioCodec>& codecs() { return codecs_; }
+ bool FindCodec(const AudioCodec&) { return false; }
+ void SetLogging(int min_sev, const char* filter) {}
+ private:
+ std::vector<AudioCodec> codecs_;
+};
+
+// NullVideoEngine can be used with CompositeMediaEngine in the case where only
+// a voice engine is desired.
+class NullVideoEngine {
+ public:
+ bool Init() { return true; }
+ void Terminate() {}
+ int GetCapabilities() { return 0; }
+ VideoMediaChannel* CreateChannel(VoiceMediaChannel* voice_media_channel) {
+ return NULL;
+ }
+ bool SetOptions(int opts) { return true; }
+ bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) {
+ return true;
+ }
+ bool SetCaptureDevice(const Device* cam_device) { return true; }
+ bool SetLocalRenderer(VideoRenderer* renderer) { return true; }
+ CaptureResult SetCapture(bool capture) { return CR_SUCCESS; }
+ const std::vector<VideoCodec>& codecs() { return codecs_; }
+ bool FindCodec(const VideoCodec&) { return false; }
+ void SetLogging(int min_sev, const char* filter) {}
+ sigslot::signal1<bool> SignalCaptureResult;
+ private:
+ std::vector<VideoCodec> codecs_;
+};
+
+typedef CompositeMediaEngine<NullVoiceEngine, NullVideoEngine> NullMediaEngine;
} // namespace cricket
diff --git a/talk/session/phone/mediamonitor.cc b/talk/session/phone/mediamonitor.cc
new file mode 100644
index 0000000..909b536
--- /dev/null
+++ b/talk/session/phone/mediamonitor.cc
@@ -0,0 +1,109 @@
+/*
+ * libjingle
+ * Copyright 2005--2007, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/common.h"
+#include "talk/session/phone/mediamonitor.h"
+#include "talk/session/phone/channelmanager.h"
+#include "talk/session/phone/mediaengine.h"
+
+namespace cricket {
+
+enum {
+ MSG_MONITOR_POLL = 1,
+ MSG_MONITOR_START = 2,
+ MSG_MONITOR_STOP = 3,
+ MSG_MONITOR_SIGNAL = 4
+};
+
+MediaMonitor::MediaMonitor(talk_base::Thread* worker_thread,
+ talk_base::Thread* monitor_thread)
+ : worker_thread_(worker_thread),
+ monitor_thread_(monitor_thread), monitoring_(false), rate_(0) {
+}
+
+MediaMonitor::~MediaMonitor() {
+ monitoring_ = false;
+ monitor_thread_->Clear(this);
+ worker_thread_->Clear(this);
+}
+
+void MediaMonitor::Start(uint32 milliseconds) {
+ rate_ = milliseconds;
+ if (rate_ < 100)
+ rate_ = 100;
+ worker_thread_->Post(this, MSG_MONITOR_START);
+}
+
+void MediaMonitor::Stop() {
+ worker_thread_->Post(this, MSG_MONITOR_STOP);
+ rate_ = 0;
+}
+
+void MediaMonitor::OnMessage(talk_base::Message* message) {
+ talk_base::CritScope cs(&crit_);
+
+ switch (message->message_id) {
+ case MSG_MONITOR_START:
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+ if (!monitoring_) {
+ monitoring_ = true;
+ PollMediaChannel();
+ }
+ break;
+
+ case MSG_MONITOR_STOP:
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+ if (monitoring_) {
+ monitoring_ = false;
+ worker_thread_->Clear(this);
+ }
+ break;
+
+ case MSG_MONITOR_POLL:
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+ PollMediaChannel();
+ break;
+
+ case MSG_MONITOR_SIGNAL:
+ ASSERT(talk_base::Thread::Current() == monitor_thread_);
+ Update();
+ break;
+ }
+}
+
+void MediaMonitor::PollMediaChannel() {
+ talk_base::CritScope cs(&crit_);
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+
+ GetStats();
+
+ // Signal the monitoring thread, start another poll timer
+ monitor_thread_->Post(this, MSG_MONITOR_SIGNAL);
+ worker_thread_->PostDelayed(rate_, this, MSG_MONITOR_POLL);
+}
+
+}
diff --git a/talk/session/phone/mediamonitor.h b/talk/session/phone/mediamonitor.h
new file mode 100644
index 0000000..9eda2aa
--- /dev/null
+++ b/talk/session/phone/mediamonitor.h
@@ -0,0 +1,100 @@
+/*
+ * libjingle
+ * Copyright 2005--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Class to collect statistics from a media channel
+
+#ifndef TALK_SESSION_PHONE_MEDIAMONITOR_H_
+#define TALK_SESSION_PHONE_MEDIAMONITOR_H_
+
+#include "talk/base/thread.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/criticalsection.h"
+#include "talk/session/phone/mediachannel.h"
+
+namespace cricket {
+
+// The base MediaMonitor class, independent of voice and video.
+class MediaMonitor : public talk_base::MessageHandler,
+ public sigslot::has_slots<> {
+ public:
+ MediaMonitor(talk_base::Thread* worker_thread,
+ talk_base::Thread* monitor_thread);
+ ~MediaMonitor();
+
+ void Start(uint32 milliseconds);
+ void Stop();
+
+ protected:
+ void OnMessage(talk_base::Message *message);
+ void PollMediaChannel();
+ virtual void GetStats() = 0;
+ virtual void Update() = 0;
+
+ talk_base::CriticalSection crit_;
+ talk_base::Thread* worker_thread_;
+ talk_base::Thread* monitor_thread_;
+ bool monitoring_;
+ uint32 rate_;
+};
+
+// Templatized MediaMonitor that can deal with different kinds of media.
+template<class MC, class MI>
+class MediaMonitorT : public MediaMonitor {
+ public:
+ MediaMonitorT(MC* media_channel, talk_base::Thread* worker_thread,
+ talk_base::Thread* monitor_thread)
+ : MediaMonitor(worker_thread, monitor_thread),
+ media_channel_(media_channel) {}
+ sigslot::signal2<MC*, const MI&> SignalUpdate;
+
+ protected:
+ // These routines assume the crit_ lock is held by the calling thread.
+ virtual void GetStats() {
+ media_info_.packetsReceived = -1;
+ if (!media_channel_->GetStats(&media_info_)) {
+ media_info_.packetsReceived = -1;
+ }
+ }
+ virtual void Update() {
+ MI stats(media_info_);
+ crit_.Leave();
+ SignalUpdate(media_channel_, stats);
+ crit_.Enter();
+ }
+
+ private:
+ MC* media_channel_;
+ MI media_info_;
+};
+
+typedef MediaMonitorT<VoiceMediaChannel, VoiceMediaInfo> VoiceMediaMonitor;
+typedef MediaMonitorT<VideoMediaChannel, VideoMediaInfo> VideoMediaMonitor;
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_MEDIAMONITOR_H_
+
diff --git a/talk/session/phone/mediasessionclient.cc b/talk/session/phone/mediasessionclient.cc
new file mode 100644
index 0000000..001cf73
--- /dev/null
+++ b/talk/session/phone/mediasessionclient.cc
@@ -0,0 +1,691 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/phone/mediasessionclient.h"
+
+#include "talk/base/logging.h"
+#include "talk/base/stringutils.h"
+#include "talk/p2p/base/constants.h"
+#include "talk/p2p/base/parsing.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmllite/qname.h"
+
+using namespace talk_base;
+
+namespace cricket {
+
+MediaSessionClient::MediaSessionClient(
+ const buzz::Jid& jid, SessionManager *manager)
+ : jid_(jid), session_manager_(manager), focus_call_(NULL),
+ channel_manager_(new ChannelManager(session_manager_->worker_thread())) {
+ Construct();
+}
+
+MediaSessionClient::MediaSessionClient(
+ const buzz::Jid& jid, SessionManager *manager,
+ MediaEngine* media_engine, DeviceManager* device_manager)
+ : jid_(jid), session_manager_(manager), focus_call_(NULL),
+ channel_manager_(new ChannelManager(
+ media_engine, device_manager, session_manager_->worker_thread())) {
+ Construct();
+}
+
+
+void MediaSessionClient::Construct() {
+ // Register ourselves as the handler of phone and video sessions.
+ session_manager_->AddClient(NS_JINGLE_RTP, this);
+ // Forward device notifications.
+ SignalDevicesChange.repeat(channel_manager_->SignalDevicesChange);
+ // Bring up the channel manager.
+ // In previous versions of ChannelManager, this was done automatically
+ // in the constructor.
+ channel_manager_->Init();
+}
+
+MediaSessionClient::~MediaSessionClient() {
+ // Destroy all calls
+ std::map<uint32, Call *>::iterator it;
+ while (calls_.begin() != calls_.end()) {
+ std::map<uint32, Call *>::iterator it = calls_.begin();
+ DestroyCall((*it).second);
+ }
+
+ // Delete channel manager. This will wait for the channels to exit
+ delete channel_manager_;
+
+ // Remove ourselves from the client map.
+ session_manager_->RemoveClient(NS_JINGLE_RTP);
+}
+
+SessionDescription* MediaSessionClient::CreateOffer(bool video, bool set_ssrc) {
+ SessionDescription* offer = new SessionDescription();
+ AudioContentDescription* audio = new AudioContentDescription();
+
+
+ AudioCodecs audio_codecs;
+ channel_manager_->GetSupportedAudioCodecs(&audio_codecs);
+ for (AudioCodecs::const_iterator codec = audio_codecs.begin();
+ codec != audio_codecs.end(); ++codec) {
+ audio->AddCodec(*codec);
+ }
+ if (set_ssrc) {
+ audio->set_ssrc(0);
+ }
+ audio->SortCodecs();
+ offer->AddContent(CN_AUDIO, NS_JINGLE_RTP, audio);
+
+ // add video codecs, if this is a video call
+ if (video) {
+ VideoContentDescription* video = new VideoContentDescription();
+ VideoCodecs video_codecs;
+ channel_manager_->GetSupportedVideoCodecs(&video_codecs);
+ for (VideoCodecs::const_iterator codec = video_codecs.begin();
+ codec != video_codecs.end(); ++codec) {
+ video->AddCodec(*codec);
+ }
+ if (set_ssrc) {
+ video->set_ssrc(0);
+ }
+ video->SortCodecs();
+ offer->AddContent(CN_VIDEO, NS_JINGLE_RTP, video);
+ }
+
+ return offer;
+}
+
+const ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc,
+ MediaType media_type) {
+ if (sdesc == NULL)
+ return NULL;
+
+ const ContentInfos& contents = sdesc->contents();
+ for (ContentInfos::const_iterator content = contents.begin();
+ content != contents.end(); content++) {
+ if (content->type == NS_JINGLE_RTP) {
+ const MediaContentDescription* media =
+ static_cast<const MediaContentDescription*>(content->description);
+ if (media->type() == media_type) {
+ return &*content;
+ }
+ }
+ }
+ return NULL;
+}
+
+const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc) {
+ return GetFirstMediaContent(sdesc, MEDIA_TYPE_AUDIO);
+}
+
+const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc) {
+ return GetFirstMediaContent(sdesc, MEDIA_TYPE_VIDEO);
+}
+
+SessionDescription* MediaSessionClient::CreateAnswer(
+ const SessionDescription* offer) {
+ // The answer contains the intersection of the codecs in the offer with the
+ // codecs we support, ordered by our local preference. As indicated by
+ // XEP-0167, we retain the same payload ids from the offer in the answer.
+ SessionDescription* accept = new SessionDescription();
+
+ const ContentInfo* audio_content = GetFirstAudioContent(offer);
+ if (audio_content) {
+ const AudioContentDescription* audio_offer =
+ static_cast<const AudioContentDescription*>(audio_content->description);
+ AudioContentDescription* audio_accept = new AudioContentDescription();
+ AudioCodecs audio_codecs;
+ channel_manager_->GetSupportedAudioCodecs(&audio_codecs);
+ for (AudioCodecs::const_iterator ours = audio_codecs.begin();
+ ours != audio_codecs.end(); ++ours) {
+ for (AudioCodecs::const_iterator theirs = audio_offer->codecs().begin();
+ theirs != audio_offer->codecs().end(); ++theirs) {
+ if (ours->Matches(*theirs)) {
+ AudioCodec negotiated(*ours);
+ negotiated.id = theirs->id;
+ audio_accept->AddCodec(negotiated);
+ }
+ }
+ }
+
+ audio_accept->SortCodecs();
+ accept->AddContent(audio_content->name, audio_content->type, audio_accept);
+ }
+
+ const ContentInfo* video_content = GetFirstVideoContent(offer);
+ if (video_content) {
+ const VideoContentDescription* video_offer =
+ static_cast<const VideoContentDescription*>(video_content->description);
+ VideoContentDescription* video_accept = new VideoContentDescription();
+ VideoCodecs video_codecs;
+ channel_manager_->GetSupportedVideoCodecs(&video_codecs);
+ for (VideoCodecs::const_iterator ours = video_codecs.begin();
+ ours != video_codecs.end(); ++ours) {
+ for (VideoCodecs::const_iterator theirs = video_offer->codecs().begin();
+ theirs != video_offer->codecs().end(); ++theirs) {
+ if (ours->Matches(*theirs)) {
+ VideoCodec negotiated(*ours);
+ negotiated.id = theirs->id;
+ video_accept->AddCodec(negotiated);
+ }
+ }
+ }
+
+ video_accept->SortCodecs();
+ accept->AddContent(video_content->name, video_content->type, video_accept);
+ }
+
+ return accept;
+}
+
+Call *MediaSessionClient::CreateCall(bool video, bool mux) {
+ Call *call = new Call(this, video, mux);
+ calls_[call->id()] = call;
+ SignalCallCreate(call);
+ return call;
+}
+
+void MediaSessionClient::OnSessionCreate(Session *session,
+ bool received_initiate) {
+ if (received_initiate) {
+ session->SignalState.connect(this, &MediaSessionClient::OnSessionState);
+ }
+}
+
+void MediaSessionClient::OnSessionState(BaseSession* base_session,
+ BaseSession::State state) {
+ // MediaSessionClient can only be used with a Session*, so it's
+ // safe to cast here.
+ Session* session = static_cast<Session*>(base_session);
+
+ if (state == Session::STATE_RECEIVEDINITIATE) {
+ // The creation of the call must happen after the session has
+ // processed the initiate message because we need the
+ // remote_description to know what content names to use in the
+ // call.
+
+ // If our accept would have no codecs, then we must reject this call.
+ const SessionDescription* offer = session->remote_description();
+ const SessionDescription* accept = CreateAnswer(offer);
+ const ContentInfo* audio_content = GetFirstAudioContent(accept);
+ const ContentInfo* video_content = GetFirstVideoContent(accept);
+ const AudioContentDescription* audio_accept = (!audio_content) ? NULL :
+ static_cast<const AudioContentDescription*>(audio_content->description);
+
+ // For some reason, we need to create the call even when we
+ // reject.
+ Call *call = CreateCall(video_content != NULL);
+ session_map_[session->id()] = call;
+ call->IncomingSession(session, offer);
+
+ if (!audio_accept || audio_accept->codecs().size() == 0) {
+ session->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
+ }
+ delete accept;
+ }
+}
+
+void MediaSessionClient::DestroyCall(Call *call) {
+ // Change focus away, signal destruction
+
+ if (call == focus_call_)
+ SetFocus(NULL);
+ SignalCallDestroy(call);
+
+ // Remove it from calls_ map and delete
+
+ std::map<uint32, Call *>::iterator it = calls_.find(call->id());
+ if (it != calls_.end())
+ calls_.erase(it);
+
+ delete call;
+}
+
+void MediaSessionClient::OnSessionDestroy(Session *session) {
+ // Find the call this session is in, remove it
+
+ std::map<std::string, Call *>::iterator it = session_map_.find(session->id());
+ ASSERT(it != session_map_.end());
+ if (it != session_map_.end()) {
+ Call *call = (*it).second;
+ session_map_.erase(it);
+ call->RemoveSession(session);
+ }
+}
+
+Call *MediaSessionClient::GetFocus() {
+ return focus_call_;
+}
+
+void MediaSessionClient::SetFocus(Call *call) {
+ Call *old_focus_call = focus_call_;
+ if (focus_call_ != call) {
+ if (focus_call_ != NULL)
+ focus_call_->EnableChannels(false);
+ focus_call_ = call;
+ if (focus_call_ != NULL)
+ focus_call_->EnableChannels(true);
+ SignalFocus(focus_call_, old_focus_call);
+ }
+}
+
+void MediaSessionClient::JoinCalls(Call *call_to_join, Call *call) {
+ // Move all sessions from call to call_to_join, delete call.
+ // If call_to_join has focus, added sessions should have enabled channels.
+
+ if (focus_call_ == call)
+ SetFocus(NULL);
+ call_to_join->Join(call, focus_call_ == call_to_join);
+ DestroyCall(call);
+}
+
+Session *MediaSessionClient::CreateSession(Call *call) {
+ const std::string& type = NS_JINGLE_RTP;
+ Session *session = session_manager_->CreateSession(jid().Str(), type);
+ session_map_[session->id()] = call;
+ return session;
+}
+
+bool ParseGingleAudioCodec(const buzz::XmlElement* element, AudioCodec* out) {
+ int id = GetXmlAttr(element, QN_ID, -1);
+ if (id < 0)
+ return false;
+
+ std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY);
+ int clockrate = GetXmlAttr(element, QN_CLOCKRATE, 0);
+ int bitrate = GetXmlAttr(element, QN_BITRATE, 0);
+ int channels = GetXmlAttr(element, QN_CHANNELS, 1);
+ *out = AudioCodec(id, name, clockrate, bitrate, channels, 0);
+ return true;
+}
+
+bool ParseGingleVideoCodec(const buzz::XmlElement* element, VideoCodec* out) {
+ int id = GetXmlAttr(element, QN_ID, -1);
+ if (id < 0)
+ return false;
+
+ std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY);
+ int width = GetXmlAttr(element, QN_WIDTH, 0);
+ int height = GetXmlAttr(element, QN_HEIGHT, 0);
+ int framerate = GetXmlAttr(element, QN_FRAMERATE, 0);
+
+ *out = VideoCodec(id, name, width, height, framerate, 0);
+ return true;
+}
+
+void ParseGingleSsrc(const buzz::XmlElement* parent_elem,
+ const buzz::QName& name,
+ MediaContentDescription* content) {
+ const buzz::XmlElement* ssrc_elem = parent_elem->FirstNamed(name);
+ if (ssrc_elem) {
+ content->set_ssrc(strtoul(ssrc_elem->BodyText().c_str(), NULL, 10));
+ }
+}
+
+bool ParseGingleAudioContent(const buzz::XmlElement* content_elem,
+ const ContentDescription** content,
+ ParseError* error) {
+ AudioContentDescription* audio = new AudioContentDescription();
+
+ if (content_elem->FirstElement()) {
+ for (const buzz::XmlElement* codec_elem =
+ content_elem->FirstNamed(QN_GINGLE_AUDIO_PAYLOADTYPE);
+ codec_elem != NULL;
+ codec_elem = codec_elem->NextNamed(QN_GINGLE_AUDIO_PAYLOADTYPE)) {
+ AudioCodec codec;
+ if (ParseGingleAudioCodec(codec_elem, &codec)) {
+ audio->AddCodec(codec);
+ }
+ }
+ } else {
+ // For backward compatibility, we can assume the other client is
+ // an old version of Talk if it has no audio payload types at all.
+ audio->AddCodec(AudioCodec(103, "ISAC", 16000, -1, 1, 1));
+ audio->AddCodec(AudioCodec(0, "PCMU", 8000, 64000, 1, 0));
+ }
+
+ ParseGingleSsrc(content_elem, QN_GINGLE_VIDEO_SRCID, audio);
+
+ *content = audio;
+ return true;
+}
+
+
+bool ParseGingleVideoContent(const buzz::XmlElement* content_elem,
+ const ContentDescription** content,
+ ParseError* error) {
+ VideoContentDescription* video = new VideoContentDescription();
+
+ for (const buzz::XmlElement* codec_elem =
+ content_elem->FirstNamed(QN_GINGLE_VIDEO_PAYLOADTYPE);
+ codec_elem != NULL;
+ codec_elem = codec_elem->NextNamed(QN_GINGLE_VIDEO_PAYLOADTYPE)) {
+ VideoCodec codec;
+ if (ParseGingleVideoCodec(codec_elem, &codec)) {
+ video->AddCodec(codec);
+ }
+ }
+
+ ParseGingleSsrc(content_elem, QN_GINGLE_VIDEO_SRCID, video);
+
+ *content = video;
+ return true;
+}
+
+void ParsePayloadTypeParameters(const buzz::XmlElement* element,
+ std::map<std::string, std::string>* paramap) {
+ for (const buzz::XmlElement* param = element->FirstNamed(QN_PARAMETER);
+ param != NULL; param = param->NextNamed(QN_PARAMETER)) {
+ std::string name = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_NAME, "");
+ std::string value = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_VALUE, "");
+ if (!name.empty() && !value.empty()) {
+ paramap->insert(make_pair(name, value));
+ }
+ }
+}
+
+int FindWithDefault(const std::map<std::string, std::string>& map,
+ const std::string& key, const int def) {
+ std::map<std::string, std::string>::const_iterator iter = map.find(key);
+ return (iter == map.end()) ? def : atoi(iter->second.c_str());
+}
+
+bool ParseJingleAudioCodec(const buzz::XmlElement* elem, AudioCodec* codec) {
+ int id = GetXmlAttr(elem, QN_ID, -1);
+ if (id < 0)
+ return false;
+
+ std::string name = GetXmlAttr(elem, QN_NAME, "");
+ int clockrate = GetXmlAttr(elem, QN_CLOCKRATE, 0);
+ int channels = GetXmlAttr(elem, QN_CHANNELS, 1);
+
+ std::map<std::string, std::string> paramap;
+ ParsePayloadTypeParameters(elem, ¶map);
+ int bitrate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_BITRATE, 0);
+
+ *codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
+ return true;
+}
+
+bool ParseJingleVideoCodec(const buzz::XmlElement* elem, VideoCodec* codec) {
+ int id = GetXmlAttr(elem, QN_ID, -1);
+ if (id < 0)
+ return false;
+
+ std::string name = GetXmlAttr(elem, QN_NAME, "");
+
+ std::map<std::string, std::string> paramap;
+ ParsePayloadTypeParameters(elem, ¶map);
+ int width = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_WIDTH, 0);
+ int height = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_HEIGHT, 0);
+ int framerate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_FRAMERATE, 0);
+
+ *codec = VideoCodec(id, name, width, height, framerate, 0);
+ return true;
+}
+
+bool ParseJingleAudioContent(const buzz::XmlElement* content_elem,
+ const ContentDescription** content,
+ ParseError* error) {
+ AudioContentDescription* audio = new AudioContentDescription();
+
+ for (const buzz::XmlElement* payload_elem =
+ content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE);
+ payload_elem != NULL;
+ payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) {
+ AudioCodec codec;
+ if (ParseJingleAudioCodec(payload_elem, &codec)) {
+ audio->AddCodec(codec);
+ }
+ }
+
+ // TODO: Figure out how to integrate SSRC into Jingle.
+ *content = audio;
+ return true;
+}
+
+bool ParseJingleVideoContent(const buzz::XmlElement* content_elem,
+ const ContentDescription** content,
+ ParseError* error) {
+ VideoContentDescription* video = new VideoContentDescription();
+
+ for (const buzz::XmlElement* payload_elem =
+ content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE);
+ payload_elem != NULL;
+ payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) {
+ VideoCodec codec;
+ if (ParseJingleVideoCodec(payload_elem, &codec)) {
+ video->AddCodec(codec);
+ }
+ }
+
+ // TODO: Figure out how to integrate SSRC into Jingle.
+ *content = video;
+ return true;
+}
+
+bool MediaSessionClient::ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* content_elem,
+ const ContentDescription** content,
+ ParseError* error) {
+ if (protocol == PROTOCOL_GINGLE) {
+ const std::string& content_type = content_elem->Name().Namespace();
+ if (NS_GINGLE_AUDIO == content_type) {
+ return ParseGingleAudioContent(content_elem, content, error);
+ } else if (NS_GINGLE_VIDEO == content_type) {
+ return ParseGingleVideoContent(content_elem, content, error);
+ } else {
+ return BadParse("Unknown content type: " + content_type, error);
+ }
+ } else {
+ std::string media;
+ if (!RequireXmlAttr(content_elem, QN_JINGLE_CONTENT_MEDIA, &media, error))
+ return false;
+
+ if (media == JINGLE_CONTENT_MEDIA_AUDIO) {
+ return ParseJingleAudioContent(content_elem, content, error);
+ } else if (media == JINGLE_CONTENT_MEDIA_VIDEO) {
+ return ParseJingleVideoContent(content_elem, content, error);
+ } else {
+ return BadParse("Unknown media: " + media, error);
+ }
+ }
+}
+
+buzz::XmlElement* CreateGingleAudioCodecElem(const AudioCodec& codec) {
+ buzz::XmlElement* payload_type =
+ new buzz::XmlElement(QN_GINGLE_AUDIO_PAYLOADTYPE, true);
+ AddXmlAttr(payload_type, QN_ID, codec.id);
+ payload_type->AddAttr(QN_NAME, codec.name);
+ if (codec.clockrate > 0)
+ AddXmlAttr(payload_type, QN_CLOCKRATE, codec.clockrate);
+ if (codec.bitrate > 0)
+ AddXmlAttr(payload_type, QN_BITRATE, codec.bitrate);
+ if (codec.channels > 1)
+ AddXmlAttr(payload_type, QN_CHANNELS, codec.channels);
+ return payload_type;
+}
+
+buzz::XmlElement* CreateGingleVideoCodecElem(const VideoCodec& codec) {
+ buzz::XmlElement* payload_type =
+ new buzz::XmlElement(QN_GINGLE_VIDEO_PAYLOADTYPE, true);
+ AddXmlAttr(payload_type, QN_ID, codec.id);
+ payload_type->AddAttr(QN_NAME, codec.name);
+ AddXmlAttr(payload_type, QN_WIDTH, codec.width);
+ AddXmlAttr(payload_type, QN_HEIGHT, codec.height);
+ AddXmlAttr(payload_type, QN_FRAMERATE, codec.framerate);
+ return payload_type;
+}
+
+buzz::XmlElement* CreateGingleSsrcElem(const buzz::QName& name, uint32 ssrc) {
+ buzz::XmlElement* elem = new buzz::XmlElement(name, true);
+ if (ssrc) {
+ SetXmlBody(elem, ssrc);
+ }
+ return elem;
+}
+
+buzz::XmlElement* CreateGingleAudioContentElem(
+ const AudioContentDescription* audio) {
+ buzz::XmlElement* elem =
+ new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT, true);
+
+ for (AudioCodecs::const_iterator codec = audio->codecs().begin();
+ codec != audio->codecs().end(); ++codec) {
+ elem->AddElement(CreateGingleAudioCodecElem(*codec));
+ }
+ if (audio->ssrc_set()) {
+ elem->AddElement(CreateGingleSsrcElem(
+ QN_GINGLE_AUDIO_SRCID, audio->ssrc()));
+ }
+
+
+ return elem;
+}
+
+buzz::XmlElement* CreateGingleVideoContentElem(
+ const VideoContentDescription* video) {
+ buzz::XmlElement* elem =
+ new buzz::XmlElement(QN_GINGLE_VIDEO_CONTENT, true);
+
+ for (VideoCodecs::const_iterator codec = video->codecs().begin();
+ codec != video->codecs().end(); ++codec) {
+ elem->AddElement(CreateGingleVideoCodecElem(*codec));
+ }
+ if (video->ssrc_set()) {
+ elem->AddElement(CreateGingleSsrcElem(
+ QN_GINGLE_VIDEO_SRCID, video->ssrc()));
+ }
+
+ return elem;
+}
+
+buzz::XmlElement* CreatePayloadTypeParameterElem(
+ const std::string& name, int value) {
+ buzz::XmlElement* elem = new buzz::XmlElement(QN_PARAMETER);
+
+ elem->AddAttr(QN_PAYLOADTYPE_PARAMETER_NAME, name);
+ AddXmlAttr(elem, QN_PAYLOADTYPE_PARAMETER_VALUE, value);
+
+ return elem;
+}
+
+buzz::XmlElement* CreateJingleAudioCodecElem(const AudioCodec& codec) {
+ buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE);
+
+ AddXmlAttr(elem, QN_ID, codec.id);
+ elem->AddAttr(QN_NAME, codec.name);
+ if (codec.clockrate > 0) {
+ AddXmlAttr(elem, QN_CLOCKRATE, codec.clockrate);
+ }
+ if (codec.bitrate > 0) {
+ elem->AddElement(CreatePayloadTypeParameterElem(
+ PAYLOADTYPE_PARAMETER_BITRATE, codec.bitrate));
+ }
+ if (codec.channels > 1) {
+ AddXmlAttr(elem, QN_CHANNELS, codec.channels);
+ }
+
+ return elem;
+}
+
+buzz::XmlElement* CreateJingleVideoCodecElem(const VideoCodec& codec) {
+ buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE);
+
+ AddXmlAttr(elem, QN_ID, codec.id);
+ elem->AddAttr(QN_NAME, codec.name);
+ elem->AddElement(CreatePayloadTypeParameterElem(
+ PAYLOADTYPE_PARAMETER_WIDTH, codec.width));
+ elem->AddElement(CreatePayloadTypeParameterElem(
+ PAYLOADTYPE_PARAMETER_HEIGHT, codec.height));
+ elem->AddElement(CreatePayloadTypeParameterElem(
+ PAYLOADTYPE_PARAMETER_FRAMERATE, codec.framerate));
+
+ return elem;
+}
+
+buzz::XmlElement* CreateJingleAudioContentElem(
+ const AudioContentDescription* audio) {
+ buzz::XmlElement* elem =
+ new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true);
+
+ elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_AUDIO);
+
+ for (AudioCodecs::const_iterator codec = audio->codecs().begin();
+ codec != audio->codecs().end(); ++codec) {
+ elem->AddElement(CreateJingleAudioCodecElem(*codec));
+ }
+
+ // TODO: Figure out how to integrate SSRC into Jingle.
+ return elem;
+}
+
+buzz::XmlElement* CreateJingleVideoContentElem(
+ const VideoContentDescription* video) {
+ buzz::XmlElement* elem =
+ new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true);
+
+ elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_VIDEO);
+
+ for (VideoCodecs::const_iterator codec = video->codecs().begin();
+ codec != video->codecs().end(); ++codec) {
+ elem->AddElement(CreateJingleVideoCodecElem(*codec));
+ }
+
+ // TODO: Figure out how to integrate SSRC into Jingle.
+ return elem;
+}
+
+bool MediaSessionClient::WriteContent(SignalingProtocol protocol,
+ const ContentDescription* content,
+ buzz::XmlElement** elem,
+ WriteError* error) {
+ const MediaContentDescription* media =
+ static_cast<const MediaContentDescription*>(content);
+
+ if (media->type() == MEDIA_TYPE_AUDIO) {
+ const AudioContentDescription* audio =
+ static_cast<const AudioContentDescription*>(media);
+ if (protocol == PROTOCOL_GINGLE) {
+ *elem = CreateGingleAudioContentElem(audio);
+ } else {
+ *elem = CreateJingleAudioContentElem(audio);
+ }
+ } else if (media->type() == MEDIA_TYPE_VIDEO) {
+ const VideoContentDescription* video =
+ static_cast<const VideoContentDescription*>(media);
+ if (protocol == PROTOCOL_GINGLE) {
+ *elem = CreateGingleVideoContentElem(video);
+ } else {
+ *elem = CreateJingleVideoContentElem(video);
+ }
+ } else {
+ return BadWrite("Unknown content type: " + media->type(), error);
+ }
+
+ return true;
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/mediasessionclient.h b/talk/session/phone/mediasessionclient.h
new file mode 100644
index 0000000..533341b
--- /dev/null
+++ b/talk/session/phone/mediasessionclient.h
@@ -0,0 +1,218 @@
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_SESSION_PHONE_MEDIASESSIONCLIENT_H_
+#define TALK_SESSION_PHONE_MEDIASESSIONCLIENT_H_
+
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include "talk/session/phone/call.h"
+#include "talk/session/phone/channelmanager.h"
+#include "talk/session/phone/cryptoparams.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/sigslotrepeater.h"
+#include "talk/base/messagequeue.h"
+#include "talk/base/thread.h"
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/base/session.h"
+#include "talk/p2p/base/sessionclient.h"
+#include "talk/p2p/base/sessiondescription.h"
+
+namespace cricket {
+
+class Call;
+class SessionDescription;
+typedef std::vector<AudioCodec> AudioCodecs;
+typedef std::vector<VideoCodec> VideoCodecs;
+
+class MediaSessionClient: public SessionClient, public sigslot::has_slots<> {
+ public:
+ MediaSessionClient(const buzz::Jid& jid, SessionManager *manager);
+ // Alternative constructor, allowing injection of media_engine
+ // and device_manager.
+ MediaSessionClient(const buzz::Jid& jid, SessionManager *manager,
+ MediaEngine* media_engine, DeviceManager* device_manager);
+ ~MediaSessionClient();
+
+ const buzz::Jid &jid() const { return jid_; }
+ SessionManager* session_manager() const { return session_manager_; }
+ ChannelManager* channel_manager() const { return channel_manager_; }
+
+ int GetCapabilities() { return channel_manager_->GetCapabilities(); }
+
+ Call *CreateCall(bool video = false, bool mux = false);
+ void DestroyCall(Call *call);
+
+ Call *GetFocus();
+ void SetFocus(Call *call);
+
+ void JoinCalls(Call *call_to_join, Call *call);
+
+ bool GetAudioInputDevices(std::vector<std::string>* names) {
+ return channel_manager_->GetAudioInputDevices(names);
+ }
+ bool GetAudioOutputDevices(std::vector<std::string>* names) {
+ return channel_manager_->GetAudioOutputDevices(names);
+ }
+ bool GetVideoCaptureDevices(std::vector<std::string>* names) {
+ return channel_manager_->GetVideoCaptureDevices(names);
+ }
+
+ bool SetAudioOptions(const std::string& in_name, const std::string& out_name,
+ int opts) {
+ return channel_manager_->SetAudioOptions(in_name, out_name, opts);
+ }
+ bool SetOutputVolume(int level) {
+ return channel_manager_->SetOutputVolume(level);
+ }
+ bool SetVideoOptions(const std::string& cam_device) {
+ return channel_manager_->SetVideoOptions(cam_device);
+ }
+
+ sigslot::signal2<Call *, Call *> SignalFocus;
+ sigslot::signal1<Call *> SignalCallCreate;
+ sigslot::signal1<Call *> SignalCallDestroy;
+ sigslot::repeater0<> SignalDevicesChange;
+
+ SessionDescription* CreateOffer(bool video = false, bool set_ssrc = false);
+ SessionDescription* CreateAnswer(const SessionDescription* offer);
+
+ private:
+ void Construct();
+ void OnSessionCreate(Session *session, bool received_initiate);
+ void OnSessionState(BaseSession *session, BaseSession::State state);
+ void OnSessionDestroy(Session *session);
+ virtual bool ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ const ContentDescription** content,
+ ParseError* error);
+ virtual bool WriteContent(SignalingProtocol protocol,
+ const ContentDescription* content,
+ buzz::XmlElement** elem,
+ WriteError* error);
+ Session *CreateSession(Call *call);
+
+ buzz::Jid jid_;
+ SessionManager* session_manager_;
+ Call *focus_call_;
+ ChannelManager *channel_manager_;
+ std::map<uint32, Call *> calls_;
+ std::map<std::string, Call *> session_map_;
+
+ friend class Call;
+};
+
+enum MediaType {
+ MEDIA_TYPE_AUDIO,
+ MEDIA_TYPE_VIDEO
+};
+
+class MediaContentDescription : public ContentDescription {
+ public:
+ MediaContentDescription() : ssrc_(0), ssrc_set_(false), rtcp_mux_(false),
+ rtp_headers_disabled_(false) {}
+
+ virtual MediaType type() const = 0;
+
+ uint32 ssrc() const { return ssrc_; }
+ bool ssrc_set() const { return ssrc_set_; }
+ void set_ssrc(uint32 ssrc) {
+ ssrc_ = ssrc;
+ ssrc_set_ = true;
+ }
+
+ bool rtcp_mux() const { return rtcp_mux_; }
+ void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
+
+ bool rtp_headers_disabled() const {
+ return rtp_headers_disabled_;
+ }
+ void set_rtp_headers_disabled(bool disable) {
+ rtp_headers_disabled_ = disable;
+ }
+
+ const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
+ void AddCrypto(const CryptoParams& params) {
+ cryptos_.push_back(params);
+ }
+
+ uint32 ssrc_;
+ bool ssrc_set_;
+ bool rtcp_mux_;
+ bool rtp_headers_disabled_;
+ std::vector<CryptoParams> cryptos_;
+};
+
+template <class C>
+class MediaContentDescriptionImpl : public MediaContentDescription {
+ public:
+ struct PreferenceSort {
+ bool operator()(C a, C b) { return a.preference > b.preference; }
+ };
+
+ const std::vector<C>& codecs() const { return codecs_; }
+ void AddCodec(const C& codec) {
+ codecs_.push_back(codec);
+ }
+ void SortCodecs() {
+ std::sort(codecs_.begin(), codecs_.end(), PreferenceSort());
+ }
+
+ private:
+ std::vector<C> codecs_;
+};
+
+class AudioContentDescription : public MediaContentDescriptionImpl<AudioCodec> {
+ public:
+ AudioContentDescription()
+ {}
+
+ virtual MediaType type() const { return MEDIA_TYPE_AUDIO; }
+
+ const std::string &lang() const { return lang_; }
+ void set_lang(const std::string &lang) { lang_ = lang; }
+
+
+ private:
+ std::string lang_;
+};
+
+class VideoContentDescription : public MediaContentDescriptionImpl<VideoCodec> {
+ public:
+ virtual MediaType type() const { return MEDIA_TYPE_VIDEO; }
+};
+
+// Convenience functions.
+const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc);
+const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc);
+
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_MEDIASESSIONCLIENT_H_
diff --git a/talk/session/phone/phonesessionclient.cc b/talk/session/phone/phonesessionclient.cc
deleted file mode 100755
index 60daf18..0000000
--- a/talk/session/phone/phonesessionclient.cc
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "talk/base/logging.h"
-#include "talk/session/phone/phonesessionclient.h"
-#include "talk/xmpp/constants.h"
-#include "talk/xmllite/qname.h"
-namespace {
-
-const std::string NS_PHONE("http://www.google.com/session/phone");
-const std::string NS_EMPTY("");
-
-const buzz::QName QN_PHONE_DESCRIPTION(true, NS_PHONE, "description");
-const buzz::QName QN_PHONE_PAYLOADTYPE(true, NS_PHONE, "payload-type");
-const buzz::QName QN_PHONE_PAYLOADTYPE_ID(true, NS_EMPTY, "id");
-const buzz::QName QN_PHONE_PAYLOADTYPE_NAME(true, NS_EMPTY, "name");
-const buzz::QName QN_PHONE_PAYLOADTYPE_RATE(true, NS_EMPTY, "clockrate");
-const buzz::QName QN_PHONE_PAYLOADTYPE_BITRATE(true, NS_EMPTY, "bitrate");
-const buzz::QName QN_PHONE_PAYLOADTYPE_CHANNELS(true, NS_EMPTY, "channels");
-}
-
-namespace cricket {
-
-PhoneSessionClient::PhoneSessionClient(
- const buzz::Jid& jid, SessionManager *manager)
- : jid_(jid), session_manager_(manager) {
- // No call to start, and certainly no call with focus
- focus_call_ = NULL;
-
- // Start up the channel manager on a worker thread
- channel_manager_ = new ChannelManager(session_manager_->worker_thread());
-
- // Register ourselves as the handler of phone sessions.
- session_manager_->AddClient(NS_PHONE, this);
-}
-
-
-PhoneSessionClient::~PhoneSessionClient() {
- // Destroy all calls
- std::map<uint32, Call *>::iterator it;
- while (calls_.begin() != calls_.end()) {
- std::map<uint32, Call *>::iterator it = calls_.begin();
- DestroyCall((*it).second);
- }
-
- // Delete channel manager. This will wait for the channels to exit
- delete channel_manager_;
-
- // Remove ourselves from the client map.
- session_manager_->RemoveClient(NS_PHONE);
-}
-
-PhoneSessionDescription* PhoneSessionClient::CreateOfferSessionDescription() {
- PhoneSessionDescription* session_desc = new PhoneSessionDescription();
-
-
- MediaEngine *me = channel_manager_->media_engine();
- std::vector<Codec> codecs = me->codecs();
- std::vector<Codec>::iterator i;
- for (i = codecs.begin(); i < codecs.end(); i++)
- session_desc->AddCodec(*i);
-
- session_desc->Sort();
- return session_desc;
-}
-
-PhoneSessionDescription* PhoneSessionClient::CreateAcceptSessionDescription(const SessionDescription* offer) {
- const PhoneSessionDescription* offer_desc =
- static_cast<const PhoneSessionDescription*>(offer);
- PhoneSessionDescription* accept_desc = new PhoneSessionDescription();
- std::vector<Codec> codecs = channel_manager_->media_engine()->codecs();
- std::vector<Codec>::iterator iter;
- for (unsigned int i = 0; i < offer_desc->codecs().size(); ++i) {
- if (channel_manager_->media_engine()->FindCodec(offer_desc->codecs()[i]))
- accept_desc->AddCodec(offer_desc->codecs()[i]);
- }
-
- accept_desc->Sort();
- return accept_desc;
-}
-
-const SessionDescription *PhoneSessionClient::CreateSessionDescription(const buzz::XmlElement *element) {
- PhoneSessionDescription* desc = new PhoneSessionDescription();
-
- const buzz::XmlElement* payload_type = element->FirstNamed(QN_PHONE_PAYLOADTYPE);
- int num_payload_types = 0;
-
- while (payload_type) {
- if (payload_type->HasAttr(QN_PHONE_PAYLOADTYPE_ID)) {
- int id = atoi(payload_type->Attr(QN_PHONE_PAYLOADTYPE_ID).c_str());
-
- std::string name = "";
- if (payload_type->HasAttr(QN_PHONE_PAYLOADTYPE_NAME))
- name = payload_type->Attr(QN_PHONE_PAYLOADTYPE_NAME);
-
- int clockrate = 0;
- if (payload_type->HasAttr(QN_PHONE_PAYLOADTYPE_RATE))
- clockrate = atoi(payload_type->Attr(QN_PHONE_PAYLOADTYPE_RATE).c_str());
-
- int bitrate = 0;
- if (payload_type->HasAttr(QN_PHONE_PAYLOADTYPE_BITRATE))
- bitrate = atoi(payload_type->Attr(QN_PHONE_PAYLOADTYPE_BITRATE).c_str());
-
- int channels = 1;
- if (payload_type->HasAttr(QN_PHONE_PAYLOADTYPE_CHANNELS))
- channels = atoi(payload_type->Attr(QN_PHONE_PAYLOADTYPE_CHANNELS).c_str());
-
- desc->AddCodec(Codec(id, name, clockrate, bitrate, channels, 0));
- }
-
- payload_type = payload_type->NextNamed(QN_PHONE_PAYLOADTYPE);
- num_payload_types += 1;
- }
-
- // For backward compatability, we can assume the other client is (an old
- // version of Talk) if it has no payload types at all.
- if (num_payload_types == 0) {
- desc->AddCodec(Codec(103, "ISAC", 16000, -1, 1, 1));
- desc->AddCodec(Codec(0, "PCMU", 8000, 64000, 1, 0));
- }
-
- return desc;
-}
-
-buzz::XmlElement *PhoneSessionClient::TranslateSessionDescription(const SessionDescription *_session_desc) {
- const PhoneSessionDescription* session_desc =
- static_cast<const PhoneSessionDescription*>(_session_desc);
- buzz::XmlElement* description = new buzz::XmlElement(QN_PHONE_DESCRIPTION, true);
-
-
- for (size_t i = 0; i < session_desc->codecs().size(); ++i) {
- buzz::XmlElement* payload_type = new buzz::XmlElement(QN_PHONE_PAYLOADTYPE, true);
-
- char buf[32];
- sprintf(buf, "%d", session_desc->codecs()[i].id);
- payload_type->AddAttr(QN_PHONE_PAYLOADTYPE_ID, buf);
-
- payload_type->AddAttr(QN_PHONE_PAYLOADTYPE_NAME,
- session_desc->codecs()[i].name.c_str());
-
- if (session_desc->codecs()[i].clockrate > 0) {
- sprintf(buf, "%d", session_desc->codecs()[i].clockrate);
- payload_type->AddAttr(QN_PHONE_PAYLOADTYPE_RATE, buf);
- }
-
- if (session_desc->codecs()[i].channels > 1) {
- sprintf(buf, "%d", session_desc->codecs()[i].channels);
- payload_type->AddAttr(QN_PHONE_PAYLOADTYPE_CHANNELS, buf);
- }
-
- if (session_desc->codecs()[i].bitrate > 0) {
- sprintf(buf, "%d", session_desc->codecs()[i].bitrate);
- payload_type->AddAttr(QN_PHONE_PAYLOADTYPE_BITRATE, buf);
- }
-
- description->AddElement(payload_type);
- }
-
- return description;
-}
-
-Call *PhoneSessionClient::CreateCall() {
- Call *call = new Call(this);
- calls_[call->id()] = call;
- SignalCallCreate(call);
- return call;
-}
-
-void PhoneSessionClient::OnSessionCreate(Session *session,
- bool received_initiate) {
- if (received_initiate) {
- session->SignalState.connect(this, &PhoneSessionClient::OnSessionState);
-
- Call *call = CreateCall();
- session_map_[session->id()] = call;
- call->AddSession(session);
- }
-}
-
-void PhoneSessionClient::OnSessionState(Session *session,
- Session::State state) {
- if (state == Session::STATE_RECEIVEDINITIATE) {
- // If our accept would have no codecs, then we must reject this call.
- PhoneSessionDescription* accept_desc =
- CreateAcceptSessionDescription(session->remote_description());
- if (accept_desc->codecs().size() == 0) {
- // TODO: include an error description with the rejection.
- session->Reject();
- }
- delete accept_desc;
- }
-}
-
-void PhoneSessionClient::DestroyCall(Call *call) {
- // Change focus away, signal destruction
-
- if (call == focus_call_)
- SetFocus(NULL);
- SignalCallDestroy(call);
-
- // Remove it from calls_ map and delete
-
- std::map<uint32, Call *>::iterator it = calls_.find(call->id());
- if (it != calls_.end())
- calls_.erase(it);
-
- delete call;
-}
-
-void PhoneSessionClient::OnSessionDestroy(Session *session) {
- // Find the call this session is in, remove it
-
- std::map<SessionID, Call *>::iterator it = session_map_.find(session->id());
- assert(it != session_map_.end());
- if (it != session_map_.end()) {
- Call *call = (*it).second;
- session_map_.erase(it);
- call->RemoveSession(session);
- }
-}
-
-Call *PhoneSessionClient::GetFocus() {
- return focus_call_;
-}
-
-void PhoneSessionClient::SetFocus(Call *call) {
- Call *old_focus_call = focus_call_;
- if (focus_call_ != call) {
- if (focus_call_ != NULL)
- focus_call_->EnableChannels(false);
- focus_call_ = call;
- if (focus_call_ != NULL)
- focus_call_->EnableChannels(true);
- SignalFocus(focus_call_, old_focus_call);
- }
-}
-
-void PhoneSessionClient::JoinCalls(Call *call_to_join, Call *call) {
- // Move all sessions from call to call_to_join, delete call.
- // If call_to_join has focus, added sessions should have enabled channels.
-
- if (focus_call_ == call)
- SetFocus(NULL);
- call_to_join->Join(call, focus_call_ == call_to_join);
- DestroyCall(call);
-}
-
-Session *PhoneSessionClient::CreateSession(Call *call) {
- Session *session = session_manager_->CreateSession(jid().Str(), NS_PHONE);
- session_map_[session->id()] = call;
- return session;
-}
-
-}
diff --git a/talk/session/phone/phonesessionclient.h b/talk/session/phone/phonesessionclient.h
deleted file mode 100755
index 0b4ce25..0000000
--- a/talk/session/phone/phonesessionclient.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _PHONESESSIONCLIENT_H_
-#define _PHONESESSIONCLIENT_H_
-
-#include "talk/session/phone/call.h"
-#include "talk/session/phone/channelmanager.h"
-#include "talk/base/sigslot.h"
-#include "talk/base/messagequeue.h"
-#include "talk/base/thread.h"
-#include "talk/p2p/base/sessionmanager.h"
-#include "talk/p2p/base/session.h"
-#include "talk/p2p/base/sessionclient.h"
-#include "talk/p2p/base/sessiondescription.h"
-#include <map>
-
-namespace cricket {
-
-class Call;
-class PhoneSessionDescription;
-
-class PhoneSessionClient: public SessionClient, public sigslot::has_slots<> {
-public:
- PhoneSessionClient(const buzz::Jid& jid, SessionManager *manager);
- ~PhoneSessionClient();
-
- const buzz::Jid &jid() const { return jid_; }
- SessionManager* session_manager() const { return session_manager_; }
- ChannelManager* channel_manager() const { return channel_manager_; }
-
- Call *CreateCall();
- void DestroyCall(Call *call);
-
- Call *GetFocus();
- void SetFocus(Call *call);
-
- void JoinCalls(Call *call_to_join, Call *call);
-
- void SetAudioOptions(bool auto_gain_control, int wave_in_device,
- int wave_out_device) {
- if (channel_manager_)
- channel_manager_->SetAudioOptions(auto_gain_control, wave_in_device,
- wave_out_device);
- }
-
- sigslot::signal2<Call *, Call *> SignalFocus;
- sigslot::signal1<Call *> SignalCallCreate;
- sigslot::signal1<Call *> SignalCallDestroy;
-
- PhoneSessionDescription* CreateOfferSessionDescription();
-
- PhoneSessionDescription* CreateAcceptSessionDescription(const SessionDescription* offer);
-
- // Returns our preference for the given codec.
- static int GetMediaCodecPreference(Codec codec);
-
-private:
- void OnSessionCreate(Session *session, bool received_initiate);
- void OnSessionState(Session *session, Session::State state);
- void OnSessionDestroy(Session *session);
- const SessionDescription *CreateSessionDescription(const buzz::XmlElement *element);
- buzz::XmlElement *TranslateSessionDescription(const SessionDescription *description);
- Session *CreateSession(Call *call);
-
- buzz::Jid jid_;
- SessionManager* session_manager_;
- Call *focus_call_;
- ChannelManager *channel_manager_;
- std::map<uint32, Call *> calls_;
- std::map<SessionID, Call *> session_map_;
-
- friend class Call;
-};
-
-class PhoneSessionDescription: public SessionDescription {
-public:
- // Returns the list of codecs sorted by our preference.
- const std::vector<Codec>& codecs() const { return codecs_; }
- // Adds another codec to the list.
- void AddCodec(const Codec& codec) { codecs_.push_back(codec); }
- // Sorts the list of codecs by preference.
- void Sort() { std::sort(codecs_.begin(), codecs_.end(), PreferenceSort()); }
-
-private:
- std::vector<Codec> codecs_;
- struct PreferenceSort {
- bool operator()(Codec a, Codec b) {
- return a.preference > b.preference;
- }
- };
-
-#if defined(FEATURE_ENABLE_VOICEMAIL)
- std::string lang_;
-#endif
-
-};
-
-}
-
-#endif // _PHONESESSIONCLIENT_H_
diff --git a/talk/session/phone/rtpdump.cc b/talk/session/phone/rtpdump.cc
new file mode 100644
index 0000000..1006015
--- /dev/null
+++ b/talk/session/phone/rtpdump.cc
@@ -0,0 +1,322 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/phone/rtpdump.h"
+
+#include <string>
+
+#include "talk/base/bytebuffer.h"
+#include "talk/base/logging.h"
+#include "talk/base/time.h"
+
+namespace cricket {
+
+static const char kRtpDumpFileFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n";
+
+struct RtpDumpFileHeader {
+ RtpDumpFileHeader(uint32 start_ms, uint32 s, uint16 p)
+ : start_sec(start_ms / 1000),
+ start_usec(start_ms % 1000 * 1000),
+ source(s),
+ port(p),
+ padding(0) {
+ }
+
+ void WriteToByteBuffer(talk_base::ByteBuffer* buf) {
+ buf->WriteUInt32(start_sec);
+ buf->WriteUInt32(start_usec);
+ buf->WriteUInt32(source);
+ buf->WriteUInt16(port);
+ buf->WriteUInt16(padding);
+ }
+
+ static const size_t kHeaderLength = 16;
+ uint32 start_sec; // start of recording, the seconds part.
+ uint32 start_usec; // start of recording, the microseconds part.
+ uint32 source; // network source (multicast address).
+ uint16 port; // UDP port.
+ uint16 padding; // 2 bytes padding.
+};
+
+// RTP packet format (http://www.networksorcery.com/enp/protocol/rtp.htm).
+static const int kRtpSeqNumOffset = 2;
+static const int kRtpSeqNumAndTimestampSize = 6;
+static const uint32 kDefaultTimeIncrease = 30;
+
+bool RtpDumpPacket::IsValidRtpPacket() const {
+ return !is_rtcp &&
+ data.size() >= kRtpSeqNumOffset + kRtpSeqNumAndTimestampSize;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation of RtpDumpReader.
+///////////////////////////////////////////////////////////////////////////
+talk_base::StreamResult RtpDumpReader::ReadPacket(RtpDumpPacket* packet) {
+ if (!packet) return talk_base::SR_ERROR;
+
+ talk_base::StreamResult res = talk_base::SR_SUCCESS;
+ // Read the file header if it has not been read yet.
+ if (!file_header_read_) {
+ res = ReadFileHeader();
+ if (res != talk_base::SR_SUCCESS) {
+ return res;
+ }
+ file_header_read_ = true;
+ }
+
+ // Read the RTP dump packet header.
+ char header[RtpDumpPacket::kHeaderLength];
+ res = stream_->ReadAll(header, sizeof(header), NULL, NULL);
+ if (res != talk_base::SR_SUCCESS) {
+ return res;
+ }
+ talk_base::ByteBuffer buf(header, sizeof(header));
+ uint16 dump_packet_len;
+ uint16 data_len;
+ buf.ReadUInt16(&dump_packet_len);
+ buf.ReadUInt16(&data_len); // data.size() for RTP, 0 for RTCP.
+ packet->is_rtcp = (0 == data_len);
+ buf.ReadUInt32(&packet->elapsed_time);
+ packet->data.resize(dump_packet_len - sizeof(header));
+
+ // Read the actual RTP or RTCP packet.
+ return stream_->ReadAll(&packet->data[0], packet->data.size(), NULL, NULL);
+}
+
+talk_base::StreamResult RtpDumpReader::ReadFileHeader() {
+ // Read the first line.
+ std::string first_line;
+ talk_base::StreamResult res = stream_->ReadLine(&first_line);
+ if (res != talk_base::SR_SUCCESS) {
+ return res;
+ }
+ if (!CheckFirstLine(first_line)) {
+ return talk_base::SR_ERROR;
+ }
+
+ // Read the 16 byte file header.
+ char header[RtpDumpFileHeader::kHeaderLength];
+ res = stream_->ReadAll(header, sizeof(header), NULL, NULL);
+ if (res == talk_base::SR_SUCCESS) {
+ talk_base::ByteBuffer buf(header, sizeof(header));
+ uint32 start_sec;
+ uint32 start_usec;
+ buf.ReadUInt32(&start_sec);
+ buf.ReadUInt32(&start_usec);
+ start_time_ms_ = start_sec * 1000 + start_usec / 1000;
+ // Increase the length by 1 since first_line does not contain the ending \n.
+ first_line_and_file_header_len_ = first_line.size() + 1 + sizeof(header);
+ }
+ return res;
+}
+
+bool RtpDumpReader::CheckFirstLine(const std::string& first_line) {
+ // The first line is like "#!rtpplay1.0 address/port"
+ bool matched = (0 == first_line.find("#!rtpplay1.0 "));
+
+ // The address could be IP or hostname. We do not check it here. Instead, we
+ // check the port at the end.
+ size_t pos = first_line.find('/');
+ matched &= (pos != std::string::npos && pos < first_line.size() - 1);
+ for (++pos; pos < first_line.size() && matched; ++pos) {
+ matched &= (0 != isdigit(first_line[pos]));
+ }
+
+ return matched;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation of RtpDumpLoopReader.
+///////////////////////////////////////////////////////////////////////////
+RtpDumpLoopReader::RtpDumpLoopReader(talk_base::StreamInterface* stream)
+ : RtpDumpReader(stream),
+ loop_count_(0),
+ elapsed_time_increases_(0),
+ rtp_seq_num_increase_(0),
+ rtp_timestamp_increase_(0),
+ packet_count_(0),
+ frame_count_(0),
+ first_elapsed_time_(0),
+ first_rtp_seq_num_(0),
+ first_rtp_timestamp_(0),
+ prev_elapsed_time_(0),
+ prev_rtp_seq_num_(0),
+ prev_rtp_timestamp_(0) {
+}
+
+talk_base::StreamResult RtpDumpLoopReader::ReadPacket(RtpDumpPacket* packet) {
+ if (!packet) return talk_base::SR_ERROR;
+
+ talk_base::StreamResult res = RtpDumpReader::ReadPacket(packet);
+ if (talk_base::SR_SUCCESS == res) {
+ if (0 == loop_count_) {
+ // During the first loop, we update the statistics of the input stream.
+ UpdateStreamStatistics(*packet);
+ }
+ } else if (talk_base::SR_EOS == res) {
+ if (0 == loop_count_) {
+ // At the end of the first loop, calculate elapsed_time_increases_,
+ // rtp_seq_num_increase_, and rtp_timestamp_increase_, which will be
+ // used during the second and later loops.
+ CalculateIncreases();
+ }
+
+ // Rewind the input stream to the first dump packet and read again.
+ ++loop_count_;
+ if (RewindToFirstDumpPacket()) {
+ res = RtpDumpReader::ReadPacket(packet);
+ }
+ }
+
+ if (talk_base::SR_SUCCESS == res && loop_count_ > 0) {
+ // During the second and later loops, we update the elapsed time of the dump
+ // packet. If the dumped packet is a RTP packet, we also update its RTP
+ // sequence number and timestamp.
+ UpdateDumpPacket(packet);
+ }
+
+ return res;
+}
+
+void RtpDumpLoopReader::UpdateStreamStatistics(const RtpDumpPacket& packet) {
+ // Get the RTP sequence number and timestamp of the dump packet.
+ uint16 rtp_seq_num = 0;
+ uint32 rtp_timestamp = 0;
+ if (packet.IsValidRtpPacket()) {
+ ReadRtpSeqNumAndTimestamp(packet, &rtp_seq_num, &rtp_timestamp);
+ }
+
+ // Get the timestamps and sequence number for the first dump packet.
+ if (0 == packet_count_++) {
+ first_elapsed_time_ = packet.elapsed_time;
+ first_rtp_seq_num_ = rtp_seq_num;
+ first_rtp_timestamp_ = rtp_timestamp;
+ // The first packet belongs to a new payload frame.
+ ++frame_count_;
+ } else if (rtp_timestamp != prev_rtp_timestamp_) {
+ // The current and previous packets belong to different payload frames.
+ ++frame_count_;
+ }
+
+ prev_elapsed_time_ = packet.elapsed_time;
+ prev_rtp_timestamp_ = rtp_timestamp;
+ prev_rtp_seq_num_ = rtp_seq_num;
+}
+
+void RtpDumpLoopReader::CalculateIncreases() {
+ // At this time, prev_elapsed_time_, prev_rtp_seq_num_, and
+ // prev_rtp_timestamp_ are values of the last dump packet in the input stream.
+ rtp_seq_num_increase_ = prev_rtp_seq_num_ - first_rtp_seq_num_ + 1;
+ // If we have only one packet or frame, we use the default timestamp
+ // increase. Otherwise, we use the difference between the first and the last
+ // packets or frames.
+ elapsed_time_increases_ = packet_count_ <= 1 ? kDefaultTimeIncrease :
+ (prev_elapsed_time_ - first_elapsed_time_) * packet_count_ /
+ (packet_count_ - 1);
+ rtp_timestamp_increase_ = frame_count_ <= 1 ? kDefaultTimeIncrease :
+ (prev_rtp_timestamp_ - first_rtp_timestamp_) * frame_count_ /
+ (frame_count_ - 1);
+}
+
+void RtpDumpLoopReader::UpdateDumpPacket(RtpDumpPacket* packet) {
+ // Increase the elapsed time of the dump packet.
+ packet->elapsed_time += loop_count_ * elapsed_time_increases_;
+
+ if (packet->IsValidRtpPacket()) {
+ // Get the old RTP sequence number and timestamp.
+ uint16 sequence;
+ uint32 timestamp;
+ ReadRtpSeqNumAndTimestamp(*packet, &sequence, ×tamp);
+ // Increase the RTP sequence number and timestamp.
+ sequence += loop_count_ * rtp_seq_num_increase_;
+ timestamp += loop_count_ * rtp_timestamp_increase_;
+ // Write the updated sequence number and timestamp back to the RTP packet.
+ talk_base::ByteBuffer buffer;
+ buffer.WriteUInt16(sequence);
+ buffer.WriteUInt32(timestamp);
+ memcpy(&packet->data[0] + kRtpSeqNumOffset, buffer.Data(), buffer.Length());
+ }
+}
+
+void RtpDumpLoopReader::ReadRtpSeqNumAndTimestamp(
+ const RtpDumpPacket& packet, uint16* sequence, uint32* timestamp) {
+ talk_base::ByteBuffer buffer(
+ reinterpret_cast<const char*>(&packet.data[0] + kRtpSeqNumOffset),
+ kRtpSeqNumAndTimestampSize);
+ buffer.ReadUInt16(sequence);
+ buffer.ReadUInt32(timestamp);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Implementation of RtpDumpWriter.
+///////////////////////////////////////////////////////////////////////////
+uint32 RtpDumpWriter::GetElapsedTime() const {
+ return talk_base::TimeSince(start_time_ms_);
+}
+
+talk_base::StreamResult RtpDumpWriter::WritePacket(
+ const void* data, size_t data_len, uint32 elapsed, bool rtcp) {
+ if (!data || 0 == data_len) return talk_base::SR_ERROR;
+
+ talk_base::StreamResult res = talk_base::SR_SUCCESS;
+ // Write the file header if it has not been written yet.
+ if (!file_header_written_) {
+ res = WriteFileHeader();
+ if (res != talk_base::SR_SUCCESS) {
+ return res;
+ }
+ file_header_written_ = true;
+ }
+
+ // Write the dump packet header.
+ talk_base::ByteBuffer buf;
+ buf.WriteUInt16(static_cast<uint16>(RtpDumpPacket::kHeaderLength + data_len));
+ buf.WriteUInt16(static_cast<uint16>(rtcp ? 0 : data_len));
+ buf.WriteUInt32(elapsed);
+ res = stream_->WriteAll(buf.Data(), buf.Length(), NULL, NULL);
+ if (res != talk_base::SR_SUCCESS) {
+ return res;
+ }
+
+ // Write the actual RTP or RTCP packet.
+ return stream_->WriteAll(data, data_len, NULL, NULL);
+}
+
+talk_base::StreamResult RtpDumpWriter::WriteFileHeader() {
+ talk_base::StreamResult res = stream_->WriteAll(
+ kRtpDumpFileFirstLine, strlen(kRtpDumpFileFirstLine), NULL, NULL);
+ if (res != talk_base::SR_SUCCESS) {
+ return res;
+ }
+
+ talk_base::ByteBuffer buf;
+ RtpDumpFileHeader file_header(talk_base::Time(), 0, 0);
+ file_header.WriteToByteBuffer(&buf);
+ return stream_->WriteAll(buf.Data(), buf.Length(), NULL, NULL);
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/rtpdump.h b/talk/session/phone/rtpdump.h
new file mode 100644
index 0000000..40c4e03
--- /dev/null
+++ b/talk/session/phone/rtpdump.h
@@ -0,0 +1,184 @@
+/*
+ * libjingle
+ * Copyright 2010, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_SESSION_PHONE_RTPDUMP_H_
+#define TALK_SESSION_PHONE_RTPDUMP_H_
+
+#include <cstring>
+#include <string>
+#include <vector>
+
+#include "talk/base/basictypes.h"
+#include "talk/base/stream.h"
+
+namespace cricket {
+
+// We use the RTP dump file format compatible to the format used by rtptools
+// (http://www.cs.columbia.edu/irt/software/rtptools/) and Wireshark
+// (http://wiki.wireshark.org/rtpdump). In particular, the file starts with the
+// first line "#!rtpplay1.0 address/port\n", followed by a 16 byte file header.
+// For each packet, the file contains a 8 byte dump packet header, followed by
+// the actual RTP or RTCP packet.
+
+struct RtpDumpPacket {
+ RtpDumpPacket() {}
+
+ RtpDumpPacket(const void* d, size_t s, uint32 elapsed, bool rtcp)
+ : elapsed_time(elapsed),
+ is_rtcp(rtcp) {
+ data.resize(s);
+ memcpy(&data[0], d, s);
+ }
+
+ // Check if the dumped packet is a valid RTP packet with the sequence number
+ // and timestamp.
+ bool IsValidRtpPacket() const;
+
+ static const size_t kHeaderLength = 8;
+ uint32 elapsed_time; // Milliseconds since the start of recording.
+ bool is_rtcp; // True if the data below is a RTCP packet.
+ std::vector<uint8> data; // The actual RTP or RTCP packet.
+};
+
+class RtpDumpReader {
+ public:
+ explicit RtpDumpReader(talk_base::StreamInterface* stream)
+ : stream_(stream),
+ file_header_read_(false),
+ first_line_and_file_header_len_(0),
+ start_time_ms_(0) {
+ }
+ virtual ~RtpDumpReader() {}
+
+ virtual talk_base::StreamResult ReadPacket(RtpDumpPacket* packet);
+
+ protected:
+ talk_base::StreamResult ReadFileHeader();
+ bool RewindToFirstDumpPacket() {
+ return stream_->SetPosition(first_line_and_file_header_len_);
+ }
+
+ private:
+ // Check if its matches "#!rtpplay1.0 address/port\n".
+ bool CheckFirstLine(const std::string& first_line);
+
+ talk_base::StreamInterface* stream_;
+ bool file_header_read_;
+ size_t first_line_and_file_header_len_;
+ uint32 start_time_ms_;
+ DISALLOW_COPY_AND_ASSIGN(RtpDumpReader);
+};
+
+// RtpDumpLoopReader reads RTP dump packets from the input stream and rewinds
+// the stream when it ends. RtpDumpLoopReader maintains the elapsed time, the
+// RTP sequence number and the RTP timestamp properly. RtpDumpLoopReader can
+// handle both RTP dump and RTCP dump. We assume that the dump does not mix
+// RTP packets and RTCP packets.
+class RtpDumpLoopReader : public RtpDumpReader {
+ public:
+ explicit RtpDumpLoopReader(talk_base::StreamInterface* stream);
+ virtual talk_base::StreamResult ReadPacket(RtpDumpPacket* packet);
+
+ private:
+ // Read the sequence number and timestamp from the RTP dump packet.
+ static void ReadRtpSeqNumAndTimestamp(const RtpDumpPacket& packet,
+ uint16* seq_num, uint32* timestamp);
+
+ // During the first loop, update the statistics, including packet count, frame
+ // count, timestamps, and sequence number, of the input stream.
+ void UpdateStreamStatistics(const RtpDumpPacket& packet);
+
+ // At the end of first loop, calculate elapsed_time_increases_,
+ // rtp_seq_num_increase_, and rtp_timestamp_increase_.
+ void CalculateIncreases();
+
+ // During the second and later loops, update the elapsed time of the dump
+ // packet. If the dumped packet is a RTP packet, update its RTP sequence
+ // number and timestamp as well.
+ void UpdateDumpPacket(RtpDumpPacket* packet);
+
+ int loop_count_;
+ // How much to increase the elapsed time, RTP sequence number, RTP timestampe
+ // for each loop. They are calcualted with the variables below during the
+ // first loop.
+ uint32 elapsed_time_increases_;
+ uint16 rtp_seq_num_increase_;
+ uint32 rtp_timestamp_increase_;
+ // How many RTP packets and how many payload frames in the input stream. RTP
+ // packets belong to the same frame have the same RTP timestamp, different
+ // dump timestamp, and different RTP sequence number.
+ uint32 packet_count_;
+ uint32 frame_count_;
+ // The elapsed time, RTP sequence number, and RTP timestamp of the first and
+ // the previous dump packets in the input stream.
+ uint32 first_elapsed_time_;
+ uint16 first_rtp_seq_num_;
+ uint32 first_rtp_timestamp_;
+ uint32 prev_elapsed_time_;
+ uint16 prev_rtp_seq_num_;
+ uint32 prev_rtp_timestamp_;
+
+ DISALLOW_COPY_AND_ASSIGN(RtpDumpLoopReader);
+};
+
+class RtpDumpWriter {
+ public:
+ explicit RtpDumpWriter(talk_base::StreamInterface* stream)
+ : stream_(stream),
+ file_header_written_(false),
+ start_time_ms_(0) {
+ }
+ // Write a RTP or RTCP packet. The parameters data points to the packet and
+ // data_len is its length.
+ talk_base::StreamResult WriteRtpPacket(const void* data, size_t data_len) {
+ return WritePacket(data, data_len, GetElapsedTime(), false);
+ }
+ talk_base::StreamResult WriteRtcpPacket(const void* data, size_t data_len) {
+ return WritePacket(data, data_len, GetElapsedTime(), true);
+ }
+ talk_base::StreamResult WritePacket(const RtpDumpPacket& packet) {
+ return WritePacket(&packet.data[0], packet.data.size(), packet.elapsed_time,
+ packet.is_rtcp);
+ }
+ uint32 GetElapsedTime() const;
+
+ protected:
+ talk_base::StreamResult WriteFileHeader();
+
+ private:
+ talk_base::StreamResult WritePacket(const void* data, size_t data_len,
+ uint32 elapsed, bool rtcp);
+
+ talk_base::StreamInterface* stream_;
+ bool file_header_written_;
+ uint32 start_time_ms_; // Time when the record starts.
+ DISALLOW_COPY_AND_ASSIGN(RtpDumpWriter);
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_RTPDUMP_H_
diff --git a/talk/session/phone/soundclip.cc b/talk/session/phone/soundclip.cc
new file mode 100644
index 0000000..f1069e0
--- /dev/null
+++ b/talk/session/phone/soundclip.cc
@@ -0,0 +1,82 @@
+/*
+ * libjingle
+ * Copyright 2004--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/phone/soundclip.h"
+
+namespace cricket {
+
+enum {
+ MSG_PLAYSOUND = 1,
+};
+
+struct PlaySoundMessageData : talk_base::MessageData {
+ PlaySoundMessageData(const void *c,
+ int l,
+ SoundclipMedia::SoundclipFlags f)
+ : clip(c),
+ len(l),
+ flags(f),
+ result(false) {
+ }
+
+ const void *clip;
+ int len;
+ SoundclipMedia::SoundclipFlags flags;
+ bool result;
+};
+
+Soundclip::Soundclip(talk_base::Thread *thread, SoundclipMedia *soundclip_media)
+ : worker_thread_(thread),
+ soundclip_media_(soundclip_media) {
+}
+
+bool Soundclip::PlaySound(const void *clip,
+ int len,
+ SoundclipMedia::SoundclipFlags flags) {
+ PlaySoundMessageData data(clip, len, flags);
+ worker_thread_->Send(this, MSG_PLAYSOUND, &data);
+ return data.result;
+}
+
+bool Soundclip::PlaySound_w(const void *clip,
+ int len,
+ SoundclipMedia::SoundclipFlags flags) {
+ return soundclip_media_->PlaySound(static_cast<const char *>(clip),
+ len,
+ flags);
+}
+
+void Soundclip::OnMessage(talk_base::Message *message) {
+ ASSERT(message->message_id == MSG_PLAYSOUND);
+ PlaySoundMessageData *data =
+ static_cast<PlaySoundMessageData *>(message->pdata);
+ data->result = PlaySound_w(data->clip,
+ data->len,
+ data->flags);
+}
+
+} // namespace cricket
diff --git a/talk/session/phone/soundclip.h b/talk/session/phone/soundclip.h
new file mode 100644
index 0000000..4038477
--- /dev/null
+++ b/talk/session/phone/soundclip.h
@@ -0,0 +1,70 @@
+/*
+ * libjingle
+ * Copyright 2004--2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_SESSION_PHONE_SOUNDCLIP_H_
+#define TALK_SESSION_PHONE_SOUNDCLIP_H_
+
+#include "talk/base/scoped_ptr.h"
+#include "talk/session/phone/mediaengine.h"
+
+namespace talk_base {
+
+class Thread;
+
+}
+
+namespace cricket {
+
+// Soundclip wraps SoundclipMedia to support marshalling calls to the proper
+// thread.
+class Soundclip : private talk_base::MessageHandler {
+ public:
+ Soundclip(talk_base::Thread* thread, SoundclipMedia* soundclip_media);
+
+ // Plays a sound out to the speakers with the given audio stream. The stream
+ // must be 16-bit little-endian 16 kHz PCM. If a stream is already playing
+ // on this Soundclip, it is stopped. If clip is NULL, nothing is played.
+ // Returns whether it was successful.
+ bool PlaySound(const void* clip,
+ int len,
+ SoundclipMedia::SoundclipFlags flags);
+
+ private:
+ bool PlaySound_w(const void* clip,
+ int len,
+ SoundclipMedia::SoundclipFlags flags);
+
+ // From MessageHandler
+ virtual void OnMessage(talk_base::Message* message);
+
+ talk_base::Thread* worker_thread_;
+ talk_base::scoped_ptr<SoundclipMedia> soundclip_media_;
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_SOUNDCLIP_H_
diff --git a/talk/session/phone/srtpfilter.cc b/talk/session/phone/srtpfilter.cc
new file mode 100644
index 0000000..63daed6
--- /dev/null
+++ b/talk/session/phone/srtpfilter.cc
@@ -0,0 +1,434 @@
+/*
+ * libjingle
+ * Copyright 2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#undef HAVE_CONFIG_H // talk's config.h conflicts with the one included by the
+ // libsrtp headers. Don't use it.
+#include "talk/session/phone/srtpfilter.h"
+
+#include <algorithm>
+#include <cstring>
+
+#include "talk/base/base64.h"
+#include "talk/base/logging.h"
+
+// TODO: For the XCode build, we force SRTP (b/2500074)
+#if defined(OSX) && !defined(HAVE_SRTP)
+#define HAVE_SRTP 1
+#endif
+
+// Enable this line to turn on SRTP debugging
+// #define SRTP_DEBUG
+
+#ifdef HAVE_SRTP
+#ifdef SRTP_RELATIVE_PATH
+#include "srtp.h" // NOLINT
+#else
+#include "third_party/libsrtp/include/srtp.h"
+#endif // SRTP_RELATIVE_PATH
+#ifdef _DEBUG
+extern "C" debug_module_t mod_srtp;
+#endif
+#else
+// SrtpFilter needs that constant.
+#define SRTP_MASTER_KEY_LEN 30
+#endif // HAVE_SRTP
+
+namespace cricket {
+
+const std::string& CS_DEFAULT = CS_AES_CM_128_HMAC_SHA1_80;
+const std::string CS_AES_CM_128_HMAC_SHA1_80 = "AES_CM_128_HMAC_SHA1_80";
+const std::string CS_AES_CM_128_HMAC_SHA1_32 = "AES_CM_128_HMAC_SHA1_32";
+
+SrtpFilter::SrtpFilter() : state_(ST_INIT) {
+}
+
+SrtpFilter::~SrtpFilter() {
+}
+
+bool SrtpFilter::IsActive() const {
+ return (state_ == ST_ACTIVE);
+}
+
+bool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
+ ContentSource source) {
+ bool ret = false;
+ if (state_ == ST_INIT) {
+ ret = StoreParams(offer_params, source);
+ } else {
+ LOG(LS_ERROR) << "Invalid state for SRTP offer";
+ }
+ return ret;
+}
+
+bool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
+ ContentSource source) {
+ bool ret = false;
+ if ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
+ (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL)) {
+ // If the answer requests crypto, finalize the parameters and apply them.
+ // Otherwise, complete the negotiation of a unencrypted session.
+ if (!answer_params.empty()) {
+ CryptoParams selected_params;
+ ret = NegotiateParams(answer_params, &selected_params);
+ if (ret) {
+ if (state_ == ST_SENTOFFER) {
+ ret = ApplyParams(selected_params, answer_params[0]);
+ } else { // ST_RECEIVEDOFFER
+ ret = ApplyParams(answer_params[0], selected_params);
+ }
+ }
+ } else {
+ ret = ResetParams();
+ }
+ } else {
+ LOG(LS_ERROR) << "Invalid state for SRTP answer";
+ }
+ return ret;
+}
+
+bool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
+ if (!IsActive()) {
+ return false;
+ }
+ return send_session_.ProtectRtp(p, in_len, max_len, out_len);
+}
+
+bool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
+ if (!IsActive()) {
+ return false;
+ }
+ return send_session_.ProtectRtcp(p, in_len, max_len, out_len);
+}
+
+bool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) {
+ if (!IsActive()) {
+ return false;
+ }
+ return recv_session_.UnprotectRtp(p, in_len, out_len);
+}
+
+bool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) {
+ if (!IsActive()) {
+ return false;
+ }
+ return recv_session_.UnprotectRtcp(p, in_len, out_len);
+}
+
+
+bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
+ ContentSource source) {
+ offer_params_ = params;
+ state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
+ return true;
+}
+
+bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
+ CryptoParams* selected_params) {
+ // We're processing an accept. We should have exactly one set of params,
+ // unless the offer didn't mention crypto, in which case we shouldn't be here.
+ bool ret = (answer_params.size() == 1U && !offer_params_.empty());
+ if (ret) {
+ // We should find a match between the answer params and the offered params.
+ std::vector<CryptoParams>::const_iterator it;
+ for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
+ if (answer_params[0].Matches(*it)) {
+ break;
+ }
+ }
+
+ if (it != offer_params_.end()) {
+ *selected_params = *it;
+ } else {
+ ret = false;
+ }
+ }
+
+ if (!ret) {
+ LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
+ }
+ return ret;
+}
+
+bool SrtpFilter::ApplyParams(const CryptoParams& send_params,
+ const CryptoParams& recv_params) {
+ // TODO: Zero these buffers after use.
+ bool ret;
+ uint8 send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN];
+ ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) &&
+ ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key)));
+ if (ret) {
+ ret = (send_session_.SetSend(send_params.cipher_suite,
+ send_key, sizeof(send_key)) &&
+ recv_session_.SetRecv(recv_params.cipher_suite,
+ recv_key, sizeof(recv_key)));
+ }
+ if (ret) {
+ offer_params_.clear();
+ state_ = ST_ACTIVE;
+ } else {
+ LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters";
+ }
+ return ret;
+}
+
+bool SrtpFilter::ResetParams() {
+ offer_params_.clear();
+ state_ = ST_INIT;
+ return true;
+}
+
+bool SrtpFilter::ParseKeyParams(const std::string& key_params,
+ uint8* key, int len) {
+ // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
+
+ // Fail if key-method is wrong.
+ if (key_params.find("inline:") != 0) {
+ return false;
+ }
+
+ // Fail if base64 decode fails, or the key is the wrong size.
+ std::string key_b64(key_params.substr(7)), key_str;
+ if (!talk_base::Base64::Decode(key_b64, talk_base::Base64::DO_STRICT,
+ &key_str, NULL) ||
+ static_cast<int>(key_str.size()) != len) {
+ return false;
+ }
+
+ memcpy(key, key_str.c_str(), len);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SrtpSession
+
+#ifdef HAVE_SRTP
+
+bool SrtpSession::inited_ = false;
+std::list<SrtpSession*> SrtpSession::sessions_;
+
+SrtpSession::SrtpSession()
+ : session_(NULL), rtp_auth_tag_len_(0), rtcp_auth_tag_len_(0) {
+ sessions_.push_back(this);
+}
+
+SrtpSession::~SrtpSession() {
+ sessions_.erase(std::find(sessions_.begin(), sessions_.end(), this));
+ if (session_) {
+ srtp_dealloc(session_);
+ }
+}
+
+bool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
+ return SetKey(ssrc_any_outbound, cs, key, len);
+}
+
+bool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
+ return SetKey(ssrc_any_inbound, cs, key, len);
+}
+
+bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
+ if (!session_)
+ return false;
+ int need_len = in_len + rtp_auth_tag_len_; // NOLINT
+ if (max_len < need_len)
+ return false;
+ *out_len = in_len;
+ int err = srtp_protect(session_, p, out_len);
+ if (err != err_status_ok) {
+ LOG(LS_WARNING) << "Failed to protect SRTP packet, err=" << err;
+ return false;
+ }
+ return true;
+}
+
+bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
+ if (!session_)
+ return false;
+ int need_len = in_len + sizeof(uint32) + rtcp_auth_tag_len_; // NOLINT
+ if (max_len < need_len)
+ return false;
+ *out_len = in_len;
+ int err = srtp_protect_rtcp(session_, p, out_len);
+ if (err != err_status_ok) {
+ LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
+ return false;
+ }
+ return true;
+}
+
+bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
+ if (!session_)
+ return false;
+ *out_len = in_len;
+ int err = srtp_unprotect(session_, p, out_len);
+ if (err != err_status_ok) {
+ LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err;
+ return false;
+ }
+ return true;
+}
+
+bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
+ if (!session_)
+ return false;
+ *out_len = in_len;
+ int err = srtp_unprotect_rtcp(session_, p, out_len);
+ if (err != err_status_ok) {
+ LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
+ return false;
+ }
+ return true;
+}
+
+bool SrtpSession::SetKey(int type, const std::string& cs,
+ const uint8* key, int len) {
+ if (session_) {
+ return false;
+ }
+
+ if (!Init()) {
+ return false;
+ }
+
+ srtp_policy_t policy;
+ memset(&policy, 0, sizeof(policy));
+
+ if (cs == CS_AES_CM_128_HMAC_SHA1_80) {
+ crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
+ crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
+ } else if (cs == CS_AES_CM_128_HMAC_SHA1_32) {
+ crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32,
+ crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80
+ } else {
+ return false;
+ }
+
+ if (!key || len != SRTP_MASTER_KEY_LEN) {
+ return false;
+ }
+
+ policy.ssrc.type = static_cast<ssrc_type_t>(type);
+ policy.ssrc.value = 0;
+ policy.key = const_cast<uint8*>(key);
+ // TODO parse window size from WSH session-param
+ policy.window_size = 1024;
+ policy.allow_repeat_tx = 1;
+ policy.next = NULL;
+
+ int err = srtp_create(&session_, &policy);
+ if (err != err_status_ok) {
+ LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
+ return false;
+ }
+
+ rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
+ rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
+ return true;
+}
+
+bool SrtpSession::Init() {
+ if (!inited_) {
+ int err;
+#ifdef DEBUG_SRTP
+ debug_on(mod_srtp);
+#endif
+ err = srtp_init();
+ if (err != err_status_ok) {
+ LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
+ return false;
+ }
+
+ err = srtp_install_event_handler(&SrtpSession::HandleEventThunk);
+ if (err != err_status_ok) {
+ LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
+ return false;
+ }
+
+ inited_ = true;
+ }
+
+ return true;
+}
+
+void SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
+ // TODO: Do something about events.
+}
+
+void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
+ for (std::list<SrtpSession*>::iterator it = sessions_.begin();
+ it != sessions_.end(); ++it) {
+ if ((*it)->session_ == ev->session) {
+ (*it)->HandleEvent(ev);
+ break;
+ }
+ }
+}
+
+#else // !HAVE_SRTP
+
+namespace {
+bool SrtpNotAvailable(const char *func) {
+ LOG(LS_ERROR) << func << ": SRTP is not available on your system.";
+ return false;
+}
+} // anonymous namespace
+
+SrtpSession::SrtpSession() {
+ LOG(WARNING) << "SRTP implementation is missing.";
+}
+
+SrtpSession::~SrtpSession() {
+}
+
+bool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
+ return SrtpNotAvailable(__FUNCTION__);
+}
+
+bool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
+ return SrtpNotAvailable(__FUNCTION__);
+}
+
+bool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
+ int* out_len) {
+ return SrtpNotAvailable(__FUNCTION__);
+}
+
+bool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
+ int* out_len) {
+ return SrtpNotAvailable(__FUNCTION__);
+}
+
+bool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
+ return SrtpNotAvailable(__FUNCTION__);
+}
+
+bool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
+ return SrtpNotAvailable(__FUNCTION__);
+}
+
+#endif // HAVE_SRTP
+} // namespace cricket
diff --git a/talk/session/phone/srtpfilter.h b/talk/session/phone/srtpfilter.h
new file mode 100644
index 0000000..71b74e0
--- /dev/null
+++ b/talk/session/phone/srtpfilter.h
@@ -0,0 +1,145 @@
+/*
+ * libjingle
+ * Copyright 2009, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_SESSION_PHONE_SRTPFILTER_H_
+#define TALK_SESSION_PHONE_SRTPFILTER_H_
+
+#include <list>
+#include <string>
+#include <vector>
+#include "talk/base/basictypes.h"
+#include "talk/session/phone/cryptoparams.h"
+#include "talk/p2p/base/sessiondescription.h"
+
+// Forward declaration to avoid pulling in libsrtp headers here
+struct srtp_event_data_t;
+struct srtp_ctx_t;
+typedef srtp_ctx_t* srtp_t;
+struct srtp_policy_t;
+
+namespace cricket {
+
+// Cipher suite to use for SRTP. Typically a 80-bit HMAC will be used, except
+// in applications (voice) where the additional bandwidth may be significant.
+// A 80-bit HMAC is always used for SRTCP.
+extern const std::string& CS_DEFAULT;
+// 128-bit AES with 80-bit SHA-1 HMAC.
+extern const std::string CS_AES_CM_128_HMAC_SHA1_80;
+// 128-bit AES with 32-bit SHA-1 HMAC.
+extern const std::string CS_AES_CM_128_HMAC_SHA1_32;
+
+// Class that wraps a libSRTP session. Used internally by SrtpFilter, below.
+class SrtpSession {
+ public:
+ SrtpSession();
+ ~SrtpSession();
+
+ // Configures the session for sending data using the specified
+ // cipher-suite and key. Receiving must be done by a separate session.
+ bool SetSend(const std::string& cs, const uint8* key, int len);
+ // Configures the session for receiving data using the specified
+ // cipher-suite and key. Sending must be done by a separate session.
+ bool SetRecv(const std::string& cs, const uint8* key, int len);
+
+ // Encrypts/signs an individual RTP/RTCP packet, in-place.
+ // If an HMAC is used, this will increase the packet size.
+ bool ProtectRtp(void* data, int in_len, int max_len, int* out_len);
+ bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len);
+ // Decrypts/verifies an invidiual RTP/RTCP packet.
+ // If an HMAC is used, this will decrease the packet size.
+ bool UnprotectRtp(void* data, int in_len, int* out_len);
+ bool UnprotectRtcp(void* data, int in_len, int* out_len);
+
+ private:
+ bool SetKey(int type, const std::string& cs, const uint8* key, int len);
+ static bool Init();
+ void HandleEvent(const srtp_event_data_t* ev);
+ static void HandleEventThunk(srtp_event_data_t* ev);
+
+ srtp_t session_;
+ int rtp_auth_tag_len_;
+ int rtcp_auth_tag_len_;
+ static bool inited_;
+ static std::list<SrtpSession*> sessions_;
+};
+
+// Class to transform SRTP to/from RTP.
+// Initialize by calling SetSend with the local security params, then call
+// SetRecv once the remote security params are received. At that point
+// Protect/UnprotectRt(c)p can be called to encrypt/decrypt data.
+// TODO: Figure out concurrency policy for SrtpFilter.
+class SrtpFilter {
+ public:
+ SrtpFilter();
+ ~SrtpFilter();
+
+ // Whether the filter is active (i.e. crypto has been properly negotiated).
+ bool IsActive() const;
+
+ // Indicates which crypto algorithms and keys were contained in the offer.
+ // offer_params should contain a list of available parameters to use, or none,
+ // if crypto is not desired. This must be called before SetAnswer.
+ bool SetOffer(const std::vector<CryptoParams>& offer_params,
+ ContentSource source);
+ // Indicates which crypto algorithms and keys were contained in the answer.
+ // answer_params should contain the negotiated parameters, which may be none,
+ // if crypto was not desired or could not be negotiated (and not required).
+ // This must be called after SetOffer. If crypto negotiation completes
+ // successfully, this will advance the filter to the active state.
+ bool SetAnswer(const std::vector<CryptoParams>& answer_params,
+ ContentSource source);
+
+ // Encrypts/signs an individual RTP/RTCP packet, in-place.
+ // If an HMAC is used, this will increase the packet size.
+ bool ProtectRtp(void* data, int in_len, int max_len, int* out_len);
+ bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len);
+ // Decrypts/verifies an invidiual RTP/RTCP packet.
+ // If an HMAC is used, this will decrease the packet size.
+ bool UnprotectRtp(void* data, int in_len, int* out_len);
+ bool UnprotectRtcp(void* data, int in_len, int* out_len);
+
+ protected:
+ bool StoreParams(const std::vector<CryptoParams>& offer_params,
+ ContentSource source);
+ bool NegotiateParams(const std::vector<CryptoParams>& answer_params,
+ CryptoParams* selected_params);
+ bool ApplyParams(const CryptoParams& send_params,
+ const CryptoParams& recv_params);
+ bool ResetParams();
+ static bool ParseKeyParams(const std::string& params, uint8* key, int len);
+
+ private:
+ enum State { ST_INIT, ST_SENTOFFER, ST_RECEIVEDOFFER, ST_ACTIVE };
+ State state_;
+ std::vector<CryptoParams> offer_params_;
+ SrtpSession send_session_;
+ SrtpSession recv_session_;
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_SRTPFILTER_H_
diff --git a/talk/session/phone/testdata/video.rtpdump b/talk/session/phone/testdata/video.rtpdump
new file mode 100644
index 0000000..3b0139b
--- /dev/null
+++ b/talk/session/phone/testdata/video.rtpdump
Binary files differ
diff --git a/talk/session/phone/testdata/voice.rtpdump b/talk/session/phone/testdata/voice.rtpdump
new file mode 100644
index 0000000..5920d1d
--- /dev/null
+++ b/talk/session/phone/testdata/voice.rtpdump
Binary files differ
diff --git a/talk/session/phone/v4llookup.cc b/talk/session/phone/v4llookup.cc
new file mode 100644
index 0000000..e8436e1
--- /dev/null
+++ b/talk/session/phone/v4llookup.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009, Google Inc.
+ * Author: lexnikitin@google.com (Alexey Nikitin)
+ *
+ * V4LLookup provides basic functionality to work with V2L2 devices in Linux
+ * The functionality is implemented as a class with virtual methods for
+ * the purpose of unit testing.
+ */
+#include "talk/session/phone/v4llookup.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <cstring>
+
+#include "talk/base/logging.h"
+
+namespace cricket {
+
+V4LLookup *V4LLookup::v4l_lookup_ = new V4LLookup();
+
+bool V4LLookup::CheckIsV4L2Device(const std::string& device_path) {
+ // check device major/minor numbers are in the range for video devices.
+ struct stat s;
+
+ if (lstat(device_path.c_str(), &s) != 0 || !S_ISCHR(s.st_mode)) return false;
+
+ int video_fd = -1;
+ bool is_v4l2 = false;
+
+ // check major/minur device numbers are in range for video device
+ if (major(s.st_rdev) == 81) {
+ dev_t num = minor(s.st_rdev);
+ if (num <= 63 && num >= 0) {
+ video_fd = ::open(device_path.c_str(), O_RDONLY | O_NONBLOCK);
+ if ((video_fd >= 0) || (errno == EBUSY)) {
+ ::v4l2_capability video_caps;
+ memset(&video_caps, 0, sizeof(video_caps));
+
+ if ((errno == EBUSY) ||
+ (::ioctl(video_fd, VIDIOC_QUERYCAP, &video_caps) >= 0 &&
+ (video_caps.capabilities & V4L2_CAP_VIDEO_CAPTURE))) {
+ LOG(LS_INFO) << "Found V4L2 capture device " << device_path;
+
+ is_v4l2 = true;
+ } else {
+ LOG(LS_ERROR) << "VIDIOC_QUERYCAP failed for " << device_path;
+ }
+ } else {
+ LOG(LS_ERROR) << "Failed to open " << device_path;
+ }
+ }
+ }
+
+ if (video_fd >= 0)
+ ::close(video_fd);
+
+ return is_v4l2;
+}
+
+}; // namespace cricket
diff --git a/talk/session/phone/v4llookup.h b/talk/session/phone/v4llookup.h
new file mode 100644
index 0000000..1150172
--- /dev/null
+++ b/talk/session/phone/v4llookup.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2009, Google Inc.
+ * Author: lexnikitin@google.com (Alexey Nikitin)
+ *
+ * V4LLookup provides basic functionality to work with V2L2 devices in Linux
+ * The functionality is implemented as a class with virtual methods for
+ * the purpose of unit testing.
+ */
+#ifndef TALK_SESSION_PHONE_V4LLOOKUP_H_
+#define TALK_SESSION_PHONE_V4LLOOKUP_H_
+
+#include <string>
+
+#ifdef LINUX
+namespace cricket {
+class V4LLookup {
+ public:
+ virtual ~V4LLookup() {}
+
+ static bool IsV4L2Device(const std::string& device_path) {
+ return GetV4LLookup()->CheckIsV4L2Device(device_path);
+ }
+
+ static void SetV4LLookup(V4LLookup* v4l_lookup) {
+ v4l_lookup_ = v4l_lookup;
+ }
+
+ static V4LLookup* GetV4LLookup() {
+ return v4l_lookup_;
+ }
+
+ protected:
+ static V4LLookup* v4l_lookup_;
+ // Making virtual so it is easier to mock
+ virtual bool CheckIsV4L2Device(const std::string& device_path);
+
+};
+} // namespace cricket
+#endif
+#endif // TALK_SESSION_PHONE_V4LLOOKUP_H_
diff --git a/talk/session/phone/videocommon.h b/talk/session/phone/videocommon.h
new file mode 100644
index 0000000..1092b5c
--- /dev/null
+++ b/talk/session/phone/videocommon.h
@@ -0,0 +1,161 @@
+// libjingle
+// Copyright 2004--2005, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Common definition for video, including fourcc and VideoFormat
+
+#ifndef TALK_SESSION_PHONE_VIDEOCOMMON_H_
+#define TALK_SESSION_PHONE_VIDEOCOMMON_H_
+
+#include <string>
+
+#include "talk/base/basictypes.h"
+
+namespace cricket {
+
+//////////////////////////////////////////////////////////////////////////////
+// Definition of fourcc.
+//////////////////////////////////////////////////////////////////////////////
+// Convert four characters to a fourcc code.
+// Needs to be a macro otherwise the OS X compiler complains when the kFormat*
+// constants are used in a switch.
+#define FOURCC(a, b, c, d) (\
+ (static_cast<uint32>(a)) | (static_cast<uint32>(b) << 8) | \
+ (static_cast<uint32>(c) << 16) | (static_cast<uint32>(d) << 24))
+
+// Get the name, that is, string with four characters, of a fourcc code.
+inline std::string GetFourccName(uint32 fourcc) {
+ std::string name;
+ name.push_back(static_cast<char>(fourcc & 0xFF));
+ name.push_back(static_cast<char>((fourcc >> 8) & 0xFF));
+ name.push_back(static_cast<char>((fourcc >> 16) & 0xFF));
+ name.push_back(static_cast<char>((fourcc >> 24) & 0xFF));
+ return name;
+}
+
+// FourCC codes used in Google Talk.
+// Some good pages discussing FourCC codes:
+// http://developer.apple.com/quicktime/icefloe/dispatch020.html
+// http://www.fourcc.org/yuv.php
+enum {
+ FOURCC_I420 = FOURCC('I', '4', '2', '0'),
+ FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420
+ FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Alias for I420
+ FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
+ FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
+ FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'),
+ FOURCC_24BG = FOURCC('2', '4', 'B', 'G'),
+ FOURCC_RGB1 = FOURCC('R', 'G', 'B', '1'),
+ FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'),
+ FOURCC_RGB2 = FOURCC('R', 'G', 'B', '2'),
+ FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
+ FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'),
+ FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'),
+ FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'),
+ FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY
+ FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2
+ FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2
+ FOURCC_RAW = FOURCC('r', 'a', 'w', ' '),
+ // Next five are Bayer RGB formats. The four characters define the order of
+ // the colours in each 2x2 pixel grid, going left-to-right and top-to-bottom.
+ FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'),
+ FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'),
+ FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'),
+ FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'),
+ FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR
+ FOURCC_ANY = 0xFFFFFFFF, // Match any fourcc.
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Definition of VideoFormat.
+//////////////////////////////////////////////////////////////////////////////
+
+static const int64 kNumNanosecsPerSec = 1000000000;
+
+struct VideoFormat {
+ static const int64 kMinimumInterval = kNumNanosecsPerSec / 10000; // 10k fps
+
+ VideoFormat() : width(0), height(0), interval(0), fourcc(0) {}
+
+ VideoFormat(int w, int h, int64 interval_ns, uint32 cc)
+ : width(w),
+ height(h),
+ interval(interval_ns),
+ fourcc(cc) {
+ }
+
+ VideoFormat(const VideoFormat& format)
+ : width(format.width),
+ height(format.height),
+ interval(format.interval),
+ fourcc(format.fourcc) {
+ }
+
+ static int64 FpsToInterval(int fps) {
+ return fps ? kNumNanosecsPerSec / fps : kMinimumInterval;
+ }
+
+ static int IntervalToFps(int64 interval) {
+ // Normalize the interval first.
+ interval = talk_base::_max(interval, kMinimumInterval);
+ return static_cast<int>(kNumNanosecsPerSec / interval);
+ }
+
+ bool operator==(const VideoFormat& format) const {
+ return width == format.width && height == format.height &&
+ interval == format.interval && fourcc == format.fourcc;
+ }
+
+ bool operator!=(const VideoFormat& format) const {
+ return !(*this == format);
+ }
+
+ bool operator<(const VideoFormat& format) const {
+ return (fourcc < format.fourcc) ||
+ (fourcc == format.fourcc && width < format.width) ||
+ (fourcc == format.fourcc && width == format.width &&
+ height < format.height) ||
+ (fourcc == format.fourcc && width == format.width &&
+ height == format.height && interval > format.interval);
+ }
+
+ int framerate() const { return IntervalToFps(interval); }
+
+ int width; // in number of pixels
+ int height; // in number of pixels
+ int64 interval; // in nanoseconds
+ uint32 fourcc; // color space. FOURCC_ANY means that any color space is OK.
+};
+
+// Result of video capturer start.
+enum CaptureResult {
+ CR_SUCCESS, // The capturer starts successfully.
+ CR_PENDING, // The capturer is pending to start the capture device.
+ CR_FAILURE, // The capturer fails to start.
+ CR_NO_DEVICE, // The capturer has no device and fails to start.
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_PHONE_VIDEOCOMMON_H_
diff --git a/talk/session/phone/voicechannel.cc b/talk/session/phone/voicechannel.cc
deleted file mode 100755
index 58b8760..0000000
--- a/talk/session/phone/voicechannel.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "talk/session/phone/voicechannel.h"
-#include "talk/base/common.h"
-#include "talk/base/logging.h"
-#include "talk/p2p/base/transportchannel.h"
-#include "talk/session/phone/channelmanager.h"
-#include "talk/session/phone/phonesessionclient.h"
-#include <cassert>
-#undef SetPort
-
-namespace cricket {
-
-
-VoiceChannel::VoiceChannel(ChannelManager *manager, Session *session,
- MediaChannel *channel) {
- channel_manager_ = manager;
- assert(channel_manager_->worker_thread() == talk_base::Thread::Current());
- media_channel_ = channel;
- session_ = session;
- socket_monitor_ = NULL;
- audio_monitor_ = NULL;
- transport_channel_ = session_->CreateChannel("rtp");
- transport_channel_->SignalWritableState.connect(
- this, &VoiceChannel::OnWritableState);
- transport_channel_->SignalReadPacket.connect(
- this, &VoiceChannel::OnChannelRead);
- media_channel_->SetInterface(this);
- enabled_ = false;
- paused_ = false;
- writable_ = false;
- muted_ = false;
- LOG(INFO) << "Created voice channel";
-
- session->SignalState.connect(this, &VoiceChannel::OnSessionState);
- OnSessionState(session, session->state());
-}
-
-VoiceChannel::~VoiceChannel() {
- assert(channel_manager_->worker_thread() == talk_base::Thread::Current());
- enabled_ = false;
- ChangeState();
- delete socket_monitor_;
- delete audio_monitor_;
- talk_base::Thread::Current()->Clear(this);
- if (transport_channel_ != NULL)
- session_->DestroyChannel(transport_channel_);
- LOG(INFO) << "Destroyed voice channel";
-}
-
-void VoiceChannel::OnMessage(talk_base::Message *pmsg) {
- switch (pmsg->message_id) {
- case MSG_ENABLE:
- EnableMedia_w();
- break;
-
- case MSG_DISABLE:
- DisableMedia_w();
- break;
-
- case MSG_MUTE:
- MuteMedia_w();
- break;
-
- case MSG_UNMUTE:
- UnmuteMedia_w();
- break;
-
- case MSG_SETSENDCODEC:
- SetSendCodec_w();
- break;
- }
-}
-
-void VoiceChannel::Enable(bool enable) {
- // Can be called from thread other than worker thread
- channel_manager_->worker_thread()->Post(this,
- enable ? MSG_ENABLE : MSG_DISABLE);
-}
-
-void VoiceChannel::Mute(bool mute) {
- // Can be called from thread other than worker thread
- channel_manager_->worker_thread()->Post(this, mute ? MSG_MUTE : MSG_UNMUTE);
-}
-
-
-MediaChannel * VoiceChannel::channel() {
- return media_channel_;
-}
-
-void VoiceChannel::OnSessionState(Session* session, Session::State state) {
- if ((state == Session::STATE_RECEIVEDACCEPT) ||
- (state == Session::STATE_RECEIVEDINITIATE)) {
- channel_manager_->worker_thread()->Post(this, MSG_SETSENDCODEC);
- }
-}
-
-void VoiceChannel::SetSendCodec_w() {
- assert(channel_manager_->worker_thread() == talk_base::Thread::Current());
-
- const PhoneSessionDescription* desc =
- static_cast<const PhoneSessionDescription*>(
- session()->remote_description());
-
- media_channel_->SetCodecs(desc->codecs());
-}
-
-void VoiceChannel::OnWritableState(TransportChannel* channel) {
- ASSERT(channel == transport_channel_);
- if (transport_channel_->writable()) {
- ChannelWritable_w();
- } else {
- ChannelNotWritable_w();
- }
-}
-
-void VoiceChannel::OnChannelRead(TransportChannel* channel,
- const char* data,
- size_t len) {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
- media_channel_->OnPacketReceived(data, (int)len);
-}
-
-void VoiceChannel::SendPacket(const void *data, size_t len) {
- // SendPacket gets called from MediaEngine; send to socket
- // MediaEngine will call us on a random thread. The Send operation on the
- // socket is special in that it can handle this.
- transport_channel_->SendPacket(static_cast<const char *>(data), len);
-}
-
-void VoiceChannel::ChangeState() {
- if (paused_ || !enabled_ || !writable_) {
- media_channel_->SetPlayout(false);
- media_channel_->SetSend(false);
- } else {
- if (muted_) {
- media_channel_->SetSend(false);
- media_channel_->SetPlayout(true);
- } else {
- media_channel_->SetSend(true);
- media_channel_->SetPlayout(true);
- }
- }
-}
-
-void VoiceChannel::PauseMedia_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- ASSERT(!paused_);
-
- LOG(INFO) << "Voice channel paused";
- paused_ = true;
- ChangeState();
-}
-
-void VoiceChannel::UnpauseMedia_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- ASSERT(paused_);
-
- LOG(INFO) << "Voice channel unpaused";
- paused_ = false;
- ChangeState();
-}
-
-void VoiceChannel::EnableMedia_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- if (enabled_)
- return;
-
- LOG(INFO) << "Voice channel enabled";
- enabled_ = true;
- ChangeState();
-}
-
-void VoiceChannel::DisableMedia_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- if (!enabled_)
- return;
-
- LOG(INFO) << "Voice channel disabled";
- enabled_ = false;
- ChangeState();
-}
-
-void VoiceChannel::MuteMedia_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- if (muted_)
- return;
-
- LOG(INFO) << "Voice channel muted";
- muted_ = true;
- ChangeState();
-}
-
-void VoiceChannel::UnmuteMedia_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- if (!muted_)
- return;
-
- LOG(INFO) << "Voice channel unmuted";
- muted_ = false;
- ChangeState();
-}
-
-void VoiceChannel::ChannelWritable_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- if (writable_)
- return;
-
- LOG(INFO) << "Voice channel socket writable";
- writable_ = true;
- ChangeState();
-}
-
-void VoiceChannel::ChannelNotWritable_w() {
- ASSERT(channel_manager_->worker_thread() == talk_base::Thread::Current());
- if (!writable_)
- return;
-
- LOG(INFO) << "Voice channel socket not writable";
- writable_ = false;
- ChangeState();
-}
-
-
-void VoiceChannel::StartConnectionMonitor(int cms) {
- delete socket_monitor_;
- socket_monitor_ =
- new SocketMonitor(session_, transport_channel_,
- talk_base::Thread::Current());
- socket_monitor_->SignalUpdate.connect(
- this, &VoiceChannel::OnConnectionMonitorUpdate);
- socket_monitor_->Start(cms);
-}
-
-void VoiceChannel::StopConnectionMonitor() {
- if (socket_monitor_ != NULL) {
- socket_monitor_->Stop();
- socket_monitor_->SignalUpdate.disconnect(this);
- delete socket_monitor_;
- socket_monitor_ = NULL;
- }
-}
-
-void VoiceChannel::OnConnectionMonitorUpdate(
- SocketMonitor *monitor, const std::vector<ConnectionInfo> &infos) {
- SignalConnectionMonitor(this, infos);
-}
-
-void VoiceChannel::StartAudioMonitor(int cms) {
- delete audio_monitor_;
- audio_monitor_ = new AudioMonitor(this, talk_base::Thread::Current());
- audio_monitor_
- ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
- audio_monitor_->Start(cms);
-}
-
-void VoiceChannel::StopAudioMonitor() {
- if (audio_monitor_ != NULL) {
- audio_monitor_ ->Stop();
- audio_monitor_ ->SignalUpdate.disconnect(this);
- delete audio_monitor_ ;
- audio_monitor_ = NULL;
- }
-}
-
-void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor *monitor,
- const AudioInfo& info) {
- SignalAudioMonitor(this, info);
-}
-
-void VoiceChannel::StartMediaMonitor(int cms) {
- media_channel_
- ->SignalMediaMonitor.connect(this, &VoiceChannel::OnMediaMonitorUpdate);
- media_channel_->StartMediaMonitor(this, cms);
-}
-
-void VoiceChannel::StopMediaMonitor() {
- media_channel_->SignalMediaMonitor.disconnect(this);
- media_channel_->StopMediaMonitor();
-}
-
-void VoiceChannel::OnMediaMonitorUpdate(
- MediaChannel *media_channel, const MediaInfo &info) {
- ASSERT(media_channel == media_channel_);
- SignalMediaMonitor(this, info);
-}
-
-Session *VoiceChannel::session() {
- return session_;
-}
-
-int VoiceChannel::GetInputLevel_w() {
- return channel_manager_->media_engine()->GetInputLevel();
-}
-
-int VoiceChannel::GetOutputLevel_w() {
- return media_channel_->GetOutputLevel();
-}
-
-talk_base::Thread* VoiceChannel::worker_thread() {
- return channel_manager_->worker_thread();
-}
-
-}
diff --git a/talk/session/phone/voicechannel.h b/talk/session/phone/voicechannel.h
old mode 100755
new mode 100644
index 3d0be12..95de637
--- a/talk/session/phone/voicechannel.h
+++ b/talk/session/phone/voicechannel.h
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004--2007, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -28,110 +28,6 @@
#ifndef _VOICECHANNEL_H_
#define _VOICECHANNEL_H_
-#include "talk/base/asyncudpsocket.h"
-#include "talk/base/network.h"
-#include "talk/base/sigslot.h"
-#include "talk/p2p/client/socketmonitor.h"
-#include "talk/p2p/base/session.h"
-#include "talk/session/phone/audiomonitor.h"
-#include "talk/session/phone/mediaengine.h"
-#include "talk/session/phone/mediachannel.h"
-
-namespace cricket {
-
-const uint32 MSG_ENABLE = 1;
-const uint32 MSG_DISABLE = 2;
-const uint32 MSG_MUTE = 3;
-const uint32 MSG_UNMUTE = 4;
-const uint32 MSG_SETSENDCODEC = 5;
-
-
-class ChannelManager;
-
-class VoiceChannel
- : public talk_base::MessageHandler, public sigslot::has_slots<>,
- public MediaChannel::NetworkInterface {
- public:
- VoiceChannel(ChannelManager *manager, Session *session,
- MediaChannel *channel);
- ~VoiceChannel();
-
- void Enable(bool enable);
- void Mute(bool mute);
-
-
- MediaChannel *channel();
- Session *session();
-
- // Monitoring
-
- void StartConnectionMonitor(int cms);
- void StopConnectionMonitor();
- sigslot::signal2<VoiceChannel *, const std::vector<ConnectionInfo> &>
- SignalConnectionMonitor;
-
- void StartAudioMonitor(int cms);
- void StopAudioMonitor();
- sigslot::signal2<VoiceChannel *, const AudioInfo&> SignalAudioMonitor;
- talk_base::Thread* worker_thread();
-
- void StartMediaMonitor(int cms);
- void StopMediaMonitor();
- sigslot::signal2<VoiceChannel *, const MediaInfo&> SignalMediaMonitor;
-
- // Pausing so that the ChannelManager can change the audio devices. These
- // should only be called from the worker thread
- void PauseMedia_w();
- void UnpauseMedia_w();
-
- int GetInputLevel_w();
- int GetOutputLevel_w();
-
- // MediaEngine calls this
- virtual void SendPacket(const void *data, size_t len);
-
-private:
- void ChangeState();
- void EnableMedia_w();
- void DisableMedia_w();
- void MuteMedia_w();
- void UnmuteMedia_w();
- void ChannelWritable_w();
- void ChannelNotWritable_w();
-
-
- void OnConnectionMonitorUpdate(SocketMonitor *monitor,
- const std::vector<ConnectionInfo> &infos);
- void OnAudioMonitorUpdate(AudioMonitor *monitor, const AudioInfo& info);
- void OnMediaMonitorUpdate(MediaChannel *media_channel,
- const MediaInfo& info);
-
- // From MessageHandler
-
- void OnMessage(talk_base::Message *pmsg);
-
- // Setting the send codec based on the remote description.
- void OnSessionState(Session* session, Session::State state);
- void SetSendCodec_w();
-
- // From TransportChannel
-
- void OnWritableState(TransportChannel* channel);
- void OnChannelRead(TransportChannel* channel, const char *data, size_t len);
-
-
- bool enabled_;
- bool paused_;
- bool writable_;
- bool muted_;
- MediaChannel *media_channel_;
- Session *session_;
- TransportChannel *transport_channel_;
- ChannelManager *channel_manager_;
- SocketMonitor *socket_monitor_;
- AudioMonitor *audio_monitor_;
-};
-
-}
+#include "talk/session/phone/channel.h"
#endif // _VOICECHANNEL_H_
diff --git a/talk/session/tunnel/Makefile.am b/talk/session/tunnel/Makefile.am
deleted file mode 100755
index 3a8d244..0000000
--- a/talk/session/tunnel/Makefile.am
+++ /dev/null
@@ -1,7 +0,0 @@
-libcricketsessiontunnel_la_SOURCES = tunnelsessionclient.cc \
- pseudotcpchannel.cc
-noinst_HEADERS = tunnelsessionclient.h \
- pseudotcpchannel.h
-noinst_LTLIBRARIES = libcricketsessiontunnel.la
-
-AM_CXXFLAGS = -DPOSIX
diff --git a/talk/session/tunnel/pseudotcpchannel.cc b/talk/session/tunnel/pseudotcpchannel.cc
old mode 100755
new mode 100644
index 54515c0..0448853
--- a/talk/session/tunnel/pseudotcpchannel.cc
+++ b/talk/session/tunnel/pseudotcpchannel.cc
@@ -2,32 +2,34 @@
* libjingle
* Copyright 2004--2006, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <string>
#include "talk/base/basictypes.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/base/stringutils.h"
#include "talk/p2p/base/transportchannel.h"
#include "pseudotcpchannel.h"
@@ -71,10 +73,6 @@
size_t* written, int* error);
virtual void Close();
- virtual bool GetSize(size_t* size) const { return false; }
- virtual bool ReserveSize(size_t size) { return true; }
- virtual bool Rewind() { return false; }
-
private:
// parent_ is accessed and modified exclusively on the event thread, to
// avoid thread contention. This means that the PseudoTcpChannel cannot go
@@ -108,6 +106,7 @@
stream_readable_(false), pending_read_event_(false),
ready_to_connect_(false) {
ASSERT(signal_thread_->IsCurrent());
+ ASSERT(NULL != session_);
}
PseudoTcpChannel::~PseudoTcpChannel() {
@@ -119,7 +118,8 @@
ASSERT(tcp_ == NULL);
}
-bool PseudoTcpChannel::Connect(const std::string& channel_name) {
+bool PseudoTcpChannel::Connect(const std::string& content_name,
+ const std::string& channel_name) {
ASSERT(signal_thread_->IsCurrent());
CritScope lock(&cs_);
@@ -128,7 +128,8 @@
ASSERT(session_ != NULL);
worker_thread_ = session_->session_manager()->worker_thread();
- channel_ = session_->CreateChannel(channel_name);
+ content_name_ = content_name;
+ channel_ = session_->CreateChannel(content_name, channel_name);
channel_name_ = channel_name;
channel_->SetOption(Socket::OPT_DONTFRAGMENT, 1);
@@ -182,6 +183,21 @@
tcp_->Close(true);
AdjustClock();
}
+ SignalChannelClosed(this);
+}
+
+void PseudoTcpChannel::OnSessionTerminate(Session* session) {
+ // When the session terminates before we even connected
+ CritScope lock(&cs_);
+ if (session_ != NULL && channel_ == NULL) {
+ ASSERT(session == session_);
+ ASSERT(worker_thread_ == NULL);
+ ASSERT(tcp_ == NULL);
+ LOG(LS_INFO) << "Destroying unconnected PseudoTcpChannel";
+ session_ = NULL;
+ if (stream_ != NULL)
+ stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, -1));
+ }
}
//
@@ -191,6 +207,8 @@
StreamState PseudoTcpChannel::GetState() const {
ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
CritScope lock(&cs_);
+ if (!session_)
+ return SS_CLOSED;
if (!tcp_)
return SS_OPENING;
switch (tcp_->State()) {
@@ -234,7 +252,7 @@
*error = tcp_->GetError();
return SR_ERROR;
}
- AdjustClock();
+ // This spot is never reached.
}
StreamResult PseudoTcpChannel::Write(const void* data, size_t data_len,
@@ -256,7 +274,7 @@
*error = tcp_->GetError();
return SR_ERROR;
}
- AdjustClock();
+ // This spot is never reached.
}
void PseudoTcpChannel::Close() {
@@ -331,19 +349,18 @@
return;
}
- scoped_ptr<Socket> mtu_socket(
- worker_thread_->socketserver()
- ->CreateSocket(SOCK_DGRAM));
-
- uint16 mtu = 65535;
- if (mtu_socket->Connect(addr) < 0) {
- LOG_F(LS_ERROR) << "Socket::Connect: " << mtu_socket->GetError();
- } else if (mtu_socket->EstimateMTU(&mtu) < 0) {
- LOG_F(LS_ERROR) << "Socket::EstimateMTU: " << mtu_socket->GetError();
- } else {
- tcp_->NotifyMTU(mtu);
- AdjustClock();
+ uint16 mtu = 1280; // safe default
+ talk_base::scoped_ptr<Socket> mtu_socket(
+ worker_thread_->socketserver()->CreateSocket(SOCK_DGRAM));
+ if (mtu_socket->Connect(addr) < 0 ||
+ mtu_socket->EstimateMTU(&mtu) < 0) {
+ LOG_F(LS_WARNING) << "Failed to estimate MTU, error="
+ << mtu_socket->GetError();
}
+
+ LOG_F(LS_VERBOSE) << "Using MTU of " << mtu << " bytes";
+ tcp_->NotifyMTU(mtu);
+ AdjustClock();
}
void PseudoTcpChannel::OnTcpOpen(PseudoTcp* tcp) {
@@ -437,7 +454,7 @@
LOG_F(LS_INFO) << "(MSG_SI_DESTROYCHANNEL)";
ASSERT(session_ != NULL);
ASSERT(channel_ != NULL);
- session_->DestroyChannel(channel_);
+ session_->DestroyChannel(content_name_, channel_->name());
} else if (pmsg->message_id == MSG_SI_DESTROY) {
@@ -545,7 +562,7 @@
void PseudoTcpChannel::InternalStream::Close() {
if (!parent_)
return;
- parent_->Close();
+ parent_->Close();
parent_ = NULL;
}
diff --git a/talk/session/tunnel/pseudotcpchannel.h b/talk/session/tunnel/pseudotcpchannel.h
old mode 100755
new mode 100644
index 27574ea..fbcb611
--- a/talk/session/tunnel/pseudotcpchannel.h
+++ b/talk/session/tunnel/pseudotcpchannel.h
@@ -66,11 +66,14 @@
PseudoTcpChannel(talk_base::Thread* stream_thread,
Session* session);
- bool Connect(const std::string& channel_name);
+ bool Connect(const std::string& content_name,
+ const std::string& channel_name);
talk_base::StreamInterface* GetStream();
sigslot::signal1<PseudoTcpChannel*> SignalChannelClosed;
+ void OnSessionTerminate(Session* session);
+
private:
class InternalStream;
friend class InternalStream;
@@ -110,6 +113,7 @@
talk_base::Thread* signal_thread_, * worker_thread_, * stream_thread_;
Session* session_;
TransportChannel* channel_;
+ std::string content_name_;
std::string channel_name_;
PseudoTcp* tcp_;
InternalStream* stream_;
diff --git a/talk/session/tunnel/securetunnelsessionclient.cc b/talk/session/tunnel/securetunnelsessionclient.cc
new file mode 100644
index 0000000..84ec5e0
--- /dev/null
+++ b/talk/session/tunnel/securetunnelsessionclient.cc
@@ -0,0 +1,382 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// SecureTunnelSessionClient and SecureTunnelSession implementation.
+
+#include "talk/session/tunnel/securetunnelsessionclient.h"
+#include "talk/base/basicdefs.h"
+#include "talk/base/basictypes.h"
+#include "talk/base/common.h"
+#include "talk/base/helpers.h"
+#include "talk/base/logging.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/sslidentity.h"
+#include "talk/base/sslstreamadapter.h"
+#include "talk/p2p/base/transportchannel.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/session/tunnel/pseudotcpchannel.h"
+
+namespace cricket {
+
+// XML elements and namespaces for XMPP stanzas used in content exchanges.
+
+const std::string NS_SECURE_TUNNEL("http://www.google.com/talk/securetunnel");
+const buzz::QName QN_SECURE_TUNNEL_DESCRIPTION(NS_SECURE_TUNNEL,
+ "description");
+const buzz::QName QN_SECURE_TUNNEL_TYPE(NS_SECURE_TUNNEL, "type");
+const buzz::QName QN_SECURE_TUNNEL_CLIENT_CERT(NS_SECURE_TUNNEL,
+ "client-cert");
+const buzz::QName QN_SECURE_TUNNEL_SERVER_CERT(NS_SECURE_TUNNEL,
+ "server-cert");
+const std::string CN_SECURE_TUNNEL("securetunnel");
+
+// SecureTunnelContentDescription
+
+// TunnelContentDescription is extended to hold string forms of the
+// client and server certificate, PEM encoded.
+
+struct SecureTunnelContentDescription : public ContentDescription {
+ std::string description;
+ std::string client_pem_certificate;
+ std::string server_pem_certificate;
+
+ SecureTunnelContentDescription(const std::string& desc,
+ const std::string& client_pem_cert,
+ const std::string& server_pem_cert)
+ : description(desc),
+ client_pem_certificate(client_pem_cert),
+ server_pem_certificate(server_pem_cert) {
+ }
+};
+
+// SecureTunnelSessionClient
+
+SecureTunnelSessionClient::SecureTunnelSessionClient(
+ const buzz::Jid& jid, SessionManager* manager)
+ : TunnelSessionClient(jid, manager, NS_SECURE_TUNNEL) {
+}
+
+void SecureTunnelSessionClient::SetIdentity(talk_base::SSLIdentity* identity) {
+ ASSERT(identity_.get() == NULL);
+ identity_.reset(identity);
+}
+
+bool SecureTunnelSessionClient::GenerateIdentity() {
+ ASSERT(identity_.get() == NULL);
+ identity_.reset(talk_base::SSLIdentity::Generate(
+ // The name on the certificate does not matter: the peer will
+ // make sure the cert it gets during SSL negotiation matches the
+ // one it got from XMPP. It would be neat to put something
+ // recognizable in there such as the JID, except this will show
+ // in clear during the SSL negotiation and so it could be a
+ // privacy issue. Specifying an empty string here causes
+ // it to use a random string.
+#ifdef _DEBUG
+ jid().Str()
+#else
+ ""
+#endif
+ ));
+ if (identity_.get() == NULL) {
+ LOG(LS_ERROR) << "Failed to generate SSL identity";
+ return false;
+ }
+ return true;
+}
+
+talk_base::SSLIdentity& SecureTunnelSessionClient::GetIdentity() const {
+ ASSERT(identity_.get() != NULL);
+ return *identity_;
+}
+
+// Parses a certificate from a PEM encoded string.
+// Returns NULL on failure.
+// The caller is responsible for freeing the returned object.
+static talk_base::SSLCertificate* ParseCertificate(
+ const std::string& pem_cert) {
+ if (pem_cert.empty())
+ return NULL;
+ return talk_base::SSLCertificate::FromPEMString(pem_cert, NULL);
+}
+
+TunnelSession* SecureTunnelSessionClient::MakeTunnelSession(
+ Session* session, talk_base::Thread* stream_thread,
+ TunnelSessionRole role) {
+ return new SecureTunnelSession(this, session, stream_thread, role);
+}
+
+bool FindSecureTunnelContent(const cricket::SessionDescription* sdesc,
+ std::string* name,
+ const SecureTunnelContentDescription** content) {
+ const ContentInfo* cinfo = sdesc->FirstContentByType(NS_SECURE_TUNNEL);
+ if (cinfo == NULL)
+ return false;
+
+ *name = cinfo->name;
+ *content = static_cast<const SecureTunnelContentDescription*>(
+ cinfo->description);
+ return true;
+}
+
+void SecureTunnelSessionClient::OnIncomingTunnel(const buzz::Jid &jid,
+ Session *session) {
+ std::string content_name;
+ const SecureTunnelContentDescription* content = NULL;
+ if (!FindSecureTunnelContent(session->remote_description(),
+ &content_name, &content)) {
+ ASSERT(false);
+ }
+
+ // Validate the certificate
+ talk_base::scoped_ptr<talk_base::SSLCertificate> peer_cert(
+ ParseCertificate(content->client_pem_certificate));
+ if (peer_cert.get() == NULL) {
+ LOG(LS_ERROR)
+ << "Rejecting incoming secure tunnel with invalid cetificate";
+ DeclineTunnel(session);
+ return;
+ }
+ // If there were a convenient place we could have cached the
+ // peer_cert so as not to have to parse it a second time when
+ // configuring the tunnel.
+ SignalIncomingTunnel(this, jid, content->description, session);
+}
+
+// The XML representation of a session initiation request (XMPP IQ),
+// containing the initiator's SecureTunnelContentDescription,
+// looks something like this:
+// <iq from="INITIATOR@gmail.com/pcpE101B7F4"
+// to="RECIPIENT@gmail.com/pcp8B87F0A3"
+// type="set" id="3">
+// <session xmlns="http://www.google.com/session"
+// type="initiate" id="2508605813"
+// initiator="INITIATOR@gmail.com/pcpE101B7F4">
+// <description xmlns="http://www.google.com/talk/securetunnel">
+// <type>send:filename</type>
+// <client-cert>
+// -----BEGIN CERTIFICATE-----
+// INITIATOR'S CERTIFICATE IN PERM FORMAT (ASCII GIBBERISH)
+// -----END CERTIFICATE-----
+// </client-cert>
+// </description>
+// <transport xmlns="http://www.google.com/transport/p2p"/>
+// </session>
+// </iq>
+
+// The session accept iq, containing the recipient's certificate and
+// echoing the initiator's certificate, looks something like this:
+// <iq from="RECIPIENT@gmail.com/pcpE101B7F4"
+// to="INITIATOR@gmail.com/pcpE101B7F4"
+// type="set" id="5">
+// <session xmlns="http://www.google.com/session"
+// type="accept" id="2508605813"
+// initiator="sdoyon911@gmail.com/pcpE101B7F4">
+// <description xmlns="http://www.google.com/talk/securetunnel">
+// <type>send:FILENAME</type>
+// <client-cert>
+// -----BEGIN CERTIFICATE-----
+// INITIATOR'S CERTIFICATE IN PERM FORMAT (ASCII GIBBERISH)
+// -----END CERTIFICATE-----
+// </client-cert>
+// <server-cert>
+// -----BEGIN CERTIFICATE-----
+// RECIPIENT'S CERTIFICATE IN PERM FORMAT (ASCII GIBBERISH)
+// -----END CERTIFICATE-----
+// </server-cert>
+// </description>
+// </session>
+// </iq>
+
+
+bool SecureTunnelSessionClient::ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ const ContentDescription** content,
+ ParseError* error) {
+ const buzz::XmlElement* type_elem = elem->FirstNamed(QN_SECURE_TUNNEL_TYPE);
+
+ if (type_elem == NULL)
+ // Missing mandatory XML element.
+ return false;
+
+ // Here we consider the certificate components to be optional. In
+ // practice the client certificate is always present, and the server
+ // certificate is initially missing from the session description
+ // sent during session initiation. OnAccept() will enforce that we
+ // have a certificate for our peer.
+ const buzz::XmlElement* client_cert_elem =
+ elem->FirstNamed(QN_SECURE_TUNNEL_CLIENT_CERT);
+ const buzz::XmlElement* server_cert_elem =
+ elem->FirstNamed(QN_SECURE_TUNNEL_SERVER_CERT);
+ *content = new SecureTunnelContentDescription(
+ type_elem->BodyText(),
+ client_cert_elem ? client_cert_elem->BodyText() : "",
+ server_cert_elem ? server_cert_elem->BodyText() : "");
+ return true;
+}
+
+bool SecureTunnelSessionClient::WriteContent(
+ SignalingProtocol protocol, const ContentDescription* untyped_content,
+ buzz::XmlElement** elem, WriteError* error) {
+ const SecureTunnelContentDescription* content =
+ static_cast<const SecureTunnelContentDescription*>(untyped_content);
+
+ buzz::XmlElement* root =
+ new buzz::XmlElement(QN_SECURE_TUNNEL_DESCRIPTION, true);
+ buzz::XmlElement* type_elem = new buzz::XmlElement(QN_SECURE_TUNNEL_TYPE);
+ type_elem->SetBodyText(content->description);
+ root->AddElement(type_elem);
+ if (!content->client_pem_certificate.empty()) {
+ buzz::XmlElement* client_cert_elem =
+ new buzz::XmlElement(QN_SECURE_TUNNEL_CLIENT_CERT);
+ client_cert_elem->SetBodyText(content->client_pem_certificate);
+ root->AddElement(client_cert_elem);
+ }
+ if (!content->server_pem_certificate.empty()) {
+ buzz::XmlElement* server_cert_elem =
+ new buzz::XmlElement(QN_SECURE_TUNNEL_SERVER_CERT);
+ server_cert_elem->SetBodyText(content->server_pem_certificate);
+ root->AddElement(server_cert_elem);
+ }
+ *elem = root;
+ return true;
+}
+
+SessionDescription* NewSecureTunnelSessionDescription(
+ const std::string& content_name, const ContentDescription* content) {
+ SessionDescription* sdesc = new SessionDescription();
+ sdesc->AddContent(content_name, NS_SECURE_TUNNEL, content);
+ return sdesc;
+}
+
+SessionDescription* SecureTunnelSessionClient::CreateOffer(
+ const buzz::Jid &jid, const std::string &description) {
+ // We are the initiator so we are the client. Put our cert into the
+ // description.
+ std::string pem_cert = GetIdentity().certificate().ToPEMString();
+ return NewSecureTunnelSessionDescription(
+ CN_SECURE_TUNNEL,
+ new SecureTunnelContentDescription(description, pem_cert, ""));
+}
+
+SessionDescription* SecureTunnelSessionClient::CreateAnswer(
+ const SessionDescription* offer) {
+ std::string content_name;
+ const SecureTunnelContentDescription* offer_tunnel = NULL;
+ if (!FindSecureTunnelContent(offer, &content_name, &offer_tunnel))
+ return NULL;
+
+ // We are accepting a session request. We need to add our cert, the
+ // server cert, into the description. The client cert was validated
+ // in OnIncomingTunnel().
+ ASSERT(!offer_tunnel->client_pem_certificate.empty());
+ return NewSecureTunnelSessionDescription(
+ content_name,
+ new SecureTunnelContentDescription(
+ offer_tunnel->description,
+ offer_tunnel->client_pem_certificate,
+ GetIdentity().certificate().ToPEMString()));
+}
+
+// SecureTunnelSession
+
+SecureTunnelSession::SecureTunnelSession(
+ SecureTunnelSessionClient* client, Session* session,
+ talk_base::Thread* stream_thread, TunnelSessionRole role)
+ : TunnelSession(client, session, stream_thread),
+ role_(role) {
+}
+
+talk_base::StreamInterface* SecureTunnelSession::MakeSecureStream(
+ talk_base::StreamInterface* stream) {
+ talk_base::SSLStreamAdapter* ssl_stream =
+ talk_base::SSLStreamAdapter::Create(stream);
+ talk_base::SSLIdentity* identity =
+ static_cast<SecureTunnelSessionClient*>(client_)->
+ GetIdentity().GetReference();
+ ssl_stream->SetIdentity(identity);
+ if (role_ == RESPONDER)
+ ssl_stream->SetServerRole();
+ ssl_stream->StartSSLWithPeer();
+
+ // SSL negotiation will start on the stream as soon as it
+ // opens. However our SSLStreamAdapter still hasn't been told what
+ // certificate to allow for our peer. If we are the initiator, we do
+ // not have the peer's certificate yet: we will obtain it from the
+ // session accept message which we will receive later (see
+ // OnAccept()). We won't Connect() the PseudoTcpChannel until we get
+ // that, so the stream will stay closed until then. Keep a handle
+ // on the streem so we can configure the peer certificate later.
+ ssl_stream_reference_.reset(new talk_base::StreamReference(ssl_stream));
+ return ssl_stream_reference_->NewReference();
+}
+
+talk_base::StreamInterface* SecureTunnelSession::GetStream() {
+ ASSERT(channel_ != NULL);
+ ASSERT(ssl_stream_reference_.get() == NULL);
+ return MakeSecureStream(channel_->GetStream());
+}
+
+void SecureTunnelSession::OnAccept() {
+ // We have either sent or received a session accept: it's time to
+ // connect the tunnel. First we must set the peer certificate.
+ ASSERT(channel_ != NULL);
+ ASSERT(session_ != NULL);
+ std::string content_name;
+ const SecureTunnelContentDescription* remote_tunnel = NULL;
+ if (!FindSecureTunnelContent(session_->remote_description(),
+ &content_name, &remote_tunnel)) {
+ session_->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
+ return;
+ }
+
+ const std::string& cert_pem =
+ role_ == INITIATOR ? remote_tunnel->server_pem_certificate :
+ remote_tunnel->client_pem_certificate;
+ talk_base::SSLCertificate* peer_cert =
+ ParseCertificate(cert_pem);
+ if (peer_cert == NULL) {
+ ASSERT(role_ == INITIATOR); // when RESPONDER we validated it earlier
+ LOG(LS_ERROR)
+ << "Rejecting secure tunnel accept with invalid cetificate";
+ session_->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
+ return;
+ }
+ ASSERT(ssl_stream_reference_.get() != NULL);
+ talk_base::SSLStreamAdapter* ssl_stream =
+ static_cast<talk_base::SSLStreamAdapter*>(
+ ssl_stream_reference_->GetStream());
+ ssl_stream->SetPeerCertificate(peer_cert); // pass ownership of certificate.
+ // We no longer need our handle to the ssl stream.
+ ssl_stream_reference_.reset();
+ LOG(LS_INFO) << "Connecting tunnel";
+ // This will try to connect the PseudoTcpChannel. If and when that
+ // succeeds, then ssl negotiation will take place, and when that
+ // succeeds, the tunnel stream will finally open.
+ VERIFY(channel_->Connect(content_name, "tcp"));
+}
+
+} // namespace cricket
diff --git a/talk/session/tunnel/securetunnelsessionclient.h b/talk/session/tunnel/securetunnelsessionclient.h
new file mode 100644
index 0000000..cb9a99c
--- /dev/null
+++ b/talk/session/tunnel/securetunnelsessionclient.h
@@ -0,0 +1,165 @@
+/*
+ * libjingle
+ * Copyright 2004--2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// SecureTunnelSessionClient and SecureTunnelSession.
+// SecureTunnelSessionClient extends TunnelSessionClient to exchange
+// certificates as part of the session description.
+// SecureTunnelSession is a TunnelSession that wraps the underlying
+// tunnel stream into an SSLStreamAdapter.
+
+#ifndef TALK_SESSION_TUNNEL_SECURETUNNELSESSIONCLIENT_H_
+#define TALK_SESSION_TUNNEL_SECURETUNNELSESSIONCLIENT_H_
+
+#include <string>
+
+#include "talk/base/sslidentity.h"
+#include "talk/base/sslstreamadapter.h"
+#include "talk/session/tunnel/tunnelsessionclient.h"
+
+namespace cricket {
+
+class SecureTunnelSession; // below
+
+// SecureTunnelSessionClient
+
+// This TunnelSessionClient establishes secure tunnels protected by
+// SSL/TLS. The PseudoTcpChannel stream is wrapped with an
+// SSLStreamAdapter. An SSLIdentity must be set or generated.
+//
+// The TunnelContentDescription is extended to include the client and
+// server certificates. The initiator acts as the client. The session
+// initiate stanza carries a description that contains the client's
+// certificate, and the session accept response's description has the
+// server certificate added to it.
+
+class SecureTunnelSessionClient : public TunnelSessionClient {
+ public:
+ // The jid is used as the name for sessions for outgoing tunnels.
+ // manager is the SessionManager to which we register this client
+ // and its sessions.
+ SecureTunnelSessionClient(const buzz::Jid& jid, SessionManager* manager);
+
+ // Configures this client to use a preexisting SSLIdentity.
+ // The client takes ownership of the identity object.
+ // Use either SetIdentity or GenerateIdentity, and only once.
+ void SetIdentity(talk_base::SSLIdentity* identity);
+
+ // Generates an identity from nothing.
+ // Returns true if generation was successful.
+ // Use either SetIdentity or GenerateIdentity, and only once.
+ bool GenerateIdentity();
+
+ // Returns our identity for SSL purposes, as either set by
+ // SetIdentity() or generated by GenerateIdentity(). Call this
+ // method only after our identity has been successfully established
+ // by one of those methods.
+ talk_base::SSLIdentity& GetIdentity() const;
+
+ // Inherited methods
+ virtual void OnIncomingTunnel(const buzz::Jid& jid, Session *session);
+ virtual bool ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ const ContentDescription** content,
+ ParseError* error);
+ virtual bool WriteContent(SignalingProtocol protocol,
+ const ContentDescription* content,
+ buzz::XmlElement** elem,
+ WriteError* error);
+ virtual SessionDescription* CreateOffer(
+ const buzz::Jid &jid, const std::string &description);
+ virtual SessionDescription* CreateAnswer(
+ const SessionDescription* offer);
+
+ protected:
+ virtual TunnelSession* MakeTunnelSession(
+ Session* session, talk_base::Thread* stream_thread,
+ TunnelSessionRole role);
+
+ private:
+ // Our identity (key and certificate) for SSL purposes. The
+ // certificate part will be communicated within the session
+ // description. The identity will be passed to the SSLStreamAdapter
+ // and used for SSL authentication.
+ talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SecureTunnelSessionClient);
+};
+
+// SecureTunnelSession:
+// A TunnelSession represents one session for one client. It
+// provides the actual tunnel stream and handles state changes.
+// A SecureTunnelSession is a TunnelSession that wraps the underlying
+// tunnel stream into an SSLStreamAdapter.
+
+class SecureTunnelSession : public TunnelSession {
+ public:
+ // This TunnelSession will tie together the given client and session.
+ // stream_thread is passed to the PseudoTCPChannel: it's the thread
+ // designated to interact with the tunnel stream.
+ // role is either INITIATOR or RESPONDER, depending on who is
+ // initiating the session.
+ SecureTunnelSession(SecureTunnelSessionClient* client, Session* session,
+ talk_base::Thread* stream_thread,
+ TunnelSessionRole role);
+
+ // Returns the stream that implements the actual P2P tunnel.
+ // This may be called only once. Caller is responsible for freeing
+ // the returned object.
+ virtual talk_base::StreamInterface* GetStream();
+
+ protected:
+ // Inherited method: callback on accepting a session.
+ virtual void OnAccept();
+
+ // Helper method for GetStream() that Instantiates the
+ // SSLStreamAdapter to wrap the PseudoTcpChannel's stream, and
+ // configures it with our identity and role.
+ talk_base::StreamInterface* MakeSecureStream(
+ talk_base::StreamInterface* stream);
+
+ // Our role in requesting the tunnel: INITIATOR or
+ // RESPONDER. Translates to our role in SSL negotiation:
+ // respectively client or server. Also indicates which slot of the
+ // SecureTunnelContentDescription our cert goes into: client-cert or
+ // server-cert respectively.
+ TunnelSessionRole role_;
+
+ // This is the stream representing the usable tunnel endpoint. It's
+ // a StreamReference wrapping the SSLStreamAdapter instance, which
+ // further wraps a PseudoTcpChannel::InternalStream. The
+ // StreamReference is because in the case of CreateTunnel(), the
+ // stream endpoint is returned early, but we need to keep a handle
+ // on it so we can setup the peer certificate when we receive it
+ // later.
+ talk_base::scoped_ptr<talk_base::StreamReference> ssl_stream_reference_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SecureTunnelSession);
+};
+
+} // namespace cricket
+
+#endif // TALK_SESSION_TUNNEL_SECURETUNNELSESSIONCLIENT_H_
diff --git a/talk/session/tunnel/tunnelsessionclient.cc b/talk/session/tunnel/tunnelsessionclient.cc
old mode 100755
new mode 100644
index 855f0db..13d5c10
--- a/talk/session/tunnel/tunnelsessionclient.cc
+++ b/talk/session/tunnel/tunnelsessionclient.cc
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2006, Google Inc.
+ * Copyright 2004--2008, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -31,6 +31,7 @@
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/stringutils.h"
+#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/transportchannel.h"
#include "talk/xmllite/xmlelement.h"
#include "pseudotcpchannel.h"
@@ -41,6 +42,7 @@
const std::string NS_TUNNEL("http://www.google.com/talk/tunnel");
const buzz::QName QN_TUNNEL_DESCRIPTION(NS_TUNNEL, "description");
const buzz::QName QN_TUNNEL_TYPE(NS_TUNNEL, "type");
+const std::string CN_TUNNEL("tunnel");
enum {
MSG_CLOCK = 1,
@@ -83,27 +85,26 @@
};
///////////////////////////////////////////////////////////////////////////////
-// TunnelSessionDescription
+// TunnelContentDescription
///////////////////////////////////////////////////////////////////////////////
-struct TunnelSessionDescription : public SessionDescription {
+struct TunnelContentDescription : public ContentDescription {
std::string description;
- TunnelSessionDescription(const std::string& desc) : description(desc) { }
+ TunnelContentDescription(const std::string& desc) : description(desc) { }
};
///////////////////////////////////////////////////////////////////////////////
-// TunnelSessionClient
+// TunnelSessionClientBase
///////////////////////////////////////////////////////////////////////////////
-TunnelSessionClient::TunnelSessionClient(const buzz::Jid& jid,
- SessionManager* manager)
- : jid_(jid), session_manager_(manager), shutdown_(false) {
- // Register ourselves as the handler of tunnel sessions.
- session_manager_->AddClient(NS_TUNNEL, this);
+TunnelSessionClientBase::TunnelSessionClientBase(const buzz::Jid& jid,
+ SessionManager* manager, const std::string &ns)
+ : jid_(jid), session_manager_(manager), namespace_(ns), shutdown_(false) {
+ session_manager_->AddClient(namespace_, this);
}
-TunnelSessionClient::~TunnelSessionClient() {
+TunnelSessionClientBase::~TunnelSessionClientBase() {
shutdown_ = true;
for (std::vector<TunnelSession*>::iterator it = sessions_.begin();
it != sessions_.end();
@@ -111,40 +112,20 @@
Session* session = (*it)->ReleaseSession(true);
session_manager_->DestroySession(session);
}
- session_manager_->RemoveClient(NS_TUNNEL);
+ session_manager_->RemoveClient(namespace_);
}
-const SessionDescription* TunnelSessionClient::CreateSessionDescription(
- const buzz::XmlElement* element) {
- if (const buzz::XmlElement* type_elem = element->FirstNamed(QN_TUNNEL_TYPE)) {
- return new TunnelSessionDescription(type_elem->BodyText());
- }
- ASSERT(false);
- return 0;
-}
-
-buzz::XmlElement* TunnelSessionClient::TranslateSessionDescription(
- const SessionDescription* description) {
- const TunnelSessionDescription* desc =
- static_cast<const TunnelSessionDescription*>(description);
-
- buzz::XmlElement* root = new buzz::XmlElement(QN_TUNNEL_DESCRIPTION, true);
- buzz::XmlElement* type_elem = new buzz::XmlElement(QN_TUNNEL_TYPE);
- type_elem->SetBodyText(desc->description);
- root->AddElement(type_elem);
- return root;
-}
-
-void TunnelSessionClient::OnSessionCreate(Session* session, bool received) {
- LOG(LS_INFO) << "TunnelSessionClient::OnSessionCreate: received=" << received;
+void TunnelSessionClientBase::OnSessionCreate(Session* session, bool received) {
+ LOG(LS_INFO) << "TunnelSessionClientBase::OnSessionCreate: received="
+ << received;
ASSERT(session_manager_->signaling_thread()->IsCurrent());
if (received)
sessions_.push_back(
- new TunnelSession(this, session, talk_base::Thread::Current()));
+ MakeTunnelSession(session, talk_base::Thread::Current(), RESPONDER));
}
-void TunnelSessionClient::OnSessionDestroy(Session* session) {
- LOG(LS_INFO) << "TunnelSessionClient::OnSessionDestroy";
+void TunnelSessionClientBase::OnSessionDestroy(Session* session) {
+ LOG(LS_INFO) << "TunnelSessionClientBase::OnSessionDestroy";
ASSERT(session_manager_->signaling_thread()->IsCurrent());
if (shutdown_)
return;
@@ -159,7 +140,7 @@
}
}
-talk_base::StreamInterface* TunnelSessionClient::CreateTunnel(
+talk_base::StreamInterface* TunnelSessionClientBase::CreateTunnel(
const buzz::Jid& to, const std::string& description) {
// Valid from any thread
CreateTunnelData data;
@@ -170,7 +151,7 @@
return data.stream;
}
-talk_base::StreamInterface* TunnelSessionClient::AcceptTunnel(
+talk_base::StreamInterface* TunnelSessionClientBase::AcceptTunnel(
Session* session) {
ASSERT(session_manager_->signaling_thread()->IsCurrent());
TunnelSession* tunnel = NULL;
@@ -184,33 +165,133 @@
}
ASSERT(tunnel != NULL);
- const TunnelSessionDescription* in_desc =
- static_cast<const TunnelSessionDescription*>(
- session->remote_description());
- TunnelSessionDescription* out_desc = new TunnelSessionDescription(
- in_desc->description);
- session->Accept(out_desc);
+ SessionDescription* answer = CreateAnswer(session->remote_description());
+ if (answer == NULL)
+ return NULL;
+
+ session->Accept(answer);
return tunnel->GetStream();
}
-void TunnelSessionClient::DeclineTunnel(Session* session) {
+void TunnelSessionClientBase::DeclineTunnel(Session* session) {
ASSERT(session_manager_->signaling_thread()->IsCurrent());
- session->Reject();
+ session->Reject(STR_TERMINATE_DECLINE);
}
-void TunnelSessionClient::OnMessage(talk_base::Message* pmsg) {
+void TunnelSessionClientBase::OnMessage(talk_base::Message* pmsg) {
if (pmsg->message_id == MSG_CREATE_TUNNEL) {
ASSERT(session_manager_->signaling_thread()->IsCurrent());
CreateTunnelData* data = static_cast<CreateTunnelData*>(pmsg->pdata);
- Session* session = session_manager_->CreateSession(jid_.Str(), NS_TUNNEL);
- TunnelSession* tunnel = new TunnelSession(this, session, data->thread);
+ Session* session = session_manager_->CreateSession(jid_.Str(), namespace_);
+ TunnelSession* tunnel = MakeTunnelSession(session, data->thread,
+ INITIATOR);
sessions_.push_back(tunnel);
- TunnelSessionDescription* desc = new TunnelSessionDescription(data->description);
- session->Initiate(data->jid.Str(), NULL, desc);
+ SessionDescription* offer = CreateOffer(data->jid, data->description);
+ session->Initiate(data->jid.Str(), offer);
data->stream = tunnel->GetStream();
}
}
+TunnelSession* TunnelSessionClientBase::MakeTunnelSession(
+ Session* session, talk_base::Thread* stream_thread,
+ TunnelSessionRole /*role*/) {
+ return new TunnelSession(this, session, stream_thread);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TunnelSessionClient
+///////////////////////////////////////////////////////////////////////////////
+
+TunnelSessionClient::TunnelSessionClient(const buzz::Jid& jid,
+ SessionManager* manager,
+ const std::string &ns)
+ : TunnelSessionClientBase(jid, manager, ns) {
+}
+
+TunnelSessionClient::TunnelSessionClient(const buzz::Jid& jid,
+ SessionManager* manager)
+ : TunnelSessionClientBase(jid, manager, NS_TUNNEL) {
+}
+
+TunnelSessionClient::~TunnelSessionClient() {
+}
+
+
+bool TunnelSessionClient::ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ const ContentDescription** content,
+ ParseError* error) {
+ if (const buzz::XmlElement* type_elem = elem->FirstNamed(QN_TUNNEL_TYPE)) {
+ *content = new TunnelContentDescription(type_elem->BodyText());
+ return true;
+ }
+ return false;
+}
+
+bool TunnelSessionClient::WriteContent(
+ SignalingProtocol protocol,
+ const ContentDescription* untyped_content,
+ buzz::XmlElement** elem, WriteError* error) {
+ const TunnelContentDescription* content =
+ static_cast<const TunnelContentDescription*>(untyped_content);
+
+ buzz::XmlElement* root = new buzz::XmlElement(QN_TUNNEL_DESCRIPTION, true);
+ buzz::XmlElement* type_elem = new buzz::XmlElement(QN_TUNNEL_TYPE);
+ type_elem->SetBodyText(content->description);
+ root->AddElement(type_elem);
+ *elem = root;
+ return true;
+}
+
+SessionDescription* NewTunnelSessionDescription(
+ const std::string& content_name, const ContentDescription* content) {
+ SessionDescription* sdesc = new SessionDescription();
+ sdesc->AddContent(content_name, NS_TUNNEL, content);
+ return sdesc;
+}
+
+bool FindTunnelContent(const cricket::SessionDescription* sdesc,
+ std::string* name,
+ const TunnelContentDescription** content) {
+ const ContentInfo* cinfo = sdesc->FirstContentByType(NS_TUNNEL);
+ if (cinfo == NULL)
+ return false;
+
+ *name = cinfo->name;
+ *content = static_cast<const TunnelContentDescription*>(
+ cinfo->description);
+ return true;
+}
+
+void TunnelSessionClient::OnIncomingTunnel(const buzz::Jid &jid,
+ Session *session) {
+ std::string content_name;
+ const TunnelContentDescription* content = NULL;
+ if (!FindTunnelContent(session->remote_description(),
+ &content_name, &content)) {
+ session->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
+ return;
+ }
+
+ SignalIncomingTunnel(this, jid, content->description, session);
+}
+
+SessionDescription* TunnelSessionClient::CreateOffer(
+ const buzz::Jid &jid, const std::string &description) {
+ return NewTunnelSessionDescription(
+ CN_TUNNEL, new TunnelContentDescription(description));
+}
+
+SessionDescription* TunnelSessionClient::CreateAnswer(
+ const SessionDescription* offer) {
+ std::string content_name;
+ const TunnelContentDescription* offer_tunnel = NULL;
+ if (!FindTunnelContent(offer, &content_name, &offer_tunnel))
+ return NULL;
+
+ return NewTunnelSessionDescription(
+ content_name, new TunnelContentDescription(offer_tunnel->description));
+}
///////////////////////////////////////////////////////////////////////////////
// TunnelSession
///////////////////////////////////////////////////////////////////////////////
@@ -219,7 +300,7 @@
// Signalling thread methods
//
-TunnelSession::TunnelSession(TunnelSessionClient* client, Session* session,
+TunnelSession::TunnelSession(TunnelSessionClientBase* client, Session* session,
talk_base::Thread* stream_thread)
: client_(client), session_(session), channel_(NULL) {
ASSERT(client_ != NULL);
@@ -258,7 +339,8 @@
return session;
}
-void TunnelSession::OnSessionState(Session* session, Session::State state) {
+void TunnelSession::OnSessionState(BaseSession* session,
+ BaseSession::State state) {
LOG(LS_INFO) << "TunnelSession::OnSessionState("
<< talk_base::nonnull(
talk_base::FindLabel(state, SESSION_STATES), "Unknown")
@@ -281,28 +363,28 @@
// ReleaseSession should have been called before this.
ASSERT(false);
break;
+ default:
+ break;
}
}
void TunnelSession::OnInitiate() {
- const TunnelSessionDescription* in_desc =
- static_cast<const TunnelSessionDescription*>(
- session_->remote_description());
-
ASSERT(client_ != NULL);
ASSERT(session_ != NULL);
- client_->SignalIncomingTunnel(client_,
- buzz::Jid(session_->remote_name()),
- in_desc->description,
- session_);
+ client_->OnIncomingTunnel(buzz::Jid(session_->remote_name()), session_);
}
void TunnelSession::OnAccept() {
ASSERT(channel_ != NULL);
- VERIFY(channel_->Connect("tcp"));
+ const ContentInfo* content =
+ session_->remote_description()->FirstContentByType(NS_TUNNEL);
+ ASSERT(content != NULL);
+ VERIFY(channel_->Connect(content->name, "tcp"));
}
void TunnelSession::OnTerminate() {
+ ASSERT(channel_ != NULL);
+ channel_->OnSessionTerminate(session_);
}
void TunnelSession::OnChannelClosed(PseudoTcpChannel* channel) {
diff --git a/talk/session/tunnel/tunnelsessionclient.h b/talk/session/tunnel/tunnelsessionclient.h
old mode 100755
new mode 100644
index 34c05bf..7259fa1
--- a/talk/session/tunnel/tunnelsessionclient.h
+++ b/talk/session/tunnel/tunnelsessionclient.h
@@ -1,27 +1,27 @@
/*
* libjingle
- * Copyright 2004--2006, Google Inc.
+ * Copyright 2004--2008, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,8 +29,10 @@
#define __TUNNELSESSIONCLIENT_H__
#include <vector>
+
#include "talk/base/criticalsection.h"
#include "talk/base/stream.h"
+#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/pseudotcp.h"
#include "talk/p2p/base/session.h"
#include "talk/p2p/base/sessiondescription.h"
@@ -44,48 +46,93 @@
class TunnelSession;
class TunnelStream;
+enum TunnelSessionRole { INITIATOR, RESPONDER };
+
///////////////////////////////////////////////////////////////////////////////
// TunnelSessionClient
///////////////////////////////////////////////////////////////////////////////
-class TunnelSessionClient
- : public SessionClient, public talk_base::MessageHandler,
- public sigslot::has_slots<> {
+// Base class is still abstract
+class TunnelSessionClientBase
+ : public SessionClient, public talk_base::MessageHandler {
public:
- TunnelSessionClient(const buzz::Jid& jid, SessionManager* manager);
- virtual ~TunnelSessionClient();
+ TunnelSessionClientBase(const buzz::Jid& jid, SessionManager* manager,
+ const std::string &ns);
+ virtual ~TunnelSessionClientBase();
const buzz::Jid& jid() const { return jid_; }
SessionManager* session_manager() const { return session_manager_; }
- const SessionDescription* CreateSessionDescription(
- const buzz::XmlElement* element);
- buzz::XmlElement* TranslateSessionDescription(
- const SessionDescription* description);
-
void OnSessionCreate(Session* session, bool received);
void OnSessionDestroy(Session* session);
- // This can be called on any thread. The stream interface is thread-safe, but
- // notifications must be registered on the creating thread.
+ // This can be called on any thread. The stream interface is
+ // thread-safe, but notifications must be registered on the creating
+ // thread.
talk_base::StreamInterface* CreateTunnel(const buzz::Jid& to,
const std::string& description);
- // Signal arguments are this, initiator, description, session
- sigslot::signal4<TunnelSessionClient*, buzz::Jid, std::string, Session*>
- SignalIncomingTunnel;
talk_base::StreamInterface* AcceptTunnel(Session* session);
void DeclineTunnel(Session* session);
-private:
+ // Invoked on an incoming tunnel
+ virtual void OnIncomingTunnel(const buzz::Jid &jid, Session *session) = 0;
+
+ // Invoked on an outgoing session request
+ virtual SessionDescription* CreateOffer(
+ const buzz::Jid &jid, const std::string &description) = 0;
+ // Invoked on a session request accept to create
+ // the local-side session description
+ virtual SessionDescription* CreateAnswer(
+ const SessionDescription* offer) = 0;
+
+protected:
+
void OnMessage(talk_base::Message* pmsg);
+ // helper method to instantiate TunnelSession. By overriding this,
+ // subclasses of TunnelSessionClient are able to instantiate
+ // subclasses of TunnelSession instead.
+ virtual TunnelSession* MakeTunnelSession(Session* session,
+ talk_base::Thread* stream_thread,
+ TunnelSessionRole role);
+
buzz::Jid jid_;
SessionManager* session_manager_;
std::vector<TunnelSession*> sessions_;
+ std::string namespace_;
bool shutdown_;
};
+class TunnelSessionClient
+ : public TunnelSessionClientBase, public sigslot::has_slots<> {
+public:
+ TunnelSessionClient(const buzz::Jid& jid, SessionManager* manager);
+ TunnelSessionClient(const buzz::Jid& jid, SessionManager* manager,
+ const std::string &ns);
+ virtual ~TunnelSessionClient();
+
+ virtual bool ParseContent(SignalingProtocol protocol,
+ const buzz::XmlElement* elem,
+ const ContentDescription** content,
+ ParseError* error);
+ virtual bool WriteContent(SignalingProtocol protocol,
+ const ContentDescription* content,
+ buzz::XmlElement** elem,
+ WriteError* error);
+
+ // Signal arguments are this, initiator, description, session
+ sigslot::signal4<TunnelSessionClient*, buzz::Jid, std::string, Session*>
+ SignalIncomingTunnel;
+
+ virtual void OnIncomingTunnel(const buzz::Jid &jid,
+ Session *session);
+ virtual SessionDescription* CreateOffer(
+ const buzz::Jid &jid, const std::string &description);
+ virtual SessionDescription* CreateAnswer(
+ const SessionDescription* offer);
+};
+
///////////////////////////////////////////////////////////////////////////////
// TunnelSession
// Note: The lifetime of TunnelSession is complicated. It needs to survive
@@ -97,7 +144,7 @@
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TunnelStream
-// Note: Because TunnelStream provides a stream interface, it's lifetime is
+// Note: Because TunnelStream provides a stream interface, its lifetime is
// controlled by the owner of the stream pointer. As a result, we must support
// both the TunnelSession disappearing before TunnelStream, and vice versa.
///////////////////////////////////////////////////////////////////////////////
@@ -105,25 +152,25 @@
class PseudoTcpChannel;
class TunnelSession : public sigslot::has_slots<> {
-public:
+ public:
// Signalling thread methods
- TunnelSession(TunnelSessionClient* client, Session* session,
+ TunnelSession(TunnelSessionClientBase* client, Session* session,
talk_base::Thread* stream_thread);
- talk_base::StreamInterface* GetStream();
+ virtual talk_base::StreamInterface* GetStream();
bool HasSession(Session* session);
Session* ReleaseSession(bool channel_exists);
-private:
+ protected:
virtual ~TunnelSession();
- void OnSessionState(Session* session, Session::State state);
- void OnInitiate();
- void OnAccept();
- void OnTerminate();
- void OnChannelClosed(PseudoTcpChannel* channel);
+ virtual void OnSessionState(BaseSession* session, BaseSession::State state);
+ virtual void OnInitiate();
+ virtual void OnAccept();
+ virtual void OnTerminate();
+ virtual void OnChannelClosed(PseudoTcpChannel* channel);
- TunnelSessionClient* client_;
+ TunnelSessionClientBase* client_;
Session* session_;
PseudoTcpChannel* channel_;
};
diff --git a/talk/site_scons/site_tools/talk_noops.py b/talk/site_scons/site_tools/talk_noops.py
new file mode 100644
index 0000000..bb8f106
--- /dev/null
+++ b/talk/site_scons/site_tools/talk_noops.py
@@ -0,0 +1,20 @@
+# Copyright 2010 Google Inc.
+# All Rights Reserved.
+# Author: thaloun@google.com (Tim Haloun)
+
+"""Noop tool that defines builder functions for non-default platforms to
+ avoid errors when scanning sconsscripts."""
+
+import SCons.Builder
+
+
+def generate(env):
+ """SCons method."""
+ if not env.Bit('windows'):
+ builder = SCons.Builder.Builder(
+ action=''
+ )
+ env.Append(BUILDERS={'RES': builder, 'Grit': builder})
+
+def exists(env):
+ return 1
diff --git a/talk/site_scons/site_tools/talk_noops.pyc b/talk/site_scons/site_tools/talk_noops.pyc
new file mode 100644
index 0000000..d25fa59
--- /dev/null
+++ b/talk/site_scons/site_tools/talk_noops.pyc
Binary files differ
diff --git a/talk/site_scons/talk.py b/talk/site_scons/talk.py
new file mode 100644
index 0000000..e5ede4f
--- /dev/null
+++ b/talk/site_scons/talk.py
@@ -0,0 +1,544 @@
+# Copyright 2010 Google Inc.
+# All Rights Reserved.
+#
+# Author: Tim Haloun (thaloun@google.com)
+# Daniel Petersson (dape@google.com)
+#
+import os
+
+# Keep a global list of what libraries have a 64 bit version. We use it for
+# replacements when linking a 64 bit dylib or executable.
+libs64 = []
+
+def Library(env, **kwargs):
+ """Extends ComponentLibrary to support multiplatform builds.
+
+ Args:
+ env: The current environment.
+ kwargs: The keyword arguments.
+ """
+ params = CombineDicts(kwargs, {'COMPONENT_STATIC': True})
+ if params.has_key('also64bit'):
+ libs64.append(params['name'])
+
+ return ExtendComponent(env, 'ComponentLibrary', **params)
+
+
+def DynamicLibrary(env, **kwargs):
+ """Extends ComponentLibrary to support multiplatform builds
+ of dynmic libraries. This use COMPONENT_STATIC = false.
+
+ Args:
+ env: The environment object.
+ kwargs: The keyword arguments.
+
+ Returns:
+ See swtoolkit ComponentLibrary
+ """
+ params = CombineDicts(kwargs, {'COMPONENT_STATIC': False})
+ return ExtendComponent(env, 'ComponentLibrary', **params)
+
+
+def Object(env, **kwargs):
+ return ExtendComponent(env, 'ComponentObject', **kwargs)
+
+
+def Unittest(env, **kwargs):
+ """Extends ComponentTestProgram to support unittest built
+ for multiple platforms.
+
+ Args:
+ env: The current environment.
+ kwargs: The keyword arguments.
+
+ Returns:
+ See swtoolkit ComponentProgram.
+ """
+ kwargs['name'] = kwargs['name'] + '_unittest'
+
+ common_test_params = {
+ 'posix_cppdefines': ['GUNIT_NO_GOOGLE3', 'GTEST_HAS_RTTI=0'],
+ 'libs': ['unittest_main', 'gunit']
+ }
+ if not kwargs.has_key('explicit_libs'):
+ common_test_params['win_libs'] = [
+ 'advapi32',
+ 'crypt32',
+ 'iphlpapi',
+ 'secur32',
+ 'shell32',
+ 'shlwapi',
+ 'user32',
+ 'wininet',
+ 'ws2_32'
+ ]
+ common_test_params['lin_libs'] = [
+ 'pthread',
+ ':libssl.so.0.9.8',
+ ':libcrypto.so.0.9.8',
+ ]
+
+ params = CombineDicts(kwargs, common_test_params)
+ return ExtendComponent(env, 'ComponentTestProgram', **params)
+
+
+def App(env, **kwargs):
+ """Extends ComponentProgram to support executables with platform specific
+ options.
+
+ Args:
+ env: The current environment.
+ kwargs: The keyword arguments.
+
+ Returns:
+ See swtoolkit ComponentProgram.
+ """
+ if not kwargs.has_key('explicit_libs'):
+ common_app_params = {
+ 'win_libs': [
+ 'advapi32',
+ 'crypt32',
+ 'iphlpapi',
+ 'secur32',
+ 'shell32',
+ 'shlwapi',
+ 'user32',
+ 'wininet',
+ 'ws2_32'
+ ]}
+ params = CombineDicts(kwargs, common_app_params)
+ else:
+ params = kwargs
+ return ExtendComponent(env, 'ComponentProgram', **params)
+
+def WiX(env, **kwargs):
+ """ Extends the WiX builder
+ Args:
+ env: The current environment.
+ kwargs: The keyword arguments.
+
+ Returns:
+ The node produced by the environment's wix builder
+ """
+ return ExtendComponent(env, 'WiX', **kwargs)
+
+def Repository(env, at, path):
+ """Maps a directory external to $MAIN_DIR to the given path so that sources
+ compiled from it end up in the correct place under $OBJ_DIR. NOT required
+ when only referring to header files.
+
+ Args:
+ env: The current environment object.
+ at: The 'mount point' within the current directory.
+ path: Path to the actual directory.
+ """
+ env.Dir(at).addRepository(env.Dir(path))
+
+
+def Components(*paths):
+ """Completes the directory paths with the correct file
+ names such that the directory/directory.scons name
+ convention can be used.
+
+ Args:
+ paths: The paths to complete. If it refers to an existing
+ file then it is ignored.
+
+ Returns:
+ The completed lif scons files that are needed to build talk.
+ """
+ files = []
+ for path in paths:
+ if os.path.isfile(path):
+ files.append(path)
+ else:
+ files.append(ExpandSconsPath(path))
+ return files
+
+
+def ExpandSconsPath(path):
+ """Expands a directory path into the path to the
+ scons file that our build uses.
+ Ex: magiflute/plugin/common => magicflute/plugin/common/common.scons
+
+ Args:
+ path: The directory path to expand.
+
+ Returns:
+ The expanded path.
+ """
+ return '%s/%s.scons' % (path, os.path.basename(path))
+
+
+def AddMediaLibs(env, **kwargs):
+ lmi_libdir = '$GOOGLE3/third_party/lmi/files/merged/lib/'
+ if env.Bit('windows'):
+ if env.get('COVERAGE_ENABLED'):
+ lmi_libdir += 'win32/c_only'
+ else:
+ lmi_libdir += 'win32/Release'
+ elif env.Bit('mac'):
+ lmi_libdir += 'macos'
+ elif env.Bit('linux'):
+ lmi_libdir += 'linux/x86'
+
+ ipp_libdir = '$GOOGLE3/third_party/Intel_ipp/%s/ia32/lib'
+ if env.Bit('windows'):
+ ipp_libdir %= 'v_5_2_windows'
+ elif env.Bit('mac'):
+ ipp_libdir %= 'v_5_3_mac_os_x'
+ elif env.Bit('linux'):
+ ipp_libdir %= 'v_5_2_linux'
+
+ AddToDict(kwargs, 'libdirs', [
+ '$MAIN_DIR/third_party/gips/Libraries/',
+ ipp_libdir,
+ lmi_libdir,
+ ])
+
+ gips_lib = ''
+ if env.Bit('windows'):
+ if env.Bit('debug'):
+ gips_lib = 'gipsvoiceenginelib_mtd'
+ else:
+ gips_lib = 'gipsvoiceenginelib_mt'
+ elif env.Bit('mac'):
+ gips_lib = 'VoiceEngine_mac_universal_gcc'
+ elif env.Bit('linux'):
+ gips_lib = 'VoiceEngine_Linux_external_gcc'
+
+ AddToDict(kwargs, 'libs', [
+ gips_lib,
+ 'LmiAudioCommon',
+ 'LmiClient',
+ 'LmiCmcp',
+ 'LmiDeviceManager',
+ 'LmiH263ClientPlugIn',
+ 'LmiH263CodecCommon',
+ 'LmiH263Decoder',
+ 'LmiH263Encoder',
+ 'LmiH264ClientPlugIn',
+ 'LmiH264CodecCommon',
+ 'LmiH264Common',
+ 'LmiH264Decoder',
+ 'LmiH264Encoder',
+ 'LmiIce',
+ 'LmiMediaPayload',
+ 'LmiOs',
+ 'LmiPacketCache',
+ 'LmiProtocolStack',
+ 'LmiRateShaper',
+ 'LmiRtp',
+ 'LmiSecurity',
+ 'LmiSignaling',
+ 'LmiStun',
+ 'LmiTransport',
+ 'LmiUi',
+ 'LmiUtils',
+ 'LmiVideoCommon',
+ 'LmiXml',
+ 'ippsmerged',
+ 'ippsemerged',
+ 'ippvcmerged',
+ 'ippvcemerged',
+ 'ippimerged',
+ 'ippiemerged',
+ 'ippsrmerged',
+ 'ippsremerged',
+ ])
+
+ if env.Bit('windows'):
+ AddToDict(kwargs, 'libs', [
+ 'dsound',
+ 'd3d9',
+ 'gdi32',
+ 'ippcorel',
+ 'ippscmerged',
+ 'ippscemerged',
+ 'strmiids',
+ ])
+ else:
+ AddToDict(kwargs, 'libs', [
+ 'ippcore',
+ 'ippacmerged',
+ 'ippacemerged',
+ 'ippccmerged',
+ 'ippccemerged',
+ 'ippchmerged',
+ 'ippchemerged',
+ 'ippcvmerged',
+ 'ippcvemerged',
+ 'ippdcmerged',
+ 'ippdcemerged',
+ 'ippjmerged',
+ 'ippjemerged',
+ 'ippmmerged',
+ 'ippmemerged',
+ 'ipprmerged',
+ 'ippremerged',
+ ])
+
+ return kwargs
+
+
+def ReadVersion(filename):
+ """Executes the supplied file and pulls out a version definition from it. """
+ defs = {}
+ execfile(str(filename), defs)
+ if not defs.has_key('version'):
+ return '0.0.0.0'
+ version = defs['version']
+ parts = version.split(',')
+ build = os.environ.get('GOOGLE_VERSION_BUILDNUMBER')
+ if build:
+ parts[-1] = str(build)
+ return '.'.join(parts)
+
+
+#-------------------------------------------------------------------------------
+# Helper methods for translating talk.Foo() declarations in to manipulations of
+# environmuent construction variables, including parameter parsing and merging,
+#
+def GetEntry(dict, key):
+ """Get the value from a dictionary by key. If the key
+ isn't in the dictionary then None is returned. If it is in
+ the dictionaruy the value is fetched and then is it removed
+ from the dictionary.
+
+ Args:
+ key: The key to get the value for.
+ kwargs: The keyword argument dictionary.
+ Returns:
+ The value or None if the key is missing.
+ """
+ value = None
+ if dict.has_key(key):
+ value = dict[key]
+ dict.pop(key)
+
+ return value
+
+
+def MergeAndFilterByPlatform(env, params):
+ """Take a dictionary of arguments to lists of values, and, depending on
+ which platform we are targetting, merge the lists of associated keys.
+ Merge by combining value lists like so:
+ {win_foo = [a,b], lin_foo = [c,d], foo = [e], mac_bar = [f], bar = [g] }
+ becomes {foo = [a,b,e], bar = [g]} on windows, and
+ {foo = [e], bar = [f,g]} on mac
+
+ Args:
+ env: The hammer environment which knows which platforms are active
+ params: The keyword argument dictionary.
+ Returns:
+ A new dictionary with the filtered and combined entries of params
+ """
+ platforms = {
+ 'linux': 'lin_',
+ 'mac': 'mac_',
+ 'posix': 'posix_',
+ 'windows': 'win_',
+ }
+ active_prefixes = [
+ platforms[x] for x in iter(platforms) if env.Bit(x)
+ ]
+ inactive_prefixes = [
+ platforms[x] for x in iter(platforms) if not env.Bit(x)
+ ]
+
+ merged = {}
+ for arg, values in params.iteritems():
+ inactive_platform = False
+
+ key = arg
+
+ for prefix in active_prefixes:
+ if arg.startswith(prefix):
+ key = arg[len(prefix):]
+
+ for prefix in inactive_prefixes:
+ if arg.startswith(prefix):
+ inactive_platform = True
+
+ if inactive_platform:
+ continue
+
+ AddToDict(merged, key, values)
+
+ return merged
+
+
+def ExtendComponent(env, component, **kwargs):
+ """A wrapper around a scons builder function that preprocesses and post-
+ processes its inputs and outputs. For example, it merges and filters
+ certain keyword arguments before appending them to the environments
+ construction variables. It can build signed targets and 64bit copies
+ of targets as well.
+
+ Args:
+ env: The hammer environment with which to build the target
+ component: The environment's builder function, e.g. ComponentProgram
+ kwargs: keyword arguments that are either merged, translated, and passed on
+ to the call to component, or which control execution.
+ TODO(): Document the fields, such as cppdefines->CPPDEFINES,
+ prepend_includedirs, include_talk_media_libs, etc.
+ Returns:
+ The output node returned by the call to component, or a subsequent signed
+ dependant node.
+ """
+ env = env.Clone()
+
+ # get the 'target' field
+ name = GetEntry(kwargs, 'name')
+
+ # if this is a signed binary we need to make an unsigned version first
+ signed = env.Bit('windows') and GetEntry(kwargs, 'signed')
+ if signed:
+ name = 'unsigned_' + name
+
+ also64bit = env.Bit('linux') and GetEntry(kwargs, 'also64bit')
+
+ # add default values
+ if GetEntry(kwargs, 'include_talk_media_libs'):
+ kwargs = AddMediaLibs(env, **kwargs)
+
+ # prune parameters intended for other platforms, then merge
+ params = MergeAndFilterByPlatform(env, kwargs)
+
+ # potentially exit now
+ srcs = GetEntry(params, 'srcs')
+ if not srcs or not hasattr(env, component):
+ return None
+
+ # apply any explicit dependencies
+ dependencies = GetEntry(kwargs, 'depends')
+ if dependencies is not None:
+ env.Depends(name, dependencies)
+
+ # put the contents of params into the environment
+ # some entries are renamed then appended, others renamed then prepended
+ appends = {
+ 'cppdefines' : 'CPPDEFINES',
+ 'libdirs' : 'LIBPATH',
+ 'link_flags' : 'LINKFLAGS',
+ 'libs' : 'LIBS',
+ 'FRAMEWORKS' : 'FRAMEWORKS',
+ }
+ prepends = {
+ 'ccflags' : 'CCFLAGS',
+ }
+ if GetEntry(params, 'prepend_includedirs'):
+ prepends['includedirs'] = 'CPPPATH'
+ else:
+ appends['includedirs'] = 'CPPPATH'
+
+ for field, var in appends.items():
+ values = GetEntry(params, field)
+ if values is not None:
+ env.Append(**{var : values})
+ for field, var in prepends.items():
+ values = GetEntry(params, field)
+ if values is not None:
+ env.Prepend(**{var : values})
+
+ # workaround for pulse stripping link flag for unknown reason
+ if env.Bit('linux'):
+ env['SHLINKCOM'] = ('$SHLINK -o $TARGET -m32 $SHLINKFLAGS $SOURCES '
+ '$_LIBDIRFLAGS $_LIBFLAGS')
+ env['LINKCOM'] = ('$LINK -o $TARGET -m32 $LINKFLAGS $SOURCES '
+ '$_LIBDIRFLAGS $_LIBFLAGS')
+
+ # any other parameters are replaced without renaming
+ for field, value in params.items():
+ env.Replace(**{field : value})
+
+ # invoke the builder function
+ builder = getattr(env, component)
+
+ node = builder(name, srcs)
+
+ # make a parallel 64bit version if requested
+ if also64bit:
+ env_64bit = env.Clone()
+ env_64bit.FilterOut(CCFLAGS = ['-m32'], LINKFLAGS = ['-m32'])
+ env_64bit.Prepend(CCFLAGS = ['-m64', '-fPIC'], LINKFLAGS = ['-m64'])
+ name_64bit = name + '64'
+ env_64bit.Replace(OBJSUFFIX = '64' + env_64bit['OBJSUFFIX'])
+ env_64bit.Replace(SHOBJSUFFIX = '64' + env_64bit['SHOBJSUFFIX'])
+ if ('ComponentProgram' == component or
+ ('ComponentLibrary' == component and
+ env_64bit['COMPONENT_STATIC'] == False)):
+ # link 64 bit versions of libraries
+ libs = []
+ for lib in env_64bit['LIBS']:
+ if lib in set(libs64):
+ libs.append(lib + '64')
+ else:
+ libs.append(lib)
+ env_64bit.Replace(LIBS = libs)
+
+ env_64bit['SHLINKCOM'] = ('$SHLINK -o $TARGET -m64 $SHLINKFLAGS $SOURCES '
+ '$_LIBDIRFLAGS $_LIBFLAGS')
+ env_64bit['LINKCOM'] = ('$LINK -o $TARGET -m64 $LINKFLAGS $SOURCES '
+ '$_LIBDIRFLAGS $_LIBFLAGS')
+ builder = getattr(env_64bit, component)
+ nodes = [node, builder(name_64bit, srcs)]
+ return nodes
+
+ if signed: # Note currently incompatible with 64Bit flag
+ # Get the name of the built binary, then get the name of the final signed
+ # version from it. We need the output path since we don't know the file
+ # extension beforehand.
+ target = node[0].path.split('_', 1)[1]
+ signed_node = env.SignedBinary(
+ source = node,
+ target = '$STAGING_DIR/' + target,
+ )
+ env.Alias('signed_binaries', signed_node)
+ return signed
+
+ return node
+
+
+def AddToDict(dictionary, key, values, append=True):
+ """Merge the given key value(s) pair into a dictionary. If it contains an
+ entry with that key already, then combine by appending or prepending the
+ values as directed. Otherwise, assign a new keyvalue pair.
+ """
+ if values is None:
+ return
+
+ if not dictionary.has_key(key):
+ dictionary[key] = values
+ return
+
+ cur = dictionary[key]
+ # TODO: Make sure that there are no duplicates
+ # in the list. I can't use python set for this since
+ # the nodes that are returned by the SCONS builders
+ # are not hashable.
+ # dictionary[key] = list(set(cur).union(set(values)))
+ if append:
+ dictionary[key] = cur + values
+ else:
+ dictionary[key] = values + cur
+
+
+def CombineDicts(a, b):
+ """Unions two dictionaries by combining values of keys shared between them.
+ """
+ c = {}
+ for key in a:
+ if b.has_key(key):
+ c[key] = a[key] + b.pop(key)
+ else:
+ c[key] = a[key]
+
+ for key in b:
+ c[key] = b[key]
+
+ return c
+
+
+def RenameKey(d, old, new, append=True):
+ AddToDict(d, new, GetEntry(d, old), append)
diff --git a/talk/site_scons/talk.pyc b/talk/site_scons/talk.pyc
new file mode 100644
index 0000000..308d2e8
--- /dev/null
+++ b/talk/site_scons/talk.pyc
Binary files differ
diff --git a/talk/third_party/Makefile.am b/talk/third_party/Makefile.am
deleted file mode 100755
index e2d0b36..0000000
--- a/talk/third_party/Makefile.am
+++ /dev/null
@@ -1,9 +0,0 @@
-if PHONE
-
-if !GIPS
-SUBDIRS=mediastreamer
-else
-SUBDIRS=gips
-endif
-
-endif
diff --git a/talk/third_party/gips/Makefile.am b/talk/third_party/gips/Makefile.am
deleted file mode 100755
index f98dbb7..0000000
--- a/talk/third_party/gips/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST=expiration.h
diff --git a/talk/third_party/gips/expiration.h b/talk/third_party/gips/expiration.h
deleted file mode 100755
index 8dc22d1..0000000
--- a/talk/third_party/gips/expiration.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#define GIPS_EXPIRATION_MONTH 0
-#define GIPS_EXPIRATION_DAY 0
-#define GIPS_EXPIRATION_YEAR 0
-
-// Remove this line after setting the expiration date
-#error You must set the VoiceEngine Lite expiration date in third_party/gips/expiration.h
diff --git a/talk/third_party/mediastreamer/Makefile.am b/talk/third_party/mediastreamer/Makefile.am
deleted file mode 100755
index 9dcf686..0000000
--- a/talk/third_party/mediastreamer/Makefile.am
+++ /dev/null
@@ -1,91 +0,0 @@
-noinst_LTLIBRARIES = libmediastreamer.la
-libmediastreamer_la_SOURCES=msfilter.c msfilter.h msutils.h waveheader.h\
- mscodec.c mscodec.h \
- mssoundread.c mssoundread.h \
- mssoundwrite.c mssoundwrite.h \
- msbuffer.c msbuffer.h \
- msqueue.c msqueue.h \
- msfifo.c msfifo.h \
- ms.c ms.h\
- mssync.c mssync.h \
- msnosync.c msnosync.h \
- msread.c msread.h \
- mswrite.c mswrite.h \
- mscopy.c mscopy.h \
- msosswrite.c msosswrite.h \
- msossread.c msossread.h \
- msringplayer.c msringplayer.h \
- msrtprecv.c msrtprecv.h \
- msrtpsend.c msrtpsend.h \
- msAlawenc.c msAlawenc.h g711common.h \
- msAlawdec.c msAlawdec.h g711common.h \
- msMUlawenc.c msMUlawenc.h g711common.h \
- msMUlawdec.c msMUlawdec.h g711common.h \
- mstimer.c mstimer.h \
- msqdispatcher.c msqdispatcher.h \
- msfdispatcher.c msfdispatcher.h \
- sndcard.c sndcard.h \
- osscard.c osscard.h\
- hpuxsndcard.c \
- alsacard.c alsacard.h \
- jackcard.c jackcard.h \
- audiostream.c mediastream.h \
- msspeexenc.c msspeexenc.h msspeexdec.c msspeexdec.h \
- msilbcdec.c msilbcdec.h msilbcenc.c msilbcenc.h
-
-noinst_HEADERS = affine.h \
- msAlawenc.h \
- msfdispatcher.h \
- msilbcdec.h \
- msnosync.h \
- msringplayer.h \
- msspeexdec.h \
- msutils.h \
- waveheader.h \
- alsacard.h \
- msavdecoder.h \
- msfifo.h \
- msilbcenc.h \
- msossread.h \
- msrtprecv.h \
- msspeexenc.h \
- msv4l.h \
- g711common.h \
- msavencoder.h \
- msfilter.h \
- msLPC10decoder.h \
- msosswrite.h \
- msrtpsend.h \
- mssync.h \
- msvideosource.h \
- jackcard.h \
- msbuffer.h \
- msGSMdecoder.h \
- msLPC10encoder.h \
- msqdispatcher.h \
- mssdlout.h \
- mstimer.h \
- mswrite.h \
- mediastream.h \
- mscodec.h \
- msGSMencoder.h \
- msMUlawdec.h \
- msqueue.h \
- mssoundread.h \
- mstruespeechdecoder.h \
- osscard.h \
- msAlawdec.h \
- mscopy.h \
- ms.h \
- msMUlawenc.h \
- msread.h \
- mssoundwrite.h \
- mstruespeechencoder.h \
- sndcard.h
-
-
-libmediastreamer_la_LIBADD= $(GLIB_LIBS) $(ORTP_LIBS)
-
-AM_CFLAGS=$(GLIB_CFLAGS) -D__ALSA_ENABLED__ -DHAVE_ALSA_ASOUNDLIB_H -DG_LOG_DOMAIN=\"MediaStreamer\" $(ORTP_CFLAGS) $(IPV6_CFLAGS) $(ILBC_CFLAGS) $(SPEEX_CFLAGS)
-
-INCLUDES= -I$(top_srcdir) $(ORTP_CFLAGS)
diff --git a/talk/third_party/mediastreamer/affine.h b/talk/third_party/mediastreamer/affine.h
deleted file mode 100755
index 620fdc9..0000000
--- a/talk/third_party/mediastreamer/affine.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * affine.h -- Affine Transforms for 2d objects
- * Copyright (C) 2002 Charles Yates <charles.yates@pandora.be>
- * Portions Copyright (C) 2003 Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _AFFINE_H
-#define _AFFINE_H
-
-#include <math.h>
-
-/** Affine transforms for 2d image manipulation. Current provides shearing and
- rotating support.
-*/
-
-typedef struct {
- double matrix[2][2];
-} affine_transform_t;
-
-void affine_transform_init( affine_transform_t *this );
-void affine_transform_rotate( affine_transform_t *this, double angle );
-void affine_transform_shear( affine_transform_t *this, double shear );
-void affine_transform_scale( affine_transform_t *this, double sx, double sy );
-double affine_transform_mapx( affine_transform_t *this, int x, int y );
-double affine_transform_mapy( affine_transform_t *this, int x, int y );
-void affine_scale( const unsigned char *src, unsigned char *dest, int src_width, int src_height, int dest_width, int dest_height, int bpp );
-
-#endif
-
diff --git a/talk/third_party/mediastreamer/alsacard.c b/talk/third_party/mediastreamer/alsacard.c
deleted file mode 100755
index ebf2909..0000000
--- a/talk/third_party/mediastreamer/alsacard.c
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "alsacard.h"
-
-#ifdef HAVE_ALSA_ASOUNDLIB_H
-
-static gchar *over_pcmdev=NULL;
-
-#include "msossread.h"
-#include "msosswrite.h"
-
-#include <signal.h>
-
-int __alsa_card_write(AlsaCard *obj,char *buf,int size);
-
-int alsa_set_params(AlsaCard *obj, int rw, int bits, int stereo, int rate)
-{
- snd_pcm_hw_params_t *hwparams=NULL;
- snd_pcm_sw_params_t *swparams=NULL;
- snd_pcm_t *pcm_handle;
- gint dir,exact_value;
- gint channels;
- gint fsize=0;
- gint periods=8;
- gint periodsize=256;
- gint err;
- int format;
-
- if (rw) {
- pcm_handle=obj->write_handle;
- }
- else pcm_handle=obj->read_handle;
-
- /* Allocate the snd_pcm_hw_params_t structure on the stack. */
- snd_pcm_hw_params_alloca(&hwparams);
-
- /* Init hwparams with full configuration space */
- if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
- g_warning("alsa_set_params: Cannot configure this PCM device.\n");
- return(-1);
- }
-
- if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
- g_warning("alsa_set_params: Error setting access.\n");
- return(-1);
- }
- /* Set sample format */
-#ifdef WORDS_BIGENDIAN
- format=SND_PCM_FORMAT_S16_BE;
-#else
- format=SND_PCM_FORMAT_S16_LE;
-#endif
- if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) {
- g_warning("alsa_set_params: Error setting format.\n");
- return(-1);
- }
- /* Set number of channels */
- if (stereo) channels=2;
- else channels=1;
- if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) {
- g_warning("alsa_set_params: Error setting channels.\n");
- return(-1);
- }
- /* Set sample rate. If the exact rate is not supported */
- /* by the hardware, use nearest possible rate. */
- exact_value=rate;
- dir=0;
- if ((err=snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_value, &dir))<0){
- g_warning("alsa_set_params: Error setting rate to %i:%s",rate,snd_strerror(err));
- return -1;
- }
- if (dir != 0) {
- g_warning("alsa_set_params: The rate %d Hz is not supported by your hardware.\n "
- "==> Using %d Hz instead.\n", rate, exact_value);
- }
- /* choose greater period size when rate is high */
- periodsize=periodsize*(rate/8000);
-
- /* Set buffer size (in frames). The resulting latency is given by */
- /* latency = periodsize * periods / (rate * bytes_per_frame) */
- /*
- fsize=periodsize * periods;
- exact_value=fsize;
- if ((err=snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams,&exact_value)) < 0) {
- g_warning("alsa_set_params: Error setting buffer size:%s",snd_strerror(err));
- return(-1);
- }
- if (fsize!= exact_value) {
- g_warning("alsa_set_params: The buffer size %d is not supported by your hardware.\n "
- "==> Using %d instead.\n", fsize, exact_value);
- }
- */
- /* set period size */
- exact_value=periodsize;
- dir=0;
- if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &exact_value, &dir) < 0) {
- g_warning("alsa_set_params: Error setting period size.\n");
- return(-1);
- }
- if (dir != 0) {
- g_warning("alsa_set_params: The period size %d is not supported by your hardware.\n "
- "==> Using %d instead.\n", periodsize, exact_value);
- }
- periodsize=exact_value;
- /* Set number of periods. Periods used to be called fragments. */
- exact_value=periods;
- dir=0;
- if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &exact_value, &dir) < 0) {
- g_warning("alsa_set_params: Error setting periods.\n");
- return(-1);
- }
- if (dir != 0) {
- g_warning("alsa_set_params: The number of periods %d is not supported by your hardware.\n "
- "==> Using %d instead.\n", periods, exact_value);
- }
- /* Apply HW parameter settings to */
- /* PCM device and prepare device */
- if ((err=snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
- g_warning("alsa_set_params: Error setting HW params:%s",snd_strerror(err));
- return(-1);
- }
- /*prepare sw params */
- if (rw){
- snd_pcm_sw_params_alloca(&swparams);
- snd_pcm_sw_params_current(pcm_handle, swparams);
- if ((err=snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams,periodsize*2 ))<0){
- g_warning("alsa_set_params: Error setting start threshold:%s",snd_strerror(err));
- return -1;
- }
- if ((err=snd_pcm_sw_params(pcm_handle, swparams))<0){
- g_warning("alsa_set_params: Error setting SW params:%s",snd_strerror(err));
- return(-1);
- }
- }
- obj->frame_size=channels*(bits/8);
- SND_CARD(obj)->bsize=periodsize*obj->frame_size;
- //SND_CARD(obj)->bsize=4096;
- obj->frames=periodsize;
- g_message("alsa_set_params: blocksize=%i.",SND_CARD(obj)->bsize);
- return SND_CARD(obj)->bsize;
-}
-
-int alsa_card_open_r(AlsaCard *obj,int bits,int stereo,int rate)
-{
- int bsize;
- int err;
- snd_pcm_t *pcm_handle;
- gchar *pcmdev;
- if (over_pcmdev!=NULL) pcmdev=over_pcmdev;
- else pcmdev=obj->pcmdev;
-
- if (snd_pcm_open(&pcm_handle, pcmdev,SND_PCM_STREAM_CAPTURE,SND_PCM_NONBLOCK) < 0) {
- g_warning("alsa_card_open_r: Error opening PCM device %s\n",obj->pcmdev );
- return -1;
- }
- g_return_val_if_fail(pcm_handle!=NULL,-1);
- obj->read_handle=pcm_handle;
- if ((bsize=alsa_set_params(obj,0,bits,stereo,rate))<0){
- snd_pcm_close(pcm_handle);
- obj->read_handle=NULL;
- return -1;
- }
- obj->readbuf=g_malloc0(bsize);
-
- err=snd_pcm_start(obj->read_handle);
- if (err<0){
- g_warning("Cannot start read pcm: %s", snd_strerror(err));
- }
- obj->readpos=0;
- SND_CARD(obj)->bsize=bsize;
- SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
- return 0;
-}
-
-int alsa_card_open_w(AlsaCard *obj,int bits,int stereo,int rate)
-{
- int err,bsize;
- snd_pcm_t *pcm_handle;
- gchar *pcmdev;
- if (over_pcmdev!=NULL) pcmdev=over_pcmdev;
- else pcmdev=obj->pcmdev;
-
- if (snd_pcm_open(&pcm_handle, pcmdev,SND_PCM_STREAM_PLAYBACK,SND_PCM_NONBLOCK) < 0) {
- g_warning("alsa_card_open_w: Error opening PCM device %s\n", obj->pcmdev);
- return -1;
- }
- obj->write_handle=pcm_handle;
- if ((bsize=alsa_set_params(obj,1,bits,stereo,rate))<0){
- snd_pcm_close(pcm_handle);
- obj->write_handle=NULL;
- return -1;
- }
- obj->writebuf=g_malloc0(bsize);
-
- obj->writepos=0;
- SND_CARD(obj)->bsize=bsize;
- SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
- return 0;
-}
-
-
-void alsa_card_set_blocking_mode(AlsaCard *obj, gboolean yesno){
- if (obj->read_handle!=NULL) snd_pcm_nonblock(obj->read_handle,!yesno);
- if (obj->write_handle!=NULL) snd_pcm_nonblock(obj->write_handle,!yesno);
-}
-
-void alsa_card_close_r(AlsaCard *obj)
-{
- if (obj->read_handle!=NULL){
- snd_pcm_close(obj->read_handle);
- obj->read_handle=NULL;
- g_free(obj->readbuf);
- obj->readbuf=NULL;
- }
-}
-
-void alsa_card_close_w(AlsaCard *obj)
-{
- if (obj->write_handle!=NULL){
- snd_pcm_close(obj->write_handle);
- obj->write_handle=NULL;
- g_free(obj->writebuf);
- obj->writebuf=NULL;
- }
-}
-
-int alsa_card_probe(AlsaCard *obj,int bits,int stereo,int rate)
-{
- int ret;
- ret=alsa_card_open_w(obj,bits,stereo,rate);
- if (ret<0) return -1;
- ret=SND_CARD(obj)->bsize;
- alsa_card_close_w(obj);
- return ret;
-}
-
-
-void alsa_card_destroy(AlsaCard *obj)
-{
- snd_card_uninit(SND_CARD(obj));
- g_free(obj->pcmdev);
- if (obj->readbuf!=0) g_free(obj->readbuf);
- if (obj->writebuf!=0) g_free(obj->writebuf);
-}
-
-gboolean alsa_card_can_read(AlsaCard *obj)
-{
- int frames;
- g_return_val_if_fail(obj->read_handle!=NULL,0);
- if (obj->readpos!=0) return TRUE;
- if ( frames=snd_pcm_avail_update(obj->read_handle)>=obj->frames) return 1;
- //g_message("frames=%i",frames);
- return 0;
-}
-
-
-
-int __alsa_card_read(AlsaCard *obj,char *buf,int bsize)
-{
- int err;
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set,SIGALRM);
- sigprocmask(SIG_BLOCK,&set,NULL);
- err=snd_pcm_readi(obj->read_handle,buf,bsize/obj->frame_size);
- if (err<0) {
- if (err!=-EPIPE){
- g_warning("alsa_card_read: snd_pcm_readi() failed:%s.",snd_strerror(err));
- }
- snd_pcm_prepare(obj->read_handle);
- err=snd_pcm_readi(obj->read_handle,buf,bsize/obj->frame_size);
- if (err<0) g_warning("alsa_card_read: snd_pcm_readi() failed:%s.",snd_strerror(err));
- }
- sigprocmask(SIG_UNBLOCK,&set,NULL);
- return err*obj->frame_size;
-}
-
-int alsa_card_read(AlsaCard *obj,char *buf,int size)
-{
- int err;
- gint bsize=SND_CARD(obj)->bsize;
- g_return_val_if_fail(obj->read_handle!=NULL,-1);
- if (size<bsize){
- gint canread=MIN(bsize-obj->readpos,size);
-
- if (obj->readpos==0){
- err=__alsa_card_read(obj,obj->readbuf,bsize);
- }
-
- memcpy(buf,&obj->readbuf[obj->readpos],canread);
- obj->readpos+=canread;
- if (obj->readpos>=bsize) obj->readpos=0;
- return canread;
- }else{
- err=__alsa_card_read(obj,buf,size);
- return err;
- }
-
-}
-
-int __alsa_card_write(AlsaCard *obj,char *buf,int size)
-{
- int err;
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set,SIGALRM);
- sigprocmask(SIG_BLOCK,&set,NULL);
- if ((err=snd_pcm_writei(obj->write_handle,buf,size/obj->frame_size))<0){
- if (err!=-EPIPE){
- g_warning("alsa_card_write: snd_pcm_writei() failed:%s.",snd_strerror(err));
- }
- snd_pcm_prepare(obj->write_handle);
- err=snd_pcm_writei(obj->write_handle,buf,size/obj->frame_size);
- if (err<0) g_warning("alsa_card_write: Error writing sound buffer (size=%i):%s",size,snd_strerror(err));
-
- }
- sigprocmask(SIG_UNBLOCK,&set,NULL);
- return err;
-}
-
-int alsa_card_write(AlsaCard *obj,char *buf,int size)
-{
- int err;
- gint bsize=SND_CARD(obj)->bsize;
- g_return_val_if_fail(obj->write_handle!=NULL,-1);
- if (size<bsize){
- gint canwrite;
-
- canwrite=MIN(bsize-obj->writepos,size);
- memcpy(&obj->writebuf[obj->writepos],buf,canwrite);
- obj->writepos+=canwrite;
- if (obj->writepos>=bsize){
- err=__alsa_card_write(obj,obj->writebuf,bsize);
- obj->writepos=0;
- }
- return canwrite;
- }else{
- return __alsa_card_write(obj,buf,bsize);
- }
-}
-
-snd_mixer_t *alsa_mixer_open(AlsaCard *obj){
- snd_mixer_t *mixer=NULL;
- int err;
- err=snd_mixer_open(&mixer,0);
- if (err<0){
- g_warning("Could not open alsa mixer: %s",snd_strerror(err));
- return NULL;
- }
- if ((err = snd_mixer_attach (mixer, obj->mixdev)) < 0){
- g_warning("Could not attach mixer to card: %s",snd_strerror(err));
- snd_mixer_close(mixer);
- return NULL;
- }
- if ((err = snd_mixer_selem_register (mixer, NULL, NULL)) < 0){
- g_warning("snd_mixer_selem_register: %s",snd_strerror(err));
- snd_mixer_close(mixer);
- return NULL;
- }
- if ((err = snd_mixer_load (mixer)) < 0){
- g_warning("snd_mixer_load: %s",snd_strerror(err));
- snd_mixer_close(mixer);
- return NULL;
- }
- obj->mixer=mixer;
- return mixer;
-}
-
-void alsa_mixer_close(AlsaCard *obj){
- snd_mixer_close(obj->mixer);
- obj->mixer=NULL;
-}
-
-typedef enum {CAPTURE, PLAYBACK, CAPTURE_SWITCH, PLAYBACK_SWITCH} MixerAction;
-
-static gint get_mixer_element(snd_mixer_t *mixer,const char *name, MixerAction action){
- long value=0;
- const char *elemname;
- snd_mixer_elem_t *elem;
- int err;
- long sndMixerPMin;
- long sndMixerPMax;
- long newvol;
- elem=snd_mixer_first_elem(mixer);
- while (elem!=NULL){
- elemname=snd_mixer_selem_get_name(elem);
- //g_message("Found alsa mixer element %s.",elemname);
- if (strcmp(elemname,name)==0){
- switch (action){
- case CAPTURE:
- if (snd_mixer_selem_has_capture_volume(elem)){
- snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
- err=snd_mixer_selem_get_capture_volume(elem,SND_MIXER_SCHN_UNKNOWN,&newvol);
- newvol-=sndMixerPMin;
- value=(100*newvol)/(sndMixerPMax-sndMixerPMin);
- if (err<0) g_warning("Could not get capture volume for %s:%s",name,snd_strerror(err));
- //else g_message("Succesfully get capture level for %s.",elemname);
- break;
- }
- break;
- case PLAYBACK:
- if (snd_mixer_selem_has_playback_volume(elem)){
- snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
- err=snd_mixer_selem_get_playback_volume(elem,SND_MIXER_SCHN_FRONT_LEFT,&newvol);
- newvol-=sndMixerPMin;
- value=(100*newvol)/(sndMixerPMax-sndMixerPMin);
- if (err<0) g_warning("Could not get playback volume for %s:%s",name,snd_strerror(err));
- //else g_message("Succesfully get playback level for %s.",elemname);
- break;
- }
- break;
- case CAPTURE_SWITCH:
-
- break;
- }
- }
- elem=snd_mixer_elem_next(elem);
- }
-
- return value;
-}
-
-
-static void set_mixer_element(snd_mixer_t *mixer,const char *name, gint level,MixerAction action){
- const char *elemname;
- snd_mixer_elem_t *elem;
- int tmp;
- long sndMixerPMin;
- long sndMixerPMax;
- long newvol;
-
- elem=snd_mixer_first_elem(mixer);
-
- while (elem!=NULL){
- elemname=snd_mixer_selem_get_name(elem);
- //g_message("Found alsa mixer element %s.",elemname);
- if (strcmp(elemname,name)==0){
- switch(action){
- case CAPTURE:
- if (snd_mixer_selem_has_capture_volume(elem)){
- snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
- newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin;
- snd_mixer_selem_set_capture_volume_all(elem,newvol);
- //g_message("Succesfully set capture level for %s.",elemname);
- return;
- }
- break;
- case PLAYBACK:
- if (snd_mixer_selem_has_playback_volume(elem)){
- snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
- newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin;
- snd_mixer_selem_set_playback_volume_all(elem,newvol);
- //g_message("Succesfully set playback level for %s.",elemname);
- return;
- }
- break;
- case CAPTURE_SWITCH:
- if (snd_mixer_selem_has_capture_switch(elem)){
- snd_mixer_selem_set_capture_switch_all(elem,level);
- //g_message("Succesfully set capture switch for %s.",elemname);
- }
- break;
- case PLAYBACK_SWITCH:
- if (snd_mixer_selem_has_playback_switch(elem)){
- snd_mixer_selem_set_playback_switch_all(elem,level);
- //g_message("Succesfully set capture switch for %s.",elemname);
- }
- break;
-
- }
- }
- elem=snd_mixer_elem_next(elem);
- }
-
- return ;
-}
-
-
-void alsa_card_set_level(AlsaCard *obj,gint way,gint a)
-{
- snd_mixer_t *mixer;
- mixer=alsa_mixer_open(obj);
- if (mixer==NULL) return ;
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- set_mixer_element(mixer,"Master",a,PLAYBACK);
- break;
- case SND_CARD_LEVEL_INPUT:
- set_mixer_element(mixer,"Capture",a,CAPTURE);
- break;
- case SND_CARD_LEVEL_OUTPUT:
- set_mixer_element(mixer,"PCM",a,PLAYBACK);
- break;
- default:
- g_warning("oss_card_set_level: unsupported command.");
- }
- alsa_mixer_close(obj);
-}
-
-gint alsa_card_get_level(AlsaCard *obj,gint way)
-{
- snd_mixer_t *mixer;
- gint value;
- mixer=alsa_mixer_open(obj);
- if (mixer==NULL) return 0;
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- value=get_mixer_element(mixer,"Master",PLAYBACK);
- break;
- case SND_CARD_LEVEL_INPUT:
- value=get_mixer_element(mixer,"Capture",CAPTURE);
- break;
- case SND_CARD_LEVEL_OUTPUT:
- value=get_mixer_element(mixer,"PCM",PLAYBACK);
- break;
- default:
- g_warning("oss_card_set_level: unsupported command.");
- }
- alsa_mixer_close(obj);
- return value;
-}
-
-void alsa_card_set_source(AlsaCard *obj,int source)
-{
- snd_mixer_t *mixer;
- mixer=alsa_mixer_open(obj);
- if (mixer==NULL) return;
- switch (source){
- case 'm':
- set_mixer_element(mixer,"Mic",1,CAPTURE_SWITCH);
- set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH);
- break;
- case 'l':
- set_mixer_element(mixer,"Line",1,CAPTURE_SWITCH);
- set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH);
- break;
- }
-}
-
-MSFilter *alsa_card_create_read_filter(AlsaCard *card)
-{
- MSFilter *f=ms_oss_read_new();
- ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index);
- return f;
-}
-
-MSFilter *alsa_card_create_write_filter(AlsaCard *card)
-{
- MSFilter *f=ms_oss_write_new();
- ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index);
- return f;
-}
-
-
-SndCard * alsa_card_new(gint devid)
-{
- AlsaCard * obj;
- SndCard *base;
- int err;
- gchar *name=NULL;
-
- /* carefull: this is an alsalib call despite its name! */
- err=snd_card_get_name(devid,&name);
- if (err<0) {
- return NULL;
- }
- obj= g_new0(AlsaCard,1);
- base= SND_CARD(obj);
- snd_card_init(base);
-
- base->card_name=g_strdup_printf("%s (Advanced Linux Sound Architecture)",name);
- base->_probe=(SndCardOpenFunc)alsa_card_probe;
- base->_open_r=(SndCardOpenFunc)alsa_card_open_r;
- base->_open_w=(SndCardOpenFunc)alsa_card_open_w;
- base->_can_read=(SndCardPollFunc)alsa_card_can_read;
- base->_set_blocking_mode=(SndCardSetBlockingModeFunc)alsa_card_set_blocking_mode;
- base->_read=(SndCardIOFunc)alsa_card_read;
- base->_write=(SndCardIOFunc)alsa_card_write;
- base->_close_r=(SndCardCloseFunc)alsa_card_close_r;
- base->_close_w=(SndCardCloseFunc)alsa_card_close_w;
- base->_set_rec_source=(SndCardMixerSetRecSourceFunc)alsa_card_set_source;
- base->_set_level=(SndCardMixerSetLevelFunc)alsa_card_set_level;
- base->_get_level=(SndCardMixerGetLevelFunc)alsa_card_get_level;
- base->_destroy=(SndCardDestroyFunc)alsa_card_destroy;
- base->_create_read_filter=(SndCardCreateFilterFunc)alsa_card_create_read_filter;
- base->_create_write_filter=(SndCardCreateFilterFunc)alsa_card_create_write_filter;
-
-
- obj->pcmdev=g_strdup_printf("plughw:%i,0",devid);
- obj->mixdev=g_strdup_printf("hw:%i",devid);
- obj->readbuf=NULL;
- obj->writebuf=NULL;
- return base;
-}
-
-
-gint alsa_card_manager_init(SndCardManager *m, gint index)
-{
- gint devindex;
- gint i;
- gint found=0;
- gchar *name=NULL;
- for(devindex=0;index<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){
- if (snd_card_get_name(devindex,&name)==0){
- g_message("Found ALSA device: %s",name);
- m->cards[index]=alsa_card_new(devindex);
- m->cards[index]->index=index;
- found++;
- index++;
- }
- }
- return found;
-}
-
-void alsa_card_manager_set_default_pcm_device(const gchar *pcmdev){
- if (over_pcmdev!=NULL){
- g_free(over_pcmdev);
- }
- over_pcmdev=g_strdup(pcmdev);
-}
-
-#endif
diff --git a/talk/third_party/mediastreamer/alsacard.h b/talk/third_party/mediastreamer/alsacard.h
deleted file mode 100755
index e96abc7..0000000
--- a/talk/third_party/mediastreamer/alsacard.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <config.h>
-
-#ifdef HAVE_ALSA_ASOUNDLIB_H
-#include "sndcard.h"
-#define ALSA_PCM_NEW_HW_PARAMS_API
-#include <alsa/asoundlib.h>
-struct _AlsaCard
-{
- SndCard parent;
- gchar *pcmdev;
- gchar *mixdev;
- snd_pcm_t *read_handle;
- snd_pcm_t *write_handle;
- gint frame_size;
- gint frames;
- gchar *readbuf;
- gint readpos;
- gchar *writebuf;
- gint writepos;
- snd_mixer_t *mixer;
-};
-
-typedef struct _AlsaCard AlsaCard;
-
-SndCard *alsa_card_new(gint dev_id);
-gint alsa_card_manager_init(SndCardManager *m, gint index);
-void alsa_card_manager_set_default_pcm_device(const gchar *pcmdev);
-
-#endif
diff --git a/talk/third_party/mediastreamer/audiostream.c b/talk/third_party/mediastreamer/audiostream.c
deleted file mode 100755
index 67a4485..0000000
--- a/talk/third_party/mediastreamer/audiostream.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "mediastream.h"
-#ifdef INET6
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
-#endif
-
-
-#define MAX_RTP_SIZE 1500
-
-/* this code is not part of the library itself, it is part of the mediastream program */
-void audio_stream_free(AudioStream *stream)
-{
- RtpSession *s;
- RtpSession *destroyed=NULL;
- if (stream->rtprecv!=NULL) {
- s=ms_rtp_recv_get_session(MS_RTP_RECV(stream->rtprecv));
- if (s!=NULL){
- destroyed=s;
- rtp_session_destroy(s);
- }
- ms_filter_destroy(stream->rtprecv);
- }
- if (stream->rtpsend!=NULL) {
- s=ms_rtp_send_get_session(MS_RTP_SEND(stream->rtpsend));
- if (s!=NULL){
- if (s!=destroyed)
- rtp_session_destroy(s);
- }
- ms_filter_destroy(stream->rtpsend);
- }
- if (stream->soundread!=NULL) ms_filter_destroy(stream->soundread);
- if (stream->soundwrite!=NULL) ms_filter_destroy(stream->soundwrite);
- if (stream->encoder!=NULL) ms_filter_destroy(stream->encoder);
- if (stream->decoder!=NULL) ms_filter_destroy(stream->decoder);
- if (stream->timer!=NULL) ms_sync_destroy(stream->timer);
- g_free(stream);
-}
-
-static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
-
-static void on_dtmf_received(RtpSession *s,gint dtmf,gpointer user_data)
-{
- AudioStream *stream=(AudioStream*)user_data;
- if (dtmf>15){
- g_warning("Unsupported telephone-event type.");
- return;
- }
- g_message("Receiving dtmf %c.",dtmf_tab[dtmf]);
- if (stream!=NULL){
- if (strcmp(stream->soundwrite->klass->name,"OssWrite")==0)
- ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf_tab[dtmf]);
- }
-}
-
-static void on_timestamp_jump(RtpSession *s,guint32* ts, gpointer user_data)
-{
- g_warning("The remote sip-phone has send data with a future timestamp: %u,"
- "resynchronising session.",*ts);
- rtp_session_reset(s);
-}
-
-static const char *ip4local="0.0.0.0";
-static const char *ip6local="::";
-
-const char *get_local_addr_for(const char *remote)
-{
- const char *ret;
-#ifdef INET6
- char num[8];
- struct addrinfo hints, *res0;
- int err;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
- err = getaddrinfo(remote,"8000", &hints, &res0);
- if (err!=0) {
- g_warning ("get_local_addr_for: %s", gai_strerror(err));
- return ip4local;
- }
- ret=(res0->ai_addr->sa_family==AF_INET6) ? ip6local : ip4local;
- freeaddrinfo(res0);
-#else
- ret=ip4local;
-#endif
- return ret;
-}
-
-void create_duplex_rtpsession(RtpProfile *profile, int locport,char *remip,int remport,
- int payload,int jitt_comp,
- RtpSession **recvsend){
- RtpSession *rtpr;
- rtpr=rtp_session_new(RTP_SESSION_SENDRECV);
- rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE);
- rtp_session_set_profile(rtpr,profile);
- rtp_session_set_local_addr(rtpr,get_local_addr_for(remip),locport);
- if (remport>0) rtp_session_set_remote_addr(rtpr,remip,remport);
- rtp_session_set_scheduling_mode(rtpr,0);
- rtp_session_set_blocking_mode(rtpr,0);
- rtp_session_set_payload_type(rtpr,payload);
- rtp_session_set_jitter_compensation(rtpr,jitt_comp);
- rtp_session_enable_adaptive_jitter_compensation(rtpr,TRUE);
- /*rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL);*/
- *recvsend=rtpr;
-}
-
-void create_rtp_sessions(RtpProfile *profile, int locport,char *remip,int remport,
- int payload,int jitt_comp,
- RtpSession **recv, RtpSession **send){
- RtpSession *rtps,*rtpr;
- PayloadType *pt;
- /* creates two rtp filters to recv send streams (remote part)*/
-
- rtps=rtp_session_new(RTP_SESSION_SENDONLY);
- rtp_session_max_buf_size_set(rtps,MAX_RTP_SIZE);
- rtp_session_set_profile(rtps,profile);
-#ifdef INET6
- rtp_session_set_local_addr(rtps,"::",locport+2);
-#else
- rtp_session_set_local_addr(rtps,"0.0.0.0",locport+2);
-#endif
- rtp_session_set_remote_addr(rtps,remip,remport);
- rtp_session_set_scheduling_mode(rtps,0);
- rtp_session_set_blocking_mode(rtps,0);
- rtp_session_set_payload_type(rtps,payload);
- rtp_session_set_jitter_compensation(rtps,jitt_comp);
-
- rtpr=rtp_session_new(RTP_SESSION_RECVONLY);
- rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE);
- rtp_session_set_profile(rtpr,profile);
-#ifdef INET6
- rtp_session_set_local_addr(rtpr,"::",locport);
-#else
- rtp_session_set_local_addr(rtpr,"0.0.0.0",locport);
-#endif
- rtp_session_set_scheduling_mode(rtpr,0);
- rtp_session_set_blocking_mode(rtpr,0);
- rtp_session_set_payload_type(rtpr,payload);
- rtp_session_set_jitter_compensation(rtpr,jitt_comp);
- rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,NULL);
- rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL);
- *recv=rtpr;
- *send=rtps;
-
-}
-
-
-AudioStream * audio_stream_start_full(RtpProfile *profile, int locport,char *remip,int remport,
- int payload,int jitt_comp, gchar *infile, gchar *outfile, SndCard *playcard, SndCard *captcard)
-{
- AudioStream *stream=g_new0(AudioStream,1);
- RtpSession *rtps,*rtpr;
- PayloadType *pt;
-
- //create_rtp_sessions(profile,locport,remip,remport,payload,jitt_comp,&rtpr,&rtps);
-
- create_duplex_rtpsession(profile,locport,remip,remport,payload,jitt_comp,&rtpr);
- rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,(gpointer)stream);
- rtps=rtpr;
-
- stream->recv_session = rtpr;
- stream->send_session = rtps;
- stream->rtpsend=ms_rtp_send_new();
- ms_rtp_send_set_session(MS_RTP_SEND(stream->rtpsend),rtps);
- stream->rtprecv=ms_rtp_recv_new();
- ms_rtp_recv_set_session(MS_RTP_RECV(stream->rtprecv),rtpr);
-
-
- /* creates the local part */
- if (infile==NULL) stream->soundread=snd_card_create_read_filter(captcard);
- else stream->soundread=ms_read_new(infile);
- if (outfile==NULL) stream->soundwrite=snd_card_create_write_filter(playcard);
- else stream->soundwrite=ms_write_new(outfile);
-
- /* creates the couple of encoder/decoder */
- pt=rtp_profile_get_payload(profile,payload);
- if (pt==NULL){
- g_error("audiostream.c: undefined payload type.");
- return NULL;
- }
- stream->encoder=ms_encoder_new_with_string_id(pt->mime_type);
- stream->decoder=ms_decoder_new_with_string_id(pt->mime_type);
- if ((stream->encoder==NULL) || (stream->decoder==NULL)){
- /* big problem: we have not a registered codec for this payload...*/
- audio_stream_free(stream);
- g_error("mediastream.c: No decoder available for payload %i.",payload);
- return NULL;
- }
- /* give the sound filters some properties */
- ms_filter_set_property(stream->soundread,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
- ms_filter_set_property(stream->soundwrite,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
-
- /* give the encoder/decoder some parameters*/
- ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
- ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate);
- ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate);
- ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate);
-
- ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FMTP, (void*)pt->fmtp);
- ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FMTP,(void*)pt->fmtp);
- /* create the synchronisation source */
- stream->timer=ms_timer_new();
-
- /* and then connect all */
- ms_filter_add_link(stream->soundread,stream->encoder);
- ms_filter_add_link(stream->encoder,stream->rtpsend);
- ms_filter_add_link(stream->rtprecv,stream->decoder);
- ms_filter_add_link(stream->decoder,stream->soundwrite);
-
- ms_sync_attach(stream->timer,stream->soundread);
- ms_sync_attach(stream->timer,stream->rtprecv);
-
- /* and start */
- ms_start(stream->timer);
-
- return stream;
-}
-
-static int defcard=0;
-
-void audio_stream_set_default_card(int cardindex){
- defcard=cardindex;
-}
-
-AudioStream * audio_stream_start_with_files(RtpProfile *prof,int locport,char *remip,
- int remport,int profile,int jitt_comp,gchar *infile, gchar*outfile)
-{
- return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,infile,outfile,NULL,NULL);
-}
-
-AudioStream * audio_stream_start(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp)
-{
- SndCard *sndcard;
- sndcard=snd_card_manager_get_card(snd_card_manager,defcard);
- return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,sndcard,sndcard);
-}
-
-AudioStream *audio_stream_start_with_sndcards(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp,SndCard *playcard, SndCard *captcard)
-{
- g_return_val_if_fail(playcard!=NULL,NULL);
- g_return_val_if_fail(captcard!=NULL,NULL);
- return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,playcard,captcard);
-}
-
-void audio_stream_set_rtcp_information(AudioStream *st, const char *cname){
- if (st->send_session!=NULL){
- rtp_session_set_source_description(st->send_session,cname,NULL,NULL,NULL, NULL,"linphone",
- "This is free software (GPL) !");
- }
-}
-
-void audio_stream_stop(AudioStream * stream)
-{
-
- ms_stop(stream->timer);
- ortp_global_stats_display();
- ms_sync_detach(stream->timer,stream->soundread);
- ms_sync_detach(stream->timer,stream->rtprecv);
-
- ms_filter_remove_links(stream->soundread,stream->encoder);
- ms_filter_remove_links(stream->encoder,stream->rtpsend);
- ms_filter_remove_links(stream->rtprecv,stream->decoder);
- ms_filter_remove_links(stream->decoder,stream->soundwrite);
-
- audio_stream_free(stream);
-}
-
-RingStream * ring_start(gchar *file,gint interval,SndCard *sndcard)
-{
- return ring_start_with_cb(file,interval,sndcard,NULL,NULL);
-}
-
-RingStream * ring_start_with_cb(gchar *file,gint interval,SndCard *sndcard, MSFilterNotifyFunc func,gpointer user_data)
-{
- RingStream *stream;
- int tmp;
- g_return_val_if_fail(sndcard!=NULL,NULL);
- stream=g_new0(RingStream,1);
- stream->source=ms_ring_player_new(file,interval);
- if (stream->source==NULL) {
- g_warning("Could not create ring player. Probably the ring file (%s) does not exist.",file);
- return NULL;
- }
- if (func!=NULL) ms_filter_set_notify_func(MS_FILTER(stream->source),func,user_data);
- stream->sndwrite=snd_card_create_write_filter(sndcard);
- ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_FREQ,&tmp);
- ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_FREQ,&tmp);
- ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_CHANNELS,&tmp);
- ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_CHANNELS,&tmp);
- stream->timer=ms_timer_new();
- ms_filter_add_link(stream->source,stream->sndwrite);
- ms_sync_attach(stream->timer,stream->source);
- ms_start(stream->timer);
- return stream;
-}
-
-void ring_stop(RingStream *stream)
-{
- ms_stop(stream->timer);
- ms_sync_detach(stream->timer,stream->source);
- ms_sync_destroy(stream->timer);
- ms_filter_remove_links(stream->source,stream->sndwrite);
- ms_filter_destroy(stream->source);
- ms_filter_destroy(stream->sndwrite);
- g_free(stream);
-}
-
-/* returns the latency in samples if the audio device with id dev_id is openable in full duplex mode, else 0 */
-gint test_audio_dev(int dev_id)
-{
- gint err;
- SndCard *sndcard=snd_card_manager_get_card(snd_card_manager,dev_id);
- if (sndcard==NULL) return -1;
- err=snd_card_probe(sndcard,16,0,8000);
- return err; /* return latency in number of sample */
-}
-
-gint audio_stream_send_dtmf(AudioStream *stream, gchar dtmf)
-{
- ms_rtp_send_dtmf(MS_RTP_SEND(stream->rtpsend), dtmf);
- ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf);
-}
diff --git a/talk/third_party/mediastreamer/g711common.h b/talk/third_party/mediastreamer/g711common.h
deleted file mode 100755
index 3f5ad16..0000000
--- a/talk/third_party/mediastreamer/g711common.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * PCM - A-Law conversion
- * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- * Wrapper for linphone Codec class by Simon Morlat <simon.morlat@free.fr>
- */
-
-static inline int val_seg(int val)
-{
- int r = 0;
- val >>= 7;
- if (val & 0xf0) {
- val >>= 4;
- r += 4;
- }
- if (val & 0x0c) {
- val >>= 2;
- r += 2;
- }
- if (val & 0x02)
- r += 1;
- return r;
-}
-
-/*
- * s16_to_alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
- *
- * s16_to_alaw() accepts an 16-bit integer and encodes it as A-law data.
- *
- * Linear Input Code Compressed Code
- * ------------------------ ---------------
- * 0000000wxyza 000wxyz
- * 0000001wxyza 001wxyz
- * 000001wxyzab 010wxyz
- * 00001wxyzabc 011wxyz
- * 0001wxyzabcd 100wxyz
- * 001wxyzabcde 101wxyz
- * 01wxyzabcdef 110wxyz
- * 1wxyzabcdefg 111wxyz
- *
- * For further information see John C. Bellamy's Digital Telephony, 1982,
- * John Wiley & Sons, pps 98-111 and 472-476.
- */
-
-static inline unsigned char s16_to_alaw(int pcm_val)
-{
- int mask;
- int seg;
- unsigned char aval;
-
- if (pcm_val >= 0) {
- mask = 0xD5;
- } else {
- mask = 0x55;
- pcm_val = -pcm_val;
- if (pcm_val > 0x7fff)
- pcm_val = 0x7fff;
- }
-
- if (pcm_val < 256)
- aval = pcm_val >> 4;
- else {
- /* Convert the scaled magnitude to segment number. */
- seg = val_seg(pcm_val);
- aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f);
- }
- return aval ^ mask;
-}
-
-/*
- * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM
- *
- */
-static inline int alaw_to_s16(unsigned char a_val)
-{
- int t;
- int seg;
-
- a_val ^= 0x55;
- t = a_val & 0x7f;
- if (t < 16)
- t = (t << 4) + 8;
- else {
- seg = (t >> 4) & 0x07;
- t = ((t & 0x0f) << 4) + 0x108;
- t <<= seg -1;
- }
- return ((a_val & 0x80) ? t : -t);
-}
-/*
- * s16_to_ulaw() - Convert a linear PCM value to u-law
- *
- * In order to simplify the encoding process, the original linear magnitude
- * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
- * (33 - 8191). The result can be seen in the following encoding table:
- *
- * Biased Linear Input Code Compressed Code
- * ------------------------ ---------------
- * 00000001wxyza 000wxyz
- * 0000001wxyzab 001wxyz
- * 000001wxyzabc 010wxyz
- * 00001wxyzabcd 011wxyz
- * 0001wxyzabcde 100wxyz
- * 001wxyzabcdef 101wxyz
- * 01wxyzabcdefg 110wxyz
- * 1wxyzabcdefgh 111wxyz
- *
- * Each biased linear code has a leading 1 which identifies the segment
- * number. The value of the segment number is equal to 7 minus the number
- * of leading 0's. The quantization interval is directly available as the
- * four bits wxyz. * The trailing bits (a - h) are ignored.
- *
- * Ordinarily the complement of the resulting code word is used for
- * transmission, and so the code word is complemented before it is returned.
- *
- * For further information see John C. Bellamy's Digital Telephony, 1982,
- * John Wiley & Sons, pps 98-111 and 472-476.
- */
-
-static inline unsigned char s16_to_ulaw(int pcm_val) /* 2's complement (16-bit range) */
-{
- int mask;
- int seg;
- unsigned char uval;
-
- if (pcm_val < 0) {
- pcm_val = 0x84 - pcm_val;
- mask = 0x7f;
- } else {
- pcm_val += 0x84;
- mask = 0xff;
- }
- if (pcm_val > 0x7fff)
- pcm_val = 0x7fff;
-
- /* Convert the scaled magnitude to segment number. */
- seg = val_seg(pcm_val);
-
- /*
- * Combine the sign, segment, quantization bits;
- * and complement the code word.
- */
- uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f);
- return uval ^ mask;
-}
-
-/*
- * ulaw_to_s16() - Convert a u-law value to 16-bit linear PCM
- *
- * First, a biased linear code is derived from the code word. An unbiased
- * output can then be obtained by subtracting 33 from the biased code.
- *
- * Note that this function expects to be passed the complement of the
- * original code word. This is in keeping with ISDN conventions.
- */
-static inline int ulaw_to_s16(unsigned char u_val)
-{
- int t;
-
- /* Complement to obtain normal u-law value. */
- u_val = ~u_val;
-
- /*
- * Extract and bias the quantization bits. Then
- * shift up by the segment number and subtract out the bias.
- */
- t = ((u_val & 0x0f) << 3) + 0x84;
- t <<= (u_val & 0x70) >> 4;
-
- return ((u_val & 0x80) ? (0x84 - t) : (t - 0x84));
-}
diff --git a/talk/third_party/mediastreamer/hpuxsndcard.c b/talk/third_party/mediastreamer/hpuxsndcard.c
deleted file mode 100755
index 8210e29..0000000
--- a/talk/third_party/mediastreamer/hpuxsndcard.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "sndcard.h"
-#include "osscard.h"
-
-#ifdef HAVE_SYS_AUDIO_H
-#include <sys/audio.h>
-
-
-#include "msossread.h"
-#include "msosswrite.h"
-
-#include <errno.h>
-#include <fcntl.h>
-
-
-int hpuxsnd_open(HpuxSndCard *obj, int bits,int stereo, int rate)
-{
- int fd;
- int p=0,cond=0;
- int i=0;
- int min_size=0,blocksize=512;
- /* do a quick non blocking open to be sure that we are not going to be blocked here
- for the eternity */
- fd=open(obj->dev_name,O_RDWR|O_NONBLOCK);
- if (fd<0) return -EWOULDBLOCK;
- close(fd);
- /* open the device */
- fd=open(obj->dev_name,O_RDWR);
-
- g_return_val_if_fail(fd>0,-errno);
-
- ioctl(fd,AUDIO_RESET,0);
- ioctl(fd,AUDIO_SET_SAMPLE_RATE,rate);
- ioctl(fd,AUDIO_SET_CHANNELS,stereo);
- p=AUDIO_FORMAT_LINEAR16BIT;
- ioctl(fd,AUDIO_SET_DATA_FORMAT,p);
- /* ioctl(fd,AUDIO_GET_RXBUFSIZE,&min_size); does not work ? */
- min_size=2048;
-
- g_message("dsp blocksize is %i.",min_size);
- obj->fd=fd;
- obj->readpos=0;
- obj->writepos=0;
- SND_CARD(obj)->bits=bits;
- SND_CARD(obj)->stereo=stereo;
- SND_CARD(obj)->rate=rate;
- SND_CARD(obj)->bsize=min_size;
- return fd;
-}
-
-int hpux_snd_card_probe(HpuxSndCard *obj,int bits,int stereo,int rate)
-{
- return 2048;
-}
-
-
-int hpux_snd_card_open(HpuxSndCard *obj,int bits,int stereo,int rate)
-{
- int fd;
- obj->ref++;
- if (obj->fd==0){
- fd=hpuxsnd_open(obj,bits,stereo,rate);
- if (fd<0) {
- obj->fd=0;
- obj->ref--;
- return -1;
- }
- }
- SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
- return 0;
-}
-
-void hpux_snd_card_close(HpuxSndCard *obj)
-{
- int i;
- obj->ref--;
- if (obj->ref==0) {
- close(obj->fd);
- obj->fd=0;
- SND_CARD(obj)->flags&=~SND_CARD_FLAGS_OPENED;
-
- }
-}
-
-void hpux_snd_card_destroy(HpuxSndCard *obj)
-{
- snd_card_uninit(SND_CARD(obj));
- g_free(obj->dev_name);
- g_free(obj->mixdev_name);
-}
-
-gboolean hpux_snd_card_can_read(HpuxSndCard *obj)
-{
- struct timeval tout={0,0};
- int err;
- fd_set fdset;
- FD_ZERO(&fdset);
- FD_SET(obj->fd,&fdset);
- err=select(obj->fd+1,&fdset,NULL,NULL,&tout);
- if (err>0) return TRUE;
- else return FALSE;
-}
-
-int hpux_snd_card_read(HpuxSndCard *obj,char *buf,int size)
-{
- int err;
- gint bsize=SND_CARD(obj)->bsize;
- if (size<bsize){
- gint canread=MIN(bsize-obj->readpos,size);
- if (obj->readbuf==NULL) obj->readbuf=g_malloc0(bsize);
- if (obj->readpos==0){
- err=read(obj->fd,obj->readbuf,bsize);
- if (err<0) {
- g_warning("hpux_snd_card_read: read() failed:%s.",strerror(errno));
- return -1;
- }
- }
-
- memcpy(buf,&obj->readbuf[obj->readpos],canread);
- obj->readpos+=canread;
- if (obj->readpos>=bsize) obj->readpos=0;
- return canread;
- }else{
- err=read(obj->fd,buf,size);
- if (err<0) {
- g_warning("hpux_snd_card_read: read-2() failed:%s.",strerror(errno));
- }
- return err;
- }
-
-}
-
-int hpux_snd_card_write(HpuxSndCard *obj,char *buf,int size)
-{
- int err;
- gint bsize=SND_CARD(obj)->bsize;
- if (size<bsize){
- gint canwrite=MIN(bsize-obj->writepos,size);
- if (obj->writebuf==NULL) obj->writebuf=g_malloc0(bsize);
-
- memcpy(&obj->writebuf[obj->writepos],buf,canwrite);
- obj->writepos+=canwrite;
- if (obj->writepos>=bsize){
- err=write(obj->fd,obj->writebuf,bsize);
- }
- return canwrite;
- }else{
- return write(obj->fd,buf,bsize);
- }
-}
-
-#define SND_CARD_LEVEL_TO_HPUX_LEVEL(a) (((a)*2) - 100)
-#define HPUX_LEVEL_TO_SND_CARD_LEVEL(a) (((a)+200)/2)
-void hpux_snd_card_set_level(HpuxSndCard *obj,gint way,gint a)
-{
- struct audio_gain gain;
- int error,mix_fd;
-
- g_return_if_fail(obj->mixdev_name!=NULL);
- memset(&gain,0,sizeof(struct audio_gain));
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- gain.cgain[0].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
- gain.cgain[1].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
- break;
- case SND_CARD_LEVEL_INPUT:
- gain.cgain[0].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
- gain.cgain[1].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
- break;
- case SND_CARD_LEVEL_OUTPUT:
- gain.cgain[0].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
- gain.cgain[1].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
- break;
- default:
- g_warning("hpux_snd_card_set_level: unsupported command.");
- return;
- }
- gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT;
- mix_fd = open(obj->mixdev_name, O_WRONLY);
- g_return_if_fail(mix_fd>0);
- error=ioctl(mix_fd,AUDIO_SET_GAINS,&gain);
- if (error<0){
- g_warning("hpux_snd_card_set_level: Could not set gains: %s",strerror(errno));
- }
- close(mix_fd);
-}
-
-gint hpux_snd_card_get_level(HpuxSndCard *obj,gint way)
-{
- struct audio_gain gain;
- int p=0,mix_fd,error;
- g_return_if_fail(obj->mixdev_name!=NULL);
-
- gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT;
- mix_fd = open(obj->mixdev_name, O_RDONLY);
- g_return_if_fail(mix_fd>0);
- error=ioctl(mix_fd,AUDIO_GET_GAINS,&gain);
- if (error<0){
- g_warning("hpux_snd_card_set_level: Could not get gains: %s",strerror(errno));
- }
- close(mix_fd);
-
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- p=gain.cgain[0].monitor_gain;
- break;
- case SND_CARD_LEVEL_INPUT:
- p=gain.cgain[0].receive_gain;
- break;
- case SND_CARD_LEVEL_OUTPUT:
- p=gain.cgain[0].transmit_gain;
- break;
- default:
- g_warning("hpux_snd_card_get_level: unsupported command.");
- return -1;
- }
- return HPUX_LEVEL_TO_SND_CARD_LEVEL(p);
-}
-
-void hpux_snd_card_set_source(HpuxSndCard *obj,int source)
-{
- gint p=0;
- gint mix_fd;
- gint error=0;
- g_return_if_fail(obj->mixdev_name!=NULL);
-
- mix_fd=open("/dev/audio",O_WRONLY);
- g_return_if_fail(mix_fd>0);
- switch(source){
- case 'm':
- error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_MIKE);
- break;
- case 'l':
- error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_LINE);
- break;
- default:
- g_warning("hpux_snd_card_set_source: unsupported source.");
- }
- close(mix_fd);
-}
-
-MSFilter *hpux_snd_card_create_read_filter(HpuxSndCard *card)
-{
- MSFilter *f=ms_oss_read_new();
- ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index);
- return f;
-}
-
-MSFilter *hpux_snd_card_create_write_filter(HpuxSndCard *card)
-{
- MSFilter *f=ms_oss_write_new();
- ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index);
- return f;
-}
-
-
-SndCard * hpux_snd_card_new(char *devname, char *mixdev_name)
-{
- HpuxSndCard * obj= g_new0(HpuxSndCard,1);
- SndCard *base= SND_CARD(obj);
- snd_card_init(base);
- obj->dev_name=g_strdup(devname);
- obj->mixdev_name=g_strdup( mixdev_name);
- base->card_name=g_strdup(devname);
- base->_probe=(SndCardOpenFunc)hpux_snd_card_probe;
- base->_open_r=(SndCardOpenFunc)hpux_snd_card_open;
- base->_open_w=(SndCardOpenFunc)hpux_snd_card_open;
- base->_can_read=(SndCardPollFunc)hpux_snd_card_can_read;
- base->_read=(SndCardIOFunc)hpux_snd_card_read;
- base->_write=(SndCardIOFunc)hpux_snd_card_write;
- base->_close_r=(SndCardCloseFunc)hpux_snd_card_close;
- base->_close_w=(SndCardCloseFunc)hpux_snd_card_close;
- base->_set_rec_source=(SndCardMixerSetRecSourceFunc)hpux_snd_card_set_source;
- base->_set_level=(SndCardMixerSetLevelFunc)hpux_snd_card_set_level;
- base->_get_level=(SndCardMixerGetLevelFunc)hpux_snd_card_get_level;
- base->_destroy=(SndCardDestroyFunc)hpux_snd_card_destroy;
- base->_create_read_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_read_filter;
- base->_create_write_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_write_filter;
- return base;
-}
-
-#endif
diff --git a/talk/third_party/mediastreamer/jackcard.c b/talk/third_party/mediastreamer/jackcard.c
deleted file mode 100755
index b929cce..0000000
--- a/talk/third_party/mediastreamer/jackcard.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- JACK support
- Copyright (C) 2004 Tobias Gehrig tobias@gehrig.tk
-*/
-
-#include "jackcard.h"
-
-#ifdef __JACK_ENABLED__
-
-#include "msossread.h"
-#include "msosswrite.h"
-
-#include <signal.h>
-
-#define READBUFFERSIZE 524288
-#define WRITEBUFFERSIZE 524288
-#define BSIZE 512
-
-/**
- * jack_shutdown:
- * @arg:
- *
- * This is the shutdown callback for this JACK application.
- * It is called by JACK if the server ever shuts down or
- * decides to disconnect the client.
- *
- */
-void
-jack_shutdown (void *arg)
-{
- JackCard* obj = (JackCard*) arg;
-
- obj->jack_running = FALSE;
- obj->jack_active = FALSE;
- obj->read.port = NULL;
- if (obj->read.open)
- obj->read.init = TRUE;
- obj->write.port = NULL;
- if (obj->write.open)
- obj->write.init = TRUE;
-}
-
-int samplerate(jack_nframes_t rate, void *arg)
-{
- JackCard* obj = (JackCard*) arg;
- int error;
-
- obj->rate = rate;
- if (obj->read.open) {
- obj->read.data.src_ratio = (double)obj->read.rate / (double)obj->rate;
- obj->read.data.input_frames = (long)((double)obj->read.frames/obj->read.data.src_ratio);
- g_free(obj->read.data.data_in);
- obj->read.data.data_in = malloc(obj->read.data.input_frames*sizeof(float));
- if (obj->read.src_state)
- if ((error = src_set_ratio(obj->read.src_state, obj->read.data.src_ratio)) != 0)
- g_warning("Error while resetting the write samplerate: %s", src_strerror(error));
- }
- if (obj->write.open) {
- obj->write.data.src_ratio = (double)obj->rate / (double)obj->write.rate;
- obj->write.data.output_frames = (long)((double)obj->write.frames*obj->write.data.src_ratio);
- g_free(obj->write.data.data_out);
- obj->write.data.data_out = malloc(obj->write.data.output_frames*sizeof(float));
- if (obj->write.src_state)
- if ((error = src_set_ratio(obj->write.src_state, obj->write.data.src_ratio)) != 0)
- g_warning("Error while resetting the write samplerate: %s", src_strerror(error));
- }
- return 0;
-}
-
-/*
- * The process callback for this JACK application.
- * It is called by JACK at the appropriate times.
- * @nframes :
- * @arg :
- */
-int
-process (jack_nframes_t nframes, void *arg)
-{
- JackCard* obj = (JackCard*) arg;
- sample_t *out;
- sample_t *in;
-
- if (obj->clear && !obj->write.can_process) {
- out = (sample_t *) jack_port_get_buffer (obj->write.port, nframes);
- memset (out, 0, nframes * sizeof(sample_t));
- obj->clear = FALSE;
- }
-
- if (!obj->can_process)
- return 0;
-
- if(obj->read.can_process) {
- in = (sample_t *) jack_port_get_buffer (obj->read.port, nframes);
- jack_ringbuffer_write (obj->read.buffer, (void *) in, sizeof(sample_t) * nframes);
- }
-
- if (obj->write.can_process) {
- out = (sample_t *) jack_port_get_buffer (obj->write.port, nframes);
- memset (out, 0, nframes * sizeof(sample_t));
- if (obj->clear && jack_ringbuffer_read_space(obj->write.buffer) == 0) {
- obj->write.can_process = FALSE;
- if (!obj->read.open)
- obj->can_process = FALSE;
- obj->clear = FALSE;
- return 0;
- }
- jack_ringbuffer_read (obj->write.buffer, (void *) out, sizeof(sample_t) * nframes);
- }
- return 0;
-}
-
-int jack_init(JackCard* obj)
-{
- char* client_name;
- int error;
-
- if (!obj->jack_running) {
- obj->client = NULL;
- client_name = g_strdup_printf("linphone-%u", g_random_int());
- if ((obj->client = jack_client_new (client_name)) == NULL) {
- g_warning("cannot create jack client");
- g_free(client_name);
- return -1;
- }
- g_message("Found Jack Daemon");
- g_free(client_name);
-
- /* tell the JACK server to call `process()' whenever
- there is work to be done.
- */
- jack_set_process_callback (obj->client, process, obj);
-
- /* tell the JACK server to call `jack_shutdown()' if
- it ever shuts down, either entirely, or if it
- just decides to stop calling us.
- */
- jack_on_shutdown (obj->client, jack_shutdown, obj);
- jack_set_sample_rate_callback (obj->client, samplerate, obj);
- obj->rate = jack_get_sample_rate (obj->client);
- if (obj->rate == 0) {
- g_warning ("rate is 0???");
- if (jack_client_close(obj->client) != 0)
- g_warning("could not close client");
- return -1;
- }
- obj->buffer_size = jack_get_buffer_size(obj->client);
- obj->jack_running = TRUE;
- }
-
- if (!obj->jack_active) {
- if (jack_activate (obj->client)) {
- g_warning("cannot activate jack client");
- return -1;
- } else obj->jack_active = TRUE;
- }
-
- if (obj->read.init) {
- if (!obj->read.port && (obj->read.port = jack_port_register (obj->client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))==NULL) {
- g_warning("error while trying to register input port");
- return -1;
- }
- if (!obj->read.phys_ports && (obj->read.phys_ports = jack_get_ports (obj->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == NULL) {
- g_warning("Cannot find any physical capture ports\n");
- jack_port_unregister(obj->client, obj->read.port);
- obj->read.port = NULL;
- return -1;
- }
- if (!jack_port_connected(obj->read.port))
- if ((error = jack_connect (obj->client, obj->read.phys_ports[0], jack_port_name (obj->read.port))) != 0) {
- g_warning("cannot connect input ports: %s -> %s\n", jack_port_name (obj->read.port), obj->read.phys_ports[0]);
- if (error == EEXIST) g_warning("connection already made");
- else {
- jack_port_unregister(obj->client, obj->read.port);
- obj->read.port = NULL;
- return -1;
- }
- }
- obj->read.init = FALSE;
- }
-
- if (obj->write.init) {
- if (!obj->write.port && (obj->write.port = jack_port_register (obj->client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0))==NULL) {
- g_warning("error while trying to register output port");
- return -1;
- }
- if (!obj->write.phys_ports && (obj->write.phys_ports = jack_get_ports (obj->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) {
- g_warning("Cannot find any physical playback ports\n");
- jack_port_unregister(obj->client, obj->write.port);
- obj->write.port = NULL;
- return -1;
- }
- if (!jack_port_connected(obj->write.port)) {
- if ((error = jack_connect (obj->client, jack_port_name (obj->write.port), obj->write.phys_ports[0])) != 0) {
- g_warning("cannot connect output ports: %s -> %s\n", jack_port_name (obj->write.port), obj->write.phys_ports[0]);
- if (error == EEXIST) g_warning("connection already made");
- else {
- jack_port_unregister(obj->client, obj->write.port);
- obj->write.port = NULL;
- return -1;
- }
- }
- if ((error = jack_connect (obj->client, jack_port_name (obj->write.port), obj->write.phys_ports[1])) != 0) {
- g_warning("cannot connect output ports: %s -> %s\n", jack_port_name (obj->write.port), obj->write.phys_ports[1]);
- if (error == EEXIST) g_warning("connection already made");
- else {
- jack_port_unregister(obj->client, obj->write.port);
- obj->write.port = NULL;
- return -1;
- }
- }
- }
- obj->write.init = FALSE;
- }
- return 0;
-}
-
-int jack_card_open_r(JackCard *obj,int bits,int stereo,int rate)
-{
- int channels = stereo + 1, bsize, error;
- obj->read.init = TRUE;
- if (jack_init(obj) != 0) return -1;
-
- obj->read.rate = rate;
- obj->sample_size = bits / 8;
- obj->frame_size = channels * obj->sample_size;
- bsize = BSIZE;
- obj->read.frames = bsize / 2;
- SND_CARD(obj)->bsize = bsize;
- SND_CARD(obj)->flags |= SND_CARD_FLAGS_OPENED;
- obj->read.channels = channels;
- if ((obj->read.src_state = src_new (SRC_SINC_FASTEST, channels, &error)) == NULL)
- g_warning("Error while initializing the samplerate converter: %s", src_strerror(error));
- obj->read.data.src_ratio = (double)rate / (double)obj->rate;
- obj->read.data.input_frames = (long)((double)obj->read.frames/obj->read.data.src_ratio);
- obj->read.data.data_in = malloc(obj->read.data.input_frames*sizeof(float));
- obj->read.data.data_out = malloc(obj->read.frames*sizeof(float));
- obj->read.data.end_of_input = 0;
- if (!obj->read.buffer)
- obj->read.buffer = jack_ringbuffer_create(READBUFFERSIZE);
- obj->read.can_process = TRUE;
- obj->can_process = TRUE;
- obj->read.open = TRUE;
- obj->read.init = FALSE;
- return 0;
-}
-
-int jack_card_open_w(JackCard *obj,int bits,int stereo,int rate)
-{
- int channels = stereo + 1, bsize, err;
- obj->write.init = TRUE;
- if (jack_init(obj) != 0) return -1;
-
- obj->write.rate = rate;
- obj->sample_size = bits / 8;
- obj->frame_size = channels * obj->sample_size;
- bsize = BSIZE;
- obj->write.frames = bsize / 2;
- SND_CARD(obj)->bsize = bsize;
- SND_CARD(obj)->flags |= SND_CARD_FLAGS_OPENED;
- obj->write.channels = channels;
- if ((obj->write.src_state = src_new (SRC_SINC_FASTEST, channels, &err)) == NULL)
- g_warning("Error while initializing the samplerate converter: %s", src_strerror(err));
- obj->write.data.src_ratio = (double)obj->rate / (double)rate;
- obj->write.data.data_in = malloc(obj->write.frames*sizeof(float));
- obj->write.data.end_of_input = 0;
- obj->write.data.output_frames = (long)((double)obj->write.frames*obj->write.data.src_ratio);
- obj->write.data.data_out = malloc(obj->write.data.output_frames*sizeof(float));
- if (!obj->write.buffer)
- obj->write.buffer = jack_ringbuffer_create(WRITEBUFFERSIZE);
- obj->write.can_process = TRUE;
- obj->can_process = TRUE;
- obj->write.open = TRUE;
- obj->write.init = FALSE;
- return 0;
-}
-
-void jack_card_set_blocking_mode(JackCard *obj, gboolean yesno)
-{
-}
-
-void jack_card_close_r(JackCard *obj)
-{
- obj->read.open = FALSE;
- obj->read.init = FALSE;
- obj->read.can_process = FALSE;
- if (!obj->write.open)
- obj->can_process = FALSE;
- if (obj->read.src_state)
- obj->read.src_state = src_delete (obj->read.src_state);
- g_free(obj->read.data.data_in);
- g_free(obj->read.data.data_out);
-}
-
-void jack_card_close_w(JackCard *obj)
-{
- obj->write.open = FALSE;
- obj->write.init = FALSE;
- obj->clear = TRUE;
- if (!obj->jack_running) {
- obj->write.can_process = FALSE;
- obj->can_process = FALSE;
- }
- if (obj->write.src_state)
- obj->write.src_state = src_delete (obj->write.src_state);
- g_free(obj->write.data.data_in);
- g_free(obj->write.data.data_out);
-}
-
-int jack_card_probe(JackCard *obj,int bits,int stereo,int rate)
-{
- if (obj->jack_running) return BSIZE;
- else if (jack_init(obj) == 0) return BSIZE;
- else return -1;
-}
-
-void jack_card_destroy(JackCard *obj)
-{
- if (obj->jack_running) jack_client_close (obj->client);
- snd_card_uninit(SND_CARD(obj));
- if (obj->read.buffer) {
- jack_ringbuffer_free(obj->read.buffer);
- obj->read.buffer = NULL;
- }
- if (obj->write.buffer) {
- jack_ringbuffer_free(obj->write.buffer);
- obj->write.buffer = NULL;
- }
- if (obj->read.phys_ports) {
- g_free(obj->read.phys_ports);
- obj->read.phys_ports = NULL;
- }
- if (obj->write.phys_ports) {
- g_free(obj->write.phys_ports);
- obj->write.phys_ports = NULL;
- }
-}
-
-gboolean jack_card_can_read(JackCard *obj)
-{
- g_return_val_if_fail(obj->read.buffer!=NULL,0);
- if (jack_ringbuffer_read_space(obj->read.buffer)>=(long)((double)obj->read.frames/obj->read.data.src_ratio)*sizeof(sample_t)) return TRUE;
- else return FALSE;
-}
-
-int jack_card_read(JackCard *obj,char *buf,int size)
-{
- size_t bytes, can_read, i;
- int error;
- float norm, value;
-
- g_return_val_if_fail((obj->read.buffer!=NULL)&&(obj->read.src_state!=NULL),-1);
- if (jack_init(obj) != 0) return -1;
- size /= 2;
- can_read = MIN(size, obj->read.frames);
- // can_read = MIN(((long)((double)can_read / obj->read.data.src_ratio))*sizeof(sample_t), jack_ringbuffer_read_space(obj->read.buffer));
- can_read = ((long)((double)can_read / obj->read.data.src_ratio))*sizeof(sample_t);
- obj->read.can_process = FALSE;
- bytes = jack_ringbuffer_read (obj->read.buffer, (void *)obj->read.data.data_in, can_read);
- obj->read.can_process = TRUE;
- obj->read.data.input_frames = bytes / sizeof(sample_t);
- can_read = MIN(size, obj->read.frames);
- obj->read.data.output_frames = can_read;
- if ((error = src_process(obj->read.src_state, &(obj->read.data))) != 0)
- g_warning("error while samplerate conversion. error: %s", src_strerror(error));
- norm = obj->read.level*obj->level*(float)0x8000;
- for (i=0; i < obj->read.data.output_frames_gen; i++) {
- value = obj->read.data.data_out[i]*norm;
- if (value >= 32767.0)
- ((short*)buf)[i] = 32767;
- else if (value <= -32768.0)
- ((short*)buf)[i] = -32768;
- else
- ((short*)buf)[i] = (short)value;
- }
- bytes = obj->read.data.output_frames_gen * 2;
- return bytes;
-}
-
-int jack_card_write(JackCard *obj,char *buf,int size)
-{
- size_t bytes, can_write, i;
- int error;
- float norm;
-
- g_return_val_if_fail((obj->write.buffer!=NULL)&&(obj->write.src_state!=NULL),-1);
- if (jack_init(obj) != 0) return -1;
- size /= 2;
- can_write = MIN(size, obj->write.frames);
- norm = obj->write.level*obj->level/(float)0x8000;
- for (i=0; i<can_write; i++) {
- obj->write.data.data_in[i] = (float)((short*)buf)[i]*norm;
- }
- obj->write.data.input_frames = can_write;
- if ((error = src_process(obj->write.src_state, &(obj->write.data))) != 0)
- g_warning("error while samplerate conversion. error: %s", src_strerror(error));
- obj->write.can_process = FALSE;
- bytes = jack_ringbuffer_write (obj->write.buffer, (void *) obj->write.data.data_out, sizeof(sample_t)*obj->write.data.output_frames_gen);
- obj->write.can_process = TRUE;
- return bytes;
-}
-
-void jack_card_set_level(JackCard *obj,gint way,gint a)
-{
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- obj->level = (float)a / 100.0;
- break;
- case SND_CARD_LEVEL_INPUT:
- obj->read.level = (float)a / 100.0;
- break;
- case SND_CARD_LEVEL_OUTPUT:
- obj->write.level = (float)a / 100.0;
- break;
- default:
- g_warning("jack_card_set_level: unsupported command.");
- }
-}
-
-gint jack_card_get_level(JackCard *obj,gint way)
-{
- gint value = 0;
-
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- value = (gint)(obj->level*100.0);
- break;
- case SND_CARD_LEVEL_INPUT:
- value = (gint)(obj->read.level*100.0);
- break;
- case SND_CARD_LEVEL_OUTPUT:
- value = (gint)(obj->write.level*100.0);
- break;
- default:
- g_warning("jack_card_get_level: unsupported command.");
- }
- return value;
-}
-
-void jack_card_set_source(JackCard *obj,int source)
-{
-}
-
-MSFilter *jack_card_create_read_filter(JackCard *card)
-{
- MSFilter *f=ms_oss_read_new();
- ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index);
- return f;
-}
-
-MSFilter *jack_card_create_write_filter(JackCard *card)
-{
- MSFilter *f=ms_oss_write_new();
- ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index);
- return f;
-}
-SndCard * jack_card_new(jack_client_t *client)
-{
- JackCard * obj;
- SndCard *base;
-
- obj= g_new0(JackCard,1);
-
- if (!client) return NULL;
- obj->client = client;
- obj->jack_running = TRUE;
- obj->jack_active = FALSE;
- obj->can_process = FALSE;
- obj->clear = TRUE;
- obj->write.can_process = FALSE;
- obj->write.open = FALSE;
- obj->write.init = TRUE;
- obj->write.port = NULL;
- obj->write.phys_ports = NULL;
- obj->write.buffer = NULL;
- obj->read.can_process = FALSE;
- obj->read.open = FALSE;
- obj->read.init = TRUE;
- obj->read.port = NULL;
- obj->read.phys_ports = NULL;
- obj->read.buffer = NULL;
-
- /* tell the JACK server to call `process()' whenever
- there is work to be done.
- */
- jack_set_process_callback (client, process, obj);
-
- /* tell the JACK server to call `jack_shutdown()' if
- it ever shuts down, either entirely, or if it
- just decides to stop calling us.
- */
- jack_on_shutdown (client, jack_shutdown, obj);
-
- jack_set_sample_rate_callback (client, samplerate, obj);
-
- obj->rate = jack_get_sample_rate (client);
- obj->buffer_size = jack_get_buffer_size(obj->client);
-
- jack_init(obj);
-
- base= SND_CARD(obj);
- snd_card_init(base);
-
-#ifdef HAVE_GLIB
- base->card_name=g_strdup_printf("JACK client");
-#else
- base->card_name=malloc(100);
- snprintf(base->card_name, 100, "JACK client");
-#endif
-
- base->_probe=(SndCardOpenFunc)jack_card_probe;
- base->_open_r=(SndCardOpenFunc)jack_card_open_r;
- base->_open_w=(SndCardOpenFunc)jack_card_open_w;
- base->_can_read=(SndCardPollFunc)jack_card_can_read;
- base->_set_blocking_mode=(SndCardSetBlockingModeFunc)jack_card_set_blocking_mode;
- base->_read=(SndCardIOFunc)jack_card_read;
- base->_write=(SndCardIOFunc)jack_card_write;
- base->_close_r=(SndCardCloseFunc)jack_card_close_r;
- base->_close_w=(SndCardCloseFunc)jack_card_close_w;
- base->_set_rec_source=(SndCardMixerSetRecSourceFunc)jack_card_set_source;
- base->_set_level=(SndCardMixerSetLevelFunc)jack_card_set_level;
- base->_get_level=(SndCardMixerGetLevelFunc)jack_card_get_level;
- base->_destroy=(SndCardDestroyFunc)jack_card_destroy;
- base->_create_read_filter=(SndCardCreateFilterFunc)jack_card_create_read_filter;
- base->_create_write_filter=(SndCardCreateFilterFunc)jack_card_create_write_filter;
-
- obj->read.buffer=NULL;
- obj->write.buffer=NULL;
- obj->buffer_size = 0;
- obj->level = 1.0;
- obj->write.level = 1.0;
- obj->read.level = 1.0;
-
- return base;
-}
-
-
-gint jack_card_manager_init(SndCardManager *m, gint index)
-{
- jack_client_t *client = NULL;
- char* client_name;
-
- client_name=g_strdup_printf("linphone-%u", g_random_int());
- if ((client = jack_client_new (client_name))!= NULL)
- {
- g_message("Found Jack Daemon");
- g_free(client_name);
- m->cards[index]=jack_card_new(client);
- m->cards[index]->index=index;
- return 1;
- } else {
- g_free(client_name);
- return 0;
- }
-}
-
-#endif
diff --git a/talk/third_party/mediastreamer/jackcard.h b/talk/third_party/mediastreamer/jackcard.h
deleted file mode 100755
index 33ec46d..0000000
--- a/talk/third_party/mediastreamer/jackcard.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- JACK support
- Copyright (C) 2004 Tobias Gehrig tobias@gehrig.tk
-*/
-
-#ifndef JACK_CARD_H
-#define JACK_CARD_H
-
-#include <config.h>
-
-#ifdef __JACK_ENABLED__
-
-#include "sndcard.h"
-
-#include <jack/jack.h>
-#include <jack/ringbuffer.h>
-
-#include <samplerate.h>
-
-typedef jack_default_audio_sample_t sample_t;
-
-typedef struct {
- jack_port_t *port;
- const char **phys_ports;
- float level;
- jack_ringbuffer_t *buffer;
- gint channels;
- gint rate;
- SRC_STATE* src_state;
- SRC_DATA data;
- size_t frames;
- gboolean can_process;
- gboolean open;
- gboolean init;
-} jackcard_mode_t;
-
-struct _JackCard
-{
- SndCard parent;
-
- jack_client_t *client;
- gboolean jack_running;
- gboolean jack_active;
- float level;
- jack_nframes_t buffer_size;
- gint sample_size;
- gint frame_size;
- gint rate;
- gboolean can_process;
- gboolean clear;
-
- jackcard_mode_t read, write;
-};
-
-typedef struct _JackCard JackCard;
-
-SndCard * jack_card_new(jack_client_t *client);
-
-gint jack_card_manager_init(SndCardManager *m, gint index);
-
-#endif
-
-#endif
diff --git a/talk/third_party/mediastreamer/mediastream.h b/talk/third_party/mediastreamer/mediastream.h
deleted file mode 100755
index 3ccbab6..0000000
--- a/talk/third_party/mediastreamer/mediastream.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MEDIASTREAM_H
-#define MEDIASTREAM_H
-
-#include "msrtprecv.h"
-#include "msrtpsend.h"
-#include "ms.h"
-#include "msosswrite.h"
-#include "msossread.h"
-#include "msread.h"
-#include "mswrite.h"
-#include "mstimer.h"
-#include "mscodec.h"
-#ifdef HAVE_SPEEX
-#include "msspeexdec.h"
-#endif
-#include "msringplayer.h"
-
-
-struct _AudioStream
-{
- MSSync *timer;
- RtpSession *send_session;
- RtpSession *recv_session;
- MSFilter *soundread;
- MSFilter *soundwrite;
- MSFilter *encoder;
- MSFilter *decoder;
- MSFilter *rtprecv;
- MSFilter *rtpsend;
-};
-
-
-typedef struct _AudioStream AudioStream;
-
-struct _RingStream
-{
- MSSync *timer;
- MSFilter *source;
- MSFilter *sndwrite;
-};
-
-typedef struct _RingStream RingStream;
-
-/* start a thread that does sampling->encoding->rtp_sending|rtp_receiving->decoding->playing */
-AudioStream *audio_stream_start (RtpProfile * prof, int locport, char *remip,
- int remport, int profile, int jitt_comp);
-
-AudioStream *audio_stream_start_with_sndcards(RtpProfile * prof, int locport, char *remip4,
- int remport, int profile, int jitt_comp, SndCard *playcard, SndCard *captcard);
-
-AudioStream *audio_stream_start_with_files (RtpProfile * prof, int locport,
- char *remip4, int remport,
- int profile, int jitt_comp,
- gchar * infile, gchar * outfile);
-void audio_stream_set_rtcp_information(AudioStream *st, const char *cname);
-
-
-/* stop the above process*/
-void audio_stream_stop (AudioStream * stream);
-
-RingStream *ring_start (gchar * file, gint interval, SndCard *sndcard);
-RingStream *ring_start_with_cb(gchar * file, gint interval, SndCard *sndcard, MSFilterNotifyFunc func,gpointer user_data);
-void ring_stop (RingStream * stream);
-
-/* returns the latency in samples if the audio device with id dev_id is openable in full duplex mode, else 0 */
-gint test_audio_dev (int dev_id);
-
-/* send a dtmf */
-gint audio_stream_send_dtmf (AudioStream * stream, gchar dtmf);
-
-void audio_stream_set_default_card(int cardindex);
-
-
-#ifdef VIDEO_ENABLED
-
-/*****************
- Video Support
- *****************/
-
-
-
-struct _VideoStream
-{
- MSSync *timer;
- RtpSession *send_session;
- RtpSession *recv_session;
- MSFilter *source;
- MSFilter *output;
- MSFilter *encoder;
- MSFilter *decoder;
- MSFilter *rtprecv;
- MSFilter *rtpsend;
- gboolean show_local;
-};
-
-
-typedef struct _VideoStream VideoStream;
-
-VideoStream *video_stream_start(RtpProfile *profile, int locport, char *remip4, int remport,
- int payload, int jitt_comp, gboolean show_local, const gchar *source, const gchar *device);
-void video_stream_set_rtcp_information(VideoStream *st, const char *cname);
-void video_stream_stop (VideoStream * stream);
-
-VideoStream * video_preview_start(const gchar *source, const gchar *device);
-void video_preview_stop(VideoStream *stream);
-
-#endif
-
-#endif
diff --git a/talk/third_party/mediastreamer/ms.c b/talk/third_party/mediastreamer/ms.c
deleted file mode 100755
index a4a57f8..0000000
--- a/talk/third_party/mediastreamer/ms.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "ms.h"
-#include "sndcard.h"
-#include "mscodec.h"
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef VIDEO_ENABLED
-extern void ms_video_source_register_all();
-#endif
-#ifdef HAVE_ILBC
-extern void ms_ilbc_codec_init();
-#endif
-
-/**
- * ms_init:
- *
- *
- * Initialize the mediastreamer. This must be the first function called in a program
- * using the mediastreamer library.
- *
- *
- */
-void ms_init()
-{
- if (!g_thread_supported()) g_thread_init (NULL);
-#ifdef HAVE_GLIB
- if (!g_module_supported()){
- g_error("GModule is not supported.");
- }
-#endif
- /* initialize the oss subsystem */
- snd_card_manager_init(snd_card_manager);
- /* register the statically linked codecs */
- ms_codec_register_all();
-#ifdef VIDEO_ENABLED
- ms_video_source_register_all();
-#endif
-#ifdef HAVE_ILBC
- ms_ilbc_codec_init();
-#endif
-}
-
-
-static gint compare(gconstpointer a, gconstpointer b)
-{
- MSFilter *f1=(MSFilter*)a,*f2=(MSFilter*)b;
- if (f1->klass<f2->klass) return -1;
- if (f1->klass==f2->klass) return 0;
- /* if f1->klass>f2->klass ....*/
- return 1;
-}
-
-static GList *g_list_append_if_new(GList *l,gpointer data)
-{
- GList *res=l;
- if (g_list_find(res,data)==NULL)
- res=g_list_append(res,data);
- return(res);
-}
-
-static GList *get_nexts(MSFilter *f,GList *l)
-{
- int i;
- MSFifo *fifo;
- MSQueue *q;
- GList *res=l;
-
- /* check fifos*/
- for (i=0;i <f->klass->max_foutputs;i++)
- {
- fifo=f->outfifos[i];
- if (fifo!=NULL) res=g_list_append_if_new(res,(gpointer)fifo->next_data);
- }
- /* check queues*/
- for (i=0;i <f->klass->max_qoutputs;i++)
- {
- q=f->outqueues[i];
- if (q!=NULL) res=g_list_append_if_new(res,(gpointer)q->next_data);
- }
- return(res);
-}
-
-/* compile graphs attached to a sync source*/
-int ms_compile(MSSync *sync)
-{
- int i;
- GList *list1=NULL,*list2=NULL,*elem;
- GList *proc_chain=NULL;
- MSFilter *f;
-
- /* first free the old list if we are just updating*/
- if (sync->execution_list!=NULL) g_list_free(sync->execution_list);
- /* get the list of filters attached to this sync*/
- for (i=0;i<sync->filters;i++)
- {
- //printf("found filter !\n");
- list1=g_list_append(list1,sync->attached_filters[i]);
- }
- /* find the processing chain */
- while (list1!=NULL)
- {
- list2=NULL;
- /* sort the list by types of filter*/
- list1=g_list_sort(list1,compare);
- /* save into the processing chain list*/
- //printf("list1 :%i elements\n",g_list_length(list1));
- proc_chain=g_list_concat(proc_chain,list1);
- /* get all following filters. They are appended to list2*/
- elem=list1;
- while (elem!=NULL)
- {
- f=(MSFilter*)(elem->data);
- /* check if filter 's status */
- if (f->klass->attributes & FILTER_CAN_SYNC)
- {
- sync->samples_per_tick=0;
- }
- list2=get_nexts(f,list2);
- elem=g_list_next(elem);
- }
- list1=list2;
- }
- sync->execution_list=proc_chain;
- sync->flags&=~MS_SYNC_NEED_UPDATE;
- ms_trace("%i filters successfully compiled in a processing chain.",g_list_length(sync->execution_list));
- return 0;
-}
-
-/*execute the processing chain attached to a sync source. It is called as a thread by ms_main()*/
-void *ms_thread_run(void *sync_ptr)
-{
- MSSync *sync=(MSSync*) sync_ptr;
- GList *filter;
- MSFilter *f;
-
-
- ms_sync_lock(sync);
- while(sync->run)
- {
- //g_message("sync->run=%i",sync->run);
- if (sync->samples_per_tick==0) ms_sync_suspend(sync);
- if (sync->flags & MS_SYNC_NEED_UPDATE){
- ms_compile(sync);
- ms_sync_setup(sync);
- }
- filter=sync->execution_list;
- ms_sync_unlock(sync);
- //ms_trace("Calling synchronisation");
- ms_sync_synchronize(sync);
- while(filter!=NULL)
- {
- f=(MSFilter*)filter->data;
- if (MS_FILTER_GET_CLASS(f)->attributes & FILTER_IS_SOURCE)
- {
- /* execute it once */
- ms_trace("Running source filter %s.",f->klass->name);
- ms_filter_process(f);
- }
- else
- {
- /* make the filter process its input data until it has no more */
- while ( ms_filter_fifos_have_data(f) || ms_filter_queues_have_data(f) )
- {
- ms_trace("Running filter %s.",f->klass->name);
- ms_filter_process(f);
- }
- }
- filter=g_list_next(filter);
- }
- ms_sync_lock(sync);
- }
- g_cond_signal(sync->stop_cond); /* signal that the sync thread has finished */
- ms_sync_unlock(sync);
- g_message("Mediastreamer processing thread is exiting.");
- return NULL;
-}
-
-/* stop the processing chain attached to a sync source.*/
-void ms_thread_stop(MSSync *sync)
-{
- if (sync->thread!=NULL)
- {
- if (sync->samples_per_tick==0)
- {
- /* to wakeup the thread */
- //g_cond_signal(sync->thread_cond);
- }
- g_mutex_lock(sync->lock);
- sync->run=0;
- sync->thread=NULL;
- g_cond_wait(sync->stop_cond,sync->lock);
- g_mutex_unlock(sync->lock);
- }
- //g_message("ms_thread_stop() finished.");
-}
-
-/**
- * ms_start:
- * @sync: A synchronisation source to be started.
- *
- * Starts a thread that will shedule all processing chains attached to the synchronisation source @sync.
- *
- *
- */
-void ms_start(MSSync *sync)
-{
- if (sync->run==1) return; /*already running*/
- ms_compile(sync);
- ms_sync_setup(sync);
- /* this is to avoid race conditions, for example:
- ms_start(sync);
- ms_oss_write_start(ossw);
- here tge ossw filter need to be compiled to run ms_oss_write_start()
- */
- ms_trace("ms_start: creating new thread.");
- sync->run=1;
- sync->thread=g_thread_create((GThreadFunc)ms_thread_run,(gpointer)sync,TRUE,NULL);
- if (sync->thread==NULL){
- g_warning("Could not create thread !");
- }
-}
-
-/**
- * ms_stop:
- * @sync: A synchronisation source to be stopped.
- *
- * Stop the thread that was sheduling the processing chains attached to the synchronisation source @sync.
- * The processing chains are kept unchanged, no object is freed. The synchronisation source can be restarted using ms_start().
- *
- *
- */
-void ms_stop(MSSync *sync)
-{
- ms_thread_stop(sync);
- ms_sync_unsetup(sync);
-}
-
-
-gint ms_load_plugin(gchar *path)
-{
-#ifdef HAVE_GLIB
- g_module_open(path,0);
-#endif
- return 0;
-}
-
-gchar * ms_proc_get_param(gchar *parameter)
-{
- gchar *file;
- int fd;
- int err,len;
- gchar *p,*begin,*end;
- gchar *ret;
- fd=open("/proc/cpuinfo",O_RDONLY);
- if (fd<0){
- g_warning("Could not open /proc/cpuinfo.");
- return NULL;
- }
- file=g_malloc(1024);
- err=read(fd,file,1024);
- file[err-1]='\0';
- /* find the parameter */
- p=strstr(file,parameter);
- if (p==NULL){
- /* parameter not found */
- g_free(file);
- return NULL;
- }
- /* find the following ':' */
- p=strchr(p,':');
- if (p==NULL){
- g_free(file);
- return NULL;
- }
- /* find the value*/
- begin=p+2;
- end=strchr(begin,'\n');
- if (end==NULL) end=strchr(begin,'\0');
- len=end-begin+1;
- ret=g_malloc(len+1);
- snprintf(ret,len,"%s",begin);
- //printf("%s=%s\n",parameter,ret);
- g_free(file);
- return ret;
-}
-
-gint ms_proc_get_type()
-{
- static int proc_type=0;
- gchar *value;
- if (proc_type==0){
- value=ms_proc_get_param("cpu family");
- if (value!=NULL) {
- proc_type=atoi(value);
- g_free(value);
- }else return -1;
- }
- return proc_type;
-}
-
-gint ms_proc_get_speed()
-{
- char *value;
- static int proc_speed=0;
- if (proc_speed==0){
- value=ms_proc_get_param("cpu MHz");
- if (value!=NULL){
- proc_speed=atoi(value);
- g_free(value);
- }else return -1;
- }
- //printf("proc_speed=%i\n",proc_speed);
- return proc_speed;
-}
diff --git a/talk/third_party/mediastreamer/ms.h b/talk/third_party/mediastreamer/ms.h
deleted file mode 100755
index 51c69b9..0000000
--- a/talk/third_party/mediastreamer/ms.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-
-#ifndef MS_H
-#define MS_H
-#include "msfilter.h"
-#include "mssync.h"
-
-
-void ms_init();
-
-/* compile graphs attached to a sync source*/
-int ms_compile(MSSync *source);
-
-
-/* stop the processing chain attached to a sync source.*/
-void ms_thread_stop(MSSync *sync);
-
-
-/**
- * function_name:ms_thread_run
- * @sync: The synchronization source for all the set of graphs to run.
- *
- * Execute the processing chain attached to a sync source. This function loops indefinitely.
- * The media streamer programmer can choose to execute this function directly, or to call ms_start(),
- * that will start a thread for the synchronisation source.
- *
- * Returns: no return value.
- */
-void *ms_thread_run(void *sync);
-
-
-/**
- * function_name:ms_start
- * @sync: A synchronisation source to be started.
- *
- * Starts a thread that will shedule all processing chains attached to the synchronisation source @sync.
- *
- * Returns: no return value.
- */
-void ms_start(MSSync *sync);
-
-
-/**
- * function_name:ms_stop
- * @sync: A synchronisation source to be stopped.
- *
- * Stop the thread that was sheduling the processing chains attached to the synchronisation source @sync.
- * The processing chains are kept unchanged, no object is freed. The synchronisation source can be restarted using ms_start().
- *
- * Returns: no return value.
- */
-void ms_stop(MSSync *sync);
-
-
-gchar * ms_proc_get_param(gchar *parameter);
-gint ms_proc_get_type();
-gint ms_proc_get_speed();
-
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msAlawdec.c b/talk/third_party/mediastreamer/msAlawdec.c
deleted file mode 100755
index 70cc906..0000000
--- a/talk/third_party/mediastreamer/msAlawdec.c
+++ /dev/null
@@ -1,132 +0,0 @@
- /*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include <msAlawdec.h>
-#include <g711common.h>
-
-extern MSFilter * ms_ALAWencoder_new(void);
-
-MSCodecInfo ALAWinfo={
- {
- "ALAW codec",
- 0,
- MS_FILTER_AUDIO_CODEC,
- ms_ALAWencoder_new,
- "This is the classic A-law codec. Good quality, but only usable with high speed network connections."
- },
- ms_ALAWencoder_new,
- ms_ALAWdecoder_new,
- 320,
- 160,
- 64000,
- 8000,
- 8,
- "PCMA",
- 1,
- 1,
-};
-
-static MSALAWDecoderClass *ms_ALAWdecoder_class=NULL;
-
-MSFilter * ms_ALAWdecoder_new(void)
-{
- MSALAWDecoder *r;
-
- r=g_new(MSALAWDecoder,1);
- ms_ALAWdecoder_init(r);
- if (ms_ALAWdecoder_class==NULL)
- {
- ms_ALAWdecoder_class=g_new(MSALAWDecoderClass,1);
- ms_ALAWdecoder_class_init(ms_ALAWdecoder_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ALAWdecoder_class);
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_ALAWdecoder_init(MSALAWDecoder *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->outfifos=r->f_outputs;
- MS_FILTER(r)->r_mingran=ALAW_DECODER_RMAXGRAN;
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSALAWDECODER_MAX_INPUTS);
- memset(r->f_outputs,0,sizeof(MSFifo*)*MSALAWDECODER_MAX_INPUTS);
-
-}
-
-void ms_ALAWdecoder_class_init(MSALAWDecoderClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ALAWDecoder");
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ALAWinfo;
- MS_FILTER_CLASS(klass)->max_finputs=MSALAWDECODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_foutputs=MSALAWDECODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=ALAW_DECODER_RMAXGRAN;
- MS_FILTER_CLASS(klass)->w_maxgran=ALAW_DECODER_WMAXGRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ALAWdecoder_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ALAWdecoder_process;
-}
-
-void ms_ALAWdecoder_process(MSALAWDecoder *r)
-{
- MSFifo *fi,*fo;
- int inlen,outlen;
- gchar *s,*d;
- int i;
- /* process output fifos, but there is only one for this class of filter*/
-
- /* this is the simplest process function design:
- the filter declares a r_mingran of ALAW_DECODER_RMAXGRAN, so the mediastreamer's
- scheduler will call the process function each time there is ALAW_DECODER_RMAXGRAN
- bytes to read in the input fifo. If there is more, then it will call it several
- time in order to the fifo to be completetly processed.
- This is very simple, but not very efficient because of the multiple call function
- of MSFilterProcessFunc that may happen.
- The MSAlawEncoder implements another design; see it.
- */
-
- fi=r->f_inputs[0];
- fo=r->f_outputs[0];
- g_return_if_fail(fi!=NULL);
- g_return_if_fail(fo!=NULL);
-
- inlen=ms_fifo_get_read_ptr(fi,ALAW_DECODER_RMAXGRAN,(void**)&s);
- if (s==NULL) return;
- outlen=ms_fifo_get_write_ptr(fo,ALAW_DECODER_WMAXGRAN,(void**)&d);
- if (d!=NULL)
- {
- for(i=0;i<ALAW_DECODER_RMAXGRAN;i++)
- {
- ((gint16*)d)[i]=alaw_to_s16( (unsigned char) s[i]);
- }
- }
- else g_warning("MSALAWDecoder: Discarding samples !!");
-
-}
-
-
-
-void ms_ALAWdecoder_destroy( MSALAWDecoder *obj)
-{
- g_free(obj);
-}
diff --git a/talk/third_party/mediastreamer/msAlawdec.h b/talk/third_party/mediastreamer/msAlawdec.h
deleted file mode 100755
index 7db4c75..0000000
--- a/talk/third_party/mediastreamer/msAlawdec.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSALAWDECODER_H
-#define MSALAWDECODER_H
-
-#include <msfilter.h>
-#include <mscodec.h>
-
-/*this is the class that implements a ALAWdecoder filter*/
-
-#define MSALAWDECODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSALAWDecoder
-{
- /* the MSALAWDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSALAWDecoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSALAWDECODER_MAX_INPUTS];
- MSFifo *f_outputs[MSALAWDECODER_MAX_INPUTS];
-} MSALAWDecoder;
-
-typedef struct _MSALAWDecoderClass
-{
- /* the MSALAWDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSALAWDecoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSALAWDecoderClass;
-
-/* PUBLIC */
-#define MS_ALAWDECODER(filter) ((MSALAWDecoder*)(filter))
-#define MS_ALAWDECODER_CLASS(klass) ((MSALAWDecoderClass*)(klass))
-MSFilter * ms_ALAWdecoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_ALAWdecoder_init(MSALAWDecoder *r);
-void ms_ALAWdecoder_class_init(MSALAWDecoderClass *klass);
-void ms_ALAWdecoder_destroy( MSALAWDecoder *obj);
-void ms_ALAWdecoder_process(MSALAWDecoder *r);
-
-/* tuning parameters :*/
-#define ALAW_DECODER_WMAXGRAN 320
-#define ALAW_DECODER_RMAXGRAN 160
-
-extern MSCodecInfo ALAWinfo;
-
-#endif
diff --git a/talk/third_party/mediastreamer/msAlawenc.c b/talk/third_party/mediastreamer/msAlawenc.c
deleted file mode 100755
index fd1f9ab..0000000
--- a/talk/third_party/mediastreamer/msAlawenc.c
+++ /dev/null
@@ -1,124 +0,0 @@
- /*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "msAlawenc.h"
-#include "g711common.h"
-
-extern MSCodecInfo ALAWinfo;
-
-static MSALAWEncoderClass *ms_ALAWencoder_class=NULL;
-
-MSFilter * ms_ALAWencoder_new(void)
-{
- MSALAWEncoder *r;
-
- r=g_new(MSALAWEncoder,1);
- ms_ALAWencoder_init(r);
- if (ms_ALAWencoder_class==NULL)
- {
- ms_ALAWencoder_class=g_new(MSALAWEncoderClass,1);
- ms_ALAWencoder_class_init(ms_ALAWencoder_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ALAWencoder_class);
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_ALAWencoder_init(MSALAWEncoder *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->outfifos=r->f_outputs;
- MS_FILTER(r)->r_mingran=ALAW_ENCODER_RMAXGRAN; /* the filter can be called as soon as there is
- something to process */
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSALAWENCODER_MAX_INPUTS);
- memset(r->f_outputs,0,sizeof(MSFifo*)*MSALAWENCODER_MAX_INPUTS);
-
-}
-
-void ms_ALAWencoder_class_init(MSALAWEncoderClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ALAWEncoder");
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ALAWinfo;
- MS_FILTER_CLASS(klass)->max_finputs=MSALAWENCODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_foutputs=MSALAWENCODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=ALAW_ENCODER_RMAXGRAN;
- MS_FILTER_CLASS(klass)->w_maxgran=ALAW_ENCODER_WMAXGRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ALAWencoder_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ALAWencoder_process;
-}
-
-void ms_ALAWencoder_process(MSALAWEncoder *r)
-{
- MSFifo *fi,*fo;
- int inlen,outlen;
- gchar *s,*d;
- int i;
- /* process output fifos, but there is only one for this class of filter*/
-
- /* this is the sophisticated design of the process function:
- Here the filter declares that it can be called as soon as there is something
- to read on the input fifo by setting r_mingran=0.
- Then it ask for the fifo to get as many data as possible by calling:
- inlen=ms_fifo_get_read_ptr(fi,0,(void**)&s);
- This avoid multiple call to the process function to process all data available
- on the input fifo... but the writing of the process function is a bit
- more difficult, because althoug ms_fifo_get_read_ptr() returns N bytes,
- we cannot ask ms_fifo_get_write_ptr to return N bytes if
- N>MS_FILTER_CLASS(klass)->w_maxgran. This is forbidden by the MSFifo
- mechanism.
- This is an open issue.
- For the moment what is done here is that ms_fifo_get_write_ptr() is called
- several time with its maximum granularity in order to try to write the output.
- ...
- One solution:
- -create a new function ms_fifo_get_rw_ptr(fifo1,p1, fifo2,p2) to
- return the number of bytes able to being processed according to the input
- and output fifo, and their respective data pointers
- */
-
-
- fi=r->f_inputs[0];
- fo=r->f_outputs[0];
-
- inlen=ms_fifo_get_read_ptr(fi,ALAW_ENCODER_RMAXGRAN,(void**)&s);
- if (s==NULL) return;
- outlen=ms_fifo_get_write_ptr(fo,ALAW_ENCODER_WMAXGRAN,(void**)&d);
- if (d!=NULL)
- {
- for(i=0;i<ALAW_ENCODER_WMAXGRAN;i++)
- {
- d[i]=s16_to_alaw( *((gint16*)s) );
- s+=2;
- }
- }
- else g_warning("MSALAWDecoder: Discarding samples !!");
-
-}
-
-
-
-void ms_ALAWencoder_destroy( MSALAWEncoder *obj)
-{
- g_free(obj);
-}
diff --git a/talk/third_party/mediastreamer/msAlawenc.h b/talk/third_party/mediastreamer/msAlawenc.h
deleted file mode 100755
index 608a988..0000000
--- a/talk/third_party/mediastreamer/msAlawenc.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSALAWENCODER_H
-#define MSALAWENCODER_H
-
-#include "mscodec.h"
-
-
-/*this is the class that implements a ALAWencoder filter*/
-
-#define MSALAWENCODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSALAWEncoder
-{
- /* the MSALAWEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSALAWEncoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSALAWENCODER_MAX_INPUTS];
- MSFifo *f_outputs[MSALAWENCODER_MAX_INPUTS];
-} MSALAWEncoder;
-
-typedef struct _MSALAWEncoderClass
-{
- /* the MSALAWEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSALAWEncoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSALAWEncoderClass;
-
-/* PUBLIC */
-#define MS_ALAWENCODER(filter) ((MSALAWEncoder*)(filter))
-#define MS_ALAWENCODER_CLASS(klass) ((MSALAWEncoderClass*)(klass))
-MSFilter * ms_ALAWencoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_ALAWencoder_init(MSALAWEncoder *r);
-void ms_ALAWencoder_class_init(MSALAWEncoderClass *klass);
-void ms_ALAWencoder_destroy( MSALAWEncoder *obj);
-void ms_ALAWencoder_process(MSALAWEncoder *r);
-
-/* tuning parameters :*/
-#define ALAW_ENCODER_WMAXGRAN 160
-#define ALAW_ENCODER_RMAXGRAN 320
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msGSMdecoder.h b/talk/third_party/mediastreamer/msGSMdecoder.h
deleted file mode 100755
index e73fb33..0000000
--- a/talk/third_party/mediastreamer/msGSMdecoder.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSGSMDECODER_H
-#define MSGSMDECODER_H
-
-#include <msfilter.h>
-#include <mscodec.h>
-#include <gsm.h>
-
-/*this is the class that implements a GSMdecoder filter*/
-
-#define MSGSMDECODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSGSMDecoder
-{
- /* the MSGSMDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSGSMDecoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSGSMDECODER_MAX_INPUTS];
- MSFifo *f_outputs[MSGSMDECODER_MAX_INPUTS];
- gsm gsm_handle;
-} MSGSMDecoder;
-
-typedef struct _MSGSMDecoderClass
-{
- /* the MSGSMDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSGSMDecoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSGSMDecoderClass;
-
-/* PUBLIC */
-#define MS_GSMDECODER(filter) ((MSGSMDecoder*)(filter))
-#define MS_GSMDECODER_CLASS(klass) ((MSGSMDecoderClass*)(klass))
-MSFilter * ms_GSMdecoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_GSMdecoder_init(MSGSMDecoder *r);
-void ms_GSMdecoder_class_init(MSGSMDecoderClass *klass);
-void ms_GSMdecoder_destroy( MSGSMDecoder *obj);
-void ms_GSMdecoder_process(MSGSMDecoder *r);
-
-extern MSCodecInfo GSMinfo;
-
-#endif
diff --git a/talk/third_party/mediastreamer/msGSMencoder.h b/talk/third_party/mediastreamer/msGSMencoder.h
deleted file mode 100755
index 2deae38..0000000
--- a/talk/third_party/mediastreamer/msGSMencoder.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSGSMENCODER_H
-#define MSGSMENCODER_H
-
-#include "msfilter.h"
-#include <gsm.h>
-
-/*this is the class that implements a GSMencoder filter*/
-
-#define MSGSMENCODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSGSMEncoder
-{
- /* the MSGSMEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSGSMEncoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSGSMENCODER_MAX_INPUTS];
- MSFifo *f_outputs[MSGSMENCODER_MAX_INPUTS];
- gsm gsm_handle;
-} MSGSMEncoder;
-
-typedef struct _MSGSMEncoderClass
-{
- /* the MSGSMEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSGSMEncoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSGSMEncoderClass;
-
-/* PUBLIC */
-#define MS_GSMENCODER(filter) ((MSGSMEncoder*)(filter))
-#define MS_GSMENCODER_CLASS(klass) ((MSGSMEncoderClass*)(klass))
-MSFilter * ms_GSMencoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_GSMencoder_init(MSGSMEncoder *r);
-void ms_GSMencoder_class_init(MSGSMEncoderClass *klass);
-void ms_GSMencoder_destroy( MSGSMEncoder *obj);
-void ms_GSMencoder_process(MSGSMEncoder *r);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msLPC10decoder.h b/talk/third_party/mediastreamer/msLPC10decoder.h
deleted file mode 100755
index 59d9dec..0000000
--- a/talk/third_party/mediastreamer/msLPC10decoder.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSLPC10DECODER_H
-#define MSLPC10DECODER_H
-
-#include <msfilter.h>
-#include <mscodec.h>
-#include <lpc10.h>
-
-/*this is the class that implements a LPC10decoder filter*/
-
-#define MSLPC10DECODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSLPC10Decoder
-{
- /* the MSLPC10Decoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSLPC10Decoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSLPC10DECODER_MAX_INPUTS];
- MSFifo *f_outputs[MSLPC10DECODER_MAX_INPUTS];
- struct lpc10_decoder_state *lpc10_dec;
-} MSLPC10Decoder;
-
-typedef struct _MSLPC10DecoderClass
-{
- /* the MSLPC10Decoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSLPC10Decoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSLPC10DecoderClass;
-
-/* PUBLIC */
-#define MS_LPC10DECODER(filter) ((MSLPC10Decoder*)(filter))
-#define MS_LPC10DECODER_CLASS(klass) ((MSLPC10DecoderClass*)(klass))
-MSFilter * ms_LPC10decoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_LPC10decoder_init(MSLPC10Decoder *r);
-void ms_LPC10decoder_class_init(MSLPC10DecoderClass *klass);
-void ms_LPC10decoder_destroy( MSLPC10Decoder *obj);
-void ms_LPC10decoder_process(MSLPC10Decoder *r);
-
-extern MSCodecInfo LPC10info;
-
-#endif
diff --git a/talk/third_party/mediastreamer/msLPC10encoder.h b/talk/third_party/mediastreamer/msLPC10encoder.h
deleted file mode 100755
index 4db1643..0000000
--- a/talk/third_party/mediastreamer/msLPC10encoder.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSLPC10ENCODER_H
-#define MSLPC10ENCODER_H
-
-#include "mscodec.h"
-
-
-int
-read_16bit_samples(gint16 int16samples[], float speech[], int n);
-
-int
-write_16bit_samples(gint16 int16samples[], float speech[], int n);
-
-void
-write_bits(unsigned char *data, gint32 *bits, int len);
-
-int
-read_bits(unsigned char *data, gint32 *bits, int len);
-
-
-/*this is the class that implements a LPC10encoder filter*/
-
-#define MSLPC10ENCODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSLPC10Encoder
-{
- /* the MSLPC10Encoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSLPC10Encoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSLPC10ENCODER_MAX_INPUTS];
- MSFifo *f_outputs[MSLPC10ENCODER_MAX_INPUTS];
- struct lpc10_encoder_state *lpc10_enc;
-} MSLPC10Encoder;
-
-typedef struct _MSLPC10EncoderClass
-{
- /* the MSLPC10Encoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSLPC10Encoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSLPC10EncoderClass;
-
-/* PUBLIC */
-#define MS_LPC10ENCODER(filter) ((MSLPC10Encoder*)(filter))
-#define MS_LPC10ENCODER_CLASS(klass) ((MSLPC10EncoderClass*)(klass))
-MSFilter * ms_LPC10encoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_LPC10encoder_init(MSLPC10Encoder *r);
-void ms_LPC10encoder_class_init(MSLPC10EncoderClass *klass);
-void ms_LPC10encoder_destroy( MSLPC10Encoder *obj);
-void ms_LPC10encoder_process(MSLPC10Encoder *r);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msMUlawdec.c b/talk/third_party/mediastreamer/msMUlawdec.c
deleted file mode 100755
index 500f238..0000000
--- a/talk/third_party/mediastreamer/msMUlawdec.c
+++ /dev/null
@@ -1,130 +0,0 @@
- /*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include <msMUlawdec.h>
-#include <g711common.h>
-
-extern MSFilter * ms_MULAWencoder_new(void);
-
-MSCodecInfo MULAWinfo={
- {
- "MULAW codec",
- 0,
- MS_FILTER_AUDIO_CODEC,
- ms_MULAWencoder_new,
- "This is the classic Mu-law codec. Good quality, but only usable with high speed network connections."
- },
- ms_MULAWencoder_new,
- ms_MULAWdecoder_new,
- 320,
- 160,
- 64000,
- 8000,
- 0,
- "PCMU",
- 1,
- 1
-};
-
-static MSMULAWDecoderClass *ms_MULAWdecoder_class=NULL;
-
-MSFilter * ms_MULAWdecoder_new(void)
-{
- MSMULAWDecoder *r;
-
- r=g_new(MSMULAWDecoder,1);
- ms_MULAWdecoder_init(r);
- if (ms_MULAWdecoder_class==NULL)
- {
- ms_MULAWdecoder_class=g_new(MSMULAWDecoderClass,1);
- ms_MULAWdecoder_class_init(ms_MULAWdecoder_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_MULAWdecoder_class);
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_MULAWdecoder_init(MSMULAWDecoder *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->outfifos=r->f_outputs;
- MS_FILTER(r)->r_mingran=MULAW_DECODER_RMAXGRAN;
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSMULAWDECODER_MAX_INPUTS);
- memset(r->f_outputs,0,sizeof(MSFifo*)*MSMULAWDECODER_MAX_INPUTS);
-
-}
-
-void ms_MULAWdecoder_class_init(MSMULAWDecoderClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"MULAWDecoder");
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&MULAWinfo;
- MS_FILTER_CLASS(klass)->max_finputs=MSMULAWDECODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_foutputs=MSMULAWDECODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=MULAW_DECODER_RMAXGRAN;
- MS_FILTER_CLASS(klass)->w_maxgran=MULAW_DECODER_WMAXGRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_MULAWdecoder_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_MULAWdecoder_process;
-}
-
-void ms_MULAWdecoder_process(MSMULAWDecoder *r)
-{
- MSFifo *fi,*fo;
- int inlen,outlen;
- gchar *s,*d;
- int i;
- /* process output fifos, but there is only one for this class of filter*/
-
- /* this is the simplest process function design:
- the filter declares a r_mingran of MULAW_DECODER_RMAXGRAN, so the mediastreamer's
- scheduler will call the process function each time there is MULAW_DECODER_RMAXGRAN
- bytes to read in the input fifo. If there is more, then it will call it several
- time in order to the fifo to be completetly processed.
- This is very simple, but not very efficient because of the multiple call function
- of MSFilterProcessFunc that may happen.
- The MSAlawEncoder implements another design; see it.
- */
-
- fi=r->f_inputs[0];
- fo=r->f_outputs[0];
-
- inlen=ms_fifo_get_read_ptr(fi,MULAW_DECODER_RMAXGRAN,(void**)&s);
- if (s==NULL) g_error("ms_MULAWdecoder_process: internal error.");
- outlen=ms_fifo_get_write_ptr(fo,MULAW_DECODER_WMAXGRAN,(void**)&d);
- if (d!=NULL)
- {
- for(i=0;i<MULAW_DECODER_RMAXGRAN;i++)
- {
- *((gint16*)d)=ulaw_to_s16( (unsigned char) s[i]);
- d+=2;
- }
- }
- else g_warning("MSMULAWDecoder: Discarding samples !!");
-}
-
-
-
-void ms_MULAWdecoder_destroy( MSMULAWDecoder *obj)
-{
- g_free(obj);
-}
diff --git a/talk/third_party/mediastreamer/msMUlawdec.h b/talk/third_party/mediastreamer/msMUlawdec.h
deleted file mode 100755
index c135d21..0000000
--- a/talk/third_party/mediastreamer/msMUlawdec.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSMULAWDECODER_H
-#define MSMULAWDECODER_H
-
-#include <msfilter.h>
-#include <mscodec.h>
-
-/*this is the class that implements a MULAWdecoder filter*/
-
-#define MSMULAWDECODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSMULAWDecoder
-{
- /* the MSMULAWDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSMULAWDecoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSMULAWDECODER_MAX_INPUTS];
- MSFifo *f_outputs[MSMULAWDECODER_MAX_INPUTS];
-} MSMULAWDecoder;
-
-typedef struct _MSMULAWDecoderClass
-{
- /* the MSMULAWDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSMULAWDecoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSMULAWDecoderClass;
-
-/* PUBLIC */
-#define MS_MULAWDECODER(filter) ((MSMULAWDecoder*)(filter))
-#define MS_MULAWDECODER_CLASS(klass) ((MSMULAWDecoderClass*)(klass))
-MSFilter * ms_MULAWdecoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_MULAWdecoder_init(MSMULAWDecoder *r);
-void ms_MULAWdecoder_class_init(MSMULAWDecoderClass *klass);
-void ms_MULAWdecoder_destroy( MSMULAWDecoder *obj);
-void ms_MULAWdecoder_process(MSMULAWDecoder *r);
-
-/* tuning parameters :*/
-#define MULAW_DECODER_WMAXGRAN 320
-#define MULAW_DECODER_RMAXGRAN 160
-
-extern MSCodecInfo MULAWinfo;
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msMUlawenc.c b/talk/third_party/mediastreamer/msMUlawenc.c
deleted file mode 100755
index 2f740d8..0000000
--- a/talk/third_party/mediastreamer/msMUlawenc.c
+++ /dev/null
@@ -1,99 +0,0 @@
- /*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "msMUlawenc.h"
-#include "g711common.h"
-
-extern MSCodecInfo MULAWinfo;
-
-static MSMULAWEncoderClass *ms_MULAWencoder_class=NULL;
-
-MSFilter * ms_MULAWencoder_new(void)
-{
- MSMULAWEncoder *r;
-
- r=g_new(MSMULAWEncoder,1);
- ms_MULAWencoder_init(r);
- if (ms_MULAWencoder_class==NULL)
- {
- ms_MULAWencoder_class=g_new(MSMULAWEncoderClass,1);
- ms_MULAWencoder_class_init(ms_MULAWencoder_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_MULAWencoder_class);
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_MULAWencoder_init(MSMULAWEncoder *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->outfifos=r->f_outputs;
- MS_FILTER(r)->r_mingran=MULAW_ENCODER_RMAXGRAN; /* the filter can be called as soon as there is
- something to process */
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSMULAWENCODER_MAX_INPUTS);
- memset(r->f_outputs,0,sizeof(MSFifo*)*MSMULAWENCODER_MAX_INPUTS);
-
-}
-
-void ms_MULAWencoder_class_init(MSMULAWEncoderClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"MULAWEncoder");
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&MULAWinfo;
- MS_FILTER_CLASS(klass)->max_finputs=MSMULAWENCODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_foutputs=MSMULAWENCODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=MULAW_ENCODER_RMAXGRAN;
- MS_FILTER_CLASS(klass)->w_maxgran=MULAW_ENCODER_WMAXGRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_MULAWencoder_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_MULAWencoder_process;
-}
-
-void ms_MULAWencoder_process(MSMULAWEncoder *r)
-{
- MSFifo *fi,*fo;
- int inlen,outlen;
- gchar *s,*d;
- int i;
- /* process output fifos, but there is only one for this class of filter*/
-
- fi=r->f_inputs[0];
- fo=r->f_outputs[0];
- inlen=ms_fifo_get_read_ptr(fi,MULAW_ENCODER_RMAXGRAN,(void**)&s);
- outlen=ms_fifo_get_write_ptr(fo,MULAW_ENCODER_WMAXGRAN,(void**)&d);
- if (d!=NULL)
- {
- for(i=0;i<MULAW_ENCODER_WMAXGRAN;i++)
- {
- d[i]=s16_to_ulaw( *((gint16*)s) );
- s+=2;
- }
- }
- else g_warning("MSMULAWDecoder: Discarding samples !!");
-}
-
-
-
-void ms_MULAWencoder_destroy( MSMULAWEncoder *obj)
-{
- g_free(obj);
-}
diff --git a/talk/third_party/mediastreamer/msMUlawenc.h b/talk/third_party/mediastreamer/msMUlawenc.h
deleted file mode 100755
index 52f7666..0000000
--- a/talk/third_party/mediastreamer/msMUlawenc.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSMULAWENCODER_H
-#define MSMULAWENCODER_H
-
-#include "mscodec.h"
-
-
-/*this is the class that implements a MULAWencoder filter*/
-
-#define MSMULAWENCODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSMULAWEncoder
-{
- /* the MSMULAWEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSMULAWEncoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSMULAWENCODER_MAX_INPUTS];
- MSFifo *f_outputs[MSMULAWENCODER_MAX_INPUTS];
-} MSMULAWEncoder;
-
-typedef struct _MSMULAWEncoderClass
-{
- /* the MSMULAWEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSMULAWEncoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSMULAWEncoderClass;
-
-/* PUBLIC */
-#define MS_MULAWENCODER(filter) ((MSMULAWEncoder*)(filter))
-#define MS_MULAWENCODER_CLASS(klass) ((MSMULAWEncoderClass*)(klass))
-MSFilter * ms_MULAWencoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_MULAWencoder_init(MSMULAWEncoder *r);
-void ms_MULAWencoder_class_init(MSMULAWEncoderClass *klass);
-void ms_MULAWencoder_destroy( MSMULAWEncoder *obj);
-void ms_MULAWencoder_process(MSMULAWEncoder *r);
-
-/* tuning parameters :*/
-#define MULAW_ENCODER_WMAXGRAN 160
-#define MULAW_ENCODER_RMAXGRAN 320
-
-#endif
diff --git a/talk/third_party/mediastreamer/msavdecoder.h b/talk/third_party/mediastreamer/msavdecoder.h
deleted file mode 100755
index e7c880b..0000000
--- a/talk/third_party/mediastreamer/msavdecoder.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSAVDECODER_H
-#define MSAVDECODER_H
-
-#include "msfilter.h"
-
-
-#include <avcodec.h>
-
-/*this is the class that implements a AVdecoder filter*/
-
-#define MSAVDECODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-struct _MSAVDecoder
-{
- /* the MSAVDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSAVDecoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSQueue *q_inputs[MSAVDECODER_MAX_INPUTS];
- MSQueue *q_outputs[MSAVDECODER_MAX_INPUTS];
- AVCodec *av_codec; /*the AVCodec from which this MSFilter is related */
- AVCodecContext av_context; /* the context of the AVCodec */
- gint av_opened;
- int output_pix_fmt;
- int width;
- int height;
- int skip_gob;
- unsigned char buf_compressed[100000];
- int buf_size;
- MSBuffer *obufwrap; /* alternate buffer, when format change is needed*/
-};
-
-typedef struct _MSAVDecoder MSAVDecoder;
-
-struct _MSAVDecoderClass
-{
- /* the MSAVDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSAVDecoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-};
-
-typedef struct _MSAVDecoderClass MSAVDecoderClass;
-
-/* PUBLIC */
-#define MS_AVDECODER(filter) ((MSAVDecoder*)(filter))
-#define MS_AVDECODER_CLASS(klass) ((MSAVDecoderClass*)(klass))
-
-MSFilter *ms_h263_decoder_new();
-MSFilter *ms_mpeg_decoder_new();
-MSFilter *ms_mpeg4_decoder_new();
-MSFilter * ms_AVdecoder_new_with_codec(enum CodecID codec_id);
-
-gint ms_AVdecoder_set_format(MSAVDecoder *dec, gchar *fmt);
-void ms_AVdecoder_set_width(MSAVDecoder *av,gint w);
-void ms_AVdecoder_set_height(MSAVDecoder *av,gint h);
-
-/* FOR INTERNAL USE*/
-void ms_AVdecoder_init(MSAVDecoder *r, AVCodec *codec);
-void ms_AVdecoder_uninit(MSAVDecoder *enc);
-void ms_AVdecoder_class_init(MSAVDecoderClass *klass);
-void ms_AVdecoder_destroy( MSAVDecoder *obj);
-void ms_AVdecoder_process(MSAVDecoder *r);
-
-void ms_AVCodec_init();
-
-#endif
diff --git a/talk/third_party/mediastreamer/msavencoder.h b/talk/third_party/mediastreamer/msavencoder.h
deleted file mode 100755
index 6fe5cad..0000000
--- a/talk/third_party/mediastreamer/msavencoder.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSAVENCODER_H
-#define MSAVENCODER_H
-
-#include "msfilter.h"
-#include "mscodec.h"
-#include <avcodec.h>
-
-/*this is the class that implements a AVencoder filter*/
-
-#define MSAVENCODER_MAX_INPUTS 1 /* max output per filter*/
-#define MSAVENCODER_MAX_OUTPUTS 2
-
-struct _MSAVEncoder
-{
- /* the MSAVEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSAVEncoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSQueue *q_inputs[MSAVENCODER_MAX_INPUTS];
- MSQueue *q_outputs[MSAVENCODER_MAX_OUTPUTS];
- AVCodec *av_codec; /*the AVCodec from which this MSFilter is related */
- AVCodecContext av_context; /* the context of the AVCodec */
- gint input_pix_fmt;
- gint av_opened;
- MSBuffer *comp_buf;
- MSBuffer *yuv_buf;
-};
-
-typedef struct _MSAVEncoder MSAVEncoder;
-/* MSAVEncoder always outputs planar YUV and accept any incoming format you should setup using
- ms_AVencoder_set_format()
-q_outputs[0] is the compressed video stream output
-q_outputs[1] is a YUV planar buffer of the image it receives in input.
-*/
-
-
-struct _MSAVEncoderClass
-{
- /* the MSAVEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSAVEncoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-};
-
-typedef struct _MSAVEncoderClass MSAVEncoderClass;
-
-/* PUBLIC */
-#define MS_AVENCODER(filter) ((MSAVEncoder*)(filter))
-#define MS_AVENCODER_CLASS(klass) ((MSAVEncoderClass*)(klass))
-
-MSFilter *ms_h263_encoder_new();
-MSFilter *ms_mpeg_encoder_new();
-MSFilter *ms_mpeg4_encoder_new();
-MSFilter * ms_AVencoder_new_with_codec(enum CodecID codec_id, MSCodecInfo *info);
-
-gint ms_AVencoder_set_format(MSAVEncoder *enc, gchar *fmt);
-
-#define ms_AVencoder_set_width(av,w) (av)->av_context.width=(w)
-#define ms_AVencoder_set_height(av,h) (av)->av_context.height=(h)
-#define ms_AVencoder_set_bit_rate(av,r) (av)->av_context.bit_rate=(r)
-
-void ms_AVencoder_set_frame_rate(MSAVEncoder *enc, gint frame_rate, gint frame_rate_base);
-
-/* FOR INTERNAL USE*/
-void ms_AVencoder_init(MSAVEncoder *r, AVCodec *codec);
-void ms_AVencoder_uninit(MSAVEncoder *enc);
-void ms_AVencoder_class_init(MSAVEncoderClass *klass);
-void ms_AVencoder_destroy( MSAVEncoder *obj);
-void ms_AVencoder_process(MSAVEncoder *r);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msbuffer.c b/talk/third_party/mediastreamer/msbuffer.c
deleted file mode 100755
index 4ca3c92..0000000
--- a/talk/third_party/mediastreamer/msbuffer.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "msbuffer.h"
-#include "msutils.h"
-#include <string.h>
-
-
-
-MSBuffer * ms_buffer_new(guint32 size)
-{
- MSBuffer *buf;
- buf=(MSBuffer*)g_malloc(sizeof(MSBuffer)+size);
- buf->ref_count=0;
- buf->size=size;
- ms_trace("ms_buffer_new: Allocating buffer of %i bytes.",size);
- /* allocate the data buffer: there is a lot of optmisation that can be done by using a pool of cached buffers*/
- buf->buffer=((char*)(buf))+sizeof(MSBuffer); /* to avoid to do two allocations,
- buffer info and buffer are contigous.*/
- buf->flags=MS_BUFFER_CONTIGUOUS;
- return(buf);
-}
-
-MSBuffer *ms_buffer_alloc(gint flags)
-{
- MSBuffer *buf;
- buf=(MSBuffer*)g_malloc(sizeof(MSBuffer));
- buf->ref_count=0;
- buf->size=0;
- buf->buffer=NULL;
- buf->flags=0;
- return(buf);
-}
-
-
-void ms_buffer_destroy(MSBuffer *buf)
-{
- if (buf->flags & MS_BUFFER_CONTIGUOUS){
- g_free(buf);
- }
- else {
- g_free(buf->buffer);
- g_free(buf);
- }
-}
-
-MSMessage *ms_message_alloc()
-{
- MSMessage *m=g_malloc(sizeof(MSMessage));
- memset(m,0,sizeof(MSMessage));
- return m;
-}
-
-MSMessage *ms_message_new(gint size)
-{
- MSMessage *m=ms_message_alloc();
- MSBuffer *buf=ms_buffer_new(size);
- ms_message_set_buf(m,buf);
- return m;
-}
-
-void ms_message_destroy(MSMessage *m)
-{
- /* the buffer is freed if its ref_count goes to zero */
- if (m->buffer!=NULL){
- m->buffer->ref_count--;
- if (m->buffer->ref_count==0) ms_buffer_destroy(m->buffer);
- }
- g_free(m);
-}
-
-MSMessage * ms_message_dup(MSMessage *m)
-{
- MSMessage *msg=ms_message_alloc();
- ms_message_set_buf(msg,m->buffer);
- return msg;
-}
diff --git a/talk/third_party/mediastreamer/msbuffer.h b/talk/third_party/mediastreamer/msbuffer.h
deleted file mode 100755
index f96b35a..0000000
--- a/talk/third_party/mediastreamer/msbuffer.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSBUFFER_H
-#define MSBUFFER_H
-#include <config.h>
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#else
-#include <uglib.h>
-#endif
-
-
-#define MS_BUFFER_LARGE 4092
-
-
-typedef struct _MSBuffer
-{
- gchar *buffer;
- guint32 size;
- guint16 ref_count;
- guint16 flags;
-#define MS_BUFFER_CONTIGUOUS (1)
-}MSBuffer;
-
-MSBuffer * ms_buffer_new(guint32 size);
-void ms_buffer_destroy(MSBuffer *buf);
-
-struct _MSMessage
-{
- MSBuffer *buffer; /* points to a MSBuffer */
- void *data; /*points to buffer->buffer */
- guint32 size; /* the size of the buffer to read in data. It may not be the
- physical size (I mean buffer->buffer->size */
- struct _MSMessage *next;
- struct _MSMessage *prev; /* MSMessage are queued into MSQueues */
-};
-
-typedef struct _MSMessage MSMessage;
-
-
-MSBuffer *ms_buffer_alloc(gint flags);
-MSMessage *ms_message_new(gint size);
-
-#define ms_message_set_buf(m,b) do { (b)->ref_count++; (m)->buffer=(b); (m)->data=(b)->buffer; (m)->size=(b)->size; }while(0)
-#define ms_message_unset_buf(m) do { (m)->buffer->ref_count--; (m)->buffer=NULL; (m)->size=0; (m)->data=NULL; } while(0)
-
-#define ms_message_size(m) (m)->size
-void ms_message_destroy(MSMessage *m);
-
-MSMessage * ms_message_dup(MSMessage *m);
-
-/* allocate a single message without buffer */
-MSMessage *ms_message_alloc();
-
-#endif
diff --git a/talk/third_party/mediastreamer/mscodec.c b/talk/third_party/mediastreamer/mscodec.c
deleted file mode 100755
index 7677dbe..0000000
--- a/talk/third_party/mediastreamer/mscodec.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "mscodec.h"
-#include "msMUlawdec.h"
-
-#ifdef TRUESPEECH
-extern MSCodecInfo TrueSpeechinfo;
-#endif
-
-#ifdef VIDEO_ENABLED
-extern void ms_AVCodec_init();
-#endif
-
-#define UDP_HDR_SZ 8
-#define RTP_HDR_SZ 12
-#define IP4_HDR_SZ 20 /*20 is the minimum, but there may be some options*/
-
-
-
-
-/* register all statically linked codecs */
-void ms_codec_register_all()
-{
-// ms_filter_register(MS_FILTER_INFO(&GSMinfo));
-// ms_filter_register(MS_FILTER_INFO(&LPC10info));
- ms_filter_register(MS_FILTER_INFO(&MULAWinfo));
-#ifdef TRUESPEECH
- ms_filter_register(MS_FILTER_INFO(&TrueSpeechinfo));
-#endif
-#ifdef VIDEO_ENABLED
- ms_AVCodec_init();
-#endif
-
-}
-
-/* returns a list of MSCodecInfo */
-GList * ms_codec_get_all_audio()
-{
- GList *audio_codecs=NULL;
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if (info->type==MS_FILTER_AUDIO_CODEC){
- audio_codecs=g_list_append(audio_codecs,info);
- }
- elem=g_list_next(elem);
- }
- return audio_codecs;
-}
-
-
-MSCodecInfo * ms_audio_codec_info_get(gchar *name)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ( (info->type==MS_FILTER_AUDIO_CODEC) ){
- MSCodecInfo *codinfo=(MSCodecInfo *)info;
- if (strcmp(codinfo->description,name)==0){
- return MS_CODEC_INFO(info);
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-
-MSCodecInfo * ms_video_codec_info_get(gchar *name)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ( (info->type==MS_FILTER_VIDEO_CODEC) ){
- MSCodecInfo *codinfo=(MSCodecInfo *)info;
- if (strcmp(codinfo->description,name)==0){
- return MS_CODEC_INFO(info);
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-
-/* returns a list of MSCodecInfo */
-GList * ms_codec_get_all_video()
-{
- GList *video_codecs=NULL;
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if (info->type==MS_FILTER_VIDEO_CODEC){
- video_codecs=g_list_append(video_codecs,info);
- }
- elem=g_list_next(elem);
- }
- return video_codecs;
-}
-
-MSFilter * ms_encoder_new(gchar *name)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){
- MSCodecInfo *codinfo=(MSCodecInfo *)elem->data;
- if (strcmp(info->name,name)==0){
- return codinfo->encoder();
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-
-MSFilter * ms_decoder_new(gchar *name)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){
- MSCodecInfo *codinfo=(MSCodecInfo *)elem->data;
- if (strcmp(info->name,name)==0){
- return codinfo->decoder();
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-
-MSFilter * ms_encoder_new_with_pt(gint pt)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){
- MSCodecInfo *codinfo=(MSCodecInfo *)elem->data;
- if (codinfo->pt==pt){
- return codinfo->encoder();
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-
-MSFilter * ms_decoder_new_with_pt(gint pt)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){
- MSCodecInfo *codinfo=(MSCodecInfo *)elem->data;
- if (codinfo->pt==pt){
- return codinfo->decoder();
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-
-MSFilter * ms_decoder_new_with_string_id(gchar *id)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){
- MSCodecInfo *codinfo=(MSCodecInfo *)elem->data;
- if (strcasecmp(codinfo->description,id)==0){
- return codinfo->decoder();
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-
-MSFilter * ms_encoder_new_with_string_id(gchar *id)
-{
- GList *elem=filter_list;
- MSFilterInfo *info;
- while (elem!=NULL)
- {
- info=(MSFilterInfo *)elem->data;
- if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){
- MSCodecInfo *codinfo=(MSCodecInfo *)elem->data;
- if (strcasecmp(codinfo->description,id)==0){
- return codinfo->encoder();
- }
- }
- elem=g_list_next(elem);
- }
- return NULL;
-}
-/* return 0 if codec can be used with bandwidth, -1 else*/
-int ms_codec_is_usable(MSCodecInfo *codec,double bandwidth)
-{
- double codec_band;
- double npacket;
- double packet_size;
-
- if (((MSFilterInfo*)codec)->type==MS_FILTER_AUDIO_CODEC)
- {
- /* calculate the total bandwdith needed by codec (including headers for rtp, udp, ip)*/
- /* number of packet per second*/
- npacket=2.0*(double)(codec->rate)/(double)(codec->fr_size);
- packet_size=(double)(codec->dt_size)+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ;
- codec_band=packet_size*8.0*npacket;
- }
- else return -1;
- return(codec_band<bandwidth);
-}
diff --git a/talk/third_party/mediastreamer/mscodec.h b/talk/third_party/mediastreamer/mscodec.h
deleted file mode 100755
index 6c6847d..0000000
--- a/talk/third_party/mediastreamer/mscodec.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSCODEC_H
-#define MSCODEC_H
-
-#include "msfilter.h"
-
-struct _MSCodecInfo
-{
- MSFilterInfo info;
- MSFilterNewFunc encoder;
- MSFilterNewFunc decoder;
- gint fr_size; /* size in char of the uncompressed frame */
- gint dt_size; /* size in char of the compressed frame */
- gint bitrate; /* the minimum bit rate in bits/second */
- gint rate; /*frequency */
- gint pt; /* the payload type number associated with this codec*/
- gchar *description; /* a rtpmap field to describe the codec */
- guint is_usable:1; /* linphone set this flag to remember if it can use this codec considering the total bandwidth*/
- guint is_selected:1; /* linphone (user) set this flag if he allows this codec to be used*/
-};
-
-typedef struct _MSCodecInfo MSCodecInfo;
-
-MSFilter * ms_encoder_new(gchar *name);
-MSFilter * ms_decoder_new(gchar *name);
-
-MSFilter * ms_encoder_new_with_pt(gint pt);
-MSFilter * ms_decoder_new_with_pt(gint pt);
-
-MSFilter * ms_encoder_new_with_string_id(gchar *id);
-MSFilter * ms_decoder_new_with_string_id(gchar *id);
-
-/* return 0 if codec can be used with bandwidth, -1 else*/
-int ms_codec_is_usable(MSCodecInfo *codec,double bandwidth);
-
-GList * ms_codec_get_all_audio();
-
-GList * ms_codec_get_all_video();
-
-MSCodecInfo * ms_audio_codec_info_get(gchar *name);
-MSCodecInfo * ms_video_codec_info_get(gchar *name);
-
-/* register all statically linked codecs */
-void ms_codec_register_all();
-
-#define MS_CODEC_INFO(codinfo) ((MSCodecInfo*)codinfo)
-
-#endif
diff --git a/talk/third_party/mediastreamer/mscopy.c b/talk/third_party/mediastreamer/mscopy.c
deleted file mode 100755
index 3040b2e..0000000
--- a/talk/third_party/mediastreamer/mscopy.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "mscopy.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <errno.h>
-
-static MSCopyClass *ms_copy_class=NULL;
-
-MSFilter * ms_copy_new(void)
-{
- MSCopy *r;
-
- r=g_new(MSCopy,1);
- ms_copy_init(r);
- if (ms_copy_class==NULL)
- {
- ms_copy_class=g_new(MSCopyClass,1);
- ms_copy_class_init(ms_copy_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_copy_class);
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_copy_init(MSCopy *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->outfifos=r->f_outputs;
- MS_FILTER(r)->r_mingran=MSCOPY_DEF_GRAN;
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSCOPY_MAX_INPUTS);
- memset(r->f_outputs,0,sizeof(MSFifo*)*MSCOPY_MAX_INPUTS);
-}
-
-void ms_copy_class_init(MSCopyClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"fifocopier");
- MS_FILTER_CLASS(klass)->max_finputs=MSCOPY_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_foutputs=MSCOPY_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=MSCOPY_DEF_GRAN;
- MS_FILTER_CLASS(klass)->w_maxgran=MSCOPY_DEF_GRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_copy_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_copy_process;
-}
-
-void ms_copy_process(MSCopy *r)
-{
- MSFifo *fi,*fo;
- int err1;
- gint gran=MS_FILTER(r)->klass->r_maxgran;
- void *s,*d;
-
- /* process output fifos, but there is only one for this class of filter*/
-
- fi=r->f_inputs[0];
- fo=r->f_outputs[0];
- if (fi!=NULL)
- {
- err1=ms_fifo_get_read_ptr(fi,gran,&s);
- if (err1>0) err1=ms_fifo_get_write_ptr(fo,gran,&d);
- if (err1>0)
- {
- memcpy(d,s,gran);
- }
- }
-}
-
-void ms_copy_destroy( MSCopy *obj)
-{
- g_free(obj);
-}
diff --git a/talk/third_party/mediastreamer/mscopy.h b/talk/third_party/mediastreamer/mscopy.h
deleted file mode 100755
index 2b5749b..0000000
--- a/talk/third_party/mediastreamer/mscopy.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSCOPY_H
-#define MSCOPY_H
-
-#include "msfilter.h"
-
-
-/*this is the class that implements a copy filter*/
-
-#define MSCOPY_MAX_INPUTS 1 /* max output per filter*/
-
-#define MSCOPY_DEF_GRAN 64 /* the default granularity*/
-
-typedef struct _MSCopy
-{
- /* the MSCopy derivates from MSFilter, so the MSFilter object MUST be the first of the MSCopy object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSCOPY_MAX_INPUTS];
- MSFifo *f_outputs[MSCOPY_MAX_INPUTS];
-} MSCopy;
-
-typedef struct _MSCopyClass
-{
- /* the MSCopy derivates from MSFilter, so the MSFilter class MUST be the first of the MSCopy class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSCopyClass;
-
-/* PUBLIC */
-#define MS_COPY(filter) ((MSCopy*)(filter))
-#define MS_COPY_CLASS(klass) ((MSCopyClass*)(klass))
-MSFilter * ms_copy_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_copy_init(MSCopy *r);
-void ms_copy_class_init(MSCopyClass *klass);
-void ms_copy_destroy( MSCopy *obj);
-void ms_copy_process(MSCopy *r);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msfdispatcher.c b/talk/third_party/mediastreamer/msfdispatcher.c
deleted file mode 100755
index 692bbb7..0000000
--- a/talk/third_party/mediastreamer/msfdispatcher.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a dispatcher of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "msfdispatcher.h"
-
-static MSFdispatcherClass *ms_fdispatcher_class=NULL;
-
-MSFilter * ms_fdispatcher_new(void)
-{
- MSFdispatcher *obj;
- obj=g_malloc(sizeof(MSFdispatcher));
- if (ms_fdispatcher_class==NULL){
- ms_fdispatcher_class=g_malloc(sizeof(MSFdispatcherClass));
- ms_fdispatcher_class_init(ms_fdispatcher_class);
- }
- MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_fdispatcher_class);
- ms_fdispatcher_init(obj);
- return MS_FILTER(obj);
-}
-
-
-void ms_fdispatcher_init(MSFdispatcher *obj)
-{
- ms_filter_init(MS_FILTER(obj));
- MS_FILTER(obj)->infifos=obj->f_inputs;
- MS_FILTER(obj)->outfifos=obj->f_outputs;
- MS_FILTER(obj)->r_mingran=MS_FDISPATCHER_DEF_GRAN;
- memset(obj->f_inputs,0,sizeof(MSFifo*)*MS_FDISPATCHER_MAX_INPUTS);
- memset(obj->f_outputs,0,sizeof(MSFifo*)*MS_FDISPATCHER_MAX_OUTPUTS);
-}
-
-
-
-void ms_fdispatcher_class_init(MSFdispatcherClass *klass)
-{
- MSFilterClass *parent_class=MS_FILTER_CLASS(klass);
- ms_filter_class_init(parent_class);
- ms_filter_class_set_name(parent_class,"fdispatcher");
- parent_class->max_finputs=MS_FDISPATCHER_MAX_INPUTS;
- parent_class->max_foutputs=MS_FDISPATCHER_MAX_OUTPUTS;
- parent_class->r_maxgran=MS_FDISPATCHER_DEF_GRAN;
- parent_class->w_maxgran=MS_FDISPATCHER_DEF_GRAN;
- parent_class->destroy=(MSFilterDestroyFunc)ms_fdispatcher_destroy;
- parent_class->process=(MSFilterProcessFunc)ms_fdispatcher_process;
-}
-
-
-void ms_fdispatcher_destroy( MSFdispatcher *obj)
-{
- g_free(obj);
-}
-
-void ms_fdispatcher_process(MSFdispatcher *obj)
-{
- gint i;
- MSFifo *inf=obj->f_inputs[0];
-
-
- if (inf!=NULL){
- void *s,*d;
- /* dispatch fifos */
- while ( ms_fifo_get_read_ptr(inf,MS_FDISPATCHER_DEF_GRAN,&s) >0 ){
- for (i=0;i<MS_FDISPATCHER_MAX_OUTPUTS;i++){
- MSFifo *outf=obj->f_outputs[i];
-
- if (outf!=NULL)
- {
- ms_fifo_get_write_ptr(outf,MS_FDISPATCHER_DEF_GRAN,&d);
- if (d!=NULL) memcpy(d,s,MS_FDISPATCHER_DEF_GRAN);
- }
- }
- }
- }
-}
-
-
diff --git a/talk/third_party/mediastreamer/msfdispatcher.h b/talk/third_party/mediastreamer/msfdispatcher.h
deleted file mode 100755
index b1b457d..0000000
--- a/talk/third_party/mediastreamer/msfdispatcher.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a dispatcher of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSFDISPATCHER_H
-#define MSFDISPATCHER_H
-
-#include "msfilter.h"
-
-
-/*this is the class that implements a fdispatcher filter*/
-
-#define MS_FDISPATCHER_MAX_INPUTS 1
-#define MS_FDISPATCHER_MAX_OUTPUTS 5
-#define MS_FDISPATCHER_DEF_GRAN 64 /* the default granularity*/
-
-typedef struct _MSFdispatcher
-{
- /* the MSFdispatcher derivates from MSFilter, so the MSFilter object MUST be the first of the MSFdispatcher object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MS_FDISPATCHER_MAX_INPUTS];
- MSFifo *f_outputs[MS_FDISPATCHER_MAX_OUTPUTS];
-} MSFdispatcher;
-
-typedef struct _MSFdispatcherClass
-{
- /* the MSFdispatcher derivates from MSFilter, so the MSFilter class MUST be the first of the MSFdispatcher class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSFdispatcherClass;
-
-/* PUBLIC */
-#define MS_FDISPATCHER(filter) ((MSFdispatcher*)(filter))
-#define MS_FDISPATCHER_CLASS(klass) ((MSFdispatcherClass*)(klass))
-MSFilter * ms_fdispatcher_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_fdispatcher_init(MSFdispatcher *r);
-void ms_fdispatcher_class_init(MSFdispatcherClass *klass);
-void ms_fdispatcher_destroy( MSFdispatcher *obj);
-void ms_fdispatcher_process(MSFdispatcher *r);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msfifo.c b/talk/third_party/mediastreamer/msfifo.c
deleted file mode 100755
index 9897e08..0000000
--- a/talk/third_party/mediastreamer/msfifo.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <errno.h>
-#include <string.h>
-#include "msutils.h"
-#include "msfifo.h"
-
-MSFifo * ms_fifo_new(MSBuffer *buf, gint r_gran, gint w_gran, gint r_offset, gint w_offset)
-{
- MSFifo *fifo;
- gint saved_offset=MAX(r_gran+r_offset,w_offset);
-
- g_return_val_if_fail(saved_offset<=(buf->size),NULL);
- fifo=g_malloc(sizeof(MSFifo));
- fifo->buffer=buf;
- fifo->r_gran=r_gran;
- fifo->w_gran=w_gran;
- fifo->begin=fifo->wr_ptr=fifo->rd_ptr=buf->buffer+saved_offset;
- fifo->readsize=0;
- fifo->size=fifo->writesize=buf->size-saved_offset;
- fifo->saved_offset= saved_offset;
- fifo->r_end=fifo->w_end=buf->buffer+buf->size;
- fifo->pre_end=fifo->w_end-saved_offset;
- buf->ref_count++;
- fifo->prev_data=NULL;
- fifo->next_data=NULL;
- ms_trace("fifo base=%x, begin=%x, end=%x, saved_offset=%i, size=%i"
- ,fifo->buffer->buffer,fifo->begin,fifo->w_end,fifo->saved_offset,fifo->size);
- return(fifo);
-}
-
-MSFifo * ms_fifo_new_with_buffer(gint r_gran, gint w_gran, gint r_offset, gint w_offset,
- gint min_fifo_size)
-{
- MSFifo *fifo;
- MSBuffer *buf;
- gint saved_offset=MAX(r_gran+r_offset,w_offset);
- gint fifo_size;
- gint tmp;
- if (min_fifo_size==0) min_fifo_size=w_gran;
-
- /* we must allocate a fifo with a size multiple of min_fifo_size,
- with a saved_offset */
- if (min_fifo_size>MS_BUFFER_LARGE)
- fifo_size=(min_fifo_size) + saved_offset;
- else fifo_size=(6*min_fifo_size) + saved_offset;
- buf=ms_buffer_new(fifo_size);
- fifo=ms_fifo_new(buf,r_gran,w_gran,r_offset,w_offset);
- ms_trace("fifo_size=%i",fifo_size);
- return(fifo);
-}
-
-void ms_fifo_destroy( MSFifo *fifo)
-{
- g_free(fifo);
-}
-
-void ms_fifo_destroy_with_buffer(MSFifo *fifo)
-{
- ms_buffer_destroy(fifo->buffer);
- ms_fifo_destroy(fifo);
-}
-
-gint ms_fifo_get_read_ptr(MSFifo *fifo, gint bsize, void **ret_ptr)
-{
- gchar *rnext;
-
- *ret_ptr=NULL;
- //ms_trace("ms_fifo_get_read_ptr: entering.");
- g_return_val_if_fail(bsize<=fifo->r_gran,-EINVAL);
-
- if (bsize>fifo->readsize)
- {
- ms_trace("Not enough data: bsize=%i, readsize=%i",bsize,fifo->readsize);
- return (-ENODATA);
- }
-
- rnext=fifo->rd_ptr+bsize;
- if (rnext<=fifo->r_end){
-
- *ret_ptr=fifo->rd_ptr;
- fifo->rd_ptr=rnext;
- }else{
- int unread=fifo->r_end-fifo->rd_ptr;
- *ret_ptr=fifo->begin-unread;
- memcpy(fifo->buffer->buffer,fifo->r_end-fifo->saved_offset,fifo->saved_offset);
- fifo->rd_ptr=(char*)(*ret_ptr) + bsize;
- fifo->r_end=fifo->w_end; /* this is important ! */
- ms_trace("moving read ptr to %x",fifo->rd_ptr);
-
- }
- /* update write size*/
- fifo->writesize+=bsize;
- fifo->readsize-=bsize;
- return bsize;
-}
-
-
-void ms_fifo_update_write_ptr(MSFifo *fifo, gint written){
- gint reserved=fifo->wr_ptr-fifo->prev_wr_ptr;
- gint unwritten;
- g_return_if_fail(reserved>=0);
- unwritten=reserved-written;
- g_return_if_fail(unwritten>=0);
- /* fix readsize and writesize */
- fifo->readsize-=unwritten;
- fifo->writesize+=unwritten;
- fifo->wr_ptr+=written;
-}
-
-gint ms_fifo_get_write_ptr(MSFifo *fifo, gint bsize, void **ret_ptr)
-{
- gchar *wnext;
-
- *ret_ptr=NULL;
- //ms_trace("ms_fifo_get_write_ptr: Entering.");
- g_return_val_if_fail(bsize<=fifo->w_gran,-EINVAL);
- if (bsize>fifo->writesize)
- {
- ms_trace("Not enough space: bsize=%i, writesize=%i",bsize,fifo->writesize);
- *ret_ptr=NULL;
- return(-ENODATA);
- }
- wnext=fifo->wr_ptr+bsize;
- if (wnext<=fifo->w_end){
- *ret_ptr=fifo->wr_ptr;
- fifo->wr_ptr=wnext;
- }else{
- *ret_ptr=fifo->begin;
- fifo->r_end=fifo->wr_ptr;
- fifo->wr_ptr=fifo->begin+bsize;
- ms_trace("moving write ptr to %x",fifo->wr_ptr);
- }
- fifo->prev_wr_ptr=*ret_ptr;
- /* update readsize*/
- fifo->readsize+=bsize;
- fifo->writesize-=bsize;
- //ms_trace("ms_fifo_get_write_ptr: readsize=%i, writesize=%i",fifo->readsize,fifo->writesize);
- return bsize;
-}
-
-gint ms_fifo_get_rw_ptr(MSFifo *f1,void **p1,gint minsize1,
- MSFifo *f2,void **p2,gint minsize2)
-{
- gint rbsize,wbsize;
-
- rbsize=MIN(f1->readsize,(f1->pre_end-f1->rd_ptr));
- wbsize=MIN(f2->writesize,(f2->w_end-f2->wr_ptr));
- return 0;
-}
diff --git a/talk/third_party/mediastreamer/msfifo.h b/talk/third_party/mediastreamer/msfifo.h
deleted file mode 100755
index fde1bec..0000000
--- a/talk/third_party/mediastreamer/msfifo.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#else
-#include "glist.h"
-#endif
-#include "msbuffer.h"
-
-typedef struct _MSFifo
-{
- gint r_gran; /*maximum granularity for reading*/
- gint w_gran; /*maximum granularity for writing*/
- gchar * rd_ptr; /* read pointer on the position where there is something to read on the MSBuffer */
- guint32 readsize;
- gchar * wr_ptr;
- gchar * prev_wr_ptr;
- guint32 writesize; /* write pointer on the position where it is possible to write on the MSBuffer */
- gchar * begin; /* rd_ptr et wr_ptr must all be >=begin*/
- guint32 size; /* the length of the fifo, but this may not be equal to buffer->size*/
- guint32 saved_offset;
- gchar * pre_end; /* the end of the buffer that is copied at the begginning when we wrap around*/
- gchar * w_end; /* when a wr ptr is expected to exceed end_offset,
- it must be wrapped around to go at the beginning of the buffer. This is the end of the buffer*/
- gchar * r_end; /* this is the last position written at the end of the fifo. If a read ptr is expected to
- exceed this pointer, it must be put at the begginning of the buffer */
- void *prev_data; /*user data, usually the writing MSFilter*/
- void *next_data; /* user data, usually the reading MSFilter */
- MSBuffer *buffer;
-} MSFifo;
-
-/* constructor*/
-/* r_gran: max granularity for reading (in number of bytes)*/
-/* w_gran: max granularity for writing (in number of bytes)*/
-/* r_offset: number of bytes that are kept available behind read pointer (for recursive filters)*/
-/* w_offset: number of bytes that are kept available behind write pointer (for recursive filters)*/
-/* buf is a MSBuffer that should be compatible with the above parameter*/
-MSFifo * ms_fifo_new(MSBuffer *buf, gint r_gran, gint w_gran, gint r_offset, gint w_offset);
-
-/*does the same that ms_fifo_new(), but also allocate a compatible buffer automatically*/
-MSFifo * ms_fifo_new_with_buffer(gint r_gran, gint w_gran, gint r_offset, gint w_offset, gint min_buffer_size);
-
-void ms_fifo_destroy( MSFifo *fifo);
-
-void ms_fifo_destroy_with_buffer(MSFifo *fifo);
-
-/* get data to read */
-gint ms_fifo_get_read_ptr(MSFifo *fifo, gint bsize, void **ret_ptr);
-
-/* get a buffer to write*/
-gint ms_fifo_get_write_ptr(MSFifo *fifo, gint bsize, void **ret_ptr);
-
-/* in case the buffer got by ms_fifo_get_write_ptr() could not be filled completely, you must
-tell it by using this function */
-void ms_fifo_update_write_ptr(MSFifo *fifo, gint written);
diff --git a/talk/third_party/mediastreamer/msfilter.c b/talk/third_party/mediastreamer/msfilter.c
deleted file mode 100755
index c67e9f0..0000000
--- a/talk/third_party/mediastreamer/msfilter.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include <errno.h>
-#include "msfilter.h"
-
-
-
-void ms_filter_init(MSFilter *filter)
-{
- filter->finputs=0;
- filter->foutputs=0;
- filter->qinputs=0;
- filter->qoutputs=0;
- filter->infifos=NULL;
- filter->outfifos=NULL;
- filter->inqueues=NULL;
- filter->outqueues=NULL;
- filter->lock=g_mutex_new();
- filter->min_fifo_size=0x7fff;
- filter->notify_event=NULL;
- filter->userdata=NULL;
-}
-
-void ms_filter_uninit(MSFilter *filter)
-{
- g_mutex_free(filter->lock);
-}
-
-void ms_filter_class_init(MSFilterClass *filterclass)
-{
- filterclass->name=NULL;
- filterclass->max_finputs=0;
- filterclass->max_foutputs=0;
- filterclass->max_qinputs=0;
- filterclass->max_qoutputs=0;
- filterclass->r_maxgran=0;
- filterclass->w_maxgran=0;
- filterclass->r_offset=0;
- filterclass->w_offset=0;
- filterclass->set_property=NULL;
- filterclass->get_property=NULL;
- filterclass->setup=NULL;
- filterclass->unsetup=NULL;
- filterclass->process=NULL;
- filterclass->destroy=NULL;
- filterclass->attributes=0;
- filterclass->ref_count=0;
-}
-
-/* find output queue */
-gint find_oq(MSFilter *m1,MSQueue *oq)
-{
- gint i;
-
- for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_qoutputs;i++){
- if (m1->outqueues[i]==oq) return i;
- }
-
- return -1;
-}
-
-/* find input queue */
-gint find_iq(MSFilter *m1,MSQueue *iq)
-{
- gint i;
- for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_qinputs;i++){
- if (m1->inqueues[i]==iq) return i;
- }
- return -1;
-}
-
-/* find output fifo */
-gint find_of(MSFilter *m1,MSFifo *of)
-{
- gint i;
- for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_foutputs;i++){
- if (m1->outfifos[i]==of) return i;
- }
-
- return -1;
-}
-
-/* find input fifo */
-gint find_if(MSFilter *m1,MSFifo *inf)
-{
- gint i;
-
- for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_finputs;i++){
- if (m1->infifos[i]==inf) return i;
- }
-
- return -1;
-}
-
-#define find_free_iq(_m1) find_iq(_m1,NULL)
-#define find_free_oq(_m1) find_oq(_m1,NULL)
-#define find_free_if(_m1) find_if(_m1,NULL)
-#define find_free_of(_m1) find_of(_m1,NULL)
-
-int ms_filter_add_link(MSFilter *m1, MSFilter *m2)
-{
- gint m1_q=-1;
- gint m1_f=-1;
- gint m2_q=-1;
- gint m2_f=-1;
- /* determine the type of link we can add */
- m1_q=find_free_oq(m1);
- m1_f=find_free_of(m1);
- m2_q=find_free_iq(m2);
- m2_f=find_free_if(m2);
- if ((m1_q!=-1) && (m2_q!=-1)){
- /* link with queues */
- ms_trace("m1_q=%i , m2_q=%i",m1_q,m2_q);
- return ms_filter_link(m1,m1_q,m2,m2_q,LINK_QUEUE);
- }
- if ((m1_f!=-1) && (m2_f!=-1)){
- /* link with queues */
- ms_trace("m1_f=%i , m2_f=%i",m1_f,m2_f);
- return ms_filter_link(m1,m1_f,m2,m2_f,LINK_FIFO);
- }
- g_warning("ms_filter_add_link: could not link.");
- return -1;
-}
-/**
- * ms_filter_link:
- * @m1: A #MSFilter object.
- * @pin1: The pin number on @m1.
- * @m2: A #MSFilter object.
- * @pin2: The pin number on @m2.
- * @linktype: Type of connection, it may be #LINK_QUEUE, #LINK_FIFOS.
- *
- * This function links two MSFilter object between them. It must be used to make chains of filters.
- * All data outgoing from pin1 of m1 will go to the input pin2 of m2.
- * The way to communicate can be fifos or queues, depending of the nature of the filters. Filters can have
- * multiple queue pins and multiple fifo pins, but most of them have only one queue input/output or only one
- * fifo input/output. Fifos are usally used by filters doing audio processing, while queues are used by filters doing
- * video processing.
- *
- * Returns: 0 if successfull, a negative value reprensenting the errno.h error.
- */
-int ms_filter_link(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2, int linktype)
-{
- MSQueue *q;
- MSFifo *fifo;
-
- g_message("ms_filter_add_link: %s,%i -> %s,%i",m1->klass->name,pin1,m2->klass->name,pin2);
- switch(linktype)
- {
- case LINK_QUEUE:
- /* Are filter m1 and m2 able to accept more queues connections ?*/
- g_return_val_if_fail(m1->qoutputs<MS_FILTER_GET_CLASS(m1)->max_qoutputs,-EMLINK);
- g_return_val_if_fail(m2->qinputs<MS_FILTER_GET_CLASS(m2)->max_qinputs,-EMLINK);
- /* Are filter m1 and m2 valid with their inputs and outputs ?*/
- g_return_val_if_fail(m1->outqueues!=NULL,-EFAULT);
- g_return_val_if_fail(m2->inqueues!=NULL,-EFAULT);
- /* are the requested pins exists ?*/
- g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_qoutputs,-EINVAL);
- g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_qinputs,-EINVAL);
- /* are the requested pins free ?*/
- g_return_val_if_fail(m1->outqueues[pin1]==NULL,-EBUSY);
- g_return_val_if_fail(m2->inqueues[pin2]==NULL,-EBUSY);
-
- q=ms_queue_new();
- m1->outqueues[pin1]=m2->inqueues[pin2]=q;
- m1->qoutputs++;
- m2->qinputs++;
- q->prev_data=(void*)m1;
- q->next_data=(void*)m2;
- break;
- case LINK_FIFO:
- /* Are filter m1 and m2 able to accept more fifo connections ?*/
- g_return_val_if_fail(m1->foutputs<MS_FILTER_GET_CLASS(m1)->max_foutputs,-EMLINK);
- g_return_val_if_fail(m2->finputs<MS_FILTER_GET_CLASS(m2)->max_finputs,-EMLINK);
- /* Are filter m1 and m2 valid with their inputs and outputs ?*/
- g_return_val_if_fail(m1->outfifos!=NULL,-EFAULT);
- g_return_val_if_fail(m2->infifos!=NULL,-EFAULT);
- /* are the requested pins exists ?*/
- g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_foutputs,-EINVAL);
- g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_finputs,-EINVAL);
- /* are the requested pins free ?*/
- g_return_val_if_fail(m1->outfifos[pin1]==NULL,-EBUSY);
- g_return_val_if_fail(m2->infifos[pin2]==NULL,-EBUSY);
-
- if (MS_FILTER_GET_CLASS(m1)->attributes & FILTER_IS_SOURCE)
- {
- /* configure min_fifo_size */
- fifo=ms_fifo_new_with_buffer(MS_FILTER_GET_CLASS(m2)->r_maxgran,
- MS_FILTER_GET_CLASS(m1)->w_maxgran,
- MS_FILTER_GET_CLASS(m2)->r_offset,
- MS_FILTER_GET_CLASS(m1)->w_offset,
- MS_FILTER_GET_CLASS(m1)->w_maxgran);
- m2->min_fifo_size=MS_FILTER_GET_CLASS(m1)->w_maxgran;
- }
- else
- {
- gint next_size;
- ms_trace("ms_filter_add_link: min_fifo_size=%i",m1->min_fifo_size);
- fifo=ms_fifo_new_with_buffer(MS_FILTER_GET_CLASS(m2)->r_maxgran,
- MS_FILTER_GET_CLASS(m1)->w_maxgran,
- MS_FILTER_GET_CLASS(m2)->r_offset,
- MS_FILTER_GET_CLASS(m1)->w_offset,
- m1->min_fifo_size);
- if (MS_FILTER_GET_CLASS(m2)->r_maxgran>0){
- next_size=(m1->min_fifo_size*
- (MS_FILTER_GET_CLASS(m2)->w_maxgran)) /
- (MS_FILTER_GET_CLASS(m2)->r_maxgran);
- }else next_size=m1->min_fifo_size;
- ms_trace("ms_filter_add_link: next_size=%i",next_size);
- m2->min_fifo_size=next_size;
- }
-
-
- m1->outfifos[pin1]=m2->infifos[pin2]=fifo;
- m1->foutputs++;
- m2->finputs++;
- fifo->prev_data=(void*)m1;
- fifo->next_data=(void*)m2;
- break;
- }
- return 0;
-}
-/**
- * ms_filter_unlink:
- * @m1: A #MSFilter object.
- * @pin1: The pin number on @m1.
- * @m2: A #MSFilter object.
- * @pin2: The pin number on @m2.
- * @linktype: Type of connection, it may be #LINK_QUEUE, #LINK_FIFOS.
- *
- * Unlink @pin1 of filter @m1 from @pin2 of filter @m2. @linktype specifies what type of connection is removed.
- *
- * Returns: 0 if successfull, a negative value reprensenting the errno.h error.
- */
-int ms_filter_unlink(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2,gint linktype)
-{
- switch(linktype)
- {
- case LINK_QUEUE:
- /* Are filter m1 and m2 valid with their inputs and outputs ?*/
- g_return_val_if_fail(m1->outqueues!=NULL,-EFAULT);
- g_return_val_if_fail(m2->inqueues!=NULL,-EFAULT);
- /* are the requested pins exists ?*/
- g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_qoutputs,-EINVAL);
- g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_qinputs,-EINVAL);
- /* are the requested pins busy ?*/
- g_return_val_if_fail(m1->outqueues[pin1]!=NULL,-ENOENT);
- g_return_val_if_fail(m2->inqueues[pin2]!=NULL,-ENOENT);
- /* are the two pins connected together ?*/
- g_return_val_if_fail(m1->outqueues[pin1]==m2->inqueues[pin2],-EINVAL);
-
- ms_queue_destroy(m1->outqueues[pin1]);
- m1->outqueues[pin1]=m2->inqueues[pin2]=NULL;
- m1->qoutputs--;
- m2->qinputs--;
-
- break;
- case LINK_FIFO:
- /* Are filter m1 and m2 valid with their inputs and outputs ?*/
- g_return_val_if_fail(m1->outfifos!=NULL,-EFAULT);
- g_return_val_if_fail(m2->infifos!=NULL,-EFAULT);
- /* are the requested pins exists ?*/
- g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_foutputs,-EINVAL);
- g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_finputs,-EINVAL);
- /* are the requested pins busy ?*/
- g_return_val_if_fail(m1->outfifos[pin1]!=NULL,-ENOENT);
- g_return_val_if_fail(m2->infifos[pin2]!=NULL,-ENOENT);
- /* are the two pins connected together ?*/
- g_return_val_if_fail(m1->outfifos[pin1]==m2->infifos[pin2],-EINVAL);
- ms_fifo_destroy_with_buffer(m1->outfifos[pin1]);
- m1->outfifos[pin1]=m2->infifos[pin2]=NULL;
- m1->foutputs--;
- m2->finputs--;
- break;
- }
- return 0;
-}
-
-/**
- *ms_filter_remove_links:
- *@m1: a filter
- *@m2: another filter.
- *
- * Removes all links between m1 and m2.
- *
- *Returns: 0 if one more link have been removed, -1 if not.
-**/
-gint ms_filter_remove_links(MSFilter *m1, MSFilter *m2)
-{
- int i,j;
- int removed=-1;
- MSQueue *qo;
- MSFifo *fo;
- /* takes all outputs of m1, and removes the one that goes to m2 */
- if (m1->outqueues!=NULL){
- for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_qoutputs;i++)
- {
- qo=m1->outqueues[i];
- if (qo!=NULL){
- MSFilter *rmf;
- /* test if the queue connects to m2 */
- rmf=(MSFilter*)qo->next_data;
- if (rmf==m2){
- j=find_iq(rmf,qo);
- if (j==-1) g_error("Could not find input queue: impossible case.");
- ms_filter_unlink(m1,i,m2,j,LINK_QUEUE);
- removed=0;
- }
- }
- }
- }
- if (m1->outfifos!=NULL){
- for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_foutputs;i++)
- {
- fo=m1->outfifos[i];
- if (fo!=NULL){
- MSFilter *rmf;
- /* test if the queue connects to m2 */
- rmf=(MSFilter*)fo->next_data;
- if (rmf==m2){
- j=find_if(rmf,fo);
- if (j==-1) g_error("Could not find input fifo: impossible case.");
- ms_filter_unlink(m1,i,m2,j,LINK_FIFO);
- removed=0;
- }
- }
- }
- }
- return removed;
-}
-
-/**
- * ms_filter_fifos_have_data:
- * @f: a #MSFilter object.
- *
- * Tells if the filter has enough data in its input fifos in order to be executed succesfully.
- *
- * Returns: 1 if it can be executed, 0 else.
- */
-gint ms_filter_fifos_have_data(MSFilter *f)
-{
- gint i,j;
- gint max_inputs=f->klass->max_finputs;
- gint con_inputs=f->finputs;
- MSFifo *fifo;
- /* test fifos */
- for(i=0,j=0; (i<max_inputs) && (j<con_inputs);i++)
- {
- fifo=f->infifos[i];
- if (fifo!=NULL)
- {
- j++;
- if (fifo->readsize==0) return 0;
- if (fifo->readsize>=f->r_mingran) return 1;
- }
- }
- return 0;
-}
-
-/**
- * ms_filter_queues_have_data:
- * @f: a #MSFilter object.
- *
- * Tells if the filter has enough data in its input queues in order to be executed succesfully.
- *
- * Returns: 1 if it can be executed, 0 else.
- */
-gint ms_filter_queues_have_data(MSFilter *f)
-{
- gint i,j;
- gint max_inputs=f->klass->max_qinputs;
- gint con_inputs=f->qinputs;
- MSQueue *q;
- /* test queues */
- for(i=0,j=0; (i<max_inputs) && (j<con_inputs);i++)
- {
- q=f->inqueues[i];
- if (q!=NULL)
- {
- j++;
- if (ms_queue_can_get(q)) return 1;
- }
- }
- return 0;
-}
-
-
-
-void ms_filter_destroy(MSFilter *f)
-{
- /* first check if the filter is disconnected from any others */
- g_return_if_fail(f->finputs==0);
- g_return_if_fail(f->foutputs==0);
- g_return_if_fail(f->qinputs==0);
- g_return_if_fail(f->qoutputs==0);
- f->klass->destroy(f);
-}
-
-GList *filter_list=NULL;
-
-void ms_filter_register(MSFilterInfo *info)
-{
- gpointer tmp;
- tmp=g_list_find(filter_list,info);
- if (tmp==NULL) filter_list=g_list_append(filter_list,(gpointer)info);
-}
-
-void ms_filter_unregister(MSFilterInfo *info)
-{
- filter_list=g_list_remove(filter_list,(gpointer)info);
-}
-
-static gint compare_names(gpointer info, gpointer name)
-{
- MSFilterInfo *i=(MSFilterInfo*) info;
- return (strcmp(i->name,name));
-}
-
-MSFilterInfo * ms_filter_get_by_name(const gchar *name)
-{
- GList *elem=g_list_find_custom(filter_list,
- (gpointer)name,(GCompareFunc)compare_names);
- if (elem!=NULL){
- return (MSFilterInfo*)elem->data;
- }
- return NULL;
-}
-
-
-
-MSFilter * ms_filter_new_with_name(const gchar *name)
-{
- MSFilterInfo *info=ms_filter_get_by_name(name);
- if (info!=NULL) return info->constructor();
- g_warning("ms_filter_new_with_name: no filter named %s found.",name);
- return NULL;
-}
-
-
-/* find the first codec in the left part of the stream */
-MSFilter * ms_filter_search_upstream_by_type(MSFilter *f,MSFilterType type)
-{
- MSFilter *tmp=f;
- MSFilterInfo *info;
-
- if ((tmp->infifos!=NULL) && (tmp->infifos[0]!=NULL)){
- tmp=(MSFilter*) tmp->infifos[0]->prev_data;
- while(1){
- info=MS_FILTER_GET_CLASS(tmp)->info;
- if (info!=NULL){
- if ( (info->type==type) ){
- return tmp;
- }
- }
- if ((tmp->infifos!=NULL) && (tmp->infifos[0]!=NULL))
- tmp=(MSFilter*) tmp->infifos[0]->prev_data;
- else break;
- }
- }
- tmp=f;
- if ((tmp->inqueues!=NULL) && (tmp->inqueues[0]!=NULL)){
- tmp=(MSFilter*) tmp->inqueues[0]->prev_data;
- while(1){
-
- info=MS_FILTER_GET_CLASS(tmp)->info;
- if (info!=NULL){
- if ( (info->type==type)){
- return tmp;
- }
- }else g_warning("ms_filter_search_upstream_by_type: filter %s has no info."
- ,MS_FILTER_GET_CLASS(tmp)->name);
- if ((tmp->inqueues!=NULL) && (tmp->inqueues[0]!=NULL))
- tmp=(MSFilter*) tmp->inqueues[0]->prev_data;
- else break;
- }
- }
- return NULL;
-}
-
-
-int ms_filter_set_property(MSFilter *f, MSFilterProperty prop,void *value)
-{
- if (f->klass->set_property!=NULL){
- return f->klass->set_property(f,prop,value);
- }
- return 0;
-}
-
-int ms_filter_get_property(MSFilter *f, MSFilterProperty prop,void *value)
-{
- if (f->klass->get_property!=NULL){
- return f->klass->get_property(f,prop,value);
- }
- return -1;
-}
-
-void ms_filter_set_notify_func(MSFilter* filter,MSFilterNotifyFunc func, gpointer userdata)
-{
- filter->notify_event=func;
- filter->userdata=userdata;
-}
-
-void ms_filter_notify_event(MSFilter *filter,gint event, gpointer arg)
-{
- if (filter->notify_event!=NULL){
- filter->notify_event(filter,event,arg,filter->userdata);
- }
-}
-
-void swap_buffer(gchar *buffer, gint len)
-{
- int i;
- gchar tmp;
- for (i=0;i<len;i+=2){
- tmp=buffer[i];
- buffer[i]=buffer[i+1];
- buffer[i+1]=tmp;
- }
-}
diff --git a/talk/third_party/mediastreamer/msfilter.h b/talk/third_party/mediastreamer/msfilter.h
deleted file mode 100755
index 71ec81a..0000000
--- a/talk/third_party/mediastreamer/msfilter.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSFILTER_H
-#define MSFILTER_H
-
-#include <config.h>
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#include <gmodule.h>
-#else
-#undef VERSION
-#undef PACKAGE
-#include <uglib.h>
-#endif
-
-#include <string.h>
-#include "msutils.h"
-#include "msfifo.h"
-#include "msqueue.h"
-
-struct _MSFilter;
-/*this is the abstract object and class for all filter types*/
-typedef gint (*MSFilterNotifyFunc)(struct _MSFilter*, gint event, gpointer arg, gpointer userdata);
-
-struct _MSFilter
-{
- struct _MSFilterClass *klass;
- GMutex *lock;
- guchar finputs; /* number of connected fifo inputs*/
- guchar foutputs; /* number of connected fifo outputs*/
- guchar qinputs; /* number of connected queue inputs*/
- guchar qoutputs; /* number of connected queue outputs*/
- gint min_fifo_size; /* set when linking*/
- gint r_mingran; /* read minimum granularity (for fifos).
- It can be zero so that the filter can accept any size of reading data*/
- MSFifo **infifos; /*pointer to a table of pointer to input fifos*/
- MSFifo **outfifos; /*pointer to a table of pointer to output fifos*/
- MSQueue **inqueues; /*pointer to a table of pointer to input queues*/
- MSQueue **outqueues; /*pointer to a table of pointer to output queues*/
- MSFilterNotifyFunc notify_event;
- gpointer userdata;
-};
-
-typedef struct _MSFilter MSFilter;
-
-typedef enum{
- MS_FILTER_PROPERTY_FREQ, /* value is int */
- MS_FILTER_PROPERTY_BITRATE, /*value is int */
- MS_FILTER_PROPERTY_CHANNELS,/*value is int */
- MS_FILTER_PROPERTY_FMTP /* value is string */
-}MSFilterProperty;
-
-#define MS_FILTER_PROPERTY_STRING_MAX_SIZE 256
-
-typedef MSFilter * (*MSFilterNewFunc)(void);
-typedef void (*MSFilterProcessFunc)(MSFilter *);
-typedef void (*MSFilterDestroyFunc)(MSFilter *);
-typedef int (*MSFilterPropertyFunc)(MSFilter *,int ,void*);
-typedef void (*MSFilterSetupFunc)(MSFilter *, void *); /*2nd arg is the sync */
-
-typedef struct _MSFilterClass
-{
- struct _MSFilterInfo *info; /*pointer to a filter_info */
- gchar *name;
- guchar max_finputs; /* maximum number of fifo inputs*/
- guchar max_foutputs; /* maximum number of fifo outputs*/
- guchar max_qinputs; /* maximum number of queue inputs*/
- guchar max_qoutputs; /* maximum number of queue outputs*/
- gint r_maxgran; /* read maximum granularity (for fifos)*/
- gint w_maxgran; /* write maximum granularity (for fifos)*/
- gint r_offset; /* size of kept samples behind read pointer (for fifos)*/
- gint w_offset; /* size of kept samples behind write pointer (for fifos)*/
- MSFilterPropertyFunc set_property;
- MSFilterPropertyFunc get_property;
- MSFilterSetupFunc setup; /* called when attaching to sync */
- void (*process)(MSFilter *filter);
- MSFilterSetupFunc unsetup; /* called when detaching from sync */
- void (*destroy)(MSFilter *filter);
- guint attributes;
-#define FILTER_HAS_FIFOS (0x0001)
-#define FILTER_HAS_QUEUES (0x0001<<1)
-#define FILTER_IS_SOURCE (0x0001<<2)
-#define FILTER_IS_SINK (0x0001<<3)
-#define FILTER_CAN_SYNC (0x0001<<4)
- guint ref_count; /*number of object using the class*/
-} MSFilterClass;
-
-
-
-#define MS_FILTER(obj) ((MSFilter*)obj)
-#define MS_FILTER_CLASS(klass) ((MSFilterClass*)klass)
-#define MS_FILTER_GET_CLASS(obj) ((MSFilterClass*)((MS_FILTER(obj)->klass)))
-
-void ms_filter_class_init(MSFilterClass *filterclass);
-void ms_filter_init(MSFilter *filter);
-
-#define ms_filter_class_set_attr(filter,flag) ((filter)->attributes|=(flag))
-#define ms_filter_class_unset_attr(filter,flag) ((filter)->attributes&=~(flag))
-
-#define ms_filter_class_set_name(__klass,__name) (__klass)->name=g_strdup((__name))
-#define ms_filter_class_set_info(_klass,_info) (_klass)->info=(_info)
-/* public*/
-
-#define ms_filter_process(filter) ((filter)->klass->process((filter)))
-
-#define ms_filter_lock(filter) g_mutex_lock((filter)->lock)
-#define ms_filter_unlock(filter) g_mutex_unlock((filter)->lock)
-/* low level connect functions */
-int ms_filter_link(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2, gint linktype);
-int ms_filter_unlink(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2,gint linktype);
-
-/* high level connect functions */
-int ms_filter_add_link(MSFilter *m1, MSFilter *m2);
-int ms_filter_remove_links(MSFilter *m1, MSFilter *m2);
-
-void ms_filter_set_notify_func(MSFilter* filter,MSFilterNotifyFunc func, gpointer userdata);
-void ms_filter_notify_event(MSFilter *filter,gint event, gpointer arg);
-
-int ms_filter_set_property(MSFilter *f,MSFilterProperty property, void *value);
-int ms_filter_get_property(MSFilter *f,MSFilterProperty property, void *value);
-
-
-gint ms_filter_fifos_have_data(MSFilter *f);
-gint ms_filter_queues_have_data(MSFilter *f);
-
-void ms_filter_uninit(MSFilter *obj);
-void ms_filter_destroy(MSFilter *f);
-
-#define ms_filter_get_mingran(f) ((f)->r_mingran)
-#define ms_filter_set_mingran(f,gran) ((f)->r_mingran=(gran))
-
-#define LINK_DEFAULT 0
-#define LINK_FIFO 1
-#define LINK_QUEUE 2
-
-
-#define MSFILTER_VERSION(a,b,c) (((a)<<2)|((b)<<1)|(c))
-
-enum _MSFilterType
-{
- MS_FILTER_DISK_IO,
- MS_FILTER_AUDIO_CODEC,
- MS_FILTER_VIDEO_CODEC,
- MS_FILTER_NET_IO,
- MS_FILTER_VIDEO_IO,
- MS_FILTER_AUDIO_IO,
- MS_FILTER_OTHER
-};
-
-typedef enum _MSFilterType MSFilterType;
-
-
-/* find the first codec in the left part of the stream */
-MSFilter * ms_filter_search_upstream_by_type(MSFilter *f,MSFilterType type);
-
-struct _MSFilterInfo
-{
- gchar *name;
- gint version;
- MSFilterType type;
- MSFilterNewFunc constructor;
- char *description; /*some textual information*/
-};
-
-typedef struct _MSFilterInfo MSFilterInfo;
-
-void ms_filter_register(MSFilterInfo *finfo);
-void ms_filter_unregister(MSFilterInfo *finfo);
-MSFilterInfo * ms_filter_get_by_name(const gchar *name);
-
-MSFilter * ms_filter_new_with_name(const gchar *name);
-
-
-
-extern GList *filter_list;
-#define MS_FILTER_INFO(obj) ((MSFilterInfo*)obj)
-
-void swap_buffer(gchar *buffer, gint len);
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msilbcdec.c b/talk/third_party/mediastreamer/msilbcdec.c
deleted file mode 100755
index b2dfff9..0000000
--- a/talk/third_party/mediastreamer/msilbcdec.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <config.h>
-
-#ifdef HAVE_ILBC
-
-
-#include "msilbcdec.h"
-#include "msilbcenc.h"
-#include "mscodec.h"
-#include <stdlib.h>
-#include <stdio.h>
-
-
-
-extern MSFilter * ms_ilbc_encoder_new(void);
-
-MSCodecInfo ilbc_info={
- {
- "iLBC codec",
- 0,
- MS_FILTER_AUDIO_CODEC,
- ms_ilbc_encoder_new,
- "A speech codec suitable for robust voice communication over IP"
- },
- ms_ilbc_encoder_new,
- ms_ilbc_decoder_new,
- 0, /* not applicable, 2 modes */
- 0, /* not applicable, 2 modes */
- 15200,
- 8000,
- 97,
- "iLBC",
- 1,
- 1,
-};
-
-
-void ms_ilbc_codec_init()
-{
- ms_filter_register(MS_FILTER_INFO(&ilbc_info));
-}
-
-
-
-static MSILBCDecoderClass *ms_ilbc_decoder_class=NULL;
-
-MSFilter * ms_ilbc_decoder_new(void)
-{
- MSILBCDecoder *r;
-
- r=g_new(MSILBCDecoder,1);
- ms_ilbc_decoder_init(r);
- if (ms_ilbc_decoder_class==NULL)
- {
- ms_ilbc_decoder_class=g_new(MSILBCDecoderClass,1);
- ms_ilbc_decoder_class_init(ms_ilbc_decoder_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ilbc_decoder_class);
- return(MS_FILTER(r));
-}
-
-
-int ms_ilbc_decoder_set_property(MSILBCDecoder *obj, MSFilterProperty prop, char *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FMTP:
- if (value == NULL) return 0;
- if (strstr(value,"ptime=20")!=NULL) obj->ms_per_frame=20;
- else if (strstr(value,"ptime=30")!=NULL) obj->ms_per_frame=30;
- else g_warning("Unrecognized fmtp parameter for ilbc encoder!");
- break;
- }
- return 0;
-}
-int ms_ilbc_decoder_get_property(MSILBCDecoder *obj, MSFilterProperty prop, char *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FMTP:
- if (obj->ms_per_frame==20) strncpy(value,"ptime=20",MS_FILTER_PROPERTY_STRING_MAX_SIZE);
- if (obj->ms_per_frame==30) strncpy(value,"ptime=30",MS_FILTER_PROPERTY_STRING_MAX_SIZE);
- break;
- }
- return 0;
-}
-
-void ms_ilbc_decoder_setup(MSILBCDecoder *r)
-{
- MSFilterClass *klass = NULL;
- switch (r->ms_per_frame) {
- case 20:
- r->samples_per_frame = BLOCKL_20MS;
- r->bytes_per_compressed_frame = NO_OF_BYTES_20MS;
- break;
- case 30:
- r->samples_per_frame = BLOCKL_30MS;
- r->bytes_per_compressed_frame = NO_OF_BYTES_30MS;
- break;
- default:
- g_error("ms_ilbc_decoder_setup: Bad value for ptime (%i)",r->ms_per_frame);
- }
- g_message("Using ilbc decoder with %i ms frames mode.",r->ms_per_frame);
- initDecode(&r->ilbc_dec, r->ms_per_frame /* ms frames */, /* user enhancer */ 0);
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_ilbc_decoder_init(MSILBCDecoder *r)
-{
- /* default bitrate */
- r->bitrate = 15200;
- r->ms_per_frame = 30;
- r->samples_per_frame = BLOCKL_20MS;
- r->bytes_per_compressed_frame = NO_OF_BYTES_20MS;
-
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->inqueues=r->q_inputs;
- MS_FILTER(r)->outfifos=r->f_outputs;
- memset(r->q_inputs,0,sizeof(MSFifo*)*MSILBCDECODER_MAX_INPUTS);
- memset(r->f_outputs,0,sizeof(MSFifo*)*MSILBCDECODER_MAX_INPUTS);
-}
-
-void ms_ilbc_decoder_class_init(MSILBCDecoderClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ILBCDec");
- MS_FILTER_CLASS(klass)->max_qinputs=MSILBCDECODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_foutputs=MSILBCDECODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->w_maxgran= ILBC_MAX_SAMPLES_PER_FRAME*2;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ilbc_decoder_destroy;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ilbc_decoder_set_property;
- MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ilbc_decoder_get_property;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ilbc_decoder_setup;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ilbc_decoder_process;
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ilbc_info;
-}
-
-void ms_ilbc_decoder_process(MSILBCDecoder *r)
-{
- MSFifo *fo;
- MSQueue *qi;
- int err1;
- void *dst=NULL;
- float speech[ILBC_MAX_SAMPLES_PER_FRAME];
- MSMessage *m;
-
- qi=r->q_inputs[0];
- fo=r->f_outputs[0];
- m=ms_queue_get(qi);
-
- ms_fifo_get_write_ptr(fo, r->samples_per_frame*2, &dst);
- if (dst!=NULL){
- if (m->data!=NULL){
- if (m->size<r->bytes_per_compressed_frame) {
- g_warning("Invalid ilbc frame ?");
- }
- iLBC_decode(speech, m->data, &r->ilbc_dec, /* mode */1);
- }else{
- iLBC_decode(speech,NULL, &r->ilbc_dec,0);
- }
- ilbc_write_16bit_samples((gint16*)dst, speech, r->samples_per_frame);
- }
- ms_message_destroy(m);
-}
-
-void ms_ilbc_decoder_uninit(MSILBCDecoder *obj)
-{
-}
-
-void ms_ilbc_decoder_destroy( MSILBCDecoder *obj)
-{
- ms_ilbc_decoder_uninit(obj);
- g_free(obj);
-}
-
-#endif
diff --git a/talk/third_party/mediastreamer/msilbcdec.h b/talk/third_party/mediastreamer/msilbcdec.h
deleted file mode 100755
index c219aab..0000000
--- a/talk/third_party/mediastreamer/msilbcdec.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSILBCDECODER_H
-#define MSILBCDECODER_H
-
-#include <msfilter.h>
-#include <mscodec.h>
-#include <iLBC_decode.h>
-
-/*this is the class that implements a ILBCdecoder filter*/
-
-#define MSILBCDECODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSILBCDecoder
-{
- /* the MSILBCDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSILBCDecoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSQueue *q_inputs[MSILBCDECODER_MAX_INPUTS];
- MSFifo *f_outputs[MSILBCDECODER_MAX_INPUTS];
- iLBC_Dec_Inst_t ilbc_dec;
- int bitrate;
- int ms_per_frame;
- int samples_per_frame;
- int bytes_per_compressed_frame;
-} MSILBCDecoder;
-
-typedef struct _MSILBCDecoderClass
-{
- /* the MSILBCDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSILBCDecoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSILBCDecoderClass;
-
-/* PUBLIC */
-
-/* call this before if don't load the plugin dynamically */
-void ms_ilbc_codec_init();
-
-#define MS_ILBCDECODER(filter) ((MSILBCDecoder*)(filter))
-#define MS_ILBCDECODER_CLASS(klass) ((MSILBCDecoderClass*)(klass))
-MSFilter * ms_ilbc_decoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_ilbc_decoder_init(MSILBCDecoder *r);
-void ms_ilbc_decoder_class_init(MSILBCDecoderClass *klass);
-void ms_ilbc_decoder_destroy( MSILBCDecoder *obj);
-void ms_ilbc_decoder_process(MSILBCDecoder *r);
-
-extern MSCodecInfo ilbc_info;
-
-#endif
diff --git a/talk/third_party/mediastreamer/msilbcenc.c b/talk/third_party/mediastreamer/msilbcenc.c
deleted file mode 100755
index 76d8b64..0000000
--- a/talk/third_party/mediastreamer/msilbcenc.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <config.h>
-
-#ifdef HAVE_ILBC
-
-#include <stdlib.h>
-#include <stdio.h>
-#include "msilbcenc.h"
-
-
-extern MSCodecInfo ilbc_info;
-
-/* The return value of each of these calls is the same as that
- returned by fread/fwrite, which should be the number of samples
- successfully read/written, not the number of bytes. */
-
-int
-ilbc_read_16bit_samples(gint16 int16samples[], float speech[], int n)
-{
- int i;
-
- /* Convert 16 bit integer samples to floating point values in the
- range [-1,+1]. */
-
- for (i = 0; i < n; i++) {
- speech[i] = int16samples[i];
- }
-
- return (n);
-}
-
-
-
-int
-ilbc_write_16bit_samples(gint16 int16samples[], float speech[], int n)
-{
- int i;
- float real_sample;
-
- /* Convert floating point samples in range [-1,+1] to 16 bit
- integers. */
- for (i = 0; i < n; i++) {
- float dtmp=speech[i];
- if (dtmp<MIN_SAMPLE)
- dtmp=MIN_SAMPLE;
- else if (dtmp>MAX_SAMPLE)
- dtmp=MAX_SAMPLE;
- int16samples[i] = (short) dtmp;
- }
- return (n);
-}
-
-/*
-
-Write the bits in bits[0] through bits[len-1] to file f, in "packed"
-format.
-
-bits is expected to be an array of len integer values, where each
-integer is 0 to represent a 0 bit, and any other value represents a 1
-bit. This bit string is written to the file f in the form of several
-8 bit characters. If len is not a multiple of 8, then the last
-character is padded with 0 bits -- the padding is in the least
-significant bits of the last byte. The 8 bit characters are "filled"
-in order from most significant bit to least significant.
-
-*/
-
-void
-ilbc_write_bits(unsigned char *data, unsigned char *bits, int nbytes)
-{
- memcpy(data, bits, nbytes);
-}
-
-
-
-/*
-
-Read bits from file f into bits[0] through bits[len-1], in "packed"
-format.
-
-*/
-
-int
-ilbc_read_bits(unsigned char *data, unsigned char *bits, int nbytes)
-{
-
- memcpy(bits, data, nbytes);
-
- return (nbytes);
-}
-
-
-
-
-static MSILBCEncoderClass *ms_ilbc_encoder_class=NULL;
-
-MSFilter * ms_ilbc_encoder_new(void)
-{
- MSILBCEncoder *r;
-
- r=g_new(MSILBCEncoder,1);
- ms_ilbc_encoder_init(r);
- if (ms_ilbc_encoder_class==NULL)
- {
- ms_ilbc_encoder_class=g_new(MSILBCEncoderClass,1);
- ms_ilbc_encoder_class_init(ms_ilbc_encoder_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ilbc_encoder_class);
- return(MS_FILTER(r));
-}
-
-
-int ms_ilbc_encoder_set_property(MSILBCEncoder *obj, MSFilterProperty prop, char *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FMTP:
- if (value == NULL) return 0;
- if (strstr(value,"ptime=20")!=NULL) obj->ms_per_frame=20;
- else if (strstr(value,"ptime=30")!=NULL) obj->ms_per_frame=30;
- else g_warning("Unrecognized fmtp parameter for ilbc encoder!");
- break;
- }
- return 0;
-}
-
-
-int ms_ilbc_encoder_get_property(MSILBCEncoder *obj, MSFilterProperty prop, char *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FMTP:
- if (obj->ms_per_frame==20) strncpy(value,"ptime=20",MS_FILTER_PROPERTY_STRING_MAX_SIZE);
- if (obj->ms_per_frame==30) strncpy(value,"ptime=30",MS_FILTER_PROPERTY_STRING_MAX_SIZE);
- break;
- }
- return 0;
-}
-
-void ms_ilbc_encoder_setup(MSILBCEncoder *r)
-{
- MSFilterClass *klass = NULL;
- switch (r->ms_per_frame) {
- case 20:
- r->samples_per_frame = BLOCKL_20MS;
- r->bytes_per_compressed_frame = NO_OF_BYTES_20MS;
- break;
- case 30:
- r->samples_per_frame = BLOCKL_30MS;
- r->bytes_per_compressed_frame = NO_OF_BYTES_30MS;
- break;
- default:
- g_error("Bad bitrate value (%i) for ilbc encoder!", r->ms_per_frame);
- break;
- }
- MS_FILTER(r)->r_mingran= (r->samples_per_frame * 2);
- g_message("Using ilbc encoder with %i ms frames mode.",r->ms_per_frame);
- initEncode(&r->ilbc_enc, r->ms_per_frame /* ms frames */);
-}
-
-/* FOR INTERNAL USE*/
-void ms_ilbc_encoder_init(MSILBCEncoder *r)
-{
- /* default bitrate */
- r->bitrate = 15200;
- r->ms_per_frame = 20;
- r->samples_per_frame = BLOCKL_20MS;
- r->bytes_per_compressed_frame = NO_OF_BYTES_20MS;
-
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->outqueues=r->q_outputs;
- MS_FILTER(r)->r_mingran= (r->samples_per_frame * 2);
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSILBCENCODER_MAX_INPUTS);
- memset(r->q_outputs,0,sizeof(MSFifo*)*MSILBCENCODER_MAX_INPUTS);
-}
-
-void ms_ilbc_encoder_class_init(MSILBCEncoderClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ILBCEnc");
- MS_FILTER_CLASS(klass)->max_finputs=MSILBCENCODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_qoutputs=MSILBCENCODER_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=ILBC_MAX_SAMPLES_PER_FRAME*2;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ilbc_encoder_set_property;
- MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ilbc_encoder_get_property;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ilbc_encoder_setup;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ilbc_encoder_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ilbc_encoder_process;
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ilbc_info;
-}
-
-void ms_ilbc_encoder_process(MSILBCEncoder *r)
-{
- MSFifo *fi;
- MSQueue *qo;
- MSMessage *m;
- void *src=NULL;
- float speech[ILBC_MAX_SAMPLES_PER_FRAME];
-
- /* process output fifos, but there is only one for this class of filter*/
-
- qo=r->q_outputs[0];
- fi=r->f_inputs[0];
- ms_fifo_get_read_ptr(fi,r->samples_per_frame*2,&src);
- if (src==NULL) {
- g_warning( "src=%p\n", src);
- return;
- }
- m=ms_message_new(r->bytes_per_compressed_frame);
-
- ilbc_read_16bit_samples((gint16*)src, speech, r->samples_per_frame);
- iLBC_encode((unsigned char *)m->data, speech, &r->ilbc_enc);
- ms_queue_put(qo,m);
-}
-
-void ms_ilbc_encoder_uninit(MSILBCEncoder *obj)
-{
-}
-
-void ms_ilbc_encoder_destroy( MSILBCEncoder *obj)
-{
- ms_ilbc_encoder_uninit(obj);
- g_free(obj);
-}
-
-#endif
diff --git a/talk/third_party/mediastreamer/msilbcenc.h b/talk/third_party/mediastreamer/msilbcenc.h
deleted file mode 100755
index bd8f3bf..0000000
--- a/talk/third_party/mediastreamer/msilbcenc.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSILBCENCODER_H
-#define MSILBCENCODER_H
-
-#include "mscodec.h"
-#include <iLBC_encode.h>
-
-#define ILBC_BITS_IN_COMPRESSED_FRAME 400
-
-int
-ilbc_read_16bit_samples(gint16 int16samples[], float speech[], int n);
-
-int
-ilbc_write_16bit_samples(gint16 int16samples[], float speech[], int n);
-
-void
-ilbc_write_bits(unsigned char *data, unsigned char *bits, int nbytes);
-
-int
-ilbc_read_bits(unsigned char *data, unsigned char *bits, int nbytes);
-
-
-/*this is the class that implements a ILBCencoder filter*/
-
-#define MSILBCENCODER_MAX_INPUTS 1 /* max output per filter*/
-
-
-typedef struct _MSILBCEncoder
-{
- /* the MSILBCEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSILBCEncoder object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSILBCENCODER_MAX_INPUTS];
- MSQueue *q_outputs[MSILBCENCODER_MAX_INPUTS];
- iLBC_Enc_Inst_t ilbc_enc;
- int ilbc_encoded_bytes;
- int bitrate;
- int ms_per_frame;
- int samples_per_frame;
- int bytes_per_compressed_frame;
-} MSILBCEncoder;
-
-typedef struct _MSILBCEncoderClass
-{
- /* the MSILBCEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSILBCEncoder class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSILBCEncoderClass;
-
-/* PUBLIC */
-#define MS_ILBCENCODER(filter) ((MSILBCEncoder*)(filter))
-#define MS_ILBCENCODER_CLASS(klass) ((MSILBCEncoderClass*)(klass))
-MSFilter * ms_ilbc_encoder_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_ilbc_encoder_init(MSILBCEncoder *r);
-void ms_ilbc_encoder_class_init(MSILBCEncoderClass *klass);
-void ms_ilbc_encoder_destroy( MSILBCEncoder *obj);
-void ms_ilbc_encoder_process(MSILBCEncoder *r);
-
-#define ILBC_MAX_BYTES_PER_COMPRESSED_FRAME NO_OF_BYTES_30MS
-#define ILBC_MAX_SAMPLES_PER_FRAME BLOCKL_30MS
-
-#endif
diff --git a/talk/third_party/mediastreamer/msnosync.c b/talk/third_party/mediastreamer/msnosync.c
deleted file mode 100755
index af5141c..0000000
--- a/talk/third_party/mediastreamer/msnosync.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "msnosync.h"
-
-static MSNoSyncClass *ms_nosync_class=NULL;
-
-void ms_nosync_init(MSNoSync *sync)
-{
- ms_sync_init(MS_SYNC(sync));
- MS_SYNC(sync)->attached_filters=sync->filters;
- memset(sync->filters,0,MSNOSYNC_MAX_FILTERS*sizeof(MSFilter*));
- MS_SYNC(sync)->samples_per_tick=160;
- sync->started=0;
-}
-
-void ms_nosync_class_init(MSNoSyncClass *klass)
-{
- ms_sync_class_init(MS_SYNC_CLASS(klass));
- MS_SYNC_CLASS(klass)->max_filters=MSNOSYNC_MAX_FILTERS;
- MS_SYNC_CLASS(klass)->synchronize=(MSSyncSyncFunc)ms_nosync_synchronize;
- MS_SYNC_CLASS(klass)->destroy=(MSSyncDestroyFunc)ms_nosync_destroy;
- /* no need to overload these function*/
- MS_SYNC_CLASS(klass)->attach=ms_sync_attach_generic;
- MS_SYNC_CLASS(klass)->detach=ms_sync_detach_generic;
-}
-
-void ms_nosync_destroy(MSNoSync *nosync)
-{
- g_free(nosync);
-}
-
-/* the synchronization function that does nothing*/
-void ms_nosync_synchronize(MSNoSync *nosync)
-{
- gint32 time;
- if (nosync->started==0){
- gettimeofday(&nosync->start,NULL);
- nosync->started=1;
- }
- gettimeofday(&nosync->current,NULL);
- MS_SYNC(nosync)->ticks++;
- /* update the time, we are supposed to work at 8000 Hz */
- time=((nosync->current.tv_sec-nosync->start.tv_sec)*1000) +
- ((nosync->current.tv_usec-nosync->start.tv_usec)/1000);
- MS_SYNC(nosync)->time=time;
- return;
-}
-
-
-MSSync *ms_nosync_new()
-{
- MSNoSync *nosync;
-
- nosync=g_malloc(sizeof(MSNoSync));
- ms_nosync_init(nosync);
- if (ms_nosync_class==NULL)
- {
- ms_nosync_class=g_new(MSNoSyncClass,1);
- ms_nosync_class_init(ms_nosync_class);
- }
- MS_SYNC(nosync)->klass=MS_SYNC_CLASS(ms_nosync_class);
- return(MS_SYNC(nosync));
-}
diff --git a/talk/third_party/mediastreamer/msnosync.h b/talk/third_party/mediastreamer/msnosync.h
deleted file mode 100755
index eef52d4..0000000
--- a/talk/third_party/mediastreamer/msnosync.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "mssync.h"
-
-#include <sys/time.h>
-#define MSNOSYNC_MAX_FILTERS 10
-
-/* MSNoSync derivates from MSSync base class*/
-
-typedef struct _MSNoSync
-{
- /* the MSSync must be the first field of the object in order to the object mechanism to work*/
- MSSync sync;
- MSFilter *filters[MSNOSYNC_MAX_FILTERS];
- int started;
- struct timeval start,current;
-} MSNoSync;
-
-
-typedef struct _MSNoSyncClass
-{
- /* the MSSyncClass must be the first field of the class in order to the class mechanism to work*/
- MSSyncClass parent_class;
-} MSNoSyncClass;
-
-
-/*private*/
-
-void ms_nosync_init(MSNoSync *sync);
-void ms_nosync_class_init(MSNoSyncClass *sync);
-
-void ms_nosync_destroy(MSNoSync *nosync);
-void ms_nosync_synchronize(MSNoSync *nosync);
-
-/*public*/
-
-/* casts a MSSync object into a MSNoSync */
-#define MS_NOSYNC(sync) ((MSNoSync*)(sync))
-/* casts a MSSync class into a MSNoSync class */
-#define MS_NOSYNC_CLASS(klass) ((MSNoSyncClass*)(klass))
-
-MSSync *ms_nosync_new();
diff --git a/talk/third_party/mediastreamer/msossread.c b/talk/third_party/mediastreamer/msossread.c
deleted file mode 100755
index 2e7b032..0000000
--- a/talk/third_party/mediastreamer/msossread.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "msossread.h"
-#include "mssync.h"
-#include <unistd.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-MSFilterInfo oss_read_info={
- "OSS read",
- 0,
- MS_FILTER_AUDIO_IO,
- ms_oss_read_new,
- NULL
-};
-
-static MSOssReadClass *msossreadclass=NULL;
-
-MSFilter * ms_oss_read_new()
-{
- MSOssRead *w;
-
- if (msossreadclass==NULL)
- {
- msossreadclass=g_new(MSOssReadClass,1);
- ms_oss_read_class_init( msossreadclass );
- }
-
- w=g_new(MSOssRead,1);
- MS_FILTER(w)->klass=MS_FILTER_CLASS(msossreadclass);
- ms_oss_read_init(w);
-
- return(MS_FILTER(w));
-}
-
-/* FOR INTERNAL USE*/
-void ms_oss_read_init(MSOssRead *w)
-{
- ms_sound_read_init(MS_SOUND_READ(w));
- MS_FILTER(w)->outfifos=w->f_outputs;
- MS_FILTER(w)->outfifos[0]=NULL;
- w->devid=0;
- w->sndcard=NULL;
- w->freq=8000;
-}
-
-gint ms_oss_read_set_property(MSOssRead *f,MSFilterProperty prop, void *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FREQ:
- f->freq=((gint*)value)[0];
- break;
- }
- return 0;
-}
-void ms_oss_read_class_init(MSOssReadClass *klass)
-{
- ms_sound_read_class_init(MS_SOUND_READ_CLASS(klass));
- MS_FILTER_CLASS(klass)->max_foutputs=1; /* one fifo output only */
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_oss_read_setup;
- MS_FILTER_CLASS(klass)->unsetup=(MSFilterSetupFunc)ms_oss_read_stop;
- MS_FILTER_CLASS(klass)->process= (MSFilterProcessFunc)ms_oss_read_process;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_oss_read_set_property;
- MS_FILTER_CLASS(klass)->destroy= (MSFilterDestroyFunc)ms_oss_read_destroy;
- MS_FILTER_CLASS(klass)->w_maxgran=MS_OSS_READ_MAX_GRAN;
- MS_FILTER_CLASS(klass)->info=&oss_read_info;
- MS_SOUND_READ_CLASS(klass)->set_device=(gint (*)(MSSoundRead*,gint))ms_oss_read_set_device;
- MS_SOUND_READ_CLASS(klass)->start=(void (*)(MSSoundRead*))ms_oss_read_start;
- MS_SOUND_READ_CLASS(klass)->stop=(void (*)(MSSoundRead*))ms_oss_read_stop;
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"OssRead");
- //ms_filter_class_set_attr( MS_FILTER_CLASS(klass),FILTER_CAN_SYNC|FILTER_IS_SOURCE);
-}
-
-void ms_oss_read_destroy( MSOssRead *obj)
-{
- g_free(obj);
-}
-
-void ms_oss_read_process(MSOssRead *f)
-{
- MSFifo *fifo;
- char *p;
- fifo=f->f_outputs[0];
-
- g_return_if_fail(f->sndcard!=NULL);
- g_return_if_fail(f->gran>0);
-
- if (snd_card_can_read(f->sndcard)){
- int got;
- ms_fifo_get_write_ptr(fifo,f->gran,(void**)&p);
- g_return_if_fail(p!=NULL);
- got=snd_card_read(f->sndcard,p,f->gran);
- if (got>=0 && got!=f->gran) ms_fifo_update_write_ptr(fifo,got);
- }
-}
-
-
-void ms_oss_read_start(MSOssRead *r)
-{
- g_return_if_fail(r->devid!=-1);
- r->sndcard=snd_card_manager_get_card(snd_card_manager,r->devid);
- g_return_if_fail(r->sndcard!=NULL);
- /* open the device for an audio telephony signal with minimum latency */
- snd_card_open_r(r->sndcard,16,0,r->freq);
- r->gran=(512*r->freq)/8000;
-
-}
-
-void ms_oss_read_stop(MSOssRead *w)
-{
- g_return_if_fail(w->devid!=-1);
- g_return_if_fail(w->sndcard!=NULL);
- snd_card_close_r(w->sndcard);
- w->sndcard=NULL;
-}
-
-
-void ms_oss_read_setup(MSOssRead *f, MSSync *sync)
-{
- f->sync=sync;
- ms_oss_read_start(f);
-}
-
-
-gint ms_oss_read_set_device(MSOssRead *r,gint devid)
-{
- r->devid=devid;
- return 0;
-}
diff --git a/talk/third_party/mediastreamer/msossread.h b/talk/third_party/mediastreamer/msossread.h
deleted file mode 100755
index 89d5a40..0000000
--- a/talk/third_party/mediastreamer/msossread.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#ifndef MSOSSREAD_H
-#define MSOSSREAD_H
-
-#include "mssoundread.h"
-#include "sndcard.h"
-#include "mssync.h"
-
-
-/*this is the class that implements oss writing sink filter*/
-
-#define MS_OSS_READ_MAX_INPUTS 1 /* max output per filter*/
-
-#define MS_OSS_READ_MAX_GRAN (512*2) /* the maximum granularity*/
-
-struct _MSOssRead
-{
- /* the MSOssRead derivates from MSSoundRead so the MSSoundRead object MUST be the first of the MSOssRead object
- in order to the object mechanism to work*/
- MSSoundRead filter;
- MSFifo *f_outputs[MS_OSS_READ_MAX_INPUTS];
- MSSync *sync;
- SndCard *sndcard;
- gint freq;
- gint devid; /* the sound device id it depends on*/
- gint gran;
- gint flags;
-#define START_REQUESTED 1
-#define STOP_REQUESTED 2
-};
-
-typedef struct _MSOssRead MSOssRead;
-
-struct _MSOssReadClass
-{
- /* the MSOssRead derivates from MSSoundRead, so the MSSoundRead class MUST be the first of the MSOssRead class
- in order to the class mechanism to work*/
- MSSoundReadClass parent_class;
-};
-
-typedef struct _MSOssReadClass MSOssReadClass;
-
-/* PUBLIC */
-#define MS_OSS_READ(filter) ((MSOssRead*)(filter))
-#define MS_OSS_READ_CLASS(klass) ((MSOssReadClass*)(klass))
-MSFilter * ms_oss_read_new(void);
-gint ms_oss_read_set_device(MSOssRead *w,gint devid);
-void ms_oss_read_start(MSOssRead *w);
-void ms_oss_read_stop(MSOssRead *w);
-
-/* FOR INTERNAL USE*/
-void ms_oss_read_init(MSOssRead *r);
-void ms_oss_read_class_init(MSOssReadClass *klass);
-void ms_oss_read_destroy( MSOssRead *obj);
-void ms_oss_read_process(MSOssRead *f);
-void ms_oss_read_setup(MSOssRead *f, MSSync *sync);
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msosswrite.c b/talk/third_party/mediastreamer/msosswrite.c
deleted file mode 100755
index 13a0dfe..0000000
--- a/talk/third_party/mediastreamer/msosswrite.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "msosswrite.h"
-#include "mssync.h"
-#include <unistd.h>
-#include <math.h>
-
-MSFilterInfo oss_write_info={
- "OSS write",
- 0,
- MS_FILTER_OTHER,
- ms_oss_write_new,
- NULL
-};
-
-
-static MSOssWriteClass *msosswriteclass=NULL;
-
-MSFilter * ms_oss_write_new()
-{
- MSOssWrite *w;
-
- if (msosswriteclass==NULL)
- {
- msosswriteclass=g_new(MSOssWriteClass,1);
- ms_oss_write_class_init( msosswriteclass );
- }
- w=g_new(MSOssWrite,1);
- MS_FILTER(w)->klass=MS_FILTER_CLASS(msosswriteclass);
- ms_oss_write_init(w);
- return(MS_FILTER(w));
-}
-
-/* FOR INTERNAL USE*/
-void ms_oss_write_init(MSOssWrite *w)
-{
- ms_sound_write_init(MS_SOUND_WRITE(w));
- MS_FILTER(w)->infifos=w->f_inputs;
- MS_FILTER(w)->infifos[0]=NULL;
- MS_FILTER(w)->r_mingran=512; /* very few cards can do that...*/
- w->devid=0;
- w->sndcard=NULL;
- w->freq=8000;
- w->channels=1;
- w->dtmf_time=-1;
-}
-
-gint ms_oss_write_set_property(MSOssWrite *f,MSFilterProperty prop, void *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FREQ:
- f->freq=((gint*)value)[0];
- break;
- case MS_FILTER_PROPERTY_CHANNELS:
- f->channels=((gint*)value)[0];
- break;
- }
- return 0;
-}
-
-void ms_oss_write_class_init(MSOssWriteClass *klass)
-{
- ms_sound_write_class_init(MS_SOUND_WRITE_CLASS(klass));
- MS_FILTER_CLASS(klass)->max_finputs=1; /* one fifo input only */
- MS_FILTER_CLASS(klass)->r_maxgran=MS_OSS_WRITE_DEF_GRAN;
- MS_FILTER_CLASS(klass)->process= (MSFilterProcessFunc)ms_oss_write_process;
- MS_FILTER_CLASS(klass)->destroy= (MSFilterDestroyFunc)ms_oss_write_destroy;
- MS_FILTER_CLASS(klass)->setup= (MSFilterSetupFunc)ms_oss_write_setup;
- MS_FILTER_CLASS(klass)->unsetup= (MSFilterSetupFunc)ms_oss_write_stop;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_oss_write_set_property;
- MS_FILTER_CLASS(klass)->info=&oss_write_info;
- MS_SOUND_WRITE_CLASS(klass)->set_device=(gint (*)(MSSoundWrite*,gint))ms_oss_write_set_device;
- MS_SOUND_WRITE_CLASS(klass)->start=(void (*)(MSSoundWrite*))ms_oss_write_start;
- MS_SOUND_WRITE_CLASS(klass)->stop=(void (*)(MSSoundWrite*))ms_oss_write_stop;
- MS_SOUND_WRITE_CLASS(klass)->set_level=(void (*)(MSSoundWrite*, gint))ms_oss_write_set_level;
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"OssWrite");
-}
-
-void ms_oss_write_destroy( MSOssWrite *obj)
-{
-
- g_free(obj);
-}
-
-void ms_oss_write_process(MSOssWrite *f)
-{
- MSFifo *fifo;
- void *p;
- int i;
- gint gran=ms_filter_get_mingran(MS_FILTER(f));
-
- /* always consume something */
- fifo=f->f_inputs[0];
- ms_fifo_get_read_ptr(fifo,gran,&p);
- if (p==NULL) {
- g_warning("Not enough data: gran=%i.",gran);
- return;
- }
- g_return_if_fail(f->sndcard!=NULL);
- if (f->dtmf_time!=-1){
- gint16 *buf=(gint16*)p;
- /* generate a DTMF*/
- for(i=0;i<gran/2;i++){
- buf[i]=(gint16)(10000.0*sin(2*M_PI*(double)f->dtmf_time*f->lowfreq));
- buf[i]+=(gint16)(10000.0*sin(2*M_PI*(double)f->dtmf_time*f->highfreq));
- f->dtmf_time++;
- //printf("buf[%i]=%i\n",i,buf[i]);
- }
- if (f->dtmf_time>f->dtmf_duration) f->dtmf_time=-1; /*finished*/
- }
- snd_card_write(f->sndcard,p,gran);
-}
-
-void ms_oss_write_start(MSOssWrite *w)
-{
- gint bsize;
- g_return_if_fail(w->devid!=-1);
- w->sndcard=snd_card_manager_get_card(snd_card_manager,w->devid);
- g_return_if_fail(w->sndcard!=NULL);
- /* open the device for an audio telephony signal with minimum latency */
- snd_card_open_w(w->sndcard,16,w->channels==2,w->freq);
- w->bsize=snd_card_get_bsize(w->sndcard);
- //MS_FILTER(w)->r_mingran=w->bsize;
- //ms_sync_set_samples_per_tick(MS_FILTER(w)->sync,bsize);
-}
-
-void ms_oss_write_stop(MSOssWrite *w)
-{
- g_return_if_fail(w->devid!=-1);
- g_return_if_fail(w->sndcard!=NULL);
- snd_card_close_w(w->sndcard);
- w->sndcard=NULL;
-}
-
-void ms_oss_write_set_level(MSOssWrite *w,gint a)
-{
-
-}
-
-gint ms_oss_write_set_device(MSOssWrite *w, gint devid)
-{
- w->devid=devid;
- return 0;
-}
-
-void ms_oss_write_setup(MSOssWrite *r)
-{
- //g_message("starting MSOssWrite..");
- ms_oss_write_start(r);
-}
-
-
-
-void ms_oss_write_play_dtmf(MSOssWrite *w, char dtmf){
-
- w->dtmf_duration=0.1*w->freq;
- switch(dtmf){
- case '0':
- w->lowfreq=941;
- w->highfreq=1336;
- break;
- case '1':
- w->lowfreq=697;
- w->highfreq=1209;
- break;
- case '2':
- w->lowfreq=697;
- w->highfreq=1336;
- break;
- case '3':
- w->lowfreq=697;
- w->highfreq=1477;
- break;
- case '4':
- w->lowfreq=770;
- w->highfreq=1209;
- break;
- case '5':
- w->lowfreq=770;
- w->highfreq=1336;
- break;
- case '6':
- w->lowfreq=770;
- w->highfreq=1477;
- break;
- case '7':
- w->lowfreq=852;
- w->highfreq=1209;
- break;
- case '8':
- w->lowfreq=852;
- w->highfreq=1336;
- break;
- case '9':
- w->lowfreq=852;
- w->highfreq=1477;
- break;
- case '*':
- w->lowfreq=941;
- w->highfreq=1209;
- break;
- case '#':
- w->lowfreq=941;
- w->highfreq=1477;
- break;
- case 'A':
- w->lowfreq=697;
- w->highfreq=1633;
- break;
- case 'B':
- w->lowfreq=770;
- w->highfreq=1633;
- break;
- case 'C':
- w->lowfreq=852;
- w->highfreq=1633;
- break;
- case 'D':
- w->lowfreq=941;
- w->highfreq=1633;
- break;
- default:
- g_warning("Not a dtmf key.");
- return;
- }
- w->lowfreq=w->lowfreq/w->freq;
- w->highfreq=w->highfreq/w->freq;
- w->dtmf_time=0;
-}
diff --git a/talk/third_party/mediastreamer/msosswrite.h b/talk/third_party/mediastreamer/msosswrite.h
deleted file mode 100755
index d477534..0000000
--- a/talk/third_party/mediastreamer/msosswrite.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#ifndef MSOSSWRITE_H
-#define MSOSSWRITE_H
-
-#include "mssoundwrite.h"
-#include "sndcard.h"
-
-/*this is the class that implements oss writing sink filter*/
-
-#define MS_OSS_WRITE_MAX_INPUTS 1 /* max output per filter*/
-
-#define MS_OSS_WRITE_DEF_GRAN (512*2) /* the default granularity*/
-
-struct _MSOssWrite
-{
- /* the MSOssWrite derivates from MSSoundWrite, so the MSSoundWrite object MUST be the first of the MSOssWrite object
- in order to the object mechanism to work*/
- MSSoundWrite filter;
- MSFifo *f_inputs[MS_OSS_WRITE_MAX_INPUTS];
- gint devid; /* the sound device id it depends on*/
- SndCard *sndcard;
- gint bsize;
- gint freq;
- gint channels;
- gdouble lowfreq;
- gdouble highfreq;
- gint dtmf_time;
- gint dtmf_duration;
-};
-
-typedef struct _MSOssWrite MSOssWrite;
-
-struct _MSOssWriteClass
-{
- /* the MSOssWrite derivates from MSSoundWrite, so the MSSoundWrite class MUST be the first of the MSOssWrite class
- in order to the class mechanism to work*/
- MSSoundWriteClass parent_class;
-};
-
-typedef struct _MSOssWriteClass MSOssWriteClass;
-
-/* PUBLIC */
-#define MS_OSS_WRITE(filter) ((MSOssWrite*)(filter))
-#define MS_OSS_WRITE_CLASS(klass) ((MSOssWriteClass*)(klass))
-MSFilter * ms_oss_write_new(void);
-gint ms_oss_write_set_device(MSOssWrite *w,gint devid);
-void ms_oss_write_start(MSOssWrite *w);
-void ms_oss_write_stop(MSOssWrite *w);
-void ms_oss_write_set_level(MSOssWrite *w, gint level);
-void ms_oss_write_play_dtmf(MSOssWrite *w, char dtmf);
-
-/* FOR INTERNAL USE*/
-void ms_oss_write_init(MSOssWrite *r);
-void ms_oss_write_setup(MSOssWrite *r);
-void ms_oss_write_class_init(MSOssWriteClass *klass);
-void ms_oss_write_destroy( MSOssWrite *obj);
-void ms_oss_write_process(MSOssWrite *f);
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msqdispatcher.c b/talk/third_party/mediastreamer/msqdispatcher.c
deleted file mode 100755
index 6bd073b..0000000
--- a/talk/third_party/mediastreamer/msqdispatcher.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a dispatcher of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "msqdispatcher.h"
-
-static MSQdispatcherClass *ms_qdispatcher_class=NULL;
-
-MSFilter * ms_qdispatcher_new(void)
-{
- MSQdispatcher *obj;
- obj=g_malloc(sizeof(MSQdispatcher));
- if (ms_qdispatcher_class==NULL){
- ms_qdispatcher_class=g_malloc0(sizeof(MSQdispatcherClass));
- ms_qdispatcher_class_init(ms_qdispatcher_class);
- }
- MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_qdispatcher_class);
- ms_qdispatcher_init(obj);
- return MS_FILTER(obj);
-}
-
-
-void ms_qdispatcher_init(MSQdispatcher *obj)
-{
- ms_filter_init(MS_FILTER(obj));
-
- MS_FILTER(obj)->inqueues=obj->q_inputs;
- MS_FILTER(obj)->outqueues=obj->q_outputs;
- memset(obj->q_inputs,0,sizeof(MSQueue*)*MS_QDISPATCHER_MAX_INPUTS);
- memset(obj->q_outputs,0,sizeof(MSQueue*)*MS_QDISPATCHER_MAX_OUTPUTS);
-}
-
-
-
-void ms_qdispatcher_class_init(MSQdispatcherClass *klass)
-{
- MSFilterClass *parent_class=MS_FILTER_CLASS(klass);
- ms_filter_class_init(parent_class);
- ms_filter_class_set_name(parent_class,"qdispatcher");
- parent_class->max_qinputs=MS_QDISPATCHER_MAX_INPUTS;
- parent_class->max_qoutputs=MS_QDISPATCHER_MAX_OUTPUTS;
-
- parent_class->destroy=(MSFilterDestroyFunc)ms_qdispatcher_destroy;
- parent_class->process=(MSFilterProcessFunc)ms_qdispatcher_process;
-}
-
-
-void ms_qdispatcher_destroy( MSQdispatcher *obj)
-{
- g_free(obj);
-}
-
-void ms_qdispatcher_process(MSQdispatcher *obj)
-{
- gint i;
- MSQueue *inq=obj->q_inputs[0];
-
- if (inq!=NULL){
- MSQueue *outq;
- MSMessage *m1,*m2;
- while ( (m1=ms_queue_get(inq))!=NULL){
- /* dispatch incoming messages to output queues */
- for (i=0;i<MS_QDISPATCHER_MAX_OUTPUTS;i++){
- outq=obj->q_outputs[i];
- if (outq!=NULL){
- m2=ms_message_dup(m1);
- ms_queue_put(outq,m2);
- }
- }
- ms_message_destroy(m1);
- }
- }
-
-}
diff --git a/talk/third_party/mediastreamer/msqdispatcher.h b/talk/third_party/mediastreamer/msqdispatcher.h
deleted file mode 100755
index 3b0c566..0000000
--- a/talk/third_party/mediastreamer/msqdispatcher.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a dispatcher of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSQDISPATCHER_H
-#define MSQDISPATCHER_H
-
-#include "msfilter.h"
-
-
-/*this is the class that implements a qdispatcher filter*/
-
-#define MS_QDISPATCHER_MAX_INPUTS 1
-#define MS_QDISPATCHER_MAX_OUTPUTS 5
-
-typedef struct _MSQdispatcher
-{
- /* the MSQdispatcher derivates from MSFilter, so the MSFilter object MUST be the first of the MSQdispatcher object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSQueue *q_inputs[MS_QDISPATCHER_MAX_INPUTS];
- MSQueue *q_outputs[MS_QDISPATCHER_MAX_OUTPUTS];
-} MSQdispatcher;
-
-typedef struct _MSQdispatcherClass
-{
- /* the MSQdispatcher derivates from MSFilter, so the MSFilter class MUST be the first of the MSQdispatcher class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSQdispatcherClass;
-
-/* PUBLIC */
-#define MS_QDISPATCHER(filter) ((MSQdispatcher*)(filter))
-#define MS_QDISPATCHER_CLASS(klass) ((MSQdispatcherClass*)(klass))
-MSFilter * ms_qdispatcher_new(void);
-
-/* FOR INTERNAL USE*/
-void ms_qdispatcher_init(MSQdispatcher *r);
-void ms_qdispatcher_class_init(MSQdispatcherClass *klass);
-void ms_qdispatcher_destroy( MSQdispatcher *obj);
-void ms_qdispatcher_process(MSQdispatcher *r);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msqueue.c b/talk/third_party/mediastreamer/msqueue.c
deleted file mode 100755
index 4636895..0000000
--- a/talk/third_party/mediastreamer/msqueue.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "msqueue.h"
-#include <string.h>
-
-MSQueue * ms_queue_new()
-{
- MSQueue *q=g_malloc(sizeof(MSQueue));
- memset(q,0,sizeof(MSQueue));
- return q;
-}
-
-MSMessage *ms_queue_get(MSQueue *q)
-{
- MSMessage *b=q->last;
- if (b==NULL) return NULL;
- q->last=b->prev;
- if (b->prev==NULL) q->first=NULL; /* it was the only element of the queue*/
- q->size--;
- b->next=b->prev=NULL;
- return(b);
-}
-
-void ms_queue_put(MSQueue *q, MSMessage *m)
-{
- MSMessage *mtmp=q->first;
- g_return_if_fail(m!=NULL);
- q->first=m;
- m->next=mtmp;
- if (mtmp!=NULL)
- {
- mtmp->prev=m;
- }
- else q->last=m; /* it was the first element of the q */
- q->size++;
-}
-
-
diff --git a/talk/third_party/mediastreamer/msqueue.h b/talk/third_party/mediastreamer/msqueue.h
deleted file mode 100755
index 73ab8d8..0000000
--- a/talk/third_party/mediastreamer/msqueue.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSQUEUE_H
-#define MSQUEUE_H
-
-#include "msbuffer.h"
-
-/* for the moment these are stupid queues limited to one element*/
-
-typedef struct _MSQueue
-{
- MSMessage *first;
- MSMessage *last;
- gint size;
- void *prev_data; /*user data, usually the writting filter*/
- void *next_data; /* user data, usually the reading filter*/
-}MSQueue;
-
-
-MSQueue * ms_queue_new();
-
-MSMessage *ms_queue_get(MSQueue *q);
-
-void ms_queue_put(MSQueue *q, MSMessage *m);
-
-#define ms_queue_can_get(q) ( (q)->size!=0 )
-
-#define ms_queue_destroy(q) g_free(q)
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msread.c b/talk/third_party/mediastreamer/msread.c
deleted file mode 100755
index 6f0ec99..0000000
--- a/talk/third_party/mediastreamer/msread.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "msread.h"
-#include "mssync.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <string.h>
-#include <errno.h>
-
-static MSReadClass *ms_read_class=NULL;
-
-MSFilter * ms_read_new(char *name)
-{
- MSRead *r;
- int fd=-1;
-
- r=g_new(MSRead,1);
- ms_read_init(r);
- if (ms_read_class==NULL)
- {
- ms_read_class=g_new(MSReadClass,1);
- ms_read_class_init(ms_read_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_read_class);
- r->fd=-1;
- if (name!=NULL) ms_read_open(r,name);
- return(MS_FILTER(r));
-}
-
-
-
-gint ms_read_open(MSRead *r, gchar *name)
-{
- gint fd;
- fd=open(name,O_RDONLY);
- if (fd<0) {
- r->fd=-1;
- g_warning("ms_read_new: cannot open %s : %s",name,strerror(errno));
- return -1;
- }
- r->fd=fd;
- if (strstr(name,".wav")!=NULL){
- /* skip the header */
- lseek(fd,20,SEEK_SET);
-#ifdef WORDS_BIGENDIAN
- r->need_swap=1;
-#else
- r->need_swap=0;
-#endif
- }
- r->state=MS_READ_STATE_STARTED;
- return 0;
-}
-
-/* FOR INTERNAL USE*/
-void ms_read_init(MSRead *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->outfifos=r->foutputs;
- MS_FILTER(r)->outqueues=r->qoutputs;
- memset(r->foutputs,0,sizeof(MSFifo*)*MSREAD_MAX_OUTPUTS);
- memset(r->qoutputs,0,sizeof(MSQueue*)*MSREAD_MAX_OUTPUTS);
- r->fd=-1;
- r->gran=320;
- r->state=MS_READ_STATE_STOPPED;
- r->need_swap=0;
- r->rate=8000;
-}
-
-gint ms_read_set_property(MSRead *f,MSFilterProperty prop, void *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FREQ:
- f->rate=((gint*)value)[0];
- break;
- }
- return 0;
-}
-
-void ms_read_class_init(MSReadClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"dskreader");
- ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE);
- MS_FILTER_CLASS(klass)->max_foutputs=MSREAD_MAX_OUTPUTS;
- MS_FILTER_CLASS(klass)->max_qoutputs=MSREAD_MAX_OUTPUTS;
- MS_FILTER_CLASS(klass)->w_maxgran=MSREAD_DEF_GRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_read_destroy;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_read_setup;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_read_process;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_read_set_property;
-}
-
-void ms_read_process(MSRead *r)
-{
- MSFifo *f;
- MSQueue *q;
- MSMessage *msg=NULL;
- int err;
- gint gran=r->gran;
- void *p;
-
- f=r->foutputs[0];
- if ((f!=NULL) && (r->state==MS_READ_STATE_STARTED))
- {
- ms_fifo_get_write_ptr(f,gran,&p);
- if (p!=NULL)
- {
- err=read(r->fd,p,gran);
- if (err<0)
- {
- /* temp: */
- g_warning("ms_read_process: failed to read: %s.\n",strerror(errno));
- }
- else if (err<gran){
- ms_trace("ms_read_process: end of file.");
- ms_filter_notify_event(MS_FILTER(r),MS_READ_EVENT_EOF,NULL);
- r->state=MS_READ_STATE_STOPPED;
- close(r->fd);
- r->fd=-1;
- }
- if (r->need_swap) swap_buffer(p,gran);
- }
- }
- /* process output queues*/
- q=r->qoutputs[0];
- if ((q!=NULL) && (r->fd>0))
- {
- msg=ms_message_new(r->gran);
- err=read(r->fd,msg->data,r->gran);
- if (err>0){
- msg->size=err;
- ms_queue_put(q,msg);
- if (r->need_swap) swap_buffer(msg->data,r->gran);
- }else{
- ms_filter_notify_event(MS_FILTER(r),MS_READ_EVENT_EOF,NULL);
- ms_trace("End of file reached.");
- r->state=MS_READ_STATE_STOPPED;
- }
- }
-}
-
-void ms_read_destroy( MSRead *obj)
-{
- if (obj->fd!=0) close(obj->fd);
- g_free(obj);
-}
-
-gint ms_read_close(MSRead *obj)
-{
- if (obj->fd!=0) {
- close(obj->fd);
- obj->fd=-1;
- obj->state=MS_READ_STATE_STOPPED;
- }
-}
-
-
-void ms_read_setup(MSRead *r, MSSync *sync)
-{
- r->sync=sync;
- r->gran=(r->rate*sync->interval/1000)*2;
-}
diff --git a/talk/third_party/mediastreamer/msread.h b/talk/third_party/mediastreamer/msread.h
deleted file mode 100755
index 93177f3..0000000
--- a/talk/third_party/mediastreamer/msread.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSREAD_H
-#define MSREAD_H
-
-#include "msfilter.h"
-#include "mssync.h"
-
-/*this is the class that implements file reading source filter*/
-
-#define MSREAD_MAX_OUTPUTS 1 /* max output per filter*/
-
-#define MSREAD_DEF_GRAN 640 /* the default granularity*/
-
-typedef enum{
- MS_READ_STATE_STARTED,
- MS_READ_STATE_STOPPED,
- MS_READ_STATE_EOF
-}MSReadState;
-
-typedef struct _MSRead
-{
- /* the MSRead derivates from MSFilter, so the MSFilter object MUST be the first of the MSRead object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *foutputs[MSREAD_MAX_OUTPUTS];
- MSQueue *qoutputs[MSREAD_MAX_OUTPUTS];
- MSSync *sync;
- gint rate;
- gint fd; /* the file descriptor of the file being read*/
- gint gran; /*granularity*/ /* for use with queues */
- gint need_swap;
- gint state;
-} MSRead;
-
-typedef struct _MSReadClass
-{
- /* the MSRead derivates from MSFilter, so the MSFilter class MUST be the first of the MSRead class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSReadClass;
-
-/* PUBLIC */
-#define MS_READ(filter) ((MSRead*)(filter))
-#define MS_READ_CLASS(klass) ((MSReadClass*)(klass))
-MSFilter * ms_read_new(char *name);
-/* set the granularity for reading file on disk */
-#define ms_read_set_bufsize(filter,sz) (filter)->gran=(sz)
-
-/* FOR INTERNAL USE*/
-void ms_read_init(MSRead *r);
-void ms_read_class_init(MSReadClass *klass);
-void ms_read_destroy( MSRead *obj);
-void ms_read_process(MSRead *r);
-void ms_read_setup(MSRead *r, MSSync *sync);
-
-typedef enum{
- MS_READ_EVENT_EOF /* end of file */
-} MSReadEvent;
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msringplayer.c b/talk/third_party/mediastreamer/msringplayer.c
deleted file mode 100755
index fb2006e..0000000
--- a/talk/third_party/mediastreamer/msringplayer.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "msringplayer.h"
-#include "mssync.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <string.h>
-#include <errno.h>
-
-#include "waveheader.h"
-
-#define WAVE_HEADER_OFFSET sizeof(wave_header_t)
-
-enum { PLAY_RING, PLAY_SILENCE};
-
-static int supported_freq[6]={8000,11025,16000,22050,32000,44100};
-
-gint freq_is_supported(gint freq){
- int i;
- for (i=0;i<6;i++){
- if (abs(supported_freq[i]-freq)<50) return supported_freq[i];
- }
- return 0;
-}
-
-static MSRingPlayerClass *ms_ring_player_class=NULL;
-
-/**
- * ms_ring_player_new:
- * @name: The path to the 16-bit 8khz raw file to be played as a ring.
- * @seconds: The number of seconds that separates two rings.
- *
- * Allocates a new MSRingPlayer object.
- *
- *
- * Returns: a pointer the the object, NULL if name could not be open.
- */
-MSFilter * ms_ring_player_new(char *name, gint seconds)
-{
- MSRingPlayer *r;
- int fd=-1;
-
- if ((name!=NULL) && (strlen(name)!=0))
- {
- fd=open(name,O_RDONLY);
- if (fd<0)
- {
- g_warning("ms_ring_player_new: failed to open %s.\n",name);
- return NULL;
- }
-
- }else {
- g_warning("ms_ring_player_new: Bad file name");
- return NULL;
- }
-
- r=g_new(MSRingPlayer,1);
- ms_ring_player_init(r);
- if (ms_ring_player_class==NULL)
- {
- ms_ring_player_class=g_new(MSRingPlayerClass,1);
- ms_ring_player_class_init(ms_ring_player_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ring_player_class);
-
- r->fd=fd;
- r->silence=seconds;
- r->freq=8000;
- if (strstr(name,".wav")!=NULL){
- wave_header_t header;
- int freq,freq2;
- /* read the header */
- read(fd,&header,sizeof(wave_header_t));
- freq=wave_header_get_rate(&header);
- if ((freq2=freq_is_supported(freq))>0){
- r->freq=freq2;
- }else {
- g_warning("Unsupported sampling rate %i",freq);
- r->freq=8000;
- }
- r->channel=wave_header_get_channel(&header);
- lseek(fd,WAVE_HEADER_OFFSET,SEEK_SET);
-#ifdef WORDS_BIGENDIAN
- r->need_swap=1;
-#else
- r->need_swap=0;
-#endif
- }
- ms_ring_player_set_property(r, MS_FILTER_PROPERTY_FREQ,&r->freq);
- r->state=PLAY_RING;
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_ring_player_init(MSRingPlayer *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->outfifos=r->foutputs;
- MS_FILTER(r)->outqueues=r->qoutputs;
- memset(r->foutputs,0,sizeof(MSFifo*)*MS_RING_PLAYER_MAX_OUTPUTS);
- memset(r->qoutputs,0,sizeof(MSQueue*)*MS_RING_PLAYER_MAX_OUTPUTS);
- r->fd=-1;
- r->current_pos=0;
- r->need_swap=0;
- r->sync=NULL;
-}
-
-gint ms_ring_player_set_property(MSRingPlayer *f,MSFilterProperty prop, void *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FREQ:
- f->rate=((gint*)value)[0]*2;
- f->silence_bytes=f->silence*f->rate;
- if (f->sync!=NULL)
- f->gran=(f->rate*f->sync->interval/1000)*2;
- break;
- }
- return 0;
-}
-
-gint ms_ring_player_get_property(MSRingPlayer *f,MSFilterProperty prop, void *value)
-{
- switch(prop){
- case MS_FILTER_PROPERTY_FREQ:
- ((gint*)value)[0]=f->freq;
-
- break;
- case MS_FILTER_PROPERTY_CHANNELS:
- ((gint*)value)[0]=f->channel;
- break;
- }
- return 0;
-}
-
-gint ms_ring_player_get_sample_freq(MSRingPlayer *obj){
- return obj->freq;
-}
-
-
-void ms_ring_player_class_init(MSRingPlayerClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ringplay");
- ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE);
- MS_FILTER_CLASS(klass)->max_foutputs=MS_RING_PLAYER_MAX_OUTPUTS;
- MS_FILTER_CLASS(klass)->max_qoutputs=MS_RING_PLAYER_MAX_OUTPUTS;
- MS_FILTER_CLASS(klass)->w_maxgran=MS_RING_PLAYER_DEF_GRAN;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ring_player_setup;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ring_player_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ring_player_process;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ring_player_set_property;
- MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ring_player_get_property;
-}
-
-void ms_ring_player_process(MSRingPlayer *r)
-{
- MSFifo *f;
- gint err;
- gint processed=0;
- gint gran=r->gran;
- char *p;
-
- g_return_if_fail(gran>0);
- /* process output fifos*/
-
- f=r->foutputs[0];
- ms_fifo_get_write_ptr(f,gran,(void**)&p);
- g_return_if_fail(p!=NULL);
- for (processed=0;processed<gran;){
- switch(r->state){
- case PLAY_RING:
- err=read(r->fd,&p[processed],gran-processed);
- if (err<0)
- {
- memset(&p[processed],0,gran-processed);
- processed=gran;
- g_warning("ms_ring_player_process: failed to read: %s.\n",strerror(errno));
- return;
- }
- else if (err<gran)
- {/* end of file */
-
- r->current_pos=r->silence_bytes;
- lseek(r->fd,WAVE_HEADER_OFFSET,SEEK_SET);
- r->state=PLAY_SILENCE;
- ms_filter_notify_event(MS_FILTER(r),MS_RING_PLAYER_END_OF_RING_EVENT,NULL);
- }
- if (r->need_swap) swap_buffer(&p[processed],err);
- processed+=err;
- break;
- case PLAY_SILENCE:
- err=gran-processed;
- if (r->current_pos>err){
- memset(&p[processed],0,err);
- r->current_pos-=gran;
- processed=gran;
- }else{
- memset(&p[processed],0,r->current_pos);
- processed+=r->current_pos;
- r->state=PLAY_RING;
- }
- break;
- }
- }
-}
-
-/**
- * ms_ring_player_destroy:
- * @obj: A valid MSRingPlayer object.
- *
- * Destroy a MSRingPlayer object.
- *
- *
- */
-
-void ms_ring_player_destroy( MSRingPlayer *obj)
-{
- if (obj->fd!=0) close(obj->fd);
- g_free(obj);
-}
-
-void ms_ring_player_setup(MSRingPlayer *r,MSSync *sync)
-{
- r->sync=sync;
- r->gran=(r->rate*r->sync->interval/1000)*r->channel;
-}
diff --git a/talk/third_party/mediastreamer/msringplayer.h b/talk/third_party/mediastreamer/msringplayer.h
deleted file mode 100755
index 1f5e67d..0000000
--- a/talk/third_party/mediastreamer/msringplayer.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSRINGPLAYER_H
-#define MSRINGPLAYER_H
-
-#include "msfilter.h"
-#include "mssync.h"
-
-
-/*this is the class that implements file reading source filter*/
-
-#define MS_RING_PLAYER_MAX_OUTPUTS 1 /* max output per filter*/
-
-#define MS_RING_PLAYER_DEF_GRAN 8192 /* the default granularity*/
-
-#define MS_RING_PLAYER_END_OF_RING_EVENT 1
-
-struct _MSRingPlayer
-{
- /* the MSRingPlayer derivates from MSFilter, so the MSFilter object MUST be the first of the MSRingPlayer object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *foutputs[MS_RING_PLAYER_MAX_OUTPUTS];
- MSQueue *qoutputs[MS_RING_PLAYER_MAX_OUTPUTS];\
- MSSync *sync;
- gint gran;
- gint freq;
- gint rate;
- gint channel; /* number of interleaved channels */
- gint silence; /* silence time between each ring, in seconds */
- gint state;
- gint fd; /* the file descriptor of the file being read*/
- gint silence_bytes; /*silence in number of bytes between each ring */
- gint current_pos;
- gint need_swap;
-};
-
-typedef struct _MSRingPlayer MSRingPlayer;
-
-struct _MSRingPlayerClass
-{
- /* the MSRingPlayer derivates from MSFilter, so the MSFilter class MUST be the first of the MSRingPlayer class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-};
-
-typedef struct _MSRingPlayerClass MSRingPlayerClass;
-
-/* PUBLIC */
-#define MS_RING_PLAYER(filter) ((MSRingPlayer*)(filter))
-#define MS_RING_PLAYER_CLASS(klass) ((MSRingPlayerClass*)(klass))
-MSFilter * ms_ring_player_new(char *name, gint seconds);
-gint ms_ring_player_get_sample_freq(MSRingPlayer *obj);
-
-
-/* FOR INTERNAL USE*/
-void ms_ring_player_init(MSRingPlayer *r);
-void ms_ring_player_class_init(MSRingPlayerClass *klass);
-void ms_ring_player_destroy( MSRingPlayer *obj);
-void ms_ring_player_process(MSRingPlayer *r);
-#define ms_ring_player_set_bufsize(filter,sz) (filter)->gran=(sz)
-void ms_ring_player_setup(MSRingPlayer *r,MSSync *sync);
-#endif
diff --git a/talk/third_party/mediastreamer/msrtprecv.c b/talk/third_party/mediastreamer/msrtprecv.c
deleted file mode 100755
index 9b82e93..0000000
--- a/talk/third_party/mediastreamer/msrtprecv.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "msrtprecv.h"
-
-
-/* some utilities to convert mblk_t to MSMessage and vice-versa */
-MSMessage *msgb_2_ms_message(mblk_t* mp){
- MSMessage *msg;
- MSBuffer *msbuf;
- if (mp->b_datap->ref_count!=1) return NULL; /* cannot handle properly non-unique buffers*/
- /* create a MSBuffer using the mblk_t buffer */
- msg=ms_message_alloc();
- msbuf=ms_buffer_alloc(0);
- msbuf->buffer=mp->b_datap->db_base;
- msbuf->size=(char*)mp->b_datap->db_lim-(char*)mp->b_datap->db_base;
- ms_message_set_buf(msg,msbuf);
- msg->size=mp->b_wptr-mp->b_rptr;
- msg->data=mp->b_rptr;
- /* free the mblk_t */
- g_free(mp->b_datap);
- g_free(mp);
- return msg;
-}
-
-
-static MSRtpRecvClass *ms_rtp_recv_class=NULL;
-
-MSFilter * ms_rtp_recv_new(void)
-{
- MSRtpRecv *r;
-
- r=g_new(MSRtpRecv,1);
- ms_rtp_recv_init(r);
- if (ms_rtp_recv_class==NULL)
- {
- ms_rtp_recv_class=g_new0(MSRtpRecvClass,1);
- ms_rtp_recv_class_init(ms_rtp_recv_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_rtp_recv_class);
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_rtp_recv_init(MSRtpRecv *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->outfifos=r->f_outputs;
- MS_FILTER(r)->outqueues=r->q_outputs;
- memset(r->f_outputs,0,sizeof(MSFifo*)*MSRTPRECV_MAX_OUTPUTS);
- memset(r->q_outputs,0,sizeof(MSFifo*)*MSRTPRECV_MAX_OUTPUTS);
- r->rtpsession=NULL;
- r->stream_started=0;
-}
-
-void ms_rtp_recv_class_init(MSRtpRecvClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"RTPRecv");
- MS_FILTER_CLASS(klass)->max_qoutputs=MSRTPRECV_MAX_OUTPUTS;
- MS_FILTER_CLASS(klass)->max_foutputs=MSRTPRECV_MAX_OUTPUTS;
- MS_FILTER_CLASS(klass)->w_maxgran=MSRTPRECV_DEF_GRAN;
- ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE);
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_rtp_recv_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_rtp_recv_process;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_rtp_recv_setup;
-}
-
-void ms_rtp_recv_process(MSRtpRecv *r)
-{
- MSFifo *fo;
- MSQueue *qo;
- MSSync *sync= r->sync;
- void *d;
- mblk_t *mp;
- gint len;
- gint gran=ms_sync_get_samples_per_tick(MS_SYNC(sync));
-
- if (r->rtpsession==NULL) return;
- /* process output fifo and output queue*/
- fo=r->f_outputs[0];
- if (fo!=NULL)
- {
- while( (mp=rtp_session_recvm_with_ts(r->rtpsession,r->prev_ts))!=NULL) {
- /* try to get rtp packets and paste them to the output fifo */
- r->stream_started=1;
- len=mp->b_cont->b_wptr-mp->b_cont->b_rptr;
- ms_fifo_get_write_ptr(fo,len,&d);
- if (d!=NULL){
- memcpy(d,mp->b_cont->b_rptr,len);
- }else ms_warning("ms_rtp_recv_process: no space on output fifo !");
- freemsg(mp);
- }
- r->prev_ts+=gran;
-
- }
- qo=r->q_outputs[0];
- if (qo!=NULL)
- {
- guint32 clock;
- gint got=0;
- /* we are connected with queues (surely for video)*/
- /* use the sync system time to compute a timestamp */
- PayloadType *pt=rtp_profile_get_payload(r->rtpsession->profile,r->rtpsession->payload_type);
- if (pt==NULL) {
- ms_warning("ms_rtp_recv_process(): NULL RtpPayload- skipping.");
- return;
- }
- clock=(guint32)(((double)sync->time*(double)pt->clock_rate)/1000.0);
- /*g_message("Querying packet with timestamp %u",clock);*/
- /* get rtp packet, and send them through the output queue */
- while ( (mp=rtp_session_recvm_with_ts(r->rtpsession,clock))!=NULL ){
- MSMessage *msg;
- mblk_t *mdata;
- /*g_message("Got packet with timestamp %u",clock);*/
- got++;
- r->stream_started=1;
- mdata=mp->b_cont;
- freeb(mp);
- msg=msgb_2_ms_message(mdata);
- ms_queue_put(qo,msg);
- }
- }
-}
-
-void ms_rtp_recv_destroy( MSRtpRecv *obj)
-{
- g_free(obj);
-}
-
-RtpSession * ms_rtp_recv_set_session(MSRtpRecv *obj,RtpSession *session)
-{
- RtpSession *old=obj->rtpsession;
- obj->rtpsession=session;
- obj->prev_ts=0;
- return old;
-}
-
-
-void ms_rtp_recv_setup(MSRtpRecv *r,MSSync *sync)
-{
- r->sync=sync;
- r->stream_started=0;
-}
diff --git a/talk/third_party/mediastreamer/msrtprecv.h b/talk/third_party/mediastreamer/msrtprecv.h
deleted file mode 100755
index 8c2c2ed..0000000
--- a/talk/third_party/mediastreamer/msrtprecv.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSRTPRECV_H
-#define MSRTPRECV_H
-
-#include "msfilter.h"
-#include "mssync.h"
-
-/* because of a conflict between config.h from oRTP and config.h from linphone:*/
-#undef PACKAGE
-#undef VERSION
-#include <ortp/ortp.h>
-
-/*this is the class that implements a copy filter*/
-
-#define MSRTPRECV_MAX_OUTPUTS 1 /* max output per filter*/
-
-#define MSRTPRECV_DEF_GRAN 4096 /* the default granularity*/
-
-struct _MSRtpRecv
-{
- /* the MSCopy derivates from MSFilter, so the MSFilter object MUST be the first of the MSCopy object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_outputs[MSRTPRECV_MAX_OUTPUTS];
- MSQueue *q_outputs[MSRTPRECV_MAX_OUTPUTS];
- MSSync *sync;
- RtpSession *rtpsession;
- guint32 prev_ts;
- gint stream_started;
-};
-
-typedef struct _MSRtpRecv MSRtpRecv;
-
-struct _MSRtpRecvClass
-{
- /* the MSCopy derivates from MSFilter, so the MSFilter class MUST be the first of the MSCopy class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-};
-
-typedef struct _MSRtpRecvClass MSRtpRecvClass;
-
-/* PUBLIC */
-#define MS_RTP_RECV(filter) ((MSRtpRecv*)(filter))
-#define MS_RTP_RECV_CLASS(klass) ((MSRtpRecvClass*)(klass))
-MSFilter * ms_rtp_recv_new(void);
-RtpSession * ms_rtp_recv_set_session(MSRtpRecv *obj,RtpSession *session);
-#define ms_rtp_recv_unset_session(obj) (ms_rtp_recv_set_session((obj),NULL))
-#define ms_rtp_recv_get_session(obj) ((obj)->rtpsession)
-
-
-
-/* FOR INTERNAL USE*/
-void ms_rtp_recv_init(MSRtpRecv *r);
-void ms_rtp_recv_class_init(MSRtpRecvClass *klass);
-void ms_rtp_recv_destroy( MSRtpRecv *obj);
-void ms_rtp_recv_process(MSRtpRecv *r);
-void ms_rtp_recv_setup(MSRtpRecv *r,MSSync *sync);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msrtpsend.c b/talk/third_party/mediastreamer/msrtpsend.c
deleted file mode 100755
index 5e781ff..0000000
--- a/talk/third_party/mediastreamer/msrtpsend.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "msrtpsend.h"
-#include <ortp/telephonyevents.h>
-#include "mssync.h"
-#include "mscodec.h"
-
-
-
-static MSRtpSendClass *ms_rtp_send_class=NULL;
-
-MSFilter * ms_rtp_send_new(void)
-{
- MSRtpSend *r;
-
- r=g_new(MSRtpSend,1);
-
- if (ms_rtp_send_class==NULL)
- {
- ms_rtp_send_class=g_new(MSRtpSendClass,1);
- ms_rtp_send_class_init(ms_rtp_send_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_rtp_send_class);
- ms_rtp_send_init(r);
- return(MS_FILTER(r));
-}
-
-
-void ms_rtp_send_init(MSRtpSend *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->inqueues=r->q_inputs;
- MS_FILTER(r)->r_mingran=MSRTPSEND_DEF_GRAN;
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSRTPSEND_MAX_INPUTS);
- memset(r->q_inputs,0,sizeof(MSFifo*)*MSRTPSEND_MAX_INPUTS);
- r->rtpsession=NULL;
- r->ts=0;
- r->ts_inc=0;
- r->flags=0;
- r->delay=0;
-}
-
-void ms_rtp_send_class_init(MSRtpSendClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"RTPSend");
- MS_FILTER_CLASS(klass)->max_qinputs=MSRTPSEND_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_finputs=MSRTPSEND_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=MSRTPSEND_DEF_GRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_rtp_send_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_rtp_send_process;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_rtp_send_setup;
-}
-
-void ms_rtp_send_set_timing(MSRtpSend *r, guint32 ts_inc, gint payload_size)
-{
- r->ts_inc=ts_inc;
- r->packet_size=payload_size;
- if (r->ts_inc!=0) r->flags|=RTPSEND_CONFIGURED;
- else r->flags&=~RTPSEND_CONFIGURED;
- MS_FILTER(r)->r_mingran=payload_size;
- /*g_message("ms_rtp_send_set_timing: ts_inc=%i",ts_inc);*/
-}
-
-guint32 get_new_timestamp(MSRtpSend *r,guint32 synctime)
-{
- guint32 clockts;
- /* use the sync system time to compute a timestamp */
- PayloadType *pt=rtp_profile_get_payload(r->rtpsession->profile,r->rtpsession->payload_type);
- g_return_val_if_fail(pt!=NULL,0);
- clockts=(guint32)(((double)synctime * (double)pt->clock_rate)/1000.0);
- ms_trace("ms_rtp_send_process: sync->time=%i clock=%i",synctime,clockts);
- if (r->flags & RTPSEND_CONFIGURED){
- if (RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(clockts,r->ts+(2*r->ts_inc) )){
- r->ts=clockts;
- }
- else r->ts+=r->ts_inc;
- }else{
- r->ts=clockts;
- }
- return r->ts;
-}
-
-
-void ms_rtp_send_process(MSRtpSend *r)
-{
- MSFifo *fi;
- MSQueue *qi;
- MSSync *sync= r->sync;
- int gran=ms_sync_get_samples_per_tick(sync);
- guint32 ts;
- void *s;
- guint skip;
- guint32 synctime=sync->time;
-
- g_return_if_fail(gran>0);
- if (r->rtpsession==NULL) return;
-
- ms_filter_lock(MS_FILTER(r));
- skip=r->delay!=0;
- if (skip) r->delay--;
- /* process output fifo and output queue*/
- fi=r->f_inputs[0];
- if (fi!=NULL)
- {
- ts=get_new_timestamp(r,synctime);
- /* try to read r->packet_size bytes and send them in a rtp packet*/
- ms_fifo_get_read_ptr(fi,r->packet_size,&s);
- if (!skip){
- rtp_session_send_with_ts(r->rtpsession,s,r->packet_size,ts);
- ms_trace("len=%i, ts=%i ",r->packet_size,ts);
- }
- }
- qi=r->q_inputs[0];
- if (qi!=NULL)
- {
- MSMessage *msg;
- /* read a MSMessage and send it through the network*/
- while ( (msg=ms_queue_get(qi))!=NULL){
- ts=get_new_timestamp(r,synctime);
- if (!skip) {
- /*g_message("Sending packet with ts=%u",ts);*/
- rtp_session_send_with_ts(r->rtpsession,msg->data,msg->size,ts);
-
- }
- ms_message_destroy(msg);
- }
- }
- ms_filter_unlock(MS_FILTER(r));
-}
-
-void ms_rtp_send_destroy( MSRtpSend *obj)
-{
- g_free(obj);
-}
-
-RtpSession * ms_rtp_send_set_session(MSRtpSend *obj,RtpSession *session)
-{
- RtpSession *old=obj->rtpsession;
- obj->rtpsession=session;
- obj->ts=0;
- obj->ts_inc=0;
- return old;
-}
-
-void ms_rtp_send_setup(MSRtpSend *r, MSSync *sync)
-{
- MSFilter *codec;
- MSCodecInfo *info;
- r->sync=sync;
- codec=ms_filter_search_upstream_by_type(MS_FILTER(r),MS_FILTER_AUDIO_CODEC);
- if (codec==NULL) codec=ms_filter_search_upstream_by_type(MS_FILTER(r),MS_FILTER_VIDEO_CODEC);
- if (codec==NULL){
- g_warning("ms_rtp_send_setup: could not find upstream codec.");
- return;
- }
- info=MS_CODEC_INFO(codec->klass->info);
- if (info->info.type==MS_FILTER_AUDIO_CODEC){
- int ts_inc=info->fr_size/2;
- int psize=info->dt_size;
- if (ts_inc==0){
- /* dont'use the normal frame size: this is a variable frame size codec */
- /* use the MS_FILTER(codec)->r_mingran */
- ts_inc=MS_FILTER(codec)->r_mingran/2;
- psize=0;
- }
- ms_rtp_send_set_timing(r,ts_inc,psize);
- }
-}
-
-gint ms_rtp_send_dtmf(MSRtpSend *r, gchar dtmf)
-{
- gint res;
-
- if (r->rtpsession==NULL) return -1;
- if (rtp_session_telephone_events_supported(r->rtpsession)==-1){
- g_warning("ERROR : telephone events not supported.\n");
- return -1;
- }
-
- ms_filter_lock(MS_FILTER(r));
- g_message("Sending DTMF.");
- res=rtp_session_send_dtmf(r->rtpsession, dtmf, r->ts);
- if (res==0){
- //r->ts+=r->ts_inc;
- r->delay+=2;
- }else g_warning("Could not send dtmf.");
-
- ms_filter_unlock(MS_FILTER(r));
-
- return res;
-}
diff --git a/talk/third_party/mediastreamer/msrtpsend.h b/talk/third_party/mediastreamer/msrtpsend.h
deleted file mode 100755
index b70f4e5..0000000
--- a/talk/third_party/mediastreamer/msrtpsend.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSRTPSEND_H
-#define MSRTPSEND_H
-
-#include "msfilter.h"
-#include "mssync.h"
-
-#undef PACKAGE
-#undef VERSION
-#include <ortp/ortp.h>
-
-
-/*this is the class that implements a sending through rtp filter*/
-
-#define MSRTPSEND_MAX_INPUTS 1 /* max input per filter*/
-
-#define MSRTPSEND_DEF_GRAN 4096/* the default granularity*/
-
-struct _MSRtpSend
-{
- /* the MSCopy derivates from MSFilter, so the MSFilter object MUST be the first of the MSCopy object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSRTPSEND_MAX_INPUTS];
- MSQueue *q_inputs[MSRTPSEND_MAX_INPUTS];
- MSSync *sync;
- RtpSession *rtpsession;
- guint32 ts;
- guint32 ts_inc; /* the timestamp increment */
- gint packet_size;
- guint flags;
- guint delay; /* number of _proccess call which must be skipped */
-#define RTPSEND_CONFIGURED (1)
-};
-
-typedef struct _MSRtpSend MSRtpSend;
-
-struct _MSRtpSendClass
-{
- /* the MSRtpSend derivates from MSFilter, so the MSFilter class MUST be the first of the MSCopy class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-};
-
-typedef struct _MSRtpSendClass MSRtpSendClass;
-
-/* PUBLIC */
-#define MS_RTP_SEND(filter) ((MSRtpSend*)(filter))
-#define MS_RTP_SEND_CLASS(klass) ((MSRtpSendClass*)(klass))
-MSFilter * ms_rtp_send_new(void);
-RtpSession * ms_rtp_send_set_session(MSRtpSend *obj,RtpSession *session);
-#define ms_rtp_send_unset_session(obj) (ms_rtp_send_set_session((obj),NULL))
-#define ms_rtp_send_get_session(obj) ((obj)->rtpsession)
-void ms_rtp_send_set_timing(MSRtpSend *r, guint32 ts_inc, gint payload_size);
-gint ms_rtp_send_dtmf(MSRtpSend *r, gchar dtmf);
-
-
-/* FOR INTERNAL USE*/
-void ms_rtp_send_init(MSRtpSend *r);
-void ms_rtp_send_class_init(MSRtpSendClass *klass);
-void ms_rtp_send_destroy( MSRtpSend *obj);
-void ms_rtp_send_process(MSRtpSend *r);
-void ms_rtp_send_setup(MSRtpSend *r, MSSync *sync);
-
-#endif
diff --git a/talk/third_party/mediastreamer/mssdlout.h b/talk/third_party/mediastreamer/mssdlout.h
deleted file mode 100755
index fd6ec54..0000000
--- a/talk/third_party/mediastreamer/mssdlout.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/***************************************************************************
- * mssdlout.h
- *
- * Mon Jul 11 16:18:55 2005
- * Copyright 2005 Simon Morlat
- * Email simon dot morlat at linphone dot org
- ****************************************************************************/
-
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef mssdlout_h
-#define mssdlout_h
-
-#include "msfilter.h"
-
-#include <SDL/SDL.h>
-#include <SDL/SDL_video.h>
-
-struct _MSSdlOut
-{
- MSFilter parent;
- MSQueue *input[2];
- gint width,height;
- const gchar *format;
- SDL_Surface *screen;
- SDL_Overlay *overlay;
- MSMessage *oldinm1;
- gboolean use_yuv;
-};
-
-
-typedef struct _MSSdlOut MSSdlOut;
-
-struct _MSSdlOutClass
-{
- MSFilterClass parent_class;
-};
-
-typedef struct _MSSdlOutClass MSSdlOutClass;
-
-MSFilter * ms_sdl_out_new(void);
-void ms_sdl_out_set_format(MSSdlOut *obj, const char *fmt);
-
-#define MS_SDL_OUT(obj) ((MSSdlOut*)obj)
-
-#endif
diff --git a/talk/third_party/mediastreamer/mssoundread.c b/talk/third_party/mediastreamer/mssoundread.c
deleted file mode 100755
index 3803b01..0000000
--- a/talk/third_party/mediastreamer/mssoundread.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation
-
- */
-
-#include "mssoundread.h"
-
-
-void ms_sound_read_init(MSSoundRead *w)
-{
- ms_filter_init(MS_FILTER(w));
-
-}
-
-void ms_sound_read_class_init(MSSoundReadClass *klass)
-{
- int i;
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- MS_FILTER_CLASS(klass)->max_foutputs=1; /* one fifo output only */
-
- ms_filter_class_set_attr( MS_FILTER_CLASS(klass),FILTER_IS_SOURCE);
-}
-
diff --git a/talk/third_party/mediastreamer/mssoundread.h b/talk/third_party/mediastreamer/mssoundread.h
deleted file mode 100755
index 7f2cab9..0000000
--- a/talk/third_party/mediastreamer/mssoundread.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#ifndef MSSOUNDREAD_H
-#define MSSOUNDREAD_H
-
-#include "msfilter.h"
-#include "mssync.h"
-
-
-
-struct _MSSoundRead
-{
- /* the MSOssRead derivates from MSFilter, so the MSFilter object MUST be the first of the MSOssRead object
- in order to the object mechanism to work*/
- MSFilter filter;
-};
-
-typedef struct _MSSoundRead MSSoundRead;
-
-struct _MSSoundReadClass
-{
- /* the MSOssRead derivates from MSFilter, so the MSFilter class MUST be the first of the MSOssRead class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
- gint (*set_device)(MSSoundRead *, gint devid);
- void (*start)(MSSoundRead *);
- void (*stop)(MSSoundRead*);
- void (*set_level)(MSSoundRead *, gint a);
-};
-
-typedef struct _MSSoundReadClass MSSoundReadClass;
-
-/* PUBLIC */
-#define MS_SOUND_READ(filter) ((MSSoundRead*)(filter))
-#define MS_SOUND_READ_CLASS(klass) ((MSSoundReadClass*)(klass))
-
-static inline int ms_sound_read_set_device(MSSoundRead *r,gint devid)
-{
- return MS_SOUND_READ_CLASS( MS_FILTER(r)->klass )->set_device(r,devid);
-}
-
-static inline void ms_sound_read_start(MSSoundRead *r)
-{
- MS_SOUND_READ_CLASS( MS_FILTER(r)->klass )->start(r);
-}
-
-static inline void ms_sound_read_stop(MSSoundRead *w)
-{
- MS_SOUND_READ_CLASS( MS_FILTER(w)->klass )->stop(w);
-}
-
-static inline void ms_sound_read_set_level(MSSoundRead *w,gint a)
-{
- MS_SOUND_READ_CLASS( MS_FILTER(w)->klass )->set_level(w,a);
-}
-
-/* FOR INTERNAL USE*/
-void ms_sound_read_init(MSSoundRead *r);
-void ms_sound_read_class_init(MSSoundReadClass *klass);
-
-
-#endif
-
diff --git a/talk/third_party/mediastreamer/mssoundwrite.c b/talk/third_party/mediastreamer/mssoundwrite.c
deleted file mode 100755
index 9c5879f..0000000
--- a/talk/third_party/mediastreamer/mssoundwrite.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation
-
- */
-
-#include "mssoundwrite.h"
-
-
-void ms_sound_write_init(MSSoundWrite *w)
-{
- ms_filter_init(MS_FILTER(w));
-
-}
-
-void ms_sound_write_class_init(MSSoundWriteClass *klass)
-{
- int i;
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- MS_FILTER_CLASS(klass)->max_finputs=1; /* one fifo output only */
-
- ms_filter_class_set_attr( MS_FILTER_CLASS(klass),FILTER_IS_SINK);
-}
-
diff --git a/talk/third_party/mediastreamer/mssoundwrite.h b/talk/third_party/mediastreamer/mssoundwrite.h
deleted file mode 100755
index e6d7987..0000000
--- a/talk/third_party/mediastreamer/mssoundwrite.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#ifndef MSSOUNDWRITE_H
-#define MSSOUNDWRITE_H
-
-#include "msfilter.h"
-#include "mssync.h"
-
-
-
-struct _MSSoundWrite
-{
- /* the MSOssWrite derivates from MSFilter, so the MSFilter object MUST be the first of the MSOssWrite object
- in order to the object mechanism to work*/
- MSFilter filter;
-};
-
-typedef struct _MSSoundWrite MSSoundWrite;
-
-struct _MSSoundWriteClass
-{
- /* the MSOssWrite derivates from MSFilter, so the MSFilter class MUST be the first of the MSOssWrite class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
- gint (*set_device)(MSSoundWrite *, gint devid);
- void (*start)(MSSoundWrite *);
- void (*stop)(MSSoundWrite*);
- void (*set_level)(MSSoundWrite *, gint a);
-};
-
-typedef struct _MSSoundWriteClass MSSoundWriteClass;
-
-/* PUBLIC */
-#define MS_SOUND_WRITE(filter) ((MSSoundWrite*)(filter))
-#define MS_SOUND_WRITE_CLASS(klass) ((MSSoundWriteClass*)(klass))
-
-static inline int ms_sound_write_set_device(MSSoundWrite *r,gint devid)
-{
- return MS_SOUND_WRITE_CLASS( MS_FILTER(r)->klass )->set_device(r,devid);
-}
-
-static inline void ms_sound_write_start(MSSoundWrite *r)
-{
- MS_SOUND_WRITE_CLASS( MS_FILTER(r)->klass )->start(r);
-}
-
-static inline void ms_sound_write_stop(MSSoundWrite *w)
-{
- MS_SOUND_WRITE_CLASS( MS_FILTER(w)->klass )->stop(w);
-}
-
-static inline void ms_sound_write_set_level(MSSoundWrite *w,gint a)
-{
- MS_SOUND_WRITE_CLASS( MS_FILTER(w)->klass )->set_level(w,a);
-}
-
-/* FOR INTERNAL USE*/
-void ms_sound_write_init(MSSoundWrite *r);
-void ms_sound_write_class_init(MSSoundWriteClass *klass);
-
-
-#endif
-
diff --git a/talk/third_party/mediastreamer/msspeexdec.c b/talk/third_party/mediastreamer/msspeexdec.c
deleted file mode 100755
index f3fd4d2..0000000
--- a/talk/third_party/mediastreamer/msspeexdec.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <config.h>
-
-#ifdef HAVE_SPEEX
-
-#include "msspeexdec.h"
-
-#ifdef HAVE_GLIB
-#include <gmodule.h>
-#endif
-
-extern MSFilter * ms_speex_enc_new();
-
-MSCodecInfo speex_info=
-{
- {
- "Speex codec",
- 0,
- MS_FILTER_AUDIO_CODEC,
- ms_speex_dec_new,
- "A high quality variable bit-rate codec from Jean Marc Valin and David Rowe."
- },
- ms_speex_enc_new,
- ms_speex_dec_new,
- 0, /*frame size */
- 0,
- 8000, /*minimal bitrate */
- -1, /* sampling frequency */
- 110, /* payload type */
- "speex",
- 1,
- 1
-};
-
-
-
-void ms_speex_codec_init()
-{
-
- ms_filter_register(MS_FILTER_INFO(&speex_info));
- //ms_filter_register(MS_FILTER_INFO(&speex_lbr_info));
-}
-
-#ifdef HAVE_GLIB
-gchar * g_module_check_init(GModule *module)
-{
- ms_speex_codec_init();
-
- return NULL;
-}
-#else
-gchar * g_module_check_init()
-{
- ms_speex_codec_init();
-
- return NULL;
-}
-#endif
-
-static MSSpeexDecClass * ms_speex_dec_class=NULL;
-//static MSSpeexDecClass * ms_speexnb_dec_class=NULL;
-
-MSFilter * ms_speex_dec_new()
-{
- MSSpeexDec *obj=g_new(MSSpeexDec,1);
-
- if (ms_speex_dec_class==NULL){
- ms_speex_dec_class=g_new(MSSpeexDecClass,1);
- ms_speex_dec_class_init(ms_speex_dec_class);
- }
- MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_speex_dec_class);
-
- ms_speex_dec_init(obj);
- return MS_FILTER(obj);
-}
-
-void ms_speex_dec_init(MSSpeexDec *obj)
-{
- ms_filter_init(MS_FILTER(obj));
- obj->initialized=0;
- MS_FILTER(obj)->outfifos=obj->outf;
- MS_FILTER(obj)->inqueues=obj->inq;
- obj->outf[0]=NULL;
- obj->inq[0]=NULL;
- obj->frequency=8000; /*default value */
-
-}
-
-void ms_speex_dec_init_core(MSSpeexDec *obj,const SpeexMode *mode)
-{
- int pf=1;
-
- obj->speex_state=speex_decoder_init(mode);
- speex_bits_init(&obj->bits);
- /* enable the perceptual post filter */
- speex_decoder_ctl(obj->speex_state,SPEEX_SET_PF, &pf);
-
- speex_mode_query(mode, SPEEX_MODE_FRAME_SIZE, &obj->frame_size);
-
- obj->initialized=1;
-}
-
-int ms_speex_dec_set_property(MSSpeexDec *obj, MSFilterProperty prop, int *value)
-{
- if (obj->initialized){
- /* we are called when speex is running !! forbid that! */
- ms_warning("ms_speex_dec_set_property: cannot call this function when running!");
- return -1;
- }
- switch(prop){
- case MS_FILTER_PROPERTY_FREQ:
- obj->frequency=value[0];
- break;
- }
- return 0;
-}
-
-void ms_speex_dec_setup(MSSpeexDec *obj)
-{
- const SpeexMode *mode;
- g_message("Speex decoder setup: freq=%i",obj->frequency);
- if ( obj->frequency< 16000) mode=&speex_nb_mode;
- else mode=&speex_wb_mode;
- ms_speex_dec_init_core(obj,mode);
-}
-
-void ms_speex_dec_unsetup(MSSpeexDec *obj)
-{
- ms_speex_dec_uninit_core(obj);
-}
-
-void ms_speex_dec_class_init(MSSpeexDecClass *klass)
-{
- gint frame_size=0;
-
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- /* use the largest frame size to configure fifos */
- speex_mode_query(&speex_wb_mode, SPEEX_MODE_FRAME_SIZE, &frame_size);
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_speex_dec_process;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_speex_dec_setup;
- MS_FILTER_CLASS(klass)->unsetup=(MSFilterSetupFunc)ms_speex_dec_unsetup;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_speex_dec_destroy;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_speex_dec_set_property;
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"SpeexDecoder");
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&speex_info;
- MS_FILTER_CLASS(klass)->max_foutputs=1;
- MS_FILTER_CLASS(klass)->max_qinputs=1;
- MS_FILTER_CLASS(klass)->w_maxgran=frame_size*2;
- ms_trace("ms_speex_dec_class_init: w_maxgran is %i.",MS_FILTER_CLASS(klass)->w_maxgran);
-}
-
-void ms_speex_dec_uninit_core(MSSpeexDec *obj)
-{
- speex_decoder_destroy(obj->speex_state);
- obj->initialized=0;
-}
-
-void ms_speex_dec_uninit(MSSpeexDec *obj)
-{
-
-}
-
-void ms_speex_dec_destroy(MSSpeexDec *obj)
-{
- ms_speex_dec_uninit(obj);
- g_free(obj);
-}
-
-void ms_speex_dec_process(MSSpeexDec *obj)
-{
- MSFifo *outf=obj->outf[0];
- MSQueue *inq=obj->inq[0];
- gint16 *output;
- gint gran=obj->frame_size*2;
- gint i;
- MSMessage *m;
-
- g_return_if_fail(inq!=NULL);
- g_return_if_fail(outf!=NULL);
-
- m=ms_queue_get(inq);
- g_return_if_fail(m!=NULL);
- speex_bits_reset(&obj->bits);
- ms_fifo_get_write_ptr(outf,gran,(void**)&output);
- g_return_if_fail(output!=NULL);
- if (m->data!=NULL){
-
- speex_bits_read_from(&obj->bits,m->data,m->size);
- /* decode */
- speex_decode_int(obj->speex_state,&obj->bits,(short*)output);
- }else{
- /* we have a missing packet */
- speex_decode_int(obj->speex_state,NULL,(short*)output);
- }
- ms_message_destroy(m);
-
-}
-
-#endif /* HAVE_SPEEX */
diff --git a/talk/third_party/mediastreamer/msspeexdec.h b/talk/third_party/mediastreamer/msspeexdec.h
deleted file mode 100755
index d4e745f..0000000
--- a/talk/third_party/mediastreamer/msspeexdec.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSSPEEXDEC_H
-#define MSSPEEXDEC_H
-
-#include <mscodec.h>
-#include <speex.h>
-
-struct _MSSpeexDec
-{
- MSFilter parent;
- MSQueue *inq[1]; /* speex has an input q because it can be variable bit rate */
- MSFifo *outf[1];
- void *speex_state;
- SpeexBits bits;
- int frequency;
- int frame_size;
- int initialized;
-};
-
-typedef struct _MSSpeexDec MSSpeexDec;
-
-
-struct _MSSpeexDecClass
-{
- MSFilterClass parent;
-};
-
-typedef struct _MSSpeexDecClass MSSpeexDecClass;
-
-
-#define MS_SPEEX_DEC(o) ((MSSpeexDec*)(o))
-#define MS_SPEEX_DEC_CLASS(o) ((MSSpeexDecClass*)(o))
-
-/* call this before if don't load the plugin dynamically */
-void ms_speex_codec_init();
-
-/* mediastreamer compliant constructor */
-MSFilter * ms_speex_dec_new();
-
-void ms_speex_dec_init(MSSpeexDec *obj);
-void ms_speex_dec_init_core(MSSpeexDec *obj,const SpeexMode *mode);
-void ms_speex_dec_class_init(MSSpeexDecClass *klass);
-void ms_speex_dec_uninit(MSSpeexDec *obj);
-void ms_speex_dec_uninit_core(MSSpeexDec *obj);
-
-void ms_speex_dec_process(MSSpeexDec *obj);
-void ms_speex_dec_destroy(MSSpeexDec *obj);
-
-#endif
diff --git a/talk/third_party/mediastreamer/msspeexenc.c b/talk/third_party/mediastreamer/msspeexenc.c
deleted file mode 100755
index abf976e..0000000
--- a/talk/third_party/mediastreamer/msspeexenc.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <config.h>
-
-#ifdef HAVE_SPEEX
-
-#include "msspeexenc.h"
-#include "ms.h"
-extern MSCodecInfo speex_info;
-
-static MSSpeexEncClass * ms_speex_enc_class=NULL;
-
-MSFilter * ms_speex_enc_new()
-{
- MSSpeexEnc *obj=g_new(MSSpeexEnc,1);
-
- if (ms_speex_enc_class==NULL){
- ms_speex_enc_class=g_new(MSSpeexEncClass,1);
- ms_speex_enc_class_init(ms_speex_enc_class);
- }
- MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_speex_enc_class);
- ms_speex_enc_init(MS_SPEEX_ENC(obj));
- return MS_FILTER(obj);
-}
-
-void ms_speex_enc_init(MSSpeexEnc *obj)
-{
- ms_filter_init(MS_FILTER(obj));
- MS_FILTER(obj)->infifos=obj->inf;
- MS_FILTER(obj)->outqueues=obj->outq;
- obj->inf[0]=NULL;
- obj->outq[0]=NULL;
- obj->frequency=8000;
- obj->bitrate=30000;
- obj->initialized=0;
-}
-
-void ms_speex_enc_init_core(MSSpeexEnc *obj,const SpeexMode *mode, gint bitrate)
-{
- int proc_type, proc_speed;
- gchar *proc_vendor;
- int tmp;
- int frame_size;
-
- obj->speex_state=speex_encoder_init(mode);
- speex_bits_init(&obj->bits);
-
- if (bitrate>0) {
- bitrate++;
- speex_encoder_ctl(obj->speex_state, SPEEX_SET_BITRATE, &bitrate);
- g_message("Setting speex output bitrate less or equal than %i",bitrate-1);
- }
-
- proc_speed=ms_proc_get_speed();
- proc_vendor=ms_proc_get_param("vendor_id");
- if (proc_speed<0 || proc_vendor==NULL){
- g_warning("Can't guess processor features: setting speex encoder to its lowest complexity.");
- tmp=1;
- speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp);
- }else if ((proc_speed!=-1) && (proc_speed<200)){
- g_warning("A cpu speed less than 200 Mhz is not enough: let's reduce the complexity of the speex codec.");
- tmp=1;
- speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp);
- }else if (proc_vendor!=NULL) {
- if (strncmp(proc_vendor,"GenuineIntel",strlen("GenuineIntel"))==0){
- proc_type=ms_proc_get_type();
- if (proc_type==5){
- g_warning("A pentium I is not enough fast for speex codec in normal mode: let's reduce its complexity.");
- tmp=1;
- speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp);
- }
- }
- g_free(proc_vendor);
- }
- /* guess the used input frame size */
- speex_mode_query(mode, SPEEX_MODE_FRAME_SIZE, &frame_size);
- MS_FILTER(obj)->r_mingran=frame_size*2;
- ms_trace("ms_speex_init: using frame size of %i.",MS_FILTER(obj)->r_mingran);
-
- obj->initialized=1;
-}
-
-/* must be called before the encoder is running*/
-int ms_speex_enc_set_property(MSSpeexEnc *obj,int property,int *value)
-{
- if (obj->initialized){
- /* we are called when speex is running !! forbid that! */
- ms_warning("ms_speex_enc_set_property: cannot call this function when running!");
- return -1;
- }
- switch(property){
- case MS_FILTER_PROPERTY_FREQ:
- obj->frequency=value[0];
- break;
- case MS_FILTER_PROPERTY_BITRATE: /* to specify max bitrate */
- obj->bitrate=value[0];
- break;
- }
- return 0;
-}
-
-void ms_speex_enc_setup(MSSpeexEnc *obj)
-{
- const SpeexMode *mode;
- int quality;
- g_message("Speex encoder setup: freq=%i",obj->frequency);
- if ( obj->frequency< 16000) mode=&speex_nb_mode;
- else mode=&speex_wb_mode;
- ms_speex_enc_init_core(obj,mode,obj->bitrate);
-
-}
-
-void ms_speex_enc_unsetup(MSSpeexEnc *obj)
-{
- ms_speex_enc_uninit_core(obj);
-}
-
-void ms_speex_enc_class_init(MSSpeexEncClass *klass)
-{
- gint frame_size=0;
-
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- /* we take the larger (wb) frame size */
- speex_mode_query(&speex_wb_mode, SPEEX_MODE_FRAME_SIZE, &frame_size);
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_speex_enc_process;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_speex_enc_destroy;
- MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_speex_enc_setup;
- MS_FILTER_CLASS(klass)->unsetup=(MSFilterSetupFunc)ms_speex_enc_unsetup;
- MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_speex_enc_set_property;
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"SpeexEncoder");
- MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&speex_info;
- MS_FILTER_CLASS(klass)->max_finputs=1;
- MS_FILTER_CLASS(klass)->max_qoutputs=1;
- MS_FILTER_CLASS(klass)->r_maxgran=frame_size*2;
- ms_trace("ms_speex_enc_class_init: r_maxgran is %i.",MS_FILTER_CLASS(klass)->r_maxgran);
-}
-
-void ms_speex_enc_uninit_core(MSSpeexEnc *obj)
-{
- if (obj->initialized){
- speex_encoder_destroy(obj->speex_state);
- obj->initialized=0;
- }
-}
-
-void ms_speex_enc_destroy(MSSpeexEnc *obj)
-{
- ms_speex_enc_uninit_core(obj);
- g_free(obj);
-}
-
-void ms_speex_enc_process(MSSpeexEnc *obj)
-{
- MSFifo *inf=obj->inf[0];
- MSQueue *outq=obj->outq[0];
- gint16 *input;
- gint gran=MS_FILTER(obj)->r_mingran;
- gint i;
- MSMessage *m;
-
- g_return_if_fail(inf!=NULL);
- g_return_if_fail(outq!=NULL);
-
- ms_fifo_get_read_ptr(inf,gran,(void**)&input);
- g_return_if_fail(input!=NULL);
- /* encode */
- speex_bits_reset(&obj->bits);
- speex_encode_int(obj->speex_state,(short*)input,&obj->bits);
- m=ms_message_new(speex_bits_nbytes(&obj->bits));
- m->size=speex_bits_write(&obj->bits,m->data,m->size);
- ms_queue_put(outq,m);
-}
-
-#endif /* HAVE_SPEEX */
diff --git a/talk/third_party/mediastreamer/msspeexenc.h b/talk/third_party/mediastreamer/msspeexenc.h
deleted file mode 100755
index 41655b9..0000000
--- a/talk/third_party/mediastreamer/msspeexenc.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSSPEEXENC_H
-#define MSSPEEXENC_H
-
-#include <mscodec.h>
-#include <speex.h>
-
-struct _MSSpeexEnc
-{
- MSFilter parent;
- MSFifo *inf[1];
- MSQueue *outq[1]; /* speex has an output q because it can be variable bit rate */
- void *speex_state;
- SpeexBits bits;
- int frequency;
- int bitrate;
- int initialized;
-};
-
-typedef struct _MSSpeexEnc MSSpeexEnc;
-
-
-struct _MSSpeexEncClass
-{
- MSFilterClass parent;
-};
-
-typedef struct _MSSpeexEncClass MSSpeexEncClass;
-
-
-#define MS_SPEEX_ENC(o) ((MSSpeexEnc*)(o))
-#define MS_SPEEX_ENC_CLASS(o) ((MSSpeexEncClass*)(o))
-
-/* generic constructor */
-MSFilter * ms_speex_enc_new();
-
-void ms_speex_enc_init_core(MSSpeexEnc *obj,const SpeexMode *mode, gint quality);
-void ms_speex_enc_uninit_core(MSSpeexEnc *obj);
-void ms_speex_enc_init(MSSpeexEnc *obj);
-void ms_speex_enc_class_init(MSSpeexEncClass *klass);
-
-
-void ms_speex_enc_process(MSSpeexEnc *obj);
-void ms_speex_enc_destroy(MSSpeexEnc *obj);
-
-#endif
diff --git a/talk/third_party/mediastreamer/mssync.c b/talk/third_party/mediastreamer/mssync.c
deleted file mode 100755
index 9e32a8a..0000000
--- a/talk/third_party/mediastreamer/mssync.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "mssync.h"
-#include <errno.h>
-
-/* TODO:
- -define an uninit function that free the mutex
-*/
-
-/**
- * function_name:ms_sync_get_bytes_per_tick
- * @sync: A #MSSync object.
- *
- * Returns the number of bytes per tick. This is a usefull information for sources, so
- * that they can know how much data they must deliver each time they are called.
- *
- */
-
-/* private */
-void ms_sync_init(MSSync *sync)
-{
- sync->klass=NULL;
- sync->lock=g_mutex_new();
- sync->thread_cond=g_cond_new();
- sync->stop_cond=g_cond_new();
- sync->attached_filters=NULL;
- sync->execution_list=NULL;
- sync->filters=0;
- sync->run=0;
- sync->flags=0;
- sync->samples_per_tick=0;
- sync->ticks=0;
- sync->time=0;
- sync->thread=NULL;
-}
-
-void ms_sync_class_init(MSSyncClass *klass)
-{
- klass->max_filters=0;
- klass->synchronize=NULL;
- klass->attach=ms_sync_attach_generic;
- klass->detach=ms_sync_detach_generic;
- klass->destroy=NULL;
-}
-
-/* public*/
-
-
-/**
- * ms_sync_attach:
- * @sync: A #MSSync object.
- * @f: A #MSFilter object.
- *
- * Attach a chain of filters to a synchronisation source @sync. Filter @f must be the first filter of the processing chain.
- * In order to be run, each chain of filter must be attached to a synchronisation source, that will be responsible for scheduling
- * the processing. Multiple chains can be attached to a single synchronisation.
- *
- * Returns: 0 if successfull, a negative value reprensenting the errno.h error.
- */
-int ms_sync_attach(MSSync *sync,MSFilter *f)
-{
- gint err;
- ms_sync_lock(sync);
- err=sync->klass->attach(sync,f);
- ms_sync_update(sync);
- ms_sync_unlock(sync);
- return(err);
-}
-
-int ms_sync_attach_generic(MSSync *sync,MSFilter *f)
-{
- int i;
- //printf("attr: %i\n",f->klass->attributes);
- g_return_val_if_fail(f->klass->attributes & FILTER_IS_SOURCE,-EINVAL);
- g_return_val_if_fail(sync->attached_filters!=NULL,-EFAULT);
-
-
- /* find a free place to attach*/
- for (i=0;i<sync->klass->max_filters;i++)
- {
- if (sync->attached_filters[i]==NULL)
- {
- sync->attached_filters[i]=f;
- sync->filters++;
- ms_trace("Filter succesfully attached to sync.");
- return 0;
- }
- }
- g_warning("No more link on sync !");
- return(-EMLINK);
-}
-
-/**
- * ms_sync_detach:
- * @sync: A #MSSync object.
- * @f: A #MSFilter object.
- *
- * Dettach a chain of filters to a synchronisation source. Filter @f must be the first filter of the processing chain.
- * The processing chain will no more be executed.
- *
- * Returns: 0 if successfull, a negative value reprensenting the errno.h error.
- */
-int ms_sync_detach(MSSync *sync,MSFilter *f)
-{
- gint err;
- ms_sync_lock(sync);
- err=sync->klass->detach(sync,f);
- ms_sync_update(sync);
- ms_sync_unlock(sync);
- return(err);
-}
-
-int ms_sync_detach_generic(MSSync *sync,MSFilter *f)
-{
- int i;
- g_return_val_if_fail(f->klass->attributes & FILTER_IS_SOURCE,-EINVAL);
- g_return_val_if_fail(sync->attached_filters!=NULL,-EFAULT);
- for (i=0;i<sync->filters;i++)
- {
- if (sync->attached_filters[i]==f)
- {
- sync->attached_filters[i]=NULL;
- sync->filters--;
- return 0;
- }
- }
- return(-EMLINK);
-}
-
-void ms_sync_set_samples_per_tick(MSSync *sync,gint size)
-{
- if (sync->samples_per_tick==0)
- {
- sync->samples_per_tick=size;
- g_cond_signal(sync->thread_cond);
- }
- else sync->samples_per_tick=size;
-}
-
-/* call the setup func of each filter attached to the graph */
-void ms_sync_setup(MSSync *sync)
-{
- GList *elem=sync->execution_list;
- MSFilter *f;
- while(elem!=NULL){
- f=(MSFilter*)elem->data;
- if (f->klass->setup!=NULL){
- f->klass->setup(f,sync);
- }
- elem=g_list_next(elem);
- }
-}
-
-/* call the unsetup func of each filter attached to the graph */
-void ms_sync_unsetup(MSSync *sync)
-{
- GList *elem=sync->execution_list;
- MSFilter *f;
- while(elem!=NULL){
- f=(MSFilter*)elem->data;
- if (f->klass->unsetup!=NULL){
- f->klass->unsetup(f,sync);
- }
- elem=g_list_next(elem);
- }
-}
-
-
-int ms_sync_uninit(MSSync *sync)
-{
- g_mutex_free(sync->lock);
- g_cond_free(sync->thread_cond);
- g_cond_free(sync->stop_cond);
-}
-
diff --git a/talk/third_party/mediastreamer/mssync.h b/talk/third_party/mediastreamer/mssync.h
deleted file mode 100755
index 012c068..0000000
--- a/talk/third_party/mediastreamer/mssync.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MS_SYNC_H
-#define MS_SYNC_H
-
-
-#include "msfilter.h"
-
-struct _MSSync
-{
- struct _MSSyncClass *klass;
- GMutex *lock;
- MSFilter **attached_filters; /* pointer to a table of pointer of filters*/
- GList *execution_list; /* the list of filters to be executed. This is filled with compilation */
- gint filters; /*number of filters attached to the sync */
- gint run; /* flag to indicate whether the sync must be run or not */
- GThread * thread; /* the thread ressource if this sync is run by a thread*/
- GCond *thread_cond;
- GCond *stop_cond;
- guint32 flags;
- gint interval; /* in miliseconds*/
-#define MS_SYNC_NEED_UPDATE (0x0001) /* a modification has occured in the processing chains
- attached to this sync; so the execution list has to be updated */
- guint samples_per_tick; /* number of bytes produced by sources of the processing chains*/
- guint32 ticks;
- guint32 time; /* a time since the start of the sync expressed in milisec*/
-};
-
-typedef struct _MSSync MSSync;
-
-typedef void (*MSSyncDestroyFunc)(MSSync*);
-typedef void (*MSSyncSyncFunc)(MSSync*);
-typedef int (*MSSyncAttachFunc)(MSSync*,MSFilter*);
-typedef int (*MSSyncDetachFunc)(MSSync*,MSFilter*);
-
-typedef struct _MSSyncClass
-{
- gint max_filters; /* the maximum number of filters that can be attached to this sync*/
- MSSyncSyncFunc synchronize;
- MSSyncDestroyFunc destroy;
- MSSyncAttachFunc attach;
- MSSyncDetachFunc detach;
-} MSSyncClass;
-
-/* private */
-void ms_sync_init(MSSync *sync);
-void ms_sync_class_init(MSSyncClass *klass);
-
-int ms_sync_attach_generic(MSSync *sync,MSFilter *f);
-int ms_sync_detach_generic(MSSync *sync,MSFilter *f);
-
-/* public*/
-
-#define MS_SYNC(sync) ((MSSync*)(sync))
-#define MS_SYNC_CLASS(klass) ((MSSyncClass*)(klass))
-
-#define ms_sync_synchronize(_sync) \
-do \
-{ \
- MSSync *__sync=_sync; \
- __sync->ticks++; \
- ((__sync)->klass->synchronize((__sync))); \
-}while(0)
-
-void ms_sync_setup(MSSync *sync);
-
-void ms_sync_unsetup(MSSync *sync);
-
-#define ms_sync_update(sync) (sync)->flags|=MS_SYNC_NEED_UPDATE
-
-#define ms_sync_get_samples_per_tick(sync) ((sync)->samples_per_tick)
-
-void ms_sync_set_samples_per_tick(MSSync *sync,gint size);
-
-#define ms_sync_get_tick_count(sync) ((sync)->ticks)
-
-#define ms_sync_suspend(sync) g_cond_wait((sync)->thread_cond,(sync)->lock)
-
-#define ms_sync_lock(sync) g_mutex_lock((sync)->lock)
-
-#define ms_sync_unlock(sync) g_mutex_unlock((sync)->lock)
-
-#define ms_sync_trylock(sync) g_mutex_trylock((sync)->lock)
-
-/**
- * function_name:ms_sync_attach
- * @sync: A #MSSync object.
- * @f: A #MSFilter object.
- *
- * Attach a chain of filters to a synchronisation source. Filter @f must be the first filter of the processing chain.
- *
- * Returns: 0 if successfull, a negative value reprensenting the errno.h error.
- */
-int ms_sync_attach(MSSync *sync,MSFilter *f);
-
-/**
- * ms_sync_detach:
- * @sync: A #MSSync object.
- * @f: A #MSFilter object.
- *
- * Dettach a chain of filters to a synchronisation source. Filter @f must be the first filter of the processing chain.
- * The processing chain will no more be executed.
- *
- * Returns: 0 if successfull, a negative value reprensenting the errno.h error.
- */
-int ms_sync_detach(MSSync *sync,MSFilter *f);
-
-int ms_sync_uninit(MSSync *sync);
-
-#define ms_sync_start(sync) ms_start((sync))
-#define ms_sync_stop(sync) ms_stop((sync))
-
-
-/*destroy*/
-#define ms_sync_destroy(sync) (sync)->klass->destroy((sync))
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/mstimer.c b/talk/third_party/mediastreamer/mstimer.c
deleted file mode 100755
index 1955ef2..0000000
--- a/talk/third_party/mediastreamer/mstimer.c
+++ /dev/null
@@ -1,114 +0,0 @@
- /*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "mstimer.h"
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <signal.h>
-
-static MSTimerClass *ms_timer_class=NULL;
-
-
-void ms_timer_init(MSTimer *sync)
-{
- ms_sync_init(MS_SYNC(sync));
- MS_SYNC(sync)->attached_filters=sync->filters;
- memset(sync->filters,0,MSTIMER_MAX_FILTERS*sizeof(MSFilter*));
- MS_SYNC(sync)->samples_per_tick=160;
- ms_timer_set_interval(sync,20);
- sync->state=MS_TIMER_STOPPED;
-}
-
-void ms_timer_class_init(MSTimerClass *klass)
-{
- ms_sync_class_init(MS_SYNC_CLASS(klass));
- MS_SYNC_CLASS(klass)->max_filters=MSTIMER_MAX_FILTERS;
- MS_SYNC_CLASS(klass)->synchronize=(MSSyncSyncFunc)ms_timer_synchronize;
- MS_SYNC_CLASS(klass)->destroy=(MSSyncDestroyFunc)ms_timer_destroy;
- /* no need to overload these function*/
- MS_SYNC_CLASS(klass)->attach=ms_sync_attach_generic;
- MS_SYNC_CLASS(klass)->detach=ms_sync_detach_generic;
-}
-
-void ms_timer_destroy(MSTimer *timer)
-{
- g_free(timer);
-}
-
-
-void ms_timer_synchronize(MSTimer *timer)
-{
- //printf("ticks=%i \n",MS_SYNC(timer)->ticks);
- if (timer->state==MS_TIMER_STOPPED){
- timer->state=MS_TIMER_RUNNING;
- gettimeofday(&timer->orig,NULL);
- timer->sync.time=0;
- }
- else {
- gint32 diff,time;
- struct timeval tv,cur;
-
- gettimeofday(&cur,NULL);
- time=((cur.tv_usec-timer->orig.tv_usec)/1000 ) + ((cur.tv_sec-timer->orig.tv_sec)*1000 );
- if ( (diff=time-timer->sync.time)>50){
- g_warning("Must catchup %i miliseconds.",diff);
- }
- while((diff = timer->sync.time-time) > 0)
- {
- tv.tv_sec = diff/1000;
- tv.tv_usec = (diff%1000)*1000;
- select(0,NULL,NULL,NULL,&tv);
- gettimeofday(&cur,NULL);
- time=((cur.tv_usec-timer->orig.tv_usec)/1000 ) + ((cur.tv_sec-timer->orig.tv_sec)*1000 );
- }
- }
- timer->sync.time+=timer->milisec;
- return;
-}
-
-
-MSSync *ms_timer_new()
-{
- MSTimer *timer;
-
- timer=g_malloc(sizeof(MSTimer));
- ms_timer_init(timer);
- if (ms_timer_class==NULL)
- {
- ms_timer_class=g_new(MSTimerClass,1);
- ms_timer_class_init(ms_timer_class);
- }
- MS_SYNC(timer)->klass=MS_SYNC_CLASS(ms_timer_class);
- return(MS_SYNC(timer));
-}
-
-void ms_timer_set_interval(MSTimer *timer, int milisec)
-{
-
- MS_SYNC(timer)->ticks=0;
- MS_SYNC(timer)->interval=milisec;
- timer->interval.tv_sec=milisec/1000;
- timer->interval.tv_usec=(milisec % 1000)*1000;
- timer->milisec=milisec;
-
-
-}
diff --git a/talk/third_party/mediastreamer/mstimer.h b/talk/third_party/mediastreamer/mstimer.h
deleted file mode 100755
index 5c7e8ed..0000000
--- a/talk/third_party/mediastreamer/mstimer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#ifndef MSTIMER_H
-#define MSTIMER_H
-
-#include "mssync.h"
-#include <sys/time.h>
-
-#define MSTIMER_MAX_FILTERS 10
-
-/* MSTimer derivates from MSSync base class*/
-
-typedef struct _MSTimer
-{
- /* the MSSync must be the first field of the object in order to the object mechanism to work*/
- MSSync sync;
- MSFilter *filters[MSTIMER_MAX_FILTERS];
- gint milisec; /* the interval */
- struct timeval interval;
- struct timeval orig;
- gint state;
-} MSTimer;
-
-
-typedef struct _MSTimerClass
-{
- /* the MSSyncClass must be the first field of the class in order to the class mechanism to work*/
- MSSyncClass parent_class;
-} MSTimerClass;
-
-
-/*private*/
-#define MS_TIMER_RUNNING 1
-#define MS_TIMER_STOPPED 0
-void ms_timer_init(MSTimer *sync);
-void ms_timer_class_init(MSTimerClass *sync);
-
-void ms_timer_destroy(MSTimer *timer);
-void ms_timer_synchronize(MSTimer *timer);
-
-/*public*/
-void ms_timer_set_interval(MSTimer *timer, gint milisec);
-
-/* casts a MSSync object into a MSTimer */
-#define MS_TIMER(sync) ((MSTimer*)(sync))
-/* casts a MSSync class into a MSTimer class */
-#define MS_TIMER_CLASS(klass) ((MSTimerClass*)(klass))
-
-MSSync *ms_timer_new();
-
-#endif
diff --git a/talk/third_party/mediastreamer/mstruespeechdecoder.h b/talk/third_party/mediastreamer/mstruespeechdecoder.h
deleted file mode 100755
index 6247743..0000000
--- a/talk/third_party/mediastreamer/mstruespeechdecoder.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- Copyright (C) 2003 Robert W. Brewer <rbrewer at op.net>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSTRUESPEECHDECODER_H
-#define MSTRUESPEECHDECODER_H
-
-#include "msfilter.h"
-#include "mstruespeechencoder.h"
-
-
-
-typedef struct _MSTrueSpeechDecoder
-{
- /* the MSTrueSpeechDecoder derives from MSFilter, so the MSFilter
- object MUST be the first of the MSTrueSpeechDecoder object
- in order for the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT];
- MSFifo *f_outputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT];
- Win32Codec* codec;
-} MSTrueSpeechDecoder;
-
-typedef struct _MSTrueSpeechDecoderClass
-{
- /* the MSTrueSpeechDecoder derives from MSFilter,
- so the MSFilter class MUST be the first of the MSTrueSpechDecoder
- class
- in order for the class mechanism to work*/
- MSFilterClass parent_class;
- Win32CodecDriver* driver;
-} MSTrueSpeechDecoderClass;
-
-/* PUBLIC */
-#define MS_TRUESPEECHDECODER(filter) ((MSTrueSpechMDecoder*)(filter))
-#define MS_TRUESPEECHDECODER_CLASS(klass) ((MSTrueSpeechDecoderClass*)(klass))
-MSFilter * ms_truespeechdecoder_new(void);
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/mstruespeechencoder.h b/talk/third_party/mediastreamer/mstruespeechencoder.h
deleted file mode 100755
index 04e40bb..0000000
--- a/talk/third_party/mediastreamer/mstruespeechencoder.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- Copyright (C) 2003 Robert W. Brewer <rbrewer at op.net>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#ifndef MSTRUESPEECHENCODER_H
-#define MSTRUESPEECHENCODER_H
-
-#include "msfilter.h"
-#include <win32codec.h>
-
-
-#define MS_TRUESPEECH_CODEC_MAX_IN_OUT 1 /* max inputs/outputs per filter*/
-
-#define TRUESPEECH_FORMAT_TAG 0x22
-#define TRUESPEECH_DLL "tssoft32.acm"
-
-typedef struct _MSTrueSpeechEncoder
-{
- /* the MSTrueSpeechEncoder derives from MSFilter, so the MSFilter
- object MUST be the first of the MSTrueSpeechEncoder object
- in order for the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT];
- MSFifo *f_outputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT];
- Win32Codec* codec;
-} MSTrueSpeechEncoder;
-
-typedef struct _MSTrueSpeechEncoderClass
-{
- /* the MSTrueSpeechEncoder derives from MSFilter,
- so the MSFilter class MUST be the first of the MSTrueSpechEncoder
- class
- in order for the class mechanism to work*/
- MSFilterClass parent_class;
- Win32CodecDriver* driver;
-} MSTrueSpeechEncoderClass;
-
-/* PUBLIC */
-#define MS_TRUESPEECHENCODER(filter) ((MSTrueSpechMEncoder*)(filter))
-#define MS_TRUESPEECHENCODER_CLASS(klass) ((MSTrueSpeechEncoderClass*)(klass))
-MSFilter * ms_truespeechencoder_new(void);
-
-/* for internal use only */
-WAVEFORMATEX* ms_truespeechencoder_wf_create();
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msutils.h b/talk/third_party/mediastreamer/msutils.h
deleted file mode 100755
index 012b87d..0000000
--- a/talk/third_party/mediastreamer/msutils.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-#ifndef MSUTILS_H
-#define MSUTILS_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#else
-#include <uglib.h>
-#endif
-#include <errno.h>
-
-#ifndef ENODATA
-/* this is for freeBSD .*/
-#define ENODATA EWOULDBLOCK
-#endif
-
-#ifdef MS_DEBUG
-
-#define ms_trace g_message
-
-#else
-
-#define ms_trace(...)
-#endif
-
-#define ms_warning g_warning
-#define ms_error g_error
-
-#define VIDEO_SIZE_CIF_W 352
-#define VIDEO_SIZE_CIF_H 288
-#define VIDEO_SIZE_QCIF_W 176
-#define VIDEO_SIZE_QCIF_H 144
-#define VIDEO_SIZE_4CIF_W 704
-#define VIDEO_SIZE_4CIF_H 576
-#define VIDEO_SIZE_MAX_W VIDEO_SIZE_4CIF_W
-#define VIDEO_SIZE_MAX_H VIDEO_SIZE_4CIF_H
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/msv4l.h b/talk/third_party/mediastreamer/msv4l.h
deleted file mode 100755
index e19ac9e..0000000
--- a/talk/third_party/mediastreamer/msv4l.h
+++ /dev/null
@@ -1,96 +0,0 @@
- /*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSV4L_H
-#define MSV4L_H
-
-#include <msvideosource.h>
-#include <sys/types.h>
-#include <linux/videodev.h>
-
-struct _MSV4l
-{
- MSVideoSource parent;
- int fd;
- char *device;
- struct video_capability cap;
- struct video_channel channel;
- struct video_window win;
- struct video_picture pict;
- struct video_mmap vmap;
- struct video_mbuf vmbuf;
- struct video_capture vcap;
- gint bsize;
- gint use_mmap;
- gint frame;
- guint query_frame;
- gchar *mmapdbuf; /* the mmap'd buffer */
- MSBuffer img[VIDEO_MAX_FRAME]; /* the buffer wrappers used for mmaps */
- gint width; /* the capture image size - can be cropped to output size */
- gint height;
- MSBuffer *allocdbuf; /* the buffer allocated for read() and mire */
- gint count;
- MSBuffer *image_grabbed;
- GCond *cond;
- GCond *stopcond;
- GThread *v4lthread;
- gboolean grab_image;
- gboolean thread_run;
- gboolean thread_exited;
-};
-
-typedef struct _MSV4l MSV4l;
-
-
-struct _MSV4lClass
-{
- MSVideoSourceClass parent_class;
-
-};
-
-typedef struct _MSV4lClass MSV4lClass;
-
-
-/* PUBLIC API */
-#define MS_V4L(v) ((MSV4l*)(v))
-#define MS_V4L_CLASS(k) ((MSV4lClass*)(k))
-MSFilter * ms_v4l_new();
-
-void ms_v4l_start(MSV4l *obj);
-void ms_v4l_stop(MSV4l *obj);
-int ms_v4l_set_device(MSV4l *f, const gchar *device);
-gint ms_v4l_get_width(MSV4l *v4l);
-gint ms_v4l_get_height(MSV4l *v4l);
-void ms_v4l_set_size(MSV4l *v4l, gint w, gint h);
-
-/* PRIVATE API */
-void ms_v4l_init(MSV4l *obj);
-void ms_v4l_class_init(MSV4lClass *klass);
-int v4l_configure(MSV4l *f);
-
-void v4l_process(MSV4l *obj);
-
-void ms_v4l_uninit(MSV4l *obj);
-
-void ms_v4l_destroy(MSV4l *obj);
-
-extern MSFilterInfo v4l_info;
-
-#endif
diff --git a/talk/third_party/mediastreamer/msvideosource.h b/talk/third_party/mediastreamer/msvideosource.h
deleted file mode 100755
index 9a27f83..0000000
--- a/talk/third_party/mediastreamer/msvideosource.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSVIDEOSOURCE_H
-#define MSVIDEOSOURCE_H
-
-
-#include "msfilter.h"
-
-/* this is the video input abstract class */
-
-#define MSVIDEOSOURCE_MAX_OUTPUTS 1 /* max output per filter*/
-
-typedef struct _MSVideoSource
-{
- /* the MSVideoSource derivates from MSFilter, so the MSFilter object MUST be the first of the MSVideoSource object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSQueue *outputs[MSVIDEOSOURCE_MAX_OUTPUTS];
- gchar *dev_name;
- gint width, height;
- gchar *format;
- gint frame_rate;
- gint frame_rate_base;
-} MSVideoSource;
-
-typedef struct _MSVideoSourceClass
-{
- /* the MSVideoSource derivates from MSFilter, so the MSFilter class MUST be the first of the MSVideoSource class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
- gint (*set_device)(MSVideoSource *s, const gchar *name);
- void (*start)(MSVideoSource *s);
- void (*stop)(MSVideoSource *s);
- void (*set_size)(MSVideoSource *s, gint width, gint height);
- void (*set_frame_rate)(MSVideoSource *s, gint frame_rate, gint frame_rate_base);
-} MSVideoSourceClass;
-
-/* PUBLIC */
-void ms_video_source_register_all();
-int ms_video_source_set_device(MSVideoSource *f, const gchar *device);
-gchar* ms_video_source_get_device_name(MSVideoSource *f);
-void ms_video_source_start(MSVideoSource *f);
-void ms_video_source_stop(MSVideoSource *f);
-void ms_video_source_set_size(MSVideoSource *f, gint width, gint height);
-void ms_video_source_set_frame_rate(MSVideoSource *f, gint frame_rate, gint frame_rate_base);
-gchar* ms_video_source_get_format(MSVideoSource *f);
-
-#define MS_VIDEO_SOURCE(obj) ((MSVideoSource*)(obj))
-#define MS_VIDEO_SOURCE_CLASS(klass) ((MSVideoSourceClass*)(klass))
-
-
-/* FOR INTERNAL USE*/
-void ms_video_source_init(MSVideoSource *f);
-void ms_video_source_class_init(MSVideoSourceClass *klass);
-
-#endif
diff --git a/talk/third_party/mediastreamer/mswrite.c b/talk/third_party/mediastreamer/mswrite.c
deleted file mode 100755
index 178e294..0000000
--- a/talk/third_party/mediastreamer/mswrite.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "mswrite.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <errno.h>
-
-static MSWriteClass *ms_write_class=NULL;
-
-MSFilter * ms_write_new(char *name)
-{
- MSWrite *r;
- int fd=-1;
-
- r=g_new(MSWrite,1);
- ms_write_init(r);
- if (ms_write_class==NULL)
- {
- ms_write_class=g_new(MSWriteClass,1);
- ms_write_class_init(ms_write_class);
- }
- MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_write_class);
- if ((name!=NULL) && (strlen(name)!=0))
- {
- fd=open(name,O_WRONLY | O_CREAT | O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (fd<0) g_error("ms_write_new: failed to open %s.\n",name);
- }
- r->fd=fd;
- return(MS_FILTER(r));
-}
-
-
-/* FOR INTERNAL USE*/
-void ms_write_init(MSWrite *r)
-{
- ms_filter_init(MS_FILTER(r));
- MS_FILTER(r)->infifos=r->f_inputs;
- MS_FILTER(r)->inqueues=r->q_inputs;
- MS_FILTER(r)->r_mingran=MSWRITE_MIN_GRAN;
- memset(r->f_inputs,0,sizeof(MSFifo*)*MSWRITE_MAX_INPUTS);
- memset(r->q_inputs,0,sizeof(MSQueue*)*MSWRITE_MAX_INPUTS);
- r->fd=-1;
-}
-
-void ms_write_class_init(MSWriteClass *klass)
-{
- ms_filter_class_init(MS_FILTER_CLASS(klass));
- ms_filter_class_set_name(MS_FILTER_CLASS(klass),"dskwriter");
- MS_FILTER_CLASS(klass)->max_finputs=MSWRITE_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->max_qinputs=MSWRITE_MAX_INPUTS;
- MS_FILTER_CLASS(klass)->r_maxgran=MSWRITE_DEF_GRAN;
- MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_write_destroy;
- MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_write_process;
-}
-
-void ms_write_process(MSWrite *r)
-{
- MSFifo *f;
- MSQueue *q;
- MSMessage *buf=NULL;
- int i,j,err1,err2;
- gint gran=ms_filter_get_mingran(MS_FILTER(r));
- void *p;
-
- /* process output fifos*/
- for (i=0,j=0;(i<MS_FILTER(r)->klass->max_finputs)&&(j<MS_FILTER(r)->finputs);i++)
- {
- f=r->f_inputs[i];
- if (f!=NULL)
- {
- if ( (err1=ms_fifo_get_read_ptr(f,gran,&p))>0 )
- {
-
- err2=write(r->fd,p,gran);
- if (err2<0) g_warning("ms_write_process: failed to write: %s.\n",strerror(errno));
- }
- j++;
- }
- }
- /* process output queues*/
- for (i=0,j=0;(i<MS_FILTER(r)->klass->max_qinputs)&&(j<MS_FILTER(r)->qinputs);i++)
- {
- q=r->q_inputs[i];
- if (q!=NULL)
- {
- while ( (buf=ms_queue_get(q))!=NULL ){
- write(r->fd,buf->data,buf->size);
- j++;
- ms_message_destroy(buf);
- }
- }
- }
-}
-
-void ms_write_destroy( MSWrite *obj)
-{
- if (obj->fd!=0) close(obj->fd);
- g_free(obj);
-}
-
diff --git a/talk/third_party/mediastreamer/mswrite.h b/talk/third_party/mediastreamer/mswrite.h
deleted file mode 100755
index cd766d1..0000000
--- a/talk/third_party/mediastreamer/mswrite.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef MSWRITE_H
-#define MSWRITE_H
-
-#include "msfilter.h"
-
-
-/*this is the class that implements writing reading sink filter*/
-
-#define MSWRITE_MAX_INPUTS 1 /* max output per filter*/
-
-#define MSWRITE_DEF_GRAN 512 /* the default granularity*/
-#define MSWRITE_MIN_GRAN 64
-
-typedef struct _MSWrite
-{
- /* the MSWrite derivates from MSFilter, so the MSFilter object MUST be the first of the MSWrite object
- in order to the object mechanism to work*/
- MSFilter filter;
- MSFifo *f_inputs[MSWRITE_MAX_INPUTS];
- MSQueue *q_inputs[MSWRITE_MAX_INPUTS];
- gint fd; /* the file descriptor of the file being written*/
-} MSWrite;
-
-typedef struct _MSWriteClass
-{
- /* the MSWrite derivates from MSFilter, so the MSFilter class MUST be the first of the MSWrite class
- in order to the class mechanism to work*/
- MSFilterClass parent_class;
-} MSWriteClass;
-
-/* PUBLIC */
-#define MS_WRITE(filter) ((MSWrite*)(filter))
-#define MS_WRITE_CLASS(klass) ((MSWriteClass*)(klass))
-MSFilter * ms_write_new(char *name);
-
-/* FOR INTERNAL USE*/
-void ms_write_init(MSWrite *r);
-void ms_write_class_init(MSWriteClass *klass);
-void ms_write_destroy( MSWrite *obj);
-void ms_write_process(MSWrite *r);
-
-#endif
-
diff --git a/talk/third_party/mediastreamer/osscard.c b/talk/third_party/mediastreamer/osscard.c
deleted file mode 100755
index 636c579..0000000
--- a/talk/third_party/mediastreamer/osscard.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include "osscard.h"
-
-#include "msossread.h"
-#include "msosswrite.h"
-
-#ifdef HAVE_SYS_SOUNDCARD_H
-#include <sys/soundcard.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/time.h>
-
-#if 0
-void * oss_thread(OssCard *obj)
-{
- gint i;
- gint err;
- g_message("oss_thread: starting **********");
- while(1){
- for(i=0;i<OSS_CARD_BUFFERS;i++){
- g_mutex_lock(obj->lock);
- if (obj->ref==0){
- g_cond_signal(obj->cond);
- g_mutex_unlock(obj->lock);
- g_thread_exit(NULL);
- }
- g_mutex_unlock(obj->lock);
- obj->readindex=i;
-
- err=read(obj->fd,obj->readbuf[i],SND_CARD(obj)->bsize);
- if (err<0) g_warning("oss_thread: read() error:%s.",strerror(errno));
- obj->writeindex=i;
- write(obj->fd,obj->writebuf[i],SND_CARD(obj)->bsize);
- memset(obj->writebuf[i],0,SND_CARD(obj)->bsize);
- }
- }
-}
-#endif
-int oss_open(OssCard *obj, int bits,int stereo, int rate)
-{
- int fd;
- int p=0,cond=0;
- int i=0;
- int min_size=0,blocksize=512;
- int err;
-
- //g_message("opening sound device");
- fd=open(obj->dev_name,O_RDWR|O_NONBLOCK);
- if (fd<0) return -EWOULDBLOCK;
- /* unset nonblocking mode */
- /* We wanted non blocking open but now put it back to normal ; thanks Xine !*/
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
-
- /* reset is maybe not needed but takes time*/
- /*ioctl(fd, SNDCTL_DSP_RESET, 0); */
-
-
-#ifdef WORDS_BIGENDIAN
- p=AFMT_U16_BE;
-#else
- p=AFMT_U16_LE;
-#endif
-
- err=ioctl(fd,SNDCTL_DSP_SETFMT,&p);
- if (err<0){
- g_warning("oss_open: can't set sample format:%s.",strerror(errno));
- }
-
-
- p = bits; /* 16 bits */
- err=ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &p);
- if (err<0){
- g_warning("oss_open: can't set sample size to %i:%s.",bits,strerror(errno));
- }
-
- p = rate; /* rate in khz*/
- err=ioctl(fd, SNDCTL_DSP_SPEED, &p);
- if (err<0){
- g_warning("oss_open: can't set sample rate to %i:%s.",rate,strerror(errno));
- }
-
- p = stereo; /* stereo or not */
- err=ioctl(fd, SNDCTL_DSP_STEREO, &p);
- if (err<0){
- g_warning("oss_open: can't set mono/stereo mode:%s.",strerror(errno));
- }
-
- if (rate==16000) blocksize=4096; /* oss emulation is not very good at 16khz */
- else blocksize=blocksize*(rate/8000);
- ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
-
- /* try to subdivide BLKSIZE to reach blocksize if necessary */
- if (min_size>blocksize)
- {
- cond=1;
- p=min_size/blocksize;
- while(cond)
- {
- i=ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &p);
- //printf("SUB_DIVIDE said error=%i,errno=%i\n",i,errno);
- if ((i==0) || (p==1)) cond=0;
- else p=p/2;
- }
- }
- ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
- if (min_size>blocksize)
- {
- g_warning("dsp block size set to %i.",min_size);
- }else{
- /* no need to access the card with less latency than needed*/
- min_size=blocksize;
- }
-
- g_message("dsp blocksize is %i.",min_size);
-
- /* start recording !!! Alex */
- {
- int fl,res;
-
- fl=PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT;
- res=ioctl(fd, SNDCTL_DSP_SETTRIGGER, &fl);
- if (res<0) g_warning("OSS_TRIGGER: %s",strerror(errno));
- }
-
- obj->fd=fd;
- obj->readpos=0;
- obj->writepos=0;
- SND_CARD(obj)->bits=bits;
- SND_CARD(obj)->stereo=stereo;
- SND_CARD(obj)->rate=rate;
- SND_CARD(obj)->bsize=min_size;
- return fd;
-}
-
-int oss_card_probe(OssCard *obj,int bits,int stereo,int rate)
-{
-
- int fd;
- int p=0,cond=0;
- int i=0;
- int min_size=0,blocksize=512;
-
- if (obj->fd>0) return SND_CARD(obj)->bsize;
- fd=open(obj->dev_name,O_RDWR|O_NONBLOCK);
- if (fd<0) {
- g_warning("oss_card_probe: can't open %s: %s.",obj->dev_name,strerror(errno));
- return -1;
- }
- ioctl(fd, SNDCTL_DSP_RESET, 0);
-
- p = bits; /* 16 bits */
- ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &p);
-
- p = stereo; /* number of channels */
- ioctl(fd, SNDCTL_DSP_CHANNELS, &p);
-
- p = rate; /* rate in khz*/
- ioctl(fd, SNDCTL_DSP_SPEED, &p);
-
- ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
-
- /* try to subdivide BLKSIZE to reach blocksize if necessary */
- if (min_size>blocksize)
- {
- cond=1;
- p=min_size/blocksize;
- while(cond)
- {
- i=ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &p);
- //printf("SUB_DIVIDE said error=%i,errno=%i\n",i,errno);
- if ((i==0) || (p==1)) cond=0;
- else p=p/2;
- }
- }
- ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
- if (min_size>blocksize)
- {
- g_warning("dsp block size set to %i.",min_size);
- }else{
- /* no need to access the card with less latency than needed*/
- min_size=blocksize;
- }
- close(fd);
- return min_size;
-}
-
-
-int oss_card_open(OssCard *obj,int bits,int stereo,int rate)
-{
- int fd;
- obj->ref++;
- if (obj->fd==0){
- fd=oss_open(obj,bits,stereo,rate);
- if (fd<0) {
- obj->fd=0;
- obj->ref--;
- return -1;
- }
- }
-
- obj->readbuf=g_malloc0(SND_CARD(obj)->bsize);
- obj->writebuf=g_malloc0(SND_CARD(obj)->bsize);
-
- SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
- return 0;
-}
-
-void oss_card_close(OssCard *obj)
-{
- int i;
- obj->ref--;
- if (obj->ref==0) {
- close(obj->fd);
- obj->fd=0;
- SND_CARD(obj)->flags&=~SND_CARD_FLAGS_OPENED;
- g_free(obj->readbuf);
- obj->readbuf=NULL;
- g_free(obj->writebuf);
- obj->writebuf=NULL;
-
- }
-}
-
-void oss_card_destroy(OssCard *obj)
-{
- snd_card_uninit(SND_CARD(obj));
- g_free(obj->dev_name);
- g_free(obj->mixdev_name);
- if (obj->readbuf!=NULL) g_free(obj->readbuf);
- if (obj->writebuf!=NULL) g_free(obj->writebuf);
-}
-
-gboolean oss_card_can_read(OssCard *obj)
-{
- struct timeval tout={0,0};
- int err;
- fd_set fdset;
- if (obj->readpos!=0) return TRUE;
- FD_ZERO(&fdset);
- FD_SET(obj->fd,&fdset);
- err=select(obj->fd+1,&fdset,NULL,NULL,&tout);
- if (err>0) return TRUE;
- else return FALSE;
-}
-
-int oss_card_read(OssCard *obj,char *buf,int size)
-{
- int err;
- gint bsize=SND_CARD(obj)->bsize;
- if (size<bsize){
- gint canread=MIN(bsize-obj->readpos,size);
- if (obj->readpos==0){
- err=read(obj->fd,obj->readbuf,bsize);
- if (err<0) {
- g_warning("oss_card_read: read() failed:%s.",strerror(errno));
- return -1;
- }
- }
-
- memcpy(buf,&obj->readbuf[obj->readpos],canread);
- obj->readpos+=canread;
- if (obj->readpos>=bsize) obj->readpos=0;
- return canread;
- }else{
- err=read(obj->fd,buf,size);
- if (err<0) {
- g_warning("oss_card_read: read-2() failed:%s.",strerror(errno));
- }
- return err;
- }
-
-}
-
-int oss_card_write(OssCard *obj,char *buf,int size)
-{
- int err;
- gint bsize=SND_CARD(obj)->bsize;
-
- if (size<bsize){
- gint canwrite;
- canwrite=MIN(bsize-obj->writepos,size);
- memcpy(&obj->writebuf[obj->writepos],buf,canwrite);
- obj->writepos+=canwrite;
- if (obj->writepos>=bsize){
- err=write(obj->fd,obj->writebuf,bsize);
- obj->writepos=0;
- }
- return canwrite;
- }else{
- return write(obj->fd,buf,bsize);
- }
-}
-
-void oss_card_set_level(OssCard *obj,gint way,gint a)
-{
- int p,mix_fd;
- int osscmd;
- g_return_if_fail(obj->mixdev_name!=NULL);
-#ifdef HAVE_SYS_SOUNDCARD_H
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- osscmd=SOUND_MIXER_VOLUME;
- break;
- case SND_CARD_LEVEL_INPUT:
- osscmd=SOUND_MIXER_IGAIN;
- break;
- case SND_CARD_LEVEL_OUTPUT:
- osscmd=SOUND_MIXER_PCM;
- break;
- default:
- g_warning("oss_card_set_level: unsupported command.");
- return;
- }
- p=(((int)a)<<8 | (int)a);
- mix_fd = open(obj->mixdev_name, O_WRONLY);
- ioctl(mix_fd,MIXER_WRITE(osscmd), &p);
- close(mix_fd);
-#endif
-}
-
-gint oss_card_get_level(OssCard *obj,gint way)
-{
- int p=0,mix_fd;
- int osscmd;
- g_return_if_fail(obj->mixdev_name!=NULL);
-#ifdef HAVE_SYS_SOUNDCARD_H
- switch(way){
- case SND_CARD_LEVEL_GENERAL:
- osscmd=SOUND_MIXER_VOLUME;
- break;
- case SND_CARD_LEVEL_INPUT:
- osscmd=SOUND_MIXER_IGAIN;
- break;
- case SND_CARD_LEVEL_OUTPUT:
- osscmd=SOUND_MIXER_PCM;
- break;
- default:
- g_warning("oss_card_get_level: unsupported command.");
- return -1;
- }
- mix_fd = open(obj->mixdev_name, O_RDONLY);
- ioctl(mix_fd,MIXER_READ(SOUND_MIXER_VOLUME), &p);
- close(mix_fd);
-#endif
- return p>>8;
-}
-
-void oss_card_set_source(OssCard *obj,int source)
-{
- gint p=0;
- gint mix_fd;
- g_return_if_fail(obj->mixdev_name!=NULL);
-#ifdef HAVE_SYS_SOUNDCARD_H
- if (source == 'c')
- p = 1 << SOUND_MIXER_CD;
- if (source == 'l')
- p = 1 << SOUND_MIXER_LINE;
- if (source == 'm')
- p = 1 << SOUND_MIXER_MIC;
-
-
- mix_fd = open(obj->mixdev_name, O_WRONLY);
- ioctl(mix_fd, SOUND_MIXER_WRITE_RECSRC, &p);
- close(mix_fd);
-#endif
-}
-
-MSFilter *oss_card_create_read_filter(OssCard *card)
-{
- MSFilter *f=ms_oss_read_new();
- ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index);
- return f;
-}
-
-MSFilter *oss_card_create_write_filter(OssCard *card)
-{
- MSFilter *f=ms_oss_write_new();
- ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index);
- return f;
-}
-
-
-SndCard * oss_card_new(char *devname, char *mixdev_name)
-{
- OssCard * obj= g_new0(OssCard,1);
- SndCard *base= SND_CARD(obj);
- snd_card_init(base);
- obj->dev_name=g_strdup(devname);
- obj->mixdev_name=g_strdup( mixdev_name);
-#ifdef HAVE_GLIB
- base->card_name=g_strdup_printf("%s (Open Sound System)",devname);
-#else
- base->card_name=malloc(100);
- snprintf(base->card_name, 100, "%s (Open Sound System)",devname);
-#endif
- base->_probe=(SndCardOpenFunc)oss_card_probe;
- base->_open_r=(SndCardOpenFunc)oss_card_open;
- base->_open_w=(SndCardOpenFunc)oss_card_open;
- base->_can_read=(SndCardPollFunc)oss_card_can_read;
- base->_read=(SndCardIOFunc)oss_card_read;
- base->_write=(SndCardIOFunc)oss_card_write;
- base->_close_r=(SndCardCloseFunc)oss_card_close;
- base->_close_w=(SndCardCloseFunc)oss_card_close;
- base->_set_rec_source=(SndCardMixerSetRecSourceFunc)oss_card_set_source;
- base->_set_level=(SndCardMixerSetLevelFunc)oss_card_set_level;
- base->_get_level=(SndCardMixerGetLevelFunc)oss_card_get_level;
- base->_destroy=(SndCardDestroyFunc)oss_card_destroy;
- base->_create_read_filter=(SndCardCreateFilterFunc)oss_card_create_read_filter;
- base->_create_write_filter=(SndCardCreateFilterFunc)oss_card_create_write_filter;
- return base;
-}
-
-#define DSP_NAME "/dev/dsp"
-#define MIXER_NAME "/dev/mixer"
-
-gint oss_card_manager_init(SndCardManager *manager, gint tabindex)
-{
- gchar *devname;
- gchar *mixername;
- gint devindex=0;
- gint found=0;
-
- /* search for /dev/dsp and /dev/mixer */
-#ifdef HAVE_GLIB
- if (g_file_test(DSP_NAME,G_FILE_TEST_EXISTS)){
- tabindex++;
- devindex++;
- manager->cards[0]=oss_card_new(DSP_NAME,MIXER_NAME);
- manager->cards[0]->index=0;
- found++;
- g_message("Found /dev/dsp.");
- }
- for (;tabindex<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){
- devname=g_strdup_printf("%s%i",DSP_NAME,devindex);
- mixername=g_strdup_printf("%s%i",MIXER_NAME,devindex);
- if (g_file_test(devname,G_FILE_TEST_EXISTS)){
- manager->cards[tabindex]=oss_card_new(devname,mixername);
- manager->cards[tabindex]->index=tabindex;
- tabindex++;
- found++;
- }
- g_free(devname);
- g_free(mixername);
- }
-#else
- if (access(DSP_NAME,F_OK)==0){
- tabindex++;
- devindex++;
- manager->cards[0]=oss_card_new(DSP_NAME,MIXER_NAME);
- manager->cards[0]->index=0;
- found++;
- g_message("Found /dev/dsp.");
- }
- for (;tabindex<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){
- devname=malloc(100);
- snprintf(devname, 100, "%s%i",DSP_NAME,devindex);
- mixername=malloc(100);
- snprintf(mixername, 100, "%s%i",MIXER_NAME,devindex);
-
- if (access(devname,F_OK)==0){
- manager->cards[tabindex]=oss_card_new(devname,mixername);
- manager->cards[tabindex]->index=tabindex;
- tabindex++;
- found++;
- }
- g_free(devname);
- g_free(mixername);
- }
-#endif
- if (tabindex==0) g_warning("No sound cards found !");
- return found;
-}
-
-
-#endif
diff --git a/talk/third_party/mediastreamer/osscard.h b/talk/third_party/mediastreamer/osscard.h
deleted file mode 100755
index 30b96c2..0000000
--- a/talk/third_party/mediastreamer/osscard.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-/* An implementation of SndCard : the OssCard */
-
-#ifndef OSS_CARD_H
-#define OSS_CARD_H
-
-#include "sndcard.h"
-
-#define OSS_CARD_BUFFERS 3
-struct _OssCard
-{
- SndCard parent;
- gchar *dev_name; /* /dev/dsp0 for example */
- gchar *mixdev_name; /* /dev/mixer0 for example */
- gint fd; /* the file descriptor of the open soundcard, 0 if not open*/
- gint ref;
- gchar *readbuf;
- gint readpos;
- gchar *writebuf;
- gint writepos;
-};
-
-typedef struct _OssCard OssCard;
-
-SndCard * oss_card_new(char *devname, char *mixdev_name);
-
-typedef OssCard HpuxSndCard;
-
-#endif
diff --git a/talk/third_party/mediastreamer/sndcard.c b/talk/third_party/mediastreamer/sndcard.c
deleted file mode 100755
index ada3e6d..0000000
--- a/talk/third_party/mediastreamer/sndcard.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-#include "sndcard.h"
-#include "msfilter.h"
-
-void snd_card_init(SndCard *obj)
-{
- memset(obj,0,sizeof(SndCard));
-}
-
-void snd_card_uninit(SndCard *obj)
-{
- if (obj->card_name!=NULL) g_free(obj->card_name);
-}
-
-const gchar *snd_card_get_identifier(SndCard *obj)
-{
- return obj->card_name;
-}
-
-int snd_card_open_r(SndCard *obj, int bits, int stereo, int rate)
-{
- g_return_val_if_fail(obj->_open_r!=NULL,-1);
- g_message("Opening sound card [%s] in capture mode with stereo=%i,rate=%i,bits=%i",obj->card_name,stereo,rate,bits);
- return obj->_open_r(obj,bits,stereo,rate);
-}
-int snd_card_open_w(SndCard *obj, int bits, int stereo, int rate)
-{
- g_return_val_if_fail(obj->_open_w!=NULL,-1);
- g_message("Opening sound card [%s] in playback mode with stereo=%i,rate=%i,bits=%i",obj->card_name,stereo,rate,bits);
- return obj->_open_w(obj,bits,stereo,rate);
-}
-
-gboolean snd_card_can_read(SndCard *obj){
- g_return_val_if_fail(obj->_can_read!=NULL,-1);
- return obj->_can_read(obj);
-}
-
-void snd_card_set_blocking_mode(SndCard *obj,gboolean yesno){
- g_return_if_fail(obj->_set_blocking_mode!=NULL);
- obj->_set_blocking_mode(obj,yesno);
-}
-
-int snd_card_read(SndCard *obj,char *buffer,int size)
-{
- g_return_val_if_fail(obj->_read!=NULL,-1);
- return obj->_read(obj,buffer,size);
-}
-int snd_card_write(SndCard *obj,char *buffer,int size)
-{
- g_return_val_if_fail(obj->_write!=NULL,-1);
- return obj->_write(obj,buffer,size);
-}
-
-int snd_card_get_bsize(SndCard *obj)
-{
- if (obj->flags & SND_CARD_FLAGS_OPENED){
- return obj->bsize;
- }
- return -1;
-}
-
-void snd_card_close_r(SndCard *obj)
-{
- g_return_if_fail(obj->_close_r!=NULL);
- g_message("Closing reading channel of soundcard.");
- obj->_close_r(obj);
-}
-
-void snd_card_close_w(SndCard *obj)
-{
- g_return_if_fail(obj->_close_w!=NULL);
- g_message("Closing writing channel of soundcard.");
- obj->_close_w(obj);
-}
-
-gint snd_card_probe(SndCard *obj,int bits, int stereo, int rate)
-{
- g_return_val_if_fail(obj->_probe!=NULL,-1);
- return obj->_probe(obj,bits,stereo,rate);
-}
-
-void snd_card_set_rec_source(SndCard *obj, int source)
-{
- g_return_if_fail(obj->_set_rec_source!=NULL);
- obj->_set_rec_source(obj,source);
-}
-
-void snd_card_set_level(SndCard *obj, int way, int level)
-{
- g_return_if_fail(obj->_set_level!=NULL);
- obj->_set_level(obj,way,level);
-}
-
-gint snd_card_get_level(SndCard *obj,int way)
-{
- g_return_val_if_fail(obj->_get_level!=NULL,-1);
- return obj->_get_level(obj,way);
-}
-
-
-MSFilter * snd_card_create_read_filter(SndCard *obj)
-{
- g_return_val_if_fail(obj->_create_read_filter!=NULL,NULL);
- return obj->_create_read_filter(obj);
-}
-MSFilter * snd_card_create_write_filter(SndCard *obj)
-{
- g_return_val_if_fail(obj->_create_write_filter!=NULL,NULL);
- return obj->_create_write_filter(obj);
-}
-
-
-#ifdef HAVE_SYS_AUDIO_H
-gint sys_audio_manager_init(SndCardManager *manager, gint index)
-{
- /* this is a quick shortcut, as multiple soundcards on HPUX does not happen
- very often... */
- manager->cards[index]=hpux_snd_card_new("/dev/audio","/dev/audio");
- return 1;
-}
-
-#endif
-
-#include "osscard.h"
-#include "alsacard.h"
-#include "jackcard.h"
-
-void snd_card_manager_init(SndCardManager *manager)
-{
- gint index=0;
- gint tmp=0;
- memset(manager,0,sizeof(SndCardManager));
- #ifdef HAVE_SYS_SOUNDCARD_H
- tmp=oss_card_manager_init(manager,index);
- index+=tmp;
- if (index>=MAX_SND_CARDS) return;
- #endif
- #ifdef __ALSA_ENABLED__
- tmp=alsa_card_manager_init(manager,index);
- index+=tmp;
- if (index>=MAX_SND_CARDS) return;
- #endif
- #ifdef __JACK_ENABLED__
- tmp=jack_card_manager_init(manager,index);
- index+=tmp;
- if (index>=MAX_SND_CARDS) return;
- #endif
- #ifdef HAVE_SYS_AUDIO_H
- tmp=sys_audio_manager_init(manager,index);
- index+=tmp;
- #endif
-}
-
-
-
-
-
-SndCard * snd_card_manager_get_card(SndCardManager *manager,int index)
-{
- g_return_val_if_fail(index>=0,NULL);
- g_return_val_if_fail(index<MAX_SND_CARDS,NULL);
- if (index>MAX_SND_CARDS) return NULL;
- return manager->cards[index];
-}
-
-SndCard * snd_card_manager_get_card_with_string(SndCardManager *manager,const char *cardname,int *index)
-{
- int i;
- for (i=0;i<MAX_SND_CARDS;i++){
- gchar *card_name;
- if (manager->cards[i]==NULL) continue;
- card_name=manager->cards[i]->card_name;
- if (card_name==NULL) continue;
- if (strcmp(card_name,cardname)==0){
- *index=i;
- return manager->cards[i];
- }
- }
- g_warning("No card %s found.",cardname);
- return NULL;
-}
-
-SndCardManager _snd_card_manager;
-SndCardManager *snd_card_manager=&_snd_card_manager;
diff --git a/talk/third_party/mediastreamer/sndcard.h b/talk/third_party/mediastreamer/sndcard.h
deleted file mode 100755
index d84757f..0000000
--- a/talk/third_party/mediastreamer/sndcard.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- The mediastreamer library aims at providing modular media processing and I/O
- for linphone, but also for any telephony application.
- Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-
-#ifndef SNDCARD_H
-#define SNDCARD_H
-
-#undef PACKAGE
-#undef VERSION
-#include <config.h>
-#undef PACKAGE
-#undef VERSION
-
-#ifdef HAVE_GLIB
-#include <glib.h>
-#else
-#include <uglib.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* the base class for all soundcards: SndCard */
-struct _SndCard;
-
-typedef int (*SndCardOpenFunc)(struct _SndCard*,int, int, int);
-typedef void (*SndCardSetBlockingModeFunc)(struct _SndCard*, gboolean );
-typedef void (*SndCardCloseFunc)(struct _SndCard*);
-typedef gint (*SndCardIOFunc)(struct _SndCard*,char *,int);
-typedef void (*SndCardDestroyFunc)(struct _SndCard*);
-typedef gboolean (*SndCardPollFunc)(struct _SndCard*);
-typedef gint (*SndCardMixerGetLevelFunc)(struct _SndCard*,gint);
-typedef void (*SndCardMixerSetRecSourceFunc)(struct _SndCard*,gint);
-typedef void (*SndCardMixerSetLevelFunc)(struct _SndCard*,gint ,gint);
-typedef struct _MSFilter * (*SndCardCreateFilterFunc)(struct _SndCard *);
-
-struct _SndCard
-{
- gchar *card_name; /* SB16 PCI for example */
- gint index;
- gint bsize;
- gint rate;
- gint stereo;
- gint bits;
- gint flags;
-#define SND_CARD_FLAGS_OPENED 1
- SndCardOpenFunc _probe;
- SndCardOpenFunc _open_r;
- SndCardOpenFunc _open_w;
- SndCardSetBlockingModeFunc _set_blocking_mode;
- SndCardPollFunc _can_read;
- SndCardIOFunc _read;
- SndCardIOFunc _write;
- SndCardCloseFunc _close_r;
- SndCardCloseFunc _close_w;
- SndCardMixerGetLevelFunc _get_level;
- SndCardMixerSetLevelFunc _set_level;
- SndCardMixerSetRecSourceFunc _set_rec_source;
- SndCardCreateFilterFunc _create_read_filter;
- SndCardCreateFilterFunc _create_write_filter;
- SndCardDestroyFunc _destroy;
-};
-
-
-typedef struct _SndCard SndCard;
-
-void snd_card_init(SndCard *obj);
-void snd_card_uninit(SndCard *obj);
-gint snd_card_probe(SndCard *obj, int bits, int stereo, int rate);
-int snd_card_open_r(SndCard *obj, int bits, int stereo, int rate);
-int snd_card_open_w(SndCard *obj, int bits, int stereo, int rate);
-int snd_card_get_bsize(SndCard *obj);
-gboolean snd_card_can_read(SndCard *obj);
-int snd_card_read(SndCard *obj,char *buffer,int size);
-int snd_card_write(SndCard *obj,char *buffer,int size);
-void snd_card_set_blocking_mode(SndCard *obj,gboolean yesno);
-void snd_card_close_r(SndCard *obj);
-void snd_card_close_w(SndCard *obj);
-
-void snd_card_set_rec_source(SndCard *obj, int source); /* source='l' or 'm'*/
-void snd_card_set_level(SndCard *obj, int way, int level);
-gint snd_card_get_level(SndCard *obj,int way);
-
-const gchar *snd_card_get_identifier(SndCard *obj);
-
-struct _MSFilter * snd_card_create_read_filter(SndCard *sndcard);
-struct _MSFilter * snd_card_create_write_filter(SndCard *sndcard);
-
-
-#define SND_CARD_LEVEL_GENERAL 1
-#define SND_CARD_LEVEL_INPUT 2
-#define SND_CARD_LEVEL_OUTPUT 3
-
-
-int snd_card_destroy(SndCard *obj);
-
-#define SND_CARD(obj) ((SndCard*)(obj))
-
-
-
-
-/* SndCardManager */
-
-#define MAX_SND_CARDS 20
-
-
-struct _SndCardManager
-{
- SndCard *cards[MAX_SND_CARDS];
-};
-
-typedef struct _SndCardManager SndCardManager;
-
-void snd_card_manager_init(SndCardManager *manager);
-SndCard * snd_card_manager_get_card(SndCardManager *manager,int index);
-SndCard * snd_card_manager_get_card_with_string(SndCardManager *manager,const char *cardname,int *index);
-
-extern SndCardManager *snd_card_manager;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/talk/third_party/mediastreamer/waveheader.h b/talk/third_party/mediastreamer/waveheader.h
deleted file mode 100755
index 6768d8f..0000000
--- a/talk/third_party/mediastreamer/waveheader.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-linphone
-Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-/* the following code was taken from a free software utility that I don't remember the name. */
-/* sorry */
-
-
-
-#include <ms.h>
-#ifndef waveheader_h
-#define waveheader_h
-
-typedef struct uint16scheme
-{
- unsigned char lo_byte;
- unsigned char hi_byte;
-} uint16scheme_t;
-
-typedef struct uint32scheme
-{
- guint16 lo_int;
- guint16 hi_int;
-} uint32scheme_t;
-
-
-/* all integer in wav header must be read in least endian order */
-inline guint16 _readuint16(guint16 a)
-{
- guint16 res;
- uint16scheme_t *tmp1=(uint16scheme_t*)&a;
-
- ((uint16scheme_t *)(&res))->lo_byte=tmp1->hi_byte;
- ((uint16scheme_t *)(&res))->hi_byte=tmp1->lo_byte;
- return res;
-}
-
-inline guint32 _readuint32(guint32 a)
-{
- guint32 res;
- uint32scheme_t *tmp1=(uint32scheme_t*)&a;
-
- ((uint32scheme_t *)(&res))->lo_int=_readuint16(tmp1->hi_int);
- ((uint32scheme_t *)(&res))->hi_int=_readuint16(tmp1->lo_int);
- return res;
-}
-
-#ifdef WORDS_BIGENDIAN
-#define le_uint32(a) (_readuint32((a)))
-#define le_uint16(a) (_readuint16((a)))
-#define le_int16(a) ( (gint16) _readuint16((guint16)((a))) )
-#else
-#define le_uint32(a) (a)
-#define le_uint16(a) (a)
-#define le_int16(a) (a)
-#endif
-
-typedef struct _riff_t {
- char riff[4] ; /* "RIFF" (ASCII characters) */
- guint32 len ; /* Length of package (binary, little endian) */
- char wave[4] ; /* "WAVE" (ASCII characters) */
-} riff_t;
-
-/* The FORMAT chunk */
-
-typedef struct _format_t {
- char fmt[4] ; /* "fmt_" (ASCII characters) */
- guint32 len ; /* length of FORMAT chunk (always 0x10) */
- guint16 que ; /* Always 0x01 */
- guint16 channel ; /* Channel numbers (0x01 = mono, 0x02 = stereo) */
- guint32 rate ; /* Sample rate (binary, in Hz) */
- guint32 bps ; /* Bytes Per Second */
- guint16 bpsmpl ; /* bytes per sample: 1 = 8 bit Mono,
- 2 = 8 bit Stereo/16 bit Mono,
- 4 = 16 bit Stereo */
- guint16 bitpspl ; /* bits per sample */
-} format_t;
-
-/* The DATA chunk */
-
-typedef struct _data_t {
- char data[4] ; /* "data" (ASCII characters) */
- int len ; /* length of data */
-} data_t;
-
-typedef struct _wave_header_t
-{
- riff_t riff_chunk;
- format_t format_chunk;
- data_t data_chunk;
-} wave_header_t;
-
-#define wave_header_get_rate(header) le_uint32((header)->format_chunk.rate)
-#define wave_header_get_channel(header) le_uint16((header)->format_chunk.channel)
-
-#endif
diff --git a/talk/xmllite/Makefile.am b/talk/xmllite/Makefile.am
deleted file mode 100755
index deaf2bf..0000000
--- a/talk/xmllite/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-libcricketxmllite_la_SOURCES = qname.cc \
- xmlbuilder.cc \
- xmlconstants.cc \
- xmlelement.cc \
- xmlnsstack.cc \
- xmlparser.cc \
- xmlprinter.cc
-
-noinst_HEADERS = qname.h \
- xmlbuilder.h \
- xmlconstants.h \
- xmlelement.h \
- xmlnsstack.h \
- xmlparser.h \
- xmlprinter.h
-AM_CPPFLAGS = -DPOSIX
-
-noinst_LTLIBRARIES = libcricketxmllite.la
diff --git a/talk/xmllite/qname.cc b/talk/xmllite/qname.cc
old mode 100755
new mode 100644
index 626cfa9..7486524
--- a/talk/xmllite/qname.cc
+++ b/talk/xmllite/qname.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -31,12 +31,10 @@
#include "talk/xmllite/qname.h"
#include "talk/xmllite/xmlconstants.h"
-//#define new TRACK_NEW
-
namespace buzz {
static int QName_Hash(const std::string & ns, const char * local) {
- int result = ns.size() * 101;
+ int result = static_cast<int>(ns.size()) * 101;
while (*local) {
result *= 19;
result += *local;
@@ -103,10 +101,10 @@
QName::QName(bool add, const std::string & ns, const char * local) :
data_(add ? Add(ns, local) : AllocateOrFind(ns, local)) {}
-
+
QName::QName(bool add, const std::string & ns, const std::string & local) :
data_(add ? Add(ns, local.c_str()) : AllocateOrFind(ns, local.c_str())) {}
-
+
QName::QName(const std::string & ns, const char * local) :
data_(AllocateOrFind(ns, local)) {}
@@ -145,15 +143,15 @@
bool
QName::operator==(const QName & other) const {
return other.data_ == data_ ||
- data_->localPart_ == other.data_->localPart_ &&
- data_->namespace_ == other.data_->namespace_;
+ (data_->localPart_ == other.data_->localPart_ &&
+ data_->namespace_ == other.data_->namespace_);
}
int
QName::Compare(const QName & other) const {
if (data_ == other.data_)
return 0;
-
+
int result = data_->localPart_.compare(other.data_->localPart_);
if (result)
return result;
@@ -162,6 +160,3 @@
}
}
-
-
-
diff --git a/talk/xmllite/qname.h b/talk/xmllite/qname.h
old mode 100755
new mode 100644
index b1bcec6..3e64726
--- a/talk/xmllite/qname.h
+++ b/talk/xmllite/qname.h
@@ -61,9 +61,9 @@
class Data {
public:
Data(const std::string & ns, const std::string & local) :
- refcount_(1),
namespace_(ns),
- localPart_(local) {}
+ localPart_(local),
+ refcount_(1) {}
Data() : refcount_(0) {}
diff --git a/talk/xmllite/xmlbuilder.cc b/talk/xmllite/xmlbuilder.cc
old mode 100755
new mode 100644
index 3e2964f..b02dfe0
--- a/talk/xmllite/xmlbuilder.cc
+++ b/talk/xmllite/xmlbuilder.cc
@@ -2,36 +2,39 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/stl_decl.h"
#include <vector>
#include <set>
-#include <expat.h>
#include "talk/base/common.h"
#include "talk/xmllite/xmlelement.h"
#include "talk/xmllite/xmlbuilder.h"
+#ifdef EXPAT_RELATIVE_PATH
+#include "lib/expat.h"
+#else
+#include "third_party/expat/v2_0_1/Source/lib/expat.h"
+#endif // EXPAT_RELATIVE_PATH
namespace buzz {
diff --git a/talk/xmllite/xmlbuilder.h b/talk/xmllite/xmlbuilder.h
old mode 100755
new mode 100644
index 5de31b2..d375985
--- a/talk/xmllite/xmlbuilder.h
+++ b/talk/xmllite/xmlbuilder.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,11 +29,15 @@
#define _xmlbuilder_h_
#include <string>
+#include <vector>
#include "talk/base/scoped_ptr.h"
-#include "talk/base/stl_decl.h"
#include "talk/xmllite/xmlparser.h"
-#include <expat.h>
+#ifdef EXPAT_RELATIVE_PATH
+#include "lib/expat.h"
+#else
+#include "third_party/expat/v2_0_1/Source/lib/expat.h"
+#endif // EXPAT_RELATIVE_PATH
namespace buzz {
@@ -65,9 +69,8 @@
private:
XmlElement * pelCurrent_;
- scoped_ptr<XmlElement> pelRoot_;
- scoped_ptr<std::vector<XmlElement *, std::allocator<XmlElement *> > >
- pvParents_;
+ talk_base::scoped_ptr<XmlElement> pelRoot_;
+ talk_base::scoped_ptr<std::vector<XmlElement*> > pvParents_;
};
}
diff --git a/talk/xmllite/xmlconstants.cc b/talk/xmllite/xmlconstants.cc
old mode 100755
new mode 100644
diff --git a/talk/xmllite/xmlconstants.h b/talk/xmllite/xmlconstants.h
old mode 100755
new mode 100644
diff --git a/talk/xmllite/xmlelement.cc b/talk/xmllite/xmlelement.cc
old mode 100755
new mode 100644
index a4be297..3ec085c
--- a/talk/xmllite/xmlelement.cc
+++ b/talk/xmllite/xmlelement.cc
@@ -85,7 +85,8 @@
pFirstAttr_(NULL),
pLastAttr_(NULL),
pFirstChild_(NULL),
- pLastChild_(NULL) {
+ pLastChild_(NULL),
+ cdata_(false) {
}
XmlElement::XmlElement(const XmlElement & elt) :
@@ -94,7 +95,8 @@
pFirstAttr_(NULL),
pLastAttr_(NULL),
pFirstChild_(NULL),
- pLastChild_(NULL) {
+ pLastChild_(NULL),
+ cdata_(false) {
// copy attributes
XmlAttr * pAttr;
@@ -123,6 +125,7 @@
}
pLastChild_ = newChild;
+ cdata_ = elt.cdata_;
}
XmlElement::XmlElement(const QName & name, bool useDefaultNs) :
@@ -130,7 +133,8 @@
pFirstAttr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
pLastAttr_(pFirstAttr_),
pFirstChild_(NULL),
- pLastChild_(NULL) {
+ pLastChild_(NULL),
+ cdata_(false) {
}
bool
@@ -391,6 +395,12 @@
}
void
+XmlElement::AddCDATAText(const char * buf, int len) {
+ cdata_ = true;
+ AddParsedText(buf, len);
+}
+
+void
XmlElement::AddText(const std::string & text) {
if (text == STR_EMPTY)
return;
@@ -450,6 +460,17 @@
}
void
+XmlElement::ClearAttributes() {
+ XmlAttr * pattr;
+ for (pattr = pFirstAttr_; pattr; ) {
+ XmlAttr * pToDelete = pattr;
+ pattr = pattr->pNextAttr_;
+ delete pToDelete;
+ }
+ pFirstAttr_ = pLastAttr_ = NULL;
+}
+
+void
XmlElement::ClearChildren() {
XmlChild * pchild;
for (pchild = pFirstChild_; pchild; ) {
diff --git a/talk/xmllite/xmlelement.h b/talk/xmllite/xmlelement.h
old mode 100755
new mode 100644
index 7419c03..38e31a9
--- a/talk/xmllite/xmlelement.h
+++ b/talk/xmllite/xmlelement.h
@@ -178,7 +178,7 @@
XmlElement * FirstWithNamespace(const std::string & ns);
const XmlElement * FirstWithNamespace(const std::string & ns) const
{ return const_cast<XmlElement *>(this)->FirstWithNamespace(ns); }
-
+
XmlElement * NextWithNamespace(const std::string & ns);
const XmlElement * NextWithNamespace(const std::string & ns) const
{ return const_cast<XmlElement *>(this)->NextWithNamespace(ns); }
@@ -201,6 +201,9 @@
void RemoveChildAfter(XmlChild * pPredecessor);
void AddParsedText(const char * buf, int len);
+ // Note: CDATA is not supported by XMPP, therefore using this function will
+ // generate non-XMPP compatible XML.
+ void AddCDATAText(const char * buf, int len);
void AddText(const std::string & text);
void AddText(const std::string & text, int depth);
void AddElement(XmlElement * pelChild);
@@ -208,6 +211,7 @@
void AddAttr(const QName & name, const std::string & value);
void AddAttr(const QName & name, const std::string & value, int depth);
void ClearNamedChildren(const QName & name);
+ void ClearAttributes();
void ClearChildren();
static XmlElement * ForStr(const std::string & str);
@@ -215,6 +219,8 @@
void Print(std::ostream * pout, std::string xmlns[], int xmlnsCount) const;
+ bool IsCDATA() const { return cdata_; }
+
protected:
virtual bool IsTextImpl() const;
virtual XmlElement * AsElementImpl() const;
@@ -226,6 +232,7 @@
XmlAttr * pLastAttr_;
XmlChild * pFirstChild_;
XmlChild * pLastChild_;
+ bool cdata_;
};
}
diff --git a/talk/xmllite/xmlnsstack.cc b/talk/xmllite/xmlnsstack.cc
old mode 100755
new mode 100644
index 4dcb649..18e1607
--- a/talk/xmllite/xmlnsstack.cc
+++ b/talk/xmllite/xmlnsstack.cc
@@ -25,7 +25,6 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/stl_decl.h"
#include <string>
#include <iostream>
#include <vector>
diff --git a/talk/xmllite/xmlnsstack.h b/talk/xmllite/xmlnsstack.h
old mode 100755
new mode 100644
index 299ec1c..c7e9f89
--- a/talk/xmllite/xmlnsstack.h
+++ b/talk/xmllite/xmlnsstack.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,8 +29,8 @@
#define _xmlnsstack_h_
#include <string>
+#include <vector>
#include "talk/base/scoped_ptr.h"
-#include "talk/base/stl_decl.h"
#include "talk/xmllite/qname.h"
namespace buzz {
@@ -54,8 +54,8 @@
private:
- scoped_ptr<std::vector<std::string, std::allocator<std::string> > > pxmlnsStack_;
- scoped_ptr<std::vector<size_t, std::allocator<size_t> > > pxmlnsDepthStack_;
+ talk_base::scoped_ptr<std::vector<std::string> > pxmlnsStack_;
+ talk_base::scoped_ptr<std::vector<size_t> > pxmlnsDepthStack_;
};
}
diff --git a/talk/xmllite/xmlparser.cc b/talk/xmllite/xmlparser.cc
old mode 100755
new mode 100644
index 338da8d..568bce1
--- a/talk/xmllite/xmlparser.cc
+++ b/talk/xmllite/xmlparser.cc
@@ -2,44 +2,44 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/xmllite/xmlparser.h"
-#include "talk/base/stl_decl.h"
#include <string>
#include <vector>
#include <iostream>
-#include <expat.h>
#include "talk/base/common.h"
#include "talk/xmllite/xmlelement.h"
#include "talk/xmllite/xmlnsstack.h"
#include "talk/xmllite/xmlconstants.h"
-
-#include <expat.h>
-
-#define new TRACK_NEW
+#include "talk/xmllite/xmlnsstack.h"
+#ifdef EXPAT_RELATIVE_PATH
+#include "lib/expat.h"
+#else
+#include "third_party/expat/v2_0_1/Source/lib/expat.h"
+#endif // EXPAT_RELATIVE_PATH
namespace buzz {
@@ -117,6 +117,9 @@
}
}
}
+ context_.SetPosition(XML_GetCurrentLineNumber(expat_),
+ XML_GetCurrentColumnNumber(expat_),
+ XML_GetCurrentByteIndex(expat_));
pxph_->StartElement(&context_, name, atts);
}
@@ -125,6 +128,9 @@
if (context_.RaisedError() != XML_ERROR_NONE)
return;
context_.EndElement();
+ context_.SetPosition(XML_GetCurrentLineNumber(expat_),
+ XML_GetCurrentColumnNumber(expat_),
+ XML_GetCurrentByteIndex(expat_));
pxph_->EndElement(&context_, name);
}
@@ -132,6 +138,9 @@
XmlParser::ExpatCharacterData(const char *text, int len) {
if (context_.RaisedError() != XML_ERROR_NONE)
return;
+ context_.SetPosition(XML_GetCurrentLineNumber(expat_),
+ XML_GetCurrentColumnNumber(expat_),
+ XML_GetCurrentByteIndex(expat_));
pxph_->CharacterData(&context_, text, len);
}
@@ -165,8 +174,13 @@
if (sentError_)
return false;
- if (XML_Parse(expat_, data, static_cast<int>(len), isFinal) != XML_STATUS_OK)
+ if (XML_Parse(expat_, data, static_cast<int>(len), isFinal) !=
+ XML_STATUS_OK) {
+ context_.SetPosition(XML_GetCurrentLineNumber(expat_),
+ XML_GetCurrentColumnNumber(expat_),
+ XML_GetCurrentByteIndex(expat_));
context_.RaiseError(XML_GetErrorCode(expat_));
+ }
if (context_.RaisedError() != XML_ERROR_NONE) {
sentError_ = true;
@@ -190,7 +204,10 @@
XmlParser::ParseContext::ParseContext(XmlParser *parser) :
parser_(parser),
xmlnsstack_(),
- raised_(XML_ERROR_NONE) {
+ raised_(XML_ERROR_NONE),
+ line_number_(0),
+ column_number_(0),
+ byte_index_(0) {
}
void
@@ -223,13 +240,13 @@
if (result == NULL)
return QN_EMPTY;
const char * localname = c + 1;
- return QName(*result, localname);
+ return QName(*result, localname);
}
}
if (isAttr) {
return QName(STR_EMPTY, qname);
}
-
+
const std::string * result;
result = xmlnsstack_.NsForPrefix(STR_EMPTY);
if (result == NULL)
@@ -244,8 +261,32 @@
raised_ = XML_ERROR_NONE;
}
+void
+XmlParser::ParseContext::SetPosition(int line, int column,
+ long byte_index) {
+ line_number_ = line;
+ column_number_ = column;
+ byte_index_ = byte_index;
+}
+
+void
+XmlParser::ParseContext::GetPosition(unsigned long * line,
+ unsigned long * column,
+ unsigned long * byte_index) {
+ if (line != NULL) {
+ *line = static_cast<unsigned long>(line_number_);
+ }
+
+ if (column != NULL) {
+ *column = static_cast<unsigned long>(column_number_);
+ }
+
+ if (byte_index != NULL) {
+ *byte_index = static_cast<unsigned long>(byte_index_);
+ }
+}
+
XmlParser::ParseContext::~ParseContext() {
}
}
-
diff --git a/talk/xmllite/xmlparser.h b/talk/xmllite/xmlparser.h
old mode 100755
new mode 100644
index 7533a45..3e85e35
--- a/talk/xmllite/xmlparser.h
+++ b/talk/xmllite/xmlparser.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,9 +29,13 @@
#define _xmlparser_h_
#include <string>
-#include <expat.h>
#include "talk/xmllite/xmlnsstack.h"
+#ifdef EXPAT_RELATIVE_PATH
+#include "lib/expat.h"
+#else
+#include "third_party/expat/v2_0_1/Source/lib/expat.h"
+#endif // EXPAT_RELATIVE_PATH
struct XML_ParserStruct;
typedef struct XML_ParserStruct* XML_Parser;
@@ -44,12 +48,16 @@
class XmlParseContext {
public:
+ virtual ~XmlParseContext() {}
virtual QName ResolveQName(const char * qname, bool isAttr) = 0;
virtual void RaiseError(XML_Error err) = 0;
+ virtual void GetPosition(unsigned long * line, unsigned long * column,
+ unsigned long * byte_index) = 0;
};
class XmlParseHandler {
public:
+ virtual ~XmlParseHandler() {}
virtual void StartElement(XmlParseContext * pctx,
const char * name, const char ** atts) = 0;
virtual void EndElement(XmlParseContext * pctx,
@@ -83,17 +91,23 @@
virtual ~ParseContext();
virtual QName ResolveQName(const char * qname, bool isAttr);
virtual void RaiseError(XML_Error err) { if (!raised_) raised_ = err; }
+ virtual void GetPosition(unsigned long * line, unsigned long * column,
+ unsigned long * byte_index);
XML_Error RaisedError() { return raised_; }
void Reset();
void StartElement();
void EndElement();
void StartNamespace(const char * prefix, const char * ns);
+ void SetPosition(int line, int column, long byte_index);
private:
const XmlParser * parser_;
XmlnsStack xmlnsstack_;
XML_Error raised_;
+ XML_Size line_number_;
+ XML_Size column_number_;
+ XML_Index byte_index_;
};
ParseContext context_;
diff --git a/talk/xmllite/xmlprinter.cc b/talk/xmllite/xmlprinter.cc
old mode 100755
new mode 100644
index 86f143a..b05898f
--- a/talk/xmllite/xmlprinter.cc
+++ b/talk/xmllite/xmlprinter.cc
@@ -25,7 +25,6 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/base/stl_decl.h"
#include <string>
#include <iostream>
#include <vector>
@@ -44,6 +43,7 @@
void PrintElement(const XmlElement * element);
void PrintQuotedValue(const std::string & text);
void PrintBodyText(const std::string & text);
+ void PrintCDATAText(const std::string & text);
private:
std::ostream *pout_;
@@ -131,9 +131,13 @@
else {
*pout_ << '>';
while (pchild) {
- if (pchild->IsText())
- PrintBodyText(pchild->AsText()->Text());
- else
+ if (pchild->IsText()) {
+ if (element->IsCDATA()) {
+ PrintCDATAText(pchild->AsText()->Text());
+ } else {
+ PrintBodyText(pchild->AsText()->Text());
+ }
+ } else
PrintElement(pchild->AsElement());
pchild = pchild->NextChild();
}
@@ -186,5 +190,9 @@
}
}
+void
+XmlPrinterImpl::PrintCDATAText(const std::string & text) {
+ *pout_ << "<![CDATA[" << text << "]]>";
+}
}
diff --git a/talk/xmllite/xmlprinter.h b/talk/xmllite/xmlprinter.h
old mode 100755
new mode 100644
diff --git a/talk/xmpp/Makefile.am b/talk/xmpp/Makefile.am
deleted file mode 100755
index ad75fbc..0000000
--- a/talk/xmpp/Makefile.am
+++ /dev/null
@@ -1,33 +0,0 @@
-libcricketxmpp_la_SOURCES = constants.cc \
- jid.cc \
- saslmechanism.cc \
- xmppclient.cc \
- xmppengineimpl.cc \
- xmppengineimpl_iq.cc \
- xmpplogintask.cc \
- xmppstanzaparser.cc \
- xmpptask.cc \
- ratelimitmanager.cc
-
-noinst_HEADERS = asyncsocket.h \
- prexmppauth.h \
- saslhandler.h \
- xmpplogintask.h \
- jid.h \
- saslmechanism.h \
- xmppclient.h \
- constants.h \
- saslplainmechanism.h \
- xmppclientsettings.h \
- xmppstanzaparser.h \
- xmppengine.h \
- xmpptask.h \
- plainsaslhandler.h \
- saslcookiemechanism.h \
- xmppengineimpl.h \
- ratelimitmanager.h
-
-
-AM_CPPFLAGS = -DPOSIX
-
-noinst_LTLIBRARIES = libcricketxmpp.la
diff --git a/talk/xmpp/asyncsocket.h b/talk/xmpp/asyncsocket.h
old mode 100755
new mode 100644
diff --git a/talk/xmpp/constants.cc b/talk/xmpp/constants.cc
old mode 100755
new mode 100644
index 9388aae..aa581f4
--- a/talk/xmpp/constants.cc
+++ b/talk/xmpp/constants.cc
@@ -204,9 +204,6 @@
const QName QN_SASL_NOT_AUTHORIZED(true, NS_SASL, "not-authorized");
const QName QN_SASL_TEMPORARY_AUTH_FAILURE(true, NS_SASL, "temporary-auth-failure");
-const std::string NS_GOOGLE_AUTH("google:auth");
-const QName QN_MISSING_USERNAME(true, NS_GOOGLE_AUTH, "missing-username");
-
const QName QN_DIALBACK_RESULT(true, NS_DIALBACK, "result");
const QName QN_DIALBACK_VERIFY(true, NS_DIALBACK, "verify");
@@ -285,6 +282,18 @@
const QName QN_VCARD_AVATAR_HASH_MODIFIED(true, NS_AVATAR_HASH, "modified");
const buzz::QName QN_NAME(true, STR_EMPTY, "name");
+const buzz::QName QN_AFFILIATION(true, STR_EMPTY, "affiliation");
+const buzz::QName QN_ROLE(true, STR_EMPTY, "role");
+
+#if defined(FEATURE_ENABLE_PSTN)
+const QName QN_VCARD_TEL(true, NS_VCARD, "TEL");
+const QName QN_VCARD_VOICE(true, NS_VCARD, "VOICE");
+const QName QN_VCARD_HOME(true, NS_VCARD, "HOME");
+const QName QN_VCARD_WORK(true, NS_VCARD, "WORK");
+const QName QN_VCARD_CELL(true, NS_VCARD, "CELL");
+const QName QN_VCARD_NUMBER(true, NS_VCARD, "NUMBER");
+#endif
+
const QName QN_XML_LANG(true, NS_XML, "lang");
const std::string STR_TYPE("type");
@@ -332,6 +341,12 @@
const std::string STR_UNSUBSCRIBE("unsubscribe");
const std::string STR_UNSUBSCRIBED("unsubscribed");
+// Google Invite
+const std::string NS_GOOGLE_INVITE("google:subscribe");
+const QName QN_INVITATION(true, NS_GOOGLE_INVITE, "invitation");
+const QName QN_INVITE_NAME(true, NS_GOOGLE_INVITE, "name");
+const QName QN_INVITE_SUBJECT(true, NS_GOOGLE_INVITE, "subject");
+const QName QN_INVITE_MESSAGE(true, NS_GOOGLE_INVITE, "body");
// JEP 0030
const QName QN_NODE(true, STR_EMPTY, "node");
@@ -346,6 +361,11 @@
const QName QN_DISCO_ITEMS_QUERY(true, NS_DISCO_ITEMS, "query");
const QName QN_DISCO_ITEM(true, NS_DISCO_ITEMS, "item");
+const std::string NS_MUC_USER("http://jabber.org/protocol/muc#user");
+const QName QN_MUC_USER_CONTINUE(true, NS_MUC_USER, "continue");
+const QName QN_MUC_USER_X(true, NS_MUC_USER, "x");
+const QName QN_MUC_USER_ITEM(true, NS_MUC_USER, "item");
+const QName QN_MUC_USER_STATUS(true, NS_MUC_USER, "status");
// JEP 0115
const std::string NS_CAPS("http://jabber.org/protocol/caps");
@@ -382,6 +402,19 @@
const QName kQnMilliseconds(true, STR_EMPTY, "ms");
+// Event tracking
+#ifdef FEATURE_ENABLE_TRACKING
+const std::string NS_GOOGLE_EVENT_TRACKING("google:client-usability-testing");
+const QName QN_EVENT_TRACKING(true, NS_GOOGLE_EVENT_TRACKING, "usage-stats");
+const QName QN_EVENT_TRACKING_BRANDID(true, NS_GOOGLE_EVENT_TRACKING, "bid");
+const QName QN_EVENT_TRACKING_EVENT(true, NS_GOOGLE_EVENT_TRACKING, "event");
+const QName QN_EVENT_TRACKING_VARIABLE_KEY(true, STR_EMPTY, "key");
+const QName QN_EVENT_TRACKING_VARIABLE_VALUE(true, STR_EMPTY, "value");
+const QName QN_EVENT_TRACKING_VARIABLE_TIME(true, STR_EMPTY, "time");
+const QName QN_EVENT_TRACKING_EVENT_GROUP(true,
+ NS_GOOGLE_EVENT_TRACKING, "events");
+#endif
+
// Jingle Info
const std::string NS_JINGLE_INFO("google:jingleinfo");
@@ -395,4 +428,40 @@
const QName QN_JINGLE_INFO_UDP(true, STR_EMPTY, "udp");
const QName QN_JINGLE_INFO_TCPSSL(true, STR_EMPTY, "tcpssl");
+// Call Performance Logging
+const std::string NS_GOOGLE_CALLPERF_STATS("google:call-perf-stats");
+const QName QN_CALLPERF_STATS(true, NS_GOOGLE_CALLPERF_STATS, "callPerfStats");
+const QName QN_CALLPERF_SESSIONID(true, STR_EMPTY, "sessionId");
+const QName QN_CALLPERF_LOCALUSER(true, STR_EMPTY, "localUser");
+const QName QN_CALLPERF_REMOTEUSER(true, STR_EMPTY, "remoteUser");
+const QName QN_CALLPERF_STARTTIME(true, STR_EMPTY, "startTime");
+const QName QN_CALLPERF_CALL_LENGTH(true, STR_EMPTY, "callLength");
+const QName QN_CALLPERF_DATAPOINT(true, NS_GOOGLE_CALLPERF_STATS, "dataPoint");
+const QName QN_CALLPERF_DATAPOINT_TIME(true, STR_EMPTY, "timeStamp");
+const QName QN_CALLPERF_DATAPOINT_FRACTION_LOST(true, STR_EMPTY, "fraction_lost");
+const QName QN_CALLPERF_DATAPOINT_CUM_LOST(true, STR_EMPTY, "cum_lost");
+const QName QN_CALLPERF_DATAPOINT_EXT_MAX(true, STR_EMPTY, "ext_max");
+const QName QN_CALLPERF_DATAPOINT_JITTER(true, STR_EMPTY, "jitter");
+const QName QN_CALLPERF_DATAPOINT_RTT(true, STR_EMPTY, "RTT");
+const QName QN_CALLPERF_DATAPOINT_BYTES_R(true, STR_EMPTY, "bytesReceived");
+const QName QN_CALLPERF_DATAPOINT_PACKETS_R(true, STR_EMPTY, "packetsReceived");
+const QName QN_CALLPERF_DATAPOINT_BYTES_S(true, STR_EMPTY, "bytesSent");
+const QName QN_CALLPERF_DATAPOINT_PACKETS_S(true, STR_EMPTY, "packetsSent");
+const QName QN_CALLPERF_CONNECTION(true, NS_GOOGLE_CALLPERF_STATS, "connection");
+const QName QN_CALLPERF_CONNECTION_LOCAL_ADDRESS(true, STR_EMPTY, "localAddress");
+const QName QN_CALLPERF_CONNECTION_REMOTE_ADDRESS(true, STR_EMPTY, "remoteAddress");
+
+// Muc invites.
+const QName QN_MUC_USER_INVITE(true, NS_MUC_USER, "invite");
+
+// Multiway audio/video.
+const std::string NS_GOOGLE_MUC_USER("google:muc#user");
+const QName QN_GOOGLE_MUC_USER_AVAILABLE_MEDIA(true, NS_GOOGLE_MUC_USER, "available-media");
+const QName QN_GOOGLE_MUC_USER_ENTRY(true, NS_GOOGLE_MUC_USER, "entry");
+const QName QN_GOOGLE_MUC_USER_MEDIA(true, NS_GOOGLE_MUC_USER, "media");
+const QName QN_GOOGLE_MUC_USER_TYPE(true, NS_GOOGLE_MUC_USER, "type");
+const QName QN_GOOGLE_MUC_USER_SRC_ID(true, NS_GOOGLE_MUC_USER, "src-id");
+const QName QN_GOOGLE_MUC_USER_STATUS(true, NS_GOOGLE_MUC_USER, "status");
+const QName QN_LABEL(true, STR_EMPTY, "label");
+
}
diff --git a/talk/xmpp/constants.h b/talk/xmpp/constants.h
old mode 100755
new mode 100644
index 2f06f75..1a626b4
--- a/talk/xmpp/constants.h
+++ b/talk/xmpp/constants.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _CRICKET_XMPP_XMPPLIB_BUZZ_CONSTANTS_H_
-#define _CRICKET_XMPP_XMPPLIB_BUZZ_CONSTANTS_H_
+#ifndef TALK_XMPP_CONSTANTS_H_
+#define TALK_XMPP_CONSTANTS_H_
#include <string>
#include "talk/xmllite/qname.h"
@@ -171,9 +171,6 @@
extern const QName QN_SASL_NOT_AUTHORIZED;
extern const QName QN_SASL_TEMPORARY_AUTH_FAILURE;
-extern const std::string NS_GOOGLE_AUTH;
-extern const QName QN_MISSING_USERNAME;
-
extern const QName QN_DIALBACK_RESULT;
extern const QName QN_DIALBACK_VERIFY;
@@ -251,6 +248,28 @@
extern const QName QN_VCARD_AVATAR_HASH;
extern const QName QN_VCARD_AVATAR_HASH_MODIFIED;
+#if defined(FEATURE_ENABLE_PSTN)
+extern const QName QN_VCARD_TEL;
+extern const QName QN_VCARD_VOICE;
+extern const QName QN_VCARD_HOME;
+extern const QName QN_VCARD_WORK;
+extern const QName QN_VCARD_CELL;
+extern const QName QN_VCARD_NUMBER;
+#endif
+
+#if defined(FEATURE_ENABLE_RICHPROFILES)
+extern const QName QN_USER_PROFILE_QUERY;
+extern const QName QN_USER_PROFILE_URL;
+
+extern const QName QN_ATOM_FEED;
+extern const QName QN_ATOM_ENTRY;
+extern const QName QN_ATOM_TITLE;
+extern const QName QN_ATOM_ID;
+extern const QName QN_ATOM_MODIFIED;
+extern const QName QN_ATOM_IMAGE;
+extern const QName QN_ATOM_LINK;
+extern const QName QN_ATOM_HREF;
+#endif
extern const QName QN_XML_LANG;
@@ -271,6 +290,8 @@
extern const QName QN_SUBSCRIPTION;
extern const QName QN_TITLE1;
extern const QName QN_TITLE2;
+extern const QName QN_AFFILIATION;
+extern const QName QN_ROLE;
extern const QName QN_XMLNS_CLIENT;
@@ -290,6 +311,13 @@
extern const std::string STR_UNSUBSCRIBE;
extern const std::string STR_UNSUBSCRIBED;
+// Google Invite
+extern const std::string NS_GOOGLE_SUBSCRIBE;
+extern const QName QN_INVITATION;
+extern const QName QN_INVITE_NAME;
+extern const QName QN_INVITE_SUBJECT;
+extern const QName QN_INVITE_MESSAGE;
+
// JEP 0030
extern const QName QN_NODE;
@@ -306,6 +334,21 @@
extern const QName QN_DISCO_ITEM;
+// JEP 0045
+extern const std::string NS_MUC;
+extern const QName QN_MUC_X;
+extern const QName QN_MUC_ITEM;
+extern const QName QN_MUC_AFFILIATION;
+extern const QName QN_MUC_ROLE;
+extern const std::string STR_AFFILIATION_NONE;
+extern const std::string STR_ROLE_PARTICIPANT;
+extern const std::string NS_MUC_USER;
+extern const QName QN_MUC_USER_CONTINUE;
+extern const QName QN_MUC_USER_X;
+extern const QName QN_MUC_USER_ITEM;
+extern const QName QN_MUC_USER_STATUS;
+
+
// JEP 0115
extern const std::string NS_CAPS;
extern const QName QN_CAPS_C;
@@ -353,6 +396,41 @@
extern const QName QN_JINGLE_INFO_UDP;
extern const QName QN_JINGLE_INFO_TCPSSL;
-}
+extern const std::string NS_GOOGLE_CALLPERF_STATS;
+extern const QName QN_CALLPERF_STATS;
+extern const QName QN_CALLPERF_SESSIONID;
+extern const QName QN_CALLPERF_LOCALUSER;
+extern const QName QN_CALLPERF_REMOTEUSER;
+extern const QName QN_CALLPERF_STARTTIME;
+extern const QName QN_CALLPERF_CALL_LENGTH;
+extern const QName QN_CALLPERF_DATAPOINT;
+extern const QName QN_CALLPERF_DATAPOINT_TIME;
+extern const QName QN_CALLPERF_DATAPOINT_FRACTION_LOST;
+extern const QName QN_CALLPERF_DATAPOINT_CUM_LOST;
+extern const QName QN_CALLPERF_DATAPOINT_EXT_MAX;
+extern const QName QN_CALLPERF_DATAPOINT_JITTER;
+extern const QName QN_CALLPERF_DATAPOINT_RTT;
+extern const QName QN_CALLPERF_DATAPOINT_BYTES_R;
+extern const QName QN_CALLPERF_DATAPOINT_PACKETS_R;
+extern const QName QN_CALLPERF_DATAPOINT_BYTES_S;
+extern const QName QN_CALLPERF_DATAPOINT_PACKETS_S;
+extern const QName QN_CALLPERF_CONNECTION;
+extern const QName QN_CALLPERF_CONNECTION_LOCAL_ADDRESS;
+extern const QName QN_CALLPERF_CONNECTION_REMOTE_ADDRESS;
-#endif // _CRICKET_XMPP_XMPPLIB_BUZZ_CONSTANTS_H_
+// Muc invites.
+extern const QName QN_MUC_USER_INVITE;
+
+// Multiway audio/video.
+extern const std::string NS_GOOGLE_MUC_USER;
+extern const QName QN_GOOGLE_MUC_USER_AVAILABLE_MEDIA;
+extern const QName QN_GOOGLE_MUC_USER_ENTRY;
+extern const QName QN_GOOGLE_MUC_USER_MEDIA;
+extern const QName QN_GOOGLE_MUC_USER_TYPE;
+extern const QName QN_GOOGLE_MUC_USER_SRC_ID;
+extern const QName QN_GOOGLE_MUC_USER_STATUS;
+extern const QName QN_LABEL;
+
+} // namespace buzz
+
+#endif // TALK_XMPP_CONSTANTS_H_
diff --git a/talk/xmpp/jid.cc b/talk/xmpp/jid.cc
old mode 100755
new mode 100644
index ead2074..01a025f
--- a/talk/xmpp/jid.cc
+++ b/talk/xmpp/jid.cc
@@ -25,22 +25,19 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-extern "C" {
-#include <ctype.h>
-}
-#include <string>
#include "talk/xmpp/jid.h"
-#include "talk/xmpp/constants.h"
-#include "talk/base/common.h"
+
+#include <ctype.h>
+
#include <algorithm>
+#include <string>
+
+#include "talk/base/common.h"
#include "talk/base/logging.h"
+#include "talk/xmpp/constants.h"
namespace buzz {
-static int AsciiToLower(int x) {
- return (x <= 'Z' && x >= 'A') ? (x + ('a' - 'A')) : x;
-}
-
Jid::Jid() : data_(NULL) {
}
@@ -209,20 +206,20 @@
bool
Jid::BareEquals(const Jid & other) const {
return (other.data_ == data_ ||
- data_ != NULL &&
+ (data_ != NULL &&
other.data_ != NULL &&
other.data_->node_name_ == data_->node_name_ &&
- other.data_->domain_name_ == data_->domain_name_);
+ other.data_->domain_name_ == data_->domain_name_));
}
bool
Jid::operator==(const Jid & other) const {
return (other.data_ == data_ ||
- data_ != NULL &&
+ (data_ != NULL &&
other.data_ != NULL &&
other.data_->node_name_ == data_->node_name_ &&
other.data_->domain_name_ == data_->domain_name_ &&
- other.data_->resource_name_ == data_->resource_name_);
+ other.data_->resource_name_ == data_->resource_name_));
}
int
diff --git a/talk/xmpp/jid.h b/talk/xmpp/jid.h
old mode 100755
new mode 100644
diff --git a/talk/xmpp/plainsaslhandler.h b/talk/xmpp/plainsaslhandler.h
old mode 100755
new mode 100644
diff --git a/talk/xmpp/prexmppauth.h b/talk/xmpp/prexmppauth.h
old mode 100755
new mode 100644
index f94bd3d..dce5e0b
--- a/talk/xmpp/prexmppauth.h
+++ b/talk/xmpp/prexmppauth.h
@@ -73,12 +73,12 @@
sigslot::signal0<> SignalAuthDone;
- virtual bool IsAuthDone() = 0;
- virtual bool IsAuthorized() = 0;
- virtual bool HadError() = 0;
- virtual int GetError() = 0;
- virtual CaptchaChallenge GetCaptchaChallenge() = 0;
- virtual std::string GetAuthCookie() = 0;
+ virtual bool IsAuthDone() const = 0;
+ virtual bool IsAuthorized() const = 0;
+ virtual bool HadError() const = 0;
+ virtual int GetError() const = 0;
+ virtual CaptchaChallenge GetCaptchaChallenge() const = 0;
+ virtual std::string GetAuthCookie() const = 0;
};
}
diff --git a/talk/xmpp/ratelimitmanager.cc b/talk/xmpp/ratelimitmanager.cc
old mode 100755
new mode 100644
index 81c55ac..14667a7
--- a/talk/xmpp/ratelimitmanager.cc
+++ b/talk/xmpp/ratelimitmanager.cc
@@ -25,6 +25,9 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <list>
+#include <string>
+
#include "talk/xmpp/ratelimitmanager.h"
namespace buzz {
diff --git a/talk/xmpp/ratelimitmanager.h b/talk/xmpp/ratelimitmanager.h
old mode 100755
new mode 100644
index 79960d8..1a7fc82
--- a/talk/xmpp/ratelimitmanager.h
+++ b/talk/xmpp/ratelimitmanager.h
@@ -92,12 +92,7 @@
// True iff the current time >= to the next song allowed time
bool IsWithinRateLimit() {
- uint32 current_time = talk_base::Time();
- if (talk_base::TimeDiff(current_time, NextTimeAllowedForCounter()) >= 0) {
- return true;
- } else {
- return false;
- }
+ return (talk_base::TimeSince(NextTimeAllowedForCounter()) >= 0);
}
// Updates time and counter for rate limit
diff --git a/talk/xmpp/saslcookiemechanism.h b/talk/xmpp/saslcookiemechanism.h
old mode 100755
new mode 100644
index a6630d9..92cff4d
--- a/talk/xmpp/saslcookiemechanism.h
+++ b/talk/xmpp/saslcookiemechanism.h
@@ -28,8 +28,9 @@
#ifndef _SASLCOOKIEMECHANISM_H_
#define _SASLCOOKIEMECHANISM_H_
-#include "talk/xmpp/saslmechanism.h"
+#include "talk/xmllite/qname.h"
#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/saslmechanism.h"
#include "talk/xmpp/constants.h"
namespace buzz {
@@ -37,8 +38,22 @@
class SaslCookieMechanism : public SaslMechanism {
public:
- SaslCookieMechanism(const std::string & mechanism, const std::string & username, const std::string & cookie) :
- mechanism_(mechanism), username_(username), cookie_(cookie) {}
+ SaslCookieMechanism(const std::string & mechanism,
+ const std::string & username,
+ const std::string & cookie,
+ const std::string & token_service)
+ : mechanism_(mechanism),
+ username_(username),
+ cookie_(cookie),
+ token_service_(token_service) {}
+
+ SaslCookieMechanism(const std::string & mechanism,
+ const std::string & username,
+ const std::string & cookie)
+ : mechanism_(mechanism),
+ username_(username),
+ cookie_(cookie),
+ token_service_("") {}
virtual std::string GetMechanismName() { return mechanism_; }
@@ -46,7 +61,12 @@
// send initial request
XmlElement * el = new XmlElement(QN_SASL_AUTH, true);
el->AddAttr(QN_MECHANISM, mechanism_);
-
+ if (!token_service_.empty()) {
+ el->AddAttr(
+ QName(true, "http://www.google.com/talk/protocol/auth", "service"),
+ token_service_);
+ }
+
std::string credential;
credential.append("\0", 1);
credential.append(username_);
@@ -60,6 +80,7 @@
std::string mechanism_;
std::string username_;
std::string cookie_;
+ std::string token_service_;
};
}
diff --git a/talk/xmpp/saslhandler.h b/talk/xmpp/saslhandler.h
old mode 100755
new mode 100644
index b57d3ba..bead8aa
--- a/talk/xmpp/saslhandler.h
+++ b/talk/xmpp/saslhandler.h
@@ -29,6 +29,7 @@
#define _SASLHANDLER_H_
#include <string>
+#include <vector>
namespace buzz {
@@ -56,4 +57,3 @@
}
#endif
-
diff --git a/talk/xmpp/saslmechanism.cc b/talk/xmpp/saslmechanism.cc
old mode 100755
new mode 100644
index 45c947a..2645ac0
--- a/talk/xmpp/saslmechanism.cc
+++ b/talk/xmpp/saslmechanism.cc
@@ -54,17 +54,19 @@
std::string
SaslMechanism::Base64Encode(const std::string & plain) {
- return Base64::encode(plain);
+ return Base64::Encode(plain);
}
std::string
SaslMechanism::Base64Decode(const std::string & encoded) {
- return Base64::decode(encoded);
+ return Base64::Decode(encoded, Base64::DO_LAX);
}
std::string
SaslMechanism::Base64EncodeFromArray(const char * plain, size_t length) {
- return Base64::encodeFromArray(plain, length);
+ std::string result;
+ Base64::EncodeFromArray(plain, length, &result);
+ return result;
}
}
diff --git a/talk/xmpp/saslmechanism.h b/talk/xmpp/saslmechanism.h
old mode 100755
new mode 100644
diff --git a/talk/xmpp/saslplainmechanism.h b/talk/xmpp/saslplainmechanism.h
old mode 100755
new mode 100644
diff --git a/talk/xmpp/xmppclient.cc b/talk/xmpp/xmppclient.cc
old mode 100755
new mode 100644
index 0db9b1d..d772998
--- a/talk/xmpp/xmppclient.cc
+++ b/talk/xmpp/xmppclient.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -36,7 +36,7 @@
namespace buzz {
-talk_base::Task* XmppClient::GetParent(int code) {
+talk_base::TaskParent* XmppClient::GetParent(int code) {
if (code == XMPP_CLIENT_TASK_CODE)
return this;
else
@@ -63,9 +63,9 @@
XmppClient * const client_;
// the two main objects
- scoped_ptr<AsyncSocket> socket_;
- scoped_ptr<XmppEngine> engine_;
- scoped_ptr<PreXmppAuth> pre_auth_;
+ talk_base::scoped_ptr<AsyncSocket> socket_;
+ talk_base::scoped_ptr<XmppEngine> engine_;
+ talk_base::scoped_ptr<PreXmppAuth> pre_auth_;
talk_base::CryptString pass_;
std::string auth_cookie_;
talk_base::SocketAddress server_;
@@ -119,8 +119,9 @@
//
// This is only true when using Gaia auth, so let's say if there's no preauth,
// we should use the actual server name
- if ((settings.server().IPAsString() == buzz::STR_TALK_GOOGLE_COM ||
- settings.server().IPAsString() == buzz::STR_TALKX_L_GOOGLE_COM) &&
+ std::string server_name = settings.server().IPAsString();
+ if ((server_name == buzz::STR_TALK_GOOGLE_COM ||
+ server_name == buzz::STR_TALKX_L_GOOGLE_COM) &&
pre_auth != NULL) {
d_->engine_->SetTlsServer(buzz::STR_GMAIL_COM, buzz::STR_GMAIL_COM);
}
@@ -185,17 +186,6 @@
return d_->auth_cookie_;
}
-static void
-ForgetPassword(std::string & to_erase) {
- size_t len = to_erase.size();
- for (size_t i = 0; i < len; i++) {
- // get rid of characters
- to_erase[i] = 'x';
- }
- // get rid of length
- to_erase.erase();
-}
-
int
XmppClient::ProcessStart() {
if (d_->pre_auth_.get()) {
@@ -262,7 +252,7 @@
EnsureClosed();
return STATE_ERROR;
}
-
+
return STATE_RESPONSE;
}
@@ -280,11 +270,12 @@
if (d_->socket_.get() == NULL)
return XMPP_RETURN_BADSTATE;
d_->engine_->Disconnect();
+ d_->socket_.reset(NULL);
return XMPP_RETURN_OK;
}
-XmppClient::XmppClient(Task * parent)
- : Task(parent),
+XmppClient::XmppClient(TaskParent * parent)
+ : Task(parent),
delivering_signal_(false),
valid_(false) {
d_.reset(new Private(this));
@@ -354,7 +345,7 @@
void
XmppClient::Private::OnSocketClosed() {
- int code = socket_->GetError();
+ int code = socket_->GetError();
engine_->ConnectionClosed(code);
}
diff --git a/talk/xmpp/xmppclient.h b/talk/xmpp/xmppclient.h
old mode 100755
new mode 100644
index 1c4b947..9983794
--- a/talk/xmpp/xmppclient.h
+++ b/talk/xmpp/xmppclient.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -59,7 +59,7 @@
// listener should be a task that is a child of the XmppClient that owns
// the connection you are using. XmppClient has all the utility methods
// that basically drill through to XmppEngine.
-//
+//
// XmppClient is just a wrapper for XmppEngine, and if I were writing it
// all over again, I would make XmppClient == XmppEngine. Why?
// XmppEngine needs tasks too, for example it has an XmppLoginTask which
@@ -71,20 +71,20 @@
class XmppClient : public talk_base::Task, public sigslot::has_slots<>
{
public:
- XmppClient(talk_base::Task * parent);
+ explicit XmppClient(talk_base::TaskParent * parent);
~XmppClient();
XmppReturnStatus Connect(const XmppClientSettings & settings,
const std::string & lang,
AsyncSocket * socket,
PreXmppAuth * preauth);
-
- virtual talk_base::Task* GetParent(int code);
+
+ virtual talk_base::TaskParent* GetParent(int code);
virtual int ProcessStart();
virtual int ProcessResponse();
XmppReturnStatus Disconnect();
const Jid & jid();
-
+
sigslot::signal1<XmppEngine::State> SignalStateChange;
XmppEngine::State GetState();
XmppEngine::Error GetError(int *subcode);
@@ -138,7 +138,7 @@
}
}
- std::string XmppClient::GetStateName(int state) const {
+ std::string GetStateName(int state) const {
switch (state) {
case STATE_PRE_XMPP_LOGIN: return "PRE_XMPP_LOGIN";
case STATE_START_XMPP_LOGIN: return "START_XMPP_LOGIN";
@@ -149,11 +149,11 @@
int ProcessCookieLogin();
int ProcessStartXmppLogin();
void EnsureClosed();
-
+
class Private;
friend class Private;
- scoped_ptr<Private> d_;
-
+ talk_base::scoped_ptr<Private> d_;
+
bool delivering_signal_;
bool valid_;
};
diff --git a/talk/xmpp/xmppclientsettings.h b/talk/xmpp/xmppclientsettings.h
old mode 100755
new mode 100644
index 281e1bb..4f821ab
--- a/talk/xmpp/xmppclientsettings.h
+++ b/talk/xmpp/xmppclientsettings.h
@@ -33,12 +33,12 @@
namespace buzz {
-class XmppClientSettings {
-public:
- XmppClientSettings() :
- use_tls_(false), use_cookie_auth_(false), protocol_(cricket::PROTO_TCP),
- proxy_(talk_base::PROXY_NONE), proxy_port_(80), use_proxy_auth_(false),
- allow_plain_(false) {}
+class XmppUserSettings {
+ public:
+ XmppUserSettings()
+ : use_tls_(false),
+ allow_plain_(false) {
+ }
void set_user(const std::string & user) { user_ = user; }
void set_host(const std::string & host) { host_ = host; }
@@ -46,6 +46,40 @@
void set_auth_cookie(const std::string & cookie) { auth_cookie_ = cookie; }
void set_resource(const std::string & resource) { resource_ = resource; }
void set_use_tls(bool use_tls) { use_tls_ = use_tls; }
+ void set_allow_plain(bool f) { allow_plain_ = f; }
+ void set_token_service(const std::string & token_service) {
+ token_service_ = token_service;
+ }
+
+ const std::string & user() const { return user_; }
+ const std::string & host() const { return host_; }
+ const talk_base::CryptString & pass() const { return pass_; }
+ const std::string & auth_cookie() const { return auth_cookie_; }
+ const std::string & resource() const { return resource_; }
+ bool use_tls() const { return use_tls_; }
+ bool allow_plain() const { return allow_plain_; }
+ const std::string & token_service() const { return token_service_; }
+
+ private:
+ std::string user_;
+ std::string host_;
+ talk_base::CryptString pass_;
+ std::string auth_cookie_;
+ std::string resource_;
+ bool use_tls_;
+ bool allow_plain_;
+ std::string token_service_;
+};
+
+class XmppClientSettings : public XmppUserSettings {
+ public:
+ XmppClientSettings()
+ : protocol_(cricket::PROTO_TCP),
+ proxy_(talk_base::PROXY_NONE),
+ proxy_port_(80),
+ use_proxy_auth_(false) {
+ }
+
void set_server(const talk_base::SocketAddress & server) {
server_ = server;
}
@@ -56,14 +90,7 @@
void set_use_proxy_auth(bool f) { use_proxy_auth_ = f; }
void set_proxy_user(const std::string & user) { proxy_user_ = user; }
void set_proxy_pass(const talk_base::CryptString & pass) { proxy_pass_ = pass; }
- void set_allow_plain(bool f) { allow_plain_ = f; }
- const std::string & user() const { return user_; }
- const std::string & host() const { return host_; }
- const talk_base::CryptString & pass() const { return pass_; }
- const std::string & auth_cookie() const { return auth_cookie_; }
- const std::string & resource() const { return resource_; }
- bool use_tls() const { return use_tls_; }
const talk_base::SocketAddress & server() const { return server_; }
cricket::ProtocolType protocol() const { return protocol_; }
talk_base::ProxyType proxy() const { return proxy_; }
@@ -72,16 +99,8 @@
bool use_proxy_auth() const { return use_proxy_auth_; }
const std::string & proxy_user() const { return proxy_user_; }
const talk_base::CryptString & proxy_pass() const { return proxy_pass_; }
- bool allow_plain() const { return allow_plain_; }
-private:
- std::string user_;
- std::string host_;
- talk_base::CryptString pass_;
- std::string auth_cookie_;
- std::string resource_;
- bool use_tls_;
- bool use_cookie_auth_;
+ private:
talk_base::SocketAddress server_;
cricket::ProtocolType protocol_;
talk_base::ProxyType proxy_;
@@ -90,7 +109,6 @@
bool use_proxy_auth_;
std::string proxy_user_;
talk_base::CryptString proxy_pass_;
- bool allow_plain_;
};
}
diff --git a/talk/xmpp/xmppengine.h b/talk/xmpp/xmppengine.h
old mode 100755
new mode 100644
index 45d2875..44ed83d
--- a/talk/xmpp/xmppengine.h
+++ b/talk/xmpp/xmppengine.h
@@ -83,6 +83,7 @@
//! Connect, SendStanza, SendIq, Disconnect, or HandleInput.
class XmppOutputHandler {
public:
+ virtual ~XmppOutputHandler() {}
//! Deliver the specified bytes to the XMPP socket.
virtual void WriteOutput(const char * bytes, size_t len) = 0;
@@ -100,6 +101,7 @@
//! to the object managing the engine.
class XmppSessionHandler {
public:
+ virtual ~XmppSessionHandler() {}
//! Called when engine changes state. Argument is new state.
virtual void OnStateChange(int state) = 0;
};
@@ -109,7 +111,7 @@
//! XmppEngine.AddSessionHAndler.
class XmppStanzaHandler {
public:
-
+ virtual ~XmppStanzaHandler() {}
//! Process the given stanza.
//! The handler must return true if it has handled the stanza.
//! A false return value causes the stanza to be passed on to
@@ -123,6 +125,7 @@
//! to sending to any registered SessionHandlers.
class XmppIqHandler {
public:
+ virtual ~XmppIqHandler() {}
//! Called to handle the iq response.
//! The response may be either a result or an error, and will have
//! an 'id' that matches the request and a 'from' that matches the
diff --git a/talk/xmpp/xmppengineimpl.cc b/talk/xmpp/xmppengineimpl.cc
old mode 100755
new mode 100644
index 64ff957..262c531
--- a/talk/xmpp/xmppengineimpl.cc
+++ b/talk/xmpp/xmppengineimpl.cc
@@ -72,8 +72,8 @@
output_handler_(NULL),
session_handler_(NULL),
iq_entries_(new IqEntryVector()),
- output_(new std::stringstream()),
- sasl_handler_(NULL) {
+ sasl_handler_(NULL),
+ output_(new std::stringstream()) {
for (int i = 0; i < HL_COUNT; i+= 1) {
stanza_handlers_[i].reset(new StanzaHandlerVector());
}
@@ -110,7 +110,7 @@
EnterExit ee(this);
- // TODO(jliaw): The return value of the xml parser is not checked.
+ // TODO: The return value of the xml parser is not checked.
stanzaParser_.Parse(bytes, len, false);
return XMPP_RETURN_OK;
diff --git a/talk/xmpp/xmppengineimpl.h b/talk/xmpp/xmppengineimpl.h
old mode 100755
new mode 100644
index 1981035..e5d3dc6
--- a/talk/xmpp/xmppengineimpl.h
+++ b/talk/xmpp/xmppengineimpl.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -29,6 +29,7 @@
#define _xmppengineimpl_h_
#include <sstream>
+#include <vector>
#include "talk/xmpp/xmppengine.h"
#include "talk/xmpp/xmppstanzaparser.h"
@@ -124,7 +125,7 @@
if (subcode) {
*subcode = subcode_;
}
- return error_code_;
+ return error_code_;
}
//! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM.
@@ -207,6 +208,7 @@
class StanzaParseHandler : public XmppStanzaParseHandler {
public:
StanzaParseHandler(XmppEngineImpl * outer) : outer_(outer) {}
+ virtual ~StanzaParseHandler() {}
virtual void StartStream(const XmlElement * pelStream)
{ outer_->IncomingStart(pelStream); }
virtual void Stanza(const XmlElement * pelStanza)
@@ -226,8 +228,8 @@
private:
XmppEngineImpl* engine_;
State state_;
- Error error_;
-
+ Error error_;
+
};
friend class StanzaParseHandler;
@@ -245,7 +247,7 @@
bool tls_needed_;
std::string tls_server_hostname_;
std::string tls_server_domain_;
- scoped_ptr<XmppLoginTask> login_task_;
+ talk_base::scoped_ptr<XmppLoginTask> login_task_;
std::string lang_;
int next_id_;
@@ -254,20 +256,20 @@
bool encrypted_;
Error error_code_;
int subcode_;
- scoped_ptr<XmlElement> stream_error_;
+ talk_base::scoped_ptr<XmlElement> stream_error_;
bool raised_reset_;
XmppOutputHandler* output_handler_;
XmppSessionHandler* session_handler_;
- typedef STD_VECTOR(XmppStanzaHandler*) StanzaHandlerVector;
- scoped_ptr<StanzaHandlerVector> stanza_handlers_[HL_COUNT];
+ typedef std::vector<XmppStanzaHandler*> StanzaHandlerVector;
+ talk_base::scoped_ptr<StanzaHandlerVector> stanza_handlers_[HL_COUNT];
- typedef STD_VECTOR(XmppIqEntry*) IqEntryVector;
- scoped_ptr<IqEntryVector> iq_entries_;
+ typedef std::vector<XmppIqEntry*> IqEntryVector;
+ talk_base::scoped_ptr<IqEntryVector> iq_entries_;
- scoped_ptr<SaslHandler> sasl_handler_;
+ talk_base::scoped_ptr<SaslHandler> sasl_handler_;
- scoped_ptr<std::stringstream> output_;
+ talk_base::scoped_ptr<std::stringstream> output_;
};
}
diff --git a/talk/xmpp/xmppengineimpl_iq.cc b/talk/xmpp/xmppengineimpl_iq.cc
old mode 100755
new mode 100644
diff --git a/talk/xmpp/xmpplogintask.cc b/talk/xmpp/xmpplogintask.cc
old mode 100755
new mode 100644
index 5101089..537818c
--- a/talk/xmpp/xmpplogintask.cc
+++ b/talk/xmpp/xmpplogintask.cc
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -221,7 +221,7 @@
state_ = LOGINSTATE_SASL_RUNNING;
continue;
}
-
+
case LOGINSTATE_SASL_RUNNING: {
if (NULL == (element = NextStanza()))
return true;
@@ -238,9 +238,6 @@
continue;
}
if (element->Name() != QN_SASL_SUCCESS) {
- if (element->FirstNamed(QN_MISSING_USERNAME) != NULL) {
- return Failure(XmppEngine::ERROR_MISSING_USERNAME);
- }
return Failure(XmppEngine::ERROR_UNAUTHORIZED);
}
@@ -338,7 +335,7 @@
if (!element->HasAttr(QN_ID))
return false;
-
+
streamId_ = element->Attr(QN_ID);
return true;
diff --git a/talk/xmpp/xmpplogintask.h b/talk/xmpp/xmpplogintask.h
old mode 100755
new mode 100644
index 993a6bf..a6507b5
--- a/talk/xmpp/xmpplogintask.h
+++ b/talk/xmpp/xmpplogintask.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -31,7 +31,6 @@
#include <string>
#include "talk/base/logging.h"
#include "talk/base/scoped_ptr.h"
-#include "talk/base/stl_decl.h"
#include "talk/xmpp/jid.h"
#include "talk/xmpp/xmppengine.h"
@@ -82,13 +81,12 @@
const XmlElement * pelStanza_;
bool isStart_;
std::string iqId_;
- scoped_ptr<XmlElement> pelFeatures_;
+ talk_base::scoped_ptr<XmlElement> pelFeatures_;
Jid fullJid_;
std::string streamId_;
- scoped_ptr<std::vector<XmlElement *,
- std::allocator<XmlElement *> > > pvecQueuedStanzas_;
-
- scoped_ptr<SaslMechanism> sasl_mech_;
+ talk_base::scoped_ptr<std::vector<XmlElement *> > pvecQueuedStanzas_;
+
+ talk_base::scoped_ptr<SaslMechanism> sasl_mech_;
#ifdef _DEBUG
static const talk_base::ConstantLabel LOGINTASK_STATES[];
diff --git a/talk/xmpp/xmppstanzaparser.cc b/talk/xmpp/xmppstanzaparser.cc
old mode 100755
new mode 100644
index 66ed44f..3aced15
--- a/talk/xmpp/xmppstanzaparser.cc
+++ b/talk/xmpp/xmppstanzaparser.cc
@@ -2,36 +2,38 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <expat.h>
#include "talk/xmllite/xmlelement.h"
#include "talk/base/common.h"
#include "talk/xmpp/xmppstanzaparser.h"
#include "talk/xmpp/constants.h"
-
-#define new TRACK_NEW
+#ifdef EXPAT_RELATIVE_PATH
+#include "lib/expat.h"
+#else
+#include "third_party/expat/v2_0_1/Source/lib/expat.h"
+#endif
namespace buzz {
@@ -101,4 +103,3 @@
}
}
-
diff --git a/talk/xmpp/xmppstanzaparser.h b/talk/xmpp/xmppstanzaparser.h
old mode 100755
new mode 100644
index 1e109a3..c6f8b08
--- a/talk/xmpp/xmppstanzaparser.h
+++ b/talk/xmpp/xmppstanzaparser.h
@@ -38,6 +38,7 @@
class XmppStanzaParseHandler {
public:
+ virtual ~XmppStanzaParseHandler() {}
virtual void StartStream(const XmlElement * pelStream) = 0;
virtual void Stanza(const XmlElement * pelStanza) = 0;
virtual void EndStream() = 0;
diff --git a/talk/xmpp/xmpptask.cc b/talk/xmpp/xmpptask.cc
old mode 100755
new mode 100644
index 4756bbe..bbd50e3
--- a/talk/xmpp/xmpptask.cc
+++ b/talk/xmpp/xmpptask.cc
@@ -35,13 +35,14 @@
RateLimitManager task_rate_manager;
-XmppTask::XmppTask(Task* parent, XmppEngine::HandlerLevel level)
+XmppTask::XmppTask(TaskParent* parent, XmppEngine::HandlerLevel level)
: Task(parent), client_(NULL) {
#ifdef _DEBUG
debug_force_timeout_ = false;
#endif
- XmppClient* client = (XmppClient*)parent->GetParent(XMPP_CLIENT_TASK_CODE);
+ XmppClient* client =
+ static_cast<XmppClient*>(parent->GetParent(XMPP_CLIENT_TASK_CODE));
client_ = client;
id_ = client->NextId();
client->AddXmppTask(this, level);
@@ -106,7 +107,7 @@
XmlElement* XmppTask::MakeIq(const std::string& type,
const buzz::Jid& to,
- const std::string id) {
+ const std::string& id) {
XmlElement* result = new XmlElement(QN_IQ);
if (!type.empty())
result->AddAttr(QN_TYPE, type);
@@ -163,7 +164,7 @@
return false;
return true;
-}
+}
bool XmppTask::VerifyTaskRateLimit(const std::string task_name, int max_count,
int per_x_seconds) {
@@ -171,4 +172,4 @@
per_x_seconds);
}
-}
\ No newline at end of file
+}
diff --git a/talk/xmpp/xmpptask.h b/talk/xmpp/xmpptask.h
old mode 100755
new mode 100644
index 156c9a5..84e2fe0
--- a/talk/xmpp/xmpptask.h
+++ b/talk/xmpp/xmpptask.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2006, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -69,7 +69,7 @@
public sigslot::has_slots<>
{
public:
- XmppTask(talk_base::Task* parent,
+ XmppTask(talk_base::TaskParent* parent,
XmppEngine::HandlerLevel level = XmppEngine::HL_NONE);
virtual ~XmppTask();
@@ -98,18 +98,18 @@
virtual void QueueStanza(const XmlElement* stanza);
const XmlElement* NextStanza();
- bool MatchResponseIq(const XmlElement* stanza, const Jid& to,
+ bool MatchResponseIq(const XmlElement* stanza, const Jid& to,
const std::string& task_id);
- bool MatchRequestIq(const XmlElement* stanza, const std::string& type,
- const QName& qn);
- XmlElement *MakeIqResult(const XmlElement* query);
- XmlElement *MakeIq(const std::string& type,
- const Jid& to, const std::string task_id);
+ static bool MatchRequestIq(const XmlElement* stanza, const std::string& type,
+ const QName& qn);
+ static XmlElement *MakeIqResult(const XmlElement* query);
+ static XmlElement *MakeIq(const std::string& type,
+ const Jid& to, const std::string& task_id);
// Returns true if the task is under the specified rate limit and updates the
// rate limit accordingly
- bool VerifyTaskRateLimit(const std::string task_name, int max_count,
+ bool VerifyTaskRateLimit(const std::string task_name, int max_count,
int per_x_seconds);
private:
@@ -117,12 +117,12 @@
XmppClient* client_;
std::deque<XmlElement*> stanza_queue_;
- scoped_ptr<XmlElement> next_stanza_;
+ talk_base::scoped_ptr<XmlElement> next_stanza_;
std::string id_;
#ifdef _DEBUG
bool debug_force_timeout_;
-#endif
+#endif
};
}