Initial import

git-svn-id: http://libjingle.googlecode.com/svn/trunk@2 dd674b97-3498-5ee5-1854-bdd07cd0ff33
diff --git a/AUTHORS b/AUTHORS
new file mode 100755
index 0000000..e491a9e
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Google Inc.
diff --git a/COPYING b/COPYING
new file mode 100755
index 0000000..d11f105
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,25 @@
+Copyright (c) 2004--2005, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+SUCH DAMAGE.
\ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
new file mode 100755
index 0000000..ce00334
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,13 @@
+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
new file mode 100644
index 0000000..7739aef
--- /dev/null
+++ b/DOCUMENTATION
@@ -0,0 +1 @@
+Documentation for libjingle can be found at http://code.google.com/apis/talk/libjingle/
diff --git a/INSTALL b/INSTALL
new file mode 100755
index 0000000..a4b3414
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,229 @@
+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
new file mode 100755
index 0000000..d4cf1cb
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,8 @@
+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/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..2f1f79f
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,642 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = README $(am__configure_deps) $(noinst_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(srcdir)/config.h.in $(top_srcdir)/configure AUTHORS COPYING \
+	ChangeLog INSTALL NEWS config.guess config.sub depcomp \
+	install-sh ltmain.sh missing
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-exec-recursive install-info-recursive \
+	install-recursive installcheck-recursive installdirs-recursive \
+	pdf-recursive ps-recursive uninstall-info-recursive \
+	uninstall-recursive
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).zip
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+SUBDIRS = talk
+noinst_HEADERS = config.h
+EXTRA_DIST = README.win DOCUMENTATION
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh:
+	@:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
+	      cd $(srcdir) && $(AUTOMAKE) --gnu  \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in:  $(am__configure_deps) 
+	cd $(top_srcdir) && $(AUTOHEADER)
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	mkdir $(distdir)
+	$(mkdir_p) $(distdir)/talk
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(mkdir_p) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
+	  dist-hook
+	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r $(distdir)
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+	$(am__remove_distdir)
+
+dist-tarZ: distdir
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__remove_distdir)
+
+dist-shar: distdir
+	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+	$(am__remove_distdir)
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__remove_distdir)
+
+dist dist-all: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	esac
+	chmod -R a-w $(distdir); chmod a+w $(distdir)
+	mkdir $(distdir)/_build
+	mkdir $(distdir)/_inst
+	chmod a-w $(distdir)
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && cd $(distdir)/_build \
+	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+	$(am__remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+	@cd $(distuninstallcheck_dir) \
+	&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(HEADERS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+	distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
+	check-am clean clean-generic clean-libtool clean-recursive \
+	ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+	dist-hook dist-shar dist-tarZ dist-zip distcheck distclean \
+	distclean-generic distclean-hdr distclean-libtool \
+	distclean-recursive distclean-tags distcleancheck distdir \
+	distuninstallcheck dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	maintainer-clean-recursive mostlyclean mostlyclean-generic \
+	mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
+	tags tags-recursive uninstall uninstall-am uninstall-info-am
+
+
+dist-hook:
+	sed -i -f talk/sanitize.sed `find $(distdir) -type f`
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100755
index 0000000..bccf886
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,15 @@
+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
new file mode 100755
index 0000000..2c4d73d
--- /dev/null
+++ b/README
@@ -0,0 +1,57 @@
+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.

diff --git a/README.win b/README.win
new file mode 100755
index 0000000..985f251
--- /dev/null
+++ b/README.win
@@ -0,0 +1,24 @@
+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
new file mode 100644
index 0000000..2178633
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,7268 @@
+# 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/config.guess b/config.guess
new file mode 100755
index 0000000..ad5281e
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1466 @@
+#! /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
new file mode 100644
index 0000000..369419b
--- /dev/null
+++ b/config.h
@@ -0,0 +1,113 @@
+/* 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
new file mode 100644
index 0000000..88a4f96
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,112 @@
+/* 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
new file mode 100755
index 0000000..1c366df
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1579 @@
+#! /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
new file mode 100755
index 0000000..2c8bdb5
--- /dev/null
+++ b/configure
@@ -0,0 +1,21525 @@
+#! /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
new file mode 100755
index 0000000..b3daac4
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,182 @@
+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
new file mode 100755
index 0000000..04701da
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,530 @@
+#! /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
new file mode 100755
index 0000000..4d4a951
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,323 @@
+#!/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
new file mode 100644
index 0000000..8fc56db
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,6871 @@
+# 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
new file mode 100755
index 0000000..894e786
--- /dev/null
+++ b/missing
@@ -0,0 +1,360 @@
+#! /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
new file mode 100755
index 0000000..dc6cc26
--- /dev/null
+++ b/talk/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS=base xmllite xmpp p2p session third_party examples 
+
+EXTRA_DIST=libjingle.sln libjingle.vcproj
diff --git a/talk/Makefile.in b/talk/Makefile.in
new file mode 100644
index 0000000..954fd7f
--- /dev/null
+++ b/talk/Makefile.in
@@ -0,0 +1,489 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-exec-recursive install-info-recursive \
+	install-recursive installcheck-recursive installdirs-recursive \
+	pdf-recursive ps-recursive uninstall-info-recursive \
+	uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+SUBDIRS = base xmllite xmpp p2p session third_party examples 
+EXTRA_DIST = libjingle.sln libjingle.vcproj
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(mkdir_p) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
+	clean clean-generic clean-libtool clean-recursive ctags \
+	ctags-recursive distclean distclean-generic distclean-libtool \
+	distclean-recursive distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-recursive \
+	mostlyclean mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/base/Equifax_Secure_Global_eBusiness_CA-1.h b/talk/base/Equifax_Secure_Global_eBusiness_CA-1.h
new file mode 100755
index 0000000..6ff97a6
--- /dev/null
+++ b/talk/base/Equifax_Secure_Global_eBusiness_CA-1.h
@@ -0,0 +1,55 @@
+// This file is the Equifax Secure global eBusiness CA-1 certificate
+// in C form.
+
+// It was generated with the following command line:
+// > openssl x509 -in Equifax_Secure_Global_eBusiness_CA-1.cer -noout -C
+
+// The certificate was retrieved from:
+// http://www.geotrust.com/resources/root_certificates/certificates/Equifax_Secure_Global_eBusiness_CA-1.cer
+
+/* subject:/C=US/O=Equifax Secure Inc./CN=Equifax Secure Global eBusiness CA-1 */
+/* issuer :/C=US/O=Equifax Secure Inc./CN=Equifax Secure Global eBusiness CA-1 */
+unsigned char EquifaxSecureGlobalEBusinessCA1_certificate[660]={
+0x30,0x82,0x02,0x90,0x30,0x82,0x01,0xF9,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
+0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,0x00,0x30,
+0x5A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1C,
+0x30,0x1A,0x06,0x03,0x55,0x04,0x0A,0x13,0x13,0x45,0x71,0x75,0x69,0x66,0x61,0x78,
+0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x2D,0x30,0x2B,
+0x06,0x03,0x55,0x04,0x03,0x13,0x24,0x45,0x71,0x75,0x69,0x66,0x61,0x78,0x20,0x53,
+0x65,0x63,0x75,0x72,0x65,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x65,0x42,0x75,
+0x73,0x69,0x6E,0x65,0x73,0x73,0x20,0x43,0x41,0x2D,0x31,0x30,0x1E,0x17,0x0D,0x39,
+0x39,0x30,0x36,0x32,0x31,0x30,0x34,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x30,
+0x30,0x36,0x32,0x31,0x30,0x34,0x30,0x30,0x30,0x30,0x5A,0x30,0x5A,0x31,0x0B,0x30,
+0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1C,0x30,0x1A,0x06,0x03,
+0x55,0x04,0x0A,0x13,0x13,0x45,0x71,0x75,0x69,0x66,0x61,0x78,0x20,0x53,0x65,0x63,
+0x75,0x72,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,
+0x03,0x13,0x24,0x45,0x71,0x75,0x69,0x66,0x61,0x78,0x20,0x53,0x65,0x63,0x75,0x72,
+0x65,0x20,0x47,0x6C,0x6F,0x62,0x61,0x6C,0x20,0x65,0x42,0x75,0x73,0x69,0x6E,0x65,
+0x73,0x73,0x20,0x43,0x41,0x2D,0x31,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,
+0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,
+0x02,0x81,0x81,0x00,0xBA,0xE7,0x17,0x90,0x02,0x65,0xB1,0x34,0x55,0x3C,0x49,0xC2,
+0x51,0xD5,0xDF,0xA7,0xD1,0x37,0x8F,0xD1,0xE7,0x81,0x73,0x41,0x52,0x60,0x9B,0x9D,
+0xA1,0x17,0x26,0x78,0xAD,0xC7,0xB1,0xE8,0x26,0x94,0x32,0xB5,0xDE,0x33,0x8D,0x3A,
+0x2F,0xDB,0xF2,0x9A,0x7A,0x5A,0x73,0x98,0xA3,0x5C,0xE9,0xFB,0x8A,0x73,0x1B,0x5C,
+0xE7,0xC3,0xBF,0x80,0x6C,0xCD,0xA9,0xF4,0xD6,0x2B,0xC0,0xF7,0xF9,0x99,0xAA,0x63,
+0xA2,0xB1,0x47,0x02,0x0F,0xD4,0xE4,0x51,0x3A,0x12,0x3C,0x6C,0x8A,0x5A,0x54,0x84,
+0x70,0xDB,0xC1,0xC5,0x90,0xCF,0x72,0x45,0xCB,0xA8,0x59,0xC0,0xCD,0x33,0x9D,0x3F,
+0xA3,0x96,0xEB,0x85,0x33,0x21,0x1C,0x3E,0x1E,0x3E,0x60,0x6E,0x76,0x9C,0x67,0x85,
+0xC5,0xC8,0xC3,0x61,0x02,0x03,0x01,0x00,0x01,0xA3,0x66,0x30,0x64,0x30,0x11,0x06,
+0x09,0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x07,
+0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,
+0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xBE,0xA8,
+0xA0,0x74,0x72,0x50,0x6B,0x44,0xB7,0xC9,0x23,0xD8,0xFB,0xA8,0xFF,0xB3,0x57,0x6B,
+0x68,0x6C,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xBE,0xA8,0xA0,
+0x74,0x72,0x50,0x6B,0x44,0xB7,0xC9,0x23,0xD8,0xFB,0xA8,0xFF,0xB3,0x57,0x6B,0x68,
+0x6C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,0x05,0x00,
+0x03,0x81,0x81,0x00,0x30,0xE2,0x01,0x51,0xAA,0xC7,0xEA,0x5F,0xDA,0xB9,0xD0,0x65,
+0x0F,0x30,0xD6,0x3E,0xDA,0x0D,0x14,0x49,0x6E,0x91,0x93,0x27,0x14,0x31,0xEF,0xC4,
+0xF7,0x2D,0x45,0xF8,0xEC,0xC7,0xBF,0xA2,0x41,0x0D,0x23,0xB4,0x92,0xF9,0x19,0x00,
+0x67,0xBD,0x01,0xAF,0xCD,0xE0,0x71,0xFC,0x5A,0xCF,0x64,0xC4,0xE0,0x96,0x98,0xD0,
+0xA3,0x40,0xE2,0x01,0x8A,0xEF,0x27,0x07,0xF1,0x65,0x01,0x8A,0x44,0x2D,0x06,0x65,
+0x75,0x52,0xC0,0x86,0x10,0x20,0x21,0x5F,0x6C,0x6B,0x0F,0x6C,0xAE,0x09,0x1C,0xAF,
+0xF2,0xA2,0x18,0x34,0xC4,0x75,0xA4,0x73,0x1C,0xF1,0x8D,0xDC,0xEF,0xAD,0xF9,0xB3,
+0x76,0xB4,0x92,0xBF,0xDC,0x95,0x10,0x1E,0xBE,0xCB,0xC8,0x3B,0x5A,0x84,0x60,0x19,
+0x56,0x94,0xA9,0x55,
+};
diff --git a/talk/base/Makefile.am b/talk/base/Makefile.am
new file mode 100755
index 0000000..4a1e321
--- /dev/null
+++ b/talk/base/Makefile.am
@@ -0,0 +1,152 @@
+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) `pkg-config --cflags gtk+-2.0`
+
+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/Makefile.in b/talk/base/Makefile.in
new file mode 100644
index 0000000..c8de0b0
--- /dev/null
+++ b/talk/base/Makefile.in
@@ -0,0 +1,722 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = natserver$(EXEEXT) nat_unittest$(EXEEXT) \
+	virtualsocket_unittest$(EXEEXT)
+subdir = talk/base
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketbase_la_LIBADD =
+am_libcricketbase_la_OBJECTS = socketaddress.lo time.lo \
+	asyncudpsocket.lo messagequeue.lo thread.lo \
+	physicalsocketserver.lo bytebuffer.lo asyncpacketsocket.lo \
+	network.lo asynctcpsocket.lo socketadapters.lo md5c.lo \
+	base64.lo task.lo taskrunner.lo host.lo proxydetect.lo \
+	socketaddresspair.lo stringencode.lo stringdigest.lo \
+	stringutils.lo proxyinfo.lo common.lo logging.lo stream.lo \
+	ssladapter.lo openssladapter.lo helpers.lo asynchttprequest.lo \
+	firewallsocketserver.lo httpcommon.lo httpbase.lo \
+	httpclient.lo httpserver.lo socketpool.lo signalthread.lo \
+	autodetectproxy.lo urlencode.lo pathutils.lo fileutils.lo \
+	unixfilesystem.lo tarstream.lo streamutils.lo diskcache.lo \
+	diskcachestd.lo
+libcricketbase_la_OBJECTS = $(am_libcricketbase_la_OBJECTS)
+libcrickettest_la_LIBADD =
+am_libcrickettest_la_OBJECTS = testclient.lo natserver.lo \
+	natsocketfactory.lo nattypes.lo virtualsocketserver.lo
+libcrickettest_la_OBJECTS = $(am_libcrickettest_la_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am_nat_unittest_OBJECTS = nat_unittest.$(OBJEXT)
+nat_unittest_OBJECTS = $(am_nat_unittest_OBJECTS)
+nat_unittest_DEPENDENCIES = libcrickettest.la libcricketbase.la
+am_natserver_OBJECTS = natserver_main.$(OBJEXT)
+natserver_OBJECTS = $(am_natserver_OBJECTS)
+natserver_DEPENDENCIES = libcrickettest.la libcricketbase.la
+am_virtualsocket_unittest_OBJECTS = virtualsocket_unittest.$(OBJEXT)
+virtualsocket_unittest_OBJECTS = $(am_virtualsocket_unittest_OBJECTS)
+virtualsocket_unittest_DEPENDENCIES = libcrickettest.la \
+	libcricketbase.la
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketbase_la_SOURCES) $(libcrickettest_la_SOURCES) \
+	$(nat_unittest_SOURCES) $(natserver_SOURCES) \
+	$(virtualsocket_unittest_SOURCES)
+DIST_SOURCES = $(libcricketbase_la_SOURCES) \
+	$(libcrickettest_la_SOURCES) $(nat_unittest_SOURCES) \
+	$(natserver_SOURCES) $(virtualsocket_unittest_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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) `pkg-config --cflags gtk+-2.0`
+noinst_LTLIBRARIES = libcricketbase.la libcrickettest.la
+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
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/base/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/base/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketbase.la: $(libcricketbase_la_OBJECTS) $(libcricketbase_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketbase_la_LDFLAGS) $(libcricketbase_la_OBJECTS) $(libcricketbase_la_LIBADD) $(LIBS)
+libcrickettest.la: $(libcrickettest_la_OBJECTS) $(libcrickettest_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcrickettest_la_LDFLAGS) $(libcrickettest_la_OBJECTS) $(libcrickettest_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+nat_unittest$(EXEEXT): $(nat_unittest_OBJECTS) $(nat_unittest_DEPENDENCIES) 
+	@rm -f nat_unittest$(EXEEXT)
+	$(CXXLINK) $(nat_unittest_LDFLAGS) $(nat_unittest_OBJECTS) $(nat_unittest_LDADD) $(LIBS)
+natserver$(EXEEXT): $(natserver_OBJECTS) $(natserver_DEPENDENCIES) 
+	@rm -f natserver$(EXEEXT)
+	$(CXXLINK) $(natserver_LDFLAGS) $(natserver_OBJECTS) $(natserver_LDADD) $(LIBS)
+virtualsocket_unittest$(EXEEXT): $(virtualsocket_unittest_OBJECTS) $(virtualsocket_unittest_DEPENDENCIES) 
+	@rm -f virtualsocket_unittest$(EXEEXT)
+	$(CXXLINK) $(virtualsocket_unittest_LDFLAGS) $(virtualsocket_unittest_OBJECTS) $(virtualsocket_unittest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asynchttprequest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asyncpacketsocket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asynctcpsocket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asyncudpsocket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/autodetectproxy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytebuffer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskcache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskcachestd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileutils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/firewallsocketserver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helpers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/host.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpbase.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpclient.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpcommon.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpserver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5c.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messagequeue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nat_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/natserver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/natserver_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/natsocketfactory.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nattypes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssladapter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pathutils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/physicalsocketserver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxydetect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxyinfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signalthread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socketadapters.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socketaddress.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socketaddresspair.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socketpool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssladapter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streamutils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringdigest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringencode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringutils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tarstream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/taskrunner.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testclient.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unixfilesystem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/urlencode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtualsocket_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtualsocketserver.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+	ctags distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/base/asyncfile.h b/talk/base/asyncfile.h
new file mode 100755
index 0000000..1437979
--- /dev/null
+++ b/talk/base/asyncfile.h
@@ -0,0 +1,56 @@
+/*
+ * 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_ASYNCFILE_H__
+#define TALK_BASE_ASYNCFILE_H__
+
+#include "talk/base/sigslot.h"
+
+namespace talk_base {
+
+// Provides the ability to perform file I/O asynchronously.
+// TODO: Create a common base class with AsyncSocket.
+class AsyncFile {
+public:
+  virtual ~AsyncFile() {}
+
+  // Determines whether the file will receive read events.
+  virtual bool readable() = 0;
+  virtual void set_readable(bool value) = 0;
+
+  // Determines whether the file will receive write events.
+  virtual bool writable() = 0;
+  virtual void set_writable(bool value) = 0;
+
+  sigslot::signal1<AsyncFile*> SignalReadEvent;
+  sigslot::signal1<AsyncFile*> SignalWriteEvent;
+  sigslot::signal2<AsyncFile*,int> SignalCloseEvent;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_ASYNCFILE_H__
diff --git a/talk/base/asynchttprequest.cc b/talk/base/asynchttprequest.cc
new file mode 100755
index 0000000..bf7bc85
--- /dev/null
+++ b/talk/base/asynchttprequest.cc
@@ -0,0 +1,155 @@
+#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"
+#include "talk/base/asynchttprequest.h"
+
+using 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;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+{
+}
+
+void AsyncHttpRequest::DoWork() {
+  // TODO: Rewrite this to use the thread's native socket server, and a more
+  // natural flow?
+
+  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_);
+  if (secure_)
+    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));
+
+  if (transparent_proxy) {
+    client_.set_proxy(proxy_);
+  }
+  client_.set_fail_redirect(fail_redirect_);
+
+  talk_base::SocketAddress server(host_, port_);
+  client_.set_server(server);
+
+  HttpMonitor monitor(ss);
+  monitor.Connect(&client_);
+  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;
+    }
+    return;
+  }
+
+  std::string value;
+  if (client_.response().hasHeader(HH_LOCATION, &value)) {
+    response_redirect_ = value.c_str();
+  }
+}
diff --git a/talk/base/asynchttprequest.h b/talk/base/asynchttprequest.h
new file mode 100755
index 0000000..65bfa26
--- /dev/null
+++ b/talk/base/asynchttprequest.h
@@ -0,0 +1,140 @@
+#ifndef _ASYNCHTTPREQUEST_H_
+#define _ASYNCHTTPREQUEST_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"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// 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 sigslot::has_slots<> {
+public:
+  AsyncHttpRequest(const std::string &user_agent);
+
+  void set_proxy(const talk_base::ProxyInfo& proxy) {
+    proxy_ = proxy;
+  }
+  void set_firewall(talk_base::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(); }
+   
+private:
+  // SignalThread Interface
+  virtual void DoWork();
+  
+  talk_base::ProxyInfo proxy_;
+  talk_base::FirewallManager * firewall_;
+  std::string host_;
+  int port_;
+  bool secure_;
+  int timeout_;
+  bool fail_redirect_;
+  HttpClient client_;
+  std::string response_redirect_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// HttpMonitor
+///////////////////////////////////////////////////////////////////////////////
+
+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_
diff --git a/talk/base/asyncpacketsocket.cc b/talk/base/asyncpacketsocket.cc
new file mode 100755
index 0000000..37ba058
--- /dev/null
+++ b/talk/base/asyncpacketsocket.cc
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#include "talk/base/asyncpacketsocket.h"
+
+namespace talk_base {
+
+AsyncPacketSocket::AsyncPacketSocket(AsyncSocket* socket) : socket_(socket) {
+}
+
+AsyncPacketSocket::~AsyncPacketSocket() {
+  delete socket_;
+}
+
+SocketAddress AsyncPacketSocket::GetLocalAddress() const {
+  return socket_->GetLocalAddress();
+}
+
+SocketAddress AsyncPacketSocket::GetRemoteAddress() const {
+  return socket_->GetRemoteAddress();
+}
+
+int AsyncPacketSocket::Bind(const SocketAddress& addr) {
+  return socket_->Bind(addr);
+}
+
+int AsyncPacketSocket::Connect(const SocketAddress& addr) {
+  return socket_->Connect(addr);
+}
+
+int AsyncPacketSocket::Send(const void *pv, size_t cb) {
+  return socket_->Send(pv, cb);
+}
+
+int AsyncPacketSocket::SendTo(
+    const void *pv, size_t cb, const SocketAddress& addr) {
+  return socket_->SendTo(pv, cb, addr);
+}
+
+int AsyncPacketSocket::Close() {
+  return socket_->Close();
+}
+
+int AsyncPacketSocket::SetOption(Socket::Option opt, int value) {
+  return socket_->SetOption(opt, value);
+}
+
+int AsyncPacketSocket::GetError() const {
+  return socket_->GetError();
+}
+
+void AsyncPacketSocket::SetError(int error) {
+  return socket_->SetError(error);
+}
+
+} // namespace talk_base
diff --git a/talk/base/asyncpacketsocket.h b/talk/base/asyncpacketsocket.h
new file mode 100755
index 0000000..c6172a7
--- /dev/null
+++ b/talk/base/asyncpacketsocket.h
@@ -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.
+ */
+
+#ifndef TALK_BASE_ASYNCPACKETSOCKET_H__
+#define TALK_BASE_ASYNCPACKETSOCKET_H__
+
+#include "talk/base/asyncsocket.h"
+
+namespace talk_base {
+
+// 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);
+  virtual ~AsyncPacketSocket();
+
+  // Relevant socket methods:
+  virtual SocketAddress GetLocalAddress() const;
+  virtual SocketAddress GetRemoteAddress() const;
+  virtual int Bind(const SocketAddress& addr);
+  virtual int Connect(const SocketAddress& addr);
+  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 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;
+
+protected:
+  AsyncSocket* socket_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_ASYNCPACKETSOCKET_H__
diff --git a/talk/base/asyncsocket.h b/talk/base/asyncsocket.h
new file mode 100755
index 0000000..ad0dfb4
--- /dev/null
+++ b/talk/base/asyncsocket.h
@@ -0,0 +1,91 @@
+/*
+ * 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_ASYNCSOCKET_H__
+#define TALK_BASE_ASYNCSOCKET_H__
+
+#include "talk/base/sigslot.h"
+#include "talk/base/socket.h"
+
+namespace talk_base {
+
+// Provides the ability to perform socket I/O asynchronously.
+class AsyncSocket : public Socket, public sigslot::has_slots<>  {
+public:
+  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
+};
+
+class AsyncSocketAdapter : public AsyncSocket {
+public:
+  AsyncSocketAdapter(Socket * socket) : socket_(socket) {
+  }
+  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 ~AsyncSocketAdapter() { delete socket_; }
+
+  virtual SocketAddress GetLocalAddress() const { return socket_->GetLocalAddress(); }
+  virtual SocketAddress GetRemoteAddress() const { return socket_->GetRemoteAddress(); }
+
+  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_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_ASYNCSOCKET_H__
diff --git a/talk/base/asynctcpsocket.cc b/talk/base/asynctcpsocket.cc
new file mode 100755
index 0000000..84d1401
--- /dev/null
+++ b/talk/base/asynctcpsocket.cc
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#include "talk/base/asynctcpsocket.h"
+#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
+
+namespace talk_base {
+
+const size_t MAX_PACKET_SIZE = 64 * 1024;
+
+typedef uint16 PacketLength;
+const size_t PKT_LEN_SIZE = sizeof(PacketLength);
+
+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) {
+  inbuf_ = new char[insize_];
+  outbuf_ = new char[outsize_];
+
+  ASSERT(socket_ != NULL);
+  socket_->SignalConnectEvent.connect(this, &AsyncTCPSocket::OnConnectEvent);
+  socket_->SignalReadEvent.connect(this, &AsyncTCPSocket::OnReadEvent);
+  socket_->SignalWriteEvent.connect(this, &AsyncTCPSocket::OnWriteEvent);
+  socket_->SignalCloseEvent.connect(this, &AsyncTCPSocket::OnCloseEvent);
+}
+
+AsyncTCPSocket::~AsyncTCPSocket() {
+  delete [] inbuf_;
+  delete [] outbuf_;
+}
+
+int AsyncTCPSocket::Send(const void *pv, size_t cb) {
+  if (cb > MAX_PACKET_SIZE) {
+    socket_->SetError(EMSGSIZE);
+    return -1;
+  }
+
+  // If we are blocking on send, then silently drop this packet
+  if (outpos_)
+    return static_cast<int>(cb);
+
+  PacketLength pkt_len = HostToNetwork16(static_cast<PacketLength>(cb));
+  memcpy(outbuf_, &pkt_len, PKT_LEN_SIZE);
+  memcpy(outbuf_ + PKT_LEN_SIZE, pv, cb);
+  outpos_ = PKT_LEN_SIZE + cb;
+
+  int res = Flush();
+  if (res <= 0) {
+    // drop packet if we made no progress
+    outpos_ = 0; 
+    return res;
+  }
+
+  // We claim to have sent the whole thing, even if we only sent partial
+  return static_cast<int>(cb);
+}
+
+int AsyncTCPSocket::SendTo(const void *pv, size_t cb, const SocketAddress& addr) {
+  if (addr == GetRemoteAddress())
+    return Send(pv, cb);
+
+  ASSERT(false);
+  socket_->SetError(ENOTCONN);
+  return -1;
+}
+
+int AsyncTCPSocket::SendRaw(const void * pv, size_t cb) {
+  if (outpos_ + cb > outsize_) {
+    socket_->SetError(EMSGSIZE);
+    return -1;
+  }
+
+  memcpy(outbuf_ + outpos_, pv, cb);
+  outpos_ += cb;
+
+  return Flush();
+}
+
+void AsyncTCPSocket::ProcessInput(char * data, size_t& len) {
+  SocketAddress remote_addr(GetRemoteAddress());
+
+  while (true) {
+    if (len < PKT_LEN_SIZE)
+      return;
+
+    PacketLength pkt_len;
+    memcpy(&pkt_len, data, PKT_LEN_SIZE);
+    pkt_len = NetworkToHost16(pkt_len);
+
+    if (len < PKT_LEN_SIZE + pkt_len)
+      return;
+
+    SignalReadPacket(data + PKT_LEN_SIZE, pkt_len, remote_addr, this);
+
+    len -= PKT_LEN_SIZE + pkt_len;
+    if (len > 0) {
+      memmove(data, data + PKT_LEN_SIZE + pkt_len, len);
+    }
+  }
+}
+
+int AsyncTCPSocket::Flush() {
+  int res = socket_->Send(outbuf_, outpos_);
+  if (res <= 0) {
+    return res;
+  }
+  if (static_cast<size_t>(res) <= outpos_) {
+    outpos_ -= res;
+  } else {
+    ASSERT(false);
+    return -1;
+  }
+  if (outpos_ > 0) {
+    memmove(outbuf_, outbuf_ + res, outpos_);
+  }
+  return res;
+}
+
+void AsyncTCPSocket::OnConnectEvent(AsyncSocket* socket) {
+  SignalConnect(this);
+}
+
+void AsyncTCPSocket::OnReadEvent(AsyncSocket* socket) {
+  ASSERT(socket == socket_);
+
+  int len = socket_->Recv(inbuf_ + inpos_, insize_ - inpos_);
+  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);
+    }
+    return;
+  }
+
+  inpos_ += len;
+
+  ProcessInput(inbuf_, inpos_);
+
+  if (inpos_ >= insize_) {
+    LOG(INFO) << "input buffer overflow";
+    ASSERT(false);
+    inpos_ = 0;
+  }
+}
+
+void AsyncTCPSocket::OnWriteEvent(AsyncSocket* socket) {
+  ASSERT(socket == socket_);
+
+  if (outpos_ > 0) {
+    Flush();
+  }
+}
+
+void AsyncTCPSocket::OnCloseEvent(AsyncSocket* socket, int error) {
+  SignalClose(this, error);
+}
+
+} // namespace talk_base
diff --git a/talk/base/asynctcpsocket.h b/talk/base/asynctcpsocket.h
new file mode 100755
index 0000000..2509451
--- /dev/null
+++ b/talk/base/asynctcpsocket.h
@@ -0,0 +1,68 @@
+/*
+ * 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_ASYNCTCPSOCKET_H__
+#define TALK_BASE_ASYNCTCPSOCKET_H__
+
+#include "talk/base/asyncpacketsocket.h"
+
+namespace talk_base {
+
+// Simulates UDP semantics over TCP.  Send and Recv packet sizes
+// are preserved, and drops packets silently on Send, rather than
+// buffer them in user space.
+class AsyncTCPSocket : public AsyncPacketSocket {
+public:
+  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);
+
+  sigslot::signal1<AsyncTCPSocket*> SignalConnect;
+  sigslot::signal2<AsyncTCPSocket*,int> SignalClose;
+
+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_;
+
+  int Flush();
+
+  // Called by the underlying socket
+  void OnConnectEvent(AsyncSocket* socket);
+  void OnReadEvent(AsyncSocket* socket);
+  void OnWriteEvent(AsyncSocket* socket);
+  void OnCloseEvent(AsyncSocket* socket, int error);
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_ASYNCTCPSOCKET_H__
diff --git a/talk/base/asyncudpsocket.cc b/talk/base/asyncudpsocket.cc
new file mode 100755
index 0000000..a0c967d
--- /dev/null
+++ b/talk/base/asyncudpsocket.cc
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#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) {
+  size_ = BUF_SIZE;
+  buf_ = new char[size_];
+
+  assert(socket_);
+  // The socket should start out readable but not writable.
+  socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
+}
+
+AsyncUDPSocket::~AsyncUDPSocket() {
+  delete [] buf_;
+}
+
+void AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) {
+  assert(socket == socket_);
+
+  SocketAddress remote_addr;
+  int len = socket_->RecvFrom(buf_, size_, &remote_addr);
+  if (len < 0) {
+    // TODO: Do something better like forwarding the error to the user.
+    PLOG(LS_ERROR, socket_->GetError()) << "recvfrom";
+    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.
+
+  SignalReadPacket(buf_, (size_t)len, remote_addr, this);
+}
+
+} // namespace talk_base
diff --git a/talk/base/asyncudpsocket.h b/talk/base/asyncudpsocket.h
new file mode 100755
index 0000000..8232938
--- /dev/null
+++ b/talk/base/asyncudpsocket.h
@@ -0,0 +1,59 @@
+/*
+ * 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_ASYNCUDPSOCKET_H__
+#define TALK_BASE_ASYNCUDPSOCKET_H__
+
+#include "talk/base/asyncpacketsocket.h"
+#include "talk/base/socketfactory.h"
+
+namespace talk_base {
+
+// 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);
+  virtual ~AsyncUDPSocket();
+
+private:
+  char* buf_;
+  size_t size_;
+
+  // Called when the underlying socket is ready to be read from.
+  void OnReadEvent(AsyncSocket* socket);
+};
+
+// Creates a new socket for sending asynchronous UDP packets using an
+// asynchronous socket from the given factory.
+inline AsyncUDPSocket* CreateAsyncUDPSocket(SocketFactory* factory) {
+  return new AsyncUDPSocket(factory->CreateAsyncSocket(SOCK_DGRAM));
+}
+
+} // namespace talk_base
+
+#endif // TALK_BASE_ASYNCUDPSOCKET_H__
diff --git a/talk/base/autodetectproxy.cc b/talk/base/autodetectproxy.cc
new file mode 100755
index 0000000..aa2feed
--- /dev/null
+++ b/talk/base/autodetectproxy.cc
@@ -0,0 +1,178 @@
+/*
+ * 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/autodetectproxy.h"
+#include "talk/base/httpcommon.h"
+#include "talk/xmpp/xmppclientsettings.h"
+#include "talk/base/proxydetect.h"
+
+using 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
+};
+
+AutoDetectProxy::AutoDetectProxy(const std::string& user_agent)
+: agent_(user_agent), socket_(NULL), next_(0)
+{
+}
+
+AutoDetectProxy::~AutoDetectProxy() {
+  delete socket_;
+}
+
+void AutoDetectProxy::DoWork() {
+  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());
+  if (url.valid()) {
+    LOG(LS_WARNING) << "AutoDetectProxy removing http prefix on proxy host";
+    proxy_.address.SetIP(url.server());
+  }
+  if (proxy_.type == talk_base::PROXY_UNKNOWN) {
+    //LOG(LS_INFO) << "Proxy classification start";
+    Next();
+    // Process I/O until Stop()
+    Thread::Current()->ProcessMessages(kForever);
+  }
+}
+
+void AutoDetectProxy::OnMessage(Message *msg) {
+  if (MSG_TIMEOUT == msg->message_id) {
+    OnCloseEvent(socket_, ETIMEDOUT);
+  } else {
+    SignalThread::OnMessage(msg);
+  }
+}
+
+void AutoDetectProxy::Next() {
+  if (TEST_ORDER[next_] >= talk_base::PROXY_UNKNOWN) {
+    Complete(talk_base::PROXY_UNKNOWN);
+    return;
+  }
+
+  LOG(LS_VERBOSE) << "AutoDetectProxy connecting to "
+                  << proxy_.address.ToString();
+
+  if (socket_) {
+    Thread::Current()->Clear(this, MSG_TIMEOUT);
+    socket_->Close();
+    Thread::Current()->Dispose(socket_);
+    socket_ = NULL;
+  }
+
+  socket_ = Thread::Current()->socketserver()->CreateAsyncSocket(SOCK_STREAM);
+  socket_->SignalConnectEvent.connect(this, &AutoDetectProxy::OnConnectEvent);
+  socket_->SignalReadEvent.connect(this, &AutoDetectProxy::OnReadEvent);
+  socket_->SignalCloseEvent.connect(this, &AutoDetectProxy::OnCloseEvent);
+  socket_->Connect(proxy_.address);
+
+  // Timeout after 2 seconds
+  Thread::Current()->PostDelayed(2000, this, MSG_TIMEOUT);
+}
+
+void AutoDetectProxy::Complete(talk_base::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;
+  LOG_V(sev) << "AutoDetectProxy detected " << proxy_.address.ToString()
+             << " as type " << proxy_.type;
+
+  Thread::Current()->MessageQueue::Stop();
+}
+
+void AutoDetectProxy::OnConnectEvent(talk_base::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;
+  }
+
+  LOG(LS_VERBOSE) << "AutoDetectProxy probing type " << TEST_ORDER[next_]
+                  << " sending " << probe.size() << " bytes";
+  socket_->Send(probe.data(), probe.size());
+}
+
+void AutoDetectProxy::OnReadEvent(talk_base::AsyncSocket * socket) {
+  char data[257];
+  int len = socket_->Recv(data, 256);
+  if (len > 0) {
+    data[len] = 0;
+    LOG(LS_VERBOSE) << "AutoDetectProxy read " << len << " bytes";
+  }
+
+  switch (TEST_ORDER[next_]) {
+  case talk_base::PROXY_HTTPS:
+    if ((len >= 2) && (data[0] == '\x05')) {
+      Complete(talk_base::PROXY_SOCKS5);
+      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) {
+  LOG(LS_VERBOSE) << "AutoDetectProxy closed with error: " << error;
+  ++next_;
+  Next();
+}
diff --git a/talk/base/autodetectproxy.h b/talk/base/autodetectproxy.h
new file mode 100755
index 0000000..9633d31
--- /dev/null
+++ b/talk/base/autodetectproxy.h
@@ -0,0 +1,68 @@
+#ifndef _AUTODETECTPROXY_H_
+#define _AUTODETECTPROXY_H_
+
+#include "talk/base/sigslot.h"
+#include "talk/base/physicalsocketserver.h"
+#include "talk/base/proxyinfo.h"
+#include "talk/base/signalthread.h"
+#include "talk/base/cryptstring.h"
+
+namespace buzz { 
+class XmppClientSettings; 
+}
+
+namespace talk_base { 
+
+///////////////////////////////////////////////////////////////////////////////
+// AutoDetectProxy
+///////////////////////////////////////////////////////////////////////////////
+
+class AsyncSocket;
+
+class AutoDetectProxy : public SignalThread, public sigslot::has_slots<> {
+public:
+  AutoDetectProxy(const std::string& user_agent);
+
+  const talk_base::ProxyInfo& proxy() const { return proxy_; }
+
+  void set_server_url(const std::string& url) {
+    server_url_ = url;
+  }
+  void set_proxy(const SocketAddress& proxy) {
+    proxy_.type = PROXY_UNKNOWN;
+    proxy_.address = proxy;
+  }
+  void set_auth_info(bool use_auth, const std::string& username,
+      const CryptString& password) {
+    if (use_auth) {
+      proxy_.username = username;
+      proxy_.password = password;
+    }
+  }
+
+protected:
+  virtual ~AutoDetectProxy();
+
+  // SignalThread Interface
+  virtual void DoWork();
+  virtual void OnMessage(Message *msg);
+
+  void Next();
+  void Complete(ProxyType type);
+
+  void OnConnectEvent(AsyncSocket * socket);
+  void OnReadEvent(AsyncSocket * socket);
+  void OnCloseEvent(AsyncSocket * socket, int error);
+
+private:
+  std::string agent_, server_url_;
+  ProxyInfo proxy_;
+  AsyncSocket * socket_;
+  int next_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif  // _AUTODETECTPROXY_H_
diff --git a/talk/base/base64.cc b/talk/base/base64.cc
new file mode 100755
index 0000000..53e5bac
--- /dev/null
+++ b/talk/base/base64.cc
@@ -0,0 +1,196 @@
+
+//*********************************************************************
+//* Base64 - a simple base64 encoder and decoder.
+//*
+//*     Copyright (c) 1999, Bob Withers - bwit@pobox.com
+//*
+//* This code may be freely used for any purpose, either personal
+//* or commercial, provided the authors copyright notice remains
+//* intact.
+//*
+//* Enhancements by Stanley Yamane:
+//*     o reverse lookup table for the decode function
+//*     o reserve string buffer space in advance
+//*
+//*********************************************************************
+
+#include "talk/base/base64.h"
+
+using std::string;
+
+namespace talk_base {
+
+static const char fillchar = '=';
+static const string::size_type np = string::npos;
+
+const string Base64::Base64Table(
+  // 0000000000111111111122222222223333333333444444444455555555556666
+  // 0123456789012345678901234567890123456789012345678901234567890123
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
+
+// 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[] = {
+// 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
+};
+
+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);
+}
+
+string Base64::encode(const string& data) {
+  string::size_type i;
+  char c;
+  string::size_type len = data.length();
+  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);
+}
+
+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) {         
+        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) {
+        break;
+      }
+
+      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);
+    }
+  }
+
+  return(ret);
+}
+
+} // namespace talk_base
diff --git a/talk/base/base64.h b/talk/base/base64.h
new file mode 100755
index 0000000..2b58761
--- /dev/null
+++ b/talk/base/base64.h
@@ -0,0 +1,32 @@
+
+//*********************************************************************
+//* C_Base64 - a simple base64 encoder and decoder.
+//*
+//*     Copyright (c) 1999, Bob Withers - bwit@pobox.com
+//*
+//* This code may be freely used for any purpose, either personal
+//* or commercial, provided the authors copyright notice remains
+//* intact.
+//*********************************************************************
+
+#ifndef TALK_BASE_BASE64_H__
+#define TALK_BASE_BASE64_H__
+
+#include <string>
+
+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);
+private:
+  static const std::string Base64::Base64Table;
+  static const std::string::size_type Base64::DecodeTable[];
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_BASE64_H__
diff --git a/talk/base/basicdefs.h b/talk/base/basicdefs.h
new file mode 100755
index 0000000..886c287
--- /dev/null
+++ b/talk/base/basicdefs.h
@@ -0,0 +1,37 @@
+/*
+ * 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_BASICDEFS_H__
+#define TAKL_BASE_BASICDEFS_H__
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define ARRAY_SIZE(x) (static_cast<int>((sizeof(x)/sizeof(x[0]))))
+
+#endif // TAKL_BASE_BASICDEFS_H__
diff --git a/talk/base/basictypes.h b/talk/base/basictypes.h
new file mode 100755
index 0000000..47588ad
--- /dev/null
+++ b/talk/base/basictypes.h
@@ -0,0 +1,85 @@
+/*
+ * 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_BASICTYPES_H__
+#define TALK_BASE_BASICTYPES_H__
+
+#ifdef COMPILER_MSVC
+typedef __int64 int64;
+#else
+typedef long long int64;
+#endif /* COMPILER_MSVC */
+typedef long int32;
+typedef short int16;
+typedef char int8;
+
+#ifdef COMPILER_MSVC
+typedef unsigned __int64 uint64;
+typedef __int64 int64;
+#else
+typedef unsigned long long uint64;
+typedef long long int64;
+#endif /* COMPILER_MSVC */
+typedef unsigned long uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+
+#ifdef WIN32
+typedef int socklen_t;
+#endif
+
+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; }
+}
+
+// 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)
+
+#ifndef UNUSED
+#define UNUSED(x) Unused(static_cast<const void *>(&x))
+#define UNUSED2(x,y) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y))
+#define UNUSED3(x,y,z) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z))
+#define UNUSED4(x,y,z,a) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a))
+#define UNUSED5(x,y,z,a,b) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a)); Unused(static_cast<const void *>(&b))
+inline void Unused(const void *) { }
+#endif // UNUSED
+
+#endif // TALK_BASE_BASICTYPES_H__
diff --git a/talk/base/bytebuffer.cc b/talk/base/bytebuffer.cc
new file mode 100755
index 0000000..7082e1a
--- /dev/null
+++ b/talk/base/bytebuffer.cc
@@ -0,0 +1,166 @@
+/*
+ * 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 "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;
+
+ByteBuffer::ByteBuffer() {
+  start_ = 0;
+  end_   = 0;
+  size_  = DEFAULT_SIZE;
+  bytes_ = new char[size_];
+}
+
+ByteBuffer::ByteBuffer(const char* bytes, size_t len) {
+  start_ = 0;
+  end_   = len;
+  size_  = len;
+  bytes_ = new char[size_];
+  memcpy(bytes_, bytes, end_);
+}
+
+ByteBuffer::ByteBuffer(const char* bytes) {
+  start_ = 0;
+  end_   = strlen(bytes);
+  size_  = end_;
+  bytes_ = new char[size_];
+  memcpy(bytes_, bytes, end_);
+}
+
+ByteBuffer::~ByteBuffer() {
+  delete bytes_;
+}
+
+bool ByteBuffer::ReadUInt8(uint8& val) {
+  return ReadBytes(reinterpret_cast<char*>(&val), 1);
+}
+
+bool ByteBuffer::ReadUInt16(uint16& val) {
+  uint16 v;
+  if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) {
+    return false;
+  } else {
+    val = NetworkToHost16(v);
+    return true;
+  }
+}
+
+bool ByteBuffer::ReadUInt32(uint32& val) {
+  uint32 v;
+  if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) {
+    return false;
+  } else {
+    val = NetworkToHost32(v);
+    return true;
+  }
+}
+
+bool ByteBuffer::ReadString(std::string& val, size_t len) {
+  if (len > Length()) {
+    return false;
+  } else {
+    val.append(bytes_ + start_, len);
+    start_ += len;
+    return true;
+  }
+}
+
+bool ByteBuffer::ReadBytes(char* val, size_t len) {
+  if (len > Length()) {
+    return false;
+  } else {
+    memcpy(val, bytes_ + start_, len);
+    start_ += len;
+    return true;
+  }
+}
+
+void ByteBuffer::WriteUInt8(uint8 val) {
+  WriteBytes(reinterpret_cast<const char*>(&val), 1);
+}
+
+void ByteBuffer::WriteUInt16(uint16 val) {
+  uint16 v = HostToNetwork16(val);
+  WriteBytes(reinterpret_cast<const char*>(&v), 2);
+}
+
+void ByteBuffer::WriteUInt32(uint32 val) {
+  uint32 v = HostToNetwork32(val);
+  WriteBytes(reinterpret_cast<const char*>(&v), 4);
+}
+
+void ByteBuffer::WriteString(const std::string& val) {
+  WriteBytes(val.c_str(), val.size());
+}
+
+void ByteBuffer::WriteBytes(const char* val, size_t len) {
+  if (Length() + len > Capacity())
+    Resize(Length() + len);
+
+  memcpy(bytes_ + end_, val, len);
+  end_ += len;
+}
+
+void ByteBuffer::Resize(size_t size) {
+  if (size > size_)
+    size = _max(size, 3 * size_ / 2);
+
+  size_t len = _min(end_ - start_, size);
+  char* new_bytes = new char[size];
+  memcpy(new_bytes, bytes_ + start_, len);
+  delete [] bytes_;
+
+  start_ = 0;
+  end_   = len;
+  size_  = size;
+  bytes_ = new_bytes;
+}
+
+void ByteBuffer::Shift(size_t size) {
+  if (size > Length())
+    return;
+
+  end_ = Length() - size;
+  memmove(bytes_, bytes_ + start_ + size, end_);
+  start_ = 0;
+}
+
+} // namespace talk_base
diff --git a/talk/base/bytebuffer.h b/talk/base/bytebuffer.h
new file mode 100755
index 0000000..0a93194
--- /dev/null
+++ b/talk/base/bytebuffer.h
@@ -0,0 +1,71 @@
+/*
+ * 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_BYTEBUFFER_H__
+#define TALK_BASE_BYTEBUFFER_H__
+
+#include <string>
+#include "talk/base/basictypes.h"
+
+namespace talk_base {
+
+class ByteBuffer {
+public:
+  ByteBuffer();
+  ByteBuffer(const char* bytes, size_t len);
+  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_; }
+
+  bool ReadUInt8(uint8& val);
+  bool ReadUInt16(uint16& val);
+  bool ReadUInt32(uint32& 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 WriteUInt32(uint32 val);
+  void WriteString(const std::string& val);
+  void WriteBytes(const char* val, size_t len);
+
+  void Resize(size_t size);
+  void Shift(size_t size);
+
+private:
+  char* bytes_;
+  size_t size_;
+  size_t start_;
+  size_t end_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_BYTEBUFFER_H__
diff --git a/talk/base/byteorder.h b/talk/base/byteorder.h
new file mode 100755
index 0000000..16834c2
--- /dev/null
+++ b/talk/base/byteorder.h
@@ -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.
+ */
+
+#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
+
+namespace talk_base {
+
+inline uint16 HostToNetwork16(uint16 n) {
+  return htons(n);
+}
+
+inline uint32 HostToNetwork32(uint32 n) {
+  return htonl(n);
+}
+
+inline uint16 NetworkToHost16(uint16 n) {
+  return ntohs(n);
+}
+
+inline uint32 NetworkToHost32(uint32 n) {
+  return ntohl(n);
+}
+
+} // namespace talk_base
+
+#endif // TALK_BASE_BYTEORDER_H__
diff --git a/talk/base/common.cc b/talk/base/common.cc
new file mode 100755
index 0000000..aa5c56a
--- /dev/null
+++ b/talk/base/common.cc
@@ -0,0 +1,62 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif  // WIN32
+
+#include <algorithm>
+
+#include "talk/base/common.h"
+
+//////////////////////////////////////////////////////////////////////
+// Assertions
+//////////////////////////////////////////////////////////////////////
+
+namespace talk_base {
+
+void Break() {
+#ifdef WIN32
+  ::DebugBreak();
+#else // !WIN32
+#if _DEBUG_HAVE_BACKTRACE
+  OutputTrace();
+#endif
+  abort();
+#endif // !WIN32
+}
+
+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);
+}
+
+} // namespace talk_base
\ No newline at end of file
diff --git a/talk/base/common.h b/talk/base/common.h
new file mode 100755
index 0000000..d652f81
--- /dev/null
+++ b/talk/base/common.h
@@ -0,0 +1,120 @@
+/*
+ * 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_COMMON_H__
+#define TALK_BASE_COMMON_H__
+
+#if defined(_MSC_VER)
+// warning C4355: 'this' : used in base member initializer list
+#pragma warning(disable:4355)
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// General Utilities
+//////////////////////////////////////////////////////////////////////
+
+#ifndef UNUSED
+#define UNUSED(x) Unused(static_cast<const void *>(&x))
+#define UNUSED2(x,y) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y))
+#define UNUSED3(x,y,z) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z))
+#define UNUSED4(x,y,z,a) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a))
+#define UNUSED5(x,y,z,a,b) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a)); Unused(static_cast<const void *>(&b))
+inline void Unused(const void *) { }
+#endif // UNUSED
+
+#ifndef WIN32
+#define strnicmp(x,y,n) strncasecmp(x,y,n)
+#define stricmp(x,y) strcasecmp(x,y)
+#define stdmax(x,y) std::max(x,y)
+#else
+#define stdmax(x,y) max(x,y)
+#endif
+
+
+#define ARRAY_SIZE(x) (static_cast<int>((sizeof(x)/sizeof(x[0]))))
+
+/////////////////////////////////////////////////////////////////////////////
+// Assertions
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef ENABLE_DEBUG
+
+namespace talk_base {
+
+// Break causes the debugger to stop executing, or the program to abort
+void Break();
+
+// LogAssert writes information about an assertion to the log
+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) {
+  if (!result) {
+    LogAssert(function, file, line, expression);
+    Break();
+  }
+}
+
+}; // 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)
+#endif
+
+#ifndef VERIFY
+#define VERIFY(x) talk_base::Assert((x),__FUNCTION__,__FILE__,__LINE__,#x)
+#endif
+
+#else // !ENABLE_DEBUG
+
+#ifndef ASSERT
+#define ASSERT(x) (void)0
+#endif
+
+#ifndef VERIFY
+#define VERIFY(x) (void)(x)
+#endif
+
+#endif // !ENABLE_DEBUG
+
+#define COMPILE_TIME_ASSERT(expr)       char CTA_UNIQUE_NAME[expr]
+#define CTA_UNIQUE_NAME                 MAKE_NAME(__LINE__)
+#define CTA_MAKE_NAME(line)             MAKE_NAME2(line)
+#define CTA_MAKE_NAME2(line)            constraint_ ## line
+
+//////////////////////////////////////////////////////////////////////
+
+// 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__
diff --git a/talk/base/convert.h b/talk/base/convert.h
new file mode 100755
index 0000000..26c6d32
--- /dev/null
+++ b/talk/base/convert.h
@@ -0,0 +1,149 @@
+/*
+ * 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
new file mode 100755
index 0000000..fbe7382
--- /dev/null
+++ b/talk/base/criticalsection.h
@@ -0,0 +1,120 @@
+/*
+ * 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_CRITICALSECTION_H__
+#define TALK_BASE_CRITICALSECTION_H__
+
+#ifdef WIN32
+#include "talk/base/win32.h"
+#endif
+
+#ifdef POSIX
+#include <pthread.h>
+#endif
+
+#ifdef _DEBUG
+#define CS_TRACK_OWNER 1
+#endif  // _DEBUG
+
+#if CS_TRACK_OWNER
+#define TRACK_OWNER(x) x
+#else  // !CS_TRACK_OWNER
+#define TRACK_OWNER(x)
+#endif  // !CS_TRACK_OWNER
+
+namespace talk_base {
+
+#ifdef WIN32
+class CriticalSection {
+public:
+  CriticalSection() {
+    InitializeCriticalSection(&crit_);
+    // Windows docs say 0 is not a valid thread id
+    TRACK_OWNER(thread_ = 0);
+  }
+  ~CriticalSection() {
+    DeleteCriticalSection(&crit_);
+  }
+  void Enter() {
+    EnterCriticalSection(&crit_);
+    TRACK_OWNER(thread_ = GetCurrentThreadId());
+  }
+  void Leave() {
+    TRACK_OWNER(thread_ = 0);
+    LeaveCriticalSection(&crit_);
+  }
+
+#if CS_TRACK_OWNER
+  bool CurrentThreadIsOwner() const { return thread_ == GetCurrentThreadId(); }
+#endif  // CS_TRACK_OWNER
+
+private:
+  CRITICAL_SECTION crit_;
+  TRACK_OWNER(DWORD thread_);  // The section's owning thread id
+};
+#endif // WIN32
+
+#ifdef POSIX
+class CriticalSection {
+public:
+  CriticalSection() {
+    pthread_mutexattr_t mutex_attribute;
+    pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&mutex_, &mutex_attribute);
+  }
+  ~CriticalSection() {
+    pthread_mutex_destroy(&mutex_);
+  }
+  void Enter() {
+    pthread_mutex_lock(&mutex_);
+  }
+  void Leave() {
+    pthread_mutex_unlock(&mutex_);
+  }
+private:
+  pthread_mutex_t mutex_;
+};
+#endif // POSIX
+
+// CritScope, for serializing exection through a scope
+
+class CritScope {
+public:
+  CritScope(CriticalSection *pcrit) {
+    pcrit_ = pcrit;
+    pcrit_->Enter();
+  }
+  ~CritScope() {
+    pcrit_->Leave();
+  }
+private:
+  CriticalSection *pcrit_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_CRITICALSECTION_H__
diff --git a/talk/base/cryptstring.h b/talk/base/cryptstring.h
new file mode 100755
index 0000000..64a7e57
--- /dev/null
+++ b/talk/base/cryptstring.h
@@ -0,0 +1,185 @@
+/*
+ * 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_CRYPTSTRING_H_
+#define _TALK_BASE_CRYPTSTRING_H_
+
+#include <string>
+#include "talk/base/linked_ptr.h"
+#include "talk/base/scoped_ptr.h"
+
+namespace talk_base {
+
+class CryptStringImpl {
+public:
+  virtual ~CryptStringImpl() {}
+  virtual size_t GetLength() const = 0;
+  virtual void CopyTo(char * dest, bool nullterminate) const = 0;
+  virtual std::string UrlEncode() const = 0;
+  virtual CryptStringImpl * Copy() const = 0;
+};
+
+class EmptyCryptStringImpl : public CryptStringImpl {
+public:
+  virtual ~EmptyCryptStringImpl() {}
+  virtual size_t GetLength() const { return 0; }
+  virtual void CopyTo(char * dest, bool nullterminate) const {
+    if (nullterminate) {
+      *dest = '\0';
+    }
+  }
+  virtual std::string UrlEncode() const { return ""; }
+  virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); }
+};
+
+class CryptString {
+public:
+  CryptString() : impl_(new EmptyCryptStringImpl()) {}
+  size_t GetLength() const { return impl_->GetLength(); }
+  void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); }
+  CryptString(const CryptString & other) : impl_(other.impl_->Copy()) {}
+  explicit CryptString(const CryptStringImpl & impl) : impl_(impl.Copy()) {}
+  CryptString & operator=(const CryptString & other) {
+    if (this != &other) {
+      impl_.reset(other.impl_->Copy());
+    }
+    return *this;
+  }
+  void Clear() { impl_.reset(new EmptyCryptStringImpl()); }
+  std::string UrlEncode() const { return impl_->UrlEncode(); }
+  
+private:
+  scoped_ptr<const CryptStringImpl> impl_;
+};
+
+
+// Used for constructing strings where a password is involved and we
+// need to ensure that we zero memory afterwards
+class FormatCryptString {
+public:
+  FormatCryptString() {
+    storage_ = new char[32];
+    capacity_ = 32;
+    length_ = 0;
+    storage_[0] = 0;
+  }
+  
+  void Append(const std::string & text) {
+    Append(text.data(), text.length());
+  }
+
+  void Append(const char * data, size_t length) {
+    EnsureStorage(length_ + length + 1);
+    memcpy(storage_ + length_, data, length);
+    length_ += length;
+    storage_[length_] = '\0';
+  }
+  
+  void Append(const CryptString * password) {
+    size_t len = password->GetLength();
+    EnsureStorage(length_ + len + 1);
+    password->CopyTo(storage_ + length_, true);
+    length_ += len;
+  }
+
+  size_t GetLength() {
+    return length_;
+  }
+
+  const char * GetData() {
+    return storage_;
+  }
+
+
+  // Ensures storage of at least n bytes
+  void EnsureStorage(size_t n) {
+    if (capacity_ >= n) {
+      return;
+    }
+
+    size_t old_capacity = capacity_;
+    char * old_storage = storage_;
+
+    for (;;) {
+      capacity_ *= 2;
+      if (capacity_ >= n)
+        break;
+    }
+
+    storage_ = new char[capacity_];
+
+    if (old_capacity) {
+      memcpy(storage_, old_storage, length_);
+    
+      // zero memory in a way that an optimizer won't optimize it out
+      old_storage[0] = 0;
+      for (size_t i = 1; i < old_capacity; i++) {
+        old_storage[i] = old_storage[i - 1];
+      }
+      delete[] old_storage;
+    }
+  }  
+
+  ~FormatCryptString() {
+    if (capacity_) {
+      storage_[0] = 0;
+      for (size_t i = 1; i < capacity_; i++) {
+        storage_[i] = storage_[i - 1];
+      }
+    }
+    delete[] storage_;
+  }
+private:
+  char * storage_;
+  size_t capacity_;
+  size_t length_;
+};
+
+class InsecureCryptStringImpl : public CryptStringImpl {
+ public:
+  std::string& password() { return password_; }
+  const std::string& password() const { return password_; }
+
+  virtual ~InsecureCryptStringImpl() {}
+  virtual size_t GetLength() const { return password_.size(); }
+  virtual void CopyTo(char * dest, bool nullterminate) const {
+    memcpy(dest, password_.data(), password_.size());
+    if (nullterminate) dest[password_.size()] = 0;
+  }
+  virtual std::string UrlEncode() const { return password_; }
+  virtual CryptStringImpl * Copy() const {
+    InsecureCryptStringImpl * copy = new InsecureCryptStringImpl;
+    copy->password() = password_;
+    return copy;
+  }
+ private:
+  std::string password_;
+};
+
+}
+
+#endif  // _TALK_BASE_CRYPTSTRING_H_
diff --git a/talk/base/diskcache.cc b/talk/base/diskcache.cc
new file mode 100755
index 0000000..44e37d9
--- /dev/null
+++ b/talk/base/diskcache.cc
@@ -0,0 +1,362 @@
+/*
+ * 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>
+
+#ifdef WIN32
+#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"
+#include "talk/base/pathutils.h"
+#include "talk/base/stream.h"
+#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
+
+#ifdef _DEBUG
+#define TRANSPARENT_CACHE_NAMES 1
+#else  // !_DEBUG
+#define TRANSPARENT_CACHE_NAMES 0
+#endif  // !_DEBUG
+
+namespace talk_base {
+
+class DiskCache;
+
+///////////////////////////////////////////////////////////////////////////////
+// DiskCacheAdapter
+///////////////////////////////////////////////////////////////////////////////
+
+class DiskCacheAdapter : public StreamAdapterInterface {
+public:
+  DiskCacheAdapter(const DiskCache* cache, const std::string& id, size_t index,
+                   StreamInterface* stream)
+  : StreamAdapterInterface(stream), cache_(cache), id_(id), index_(index)
+  { }
+  virtual ~DiskCacheAdapter() {
+    Close();
+    cache_->ReleaseResource(id_, index_);
+  }
+
+private:
+  const DiskCache* cache_;
+  std::string id_;
+  size_t index_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// DiskCache
+///////////////////////////////////////////////////////////////////////////////
+
+DiskCache::DiskCache() : max_cache_(0), total_size_(0), total_accessors_(0) {
+}
+
+DiskCache::~DiskCache() {
+  ASSERT(0 == total_accessors_);
+}
+
+bool DiskCache::Initialize(const std::string& folder, size_t size) {
+  if (!folder_.empty() || !Filesystem::CreateFolder(folder))
+    return false;
+
+  folder_ = folder;
+  max_cache_ = size;
+  ASSERT(0 == total_size_);
+
+  if (!InitializeEntries())
+    return false;
+
+  return CheckLimit();
+}
+
+bool DiskCache::Purge() {
+  if (folder_.empty())
+    return false;
+
+  if (total_accessors_ > 0) {
+    LOG_F(LS_WARNING) << "Cache files open";
+    return false;
+  }
+
+  if (!PurgeFiles())
+    return false;
+
+  map_.clear();
+  return true;
+}
+
+bool DiskCache::LockResource(const std::string& id) {
+  Entry* entry = GetOrCreateEntry(id, true);
+  if (LS_LOCKED == entry->lock_state)
+    return false;
+  if ((LS_UNLOCKED == entry->lock_state) && (entry->accessors > 0))
+    return false;
+  if ((total_size_ > max_cache_) && !CheckLimit()) {
+    LOG_F(LS_WARNING) << "Cache overfull";
+    return false;
+  }
+  entry->lock_state = LS_LOCKED;
+  return true;
+}
+
+StreamInterface* DiskCache::WriteResource(const std::string& id, size_t index) {
+  Entry* entry = GetOrCreateEntry(id, false);
+  if (LS_LOCKED != entry->lock_state)
+    return NULL;
+
+  size_t previous_size = 0;
+  std::string filename(IdToFilename(id, index));
+  FileStream::GetSize(filename, &previous_size);
+  ASSERT(previous_size <= entry->size);
+  if (previous_size > entry->size) {
+    previous_size = entry->size;
+  }
+
+  scoped_ptr<FileStream> file(new FileStream);
+  if (!file->Open(filename, "wb")) {
+    LOG_F(LS_ERROR) << "Couldn't create cache file";
+    return NULL;
+  }
+
+  entry->streams = stdmax(entry->streams, index + 1);
+  entry->size -= previous_size;
+  total_size_ -= previous_size;
+
+  entry->accessors += 1;
+  total_accessors_ += 1;
+  return new DiskCacheAdapter(this, id, index, file.release());
+}
+
+bool DiskCache::UnlockResource(const std::string& id) {
+  Entry* entry = GetOrCreateEntry(id, false);
+  if (LS_LOCKED != entry->lock_state)
+    return false;
+
+  if (entry->accessors > 0) {
+    entry->lock_state = LS_UNLOCKING;
+  } else {
+    entry->lock_state = LS_UNLOCKED;
+    entry->last_modified = time(0);
+    CheckLimit();
+  }
+  return true;
+}
+
+StreamInterface* DiskCache::ReadResource(const std::string& id,
+                                         size_t index) const {
+  const Entry* entry = GetEntry(id);
+  if (LS_UNLOCKED != entry->lock_state)
+    return NULL;
+  if (index >= entry->streams)
+    return NULL;
+
+  scoped_ptr<FileStream> file(new FileStream);
+  if (!file->Open(IdToFilename(id, index), "rb"))
+    return NULL;
+
+  entry->accessors += 1;
+  total_accessors_ += 1;
+  return new DiskCacheAdapter(this, id, index, file.release());
+}
+
+bool DiskCache::HasResource(const std::string& id) const {
+  const Entry* entry = GetEntry(id);
+  return (NULL != entry) && (entry->streams > 0);
+}
+
+bool DiskCache::HasResourceStream(const std::string& id, size_t index) const {
+  const Entry* entry = GetEntry(id);
+  if ((NULL == entry) || (index >= entry->streams))
+    return false;
+
+  std::string filename = IdToFilename(id, index);
+
+  return FileExists(filename);
+}
+
+bool DiskCache::DeleteResource(const std::string& id) {
+  Entry* entry = GetOrCreateEntry(id, false);
+  if (!entry)
+    return true;
+
+  if ((LS_UNLOCKED != entry->lock_state) || (entry->accessors > 0))
+    return false;
+
+  bool success = true;
+  for (size_t index = 0; index < entry->streams; ++index) {
+    std::string filename = IdToFilename(id, index);
+
+    if (!FileExists(filename))
+      continue;
+
+    if (!DeleteFile(filename)) {
+      LOG_F(LS_ERROR) << "Couldn't remove cache file: " << filename;
+      success = false;
+    }
+  }
+
+  total_size_ -= entry->size;
+  map_.erase(id);
+  return success;
+}
+
+bool DiskCache::CheckLimit() {
+#ifdef _DEBUG
+  // Temporary check to make sure everything is working correctly.
+  size_t cache_size = 0;
+  for (EntryMap::iterator it = map_.begin(); it != map_.end(); ++it) {
+    cache_size += it->second.size;
+  }
+  ASSERT(cache_size == total_size_);
+#endif  // _DEBUG
+
+  // TODO: Replace this with a non-brain-dead algorithm for clearing out the
+  // oldest resources... something that isn't O(n^2)
+  while (total_size_ > max_cache_) {
+    EntryMap::iterator oldest = map_.end();
+    for (EntryMap::iterator it = map_.begin(); it != map_.end(); ++it) {
+      if ((LS_UNLOCKED != it->second.lock_state) || (it->second.accessors > 0))
+        continue;
+      oldest = it;
+      break;
+    }
+    if (oldest == map_.end()) {
+      LOG_F(LS_WARNING) << "All resources are locked!";
+      return false;
+    }
+    for (EntryMap::iterator it = oldest++; it != map_.end(); ++it) {
+      if (it->second.last_modified < oldest->second.last_modified) {
+        oldest = it;
+      }
+    }
+    if (!DeleteResource(oldest->first)) {
+      LOG_F(LS_ERROR) << "Couldn't delete from cache!";
+      return false;
+    }
+  }
+  return true;
+}
+
+std::string DiskCache::IdToFilename(const std::string& id, size_t index) const {
+#ifdef TRANSPARENT_CACHE_NAMES
+  // This escapes colons and other filesystem characters, so the user can't open
+  // special devices (like "COM1:"), or access other directories.
+  size_t buffer_size = id.length()*3 + 1;
+  char* buffer = new char[buffer_size];
+  encode(buffer, buffer_size, id.data(), id.length(),
+         unsafe_filename_characters(), '%');
+  // TODO: ASSERT(strlen(buffer) < FileSystem::MaxBasenameLength());
+#else  // !TRANSPARENT_CACHE_NAMES
+  // We might want to just use a hash of the filename at some point, both for
+  // obfuscation, and to avoid both filename length and escaping issues.
+  ASSERT(false);
+#endif  // !TRANSPARENT_CACHE_NAMES
+
+  char extension[32];
+  sprintfn(extension, ARRAY_SIZE(extension), ".%u", index);
+
+  Pathname pathname;
+  pathname.SetFolder(folder_);
+  pathname.SetBasename(buffer);
+  pathname.SetExtension(extension);
+
+#ifdef TRANSPARENT_CACHE_NAMES
+  delete [] buffer;
+#endif  // TRANSPARENT_CACHE_NAMES
+
+  return pathname.pathname();
+}
+
+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))
+    return false;
+
+  size_t buffer_size = pathname.basename().length() + 1;
+  char* buffer = new char[buffer_size];
+  decode(buffer, buffer_size, pathname.basename().data(),
+         pathname.basename().length(), '%');
+  id->assign(buffer);
+  delete [] buffer;
+  return true;
+}
+
+DiskCache::Entry* DiskCache::GetOrCreateEntry(const std::string& id,
+                                              bool create) {
+  EntryMap::iterator it = map_.find(id);
+  if (it != map_.end())
+    return &it->second;
+  if (!create)
+    return NULL;
+  Entry e;
+  e.lock_state = LS_UNLOCKED;
+  e.accessors = 0;
+  e.size = 0;
+  e.streams = 0;
+  e.last_modified = time(0);
+  it = map_.insert(EntryMap::value_type(id, e)).first;
+  return &it->second;
+}
+
+void DiskCache::ReleaseResource(const std::string& id, size_t index) const {
+  const Entry* entry = GetEntry(id);
+  if (!entry) {
+    LOG_F(LS_WARNING) << "Missing cache entry";
+    ASSERT(false);
+    return;
+  }
+
+  entry->accessors -= 1;
+  total_accessors_ -= 1;
+
+  if (LS_UNLOCKED != entry->lock_state) {
+    // This is safe, because locked resources only issue WriteResource, which
+    // is non-const.  Think about a better way to handle it.
+    DiskCache* this2 = const_cast<DiskCache*>(this);
+    Entry* entry2 = this2->GetOrCreateEntry(id, false);
+
+    size_t new_size = 0;
+    std::string filename(IdToFilename(id, index));
+    FileStream::GetSize(filename, &new_size);
+    entry2->size += new_size;
+    this2->total_size_ += new_size;
+
+    if ((LS_UNLOCKING == entry->lock_state) && (0 == entry->accessors)) {
+      entry2->last_modified = time(0);
+      entry2->lock_state = LS_UNLOCKED;
+      this2->CheckLimit();
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/diskcache.h b/talk/base/diskcache.h
new file mode 100755
index 0000000..b42e3e0
--- /dev/null
+++ b/talk/base/diskcache.h
@@ -0,0 +1,142 @@
+/*
+ * 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_DISKCACHE_H__
+#define TALK_BASE_DISKCACHE_H__
+
+#include <map>
+#include <string>
+
+#ifdef WIN32
+#undef UnlockResource
+#endif  // WIN32
+
+namespace talk_base {
+
+class StreamInterface;
+
+///////////////////////////////////////////////////////////////////////////////
+// DiskCache - An LRU cache of streams, stored on disk.
+//
+// Streams are identified by a unique resource id.  Multiple streams can be
+// associated with each resource id, distinguished by an index.  When old
+// resources are flushed from the cache, all streams associated with those
+// resources are removed together.
+// DiskCache is designed to persist across executions of the program.  It is
+// safe for use from an arbitrary number of users on a single thread, but not
+// from multiple threads or other processes.
+///////////////////////////////////////////////////////////////////////////////
+
+class DiskCache {
+public:
+  DiskCache();
+  ~DiskCache();
+
+  bool Initialize(const std::string& folder, size_t size);
+  bool Purge();
+
+  bool LockResource(const std::string& id);
+  StreamInterface* WriteResource(const std::string& id, size_t index);
+  bool UnlockResource(const std::string& id);
+
+  StreamInterface* ReadResource(const std::string& id, size_t index) const;
+
+  bool HasResource(const std::string& id) const;
+  bool HasResourceStream(const std::string& id, size_t index) const;
+  bool DeleteResource(const std::string& id);
+
+ protected:
+  virtual bool InitializeEntries() = 0;
+  virtual bool PurgeFiles() = 0;
+
+  virtual bool FileExists(const std::string& filename) const = 0;
+  virtual bool DeleteFile(const std::string& filename) const = 0;
+
+  enum LockState { LS_UNLOCKED, LS_LOCKED, LS_UNLOCKING };
+  struct Entry {
+    LockState lock_state;
+    mutable size_t accessors;
+    size_t size;
+    size_t streams;
+    time_t last_modified;
+  };
+  typedef std::map<std::string, Entry> EntryMap;
+  friend class DiskCacheAdapter;
+
+  bool CheckLimit();
+
+  std::string IdToFilename(const std::string& id, size_t index) const;
+  bool FilenameToId(const std::string& filename, std::string* id,
+                    size_t* index) const;
+
+  const Entry* GetEntry(const std::string& id) const {
+    return const_cast<DiskCache*>(this)->GetOrCreateEntry(id, false);
+  }
+  Entry* GetOrCreateEntry(const std::string& id, bool create);
+
+  void ReleaseResource(const std::string& id, size_t index) const;
+
+  std::string folder_;
+  size_t max_cache_, total_size_;
+  EntryMap map_;
+  mutable size_t total_accessors_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// CacheLock - Automatically manage locking and unlocking, with optional
+// rollback semantics
+///////////////////////////////////////////////////////////////////////////////
+
+class CacheLock {
+public:
+  CacheLock(DiskCache* cache, const std::string& id, bool rollback = false)
+  : cache_(cache), id_(id), rollback_(rollback)
+  {
+    locked_ = cache_->LockResource(id_);
+  }
+  ~CacheLock() {
+    if (locked_) {
+      cache_->UnlockResource(id_);
+      if (rollback_) {
+        cache_->DeleteResource(id_);
+      }
+    }
+  }
+  bool IsLocked() const { return locked_; }
+  void Commit() { rollback_ = false; }
+
+private:
+  DiskCache* cache_;
+  std::string id_;
+  bool rollback_, locked_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif // TALK_BASE_DISKCACHE_H__
diff --git a/talk/base/diskcache_win32.cc b/talk/base/diskcache_win32.cc
new file mode 100755
index 0000000..3132602
--- /dev/null
+++ b/talk/base/diskcache_win32.cc
@@ -0,0 +1,76 @@
+#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
new file mode 100755
index 0000000..aa5a1b6
--- /dev/null
+++ b/talk/base/diskcache_win32.h
@@ -0,0 +1,28 @@
+//
+//  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
new file mode 100755
index 0000000..f50c7d7
--- /dev/null
+++ b/talk/base/diskcachestd.cc
@@ -0,0 +1,30 @@
+//
+//  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
new file mode 100755
index 0000000..b676771
--- /dev/null
+++ b/talk/base/diskcachestd.h
@@ -0,0 +1,28 @@
+//
+//  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.h b/talk/base/event.h
new file mode 100755
index 0000000..ca15c38
--- /dev/null
+++ b/talk/base/event.h
@@ -0,0 +1,79 @@
+/*
+ * 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_EVENT_H__
+#define TALK_BASE_EVENT_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_;
+};
+#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
+
+#endif // TALK_BASE_EVENT_H__
diff --git a/talk/base/fileutils.cc b/talk/base/fileutils.cc
new file mode 100755
index 0000000..12c2576
--- /dev/null
+++ b/talk/base/fileutils.cc
@@ -0,0 +1,273 @@
+/*
+ * 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 <errno.h>
+#include <cassert>
+
+#ifdef WIN32
+#include "talk/base/convert.h"
+#endif
+
+#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 "talk/base/win32filesystem.h"
+
+#ifndef WIN32
+#define MAX_PATH 256
+#endif
+
+namespace talk_base {
+
+//////////////////////////
+// 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.
+
+  // Constructor
+DirectoryIterator::DirectoryIterator() : 
+#ifdef _WIN32
+  handle_(INVALID_HANDLE_VALUE)
+#else
+  dir_(NULL), dirent_(NULL)
+#endif
+{}
+
+  // Destructor
+DirectoryIterator::~DirectoryIterator() {
+#ifdef WIN32
+  if (handle_ != INVALID_HANDLE_VALUE)
+    ::FindClose(handle_);
+#else
+  if (dir_)
+    closedir(dir_);
+#endif
+}
+
+  // Starts traversing a directory.
+  // dir is the directory to traverse
+  // returns true if the directory exists and is valid
+bool DirectoryIterator::Iterate(const Pathname &dir) {
+  directory_ = dir.pathname();
+#ifdef WIN32
+  if (handle_ != INVALID_HANDLE_VALUE)
+    ::FindClose(handle_);
+  std::string d = dir.pathname() + '*';
+  handle_ = ::FindFirstFile(Utf16(d).AsWz(), &data_);
+  if (handle_ == INVALID_HANDLE_VALUE)
+    return false;
+#else
+  if (dir_ != NULL)
+    closedir(dir_);
+  dir_ = ::opendir(directory_.c_str());
+  if (dir_ == NULL)
+    return false;
+  dirent_ = readdir(dir_);
+  if (dirent_ == NULL)
+    return false;
+  
+  if (::stat(std::string(directory_ + Name()).c_str(), &stat_) != 0)
+    return false;
+#endif
+  return true;
+}
+
+  // Advances to the next file
+  // returns true if there were more files in the directory.
+bool DirectoryIterator::Next() {
+#ifdef WIN32
+  return ::FindNextFile(handle_, &data_) == TRUE;
+#else
+  dirent_ = ::readdir(dir_);
+  if (dirent_ == NULL)
+    return false;
+
+  return ::stat(std::string(directory_ + Name()).c_str(), &stat_) == 0;
+#endif
+}
+
+  // returns true if the file currently pointed to is a directory
+bool DirectoryIterator::IsDirectory() const {
+#ifdef WIN32
+  return (data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FALSE;
+#else
+  return S_ISDIR(stat_.st_mode);
+#endif
+}
+
+  // returns the name of the file currently pointed to
+std::string DirectoryIterator::Name() const {
+#ifdef WIN32
+  return Utf8(data_.cFileName).AsString();
+#else
+  assert(dirent_ != NULL);
+  return dirent_->d_name;
+#endif
+}
+
+  // returns the size of the file currently pointed to
+size_t DirectoryIterator::FileSize() const {
+#ifndef WIN32
+      	return stat_.st_size;
+#else
+	return data_.nFileSizeLow;
+#endif
+}
+ 
+  // returns the last modified time of this file
+time_t DirectoryIterator::FileModifyTime() const {
+#ifdef WIN32
+return 0;
+#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_)
+#ifdef WIN32
+    default_filesystem_ = new Win32Filesystem();
+#else
+    default_filesystem_ = new UnixFilesystem();
+#endif
+    return default_filesystem_;
+}
+
+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 (path.folder().empty()) {
+    Pathname temporary_path;
+    if (!Filesystem::GetTemporaryFolder(temporary_path, true, NULL)) {
+      printf("Get temp failed\n");
+      return false;
+    }
+    path.SetFolder(temporary_path.pathname());
+  }
+
+  // If not 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);
+    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();
+  const size_t MAX_VERSION = 100;
+  size_t version = 0;
+  while (version < MAX_VERSION) {
+    std::string pathname = path.pathname();
+ 
+    if (!Filesystem::FileExists(pathname)) {
+      if (create_empty) {
+        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);
+    path.SetBasename(version_base);
+  }
+  return true;
+}
+}
diff --git a/talk/base/fileutils.h b/talk/base/fileutils.h
new file mode 100755
index 0000000..868f4c2
--- /dev/null
+++ b/talk/base/fileutils.h
@@ -0,0 +1,185 @@
+/*
+ * 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_FILEUTILS_H__
+#define TALK_BASE_FILEUTILS_H__
+
+#include <string>
+
+#ifdef _WINDOWS
+#include <windows.h>
+#else
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+
+#include "talk/base/common.h"
+
+namespace talk_base {
+
+class FileStream;
+class Pathname;
+
+//////////////////////////
+// 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.
+
+class DirectoryIterator {
+
+ public:
+  // Constructor 
+  DirectoryIterator();
+
+  // Destructor
+  ~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);
+
+  // Advances to the next file
+  // returns true if there were more files in the directory.
+  bool Next();
+
+  // returns true if the file currently pointed to is a directory
+  bool IsDirectory() const;
+
+  // returns the name of the file currently pointed to
+  std::string Name() const;
+
+  // returns the size of the file currently pointed to
+  size_t FileSize() const;
+
+  // returns the last modified time of the file currently poitned to
+  time_t FileModifyTime() const;
+
+ private:
+  std::string directory_;
+#ifdef _WINDOWS
+  WIN32_FIND_DATA data_;
+  HANDLE handle_;
+#else
+  DIR *dir_;
+  struct dirent *dirent_;
+  struct stat stat_;
+#endif
+};
+
+class Filesystem {
+ 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;
+
+  // 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;
+
+  // 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;
+
+  // 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;
+
+  // Returns true if a pathname is a directory
+  virtual bool IsFolderI(const Pathname& pathname) = 0;
+
+  // Returns true if a file exists at this path
+  virtual bool FileExistsI(const Pathname& pathname) = 0;
+
+  // Returns true if pathname represents a temporary location on the system.
+  virtual bool IsTemporaryPathI(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;
+
+  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();
+
+};
+
+// Generates a unique temporary filename in 'directory' with the given 'prefix'
+ std::string TempFilename(const Pathname &dir, const std::string &prefix);
+
+  // 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);
+
+}
+
+#endif   // TALK_BASE_FILEUTILS_H__
diff --git a/talk/base/firewallsocketserver.cc b/talk/base/firewallsocketserver.cc
new file mode 100755
index 0000000..49db8a8
--- /dev/null
+++ b/talk/base/firewallsocketserver.cc
@@ -0,0 +1,213 @@
+/*
+ * 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 <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)
+    : 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?
+        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 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";
+        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 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))
+          return res;
+        //LOG(INFO) << "FirewallSocket::RecvFrom - Inbound UDP packet 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))
+        return sock;
+      sock->Close();
+      delete sock;
+      //LOG(INFO) << "FirewallSocket::Accept - Inbound TCP connection denied";
+    }
+    return 0;
+  }
+
+private:
+  FirewallSocketServer * server_;
+  int type_;
+};
+
+FirewallSocketServer::FirewallSocketServer(SocketServer * server, FirewallManager * manager) : server_(server), manager_(manager) {
+  if (manager_)
+    manager_->AddServer(this);
+}
+
+FirewallSocketServer::~FirewallSocketServer() {
+  if (manager_)
+    manager_->RemoveServer(this);
+}
+
+void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p, FirewallDirection d, const SocketAddress& addr) {
+  Rule r;
+  r.allow = allow;
+  r.p = p;
+  r.d = d;
+  r.addr = addr;
+  CritScope scope(&crit_);
+  rules_.push_back(r);
+}
+
+void FirewallSocketServer::ClearRules() {
+  CritScope scope(&crit_);
+  rules_.clear();
+}
+
+bool FirewallSocketServer::Check(FirewallProtocol p, FirewallDirection d, const SocketAddress& addr) {
+  CritScope scope(&crit_);
+  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))
+      continue;
+    if ((r.addr.ip() != addr.ip()) && !r.addr.IsAny())
+      continue;
+    if ((r.addr.port() != addr.port()) && (r.addr.port() != 0))
+      continue;
+    return r.allow;
+  }
+  return true;
+}
+
+Socket* FirewallSocketServer::CreateSocket(int type) {
+  return WrapSocket(server_->CreateSocket(type), type);
+}
+
+AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int type) {
+  return WrapSocket(server_->CreateAsyncSocket(type), type);
+}
+
+Socket * FirewallSocketServer::WrapSocket(Socket * sock, int type) {
+  if (!sock)
+    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);
+}
+
+FirewallManager::FirewallManager() {
+}
+
+FirewallManager::~FirewallManager() {
+  assert(servers_.empty());
+}
+
+void FirewallManager::AddServer(FirewallSocketServer * server) {
+  CritScope scope(&crit_);
+  servers_.push_back(server);
+}
+
+void FirewallManager::RemoveServer(FirewallSocketServer * server) {
+  CritScope scope(&crit_);
+  servers_.erase(std::remove(servers_.begin(), servers_.end(), server), servers_.end());
+}
+
+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) {
+    (*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) {
+    (*it)->ClearRules();
+  }
+}
+
+} // namespace talk_base
diff --git a/talk/base/firewallsocketserver.h b/talk/base/firewallsocketserver.h
new file mode 100755
index 0000000..10c07e6
--- /dev/null
+++ b/talk/base/firewallsocketserver.h
@@ -0,0 +1,95 @@
+/*
+ * 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_FIREWALLSOCKETSERVER_H__
+#define TALK_BASE_FIREWALLSOCKETSERVER_H__
+
+#include <vector>
+#include "talk/base/socketserver.h"
+#include "talk/base/criticalsection.h"
+
+namespace talk_base {
+
+class FirewallManager;
+
+// 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);
+  virtual ~FirewallSocketServer();
+
+  void AddRule(bool allow, FirewallProtocol p = FP_ANY, FirewallDirection d = FD_ANY, const SocketAddress& addr = SocketAddress());
+  void ClearRules();
+
+  bool Check(FirewallProtocol p, FirewallDirection d, const SocketAddress& addr);
+
+  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(); }
+
+  Socket * WrapSocket(Socket * sock, int type);
+  AsyncSocket * WrapSocket(AsyncSocket * sock, int type);
+
+private:
+  SocketServer * server_;
+  FirewallManager * manager_;
+  CriticalSection crit_;
+  struct Rule {
+    bool allow;
+    FirewallProtocol p;
+    FirewallDirection d;
+    SocketAddress addr;
+  };
+  std::vector<Rule> rules_;
+};
+
+// FirewallManager allows you to manage firewalls in multiple threads together
+
+class FirewallManager {
+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 ClearRules();
+
+private:
+  CriticalSection crit_;
+  std::vector<FirewallSocketServer *> servers_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_FIREWALLSOCKETSERVER_H__
diff --git a/talk/base/helpers.cc b/talk/base/helpers.cc
new file mode 100755
index 0000000..627edce
--- /dev/null
+++ b/talk/base/helpers.cc
@@ -0,0 +1,148 @@
+/*
+ * 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/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>
+#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;
+  }
+#else
+  seed = talk_base::Time();
+#endif
+
+  SetRandomSeed(seed ^ hash);
+}
+
+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',
+  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+  '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.
+
+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;
+}
+
+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 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;
+  }
+  return true;
+}
+
+} // namespace cricket
diff --git a/talk/base/helpers.h b/talk/base/helpers.h
new file mode 100755
index 0000000..696edbe
--- /dev/null
+++ b/talk/base/helpers.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 __HELPERS_H__
+#define __HELPERS_H__
+
+#include "talk/base/basictypes.h"
+#include <string>
+
+namespace cricket {
+
+// srand initializer
+void InitRandom(const char *client_unique, size_t len);
+
+// For testing, the random seed can be directly accessed.
+long GetRandomSeed();
+void SetRandomSeed(unsigned long seed);
+
+// Generates a (cryptographically) random string of the given length.
+std::string CreateRandomString(int length);
+
+// Generates a random id
+uint32 CreateRandomId();
+
+// Determines whether the given string consists entirely of valid base64
+// encoded characters.
+bool IsBase64Encoded(const std::string& str);
+
+} // namespace cricket
+
+#endif // __HELPERS_H__
diff --git a/talk/base/host.cc b/talk/base/host.cc
new file mode 100755
index 0000000..df5f7f7
--- /dev/null
+++ b/talk/base/host.cc
@@ -0,0 +1,100 @@
+/*
+ * 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 <string>
+#include <iostream>
+#include <cassert>
+#include <errno.h>
+
+#ifdef POSIX
+extern "C" {
+#include <sys/utsname.h>
+}
+#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
+
+namespace talk_base {
+
+namespace {
+
+void FatalError(const std::string& name, int err) {
+  PLOG(LERROR, err) << name;
+  std::exit(1);
+}
+
+}
+
+#ifdef POSIX
+std::string GetHostName() {
+  struct utsname nm;
+  if (uname(&nm) < 0)
+    FatalError("uname", errno);
+  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
diff --git a/talk/base/host.h b/talk/base/host.h
new file mode 100755
index 0000000..7ee603d
--- /dev/null
+++ b/talk/base/host.h
@@ -0,0 +1,59 @@
+/*
+ * 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_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__
diff --git a/talk/base/httpbase.cc b/talk/base/httpbase.cc
new file mode 100755
index 0000000..06b7378
--- /dev/null
+++ b/talk/base/httpbase.cc
@@ -0,0 +1,591 @@
+/*
+ * 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 OSX
+#include <errno.h>
+#endif
+
+#ifdef WIN32
+#include "talk/base/win32.h"
+#else  // !WIN32
+#define SEC_E_CERT_EXPIRED (-2146893016)
+#endif  // !WIN32
+
+#include "talk/base/common.h"
+#include "talk/base/httpbase.h"
+#include "talk/base/logging.h"
+#include "talk/base/socket.h"
+#include "talk/base/stringutils.h"
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// Helpers
+//////////////////////////////////////////////////////////////////////
+
+bool MatchHeader(const char* str, size_t len, HttpHeader header) {
+  const char* const header_str = ToString(header);
+  const size_t header_len = strlen(header_str);
+  return (len == header_len) && (_strnicmp(str, header_str, header_len) == 0);
+}
+
+//////////////////////////////////////////////////////////////////////
+// HttpParser
+//////////////////////////////////////////////////////////////////////
+
+HttpParser::HttpParser() {
+  reset();
+}
+
+HttpParser::~HttpParser() {
+}
+
+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;
+
+  if (state_ >= ST_COMPLETE) {
+    ASSERT(false);
+    return false;
+  }
+
+  while (true) {
+    if (state_ < ST_DATA) {
+      size_t pos = processed;
+      while ((pos < len) && (buffer[pos] != '\n')) {
+        pos += 1;
+      }
+      if (pos >= len) {
+        break; // don't have a full header
+      }
+      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
+      }
+    } else if (data_size_ == 0) {
+      if (chunked_) {
+        state_ = ST_CHUNKTERM;
+      } else {
+        return false;
+      }
+    } else {
+      size_t available = len - processed;
+      if (available <= 0) {
+        break; // no more data
+      }
+      if ((data_size_ != SIZE_UNKNOWN) && (available > data_size_)) {
+        available = data_size_;
+      }
+      size_t read = 0;
+      err = onHttpRecvData(buffer + processed, available, read);
+      if (err != HE_NONE) {
+        return false; // error occurred
+      }
+      processed += read;
+      if (data_size_ != SIZE_UNKNOWN) {
+        data_size_ -= read;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool
+HttpParser::process_line(const char* line, size_t len, HttpError& err) {
+  switch (state_) {
+  case ST_LEADER:
+    state_ = ST_HEADERS;
+    err = onHttpRecvLeader(line, len);
+    break;
+
+  case ST_HEADERS:
+    if (len > 0) {
+      const char* value = strchrn(line, len, ':');
+      if (!value) {
+        err = HE_PROTOCOL;
+        break;
+      }
+      size_t nlen = (value - line);
+      const char* eol = line + len;
+      do {
+        value += 1;
+      } 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;
+        }
+      } 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;
+        }
+      }
+      err = onHttpRecvHeader(line, nlen, value, vlen);
+    } else {
+      state_ = chunked_ ? ST_CHUNKSIZE : ST_DATA;
+      err = onHttpRecvHeaderComplete(chunked_, data_size_);
+    }
+    break;
+
+  case ST_CHUNKSIZE:
+    if (len > 0) {
+      char* ptr = NULL;
+      data_size_ = strtoul(line, &ptr, 16);
+      if (ptr != line + len) {
+        err = HE_PROTOCOL;
+        break;
+      }
+      state_ = (data_size_ == 0) ? ST_TRAILERS : ST_DATA;
+    } else {
+      err = HE_PROTOCOL;
+    }
+    break;
+
+  case ST_CHUNKTERM:
+    if (len > 0) {
+      err = HE_PROTOCOL;
+    } else {
+      state_ = chunked_ ? ST_CHUNKSIZE : ST_DATA;
+    }
+    break;
+
+  case ST_TRAILERS:
+    if (len == 0) {
+      return false;
+    }
+    // err = onHttpRecvTrailer();
+    break;
+
+  default:
+    break;
+  }
+
+  return (err == HE_NONE);
+}
+ 
+void 
+HttpParser::end_of_input() {
+  if ((state_ == ST_DATA) && (data_size_ == SIZE_UNKNOWN)) {
+    complete(HE_NONE);
+  } else {
+    complete(HE_DISCONNECTED);
+  }
+}
+
+void 
+HttpParser::complete(HttpError err) {
+  if (state_ < ST_COMPLETE) {
+    state_ = ST_COMPLETE;
+    onHttpRecvComplete(err);
+  }
+}
+
+//////////////////////////////////////////////////////////////////////
+// HttpBase
+//////////////////////////////////////////////////////////////////////
+
+HttpBase::HttpBase() : mode_(HM_NONE), data_(NULL), notify_(NULL),
+                       stream_(NULL) {
+}
+
+HttpBase::~HttpBase() {
+}
+
+bool
+HttpBase::isConnected() const {
+  return (stream_ != NULL) && (stream_->GetState() == SS_OPEN);
+}
+
+bool
+HttpBase::attach(StreamInterface* stream) {
+  if ((mode_ != HM_NONE) || (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;
+  return true;
+}
+
+StreamInterface*
+HttpBase::detach() {
+  if (mode_ != HM_NONE) {
+    ASSERT(false);
+    return NULL;
+  }
+  StreamInterface* stream = stream_;
+  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) {
+  if (mode_ != HM_NONE) {
+    ASSERT(false);
+    return;
+  } else if (!isConnected()) {
+    OnEvent(stream_, SE_CLOSE, HE_DISCONNECTED);
+    return;
+  }
+  
+  mode_ = HM_SEND;
+  data_ = data;
+  len_ = 0;
+  ignore_data_ = chunk_data_ = false;
+
+  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);
+}
+
+void
+HttpBase::recv(HttpData* data) {
+  if (mode_ != HM_NONE) {
+    ASSERT(false);
+    return;
+  } else if (!isConnected()) {
+    OnEvent(stream_, SE_CLOSE, HE_DISCONNECTED);
+    return;
+  }
+  
+  mode_ = HM_RECV;
+  data_ = data;
+  len_ = 0;
+  ignore_data_ = chunk_data_ = false;
+  
+  reset();
+  OnEvent(stream_, SE_READ, 0);
+}
+
+void
+HttpBase::abort(HttpError err) {
+  if (mode_ != HM_NONE) {
+    if (stream_ != NULL) {
+      stream_->Close();
+    }
+    do_complete(err);
+  }
+}
+
+void
+HttpBase::flush_data() {
+  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;
+      } else {
+        ASSERT(result == SR_ERROR);
+        LOG_F(LS_ERROR) << "error";
+        OnEvent(stream_, SE_CLOSE, error);
+        return;
+      }
+    }
+    len_ = 0;
+
+    // Check for more headers
+    if (header_ != data_->end()) {
+      queue_headers();
+      continue;
+    }
+
+    // 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);
+    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;
+    } else {
+      LOG_F(LS_ERROR) << "Read error: " << error;
+      do_complete(HE_STREAM);
+      return;
+    }
+  }
+
+  do_complete();
+}
+
+void
+HttpBase::queue_headers() {
+  while (header_ != data_->end()) {
+    size_t len = sprintfn(buffer_ + len_, sizeof(buffer_) - len_,
+                          "%.*s: %.*s\r\n",
+                          header_->first.size(), header_->first.data(),
+                          header_->second.size(), header_->second.data());
+    if (len_ + len < sizeof(buffer_) - 3) {
+      len_ += len;
+      ++header_;
+    } else if (len_ == 0) {
+      LOG(WARNING) << "discarding header that is too long: " << header_->first;
+      ++header_;
+    } else {
+      break;
+    }
+  }
+  if (header_ == data_->end()) {
+    len_ += strcpyn(buffer_ + len_, sizeof(buffer_) - len_, "\r\n");
+  }
+}
+
+void
+HttpBase::do_complete(HttpError err) {
+  ASSERT(mode_ != HM_NONE);
+  HttpMode mode = mode_;
+  mode_ = HM_NONE;
+  data_ = NULL;
+  if (notify_) {
+	  notify_->onHttpComplete(mode, err);
+  }
+}
+
+void
+HttpBase::OnEvent(StreamInterface* stream, int events, int error) {
+  if ((events & SE_OPEN) && (mode_ == HM_CONNECT)) {
+    do_complete();
+    return;
+  }
+
+  if ((events & SE_WRITE) && (mode_ == HM_SEND)) {
+    flush_data();
+    return;
+  }
+
+  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;
+      }
+    }
+    return;
+  }
+
+  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();
+  } else if (mode_ != HM_NONE) {
+    do_complete(mkerr(herr, HE_DISCONNECTED));
+  } else if (notify_) {
+    notify_->onHttpClosed(mkerr(herr, HE_DISCONNECTED));
+  }
+}
+
+//
+// HttpParser Implementation
+//
+
+HttpError
+HttpBase::onHttpRecvLeader(const char* line, size_t len) {
+  return data_->parseLeader(line, len);
+}
+
+HttpError
+HttpBase::onHttpRecvHeader(const char* name, size_t nlen, const char* value,
+                           size_t vlen) {
+  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;
+}
+
+HttpError
+HttpBase::onHttpRecvData(const char* data, size_t len, size_t& read) {
+  if (ignore_data_ || !data_->document.get()) {
+    read = len;
+    return HE_NONE;  
+  }
+  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;
+  }
+  LOG_F(LS_ERROR) << "Write error: " << error;
+  return HE_STREAM;
+}
+
+void
+HttpBase::onHttpRecvComplete(HttpError err) {
+  do_complete(err);
+}
+
+} // namespace talk_base
diff --git a/talk/base/httpbase.h b/talk/base/httpbase.h
new file mode 100755
index 0000000..64aefe9
--- /dev/null
+++ b/talk/base/httpbase.h
@@ -0,0 +1,142 @@
+/*
+ * 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_HTTPBASE_H__
+#define TALK_BASE_HTTPBASE_H__
+
+#include "talk/base/httpcommon.h"
+
+namespace talk_base {
+
+class StreamInterface;
+
+//////////////////////////////////////////////////////////////////////
+// HttpParser
+//////////////////////////////////////////////////////////////////////
+
+class HttpParser {
+public:
+  HttpParser();
+  virtual ~HttpParser();
+  
+  void reset();
+  bool process(const char* buffer, size_t len, size_t& read, HttpError& err);
+  void end_of_input();
+  void complete(HttpError err);
+  
+protected:
+  bool process_line(const char* line, size_t len, HttpError& err);
+
+  // 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;
+  
+private:
+  enum State {
+    ST_LEADER, ST_HEADERS,
+    ST_CHUNKSIZE, ST_CHUNKTERM, ST_TRAILERS,
+    ST_DATA, ST_COMPLETE
+  } state_;
+  bool chunked_;
+  size_t data_size_;
+};
+
+//////////////////////////////////////////////////////////////////////
+// IHttpNotify
+//////////////////////////////////////////////////////////////////////
+
+enum HttpMode { HM_NONE, HM_CONNECT, HM_RECV, HM_SEND };
+
+class IHttpNotify {
+public:
+  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
+//////////////////////////////////////////////////////////////////////
+
+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* detach();
+  bool isConnected() const;
+
+  void send(HttpData* data);
+  void recv(HttpData* data);
+  void abort(HttpError err);
+
+  HttpMode mode() const { return mode_; }
+
+  void set_ignore_data(bool ignore) { ignore_data_ = ignore; }
+  bool ignore_data() const { return ignore_data_; }
+
+protected:
+  void flush_data();
+  void queue_headers();
+  void do_complete(HttpError err = HE_NONE);
+
+  void OnEvent(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);
+
+private:
+  enum { kBufferSize = 32 * 1024 };
+
+  HttpMode mode_;
+  HttpData* data_;
+  IHttpNotify* notify_;
+  StreamInterface* stream_;
+  char buffer_[kBufferSize];
+  size_t len_;
+
+  bool ignore_data_, chunk_data_;
+  HttpData::const_iterator header_;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_HTTPBASE_H__
diff --git a/talk/base/httpclient.cc b/talk/base/httpclient.cc
new file mode 100755
index 0000000..49c5070
--- /dev/null
+++ b/talk/base/httpclient.cc
@@ -0,0 +1,714 @@
+/*
+ * 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 "talk/base/httpcommon-inl.h"
+
+#include "talk/base/asyncsocket.h"
+#include "talk/base/common.h"
+#include "talk/base/diskcache.h"
+#include "talk/base/httpclient.h"
+#include "talk/base/logging.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/socketstream.h"
+#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/basicdefs.h"
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// Helpers
+//////////////////////////////////////////////////////////////////////
+
+namespace {
+
+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);
+  char* eos = NULL;
+  *val = strtoul(str.c_str(), &eos, 10);
+  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 request_allows_cache =
+    has_expires || (std::string::npos != request.path.find('?'));
+  bool response_allows_cache =
+    has_expires || HttpCodeIsCacheable(response.scode);
+
+  bool may_cache = verb_allows_cache
+                   && request_allows_cache
+                   && response_allows_cache
+                   && !is_range_response;
+
+  std::string value;
+  if (response.hasHeader(HH_CACHE_CONTROL, &value)) {
+    HttpAttributeList directives;
+    HttpParseAttributes(value.data(), value.size(), directives);
+    // Response Directives Summary:
+    // public - always cacheable
+    // private - do not cache in a shared cache
+    // no-cache - may cache, but must revalidate whether fresh or stale
+    // no-store - sensitive information, do not cache or store in any way
+    // max-age - supplants Expires for staleness
+    // s-maxage - use as max-age for shared caches, ignore otherwise
+    // must-revalidate - may cache, but must revalidate after stale
+    // proxy-revalidate - shared cache must revalidate
+    if (HttpHasAttribute(directives, "no-store", NULL)) {
+      may_cache = false;
+    } else if (HttpHasAttribute(directives, "public", NULL)) {
+      may_cache = true;
+    }
+  }
+  return may_cache;
+}
+
+enum HttpCacheState {
+  HCS_FRESH,  // In cache, may use
+  HCS_STALE,  // In cache, must revalidate
+  HCS_NONE    // Not in cache
+};
+
+HttpCacheState HttpGetCacheState(const HttpRequestData& request, 
+                                 const HttpResponseData& response) {
+  // Temporaries
+  std::string s_temp;
+  unsigned long i_temp;
+
+  // Current time
+  unsigned long now = time(0);
+
+  HttpAttributeList cache_control;
+  if (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)
+      || !HttpDateToSeconds(s_temp, &date))
+    return HCS_NONE;
+
+  // TODO: Timestamp when cache request sent and response received?
+  unsigned long request_time = date;
+  unsigned long response_time = date;
+
+  unsigned long apparent_age = 0;
+  if (response_time > date) {
+    apparent_age = response_time - date;
+  }
+
+  unsigned long corrected_received_age = apparent_age;
+  if (response.hasHeader(HH_AGE, &s_temp)
+      && HttpStringToInt(s_temp, &i_temp)) {
+    corrected_received_age = stdmax(apparent_age, i_temp);
+  }
+
+  unsigned long response_delay = response_time - request_time;
+  unsigned long corrected_initial_age = corrected_received_age + response_delay;
+  unsigned long resident_time = now - response_time;
+  unsigned long current_age = corrected_initial_age + resident_time;
+
+  // Compute lifetime of document
+  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)
+             && HttpDateToSeconds(s_temp, &i_temp)) {
+    lifetime = i_temp - date;
+  } else if (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;
+  } else {
+    return HCS_STALE;
+  }
+
+  return (lifetime > current_age) ? HCS_FRESH : HCS_STALE;
+}
+
+enum HttpValidatorStrength {
+  HVS_NONE,
+  HVS_WEAK,
+  HVS_STRONG
+};
+
+HttpValidatorStrength
+HttpRequestValidatorLevel(const HttpRequestData& request) {
+  if (HV_GET != request.verb)
+    return HVS_STRONG;
+  return request.hasHeader(HH_RANGE, NULL) ? HVS_STRONG : HVS_WEAK;
+}
+
+HttpValidatorStrength
+HttpResponseValidatorLevel(const HttpResponseData& response) {
+  std::string value;
+  if (response.hasHeader(HH_ETAG, &value)) {
+    bool is_weak = (strnicmp(value.c_str(), "W/", 2) == 0);
+    return is_weak ? HVS_WEAK : HVS_STRONG;
+  }
+  if (response.hasHeader(HH_LAST_MODIFIED, &value)) {
+    unsigned long last_modified, date;
+    if (HttpDateToSeconds(value, &last_modified) 
+        && response.hasHeader(HH_DATE, &value)
+        && HttpDateToSeconds(value, &date)
+        && (last_modified + 60 < date)) {
+      return HVS_STRONG;
+    }
+    return HVS_WEAK;
+  }
+  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;
+}
+
+}  // anonymous namespace
+
+//////////////////////////////////////////////////////////////////////
+// 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)
+{
+  base_.notify(this);
+}
+
+HttpClient::~HttpClient() {
+  base_.notify(NULL);
+  base_.abort(HE_SHUTDOWN);
+  release();
+}
+
+void HttpClient::reset() {
+  server_.Clear();
+  request_.clear(true);
+  response_.clear(true);
+  context_.reset();
+  base_.abort(HE_OPERATION_CANCELLED);
+}
+
+void HttpClient::set_server(const SocketAddress& address) {
+  server_ = address;
+  // Setting 'Host' here allows it to be overridden before starting the request,
+  // if necessary.
+  request_.setHeader(HH_HOST, HttpAddress(server_), true);
+}
+
+void HttpClient::start() {
+  if (base_.mode() != HM_NONE) {
+    // call reset() to abort an in-progress request
+    ASSERT(false);
+    return;
+  }
+
+  ASSERT(!IsCacheActive());
+
+  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;
+  }
+
+  // If no content has been specified, using length of 0.
+  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);
+  }
+
+  bool absolute_uri = absolute_uri_;
+  if (PROXY_HTTPS == proxy_.type) {
+    request().version = HVER_1_0;
+    // Proxies require canonical form
+    absolute_uri = true;
+  }
+
+  // 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 ((NULL != cache_) && CheckCache()) {
+    return;
+  }
+
+  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);
+  } else {
+    base_.attach(stream);
+    if (stream->GetState() == SS_OPEN) {
+      base_.send(&request_);
+    }
+  }
+}
+
+void HttpClient::prepare_get(const std::string& url) {
+  reset();
+  Url<char> purl(url);
+  set_server(SocketAddress(purl.server(), purl.port(), false));
+  request().verb = HV_GET;
+  request().path = purl.full_path();
+}
+
+void HttpClient::prepare_post(const std::string& url,
+                              const std::string& content_type,
+                              StreamInterface* request_doc) {
+  reset();
+  Url<char> purl(url);
+  set_server(SocketAddress(purl.server(), purl.port(), false));
+  request().verb = HV_POST;
+  request().path = purl.full_path();
+  request().setContent(content_type, request_doc);
+}
+
+void HttpClient::release() {
+  if (StreamInterface* stream = base_.detach()) {
+    pool_->ReturnConnectedStream(stream);
+  }
+}
+
+bool HttpClient::BeginCacheFile() {
+  ASSERT(NULL != cache_);
+  ASSERT(CS_READY == cache_state_);
+
+  std::string id = GetCacheID(server_, request_);
+  CacheLock lock(cache_, id, true);
+  if (!lock.IsLocked()) {
+    LOG_F(LS_WARNING) << "Couldn't lock cache";
+    return false;
+  }
+
+  if (HE_NONE != WriteCacheHeaders(id)) {
+    return false;
+  }
+
+  scoped_ptr<StreamInterface> stream(cache_->WriteResource(id, kCacheBody));
+  if (!stream.get()) {
+    LOG_F(LS_ERROR) << "Couldn't open body cache";
+    return false;
+  }
+  lock.Commit();
+
+  // 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();
+  if (!output) {
+    output = new NullStream;
+  }
+  StreamTap* tap = new StreamTap(output, stream.release());
+  response_.document.reset(tap);
+  return true;
+}
+
+HttpError HttpClient::WriteCacheHeaders(const std::string& id) {
+  scoped_ptr<StreamInterface> stream(cache_->WriteResource(id, kCacheHeader));
+  if (!stream.get()) {
+    LOG_F(LS_ERROR) << "Couldn't open header cache";
+    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;
+    }
+  }
+
+  return HE_NONE;
+}
+
+void HttpClient::CompleteCacheFile() {
+  // Restore previous response document
+  StreamTap* tap = static_cast<StreamTap*>(response_.document.release());
+  response_.document.reset(tap->Detach());
+
+  int error;
+  StreamResult result = tap->GetTapResult(&error);
+
+  // Delete the tap and cache stream (which completes cache unlock)
+  delete tap;
+
+  if (SR_SUCCESS != result) {
+    LOG(LS_ERROR) << "Cache file error: " << error;
+    cache_->DeleteResource(GetCacheID(server_, request_));
+  }
+}
+
+bool HttpClient::CheckCache() {
+  ASSERT(NULL != cache_);
+  ASSERT(CS_READY == cache_state_);
+
+  std::string id = GetCacheID(server_, request_);
+  if (!cache_->HasResource(id)) {
+    // No cache file available
+    return false;
+  }
+
+  HttpError error = ReadCacheHeaders(id, true);
+
+  if (HE_NONE == error) {
+    switch (HttpGetCacheState(request_, response_)) {
+    case HCS_FRESH:
+      // Cache content is good, read from cache
+      break;
+    case HCS_STALE:
+      // Cache content may be acceptable.  Issue a validation request.
+      if (PrepareValidate()) {
+        return false;
+      }
+      // Couldn't validate, fall through.
+    case HCS_NONE:
+      // Cache content is not useable.  Issue a regular request.
+      response_.clear(false);
+      return false;
+    }
+  }
+
+  if (HE_NONE == error) {
+    error = ReadCacheBody(id);
+    cache_state_ = CS_READY;
+  }
+
+  if (HE_CACHE == error) {
+    LOG_F(LS_WARNING) << "Cache failure, continuing with normal request";
+    response_.clear(false);
+    return false;
+  }
+
+  SignalHttpClientComplete(this, error);
+  return true;
+}
+
+HttpError HttpClient::ReadCacheHeaders(const std::string& id, bool override) {
+  scoped_ptr<StreamInterface> stream(cache_->ReadResource(id, kCacheHeader));
+  if (!stream.get()) {
+    return HE_CACHE;
+  }
+
+  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);
+  }
+
+  response_.scode = HC_OK;
+  return HE_NONE;
+}
+
+HttpError HttpClient::ReadCacheBody(const std::string& id) {
+  cache_state_ = CS_READING;
+
+  HttpError error = HE_NONE;
+
+  size_t data_size;
+  scoped_ptr<StreamInterface> stream(cache_->ReadResource(id, kCacheBody));
+  if (!stream.get() || !stream->GetSize(&data_size)) {
+    LOG_F(LS_ERROR) << "Unavailable cache body";
+    error = HE_CACHE;
+  } else {
+    error = OnHeaderAvailable(false, false, data_size);
+  }
+
+  if ((HE_NONE == error)
+      && (HV_HEAD != request_.verb)
+      && (NULL != response_.document.get())) {
+    char buffer[1024 * 64];
+    StreamResult result = Flow(stream.get(), buffer, ARRAY_SIZE(buffer),
+                               response_.document.get());
+    if (SR_SUCCESS != result) {
+      error = HE_STREAM;
+    }
+  }
+
+  return error;
+}
+
+bool HttpClient::PrepareValidate() {
+  ASSERT(CS_READY == cache_state_);
+  // 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_);
+  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_LAST_MODIFIED, &value)) {
+    request_.addHeader(HH_IF_MODIFIED_SINCE, value);
+  }
+  response_.clear(false);
+  cache_state_ = CS_VALIDATING;
+  return true;
+}
+
+HttpError HttpClient::CompleteValidate() {
+  ASSERT(CS_VALIDATING == cache_state_);
+
+  std::string id = GetCacheID(server_, request_);
+
+  // Merge cached headers with new headers
+  HttpError error = ReadCacheHeaders(id, false);
+  if (HE_NONE != error) {
+    // Rewrite merged headers to cache
+    CacheLock lock(cache_, id);
+    error = WriteCacheHeaders(id);
+  }
+  if (HE_NONE != error) {
+    error = ReadCacheBody(id);
+  }
+  return error;
+}
+
+HttpError HttpClient::OnHeaderAvailable(bool ignore_data, bool chunked,
+                                        size_t data_size) {
+  if (!ignore_data && !chunked && response_.document.get()) {
+    // Attempt to pre-allocate space for the downloaded data.
+    if (!response_.document->ReserveSize(data_size)) {
+      return HE_OVERFLOW;
+    }
+  }
+  SignalHeaderAvailable(this, chunked, data_size);
+  return HE_NONE;
+}
+
+//
+// HttpBase Implementation
+//
+
+HttpError HttpClient::onHttpHeaderComplete(bool chunked, size_t& data_size) {
+  if (CS_VALIDATING == cache_state_) {
+    if (HC_NOT_MODIFIED == response_.scode) {
+      return CompleteValidate();
+    }
+    // Should we remove conditional headers from request?
+    cache_state_ = CS_READY;
+    cache_->DeleteResource(GetCacheID(server_, request_));
+    // Continue processing response as normal
+  }
+
+  ASSERT(!IsCacheActive());
+  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)
+          && (PROXY_HTTPS == proxy_.type))) {
+    // We're going to issue another request, so ignore the incoming data.
+    base_.set_ignore_data(true);
+  }
+
+  HttpError error = OnHeaderAvailable(base_.ignore_data(), chunked, data_size);
+  if (HE_NONE != error) {
+    return error;
+  }
+
+  if ((NULL != cache_)
+      && !base_.ignore_data()
+      && HttpShouldCache(request_, response_)) {
+    if (BeginCacheFile()) {
+      cache_state_ = CS_WRITING;
+    }
+  }
+  return HE_NONE;
+}
+
+void HttpClient::onHttpComplete(HttpMode mode, HttpError err) {
+  if (err != HE_NONE) {
+    // fall through
+  } else if (mode == HM_CONNECT) {
+    base_.send(&request_);
+    return;
+  } else if ((mode == HM_SEND) || HttpCodeIsInformational(response_.scode)) {
+    // If you're interested in informational headers, catch
+    // SignalHeaderAvailable.
+    base_.recv(&response_);
+    return;
+  } else {
+    if (!HttpShouldKeepAlive(response_)) {
+      LOG(INFO) << "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;
+        }
+      }
+      if (err == HE_NONE) {
+        context_.reset();
+        response_.clear(false);
+        release();
+        start();
+        return;
+      }
+    } 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);
+      for (HttpData::const_iterator it = begin; it != end; ++it) {
+        HttpAuthResult res = HttpAuthenticate(
+          it->second.data(), it->second.size(),
+          proxy_.address,
+          ToString(request_.verb), request_.path,
+          proxy_.username, proxy_.password,
+          *context_.use(), response, auth_method);
+        if (res == HAR_RESPONSE) {
+          request_.setHeader(HH_PROXY_AUTHORIZATION, response);
+          if (request_.document.get() && !request_.document->Rewind()) {
+            err = HE_STREAM;
+          } else {
+            // Explicitly do not reset the HttpAuthContext
+            response_.clear(false);
+            // TODO: Reuse socket when authenticating?
+            release();
+            start();
+            return;
+          }
+        } else if (res == HAR_IGNORE) {
+          LOG(INFO) << "Ignoring Proxy-Authenticate: " << auth_method;
+          continue;
+        } else {
+          break;
+        }
+      }
+    }
+  }
+  if (CS_WRITING == cache_state_) {
+    CompleteCacheFile();
+    cache_state_ = CS_READY;
+  } else if (CS_READING == cache_state_) {
+    cache_state_ = CS_READY;
+  }
+  release();
+  SignalHttpClientComplete(this, err);
+}
+
+void HttpClient::onHttpClosed(HttpError err) {
+  SignalHttpClientClosed(this, err);
+}
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/httpclient.h b/talk/base/httpclient.h
new file mode 100755
index 0000000..789cb59
--- /dev/null
+++ b/talk/base/httpclient.h
@@ -0,0 +1,155 @@
+/*
+ * 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_HTTPCLIENT_H__
+#define TALK_BASE_HTTPCLIENT_H__
+
+#include "talk/base/common.h"
+#include "talk/base/httpbase.h"
+#include "talk/base/proxyinfo.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/socketaddress.h"
+#include "talk/base/socketpool.h"
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// HttpClient
+//////////////////////////////////////////////////////////////////////
+
+class DiskCache;
+class HttpClient;
+class IPNetPool;
+
+class HttpClient : private IHttpNotify {
+public:
+  HttpClient(const std::string& agent, StreamPool* pool);
+  virtual ~HttpClient();
+
+  void set_pool(StreamPool* pool) { pool_ = pool; }
+
+  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_; }
+
+  void use_absolute_uri(bool absolute_uri) { absolute_uri_ = absolute_uri; }
+  bool absolute_uri() const { return absolute_uri_; }
+
+  void set_cache(DiskCache* cache) { ASSERT(!IsCacheActive()); cache_ = cache; }
+  bool cache_enabled() const { return (NULL != cache_); }
+
+  // reset clears the server, request, and response structures.  It will also
+  // abort an active request.
+  void reset();
+  
+  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_; }
+  
+  // convenience methods
+  void prepare_get(const std::string& url);
+  void prepare_post(const std::string& url, const std::string& content_type,
+                    StreamInterface* request_doc);
+
+  // 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;
+
+protected:
+  void release();
+
+  bool BeginCacheFile();
+  HttpError WriteCacheHeaders(const std::string& id);
+  void CompleteCacheFile();
+
+  bool CheckCache();
+  HttpError ReadCacheHeaders(const std::string& id, bool override);
+  HttpError ReadCacheBody(const std::string& id);
+
+  bool PrepareValidate();
+  HttpError CompleteValidate();
+
+  HttpError OnHeaderAvailable(bool ignore_data, bool chunked, size_t data_size);
+
+  // IHttpNotify Interface
+  virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size);
+  virtual void onHttpComplete(HttpMode mode, HttpError err);
+  virtual void onHttpClosed(HttpError err);
+  
+private:
+  enum CacheState { CS_READY, CS_WRITING, CS_READING, CS_VALIDATING };
+  bool IsCacheActive() const { return (cache_state_ > CS_READY); }
+
+  std::string agent_;
+  StreamPool* pool_;
+  HttpBase base_;
+  SocketAddress server_;
+  ProxyInfo proxy_;
+  HttpRequestData request_;
+  HttpResponseData response_;
+  bool fail_redirect_, absolute_uri_;
+  scoped_ptr<HttpAuthContext> context_;
+  DiskCache* cache_;
+  CacheState cache_state_;
+};
+
+//////////////////////////////////////////////////////////////////////
+// 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);
+  }
+};
+
+//////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif // TALK_BASE_HTTPCLIENT_H__
diff --git a/talk/base/httpcommon-inl.h b/talk/base/httpcommon-inl.h
new file mode 100755
index 0000000..5235b89
--- /dev/null
+++ b/talk/base/httpcommon-inl.h
@@ -0,0 +1,114 @@
+/*
+ * 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_HTTPCOMMON_INL_H__
+#define TALK_BASE_HTTPCOMMON_INL_H__
+
+#include "talk/base/common.h"
+#include "talk/base/httpcommon.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// Url
+///////////////////////////////////////////////////////////////////////////////
+
+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;
+  } else {
+    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);
+    }
+  }
+  ASSERT(m_path.empty() || (m_path[0] == static_cast<CTYPE>('/')));
+  ASSERT(m_query.empty() || (m_query[0] == static_cast<CTYPE>('?')));
+}
+
+template<class CTYPE>
+typename Traits<CTYPE>::string Url<CTYPE>::full_path() {
+  string full_path(m_path);
+  full_path.append(m_query);
+  return full_path;
+}
+
+template<class CTYPE>
+typename Traits<CTYPE>::string Url<CTYPE>::url() {
+  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)) {
+    CTYPE format[5], port[32];
+    asccpyn(format, ARRAY_SIZE(format), ":%hu");
+    sprintfn(port, ARRAY_SIZE(port), format, m_port);
+    url.append(port);
+  }
+  url.append(m_path);
+  url.append(m_query);
+  return url;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif  // TALK_BASE_HTTPCOMMON_INL_H__
diff --git a/talk/base/httpcommon.cc b/talk/base/httpcommon.cc
new file mode 100755
index 0000000..0358121
--- /dev/null
+++ b/talk/base/httpcommon.cc
@@ -0,0 +1,940 @@
+/*
+ * 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>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define _WINSOCKAPI_
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+#endif
+
+#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/stringutils.h"
+
+namespace talk_base {
+
+#ifdef WIN32
+extern const ConstantLabel SECURITY_ERRORS[];
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Enum - TODO: expose globally later?
+//////////////////////////////////////////////////////////////////////
+
+bool find_string(size_t& index, const std::string& needle,
+                 const char* const haystack[], size_t max_index) {
+  for (index=0; index<max_index; ++index) {
+	if (_stricmp(needle.c_str(), haystack[index]) == 0) {
+	  return true;
+	}
+  }
+  return false;
+}
+
+template<class E>
+struct Enum {
+  static const char** Names;
+  static size_t Size;
+
+  static inline const char* Name(E val) { return Names[val]; }
+  static inline bool Parse(E& val, const std::string& name) { 
+	size_t index;
+	if (!find_string(index, name, Names, Size))
+	  return false;
+	val = static_cast<E>(index);
+	return true;
+  }
+
+  E val;
+
+  inline operator E&() { return val; }
+  inline Enum& operator=(E rhs) { val = rhs; return *this; }
+
+  inline const char* name() const { return Name(val); }
+  inline bool assign(const std::string& name) { return Parse(val, name); }
+  inline Enum& operator=(const std::string& rhs) { assign(rhs); return *this; }
+};
+
+#define ENUM(e,n) \
+  template<> const char** Enum<e>::Names = n; \
+  template<> size_t Enum<e>::Size = sizeof(n)/sizeof(n[0])
+
+//////////////////////////////////////////////////////////////////////
+// HttpCommon
+//////////////////////////////////////////////////////////////////////
+
+static const char* kHttpVersions[HVER_LAST+1] = {
+  "1.0", "1.1"
+};
+ENUM(HttpVersion, kHttpVersions);
+
+static const char* kHttpVerbs[HV_LAST+1] = {
+  "GET", "POST", "PUT", "DELETE", "CONNECT", "HEAD"
+};
+ENUM(HttpVerb, kHttpVerbs);
+
+static const char* kHttpHeaders[HH_LAST+1] = {
+  "Age",
+  "Cache-Control",
+  "Connection",
+  "Content-Length",
+  "Content-Range",
+  "Content-Type",
+  "Cookie",
+  "Date",
+  "ETag",
+  "Expires",
+  "Host",
+  "If-Modified-Since",
+  "If-None-Match",
+  "Keep-Alive",
+  "Last-Modified",
+  "Location",
+  "Proxy-Authenticate",
+  "Proxy-Authorization",
+  "Proxy-Connection",
+  "Range",
+  "Set-Cookie",
+  "TE",
+  "Trailers",
+  "Transfer-Encoding",
+  "Upgrade",
+  "User-Agent",
+  "WWW-Authenticate",
+};
+ENUM(HttpHeader, kHttpHeaders);
+
+const char* ToString(HttpVersion version) {
+  return Enum<HttpVersion>::Name(version);
+}
+
+bool FromString(HttpVersion& version, const std::string& str) {
+  return Enum<HttpVersion>::Parse(version, str);
+}
+
+const char* ToString(HttpVerb verb) {
+  return Enum<HttpVerb>::Name(verb);
+}
+
+bool FromString(HttpVerb& verb, const std::string& str) {
+  return Enum<HttpVerb>::Parse(verb, str);
+}
+
+const char* ToString(HttpHeader header) {
+  return Enum<HttpHeader>::Name(header);
+}
+
+bool FromString(HttpHeader& header, const std::string& str) {
+  return Enum<HttpHeader>::Parse(header, str);
+}
+
+bool HttpCodeHasBody(uint32 code) {
+  return !HttpCodeIsInformational(code)
+         && (code != HC_NO_CONTENT) || (code != HC_NOT_MODIFIED);
+}
+
+bool HttpCodeIsCacheable(uint32 code) {
+  switch (code) {
+  case HC_OK:
+  case HC_NON_AUTHORITATIVE:
+  case HC_PARTIAL_CONTENT:
+  case HC_MULTIPLE_CHOICES:
+  case HC_MOVED_PERMANENTLY:
+  case HC_GONE:
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool HttpHeaderIsEndToEnd(HttpHeader header) {
+  switch (header) {
+  case HH_CONNECTION:
+  case HH_KEEP_ALIVE:
+  case HH_PROXY_AUTHENTICATE:
+  case HH_PROXY_AUTHORIZATION:
+  //case HH_PROXY_CONNECTION:??
+  case HH_TE:
+  case HH_TRAILERS:
+  case HH_TRANSFER_ENCODING:
+  case HH_UPGRADE:
+    return false;
+  default:
+    return true;
+  }
+}
+
+bool HttpHeaderIsCollapsible(HttpHeader header) {
+  switch (header) {
+  case HH_SET_COOKIE:
+  case HH_PROXY_AUTHENTICATE:
+  case HH_WWW_AUTHENTICATE:
+    return false;
+  default:
+    return true;
+  }
+}
+
+bool HttpShouldKeepAlive(const HttpData& data) {
+  std::string connection;
+  if ((data.hasHeader(HH_PROXY_CONNECTION, &connection)
+      || data.hasHeader(HH_CONNECTION, &connection))) {
+    return (_stricmp(connection.c_str(), "Keep-Alive") == 0);
+  }
+  return (data.version >= HVER_1_1);
+}
+
+namespace {
+
+inline bool IsEndOfAttributeName(size_t pos, size_t len, const char * data) {
+  if (pos >= len)
+    return true;
+  if (isspace(static_cast<unsigned char>(data[pos])))
+    return true;
+  // The reason for this complexity is that some attributes may contain trailing
+  // equal signs (like base64 tokens in Negotiate auth headers)
+  if ((pos+1 < len) && (data[pos] == '=') &&
+      !isspace(static_cast<unsigned char>(data[pos+1])) &&
+      (data[pos+1] != '=')) {
+    return true;
+  }
+  return false;
+}
+
+}  // anonymous namespace
+
+void HttpParseAttributes(const char * data, size_t len, 
+                         HttpAttributeList& attributes) {
+  size_t pos = 0;
+  while (true) {
+    // Skip leading whitespace
+    while ((pos < len) && isspace(static_cast<unsigned char>(data[pos]))) {
+      ++pos;
+    }
+
+    // End of attributes?
+    if (pos >= len)
+      return;
+
+    // Find end of attribute name
+    size_t start = pos;
+    while (!IsEndOfAttributeName(pos, len, data)) {
+      ++pos;
+    }
+
+    HttpAttribute attribute;
+    attribute.first.assign(data + start, data + pos);
+
+    // Attribute has value?
+    if ((pos < len) && (data[pos] == '=')) {
+      ++pos; // Skip '='
+      // Check if quoted value
+      if ((pos < len) && (data[pos] == '"')) {
+        while (++pos < len) {
+          if (data[pos] == '"') {
+            ++pos;
+            break;
+          }
+          if ((data[pos] == '\\') && (pos + 1 < len))
+            ++pos;
+          attribute.second.append(1, data[pos]);
+        }
+      } else {
+        while ((pos < len) &&
+            !isspace(static_cast<unsigned char>(data[pos])) &&
+            (data[pos] != ',')) {
+          attribute.second.append(1, data[pos++]);
+        }
+      }
+    }
+
+    attributes.push_back(attribute);
+    if ((pos < len) && (data[pos] == ',')) ++pos; // Skip ','
+  }
+}
+
+bool HttpHasAttribute(const HttpAttributeList& attributes,
+                      const std::string& name,
+                      std::string* value) {
+  for (HttpAttributeList::const_iterator it = attributes.begin();
+       it != attributes.end(); ++it) {
+    if (it->first == name) {
+      if (value) {
+        *value = it->second;
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+bool HttpHasNthAttribute(HttpAttributeList& attributes,
+                         size_t index, 
+                         std::string* name,
+                         std::string* value) {
+  if (index >= attributes.size())
+    return false;
+
+  if (name)
+    *name = attributes[index].first;
+  if (value)
+    *value = attributes[index].second;
+  return true;
+}
+
+bool HttpDateToSeconds(const std::string& date, unsigned long* seconds) {
+  const char* const kTimeZones[] = {
+    "UT", "GMT", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", "PDT",
+    "A", "B", "C", "D", "E", "F", "G", "H", "I", "K", "L", "M",
+    "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y"
+  };
+  const int kTimeZoneOffsets[] = {
+     0,  0, -5, -4, -6, -5, -7, -6, -8, -7,
+    -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12,
+     1,  2,  3,  4,  5,  6,  7,  8,  9,  10,  11,  12
+  };
+
+  ASSERT(NULL != seconds);
+  struct tm tval;
+  memset(&tval, 0, sizeof(tval));
+  char month[4], zone[6];
+  memset(month, 0, sizeof(month));
+  memset(zone, 0, sizeof(zone));
+
+  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)) {
+    return false;
+  }
+  switch (toupper(month[2])) {
+  case 'N': tval.tm_mon = (month[1] == 'A') ? 0 : 5; break;
+  case 'B': tval.tm_mon = 1; break;
+  case 'R': tval.tm_mon = (month[0] == 'M') ? 2 : 3; break;
+  case 'Y': tval.tm_mon = 4; break;
+  case 'L': tval.tm_mon = 6; break;
+  case 'G': tval.tm_mon = 7; break;
+  case 'P': tval.tm_mon = 8; break;
+  case 'T': tval.tm_mon = 9; break;
+  case 'V': tval.tm_mon = 10; break;
+  case 'C': tval.tm_mon = 11; break;
+  }
+  tval.tm_year -= 1900;
+  unsigned long gmt, non_gmt = mktime(&tval);
+  if ((zone[0] == '+') || (zone[0] == '-')) {
+    if (!isdigit(zone[1]) || !isdigit(zone[2])
+        || !isdigit(zone[3]) || !isdigit(zone[4])) {
+      return false;
+    }
+    int hours = (zone[1] - '0') * 10 + (zone[2] - '0');
+    int minutes = (zone[3] - '0') * 10 + (zone[4] - '0');
+    int offset = (hours * 60 + minutes) * 60;
+    gmt = non_gmt + (zone[0] == '+') ? offset : -offset;
+  } else {
+    size_t zindex;
+    if (!find_string(zindex, zone, kTimeZones, ARRAY_SIZE(kTimeZones))) {
+      return false;
+    }
+    gmt = non_gmt + kTimeZoneOffsets[zindex] * 60 * 60;
+  }
+#ifdef OSX
+  tm *tm_for_timezone = localtime((time_t *)&gmt);
+  *seconds = gmt + tm_for_timezone->tm_gmtoff;
+#else
+  *seconds = gmt - timezone;
+#endif
+  return true;
+}
+
+//////////////////////////////////////////////////////////////////////
+// HttpData
+//////////////////////////////////////////////////////////////////////
+
+void
+HttpData::clear(bool release_document) {
+  if (release_document) {
+    document.reset();
+  }
+  m_headers.clear();
+}
+
+void
+HttpData::changeHeader(const std::string& name, const std::string& value,
+                       HeaderCombine combine) {
+  if (combine == HC_AUTO) {
+    HttpHeader header;
+    // Unrecognized headers are collapsible
+    combine = !FromString(header, name) || HttpHeaderIsCollapsible(header)
+              ? HC_YES : HC_NO;
+  } else if (combine == HC_REPLACE) {
+    m_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()) {
+      if (combine == HC_YES) {
+        it->second.append(",");
+        it->second.append(value);
+	  }
+      return;
+	}
+  }
+  m_headers.insert(HeaderMap::value_type(name, value));
+}
+
+void
+HttpData::clearHeader(const std::string& name) {
+  m_headers.erase(name);
+}
+
+bool
+HttpData::hasHeader(const std::string& name, std::string* value) const {
+  HeaderMap::const_iterator it = m_headers.find(name);
+  if (it == m_headers.end()) {
+    return false;
+  } else if (value) {
+    *value = it->second;
+  }
+  return true;
+}
+
+void
+HttpData::setContent(const std::string& content_type,
+                     StreamInterface* document) {
+  ASSERT(document != NULL);
+  this->document.reset(document);
+  setHeader(HH_CONTENT_TYPE, content_type);
+  size_t content_length = 0;
+  if (this->document->GetSize(&content_length)) {
+    char buffer[32];
+    sprintfn(buffer, sizeof(buffer), "%d", content_length);
+    setHeader(HH_CONTENT_LENGTH, buffer);
+  } else {
+    setHeader(HH_TRANSFER_ENCODING, "chunked");
+  }
+}
+
+//
+// HttpRequestData
+//
+
+void
+HttpRequestData::clear(bool release_document) {
+  HttpData::clear(release_document);
+  verb = HV_GET;
+  path.clear();
+}
+
+size_t
+HttpRequestData::formatLeader(char* buffer, size_t size) {
+  ASSERT(path.find(' ') == std::string::npos);
+  return sprintfn(buffer, size, "%s %.*s HTTP/%s", ToString(verb), path.size(),
+                  path.data(), ToString(version));
+}
+
+HttpError
+HttpRequestData::parseLeader(const char* line, size_t len) {
+  UNUSED(len);
+  uint32 vmajor, vminor;
+  int vend, dstart, dend;
+  if ((sscanf(line, "%*s%n %n%*s%n HTTP/%lu.%lu", &vend, &dstart, &dend,
+              &vmajor, &vminor) != 2)
+      || (vmajor != 1)) {
+    return HE_PROTOCOL;
+  }
+  if (vminor == 0) {
+    version = HVER_1_0;
+  } else if (vminor == 1) {
+    version = HVER_1_1;
+  } else {
+    return HE_PROTOCOL;
+  }
+  std::string sverb(line, vend);
+  if (!FromString(verb, sverb.c_str())) {
+    return HE_PROTOCOL; // !?! HC_METHOD_NOT_SUPPORTED?
+  }
+  path.assign(line + dstart, line + dend);
+  return HE_NONE;
+}
+
+//
+// HttpResponseData
+//
+
+void
+HttpResponseData::clear(bool release_document) {
+  HttpData::clear(release_document);
+  scode = HC_INTERNAL_SERVER_ERROR;
+  message.clear();
+}
+
+void
+HttpResponseData::set_success(uint32 scode) {
+  this->scode = scode;
+  message.clear();
+  setHeader(HH_CONTENT_LENGTH, "0");
+}
+
+void
+HttpResponseData::set_success(const std::string& content_type,
+                              StreamInterface* document,
+                              uint32 scode) {
+  this->scode = scode;
+  message.erase(message.begin(), message.end());
+  setContent(content_type, document);
+}
+
+void
+HttpResponseData::set_redirect(const std::string& location, uint32 scode) {
+  this->scode = scode;
+  message.clear();
+  setHeader(HH_LOCATION, location);
+  setHeader(HH_CONTENT_LENGTH, "0");
+}
+
+void
+HttpResponseData::set_error(uint32 scode) {
+  this->scode = scode;
+  message.clear();
+  setHeader(HH_CONTENT_LENGTH, "0");
+}
+
+size_t
+HttpResponseData::formatLeader(char* buffer, size_t size) {
+  size_t len = sprintfn(buffer, size, "HTTP/%s %lu", ToString(version), scode);
+  if (!message.empty()) {
+    len += sprintfn(buffer + len, size - len, " %.*s",
+                    message.size(), message.data());
+  }
+  return len;
+}
+
+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;
+  } else {
+    return HE_PROTOCOL;
+  }
+  while ((pos < len) && isspace(static_cast<unsigned char>(line[pos]))) ++pos;
+  message.assign(line + pos, len - pos);
+  return HE_NONE;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Http Authentication
+//////////////////////////////////////////////////////////////////////
+
+#define TEST_DIGEST 0
+#if TEST_DIGEST
+/*
+const char * const DIGEST_CHALLENGE =
+  "Digest realm=\"testrealm@host.com\","
+  " qop=\"auth,auth-int\","
+  " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","
+  " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
+const char * const DIGEST_METHOD = "GET";
+const char * const DIGEST_URI =
+  "/dir/index.html";;
+const char * const DIGEST_CNONCE =
+  "0a4f113b";
+const char * const DIGEST_RESPONSE =
+  "6629fae49393a05397450978507c4ef1";
+//user_ = "Mufasa";
+//pass_ = "Circle Of Life";
+*/
+const char * const DIGEST_CHALLENGE =
+  "Digest realm=\"Squid proxy-caching web server\","
+  " nonce=\"Nny4QuC5PwiSDixJ\","
+  " qop=\"auth\","
+  " stale=false";
+const char * const DIGEST_URI =
+  "/";
+const char * const DIGEST_CNONCE =
+  "6501d58e9a21cee1e7b5fec894ded024";
+const char * const DIGEST_RESPONSE =
+  "edffcb0829e755838b073a4a42de06bc";
+#endif
+
+static std::string quote(const std::string& str) {
+  std::string result;
+  result.push_back('"');
+  for (size_t i=0; i<str.size(); ++i) {
+    if ((str[i] == '"') || (str[i] == '\\'))
+      result.push_back('\\');
+    result.push_back(str[i]);
+  }
+  result.push_back('"');
+  return result;
+}
+
+#ifdef WIN32
+struct NegotiateAuthContext : public HttpAuthContext {
+  CredHandle cred;
+  CtxtHandle ctx;
+  size_t steps;
+  bool specified_credentials;
+
+  NegotiateAuthContext(const std::string& auth, CredHandle c1, CtxtHandle c2)
+  : HttpAuthContext(auth), cred(c1), ctx(c2), steps(0),
+    specified_credentials(false)
+  { }
+
+  virtual ~NegotiateAuthContext() {
+    DeleteSecurityContext(&ctx);
+    FreeCredentialsHandle(&cred);
+  }
+};
+#endif // WIN32
+
+HttpAuthResult HttpAuthenticate(
+  const char * challenge, size_t len,
+  const SocketAddress& server,
+  const std::string& method, const std::string& uri,
+  const std::string& username, const CryptString& password,
+  HttpAuthContext *& context, std::string& response, std::string& auth_method)
+{
+#if TEST_DIGEST
+  challenge = DIGEST_CHALLENGE;
+  len = strlen(challenge);
+#endif
+
+  HttpAttributeList args;
+  HttpParseAttributes(challenge, len, args);
+  HttpHasNthAttribute(args, 0, &auth_method, NULL);
+
+  if (context && (context->auth_method != auth_method))
+    return HAR_IGNORE;
+
+  // BASIC
+  if (_stricmp(auth_method.c_str(), "basic") == 0) {
+    if (context)
+      return HAR_CREDENTIALS; // Bad credentials
+    if (username.empty())
+      return HAR_CREDENTIALS; // Missing credentials
+
+    context = new HttpAuthContext(auth_method);
+
+    // TODO: convert sensitive to a secure buffer that gets securely deleted
+    //std::string decoded = username + ":" + password;
+    size_t len = username.size() + password.GetLength() + 2;
+    char * sensitive = new char[len];
+    size_t pos = strcpyn(sensitive, len, username.data(), username.size());
+    pos += strcpyn(sensitive + pos, len - pos, ":");
+    password.CopyTo(sensitive + pos, true);
+
+    response = auth_method;
+    response.append(" ");
+    // TODO: create a sensitive-source version of Base64::encode
+    response.append(Base64::encode(sensitive));
+    memset(sensitive, 0, len);
+    delete [] sensitive;
+    return HAR_RESPONSE;
+  }
+
+  // DIGEST
+  if (_stricmp(auth_method.c_str(), "digest") == 0) {
+    if (context)
+      return HAR_CREDENTIALS; // Bad credentials
+    if (username.empty())
+      return HAR_CREDENTIALS; // Missing credentials
+
+    context = new HttpAuthContext(auth_method);
+
+    std::string cnonce, ncount;
+#if TEST_DIGEST
+    method = DIGEST_METHOD;
+    uri    = DIGEST_URI;
+    cnonce = DIGEST_CNONCE;
+#else
+    char buffer[256];
+    sprintf(buffer, "%d", time(0));
+    cnonce = MD5(buffer);
+#endif
+    ncount = "00000001";
+
+    std::string realm, nonce, qop, opaque;
+    HttpHasAttribute(args, "realm", &realm);
+    HttpHasAttribute(args, "nonce", &nonce);
+    bool has_qop = HttpHasAttribute(args, "qop", &qop);
+    bool has_opaque = HttpHasAttribute(args, "opaque", &opaque);
+
+    // TODO: convert sensitive to be secure buffer
+    //std::string A1 = username + ":" + realm + ":" + password;
+    size_t len = username.size() + realm.size() + password.GetLength() + 3;
+    char * sensitive = new char[len];  // A1
+    size_t pos = strcpyn(sensitive, len, username.data(), username.size());
+    pos += strcpyn(sensitive + pos, len - pos, ":");
+    pos += strcpyn(sensitive + pos, len - pos, realm.c_str());
+    pos += strcpyn(sensitive + pos, len - pos, ":");
+    password.CopyTo(sensitive + pos, true);
+
+    std::string A2 = method + ":" + uri;
+    std::string middle;
+    if (has_qop) {
+      qop = "auth";
+      middle = nonce + ":" + ncount + ":" + cnonce + ":" + qop;
+    } else {
+      middle = nonce;
+    }
+    std::string HA1 = MD5(sensitive);
+    memset(sensitive, 0, len);
+    delete [] sensitive;
+    std::string HA2 = MD5(A2);
+    std::string dig_response = MD5(HA1 + ":" + middle + ":" + HA2);
+
+#if TEST_DIGEST
+    assert(strcmp(dig_response.c_str(), DIGEST_RESPONSE) == 0);
+#endif
+
+    std::stringstream ss;
+    ss << auth_method;
+    ss << " username=" << quote(username);
+    ss << ", realm=" << quote(realm);
+    ss << ", nonce=" << quote(nonce);
+    ss << ", uri=" << quote(uri);
+    if (has_qop) {
+      ss << ", qop=" << qop;
+      ss << ", nc="  << ncount;
+      ss << ", cnonce=" << quote(cnonce);
+    }
+    ss << ", response=\"" << dig_response << "\"";
+    if (has_opaque) {
+      ss << ", opaque=" << quote(opaque);
+    }
+    response = ss.str();
+    return HAR_RESPONSE;
+  }
+
+#ifdef WIN32
+#if 1
+  bool want_negotiate = (_stricmp(auth_method.c_str(), "negotiate") == 0);
+  bool want_ntlm = (_stricmp(auth_method.c_str(), "ntlm") == 0);
+  // SPNEGO & NTLM
+  if (want_negotiate || want_ntlm) {
+    const size_t MAX_MESSAGE = 12000, MAX_SPN = 256;
+    char out_buf[MAX_MESSAGE], spn[MAX_SPN];
+
+#if 0 // Requires funky windows versions
+    DWORD len = MAX_SPN;
+    if (DsMakeSpn("HTTP", server.IPAsString().c_str(), NULL, server.port(),
+                  0, &len, spn) != ERROR_SUCCESS) {
+      LOG_F(WARNING) << "(Negotiate) - DsMakeSpn failed";
+      return HAR_IGNORE;
+    }
+#else
+    sprintfn(spn, MAX_SPN, "HTTP/%s", server.ToString().c_str());
+#endif
+
+    SecBuffer out_sec;
+    out_sec.pvBuffer   = out_buf;
+    out_sec.cbBuffer   = sizeof(out_buf);
+    out_sec.BufferType = SECBUFFER_TOKEN;
+
+    SecBufferDesc out_buf_desc;
+    out_buf_desc.ulVersion = 0;
+    out_buf_desc.cBuffers  = 1;
+    out_buf_desc.pBuffers  = &out_sec;
+
+    const ULONG NEG_FLAGS_DEFAULT =
+      //ISC_REQ_ALLOCATE_MEMORY
+      ISC_REQ_CONFIDENTIALITY
+      //| ISC_REQ_EXTENDED_ERROR
+      //| ISC_REQ_INTEGRITY
+      | ISC_REQ_REPLAY_DETECT
+      | ISC_REQ_SEQUENCE_DETECT
+      //| ISC_REQ_STREAM
+      //| ISC_REQ_USE_SUPPLIED_CREDS
+      ;
+
+    TimeStamp lifetime;
+    SECURITY_STATUS ret = S_OK;
+    ULONG ret_flags = 0, flags = NEG_FLAGS_DEFAULT;
+
+    bool specify_credentials = !username.empty();
+    size_t steps = 0;
+
+    //uint32 now = Time();
+
+    NegotiateAuthContext * neg = static_cast<NegotiateAuthContext *>(context);
+    if (neg) {
+      const size_t max_steps = 10;
+      if (++neg->steps >= max_steps) {
+        LOG(WARNING) << "AsyncHttpsProxySocket::Authenticate(Negotiate) too many retries";
+        return HAR_ERROR;
+      }
+      steps = neg->steps;
+
+      std::string decoded_challenge;
+      HttpHasNthAttribute(args, 1, &decoded_challenge, NULL);
+      decoded_challenge = Base64::decode(decoded_challenge);
+      if (!decoded_challenge.empty()) {
+        SecBuffer in_sec;
+        in_sec.pvBuffer   = const_cast<char *>(decoded_challenge.data());
+        in_sec.cbBuffer   = static_cast<unsigned long>(decoded_challenge.size());
+        in_sec.BufferType = SECBUFFER_TOKEN;
+
+        SecBufferDesc in_buf_desc;
+        in_buf_desc.ulVersion = 0;
+        in_buf_desc.cBuffers  = 1;
+        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);
+        if (FAILED(ret)) {
+          LOG(LS_ERROR) << "InitializeSecurityContext returned: "
+                      << ErrorName(ret, SECURITY_ERRORS);
+          return HAR_ERROR;
+        }
+      } else if (neg->specified_credentials) {
+        // Try again with default credentials
+        specify_credentials = false;
+        delete context;
+        context = neg = 0;
+      } else {
+        return HAR_CREDENTIALS;
+      }
+    }
+
+    if (!neg) {
+      unsigned char userbuf[256], passbuf[256], domainbuf[16];
+      SEC_WINNT_AUTH_IDENTITY_A auth_id, * pauth_id = 0;
+      if (specify_credentials) {
+        memset(&auth_id, 0, sizeof(auth_id));
+        size_t len = password.GetLength()+1;
+        char * sensitive = new char[len];
+        password.CopyTo(sensitive, true);
+        std::string::size_type pos = username.find('\\');
+        if (pos == std::string::npos) {
+          auth_id.UserLength = static_cast<unsigned long>(
+            _min(sizeof(userbuf) - 1, username.size()));
+          memcpy(userbuf, username.c_str(), auth_id.UserLength);
+          userbuf[auth_id.UserLength] = 0;
+          auth_id.DomainLength = 0;
+          domainbuf[auth_id.DomainLength] = 0;
+          auth_id.PasswordLength = static_cast<unsigned long>(
+            _min(sizeof(passbuf) - 1, password.GetLength()));
+          memcpy(passbuf, sensitive, auth_id.PasswordLength);
+          passbuf[auth_id.PasswordLength] = 0;
+        } else {
+          auth_id.UserLength = static_cast<unsigned long>(
+            _min(sizeof(userbuf) - 1, username.size() - pos - 1));
+          memcpy(userbuf, username.c_str() + pos + 1, auth_id.UserLength);
+          userbuf[auth_id.UserLength] = 0;
+          auth_id.DomainLength = static_cast<unsigned long>(
+            _min(sizeof(domainbuf) - 1, pos));
+          memcpy(domainbuf, username.c_str(), auth_id.DomainLength);
+          domainbuf[auth_id.DomainLength] = 0;
+          auth_id.PasswordLength = static_cast<unsigned long>(
+            _min(sizeof(passbuf) - 1, password.GetLength()));
+          memcpy(passbuf, sensitive, auth_id.PasswordLength);
+          passbuf[auth_id.PasswordLength] = 0;
+        }
+        memset(sensitive, 0, len);
+        delete [] sensitive;
+        auth_id.User = userbuf;
+        auth_id.Domain = domainbuf;
+        auth_id.Password = passbuf;
+        auth_id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
+        pauth_id = &auth_id;
+        LOG(LS_VERBOSE) << "Negotiate protocol: Using specified credentials";
+      } else {
+        LOG(LS_VERBOSE) << "Negotiate protocol: Using default credentials";
+      }
+
+      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);
+      if (ret != SEC_E_OK) {
+        LOG(LS_ERROR) << "AcquireCredentialsHandle error: "
+                    << ErrorName(ret, SECURITY_ERRORS);
+        return HAR_IGNORE;
+      }
+
+      //CSecBufferBundle<5, CSecBufferBase::FreeSSPI> sb_out;
+
+      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);
+      if (FAILED(ret)) {
+        LOG(LS_ERROR) << "InitializeSecurityContext returned: "
+                    << ErrorName(ret, SECURITY_ERRORS);
+        FreeCredentialsHandle(&cred);
+        return HAR_IGNORE;
+      }
+
+      assert(!context);
+      context = neg = new NegotiateAuthContext(auth_method, cred, ctx);
+      neg->specified_credentials = specify_credentials;
+      neg->steps = steps;
+    }
+
+    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(LS_VERBOSE) << "CompleteAuthToken returned: "
+                      << ErrorName(ret, SECURITY_ERRORS);
+      if (FAILED(ret)) {
+        return HAR_ERROR;
+      }
+    }
+
+    //LOG(INFO) << "$$$ NEGOTIATE took " << TimeDiff(talk_base::Time(), now) << "ms";
+
+    std::string decoded(out_buf, out_buf + out_sec.cbBuffer);
+    response = auth_method;
+    response.append(" ");
+    response.append(Base64::encode(decoded));
+    return HAR_RESPONSE;
+  }
+#endif
+#endif // WIN32
+
+  return HAR_IGNORE;
+}
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/httpcommon.h b/talk/base/httpcommon.h
new file mode 100755
index 0000000..2893933
--- /dev/null
+++ b/talk/base/httpcommon.h
@@ -0,0 +1,373 @@
+/*
+ * 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_HTTPCOMMON_H__
+#define TALK_BASE_HTTPCOMMON_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include "talk/base/basictypes.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/stream.h"
+
+namespace talk_base {
+
+class CryptString;
+class SocketAddress;
+
+//////////////////////////////////////////////////////////////////////
+// Constants
+//////////////////////////////////////////////////////////////////////
+
+enum HttpCode { 
+  HC_OK = 200,
+  HC_NON_AUTHORITATIVE = 203,
+  HC_NO_CONTENT = 204,
+  HC_PARTIAL_CONTENT = 206,
+
+  HC_MULTIPLE_CHOICES = 300,
+  HC_MOVED_PERMANENTLY = 301,
+  HC_FOUND = 302,
+  HC_SEE_OTHER = 303,
+  HC_NOT_MODIFIED = 304,
+  HC_MOVED_TEMPORARILY = 307,
+
+  HC_BAD_REQUEST = 400,
+  HC_UNAUTHORIZED = 401,
+  HC_FORBIDDEN = 403,
+  HC_NOT_FOUND = 404,
+  HC_PROXY_AUTHENTICATION_REQUIRED = 407,
+  HC_GONE = 410,
+
+  HC_INTERNAL_SERVER_ERROR = 500 
+};
+
+enum HttpVersion {
+  HVER_1_0, HVER_1_1,
+  HVER_LAST = HVER_1_1
+};
+
+enum HttpVerb {
+  HV_GET, HV_POST, HV_PUT, HV_DELETE, HV_CONNECT, HV_HEAD,
+  HV_LAST = HV_HEAD
+};
+
+enum HttpError {
+  HE_NONE,
+  HE_PROTOCOL, HE_DISCONNECTED, HE_OVERFLOW,
+  HE_SOCKET, HE_SHUTDOWN, HE_OPERATION_CANCELLED,
+  HE_AUTH,                // Proxy Authentication Required
+  HE_CERTIFICATE_EXPIRED, // During SSL negotiation
+  HE_STREAM,              // Problem reading or writing to the document
+  HE_CACHE,               // Problem reading from cache
+  HE_DEFAULT
+};
+
+enum HttpHeader {
+  HH_AGE,
+  HH_CACHE_CONTROL,
+  HH_CONNECTION,
+  HH_CONTENT_LENGTH,
+  HH_CONTENT_RANGE,
+  HH_CONTENT_TYPE,
+  HH_COOKIE,
+  HH_DATE,
+  HH_ETAG,
+  HH_EXPIRES,
+  HH_HOST,
+  HH_IF_MODIFIED_SINCE,
+  HH_IF_NONE_MATCH,
+  HH_KEEP_ALIVE,
+  HH_LAST_MODIFIED,
+  HH_LOCATION,
+  HH_PROXY_AUTHENTICATE,
+  HH_PROXY_AUTHORIZATION,
+  HH_PROXY_CONNECTION,
+  HH_RANGE,
+  HH_SET_COOKIE,
+  HH_TE,
+  HH_TRAILERS,
+  HH_TRANSFER_ENCODING,
+  HH_UPGRADE,
+  HH_USER_AGENT,
+  HH_WWW_AUTHENTICATE,
+  HH_LAST = HH_WWW_AUTHENTICATE
+};
+
+const uint16 HTTP_DEFAULT_PORT = 80;
+const uint16 HTTP_SECURE_PORT = 443;
+
+//////////////////////////////////////////////////////////////////////
+// Utility Functions
+//////////////////////////////////////////////////////////////////////
+
+inline HttpError mkerr(HttpError err, HttpError def_err = HE_DEFAULT) {
+  return (err != HE_NONE) ? err : def_err;
+}
+
+const char* ToString(HttpVersion version);
+bool FromString(HttpVersion& version, const std::string& str);
+
+const char* ToString(HttpVerb verb);
+bool FromString(HttpVerb& verb, const std::string& str);
+
+const char* ToString(HttpHeader header);
+bool FromString(HttpHeader& header, const std::string& str);
+
+inline bool HttpCodeIsInformational(uint32 code) { return ((code / 100) == 1); }
+inline bool HttpCodeIsSuccessful(uint32 code)    { return ((code / 100) == 2); }
+inline bool HttpCodeIsRedirection(uint32 code)   { return ((code / 100) == 3); }
+inline bool HttpCodeIsClientError(uint32 code)   { return ((code / 100) == 4); }
+inline bool HttpCodeIsServerError(uint32 code)   { return ((code / 100) == 5); }
+
+bool HttpCodeHasBody(uint32 code);
+bool HttpCodeIsCacheable(uint32 code);
+bool HttpHeaderIsEndToEnd(HttpHeader header);
+bool HttpHeaderIsCollapsible(HttpHeader header);
+
+struct HttpData;
+bool HttpShouldKeepAlive(const HttpData& data);
+
+typedef std::pair<std::string, std::string> HttpAttribute;
+typedef std::vector<HttpAttribute> HttpAttributeList;
+void HttpParseAttributes(const char * data, size_t len, 
+                         HttpAttributeList& attributes);
+bool HttpHasAttribute(const HttpAttributeList& attributes,
+                      const std::string& name,
+                      std::string* value);
+bool HttpHasNthAttribute(HttpAttributeList& attributes,
+                         size_t index, 
+                         std::string* name,
+                         std::string* value);
+
+// 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) {
+  return secure ? HTTP_SECURE_PORT : HTTP_DEFAULT_PORT;
+}
+
+// functional for insensitive std::string compare
+struct iless {
+  bool operator()(const std::string& lhs, const std::string& rhs) const {
+    return (::_stricmp(lhs.c_str(), rhs.c_str()) < 0);
+  }
+};
+
+//////////////////////////////////////////////////////////////////////
+// Url
+//////////////////////////////////////////////////////////////////////
+
+template<class CTYPE>
+class Url {
+public:
+  typedef typename Traits<CTYPE>::string string;
+
+  // TODO: Implement Encode/Decode
+  static int Encode(const CTYPE* source, CTYPE* destination, size_t len);
+  static int Encode(const string& source, string& destination);
+  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; }
+
+  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;
+  }
+  void set_query(const string& val) {
+    ASSERT(val.empty() || (val[0] == static_cast<CTYPE>('?')));
+    m_query = val;
+  }
+  void set_port(uint16 val) { m_port = val; }
+  void set_secure(bool val) { m_secure = val; }
+
+private:
+  string m_server, m_path, m_query;
+  uint16 m_port;
+  bool m_secure;
+};
+
+//////////////////////////////////////////////////////////////////////
+// HttpData
+//////////////////////////////////////////////////////////////////////
+
+struct HttpData {
+  typedef std::multimap<std::string, std::string, iless> HeaderMap;
+  typedef HeaderMap::const_iterator const_iterator;
+  
+  HttpVersion version;
+  scoped_ptr<StreamInterface> document;
+
+  HttpData() : version(HVER_1_1) { }
+
+  enum HeaderCombine { HC_YES, HC_NO, HC_AUTO, HC_REPLACE, HC_NEW };
+  void changeHeader(const std::string& name, const std::string& value,
+                    HeaderCombine combine);
+  inline void addHeader(const std::string& name, const std::string& value,
+                        bool append = true) {
+    changeHeader(name, value, append ? HC_AUTO : HC_NO);
+  }
+  inline void setHeader(const std::string& name, const std::string& value,
+                        bool overwrite = true) {
+    changeHeader(name, value, overwrite ? HC_REPLACE : HC_NEW);
+  }
+  void clearHeader(const std::string& name);
+
+  // 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();
+  }
+  inline const_iterator end() const {
+    return m_headers.end();
+  }
+  inline const_iterator begin(const std::string& name) const {
+    return m_headers.lower_bound(name);
+  }
+  inline const_iterator end(const std::string& name) const {
+    return m_headers.upper_bound(name);
+  }
+  
+  // Convenience methods using HttpHeader
+  inline void changeHeader(HttpHeader header, const std::string& value,
+                           HeaderCombine combine) {
+    changeHeader(ToString(header), value, combine);
+  }
+  inline void addHeader(HttpHeader header, const std::string& value,
+                        bool append = true) {
+    addHeader(ToString(header), value, append);
+  }
+  inline void setHeader(HttpHeader header, const std::string& value,
+                        bool overwrite = true) {
+    setHeader(ToString(header), value, overwrite);
+  }
+  inline void clearHeader(HttpHeader header) {
+    clearHeader(ToString(header));
+  }
+  inline bool hasHeader(HttpHeader header, std::string* value) const {
+    return hasHeader(ToString(header), value);
+  }
+  inline const_iterator begin(HttpHeader header) const {
+    return m_headers.lower_bound(ToString(header));
+  }
+  inline const_iterator end(HttpHeader header) const {
+    return m_headers.upper_bound(ToString(header));
+  }
+
+  void setContent(const std::string& content_type, StreamInterface* document);
+
+  virtual size_t formatLeader(char* buffer, size_t size) = 0;
+  virtual HttpError parseLeader(const char* line, size_t len) = 0;
+  
+protected:  
+  virtual ~HttpData() { }
+  void clear(bool release_document);
+
+private:
+  HeaderMap m_headers;
+};
+
+struct HttpRequestData : public HttpData {
+  HttpVerb verb;
+  std::string path;
+
+  HttpRequestData() : verb(HV_GET) { }
+
+  void clear(bool release_document);
+
+  virtual size_t formatLeader(char* buffer, size_t size);
+  virtual HttpError parseLeader(const char* line, size_t len);
+};
+
+struct HttpResponseData : public HttpData {
+  uint32 scode;
+  std::string message;
+
+  HttpResponseData() : scode(HC_INTERNAL_SERVER_ERROR) { }
+  void clear(bool release_document);
+
+  // Convenience methods
+  void set_success(uint32 scode = HC_OK);
+  void set_success(const std::string& content_type, StreamInterface* document,
+                   uint32 scode = HC_OK);
+  void set_redirect(const std::string& location,
+                    uint32 scode = HC_MOVED_TEMPORARILY);
+  void set_error(uint32 scode);
+
+  virtual size_t formatLeader(char* buffer, size_t size);
+  virtual HttpError parseLeader(const char* line, size_t len);
+};
+
+//////////////////////////////////////////////////////////////////////
+// Http Authentication
+//////////////////////////////////////////////////////////////////////
+
+struct HttpAuthContext {
+  std::string auth_method;
+  HttpAuthContext(const std::string& auth) : auth_method(auth) { }
+  virtual ~HttpAuthContext() { }
+};
+
+enum HttpAuthResult { HAR_RESPONSE, HAR_IGNORE, HAR_CREDENTIALS, HAR_ERROR };
+
+// 'context' is used by this function to record information between calls.
+// Start by passing a null pointer, then pass the same pointer each additional
+// call.  When the authentication attempt is finished, delete the context.
+HttpAuthResult HttpAuthenticate(
+  const char * challenge, size_t len,
+  const SocketAddress& server,
+  const std::string& method, const std::string& uri,
+  const std::string& username, const CryptString& password,
+  HttpAuthContext *& context, std::string& response, std::string& auth_method);
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_HTTPCOMMON_H__
diff --git a/talk/base/httpserver.cc b/talk/base/httpserver.cc
new file mode 100755
index 0000000..9c27b5c
--- /dev/null
+++ b/talk/base/httpserver.cc
@@ -0,0 +1,261 @@
+/*
+ * 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
new file mode 100755
index 0000000..a09218c
--- /dev/null
+++ b/talk/base/httpserver.h
@@ -0,0 +1,143 @@
+/*
+ * 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
new file mode 100755
index 0000000..8d5ce49
--- /dev/null
+++ b/talk/base/linked_ptr.h
@@ -0,0 +1,115 @@
+/*
+ * linked_ptr - simple reference linked pointer
+ * (like reference counting, just using a linked list of the references
+ * instead of their count.)
+ *
+ * The implementation stores three pointers for every linked_ptr, but
+ * does not allocate anything on the free store.
+ */
+
+#ifndef TALK_BASE_LINKED_PTR_H__
+#define TALK_BASE_LINKED_PTR_H__
+
+namespace talk_base {
+
+/* For ANSI-challenged compilers, you may want to #define
+ * NO_MEMBER_TEMPLATES, explicit or mutable */
+#define NO_MEMBER_TEMPLATES
+
+template <class X> class linked_ptr
+{
+public:
+
+#ifndef NO_MEMBER_TEMPLATES
+#   define TEMPLATE_FUNCTION template <class Y>
+    TEMPLATE_FUNCTION friend class linked_ptr<Y>;
+#else
+#   define TEMPLATE_FUNCTION
+    typedef X Y;
+#endif
+
+    typedef X element_type;
+
+    explicit linked_ptr(X* p = 0) throw()
+        : itsPtr(p) {itsPrev = itsNext = this;}
+    ~linked_ptr()
+        {release();}
+    linked_ptr(const linked_ptr& r) throw()
+        {acquire(r);}
+    linked_ptr& operator=(const linked_ptr& r)
+    {
+        if (this != &r) {
+            release();
+            acquire(r);
+        }
+        return *this;
+    }
+
+#ifndef NO_MEMBER_TEMPLATES
+    template <class Y> friend class linked_ptr<Y>;
+    template <class Y> linked_ptr(const linked_ptr<Y>& r) throw()
+        {acquire(r);}
+    template <class Y> linked_ptr& operator=(const linked_ptr<Y>& r)
+    {
+        if (this != &r) {
+            release();
+            acquire(r);
+        }
+        return *this;
+    }
+#endif // NO_MEMBER_TEMPLATES
+
+    X& operator*()  const throw()   {return *itsPtr;}
+    X* operator->() const throw()   {return itsPtr;}
+    X* get()        const throw()   {return itsPtr;}
+    bool unique()   const throw()   {return itsPrev ? itsPrev==this : true;}
+
+private:
+    X*                          itsPtr;
+    mutable const linked_ptr*   itsPrev;
+    mutable const linked_ptr*   itsNext;
+
+    void acquire(const linked_ptr& r) throw()
+    { // insert this to the list
+        itsPtr = r.itsPtr;
+        itsNext = r.itsNext;
+        itsNext->itsPrev = this;
+        itsPrev = &r;
+#ifndef mutable
+        r.itsNext = this;
+#else // for ANSI-challenged compilers
+        (const_cast<linked_ptr<X>*>(&r))->itsNext = this;
+#endif
+    }
+
+#ifndef NO_MEMBER_TEMPLATES
+    template <class Y> void acquire(const linked_ptr<Y>& r) throw()
+    { // insert this to the list
+        itsPtr = r.itsPtr;
+        itsNext = r.itsNext;
+        itsNext->itsPrev = this;
+        itsPrev = &r;
+#ifndef mutable
+        r.itsNext = this;
+#else // for ANSI-challenged compilers
+        (const_cast<linked_ptr<X>*>(&r))->itsNext = this;
+#endif
+    }
+#endif // NO_MEMBER_TEMPLATES
+
+    void release()
+    { // erase this from the list, delete if unique
+        if (unique()) delete itsPtr;
+        else {
+            itsPrev->itsNext = itsNext;
+            itsNext->itsPrev = itsPrev;
+            itsPrev = itsNext = 0;
+        }
+        itsPtr = 0;
+    }
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_LINKED_PTR_H__
+
diff --git a/talk/base/logging.cc b/talk/base/logging.cc
new file mode 100755
index 0000000..2a7fbe3
--- /dev/null
+++ b/talk/base/logging.cc
@@ -0,0 +1,349 @@
+/*
+ * 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 WIN32
+#include <windows.h>
+#define snprintf _snprintf
+#undef ERROR  // wingdi.h
+#endif
+
+#include <iostream>
+#include <iomanip>
+
+#include "talk/base/logging.h"
+#include "talk/base/stream.h"
+#include "talk/base/stringencode.h"
+#include "talk/base/time.h"
+
+namespace talk_base {
+
+/////////////////////////////////////////////////////////////////////////////
+// Constant Labels
+/////////////////////////////////////////////////////////////////////////////
+
+const char * FindLabel(int value, const talk_base::ConstantLabel entries[]) {
+  for (int i=0; entries[i].label; ++i) {
+    if (value == entries[i].value) {
+      return entries[i].label;
+    }
+  }
+  return 0;
+}
+
+std::string ErrorName(int err, const talk_base::ConstantLabel * err_table) {
+	const char * value = 0;
+	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);  
+  return buffer;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// LogMessage
+/////////////////////////////////////////////////////////////////////////////
+
+#if _DEBUG
+static const int LOG_DEFAULT = LS_INFO;
+#else  // !_DEBUG
+static const int LOG_DEFAULT = LogMessage::NO_LOGGING;
+#endif  // !_DEBUG
+
+// 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
+// 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_;
+
+// Boolean options default to false (0)
+bool LogMessage::thread_, LogMessage::timestamp_;
+
+// Program start time
+uint32 LogMessage::start_ = StartTime();
+
+// if we're in diagnostic mode, we'll be explicitly set that way.  default to 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) {
+  if (timestamp_) {
+    uint32 time = TimeDiff(Time(), start_);
+    print_stream_ << "[" << std::setfill('0') << std::setw(3) << (time / 1000)
+                  << ":" << std::setw(3) << (time % 1000) << std::setfill(' ')
+                  << "] ";
+  }
+
+  if (thread_) {
+#ifdef WIN32
+    DWORD id = GetCurrentThreadId();
+    print_stream_ << "[" << std::hex << id << std::dec << "] ";
+#endif  // WIN32
+  }
+
+  if (severity_ >= ctx_sev_) {
+    print_stream_ << Describe(sev) << "(" << DescribeFile(file)
+                  << ":" << line << "): ";
+  }
+
+  if (err_ctx != ERRCTX_NONE) {
+    std::ostringstream tmp;
+    tmp << "[0x" << std::setfill('0') << std::hex << std::setw(8) << err << "]";
+    switch (err_ctx) {
+      case ERRCTX_ERRNO:
+        tmp << " " << strerror(err);
+        break;
+  #ifdef WIN32
+      case ERRCTX_HRESULT: {
+        char msgbuf[256];
+        DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM;
+        HMODULE hmod = GetModuleHandleA(module);
+        if (hmod)
+          flags |= FORMAT_MESSAGE_FROM_HMODULE;
+        if (DWORD len = FormatMessageA(
+            flags, hmod, err,
+            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+            msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), NULL)) {
+          while ((len > 0) &&
+              isspace(static_cast<unsigned char>(msgbuf[len-1]))) {
+            msgbuf[--len] = 0;
+          }
+          tmp << " " << msgbuf;
+        }
+        break; }
+  #endif  // WIN32
+      default:
+        break;
+    }
+    extra_ = tmp.str();
+  }
+}
+
+LogMessage::~LogMessage() {
+  if (!extra_.empty())
+    print_stream_ << " : " << extra_;
+  print_stream_ << std::endl;
+  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();
+    }
+  }
+
+  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);
+  }
+}
+
+void LogMessage::LogContext(int min_sev) {
+  ctx_sev_ = min_sev;
+}
+
+void LogMessage::LogThreads(bool on) {
+  thread_ = on;
+}
+
+void LogMessage::LogTimestamps(bool on) {
+  timestamp_ = on;
+}
+
+void LogMessage::ResetTimestamps() {
+  start_ = Time();
+}
+
+void LogMessage::LogToDebug(int min_sev) {
+  dbg_sev_ = min_sev;
+  min_sev_ = _min(dbg_sev_, stream_sev_);
+}
+
+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_);
+}
+
+const char* LogMessage::Describe(LoggingSeverity sev) {
+  switch (sev) {
+  case LS_SENSITIVE: return "Sensitive";
+  case LS_VERBOSE:   return "Verbose";
+  case LS_INFO:      return "Info";
+  case LS_WARNING:   return "Warning";
+  case LS_ERROR:     return "Error";
+  default:           return "<unknown>";
+  }
+}
+
+const char* LogMessage::DescribeFile(const char* file) {
+  const char* end1 = ::strrchr(file, '/');
+  const char* end2 = ::strrchr(file, '\\');
+  if (!end1 && !end2)
+    return file;
+  else
+    return (end1 > end2) ? end1 + 1 : end2 + 1;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Logging Helpers
+//////////////////////////////////////////////////////////////////////
+
+void LogMultiline(LoggingSeverity level, const char* label, bool input,
+                  const char * data, size_t len, bool hex_mode,
+                  LogMultilineState* state) {
+  if (!LOG_CHECK_LEVEL_V(level))
+    return;
+
+  const char * direction = (input ? " << " : " >> ");
+  if (hex_mode) {
+    const size_t LINE_SIZE = 24;
+    char hex_line[LINE_SIZE * 9 / 4 + 2], asc_line[LINE_SIZE + 1];
+    while (len > 0) {
+      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] : '.';
+        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 
+                   << asc_line << " " << hex_line << " ";
+      data += line_len;
+      len -= line_len;
+    }
+    return;
+  }
+
+  size_t consecutive_unprintable = state ? state->unprintable_count_ : 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);
+    } else {
+      line_end_length = 1;
+      substr = str.substr(0, pos);
+      str = str.substr(pos + 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;
+      }
+    }
+    // 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 {
+      continue;
+    }
+
+    // Filter out any private data
+    std::string::size_type pos_private = substr.find("Email");
+    if (pos_private == std::string::npos) {
+      pos_private = substr.find("Passwd");
+    }
+    if (pos_private == std::string::npos) {
+      LOG_V(level) << label << direction << substr;
+    } else {
+      LOG_V(level) << label << direction << "## omitted for privacy ##";
+    }
+  }
+
+  if (state) {
+    state->unprintable_count_ = consecutive_unprintable;
+  }
+}
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/logging.h b/talk/base/logging.h
new file mode 100755
index 0000000..a4686b7
--- /dev/null
+++ b/talk/base/logging.h
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+//   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
+// 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__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sstream>
+#include "talk/base/basictypes.h"
+
+namespace talk_base {
+
+class StreamInterface;
+
+///////////////////////////////////////////////////////////////////////////////
+// ConstantLabel can be used to easily generate string names from constant
+// values.  This can be useful for logging descriptive names of error messages.
+// Usage:
+//   const ConstantLabel LIBRARY_ERRORS[] = {
+//     KLABEL(SOME_ERROR),
+//     KLABEL(SOME_OTHER_ERROR),
+//     ...
+//     LASTLABEL
+//   }
+//
+//   int err = LibraryFunc();
+//   LOG(LS_ERROR) << "LibraryFunc returned: "
+//                 << ErrorName(err, LIBRARY_ERRORS);
+
+struct ConstantLabel { int value; const char * label; };
+#define KLABEL(x) { x, #x }
+#define TLABEL(x,y) { x, y }
+#define LASTLABEL { 0, 0 }
+
+const char * FindLabel(int value, const ConstantLabel entries[]);
+std::string ErrorName(int err, const ConstantLabel* err_table);
+
+//////////////////////////////////////////////////////////////////////
+
+// Note that the non-standard LoggingSeverity aliases exist because they are
+// still in broad use.  The meanings of the levels are:
+//  LS_SENSITIVE: Information which should only be logged with the consent
+//   of the user, due to privacy concerns.
+//  LS_VERBOSE: This level is for data which we do not want to appear in the
+//   normal debug log, but should appear in diagnostic logs.
+//  LS_INFO: Chatty level used in debugging for all sorts of things, the default
+//   in debug builds.
+//  LS_WARNING: Something that may warrant investigation.
+//  LS_ERROR: Something that should not have occurred.
+enum LoggingSeverity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR,
+                       INFO = LS_INFO,
+                       WARNING = LS_WARNING,
+                       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 };
+
+class LogMessage {
+ public:
+  LogMessage(const char* file, int line, LoggingSeverity sev,
+             LogErrorContext err_ctx = ERRCTX_NONE, int err = 0,
+             const char* module = NULL);
+  ~LogMessage();
+
+  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);
+  //  LogThreads: Display the thread identifier of the current thread
+  static void LogThreads(bool on = true);
+  //  LogTimestamps: Display the elapsed time of the program
+  static void LogTimestamps(bool on = true);
+
+  // Timestamps begin with program execution, but can be reset with this
+  // function for measuring the duration of an activity, or to synchronize
+  // timestamps between multiple instances.
+  static void ResetTimestamps();
+
+  // These are the available logging channels
+  //  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.
+  static void LogToStream(StreamInterface* stream, int min_sev);
+  static int GetLogToStream() { return stream_sev_; }
+
+  // Testing against MinLogSeverity allows code to avoid potentially expensive
+  // logging operations by pre-checking the logging level.
+  static int GetMinLogSeverity() { return min_sev_; }
+
+  static void SetDiagnosticMode(bool f) { is_diagnostic_mode_ = f; }
+  static bool IsDiagnosticMode() { return is_diagnostic_mode_; }
+
+ private:
+  // These assist in formatting some parts of the debug output.
+  static const char* Describe(LoggingSeverity sev);
+  static const char* DescribeFile(const char* file);
+
+  // The ostream that buffers the formatted message before output
+  std::ostringstream print_stream_;
+
+  // The severity level of this message
+  LoggingSeverity severity_;
+
+  // String data generated in the constructor, that should be appended to
+  // the message before output.
+  std::string extra_;
+
+  // dbg_sev_ and stream_sev_ are 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_;
+
+  // The output stream, if any
+  static StreamInterface * stream_;
+
+  // Flags for formatting options
+  static bool thread_, timestamp_;
+
+  // The timestamp at which logging started.
+  static uint32 start_;
+
+  // are we in diagnostic mode (as defined by the app)?
+  static bool is_diagnostic_mode_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(LogMessage);
+};
+
+//////////////////////////////////////////////////////////////////////
+// Logging Helpers
+//////////////////////////////////////////////////////////////////////
+
+class LogMultilineState {
+public:
+  size_t unprintable_count_;
+  LogMultilineState() : unprintable_count_(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,
+                  LogMultilineState* state);
+
+//////////////////////////////////////////////////////////////////////
+// Macros which automatically disable logging when LOGGING == 0
+//////////////////////////////////////////////////////////////////////
+
+// If LOGGING is not explicitly defined, default to enabled in debug mode
+#if !defined(LOGGING)
+#if defined(_DEBUG) && !defined(NDEBUG)
+#define LOGGING 1
+#else
+#define LOGGING 0
+#endif
+#endif  // !defined(LOGGING)
+
+#ifndef LOG
+#if LOGGING
+
+#define LOG(sev) \
+  if (talk_base::LogMessage::Loggable(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)) \
+    talk_base::LogMessage(__FILE__, __LINE__, sev).stream()
+
+// The _F version prefixes the message with the current function name.
+#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
+
+// 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) \
+  talk_base::LogCheckLevel(sev)
+inline bool LogCheckLevel(LoggingSeverity sev) {
+  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)) \
+    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.
+
+#else  // !LOGGING
+
+// Hopefully, the compiler will optimize away some of this code.
+// Note: syntax of "1 ? (void)0 : LogMessage" was causing errors in g++,
+//   converted to "while (false)"
+#define LOG(sev) \
+  while (false)talk_base:: LogMessage(NULL, 0, talk_base::sev).stream()
+#define LOG_V(sev) \
+  while (false) talk_base::LogMessage(NULL, 0, sev).stream()
+#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
+#define LOG_CHECK_LEVEL(sev) \
+  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
+
+#endif  // !LOGGING
+#endif  // LOG
+
+//////////////////////////////////////////////////////////////////////
+
+} // talk_base
+
+#endif  // TALK_BASE_LOGGING_H__
diff --git a/talk/base/md5.h b/talk/base/md5.h
new file mode 100755
index 0000000..ec458d1
--- /dev/null
+++ b/talk/base/md5.h
@@ -0,0 +1,45 @@
+/*
+ * This is the header file for the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ */
+
+#ifndef TALK_BASE_MD5_H__
+#define TALK_BASE_MD5_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef long unsigned int uint32;
+typedef struct MD5Context MD5_CTX;
+
+#define md5byte unsigned char
+
+struct MD5Context {
+  uint32 buf[4];
+  uint32 bits[2];
+  uint32 in[16];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+void MD5Transform(uint32 buf[4], uint32 const in[16]);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // TALK_BASE_MD5_H__
diff --git a/talk/base/md5c.c b/talk/base/md5c.c
new file mode 100755
index 0000000..eb2c034
--- /dev/null
+++ b/talk/base/md5c.c
@@ -0,0 +1,256 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+#include <string.h>	/* for memcpy() */
+#include "md5.h"
+
+#ifndef HIGHFIRST
+#define byteReverse(buf, len)	/* Nothing */
+#else
+void byteReverse(unsigned char *buf, unsigned longs);
+
+#ifndef ASM_MD5
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+void byteReverse(unsigned char *buf, unsigned longs)
+{
+	uint32 t;
+	do {
+		t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
+		            ((unsigned)buf[1]<<8 | buf[0]);
+		*(uint32 *)buf = t;
+		buf += 4;
+	} while (--longs);
+}
+#endif
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(struct MD5Context *ctx)
+{
+	ctx->buf[0] = 0x67452301;
+	ctx->buf[1] = 0xefcdab89;
+	ctx->buf[2] = 0x98badcfe;
+	ctx->buf[3] = 0x10325476;
+
+	ctx->bits[0] = 0;
+	ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+	uint32 t;
+
+	/* Update bitcount */
+
+	t = ctx->bits[0];
+	if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
+		ctx->bits[1]++;	/* Carry from low to high */
+	ctx->bits[1] += len >> 29;
+
+	t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+	/* Handle any leading odd-sized chunks */
+
+	if ( t ) {
+		unsigned char *p = (unsigned char *)ctx->in + t;
+
+		t = 64-t;
+		if (len < t) {
+			memcpy(p, buf, len);
+			return;
+		}
+		memcpy(p, buf, t);
+		byteReverse(ctx->in, 16);
+		MD5Transform(ctx->buf, (uint32 *)ctx->in);
+		buf += t;
+		len -= t;
+	}
+
+	/* Process data in 64-byte chunks */
+
+	while (len >= 64) {
+		memcpy(ctx->in, buf, 64);
+		byteReverse(ctx->in, 16);
+		MD5Transform(ctx->buf, (uint32 *)ctx->in);
+		buf += 64;
+		len -= 64;
+	}
+
+	/* Handle any remaining bytes of data. */
+
+	memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+	unsigned count;
+	unsigned char *p;
+
+	/* Compute number of bytes mod 64 */
+	count = (ctx->bits[0] >> 3) & 0x3F;
+
+	/* Set the first char of padding to 0x80.  This is safe since there is
+	   always at least one byte free */
+	p = (unsigned char*)(ctx->in) + count;
+	*p++ = 0x80;
+
+	/* Bytes of padding needed to make 64 bytes */
+	count = 64 - 1 - count;
+
+	/* Pad out to 56 mod 64 */
+	if (count < 8) {
+		/* Two lots of padding:  Pad the first block to 64 bytes */
+		memset(p, 0, count);
+		byteReverse(ctx->in, 16);
+		MD5Transform(ctx->buf, (uint32 *)ctx->in);
+
+		/* Now fill the next block with 56 bytes */
+		memset(ctx->in, 0, 56);
+	} else {
+		/* Pad block to 56 bytes */
+		memset(p, 0, count-8);
+	}
+	byteReverse(ctx->in, 14);
+
+	/* Append length in bits and transform */
+	((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
+	((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
+
+	MD5Transform(ctx->buf, (uint32 *)ctx->in);
+	byteReverse((unsigned char *)ctx->buf, 4);
+	memcpy(digest, ctx->buf, 16);
+	memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform(uint32 buf[4], uint32 const in[16])
+{
+	register uint32 a, b, c, d;
+
+	a = buf[0];
+	b = buf[1];
+	c = buf[2];
+	d = buf[3];
+
+	MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
+	MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+	MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+	MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+	MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
+	MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+	MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+	MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+	MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
+	MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+	MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+	MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+	MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
+	MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+	MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+	MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+	MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
+	MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
+	MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+	MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+	MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
+	MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
+	MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+	MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+	MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
+	MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
+	MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+	MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+	MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
+	MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
+	MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+	MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+	MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
+	MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+	MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+	MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+	MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
+	MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+	MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+	MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+	MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
+	MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+	MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+	MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+	MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
+	MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+	MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+	MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+	MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
+	MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+	MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+	MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+	MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
+	MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+	MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+	MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+	MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
+	MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+	MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+	MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+	MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
+	MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+	MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+	MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+}
+#endif
diff --git a/talk/base/messagequeue.cc b/talk/base/messagequeue.cc
new file mode 100755
index 0000000..64f57cc
--- /dev/null
+++ b/talk/base/messagequeue.cc
@@ -0,0 +1,360 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#ifdef POSIX
+extern "C" {
+#include <sys/time.h>
+}
+#endif
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/messagequeue.h"
+#include "talk/base/physicalsocketserver.h"
+
+
+namespace talk_base {
+
+const uint32 kMaxMsgLatency = 150;  // 150 ms
+
+//------------------------------------------------------------------
+// MessageQueueManager
+
+MessageQueueManager* MessageQueueManager::instance_;
+
+MessageQueueManager* MessageQueueManager::Instance() {
+  // Note: This is not thread safe, but it is first called before threads are
+  // spawned.
+  if (!instance_)
+    instance_ = new MessageQueueManager;
+  return instance_;
+}
+
+MessageQueueManager::MessageQueueManager() {
+}
+
+MessageQueueManager::~MessageQueueManager() {
+}
+
+void MessageQueueManager::Add(MessageQueue *message_queue) {
+  // MessageQueueManager methods should be non-reentrant, so we
+  // ASSERT that is the case.
+  ASSERT(!crit_.CurrentThreadIsOwner());
+  CritScope cs(&crit_);
+  message_queues_.push_back(message_queue);
+}
+
+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);
+}
+
+void MessageQueueManager::Clear(MessageHandler *handler) {
+  ASSERT(!crit_.CurrentThreadIsOwner());  // See note above.
+  CritScope cs(&crit_);
+  std::vector<MessageQueue *>::iterator iter;
+  for (iter = message_queues_.begin(); iter != message_queues_.end(); iter++)
+    (*iter)->Clear(handler);
+}
+
+//------------------------------------------------------------------
+// MessageQueue
+
+MessageQueue::MessageQueue(SocketServer* ss)
+    : ss_(ss), new_ss(false), fStop_(false), fPeekKeep_(false), active_(false) {
+  if (!ss_) {
+    new_ss = true;
+    ss_ = new PhysicalSocketServer();
+  }
+}
+
+MessageQueue::~MessageQueue() {
+  if (active_) {
+    MessageQueueManager::Instance()->Remove(this);
+    Clear(NULL);
+  }
+  if (new_ss)
+    delete ss_;
+}
+
+void MessageQueue::set_socketserver(SocketServer* ss) {
+  if (new_ss)
+    delete ss_;
+  new_ss = false;
+  ss_ = ss;
+}
+
+void MessageQueue::Stop() {
+  fStop_ = true;
+  ss_->WakeUp();
+}
+
+bool MessageQueue::IsStopping() {
+  return fStop_;
+}
+
+void MessageQueue::Restart() {
+  fStop_ = false;
+}
+
+bool MessageQueue::Peek(Message *pmsg, int cmsWait) {
+  if (fPeekKeep_) {
+    *pmsg = msgPeek_;
+    return true;
+  }
+  if (!Get(pmsg, cmsWait))
+    return false;
+  msgPeek_ = *pmsg;
+  fPeekKeep_ = true;
+  return true;
+}
+
+bool MessageQueue::Get(Message *pmsg, int cmsWait) {
+  // Return and clear peek if present
+  // Always return the peek if it exists so there is Peek/Get symmetry
+
+  if (fPeekKeep_) {
+    *pmsg = msgPeek_;
+    fPeekKeep_ = false;
+    return true;
+  }
+
+  // Get w/wait + timer scan / dispatch + socket / event multiplexer dispatch
+
+  int cmsTotal = cmsWait;
+  int cmsElapsed = 0;
+  uint32 msStart = Time();
+  uint32 msCurrent = msStart;
+  while (true) {
+    // Check for sent messages
+
+    ReceiveSends();
+
+    // Check queues
+
+    int cmsDelayNext = kForever;
+    {
+      CritScope cs(&crit_);
+
+      // Check for delayed messages that have been triggered
+      // Calc the next trigger too
+
+      while (!dmsgq_.empty()) {
+        if (msCurrent < dmsgq_.top().msTrigger_) {
+          cmsDelayNext = dmsgq_.top().msTrigger_ - msCurrent;
+          break;
+        }
+        msgq_.push(dmsgq_.top().msg_);
+        dmsgq_.pop();
+      }
+
+      // Check for posted events
+
+      while (!msgq_.empty()) {
+        *pmsg = msgq_.front();
+        if (pmsg->ts_sensitive) {
+          long delay = TimeDiff(msCurrent, pmsg->ts_sensitive);
+          if (delay > 0) {
+            LOG_F(LS_WARNING) << "id: " << pmsg->message_id << "  delay: "
+                              << (delay + kMaxMsgLatency) << "ms";
+          }
+        }
+        msgq_.pop();
+        if (MQID_DISPOSE == pmsg->message_id) {
+          ASSERT(NULL == pmsg->phandler);
+          delete pmsg->pdata;
+          continue;
+        }
+        return true;
+      }
+    }
+
+    if (fStop_)
+      break;
+
+    // Which is shorter, the delay wait or the asked wait?
+
+    int cmsNext;
+    if (cmsWait == kForever) {
+      cmsNext = cmsDelayNext;
+    } else {
+      cmsNext = cmsTotal - cmsElapsed;
+      if (cmsNext < 0)
+        cmsNext = 0;
+      if ((cmsDelayNext != kForever) && (cmsDelayNext < cmsNext))
+        cmsNext = cmsDelayNext;
+    }
+
+    // Wait and multiplex in the meantime
+    ss_->Wait(cmsNext, true);
+
+    // If the specified timeout expired, return
+
+    msCurrent = Time();
+    cmsElapsed = msCurrent - msStart;
+    if (cmsWait != kForever) {
+      if (cmsElapsed >= cmsWait)
+        return false;
+    }
+  }
+  return false;
+}
+
+void MessageQueue::ReceiveSends() {
+}
+
+void MessageQueue::Post(MessageHandler *phandler, uint32 id,
+    MessageData *pdata, bool time_sensitive) {
+  if (fStop_)
+    return;
+
+  // Keep thread safe
+  // Add the message to the end of the queue
+  // Signal for the multiplexer to return
+
+  CritScope cs(&crit_);
+  EnsureActive();
+  Message msg;
+  msg.phandler = phandler;
+  msg.message_id = id;
+  msg.pdata = pdata;
+  if (time_sensitive) {
+    msg.ts_sensitive = Time() + kMaxMsgLatency;
+  }
+  msgq_.push(msg);
+  ss_->WakeUp();
+}
+
+void MessageQueue::PostDelayed(int cmsDelay, MessageHandler *phandler,
+    uint32 id, MessageData *pdata) {
+  if (fStop_)
+    return;
+
+  // Keep thread safe
+  // Add to the priority queue. Gets sorted soonest first.
+  // Signal for the multiplexer to return.
+
+  CritScope cs(&crit_);
+  EnsureActive();
+  Message msg;
+  msg.phandler = phandler;
+  msg.message_id = id;
+  msg.pdata = pdata;
+  dmsgq_.push(DelayedMessage(cmsDelay, &msg));
+  ss_->WakeUp();
+}
+
+int MessageQueue::GetDelay() {
+  CritScope cs(&crit_);
+
+  if (!msgq_.empty())
+    return 0;
+
+  if (!dmsgq_.empty()) {
+    int delay = dmsgq_.top().msTrigger_ - Time();
+    if (delay < 0)
+      delay = 0;
+    return delay;
+  }
+
+  return kForever;
+}
+
+void MessageQueue::Clear(MessageHandler *phandler, uint32 id) {
+  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;
+      }
+    }
+  }
+
+  // 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;
+      } else {
+        msgq_.push(msg);
+      }
+    }
+  }
+
+  // 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;
+      } else {
+        dmsgs.push(dmsg);
+      }
+    }
+  }
+  while (!dmsgs.empty()) {
+    dmsgq_.push(dmsgs.front());
+    dmsgs.pop();
+  }
+}
+
+void MessageQueue::Dispatch(Message *pmsg) {
+  pmsg->phandler->OnMessage(pmsg);
+}
+
+void MessageQueue::EnsureActive() {
+  ASSERT(crit_.CurrentThreadIsOwner());
+  if (!active_) {
+    active_ = true;
+    MessageQueueManager::Instance()->Add(this);
+  }
+}
+
+} // namespace talk_base
diff --git a/talk/base/messagequeue.h b/talk/base/messagequeue.h
new file mode 100755
index 0000000..ce79700
--- /dev/null
+++ b/talk/base/messagequeue.h
@@ -0,0 +1,207 @@
+/*
+ * 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_MESSAGEQUEUE_H__
+#define TALK_BASE_MESSAGEQUEUE_H__
+
+#include <vector>
+#include <queue>
+#include <algorithm>
+#include "talk/base/basictypes.h"
+#include "talk/base/criticalsection.h"
+#include "talk/base/socketserver.h"
+#include "talk/base/time.h"
+
+namespace talk_base {
+
+struct Message;
+class MessageQueue;
+class MessageHandler;
+
+// MessageQueueManager does cleanup of of message queues
+
+class MessageQueueManager {
+public:
+  static MessageQueueManager* Instance();
+
+  void Add(MessageQueue *message_queue);
+  void Remove(MessageQueue *message_queue);
+  void Clear(MessageHandler *handler);
+
+private:
+  MessageQueueManager();
+  ~MessageQueueManager();
+
+  static MessageQueueManager* instance_;
+  // This list contains 'active' MessageQueues.
+  std::vector<MessageQueue *> message_queues_;
+  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:
+  MessageData() {}
+  virtual ~MessageData() {}
+};
+
+template <class T>
+class TypedMessageData : public MessageData {
+public:
+  TypedMessageData(const T& data) : data_(data) { }
+  const T& data() const { return data_; }
+  T& data() { return data_; }
+private:
+  T data_;
+};
+
+template<class T>
+inline MessageData* WrapMessageData(const T& data) {
+  return new TypedMessageData<T>(data);
+}
+
+template<class T>
+inline const T& UseMessageData(MessageData* data) {
+  return static_cast< TypedMessageData<T>* >(data)->data();
+}
+
+template<class T>
+class DisposeData : public MessageData {
+public:
+  DisposeData(T* data) : data_(data) { }
+  virtual ~DisposeData() { delete data_; }
+private:
+  T* data_;
+};
+
+const uint32 MQID_ANY = static_cast<uint32>(-1);
+const uint32 MQID_DISPOSE = static_cast<uint32>(-2);
+
+// No destructor
+
+struct Message {
+  Message() {
+    memset(this, 0, sizeof(*this));
+  }
+  MessageHandler *phandler;
+  uint32 message_id;
+  MessageData *pdata;
+  uint32 ts_sensitive;
+};
+
+// DelayedMessage goes into a priority queue, sorted by trigger time
+
+class DelayedMessage {
+public:
+  DelayedMessage(int cmsDelay, Message *pmsg) {
+    cmsDelay_ = cmsDelay;
+    msTrigger_ = GetMillisecondCount() + cmsDelay;
+    msg_ = *pmsg;
+  }
+
+  bool operator< (const DelayedMessage& dmsg) const {
+    return dmsg.msTrigger_ < msTrigger_;
+  }
+
+  int cmsDelay_; // for debugging
+  uint32 msTrigger_;
+  Message msg_;
+};
+
+class MessageQueue {
+public:
+  MessageQueue(SocketServer* ss = 0);
+  virtual ~MessageQueue();
+
+  SocketServer* socketserver() { return ss_; }
+  void set_socketserver(SocketServer* ss);
+
+  // Note: The behavior of MessageQueue has changed.  When a MQ is stopped,
+  // futher Posts and Sends will fail.  However, any pending Sends and *ready*
+  // Posts (as opposed to unexpired delayed Posts) will be delivered before
+  // 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 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 Peek(Message *pmsg, int cmsWait = 0);
+  virtual void Post(MessageHandler *phandler, uint32 id = 0,
+      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);
+  virtual void Dispatch(Message *pmsg);
+  virtual void ReceiveSends();
+  virtual int GetDelay();
+
+  // 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));
+    }
+  }
+
+protected:
+  void EnsureActive();
+
+  SocketServer* ss_;
+  bool new_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_;
+  CriticalSection crit_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_MESSAGEQUEUE_H__
diff --git a/talk/base/nat_unittest.cc b/talk/base/nat_unittest.cc
new file mode 100755
index 0000000..23c122b
--- /dev/null
+++ b/talk/base/nat_unittest.cc
@@ -0,0 +1,223 @@
+#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
new file mode 100755
index 0000000..336cf64
--- /dev/null
+++ b/talk/base/natserver.cc
@@ -0,0 +1,210 @@
+/*
+ * 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
new file mode 100755
index 0000000..61c1dd3
--- /dev/null
+++ b/talk/base/natserver.h
@@ -0,0 +1,114 @@
+/*
+ * 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
new file mode 100755
index 0000000..a748108
--- /dev/null
+++ b/talk/base/natserver_main.cc
@@ -0,0 +1,57 @@
+/*
+ * 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
new file mode 100755
index 0000000..2b0309e
--- /dev/null
+++ b/talk/base/natsocketfactory.cc
@@ -0,0 +1,228 @@
+/*
+ * 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/natsocketfactory.h b/talk/base/natsocketfactory.h
new file mode 100755
index 0000000..a689158
--- /dev/null
+++ b/talk/base/natsocketfactory.h
@@ -0,0 +1,51 @@
+/*
+ * 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_NATSOCKETFACTORY_H__
+#define TALK_BASE_NATSOCKETFACTORY_H__
+
+#include "talk/base/socketfactory.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_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_NATSOCKETFACTORY_H__
diff --git a/talk/base/nattypes.cc b/talk/base/nattypes.cc
new file mode 100755
index 0000000..290c3ad
--- /dev/null
+++ b/talk/base/nattypes.cc
@@ -0,0 +1,72 @@
+/*
+ * 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
new file mode 100755
index 0000000..aad11bb
--- /dev/null
+++ b/talk/base/nattypes.h
@@ -0,0 +1,62 @@
+/*
+ * 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/network.cc b/talk/base/network.cc
new file mode 100755
index 0000000..d5a7d24
--- /dev/null
+++ b/talk/base/network.cc
@@ -0,0 +1,381 @@
+/*
+ * 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 <cfloat>
+#include <cmath>
+#include <sstream>
+
+#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
+
+#ifdef WIN32
+#include "talk/base/win32.h"
+#include <Iphlpapi.h>
+#endif
+
+#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/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 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;
+
+void BuildMap(const StrMap& map, std::string& str) {
+  str.append("{");
+  bool first = true;
+  for (StrMap::const_iterator i = map.begin(); i != map.end(); ++i) {
+    if (!first) str.append(",");
+    str.append(i->first);
+    str.append("=");
+    str.append(i->second);
+    first = false;
+  }
+  str.append("}");
+}
+
+void ParseCheck(std::istringstream& ist, char ch) {
+  if (ist.get() != ch)
+    LOG(LERROR) << "Expecting '" << ch << "'";
+}
+
+std::string ParseString(std::istringstream& ist) {
+  std::string str;
+  int count = 0;
+  while (ist) {
+    char ch = ist.peek();
+    if ((count == 0) && ((ch == '=') || (ch == ',') || (ch == '}'))) {
+      break;
+    } else if (ch == '{') {
+      count += 1;
+    } else if (ch == '}') {
+      count -= 1;
+      if (count < 0)
+        LOG(LERROR) << "mismatched '{' and '}'";
+    }
+    str.append(1, static_cast<char>(ist.get()));
+  }
+  return str;
+}
+
+void ParseMap(const std::string& str, StrMap& map) {
+  if (str.size() == 0)
+    return;
+  std::istringstream ist(str);
+  ParseCheck(ist, '{');
+  for (;;) {
+    std::string key = ParseString(ist);
+    ParseCheck(ist, '=');
+    std::string val = ParseString(ist);
+    map[key] = val;
+    if (ist.peek() == ',')
+      ist.get();
+    else
+      break;
+  }
+  ParseCheck(ist, '}');
+  if (ist.rdbuf()->in_avail() != 0)
+    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 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);
+}
+#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) {
+  std::vector<Network*> list;
+  CreateNetworks(list);
+
+  for (uint32 i = 0; i < list.size(); ++i) {
+    NetworkMap::iterator iter = networks_.find(list[i]->name());
+
+    Network* network;
+    if (iter == networks_.end()) {
+      network = list[i];
+    } else {
+      network = iter->second;
+      network->set_ip(list[i]->ip());
+      delete list[i];
+    }
+
+    networks_[network->name()] = network;
+    result.push_back(network);
+  }
+}
+
+std::string NetworkManager::GetState() {
+  StrMap map;
+  for (NetworkMap::iterator i = networks_.begin(); i != networks_.end(); ++i)
+    map[i->first] = i->second->GetState();
+
+  std::string str;
+  BuildMap(map, str);
+  return str;
+}
+
+void NetworkManager::SetState(std::string str) {
+  StrMap map;
+  ParseMap(str, map);
+
+  for (StrMap::iterator i = map.begin(); i != map.end(); ++i) {
+    std::string name = i->first;
+    std::string state = i->second;
+
+    Network* network = new Network(name, 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) {
+
+  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).
+}
+
+void Network::StartSession(NetworkSession* session) {
+  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);
+  if (iter != sessions_.end())
+    sessions_.erase(iter);
+}
+
+void Network::EstimateQuality() {
+  uint32 now = Time();
+
+  // Add new data points for the current time.
+  for (uint32 i = 0; i < sessions_.size(); ++i) {
+    if (sessions_[i]->HasQuality())
+      AddDataPoint(now, sessions_[i]->GetCurrentQuality());
+  }
+
+  // Construct the weighted average using both uniform and exponential weights.
+
+  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_;
+
+  if (denominator < DBL_EPSILON)
+    quality_ = kDefaultQuality;
+  else
+    quality_ = numerator / denominator;
+}
+
+std::string Network::ToString() const {
+  std::stringstream ss;
+  // Print out the first space-terminated token of the network name, plus
+  // the IP address.
+  ss << "Net[" << name_.substr(0, name_.find(' ')) 
+     << ":" << SocketAddress::IPToString(ip_) << "]";
+  return ss.str();
+}
+
+void Network::AddDataPoint(uint32 time, double quality) {
+  uniform_numerator_ += kAlpha * quality;
+  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_;
+
+  last_data_time_ = time;
+}
+
+std::string Network::GetState() {
+  StrMap map;
+  map["lt"] = talk_base::ToString<uint32>(last_data_time_);
+  map["un"] = talk_base::ToString<double>(uniform_numerator_);
+  map["ud"] = talk_base::ToString<double>(uniform_denominator_);
+  map["en"] = talk_base::ToString<double>(exponential_numerator_);
+  map["ed"] = talk_base::ToString<double>(exponential_denominator_);
+
+  std::string str;
+  BuildMap(map, str);
+  return str;
+}
+
+void Network::SetState(std::string str) {
+  StrMap map;
+  ParseMap(str, map);
+
+  last_data_time_ = FromString<uint32>(map["lt"]);
+  uniform_numerator_ = FromString<double>(map["un"]);
+  uniform_denominator_ = FromString<double>(map["ud"]);
+  exponential_numerator_ = FromString<double>(map["en"]);
+  exponential_denominator_ = FromString<double>(map["ed"]);
+}
+
+} // namespace talk_base
diff --git a/talk/base/network.h b/talk/base/network.h
new file mode 100755
index 0000000..52785ba
--- /dev/null
+++ b/talk/base/network.h
@@ -0,0 +1,139 @@
+/*
+ * 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_NETWORK_H__
+#define TALK_BASE_NETWORK_H__
+
+#include <deque>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "talk/base/basictypes.h"
+
+namespace talk_base {
+
+class Network;
+class NetworkSession;
+
+// Keeps track of the available network interfaces over time so that quality
+// information can be aggregated and recorded.
+class NetworkManager {
+public:
+
+  // 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);
+
+  // Reads and writes the state of the quality database in a string format.
+  std::string GetState();
+  void SetState(std::string str);
+
+  // Creates a network object for each network available on the machine.
+  static void CreateNetworks(std::vector<Network*>& networks);
+
+private:
+  typedef std::map<std::string,Network*> NetworkMap;
+
+  NetworkMap networks_;
+};
+
+// 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);
+
+  // Returns the OS name of this network.  This is considered the primary key
+  // that identifies each network.
+  const std::string& name() const { return name_; }
+
+  // Identifies the current IP address used by this network.
+  uint32 ip() const { return ip_; }
+  void set_ip(uint32 ip) { ip_ = ip; }
+
+  // Updates the list of sessions that are ongoing.
+  void StartSession(NetworkSession* session);
+  void StopSession(NetworkSession* session);
+
+  // Re-computes the estimate of near-future quality based on the information
+  // as of this exact moment.
+  void EstimateQuality();
+
+  // Returns the current estimate of the near-future quality of connections
+  // that use this local interface.
+  double quality() { return quality_; }
+
+  // Debugging description of this network
+  std::string ToString() const;
+
+private:
+  typedef std::vector<NetworkSession*> SessionList;
+
+  std::string name_;
+  uint32 ip_;
+  SessionList sessions_;
+  double uniform_numerator_;
+  double uniform_denominator_;
+  double exponential_numerator_;
+  double exponential_denominator_;
+  uint32 last_data_time_;
+  double quality_;
+
+  // Updates the statistics maintained to include the given estimate.
+  void AddDataPoint(uint32 time, double quality);
+
+  // 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();
+
+  friend class NetworkManager;
+};
+
+// 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:
+  // Determines whether this session has an estimate at this moment.  We will
+  // only call GetCurrentQuality when this returns true.
+  virtual bool HasQuality() = 0;
+
+  // 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
+
+#endif // TALK_BASE_NETWORK_H__
diff --git a/talk/base/openssladapter.cc b/talk/base/openssladapter.cc
new file mode 100755
index 0000000..1d4f02c
--- /dev/null
+++ b/talk/base/openssladapter.cc
@@ -0,0 +1,809 @@
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/openssladapter.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/Equifax_Secure_Global_eBusiness_CA-1.h"
+
+//////////////////////////////////////////////////////////////////////
+// StreamBIO
+//////////////////////////////////////////////////////////////////////
+
+#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;
+	}
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// SocketBIO
+//////////////////////////////////////////////////////////////////////
+
+static int socket_write(BIO* h, const char* buf, int num);
+static int socket_read(BIO* h, char* buf, int size);
+static int socket_puts(BIO* h, const char* str);
+static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
+static int socket_new(BIO* h);
+static int socket_free(BIO* data);
+
+static BIO_METHOD methods_socket = {
+	BIO_TYPE_BIO,
+	"socket",
+	socket_write,
+	socket_read,
+	socket_puts,
+	0,
+	socket_ctrl,
+	socket_new,
+	socket_free,
+	NULL,
+};
+
+BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
+
+BIO* BIO_new_socket(talk_base::AsyncSocket* socket) {
+	BIO* ret = BIO_new(BIO_s_socket2());
+	if (ret == NULL) {
+          return NULL;
+	}
+	ret->ptr = socket;
+	return ret;
+}
+
+static int socket_new(BIO* b) {
+	b->shutdown = 0;
+	b->init = 1;
+	b->num = 0; // 1 means socket closed
+	b->ptr = 0;
+	return 1;
+}
+
+static int socket_free(BIO* b) {
+	if (b == NULL)
+		return 0;
+	return 1;
+}
+
+static int socket_read(BIO* b, char* out, int outl) {
+	if (!out)
+		return -1;
+	talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr);
+	BIO_clear_retry_flags(b);
+  int result = socket->Recv(out, outl);
+  if (result > 0) {
+    return result;
+  } else if (result == 0) {
+		b->num = 1;
+  } else if (socket->IsBlocking()) {
+		BIO_set_retry_read(b);
+	}
+	return -1;
+}
+
+static int socket_write(BIO* b, const char* in, int inl) {
+	if (!in)
+		return -1;
+	talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr);
+	BIO_clear_retry_flags(b);
+  int result = socket->Send(in, inl);
+  if (result > 0) {
+    return result;
+  } else if (socket->IsBlocking()) {
+		BIO_set_retry_write(b);
+	}
+	return -1;
+}
+
+static int socket_puts(BIO* b, const char* str) {
+	return socket_write(b, str, strlen(str));
+}
+
+static long socket_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;
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// OpenSSLAdapter
+/////////////////////////////////////////////////////////////////////////////
+
+namespace talk_base {
+
+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) {
+}
+
+OpenSSLAdapter::~OpenSSLAdapter() {
+  Cleanup();
+}
+
+int
+OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
+  if (state_ != SSL_NONE)
+    return -1; 
+
+  ssl_host_name_ = hostname;
+  restartable_ = restartable;
+
+  if (socket_->GetState() != Socket::CS_CONNECTED) {
+    state_ = SSL_WAIT;
+    return 0;
+  }
+
+  state_ = SSL_CONNECTING;
+  if (int err = BeginSSL()) {
+    Error("BeginSSL", err, false);
+    return err;
+  }
+
+  return 0;
+}
+
+int
+OpenSSLAdapter::BeginSSL() {
+  LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_;
+  ASSERT(state_ == SSL_CONNECTING);
+
+  int err = 0;
+  BIO* bio = NULL;
+
+  // First set up the context
+  if (!ssl_ctx_)
+    ssl_ctx_ = SetupSSLContext();
+
+  if (!ssl_ctx_) {
+    err = -1;
+    goto ssl_error;
+  }
+
+  bio = BIO_new_socket(static_cast<talk_base::AsyncSocketAdapter*>(socket_));
+  if (!bio) {
+    err = -1;
+    goto ssl_error;
+  }
+
+  ssl_ = SSL_new(ssl_ctx_);
+  if (!ssl_) {
+    err = -1;
+    goto ssl_error;
+  }
+
+  SSL_set_app_data(ssl_, this);
+
+  SSL_set_bio(ssl_, bio, bio);
+  SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
+                     SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+  // the SSL object owns the bio now
+  bio = NULL;
+
+  // Do the connect
+  err = ContinueSSL();
+  if (err != 0)
+    goto ssl_error;
+
+  return err;
+
+ssl_error:
+  Cleanup();
+  if (bio)
+    BIO_free(bio);
+
+  return err;
+}
+
+int
+OpenSSLAdapter::ContinueSSL() {
+  LOG(LS_INFO) << "ContinueSSL";
+  ASSERT(state_ == SSL_CONNECTING);
+
+  int code = SSL_connect(ssl_);
+  switch (SSL_get_error(ssl_, code)) {
+  case SSL_ERROR_NONE:
+    LOG(LS_INFO) << " -- success";
+
+    if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
+      LOG(LS_ERROR) << "TLS post connection check failed";
+      // make sure we close the socket
+      Cleanup();
+      // The connect failed so return -1 to shut down the socket
+      return -1;
+    }
+
+    state_ = SSL_CONNECTED;
+    AsyncSocketAdapter::OnConnectEvent(this);
+#if 0  // TODO: worry about this
+    // Don't let ourselves go away during the callbacks
+    PRefPtr<OpenSSLAdapter> lock(this);
+    LOG(LS_INFO) << " -- onStreamReadable";
+    AsyncSocketAdapter::OnReadEvent(this);
+    LOG(LS_INFO) << " -- onStreamWriteable";
+    AsyncSocketAdapter::OnWriteEvent(this);
+#endif
+    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
+OpenSSLAdapter::Error(const char* context, int err, bool signal) {
+  LOG(LS_WARNING) << "SChannelAdapter::Error("
+                  << context << ", " << err << ")";
+  state_ = SSL_ERROR;
+  SetError(err);
+  if (signal)
+    AsyncSocketAdapter::OnCloseEvent(this, err);
+}
+
+void
+OpenSSLAdapter::Cleanup() {
+  LOG(LS_INFO) << "Cleanup";
+
+  state_ = SSL_NONE;
+  ssl_read_needs_write_ = false;
+  ssl_write_needs_read_ = false;
+
+  if (ssl_) {
+    SSL_free(ssl_);
+    ssl_ = NULL;
+  }
+
+  if (ssl_ctx_) {
+    SSL_CTX_free(ssl_ctx_);
+    ssl_ctx_ = NULL;
+  }
+}
+
+//
+// AsyncSocket Implementation
+//
+
+int
+OpenSSLAdapter::Send(const void* pv, size_t cb) {
+  //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
+
+  switch (state_) {
+  case SSL_NONE:
+    return AsyncSocketAdapter::Send(pv, cb);
+
+  case SSL_WAIT:
+  case SSL_CONNECTING:
+    SetError(EWOULDBLOCK);
+    return SOCKET_ERROR;
+
+  case SSL_CONNECTED:
+    break;
+
+  case SSL_ERROR:
+  default:
+    return SOCKET_ERROR;
+  }
+
+  // OpenSSL will return an error if we try to write zero bytes
+  if (cb == 0)
+    return 0;
+
+  ssl_write_needs_read_ = false;
+
+  int code = SSL_write(ssl_, pv, cb);
+  switch (SSL_get_error(ssl_, code)) {
+  case SSL_ERROR_NONE:
+    //LOG(LS_INFO) << " -- success";
+    return code;
+  case SSL_ERROR_WANT_READ:
+    //LOG(LS_INFO) << " -- error want read";
+    ssl_write_needs_read_ = true;
+    SetError(EWOULDBLOCK);
+    break;
+  case SSL_ERROR_WANT_WRITE:
+    //LOG(LS_INFO) << " -- error want write";
+    SetError(EWOULDBLOCK);
+    break;
+  case SSL_ERROR_ZERO_RETURN:
+    //LOG(LS_INFO) << " -- remote side closed";
+    SetError(EWOULDBLOCK);
+    // do we need to signal closure?
+    break;
+  default:
+    //LOG(LS_INFO) << " -- error " << code;
+    Error("SSL_write", (code ? code : -1), false);
+    break;
+  }
+
+  return SOCKET_ERROR;
+}
+
+int
+OpenSSLAdapter::Recv(void* pv, size_t cb) {
+  //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
+  switch (state_) {
+
+  case SSL_NONE:
+    return AsyncSocketAdapter::Recv(pv, cb);
+
+  case SSL_WAIT:
+  case SSL_CONNECTING:
+    SetError(EWOULDBLOCK);
+    return SOCKET_ERROR;
+
+  case SSL_CONNECTED:
+    break;
+
+  case SSL_ERROR:
+  default:
+    return SOCKET_ERROR;
+  }
+
+  // Don't trust OpenSSL with zero byte reads
+  if (cb == 0)
+    return 0;
+
+  ssl_read_needs_write_ = false;
+
+  int code = SSL_read(ssl_, pv, cb);
+  switch (SSL_get_error(ssl_, code)) {
+  case SSL_ERROR_NONE:
+    //LOG(LS_INFO) << " -- success";
+    return code;
+  case SSL_ERROR_WANT_READ:
+    //LOG(LS_INFO) << " -- error want read";
+    SetError(EWOULDBLOCK);
+    break;
+  case SSL_ERROR_WANT_WRITE:
+    //LOG(LS_INFO) << " -- error want write";
+    ssl_read_needs_write_ = true;
+    SetError(EWOULDBLOCK);
+    break;
+  case SSL_ERROR_ZERO_RETURN:
+    //LOG(LS_INFO) << " -- remote side closed";
+    SetError(EWOULDBLOCK);
+    // do we need to signal closure?
+    break;
+  default:
+    //LOG(LS_INFO) << " -- error " << code;
+    Error("SSL_read", (code ? code : -1), false);
+    break;
+  }
+
+  return SOCKET_ERROR;
+}
+
+int
+OpenSSLAdapter::Close() {
+  Cleanup();
+  state_ = restartable_ ? SSL_WAIT : SSL_NONE;
+  return AsyncSocketAdapter::Close();
+}
+
+Socket::ConnState
+OpenSSLAdapter::GetState() const {
+  //if (signal_close_)
+  //  return CS_CONNECTED;
+  ConnState state = socket_->GetState();
+  if ((state == CS_CONNECTED)
+      && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
+    state = CS_CONNECTING;
+  return state;
+}
+
+void
+OpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
+  LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
+  if (state_ != SSL_WAIT) {
+    ASSERT(state_ == SSL_NONE);
+    AsyncSocketAdapter::OnConnectEvent(socket);
+    return;
+  }
+
+  state_ = SSL_CONNECTING;
+  if (int err = BeginSSL()) {
+    AsyncSocketAdapter::OnCloseEvent(socket, err);
+  }
+}
+
+void
+OpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
+  //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
+
+  if (state_ == SSL_NONE) {
+    AsyncSocketAdapter::OnReadEvent(socket);
+    return;
+  }
+
+  if (state_ == SSL_CONNECTING) {
+    if (int err = ContinueSSL()) {
+      Error("ContinueSSL", err);
+    }
+    return;
+  }
+
+  if (state_ != SSL_CONNECTED)
+    return;
+
+  // Don't let ourselves go away during the callbacks
+  //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
+  if (ssl_write_needs_read_)  {
+    //LOG(LS_INFO) << " -- onStreamWriteable";
+    AsyncSocketAdapter::OnWriteEvent(socket);
+  }
+
+  //LOG(LS_INFO) << " -- onStreamReadable";
+  AsyncSocketAdapter::OnReadEvent(socket);
+}
+
+void
+OpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
+  //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
+
+  if (state_ == SSL_NONE) {
+    AsyncSocketAdapter::OnWriteEvent(socket);
+    return;
+  }
+
+  if (state_ == SSL_CONNECTING) {
+    if (int err = ContinueSSL()) {
+      Error("ContinueSSL", err);
+    }
+    return;
+  }
+
+  if (state_ != SSL_CONNECTED)
+    return;
+
+  // Don't let ourselves go away during the callbacks
+  //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
+
+  if (ssl_read_needs_write_)  {
+    //LOG(LS_INFO) << " -- onStreamReadable";
+    AsyncSocketAdapter::OnReadEvent(socket);
+  }
+
+  //LOG(LS_INFO) << " -- onStreamWriteable";
+  AsyncSocketAdapter::OnWriteEvent(socket);
+}
+
+void
+OpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
+  LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
+  AsyncSocketAdapter::OnCloseEvent(socket, err);
+}
+
+// This code is taken from the "Network Security with OpenSSL"
+// sample in chapter 5
+bool
+OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
+  if (!host)
+    return false;
+
+  // Checking the return from SSL_get_peer_certificate here is not strictly
+  // necessary.  With our setup, it is not possible for it to return
+  // NULL.  However, it is good form to check the return.
+  X509* certificate = SSL_get_peer_certificate(ssl);
+  if (!certificate)
+    return false;
+
+#ifdef _DEBUG
+  {
+    LOG(LS_INFO) << "Certificate from server:";
+    BIO* mem = BIO_new(BIO_s_mem());
+    X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
+    BIO_write(mem, "\0", 1);
+    char* buffer;
+    BIO_get_mem_data(mem, &buffer);
+    LOG(LS_INFO) << buffer;
+    BIO_free(mem);
+
+    char* cipher_description =
+      SSL_CIPHER_description(SSL_get_current_cipher(ssl), NULL, 128);
+    LOG(LS_INFO) << "Cipher: " << cipher_description;
+    OPENSSL_free(cipher_description);
+  }
+#endif
+
+  bool ok = false;
+  int extension_count = X509_get_ext_count(certificate);
+  for (int i = 0; i < extension_count; ++i) {
+    X509_EXTENSION* extension = X509_get_ext(certificate, i);
+    int extension_nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
+
+    if (extension_nid == NID_subject_alt_name) {
+      X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
+      if (!meth)
+        break;
+
+      void* ext_str = NULL;
+
+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
+      const unsigned char **ext_value_data = (const_cast<const unsigned char **>
+					      (&extension->value->data));
+#else
+      unsigned char **ext_value_data = &extension->value->data;
+#endif
+
+      if (meth->it) {
+        ext_str = ASN1_item_d2i(NULL, ext_value_data, extension->value->length,
+                                ASN1_ITEM_ptr(meth->it));
+      } else {
+        ext_str = meth->d2i(NULL, ext_value_data, 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)) {
+          ok = true;
+          break;
+        }
+      }
+    }
+    if (ok)
+      break;
+  }
+
+  char data[256];
+  X509_name_st* subject;
+  if (!ok
+      && (subject = X509_get_subject_name(certificate))
+      && (X509_NAME_get_text_by_NID(subject, NID_commonName,
+                                    data, sizeof(data)) > 0)) {
+    data[sizeof(data)-1] = 0;
+    if (_stricmp(data, host) == 0)
+      ok = true;
+  }
+
+  X509_free(certificate);
+
+  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);
+
+  if (!ok && ignore_bad_cert()) {
+    LOG(LS_INFO) << "Other TLS post connection checks failed.";
+    ok = true;
+  }
+
+  return ok;
+}
+
+#if _DEBUG
+
+// We only use this for tracing and so it is only needed in debug mode
+
+void
+OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
+  const char* str = "undefined";
+  int w = where & ~SSL_ST_MASK;
+  if (w & SSL_ST_CONNECT) {
+    str = "SSL_connect";
+  } else if (w & SSL_ST_ACCEPT) {
+    str = "SSL_accept";
+  }
+  if (where & SSL_CB_LOOP) {
+    LOG(LS_INFO) <<  str << ":" << SSL_state_string_long(s);
+  } else if (where & SSL_CB_ALERT) {
+    str = (where & SSL_CB_READ) ? "read" : "write";
+    LOG(LS_INFO) <<  "SSL3 alert " << str
+      << ":" << SSL_alert_type_string_long(ret)
+      << ":" << SSL_alert_desc_string_long(ret);
+  } else if (where & SSL_CB_EXIT) {
+    if (ret == 0) {
+      LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
+    } else if (ret < 0) {
+      LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
+    }
+  }
+}
+
+#endif  // _DEBUG
+
+int
+OpenSSLAdapter::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 stream pointer from the store
+  SSL* ssl = reinterpret_cast<SSL*>(
+                X509_STORE_CTX_get_ex_data(store,
+                  SSL_get_ex_data_X509_STORE_CTX_idx()));
+
+  OpenSSLAdapter* stream =
+    reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
+
+  if (!ok && stream->ignore_bad_cert()) {
+    LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
+    ok = 1;
+  }
+
+  return ok;
+}
+
+SSL_CTX*
+OpenSSLAdapter::SetupSSLContext() {
+  SSL_CTX* ctx = SSL_CTX_new(TLSv1_client_method());
+  if (ctx == NULL) 
+	  return NULL;
+
+  // Add the root cert to the SSL context
+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
+   const unsigned char* cert_buffer
+#else
+   unsigned char* cert_buffer
+#endif
+    = 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);
+    return NULL;
+  }
+  if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert)) {
+    X509_free(cert);
+    SSL_CTX_free(ctx);
+    return NULL;
+  }
+
+#ifdef _DEBUG
+  SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
+#endif
+
+  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
+  SSL_CTX_set_verify_depth(ctx, 4);
+  SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+
+  return ctx;
+}
+
+} // namespace talk_base
diff --git a/talk/base/openssladapter.h b/talk/base/openssladapter.h
new file mode 100755
index 0000000..b794a7b
--- /dev/null
+++ b/talk/base/openssladapter.h
@@ -0,0 +1,94 @@
+/*
+ * 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_OPENSSLADAPTER_H__
+#define TALK_BASE_OPENSSLADAPTER_H__
+
+#include <string>
+#include "talk/base/ssladapter.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 {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class OpenSSLAdapter : public SSLAdapter {
+public:
+  OpenSSLAdapter(AsyncSocket* socket);
+  virtual ~OpenSSLAdapter();
+
+  virtual int StartSSL(const char* hostname, bool restartable);
+  virtual int Send(const void* pv, size_t cb);
+  virtual int Recv(void* pv, size_t cb);
+  virtual int Close();
+
+  // Note that the socket returns ST_CONNECTING while SSL is being negotiated.
+  virtual ConnState GetState() const;
+
+protected:
+  virtual void OnConnectEvent(AsyncSocket* socket);
+  virtual void OnReadEvent(AsyncSocket* socket);
+  virtual void OnWriteEvent(AsyncSocket* socket);
+  virtual void OnCloseEvent(AsyncSocket* socket, int err);
+
+private:
+  enum SSLState {
+    SSL_NONE, SSL_WAIT, SSL_CONNECTING, SSL_CONNECTED, SSL_ERROR
+  };
+
+  int BeginSSL();
+  int ContinueSSL();
+  void Error(const char* context, int err, bool signal = true);
+  void Cleanup();
+
+  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 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_; 
+
+  SSL* ssl_;
+  SSL_CTX* ssl_ctx_;
+  std::string ssl_host_name_;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_OPENSSLADAPTER_H__
diff --git a/talk/base/pathutils.cc b/talk/base/pathutils.cc
new file mode 100755
index 0000000..4a77879
--- /dev/null
+++ b/talk/base/pathutils.cc
@@ -0,0 +1,426 @@
+/*
+ * 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 WIN32
+#include "talk/base/win32.h"
+#include <shellapi.h>
+#include <shlobj.h>
+#include <tchar.h>
+#endif  // WIN32
+
+#include "talk/base/common.h"
+#include "talk/base/pathutils.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/urlencode.h"
+
+namespace talk_base {
+
+std::string const EMPTY_STR = "";
+
+// EXT_DELIM separates a file basename from extension
+const char EXT_DELIM = '.';
+
+// FOLDER_DELIMS separate folder segments and the filename
+const char* const FOLDER_DELIMS = "/\\";
+
+// DEFAULT_FOLDER_DELIM is the preferred delimiter for this platform
+#if WIN32
+const char DEFAULT_FOLDER_DELIM = '\\';
+#else  // !WIN32
+const char DEFAULT_FOLDER_DELIM = '/';
+#endif  // !WIN32
+
+///////////////////////////////////////////////////////////////////////////////
+// Pathname - parsing of pathnames into components, and vice versa
+///////////////////////////////////////////////////////////////////////////////
+
+bool Pathname::IsFolderDelimiter(char ch) {
+  return (NULL != ::strchr(FOLDER_DELIMS, ch));
+}
+
+Pathname::Pathname()
+  : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
+}
+
+Pathname::Pathname(const std::string& pathname)
+  : folder_delimiter_(DEFAULT_FOLDER_DELIM) {
+  SetPathname(pathname);
+}
+
+void Pathname::SetFolderDelimiter(char delimiter) {
+  ASSERT(IsFolderDelimiter(delimiter));
+  folder_delimiter_ = delimiter;
+}
+
+void Pathname::Normalize() {
+  for (size_t i=0; i<folder_.length(); ++i) {
+    if (IsFolderDelimiter(folder_[i])) {
+      folder_[i] = folder_delimiter_;
+    }
+  }
+}
+
+void Pathname::clear() {
+  folder_.clear();
+  basename_.clear();
+  extension_.clear();
+}
+
+std::string Pathname::pathname() const {
+  std::string pathname(folder_);
+  pathname.append(basename_);
+  pathname.append(extension_);
+  return pathname;
+}
+
+std::string Pathname::url() const {
+  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]))
+      s += '/';
+    else
+      s += folder_[i];
+  }
+  s += basename_;
+  s += extension_;
+  return UrlEncodeString(s);
+}
+
+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));
+    SetFilename(pathname.substr(pos + 1));
+  } else {
+    SetFolder(EMPTY_STR);
+    SetFilename(pathname);
+  }
+}
+
+void Pathname::AppendPathname(const Pathname& pathname) {
+  std::string full_pathname(folder_);
+  full_pathname.append(pathname.pathname());
+  SetPathname(full_pathname);
+}
+
+std::string Pathname::folder() const {
+  return folder_;
+}
+
+std::string Pathname::folder_name() const {
+  std::string::size_type pos = std::string::npos;
+  if (folder_.size() >= 2) {
+    pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2);
+  }
+  if (pos != std::string::npos) {
+    return folder_.substr(pos + 1);
+  } else {
+    return folder_;
+  }
+}
+
+std::string Pathname::parent_folder() const {
+  std::string::size_type pos = std::string::npos;
+  if (folder_.size() >= 2) {
+    pos = folder_.find_last_of(FOLDER_DELIMS, folder_.length() - 2);
+  }
+  if (pos != std::string::npos) {
+    return folder_.substr(0, pos + 1);
+  } else {
+    return EMPTY_STR;
+  }
+}
+
+void Pathname::SetFolder(const std::string& folder) {
+  folder_.assign(folder);
+  // Ensure folder ends in a path delimiter
+  if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) {
+    folder_.push_back(folder_delimiter_);
+  }
+}
+
+void Pathname::AppendFolder(const std::string& folder) {
+  folder_.append(folder);
+  // Ensure folder ends in a path delimiter
+  if (!folder_.empty() && !IsFolderDelimiter(folder_[folder_.length()-1])) {
+    folder_.push_back(folder_delimiter_);
+  }
+}
+
+std::string Pathname::basename() const {
+  return basename_;
+}
+
+void Pathname::SetBasename(const std::string& basename) {
+  ASSERT(basename.find_first_of(FOLDER_DELIMS) == std::string::npos);
+  basename_.assign(basename);
+}
+
+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);
+  extension_.assign(extension);
+  // Ensure extension begins with the extension delimiter
+  if (!extension_.empty() && (extension_[0] != EXT_DELIM)) {
+    extension_.insert(extension_.begin(), EXT_DELIM);
+  }
+} 
+
+std::string Pathname::filename() const {
+  std::string filename(basename_);
+  filename.append(extension_);
+  return filename;
+}
+
+void 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);
+  } else {
+    SetBasename(filename.substr(0, pos));
+    SetExtension(filename.substr(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 FinishPath(talk_base::Pathname& path, bool create,
+                const std::string& append) {
+  if (!append.empty()) {
+    path.AppendFolder(append);
+  }
+  if (create && !CreateFolder(path))
+    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
+}
+#endif
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/pathutils.h b/talk/base/pathutils.h
new file mode 100755
index 0000000..eb33edf
--- /dev/null
+++ b/talk/base/pathutils.h
@@ -0,0 +1,110 @@
+/*
+ * 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_PATHUTILS_H__
+#define TALK_BASE_PATHUTILS_H__
+
+#include <string>
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// Pathname - parsing of pathnames into components, and vice versa.
+//
+// To establish consistent terminology, a filename never contains a folder
+// component.  A folder never contains a filename.  A pathname may include
+// a folder and/or filename component.  Here are some examples:
+//
+//   pathname()      /home/john/example.txt
+//   folder()        /home/john/
+//   filename()                 example.txt
+//   parent_folder() /home/
+//   folder_name()         john/
+//   basename()                 example
+//   extension()                       .txt
+//
+// Basename may begin, end, and/or include periods, but no folder delimiters.
+// If extension exists, it consists of a period followed by zero or more
+// non-period/non-delimiter characters, and basename is non-empty.
+///////////////////////////////////////////////////////////////////////////////
+
+class Pathname {
+public:
+  // Folder delimiters are slash and backslash
+  static bool IsFolderDelimiter(char ch);
+
+  Pathname();
+  Pathname(const std::string& pathname);
+
+  // Set's the default folder delimiter for this Pathname
+  char folder_delimiter() const { return folder_delimiter_; }
+  void SetFolderDelimiter(char delimiter);
+
+  // Normalize changes all folder delimiters to folder_delimiter()
+  void Normalize();
+
+  // Reset to the empty pathname
+  void clear();
+
+  std::string url() const;
+
+  std::string pathname() const;
+  void SetPathname(const std::string& pathname);
+
+  // Append pathname to the current folder (if any).  Any existing filename
+  // will be discarded.
+  void AppendPathname(const Pathname& pathname);
+
+  std::string folder() const;
+  std::string folder_name() const;
+  std::string parent_folder() const;
+  // SetFolder and AppendFolder will append a folder delimiter, if needed.
+  void SetFolder(const std::string& folder);
+  void AppendFolder(const std::string& folder);
+
+  std::string basename() const;
+  void SetBasename(const std::string& basename);
+
+  std::string extension() const;
+  // SetExtension will prefix a period, if needed.
+  void SetExtension(const std::string& extension);
+
+  std::string filename() const;
+  void SetFilename(const std::string& filename);
+
+private:
+
+  std::string folder_, basename_, extension_;
+  char folder_delimiter_;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif // TALK_BASE_PATHUTILS_H__
diff --git a/talk/base/physicalsocketserver.cc b/talk/base/physicalsocketserver.cc
new file mode 100755
index 0000000..9cdacdf
--- /dev/null
+++ b/talk/base/physicalsocketserver.cc
@@ -0,0 +1,1132 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#include <cassert>
+
+#ifdef POSIX
+extern "C" {
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <unistd.h>
+}
+#endif
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define _WINSOCKAPI_
+#include <windows.h>
+#undef SetPort
+#endif
+
+#include <algorithm>
+#include <iostream>
+
+#include "talk/base/basictypes.h"
+#include "talk/base/byteorder.h"
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/physicalsocketserver.h"
+#include "talk/base/time.h"
+#include "talk/base/winping.h"
+
+#ifdef __linux 
+#define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
+#endif  // __linux
+
+#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;
+#endif
+
+namespace talk_base {
+
+const int kfRead  = 0x0001;
+const int kfWrite = 0x0002;
+const int kfConnect = 0x0004;
+const int kfClose = 0x0008;
+
+// Standard MTUs
+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)
+  4352,     // FDDI
+  //2048,   // Wideband Network
+  2002,     // IEEE 802.5 (4Mb recommended)
+  //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
+  508,      // IEEE 802/Source-Rt Bridge, ARCNET
+  296,      // Point-to-Point (low delay)
+  68,       // Official minimum
+  0,        // End of list marker
+};
+
+const uint32 IP_HEADER_SIZE = 20;
+const uint32 ICMP_HEADER_SIZE = 8;
+
+class PhysicalSocket : public AsyncSocket {
+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)
+      enabled_events_ = kfRead | kfWrite;
+  }
+
+  virtual ~PhysicalSocket() {
+    Close();
+  }
+
+  // Creates the underlying OS socket (same as the "socket" function).
+  virtual bool Create(int type) {
+    Close();
+    s_ = ::socket(AF_INET, type, 0);
+    UpdateLastError();
+    if (type != SOCK_STREAM)
+      enabled_events_ = kfRead | kfWrite;
+    return s_ != INVALID_SOCKET;
+  }
+
+  SocketAddress GetLocalAddress() const {
+    sockaddr_in addr;
+    socklen_t addrlen = sizeof(addr);
+    int result = ::getsockname(s_, (sockaddr*)&addr, &addrlen);
+    ASSERT(addrlen == sizeof(addr));
+    talk_base::SocketAddress address;
+    if (result >= 0) {
+      address.FromSockAddr(addr);
+    } else {
+      ASSERT(result >= 0);
+    }
+    return address;
+  }
+
+  SocketAddress GetRemoteAddress() const {
+    sockaddr_in addr;
+    socklen_t addrlen = sizeof(addr);
+    int result = ::getpeername(s_, (sockaddr*)&addr, &addrlen);
+    ASSERT(addrlen == sizeof(addr));
+    talk_base::SocketAddress address;
+    if (result >= 0) {
+      address.FromSockAddr(addr);
+    } else {
+      ASSERT(errno == ENOTCONN);
+    }
+    return address;
+  }
+
+  int Bind(const SocketAddress& addr) {
+    sockaddr_in saddr;
+    addr.ToSockAddr(&saddr);
+    int err = ::bind(s_, (sockaddr*)&saddr, sizeof(saddr));
+    UpdateLastError();
+    return err;
+  }
+
+  int Connect(const SocketAddress& addr) {
+    // TODO: Implicit creation is required to reconnect...
+    // ...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?
+    }
+    sockaddr_in saddr;
+    addr2.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_;
+    if (err == 0) {
+      state_ = CS_CONNECTED;
+    } else if (IsBlockingError(error_)) {
+      state_ = CS_CONNECTING;
+      enabled_events_ |= kfConnect;
+    }
+    enabled_events_ |= kfRead | kfWrite;
+    return err;
+  }
+
+  int GetError() const {
+    return error_;
+  }
+
+  void SetError(int error) {
+    error_ = error;
+  }
+
+  ConnState GetState() const {
+    return state_;
+  }
+
+  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));
+#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
+  }
+
+  int Send(const void *pv, size_t cb) {
+    int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb, 0);
+    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
+    if ((sent < 0) && IsBlockingError(error_)) {
+      enabled_events_ |= kfWrite;
+    }
+    return sent;
+  }
+
+  int SendTo(const void *pv, size_t cb, const SocketAddress& addr) {
+    sockaddr_in saddr;
+    addr.ToSockAddr(&saddr);
+    int sent = ::sendto(
+        s_, (const char *)pv, (int)cb, 0, (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;
+    }
+    return sent;
+  }
+
+  int Recv(void *pv, size_t cb) {
+    int received = ::recv(s_, (char *)pv, (int)cb, 0);
+    if ((received == 0) && (cb != 0)) {
+      // 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.
+      error_ = EWOULDBLOCK;
+      return SOCKET_ERROR;
+    }
+    UpdateLastError();
+    if ((received >= 0) || IsBlockingError(error_)) {
+      enabled_events_ |= kfRead;
+    }
+    return received;
+  }
+
+  int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
+    sockaddr_in saddr;
+    socklen_t cbAddr = sizeof(saddr);
+    int received = ::recvfrom(s_, (char *)pv, (int)cb, 0, (sockaddr*)&saddr,
+                              &cbAddr);
+    UpdateLastError();
+    if ((received >= 0) && (paddr != NULL))
+      paddr->FromSockAddr(saddr);
+    if ((received >= 0) || IsBlockingError(error_)) {
+      enabled_events_ |= kfRead;
+    }
+    return received;
+  }
+
+  int Listen(int backlog) {
+    int err = ::listen(s_, backlog);
+    UpdateLastError();
+    if (err == 0)
+      state_ = CS_CONNECTING;
+    enabled_events_ |= kfRead;
+
+    return err;
+  }
+
+  Socket* 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;
+    if (paddr != NULL)
+      paddr->FromSockAddr(saddr);
+    enabled_events_ |= kfRead | kfWrite;
+    return ss_->WrapSocket(s);
+  }
+
+  int Close() {
+    if (s_ == INVALID_SOCKET)
+      return 0;
+    int err = ::closesocket(s_);
+    UpdateLastError();
+    //LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] Close() Ret: " << err << " Error: " << error_;
+    s_ = INVALID_SOCKET;
+    state_ = CS_CLOSED;
+    enabled_events_ = 0;
+    return err;
+  }
+
+  int EstimateMTU(uint16* mtu) {
+    SocketAddress addr = GetRemoteAddress();
+    if (addr.IsAny()) {
+      error_ = ENOTCONN;
+      return -1;
+    }
+
+#ifdef WIN32
+
+    WinPing ping;
+    if (!ping.IsValid()) {
+      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;
+      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 != WinPing::PING_TOO_LARGE) {
+        *mtu = PACKET_MAXIMUMS[level];
+        return 0;
+      }
+    }
+
+    assert(false);
+    return 0;
+
+#endif // WIN32
+
+#ifdef __linux 
+
+    int value;
+    socklen_t vlen = sizeof(value);
+    int err = getsockopt(s_, IPPROTO_IP, IP_MTU, &value, &vlen);
+    if (err < 0) {
+      UpdateLastError();
+      return err;
+    }
+
+    assert((0 <= value) && (value <= 65536));
+    *mtu = uint16(value);
+    return 0;
+
+#endif   // __linux
+
+    // TODO: OSX support
+  }
+
+  SocketServer* socketserver() { return ss_; }
+ 
+protected:
+  PhysicalSocketServer* ss_;
+  SOCKET s_;
+  uint32 enabled_events_;
+  int error_;
+  ConnState state_;
+
+  void UpdateLastError() {
+#ifdef WIN32
+    error_ = WSAGetLastError();
+#endif
+#ifdef POSIX
+    error_ = errno;
+#endif
+  }
+};
+
+#ifdef POSIX
+class Dispatcher {
+public:
+  virtual uint32 GetRequestedEvents() = 0;
+  virtual void OnPreEvent(uint32 ff) = 0;    
+  virtual void OnEvent(uint32 ff, int err) = 0;
+  virtual int GetDescriptor() = 0;
+};
+
+class EventDispatcher : public Dispatcher {
+public:
+  EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
+    if (pipe(afd_) < 0)
+      LOG(LERROR) << "pipe failed";
+    ss_->Add(this);
+  }
+
+  virtual ~EventDispatcher() {
+    ss_->Remove(this);
+    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;
+    }
+  }
+  
+  virtual uint32 GetRequestedEvents() {
+    return kfRead;
+  }
+
+  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));
+      fSignaled_ = false;
+    }
+  }
+
+  virtual void OnEvent(uint32 ff, int err) {
+    assert(false);
+  }
+
+  virtual int GetDescriptor() {
+    return afd_[0];
+  }
+
+private:
+  PhysicalSocketServer *ss_;
+  int afd_[2];
+  bool fSignaled_;
+  CriticalSection crit_;
+};
+
+class SocketDispatcher : public Dispatcher, public PhysicalSocket {
+public:
+  SocketDispatcher(PhysicalSocketServer *ss) : PhysicalSocket(ss) {
+    ss_->Add(this);
+  }
+  SocketDispatcher(SOCKET s, PhysicalSocketServer *ss) : PhysicalSocket(ss, s) {
+    ss_->Add(this);
+  }
+
+  virtual ~SocketDispatcher() {
+    Close();
+  }
+
+  bool Initialize() {
+    ss_->Add(this);
+    fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
+    return true;
+  }
+
+  virtual bool Create(int type) {
+    // Change the socket to be non-blocking.
+    if (!PhysicalSocket::Create(type))
+      return false;
+
+    return Initialize();
+  }
+  
+  virtual int GetDescriptor() {
+    return s_;
+  }
+
+  virtual uint32 GetRequestedEvents() {
+    return enabled_events_;
+  }
+
+  virtual void OnPreEvent(uint32 ff) {
+    if ((ff & kfConnect) != 0)
+      state_ = CS_CONNECTED;
+  }
+
+  virtual void OnEvent(uint32 ff, int err) {
+    if ((ff & kfRead) != 0) {
+      enabled_events_ &= ~kfRead;
+      SignalReadEvent(this);
+    }
+    if ((ff & kfWrite) != 0) {
+      enabled_events_ &= ~kfWrite;
+      SignalWriteEvent(this);
+    }
+    if ((ff & kfConnect) != 0) {
+      enabled_events_ &= ~kfConnect;
+      SignalConnectEvent(this);
+    }
+    if ((ff & kfClose) != 0)
+      SignalCloseEvent(this, err);
+  }
+
+  virtual int Close() {
+    if (s_ == INVALID_SOCKET)
+      return 0;
+
+    ss_->Remove(this);
+    return PhysicalSocket::Close();
+  }
+    
+};
+
+class FileDispatcher: public Dispatcher, public AsyncFile {
+public:
+  FileDispatcher(int fd, PhysicalSocketServer *ss) : ss_(ss), fd_(fd) {
+    set_readable(true);
+
+    ss_->Add(this);
+
+    fcntl(fd_, F_SETFL, fcntl(fd_, F_GETFL, 0) | O_NONBLOCK);
+  }
+
+  virtual ~FileDispatcher() {
+    ss_->Remove(this);
+  }
+
+  SocketServer* socketserver() { return ss_; }
+
+  virtual int GetDescriptor() {
+    return fd_;
+  }
+
+  virtual uint32 GetRequestedEvents() {
+    return flags_;
+  }
+
+  virtual void OnPreEvent(uint32 ff) {
+  }
+
+  virtual void OnEvent(uint32 ff, int err) {
+    if ((ff & kfRead) != 0)
+      SignalReadEvent(this);
+    if ((ff & kfWrite) != 0)
+      SignalWriteEvent(this);
+    if ((ff & kfClose) != 0)
+      SignalCloseEvent(this, err);
+  }
+
+  virtual bool readable() {
+    return (flags_ & kfRead) != 0;
+  }
+
+  virtual void set_readable(bool value) {
+    flags_ = value ? (flags_ | kfRead) : (flags_ & ~kfRead);
+  }
+
+  virtual bool writable() {
+    return (flags_ & kfWrite) != 0;
+  }
+
+  virtual void set_writable(bool value) {
+    flags_ = value ? (flags_ | kfWrite) : (flags_ & ~kfWrite);
+  }
+
+private:
+  PhysicalSocketServer* ss_;
+  int fd_;
+  int flags_;
+};
+
+AsyncFile* PhysicalSocketServer::CreateFile(int fd) {
+  return new FileDispatcher(fd, this);
+}
+
+#endif // POSIX
+
+#ifdef WIN32
+class Dispatcher {
+public:
+  virtual uint32 GetRequestedEvents() = 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;
+  if (events & kfRead)
+    ffFD |= FD_READ;
+  if (events & kfWrite)
+    ffFD |= FD_WRITE;
+  if (events & kfConnect)
+    ffFD |= FD_CONNECT;
+  return ffFD;
+}
+
+class EventDispatcher : public Dispatcher {
+public:
+  EventDispatcher(PhysicalSocketServer *ss) : ss_(ss) {
+    if (hev_ = WSACreateEvent()) {
+      ss_->Add(this);
+    }
+  }
+
+  ~EventDispatcher() {
+    if (hev_ != NULL) {
+      ss_->Remove(this);
+      WSACloseEvent(hev_);
+      hev_ = NULL;
+    }
+  }
+  
+  virtual void Signal() {
+    if (hev_ != NULL)
+      WSASetEvent(hev_);
+  }
+  
+  virtual uint32 GetRequestedEvents() {
+    return 0;
+  }
+
+  virtual void OnPreEvent(uint32 ff) {
+    WSAResetEvent(hev_);
+  }
+
+  virtual void OnEvent(uint32 ff, int err) {
+  }
+
+  virtual WSAEVENT GetWSAEvent() {
+    return hev_;
+  }
+
+  virtual SOCKET GetSocket() {
+    return INVALID_SOCKET;
+  }
+
+  virtual bool CheckSignalClose() { return false; }
+
+private:
+  PhysicalSocketServer* ss_;
+  WSAEVENT hev_;
+};
+
+class SocketDispatcher : public Dispatcher, public PhysicalSocket {
+public:
+  static int next_id_;
+  int id_;
+  bool signal_close_;
+  int signal_err_;
+
+  SocketDispatcher(PhysicalSocketServer* ss) : PhysicalSocket(ss), id_(0), signal_close_(false) {
+  }
+  SocketDispatcher(SOCKET s, PhysicalSocketServer* ss) : PhysicalSocket(ss, s), id_(0), signal_close_(false) {
+  }
+
+  virtual ~SocketDispatcher() {
+    Close();
+  }
+
+  bool Initialize() {
+    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))
+      return false;
+
+    if (!Initialize())
+      return false;
+
+    do { id_ = ++next_id_; } while (id_ == 0);
+    return true;
+  }
+
+  virtual int Close() {
+    if (s_ == INVALID_SOCKET)
+      return 0;
+
+    id_ = 0;
+    signal_close_ = false;
+    ss_->Remove(this);
+    return PhysicalSocket::Close();
+  }
+
+  virtual uint32 GetRequestedEvents() {
+    return enabled_events_;
+  }
+
+  virtual void OnPreEvent(uint32 ff) {
+    if ((ff & kfConnect) != 0)
+      state_ = CS_CONNECTED;
+  }
+
+  virtual void OnEvent(uint32 ff, int err) {
+    int cache_id = id_;
+    if ((ff & kfRead) != 0) {
+      enabled_events_ &= ~kfRead;
+      SignalReadEvent(this);
+    }
+    if (((ff & kfWrite) != 0) && (id_ == cache_id)) {
+      enabled_events_ &= ~kfWrite;
+      SignalWriteEvent(this);
+    }
+    if (((ff & kfConnect) != 0) && (id_ == cache_id)) {
+      if (ff != kfConnect)
+        LOG(LS_VERBOSE) << "Signalled with kfConnect: " << ff;
+      enabled_events_ &= ~kfConnect;
+      SignalConnectEvent(this);
+    }
+    if (((ff & kfClose) != 0) && (id_ == cache_id)) {
+      //LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] OnClose() Error: " << err;
+      signal_close_ = true;
+      signal_err_ = err;
+    }
+  }
+
+  virtual WSAEVENT GetWSAEvent() {
+    return WSA_INVALID_EVENT;
+  }
+
+  virtual SOCKET GetSocket() {
+    return s_;
+  }
+
+  virtual bool CheckSignalClose() {
+    if (!signal_close_)
+      return false;
+
+    char ch;
+    if (recv(s_, &ch, 1, MSG_PEEK) > 0)
+      return false;
+
+    signal_close_ = false;
+    SignalCloseEvent(this, signal_err_);
+    return true;
+  }
+};
+
+int SocketDispatcher::next_id_ = 0;
+
+#endif // WIN32
+
+// Sets the value of a boolean value to false when signaled.
+class Signaler : public EventDispatcher {
+public:
+  Signaler(PhysicalSocketServer* ss, bool* pf)
+      : EventDispatcher(ss), pf_(pf) {
+  }
+  virtual ~Signaler() { }
+
+  void OnEvent(uint32 ff, int err) {
+    if (pf_)
+      *pf_ = false;
+  }
+
+private:
+  bool *pf_;
+};
+
+PhysicalSocketServer::PhysicalSocketServer() : fWait_(false),
+  last_tick_tracked_(0), last_tick_dispatch_count_(0) {
+  signal_wakeup_ = new Signaler(this, &fWait_);
+}
+
+PhysicalSocketServer::~PhysicalSocketServer() {
+  delete signal_wakeup_;
+  //  ASSERT(dispatchers_.empty());
+}
+
+void PhysicalSocketServer::WakeUp() {
+  signal_wakeup_->Signal();
+}
+
+Socket* PhysicalSocketServer::CreateSocket(int type) {
+  PhysicalSocket* socket = new PhysicalSocket(this);
+  if (socket->Create(type)) {
+    return socket;
+  } else {
+    delete socket;
+    return 0;
+  }
+}
+
+AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int type) {
+  SocketDispatcher* dispatcher = new SocketDispatcher(this);
+  if (dispatcher->Create(type)) {
+    return dispatcher;
+  } else {
+    delete dispatcher;
+    return 0;
+  }
+}
+
+AsyncSocket* PhysicalSocketServer::WrapSocket(SOCKET s) {
+  SocketDispatcher* dispatcher = new SocketDispatcher(s, this);
+  if (dispatcher->Initialize()) {
+    return dispatcher;
+  } else {
+    delete dispatcher;
+    return 0;
+  }
+}
+
+void PhysicalSocketServer::Add(Dispatcher *pdispatcher) {
+  CritScope cs(&crit_);
+  dispatchers_.push_back(pdispatcher);
+}
+
+void PhysicalSocketServer::Remove(Dispatcher *pdispatcher) {
+  CritScope cs(&crit_);
+  dispatchers_.erase(std::remove(dispatchers_.begin(), dispatchers_.end(), pdispatcher), dispatchers_.end());
+}
+
+#ifdef POSIX
+bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
+  // Calculate timing information
+
+  struct timeval *ptvWait = NULL;
+  struct timeval tvWait;
+  struct timeval tvStop;
+  if (cmsWait != kForever) {
+    // Calculate wait timeval
+    tvWait.tv_sec = cmsWait / 1000;
+    tvWait.tv_usec = (cmsWait % 1000) * 1000;
+    ptvWait = &tvWait;
+
+    // Calculate when to return in a timeval
+    gettimeofday(&tvStop, NULL);
+    tvStop.tv_sec += tvWait.tv_sec;
+    tvStop.tv_usec += tvWait.tv_usec;
+    if (tvStop.tv_usec >= 1000000) {
+      tvStop.tv_usec -= 1000000;
+      tvStop.tv_sec += 1;
+    }
+  }
+
+  // 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++) {
+        // Query dispatchers for read and write wait state
+      
+        Dispatcher *pdispatcher = dispatchers_[i];
+        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)
+          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)
+      return true;
+    
+    // We have signaled descriptors
+   
+    {
+      CritScope cr(&crit_);
+      for (unsigned i = 0; i < dispatchers_.size(); i++) {
+        Dispatcher *pdispatcher = dispatchers_[i];
+        int fd = pdispatcher->GetDescriptor();
+        uint32 ff = 0;
+        if (FD_ISSET(fd, &fdsRead)) {
+          FD_CLR(fd, &fdsRead);
+          ff |= kfRead;
+        }
+        if (FD_ISSET(fd, &fdsWrite)) {
+          FD_CLR(fd, &fdsWrite);
+          if (pdispatcher->GetRequestedEvents() & kfConnect) {
+            ff |= kfConnect;
+          } else {
+            ff |= kfWrite;
+          }
+        }
+        if (ff != 0) {
+          pdispatcher->OnPreEvent(ff);
+          pdispatcher->OnEvent(ff, 0);
+        }
+      }
+    }
+
+    // Recalc the time remaining to wait. Doing it here means it doesn't get
+    // calced twice the first time through the loop
+
+    if (cmsWait != kForever) {
+      ptvWait->tv_sec = 0;
+      ptvWait->tv_usec = 0;
+      struct timeval tvT;
+      gettimeofday(&tvT, NULL);
+      if (tvStop.tv_sec >= tvT.tv_sec) {
+        ptvWait->tv_sec = tvStop.tv_sec - tvT.tv_sec;
+        ptvWait->tv_usec = tvStop.tv_usec - tvT.tv_usec;
+        if (ptvWait->tv_usec < 0) {
+          ptvWait->tv_usec += 1000000;
+          ptvWait->tv_sec -= 1;
+        }
+      }
+    }
+  }
+        
+  return true;
+}
+#endif // POSIX
+
+#ifdef WIN32
+bool PhysicalSocketServer::Wait(int cmsWait, bool process_io)
+{
+  int cmsTotal = cmsWait;
+  int cmsElapsed = 0;
+  uint32 msStart = GetMillisecondCount();
+
+#if LOGGING
+  if (last_tick_dispatch_count_ == 0) {
+    last_tick_tracked_ = msStart;
+  }
+#endif
+
+  WSAEVENT socket_ev = WSACreateEvent();
+  
+  fWait_ = true;
+  while (fWait_) {
+    std::vector<WSAEVENT> events;
+    std::vector<Dispatcher *> event_owners;
+
+    events.push_back(socket_ev);
+
+    {
+      CritScope cr(&crit_);
+      for (size_t i = 0; i < dispatchers_.size(); ++i) {
+        Dispatcher * disp = dispatchers_[i];
+        if (!process_io && (disp != signal_wakeup_))
+          continue;
+        SOCKET s = disp->GetSocket();
+        if (disp->CheckSignalClose()) {
+          // We just signalled close, don't poll this socket
+        } else if (s != INVALID_SOCKET) {
+          WSAEventSelect(s, events[0], FlagsToEvents(disp->GetRequestedEvents()));
+        } else {
+          events.push_back(disp->GetWSAEvent());
+          event_owners.push_back(disp);
+        }
+      }
+    }
+
+    // Which is shorter, the delay wait or the asked wait?
+
+    int cmsNext;
+    if (cmsWait == kForever) {
+      cmsNext = cmsWait;
+    } else {
+      cmsNext = cmsTotal - cmsElapsed;
+      if (cmsNext < 0)
+        cmsNext = 0;
+    }
+
+    // Wait for one of the events to signal
+    DWORD dw = WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()), &events[0], false, cmsNext, false);
+
+#if 0  // LOGGING
+    // 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";
+
+      // 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;
+      last_tick_dispatch_count_ = 0;
+    }
+#endif
+
+    // Failed?
+    // todo: need a better strategy than this!
+
+    if (dw == WSA_WAIT_FAILED) {
+      int error = WSAGetLastError();
+      assert(false);
+      WSACloseEvent(socket_ev);
+      return false;
+    }
+
+    // Timeout?
+
+    if (dw == WSA_WAIT_TIMEOUT) {
+      WSACloseEvent(socket_ev);
+      return true;
+    }
+
+    // Figure out which one it is and call it
+
+    {
+      CritScope cr(&crit_);
+      int index = dw - WSA_WAIT_EVENT_0;
+      if (index > 0) {
+        --index; // The first event is the socket event
+        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];
+          SOCKET s = disp->GetSocket();
+          if (s == INVALID_SOCKET)
+            continue;
+
+          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) {
+                LOG(WARNING) << "PhysicalSocketServer got FD_READ_BIT error " << wsaEvents.iErrorCode[FD_READ_BIT];
+              }
+              if ((wsaEvents.lNetworkEvents & FD_WRITE) && wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
+                LOG(WARNING) << "PhysicalSocketServer got FD_WRITE_BIT error " << wsaEvents.iErrorCode[FD_WRITE_BIT];
+              }
+              if ((wsaEvents.lNetworkEvents & FD_CONNECT) && wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
+                LOG(WARNING) << "PhysicalSocketServer got FD_CONNECT_BIT error " << wsaEvents.iErrorCode[FD_CONNECT_BIT];
+              }
+              if ((wsaEvents.lNetworkEvents & FD_ACCEPT) && wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
+                LOG(WARNING) << "PhysicalSocketServer got FD_ACCEPT_BIT error " << wsaEvents.iErrorCode[FD_ACCEPT_BIT];
+              }
+              if ((wsaEvents.lNetworkEvents & FD_CLOSE) && wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
+                LOG(WARNING) << "PhysicalSocketServer got FD_CLOSE_BIT error " << wsaEvents.iErrorCode[FD_CLOSE_BIT];
+              }
+            }
+#endif
+            uint32 ff = 0;
+            int errcode = 0;
+            if (wsaEvents.lNetworkEvents & FD_READ)
+              ff |= kfRead;
+            if (wsaEvents.lNetworkEvents & FD_WRITE)
+              ff |= kfWrite;
+            if (wsaEvents.lNetworkEvents & FD_CONNECT) {
+              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; 
+                errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
+              }
+            }
+            if (wsaEvents.lNetworkEvents & FD_ACCEPT)
+              ff |= kfRead;
+            if (wsaEvents.lNetworkEvents & FD_CLOSE) {
+              ff |= kfClose;
+              errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
+            }
+            if (ff != 0) {
+              disp->OnPreEvent(ff);
+              disp->OnEvent(ff, errcode);
+            }
+          }
+        }
+      }
+
+      // Reset the network event until new activity occurs
+      WSAResetEvent(socket_ev);
+    }
+
+    // Break?
+
+    if (!fWait_)
+      break;
+    cmsElapsed = GetMillisecondCount() - msStart;
+    if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
+       break;
+    }
+  }
+  
+  // Done
+  
+  WSACloseEvent(socket_ev);
+  return true;
+}
+#endif // WIN32
+
+} // namespace talk_base
diff --git a/talk/base/physicalsocketserver.h b/talk/base/physicalsocketserver.h
new file mode 100755
index 0000000..cc2e707
--- /dev/null
+++ b/talk/base/physicalsocketserver.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 TALK_BASE_PHYSICALSOCKETSERVER_H__
+#define TALK_BASE_PHYSICALSOCKETSERVER_H__
+
+#include <vector>
+
+#include "talk/base/asyncfile.h"
+#include "talk/base/socketserver.h"
+#include "talk/base/criticalsection.h"
+
+#ifdef POSIX
+typedef int SOCKET;
+#endif // POSIX
+
+namespace talk_base { 
+
+class Dispatcher;
+class Signaler;
+
+// A socket server that provides the real sockets of the underlying OS.
+class PhysicalSocketServer : public SocketServer {
+public:
+  PhysicalSocketServer();
+  virtual ~PhysicalSocketServer();
+
+  // SocketFactory:
+  virtual Socket* CreateSocket(int type);
+  virtual AsyncSocket* CreateAsyncSocket(int type);
+
+  // Internal Factory for Accept
+  AsyncSocket* WrapSocket(SOCKET s);
+
+  // SocketServer:
+  virtual bool Wait(int cms, bool process_io);
+  virtual void WakeUp();
+
+  void Add(Dispatcher* dispatcher);
+  void Remove(Dispatcher* dispatcher);
+
+#ifdef POSIX
+  AsyncFile* CreateFile(int fd);
+#endif
+
+private:
+  std::vector<Dispatcher*> dispatchers_;
+  Signaler* signal_wakeup_;
+  CriticalSection crit_;
+  bool fWait_;
+  uint32 last_tick_tracked_;
+  int last_tick_dispatch_count_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_PHYSICALSOCKETSERVER_H__
diff --git a/talk/base/proxydetect.cc b/talk/base/proxydetect.cc
new file mode 100755
index 0000000..04a9c61
--- /dev/null
+++ b/talk/base/proxydetect.cc
@@ -0,0 +1,827 @@
+// TODO: Abstract this better for cross-platformability
+
+#ifdef _WINDOWS
+#include "talk/base/win32.h"
+#include <shlobj.h>
+#endif
+
+#include "talk/base/httpcommon.h"
+#include "talk/base/httpcommon-inl.h"
+#include "talk/base/proxydetect.h"
+#include "talk/base/stringutils.h"
+#include "talk/base/basicdefs.h"
+
+#if _WINDOWS
+#define _TRY_FIREFOX 1
+#define _TRY_WINHTTP 1
+#define _TRY_JSPROXY 0
+#define _TRY_WM_FINDPROXY 0
+#define _TRY_IE_LAN_SETTINGS 1
+#endif // _WINDOWS
+
+#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
+} WINHTTP_PROXY_INFO, * LPWINHTTP_PROXY_INFO;
+
+typedef struct {
+    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;
+} 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
+);
+
+} // extern "C"
+
+#define WINHTTP_AUTOPROXY_AUTO_DETECT           0x00000001
+#define WINHTTP_AUTOPROXY_CONFIG_URL            0x00000002
+#define WINHTTP_AUTOPROXY_RUN_INPROCESS         0x00010000
+#define WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY   0x00020000
+#define WINHTTP_AUTO_DETECT_TYPE_DHCP           0x00000001
+#define WINHTTP_AUTO_DETECT_TYPE_DNS_A          0x00000002
+#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY               0
+#define WINHTTP_ACCESS_TYPE_NO_PROXY                    1
+#define WINHTTP_ACCESS_TYPE_NAMED_PROXY                 3
+#define WINHTTP_NO_PROXY_NAME     NULL
+#define WINHTTP_NO_PROXY_BYPASS   NULL
+
+#endif // _TRY_WINHTTP
+
+#if _TRY_JSPROXY
+extern "C" {
+typedef BOOL (STDAPICALLTYPE * pfnInternetGetProxyInfo)
+(
+    LPCSTR lpszUrl,
+    DWORD dwUrlLength,
+    LPSTR lpszUrlHostName,
+    DWORD dwUrlHostNameLength,
+    LPSTR * lplpszProxyHostName,
+    LPDWORD lpdwProxyHostNameLength
+  );
+} // extern "C"
+#endif // _TRY_JSPROXY
+
+#if _TRY_WM_FINDPROXY
+#include <comutil.h>
+#include <wmnetsourcecreator.h>
+#include <wmsinternaladminnetsource.h>
+#endif // _TRY_WM_FINDPROXY
+
+#if _TRY_IE_LAN_SETTINGS
+#include <wininet.h>
+#include <string>
+#endif // _TRY_IE_LAN_SETTINGS
+
+using namespace talk_base;
+
+//////////////////////////////////////////////////////////////////////
+// Utility Functions
+//////////////////////////////////////////////////////////////////////
+
+#ifdef _WINDOWS
+#ifdef _UNICODE
+
+typedef std::wstring tstring;
+std::string Utf8String(const tstring& str) { return ToUtf8(str); }
+
+#else  // !_UNICODE
+
+typedef std::string tstring;
+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;
+}
+
+bool ProxyItemMatch(const Url<char>& url, char * item, size_t len) {
+  // hostname:443
+  if (char * port = strchr(item, ':')) {
+    *port++ = '\0';
+    if (url.port() != atol(port)) {
+      return false;
+    }
+  }
+
+  // A.B.C.D or A.B.C.D/24
+  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);
+    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());
+    return !addr.IsUnresolved() && ((addr.ip() & mask) == (ip & mask));
+  }
+
+  // .foo.com
+  if (*item == '.') {
+    size_t hostlen = url.server().length();
+    return (hostlen > len)
+      && (stricmp(url.server().c_str() + (hostlen - len), item) == 0);
+  }
+
+  // localhost or www.*.com
+  if (!WildMatch(url.server().c_str(), item))
+    return false;
+
+  return true;
+}
+
+bool ProxyListMatch(const Url<char>& url, const std::string& slist, char sep) {
+  const size_t BUFSIZE = 256;
+  char buffer[BUFSIZE];
+  const char* list = slist.c_str();
+  while (*list) {
+    // Remove leading space
+    if (isspace(*list)) {
+      ++list;
+      continue;
+    }
+    // Break on separator
+    size_t len;
+    const char * start = list;
+    if (const char * end = strchr(list, sep)) {
+      len = (end - list);
+      list += len + 1;
+    } else {
+      len = strlen(list);
+      list += len;
+    }
+    // Remove trailing space
+    while ((len > 0) && isspace(start[len-1]))
+      --len;
+    // Check for oversized entry
+    if (len >= BUFSIZE)
+      continue;
+    memcpy(buffer, start, len);
+    buffer[len] = 0;
+    if (!ProxyItemMatch(url, buffer, len))
+      continue;
+    return true;
+  }
+  return false;
+}
+
+bool Better(ProxyType lhs, const ProxyType rhs) {
+  // PROXY_NONE, PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN
+  const int PROXY_VALUE[4] = { 0, 2, 3, 1 };
+  return (PROXY_VALUE[lhs] > PROXY_VALUE[rhs]);
+}
+
+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";
+
+  ProxyType ptype;
+  std::string host;
+  uint16 port;
+
+  const char* address = saddress.c_str();
+  while (*address) {
+    size_t len;
+    const char * start = address;
+    if (const char * sep = strchr(address, kAddressSeparator)) {
+      len = (sep - address);
+      address += len + 1;
+      while (strchr(kAddressSeparator, *address)) {
+        address += 1;
+      }
+    } else {
+      len = strlen(address);
+      address += len;
+    }
+
+    if (len > kMaxAddressLength - 1) {
+      LOG(LS_WARNING) << "Proxy address too long [" << start << "]";
+      continue;
+    }
+
+    char buffer[kMaxAddressLength];
+    memcpy(buffer, start, len);
+    buffer[len] = 0;
+
+    char * colon = strchr(buffer, ':');
+    if (!colon) {
+      LOG(LS_WARNING) << "Proxy address without port [" << buffer << "]";
+      continue;
+    }
+
+    *colon = 0;
+    char * endptr;
+    port = static_cast<uint16>(strtol(colon + 1, &endptr, 0));
+    if (*endptr != 0) {
+      LOG(LS_WARNING) << "Proxy address with invalid port [" << buffer << "]";
+      continue;
+    }
+
+    if (char * equals = strchr(buffer, '=')) {
+      *equals = 0;
+      host = equals + 1;
+      if (_stricmp(buffer, "socks") == 0) {
+        ptype = PROXY_SOCKS5;
+      } else if (_stricmp(buffer, "https") == 0) {
+        ptype = PROXY_HTTPS;
+      } else {
+        LOG(LS_WARNING) << "Proxy address with unknown protocol ["
+                        << buffer << "]";
+        ptype = PROXY_UNKNOWN;
+      }
+    } else {
+      host = buffer;
+      ptype = PROXY_UNKNOWN;
+    }
+
+    if (Better(ptype, proxy.type)) {
+      proxy.type = ptype;
+      proxy.address.SetIP(host);
+      proxy.address.SetPort((int)port);
+    }
+  }
+
+  return (proxy.type != PROXY_NONE);
+}
+
+#if _WINDOWS
+bool IsDefaultBrowserFirefox() {
+  HKEY key;
+  LONG result = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"http\\shell\\open\\command",
+                             0, KEY_READ, &key);
+  if (ERROR_SUCCESS != result)
+    return false;
+
+  wchar_t* value = NULL;
+  DWORD size, type;
+  result = RegQueryValueEx(key, L"", 0, &type, NULL, &size);
+  if (REG_SZ != type) {
+    result = ERROR_ACCESS_DENIED;  // Any error is fine
+  } else if (ERROR_SUCCESS == result) {
+    value = new wchar_t[size+1];
+    BYTE* buffer = reinterpret_cast<BYTE*>(value);
+    result = RegQueryValueEx(key, L"", 0, &type, buffer, &size);
+  }
+  RegCloseKey(key);
+
+  bool success = false;
+  if (ERROR_SUCCESS == result) {
+    value[size] = L'\0';
+    for (size_t i=0; i<size; ++i) {
+      value[i] = tolowercase(value[i]);
+    }
+    success = (NULL != strstr(value, L"firefox.exe"));
+  }
+  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)
+    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();
+      }
+      candidate.append(ToUtf16(buffer + 5));
+      candidate.append(L"\\");
+    } else if (strnicmp(buffer, "Default=", 8) == 0) {
+      if ((buffer[8] != '0') && !candidate.empty()) {
+        break;
+      }
+    }
+  }
+  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
+
+  return success;
+}
+#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;
+        }
+      }
+      if (complete) { // Otherwise fall through to IE autoproxy code
+        return success;
+      }
+    }
+  }
+#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;
+}
diff --git a/talk/base/proxydetect.h b/talk/base/proxydetect.h
new file mode 100755
index 0000000..3de2598
--- /dev/null
+++ b/talk/base/proxydetect.h
@@ -0,0 +1,13 @@
+#ifndef _PROXYDETECT_H_
+#define _PROXYDETECT_H_
+
+#include "talk/base/proxyinfo.h"
+
+// 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.
+
+bool GetProxySettingsForUrl(const char* agent, const char* url,
+                            talk_base::ProxyInfo& proxy,
+                            bool long_operation = false);
+
+#endif // _PROXYDETECT_H_
diff --git a/talk/base/proxyinfo.cc b/talk/base/proxyinfo.cc
new file mode 100755
index 0000000..1d9c588
--- /dev/null
+++ b/talk/base/proxyinfo.cc
@@ -0,0 +1,37 @@
+/*
+ * 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/proxyinfo.h"
+
+namespace talk_base {
+
+const char * ProxyToString(ProxyType proxy) {
+  const char * const PROXY_NAMES[] = { "none", "https", "socks5", "unknown" };
+  return PROXY_NAMES[proxy];
+}
+
+} // namespace talk_base
diff --git a/talk/base/proxyinfo.h b/talk/base/proxyinfo.h
new file mode 100755
index 0000000..834ec4f
--- /dev/null
+++ b/talk/base/proxyinfo.h
@@ -0,0 +1,51 @@
+/*
+ * 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_PROXYINFO_H__
+#define TALK_BASE_PROXYINFO_H__
+
+#include <string>
+#include "talk/base/socketaddress.h"
+#include "talk/base/cryptstring.h"
+
+namespace talk_base {
+
+enum ProxyType { PROXY_NONE, PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN };
+const char * ProxyToString(ProxyType proxy);
+
+struct ProxyInfo {
+  ProxyType type;
+  SocketAddress address;
+  std::string username;
+  CryptString password;
+
+  ProxyInfo() : type(PROXY_NONE) { }
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_PROXYINFO_H__
diff --git a/talk/base/schanneladapter.cc b/talk/base/schanneladapter.cc
new file mode 100755
index 0000000..d971c7e
--- /dev/null
+++ b/talk/base/schanneladapter.cc
@@ -0,0 +1,749 @@
+/*
+ * 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"
+#define SECURITY_WIN32
+#include <security.h>
+#include <schannel.h>
+
+#include <iomanip>
+#include <vector>
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/schanneladapter.h"
+#include "talk/base/sec_buffer.h"
+#include "talk/base/thread.h"
+
+namespace talk_base {
+
+/////////////////////////////////////////////////////////////////////////////
+// SChannelAdapter
+/////////////////////////////////////////////////////////////////////////////
+
+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
+  KLABEL(SECBUFFER_TOKEN),              //  2
+  KLABEL(SECBUFFER_PKG_PARAMS),         //  3
+  KLABEL(SECBUFFER_MISSING),            //  4
+  KLABEL(SECBUFFER_EXTRA),              //  5
+  KLABEL(SECBUFFER_STREAM_TRAILER),     //  6
+  KLABEL(SECBUFFER_STREAM_HEADER),      //  7
+  KLABEL(SECBUFFER_MECHLIST),           // 11
+  KLABEL(SECBUFFER_MECHLIST_SIGNATURE), // 12
+  KLABEL(SECBUFFER_TARGET),             // 13
+  KLABEL(SECBUFFER_CHANNEL_BINDINGS),   // 14
+  LASTLABEL
+};
+
+void DescribeBuffer(LoggingSeverity severity, const char* prefix,
+                    const SecBuffer& sb) {
+  LOG_V(severity) 
+    << prefix
+    << "(" << sb.cbBuffer
+    << ", " << FindLabel(sb.BufferType & ~SECBUFFER_ATTRMASK,
+                          SCHANNEL_BUFFER_TYPES)
+    << ", " << sb.pvBuffer << ")";
+}
+
+void DescribeBuffers(LoggingSeverity severity, const char* prefix,
+                     const SecBufferDesc* sbd) {
+  if (!LOG_CHECK_LEVEL_V(severity))
+    return;
+  LOG_V(severity) << prefix << "(";
+  for (size_t i=0; i<sbd->cBuffers; ++i) {
+    DescribeBuffer(severity, "  ", sbd->pBuffers[i]);
+  }
+  LOG_V(severity) << ")";
+}
+
+const ULONG SSL_FLAGS_DEFAULT = ISC_REQ_ALLOCATE_MEMORY
+                              | ISC_REQ_CONFIDENTIALITY
+                              | ISC_REQ_EXTENDED_ERROR
+                              | ISC_REQ_INTEGRITY
+                              | ISC_REQ_REPLAY_DETECT
+                              | ISC_REQ_SEQUENCE_DETECT
+                              | ISC_REQ_STREAM;
+                              //| ISC_REQ_USE_SUPPLIED_CREDS;
+
+typedef std::vector<char> SChannelBuffer;
+
+struct SChannelAdapter::SSLImpl {
+  CredHandle cred;
+  CtxtHandle ctx;
+  bool cred_init, ctx_init;
+  SChannelBuffer inbuf, outbuf, readable;
+  SecPkgContext_StreamSizes sizes;
+
+  SSLImpl() : cred_init(false), ctx_init(false) { }
+};
+
+SChannelAdapter::SChannelAdapter(AsyncSocket* socket)
+  : SSLAdapter(socket), state_(SSL_NONE),
+    restartable_(false), signal_close_(false), message_pending_(false),
+    impl_(new SSLImpl) {
+}
+
+SChannelAdapter::~SChannelAdapter() {
+  Cleanup();
+}
+
+int
+SChannelAdapter::StartSSL(const char* hostname, bool restartable) {
+  if (state_ != SSL_NONE)
+    return ERROR_ALREADY_INITIALIZED;
+
+  ssl_host_name_ = hostname;
+  restartable_ = restartable;
+
+  if (socket_->GetState() != Socket::CS_CONNECTED) {
+    state_ = SSL_WAIT;
+    return 0;
+  }
+
+  state_ = SSL_CONNECTING;
+  if (int err = BeginSSL()) {
+    Error("BeginSSL", err, false);
+    return err;
+  }
+
+  return 0;
+}
+
+int
+SChannelAdapter::BeginSSL() {
+  LOG(LS_VERBOSE) << "BeginSSL: " << ssl_host_name_;
+  ASSERT(state_ == SSL_CONNECTING);
+
+  SECURITY_STATUS ret;
+
+  SCHANNEL_CRED sc_cred = { 0 };
+  sc_cred.dwVersion = SCHANNEL_CRED_VERSION;
+  //sc_cred.dwMinimumCipherStrength = 128; // Note: use system default
+  sc_cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_AUTO_CRED_VALIDATION;
+
+  ret = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
+                                 &sc_cred, NULL, NULL, &impl_->cred, NULL);
+  if (ret != SEC_E_OK) {
+    LOG(LS_ERROR) << "AcquireCredentialsHandle error: "
+                  << ErrorName(ret, SECURITY_ERRORS);
+    return ret;
+  }
+  impl_->cred_init = true;
+
+  if (LOG_CHECK_LEVEL(LS_VERBOSE)) {
+    SecPkgCred_CipherStrengths cipher_strengths = { 0 };
+    ret = QueryCredentialsAttributes(&impl_->cred,
+                                     SECPKG_ATTR_CIPHER_STRENGTHS,
+                                     &cipher_strengths);
+    if (SUCCEEDED(ret)) {
+      LOG(LS_VERBOSE) << "SChannel cipher strength: "
+                  << cipher_strengths.dwMinimumCipherStrength << " - "
+                  << cipher_strengths.dwMaximumCipherStrength;
+    }
+
+    SecPkgCred_SupportedAlgs supported_algs = { 0 };
+    ret = QueryCredentialsAttributes(&impl_->cred,
+                                     SECPKG_ATTR_SUPPORTED_ALGS,
+                                     &supported_algs);
+    if (SUCCEEDED(ret)) {
+      LOG(LS_VERBOSE) << "SChannel supported algorithms:";
+      for (DWORD i=0; i<supported_algs.cSupportedAlgs; ++i) {
+        ALG_ID alg_id = supported_algs.palgSupportedAlgs[i];
+        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 << ")";
+      }
+    }
+  }
+
+  ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0;
+  if (ignore_bad_cert())
+    flags |= ISC_REQ_MANUAL_CRED_VALIDATION;
+
+  CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out;
+  ret = InitializeSecurityContextA(&impl_->cred, NULL,
+                                   const_cast<char*>(ssl_host_name_.c_str()),
+                                   flags, 0, 0, NULL, 0,
+                                   &impl_->ctx, sb_out.desc(),
+                                   &ret_flags, NULL);
+  if (SUCCEEDED(ret))
+    impl_->ctx_init = true;
+  return ProcessContext(ret, NULL, sb_out.desc());
+}
+
+int
+SChannelAdapter::ContinueSSL() {
+  LOG(LS_VERBOSE) << "ContinueSSL";
+  ASSERT(state_ == SSL_CONNECTING);
+
+  SECURITY_STATUS ret;
+
+  CSecBufferBundle<2> sb_in;
+  sb_in[0].BufferType = SECBUFFER_TOKEN;
+  sb_in[0].cbBuffer = static_cast<unsigned long>(impl_->inbuf.size());
+  sb_in[0].pvBuffer = &impl_->inbuf[0];
+  //DescribeBuffers(LS_VERBOSE, "Input Buffer ", sb_in.desc());
+
+  ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0;
+  if (ignore_bad_cert())
+    flags |= ISC_REQ_MANUAL_CRED_VALIDATION;
+
+  CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out;
+  ret = InitializeSecurityContextA(&impl_->cred, &impl_->ctx,
+                                   const_cast<char*>(ssl_host_name_.c_str()),
+                                   flags, 0, 0, sb_in.desc(), 0,
+                                   NULL, sb_out.desc(),
+                                   &ret_flags, NULL);
+  return ProcessContext(ret, sb_in.desc(), sb_out.desc());
+}
+
+int
+SChannelAdapter::ProcessContext(long int status, _SecBufferDesc* sbd_in,
+                                _SecBufferDesc* sbd_out) {
+  LoggingSeverity level = LS_ERROR;
+  if ((status == SEC_E_OK)
+      || (status != SEC_I_CONTINUE_NEEDED)
+      || (status != SEC_E_INCOMPLETE_MESSAGE)) {
+    level = LS_VERBOSE;  // Expected messages
+  }
+  LOG_V(level) 
+    << "InitializeSecurityContext error: "
+    << ErrorName(status, SECURITY_ERRORS);
+  //if (sbd_in)
+  //  DescribeBuffers(LS_VERBOSE, "Input Buffer ", sbd_in);
+  //if (sbd_out)
+  //  DescribeBuffers(LS_VERBOSE, "Output Buffer ", sbd_out);
+
+  if (status == SEC_E_INCOMPLETE_MESSAGE) {
+    // 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.
+    return status;
+  }
+
+  // Note: we check both input and output buffers for SECBUFFER_EXTRA.
+  // Experience shows it appearing in the input, but the documentation claims
+  // it should appear in the output.
+  size_t extra = 0;
+  if (sbd_in) {
+    for (size_t i=0; i<sbd_in->cBuffers; ++i) {
+      SecBuffer& buffer = sbd_in->pBuffers[i];
+      if (buffer.BufferType == SECBUFFER_EXTRA) {
+        extra += buffer.cbBuffer;
+      }
+    }
+  }
+  if (sbd_out) {
+    for (size_t i=0; i<sbd_out->cBuffers; ++i) {
+      SecBuffer& buffer = sbd_out->pBuffers[i];
+      if (buffer.BufferType == SECBUFFER_EXTRA) {
+        extra += buffer.cbBuffer;
+      } else if (buffer.BufferType == SECBUFFER_TOKEN) {
+        impl_->outbuf.insert(impl_->outbuf.end(),
+          reinterpret_cast<char*>(buffer.pvBuffer),
+          reinterpret_cast<char*>(buffer.pvBuffer) + buffer.cbBuffer);
+      }
+    }
+  }
+
+  if (extra) {
+    ASSERT(extra <= impl_->inbuf.size());
+    size_t consumed = impl_->inbuf.size() - extra;
+    memmove(&impl_->inbuf[0], &impl_->inbuf[consumed], extra);
+    impl_->inbuf.resize(extra);
+  } else {
+    impl_->inbuf.clear();
+  }
+
+  if (SEC_I_CONTINUE_NEEDED == status) {
+    // Send data to server and wait for response.
+    // Note: ContinueSSL will result in a Flush, anyway.
+    return impl_->inbuf.empty() ? Flush() : ContinueSSL();
+  }
+
+  if (SEC_E_OK == status) {
+    LOG(LS_VERBOSE) << "QueryContextAttributes";
+    status = QueryContextAttributes(&impl_->ctx, SECPKG_ATTR_STREAM_SIZES,
+                                    &impl_->sizes);
+    if (FAILED(status)) {
+      LOG(LS_ERROR) << "QueryContextAttributes error: "
+                    << ErrorName(status, SECURITY_ERRORS);
+      return status;
+    }
+
+    state_ = SSL_CONNECTED;
+
+    if (int err = DecryptData()) {
+      return err;
+    } else if (int err = Flush()) {
+      return err;
+    } else {
+      // If we decrypted any data, queue up a notification here
+      PostEvent();
+      // Signal our connectedness
+      AsyncSocketAdapter::OnConnectEvent(this);
+    }
+    return 0;
+  }
+
+  if (SEC_I_INCOMPLETE_CREDENTIALS == status) {
+    // We don't support client authentication in schannel.
+    return status;
+  }
+
+  // We don't expect any other codes
+  ASSERT(false);
+  return status;
+}
+
+int
+SChannelAdapter::DecryptData() {
+  SChannelBuffer& inbuf = impl_->inbuf;
+  SChannelBuffer& readable = impl_->readable;
+
+  while (!inbuf.empty()) {
+    CSecBufferBundle<4> in_buf;
+    in_buf[0].BufferType = SECBUFFER_DATA;
+    in_buf[0].cbBuffer = static_cast<unsigned long>(inbuf.size());
+    in_buf[0].pvBuffer = &inbuf[0];
+
+    //DescribeBuffers(LS_VERBOSE, "Decrypt In ", in_buf.desc());
+    SECURITY_STATUS status = DecryptMessage(&impl_->ctx, in_buf.desc(), 0, 0);
+    //DescribeBuffers(LS_VERBOSE, "Decrypt Out ", in_buf.desc());
+
+    // Note: We are explicitly treating SEC_E_OK, SEC_I_CONTEXT_EXPIRED, and
+    // any other successful results as continue.
+    if (SUCCEEDED(status)) {
+      size_t data_len = 0, extra_len = 0;
+      for (size_t i=0; i<in_buf.desc()->cBuffers; ++i) {
+        if (in_buf[i].BufferType == SECBUFFER_DATA) {
+          data_len += in_buf[i].cbBuffer;
+          readable.insert(readable.end(),
+            reinterpret_cast<char*>(in_buf[i].pvBuffer),
+            reinterpret_cast<char*>(in_buf[i].pvBuffer) + in_buf[i].cbBuffer);
+        } else if (in_buf[i].BufferType == SECBUFFER_EXTRA) {
+          extra_len += in_buf[i].cbBuffer;
+        }
+      }
+      // There is a bug on Win2K where SEC_I_CONTEXT_EXPIRED is misclassified.
+      if ((data_len == 0) && (inbuf[0] == 0x15)) {
+        status = SEC_I_CONTEXT_EXPIRED;
+      }
+      if (extra_len) {
+        size_t consumed = inbuf.size() - extra_len;
+        memmove(&inbuf[0], &inbuf[consumed], extra_len);
+        inbuf.resize(extra_len);
+      } else {
+        inbuf.clear();
+      }
+      // TODO: Handle SEC_I_CONTEXT_EXPIRED to do clean shutdown
+      if (status != SEC_E_OK) {
+        LOG(LS_INFO) << "DecryptMessage returned continuation code: "
+                      << ErrorName(status, SECURITY_ERRORS);
+      }
+      continue;
+    }
+    
+    if (status == SEC_E_INCOMPLETE_MESSAGE) {
+      break;
+    } else {
+      return status;
+    }
+  }
+
+  return 0;
+}
+
+void
+SChannelAdapter::Cleanup() {
+  if (impl_->ctx_init)
+    DeleteSecurityContext(&impl_->ctx);
+  if (impl_->cred_init)
+    FreeCredentialsHandle(&impl_->cred);
+  delete impl_;
+}
+
+void
+SChannelAdapter::PostEvent() {
+  // Check if there's anything notable to signal
+  if (impl_->readable.empty() && !signal_close_)
+    return;
+
+  // Only one post in the queue at a time
+  if (message_pending_)
+    return;
+
+  if (Thread* thread = Thread::Current()) {
+    message_pending_ = true;
+    thread->Post(this);
+  } else {
+    LOG(LS_ERROR) << "No thread context available for SChannelAdapter";
+    ASSERT(false);
+  }
+}
+
+void
+SChannelAdapter::Error(const char* context, int err, bool signal) {
+  LOG(LS_WARNING) << "SChannelAdapter::Error("
+                  << context << ", "
+                  << ErrorName(err, SECURITY_ERRORS) << ")";
+  state_ = SSL_ERROR;
+  SetError(err);
+  if (signal)
+    AsyncSocketAdapter::OnCloseEvent(this, err);
+}
+
+int
+SChannelAdapter::Read() {
+  char buffer[4096];
+  SChannelBuffer& inbuf = impl_->inbuf;
+  while (true) {
+    int ret = AsyncSocketAdapter::Recv(buffer, sizeof(buffer));
+    if (ret > 0) {
+      inbuf.insert(inbuf.end(), buffer, buffer + ret);
+    } else if (GetError() == EWOULDBLOCK) {
+      return 0;  // Blocking
+    } else {
+      return GetError();
+    }
+  }
+}
+
+int
+SChannelAdapter::Flush() {
+  int result = 0;
+  size_t pos = 0;
+  SChannelBuffer& outbuf = impl_->outbuf;
+  while (pos < outbuf.size()) {
+    int sent = AsyncSocketAdapter::Send(&outbuf[pos], outbuf.size() - pos);
+    if (sent > 0) {
+      pos += sent;
+    } else if (GetError() == EWOULDBLOCK) {
+      break;  // Blocking
+    } else {
+      result = GetError();
+      break;
+    }
+  }
+  if (int remainder = outbuf.size() - pos) {
+    memmove(&outbuf[0], &outbuf[pos], remainder);
+    outbuf.resize(remainder);
+  } else {
+    outbuf.clear();
+  }
+  return result;
+}
+
+//
+// AsyncSocket Implementation
+//
+
+int
+SChannelAdapter::Send(const void* pv, size_t cb) {
+  switch (state_) {
+  case SSL_NONE:
+    return AsyncSocketAdapter::Send(pv, cb);
+
+  case SSL_WAIT:
+  case SSL_CONNECTING:
+    SetError(EWOULDBLOCK);
+    return SOCKET_ERROR;
+
+  case SSL_CONNECTED:
+    break;
+
+  case SSL_ERROR:
+  default:
+    return SOCKET_ERROR;
+  }
+
+  size_t written = 0;
+  SChannelBuffer& outbuf = impl_->outbuf;
+  while (written < cb) {
+    const size_t encrypt_len = std::min<size_t>(cb - written,
+                                                impl_->sizes.cbMaximumMessage);
+
+    CSecBufferBundle<4> out_buf;
+    out_buf[0].BufferType = SECBUFFER_STREAM_HEADER;
+    out_buf[0].cbBuffer = impl_->sizes.cbHeader;
+    out_buf[1].BufferType = SECBUFFER_DATA;
+    out_buf[1].cbBuffer = static_cast<unsigned long>(encrypt_len);
+    out_buf[2].BufferType = SECBUFFER_STREAM_TRAILER;
+    out_buf[2].cbBuffer = impl_->sizes.cbTrailer;
+
+    size_t packet_len = out_buf[0].cbBuffer
+                      + out_buf[1].cbBuffer
+                      + out_buf[2].cbBuffer;
+
+    SChannelBuffer message;
+    message.resize(packet_len);
+    out_buf[0].pvBuffer = &message[0];
+    out_buf[1].pvBuffer = &message[out_buf[0].cbBuffer];
+    out_buf[2].pvBuffer = &message[out_buf[0].cbBuffer + out_buf[1].cbBuffer];
+
+    memcpy(out_buf[1].pvBuffer,
+           static_cast<const char*>(pv) + written,
+           encrypt_len);
+
+    //DescribeBuffers(LS_VERBOSE, "Encrypt In ", out_buf.desc());
+    SECURITY_STATUS res = EncryptMessage(&impl_->ctx, 0, out_buf.desc(), 0);
+    //DescribeBuffers(LS_VERBOSE, "Encrypt Out ", out_buf.desc());
+
+    if (FAILED(res)) {
+      Error("EncryptMessage", res, false);
+      return SOCKET_ERROR;
+    }
+
+    // We assume that the header and data segments do not change length,
+    // or else encrypting the concatenated packet in-place is wrong.
+    ASSERT(out_buf[0].cbBuffer == impl_->sizes.cbHeader);
+    ASSERT(out_buf[1].cbBuffer == static_cast<unsigned long>(encrypt_len));
+
+    // However, the length of the trailer may change due to padding.
+    ASSERT(out_buf[2].cbBuffer <= impl_->sizes.cbTrailer);
+
+    packet_len = out_buf[0].cbBuffer
+               + out_buf[1].cbBuffer
+               + out_buf[2].cbBuffer;
+
+    written += encrypt_len;
+    outbuf.insert(outbuf.end(), &message[0], &message[packet_len-1]+1);
+  }
+
+  if (int err = Flush()) {
+    state_ = SSL_ERROR;
+    SetError(err);
+    return SOCKET_ERROR;
+  }
+
+  return static_cast<int>(written);
+}
+
+int
+SChannelAdapter::Recv(void* pv, size_t cb) {
+  switch (state_) {
+  case SSL_NONE:
+    return AsyncSocketAdapter::Recv(pv, cb);
+
+  case SSL_WAIT:
+  case SSL_CONNECTING:
+    SetError(EWOULDBLOCK);
+    return SOCKET_ERROR;
+
+  case SSL_CONNECTED:
+    break;
+
+  case SSL_ERROR:
+  default:
+    return SOCKET_ERROR;
+  }
+
+  SChannelBuffer& readable = impl_->readable;
+  if (readable.empty()) {
+    SetError(EWOULDBLOCK);
+    return SOCKET_ERROR;
+  }
+  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);
+    readable.resize(remaining);
+  } else {
+    readable.clear();
+  }
+
+  PostEvent();
+  return static_cast<int>(read);
+}
+
+int
+SChannelAdapter::Close() {
+  if (!impl_->readable.empty()) {
+    LOG(WARNING) << "SChannelAdapter::Close with readable data";
+    // Note: this isn't strictly an error, but we're using it temporarily to
+    // track bugs.
+    //ASSERT(false);
+  }
+  if (state_ == SSL_CONNECTED) {
+    DWORD token = SCHANNEL_SHUTDOWN;
+    CSecBufferBundle<1> sb_in;
+    sb_in[0].BufferType = SECBUFFER_TOKEN;
+    sb_in[0].cbBuffer = sizeof(token);
+    sb_in[0].pvBuffer = &token;
+    ApplyControlToken(&impl_->ctx, sb_in.desc());
+    // TODO: In theory, to do a nice shutdown, we need to begin shutdown
+    // negotiation with more calls to InitializeSecurityContext.  Since the
+    // socket api doesn't support nice shutdown at this point, we don't bother.
+  }
+  Cleanup();
+  impl_ = new SSLImpl;
+  state_ = restartable_ ? SSL_WAIT : SSL_NONE;
+  signal_close_ = false;
+  message_pending_ = false;
+  return AsyncSocketAdapter::Close();
+}
+
+Socket::ConnState
+SChannelAdapter::GetState() const {
+  if (signal_close_)
+    return CS_CONNECTED;
+  ConnState state = socket_->GetState();
+  if ((state == CS_CONNECTED)
+      && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
+    state = CS_CONNECTING;
+  return state;
+}
+
+void
+SChannelAdapter::OnConnectEvent(AsyncSocket* socket) {
+  LOG(LS_VERBOSE) << "SChannelAdapter::OnConnectEvent";
+  if (state_ != SSL_WAIT) {
+    ASSERT(state_ == SSL_NONE);
+    AsyncSocketAdapter::OnConnectEvent(socket);
+    return;
+  }
+
+  state_ = SSL_CONNECTING;
+  if (int err = BeginSSL()) {
+    Error("BeginSSL", err);
+  }
+}
+
+void
+SChannelAdapter::OnReadEvent(AsyncSocket* socket) {
+  if (state_ == SSL_NONE) {
+    AsyncSocketAdapter::OnReadEvent(socket);
+    return;
+  }
+
+  if (int err = Read()) {
+    Error("Read", err);
+    return;
+  }
+
+  if (impl_->inbuf.empty())
+    return;
+
+  if (state_ == SSL_CONNECTED) {
+    if (int err = DecryptData()) {
+      Error("DecryptData", err);
+    } else if (!impl_->readable.empty()) {
+      AsyncSocketAdapter::OnReadEvent(this);
+    }
+  } else if (state_ == SSL_CONNECTING) {
+    if (int err = ContinueSSL()) {
+      Error("ContinueSSL", err);
+    }
+  }
+}
+
+void
+SChannelAdapter::OnWriteEvent(AsyncSocket* socket) {
+  if (state_ == SSL_NONE) {
+    AsyncSocketAdapter::OnWriteEvent(socket);
+    return;
+  }
+
+  if (int err = Flush()) {
+    Error("Flush", err);
+    return;
+  }
+
+  // See if we have more data to write
+  if (!impl_->outbuf.empty())
+    return;
+
+  // Buffer is empty, submit notification
+  if (state_ == SSL_CONNECTED) {
+    AsyncSocketAdapter::OnWriteEvent(socket);
+  }
+}
+
+void
+SChannelAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
+  if ((state_ == SSL_NONE) || impl_->readable.empty()) {
+    AsyncSocketAdapter::OnCloseEvent(socket, err);
+    return;
+  }
+
+  // If readable is non-empty, then we have a pending Message
+  // that will allow us to signal close (eventually).
+  signal_close_ = true;
+}
+
+void
+SChannelAdapter::OnMessage(Message* pmsg) {
+  if (!message_pending_)
+    return;  // This occurs when socket is closed
+
+  message_pending_ = false;
+  if (!impl_->readable.empty()) {
+    AsyncSocketAdapter::OnReadEvent(this);
+  } else if (signal_close_) {
+    signal_close_ = false;
+    AsyncSocketAdapter::OnCloseEvent(this, 0); // TODO: cache this error?
+  }
+}
+
+} // namespace talk_base
diff --git a/talk/base/schanneladapter.h b/talk/base/schanneladapter.h
new file mode 100755
index 0000000..a5ab7b3
--- /dev/null
+++ b/talk/base/schanneladapter.h
@@ -0,0 +1,94 @@
+/*
+ * 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_SCHANNELADAPTER_H__
+#define TALK_BASE_SCHANNELADAPTER_H__
+
+#include <string>
+#include "talk/base/ssladapter.h"
+#include "talk/base/messagequeue.h"
+struct _SecBufferDesc;
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SChannelAdapter : public SSLAdapter, public MessageHandler {
+public:
+  SChannelAdapter(AsyncSocket* socket);
+  virtual ~SChannelAdapter();
+
+  virtual int StartSSL(const char* hostname, bool restartable);
+  virtual int Send(const void* pv, size_t cb);
+  virtual int Recv(void* pv, size_t cb);
+  virtual int Close();
+
+  // Note that the socket returns ST_CONNECTING while SSL is being negotiated.
+  virtual ConnState GetState() const;
+
+protected:
+  enum SSLState {
+    SSL_NONE, SSL_WAIT, SSL_CONNECTING, SSL_CONNECTED, SSL_ERROR
+  };
+  struct SSLImpl;
+
+  virtual void OnConnectEvent(AsyncSocket* socket);
+  virtual void OnReadEvent(AsyncSocket* socket);
+  virtual void OnWriteEvent(AsyncSocket* socket);
+  virtual void OnCloseEvent(AsyncSocket* socket, int err);
+  virtual void OnMessage(Message* pmsg);
+
+  int BeginSSL();
+  int ContinueSSL();
+  int ProcessContext(long int status, _SecBufferDesc* sbd_in,
+                     _SecBufferDesc* sbd_out);
+  int DecryptData();
+
+  int Read();
+  int Flush();
+  void Error(const char* context, int err, bool signal = true);
+  void Cleanup();
+
+  void PostEvent();
+
+private:
+  SSLState state_;
+  std::string ssl_host_name_;
+  // If true, socket will retain SSL configuration after Close.
+  bool restartable_; 
+  // If true, we are delaying signalling close until all data is read.
+  bool signal_close_;
+  // If true, we are waiting to be woken up to signal readability or closure.
+  bool message_pending_;
+  SSLImpl* impl_;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SCHANNELADAPTER_H__
diff --git a/talk/base/scoped_ptr.h b/talk/base/scoped_ptr.h
new file mode 100755
index 0000000..c5e3c5d
--- /dev/null
+++ b/talk/base/scoped_ptr.h
@@ -0,0 +1,259 @@
+//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+//  Copyright (c) 2001, 2002 Peter Dimov
+//
+//  Permission to copy, use, modify, sell and distribute this software
+//  is granted provided this copyright notice appears in all copies.
+//  This software is provided "as is" without express or implied
+//  warranty, and with no claim as to its suitability for any purpose.
+//
+//  See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
+//
+
+//  scoped_ptr mimics a built-in pointer except that it guarantees deletion
+//  of the object pointed to, either on destruction of the scoped_ptr or via
+//  an explicit reset(). scoped_ptr is a simple solution for simple needs;
+//  use shared_ptr or std::auto_ptr if your needs are more complex.
+
+//  scoped_ptr_malloc added in by Google.  When one of
+//  these goes out of scope, instead of doing a delete or delete[], it
+//  calls free().  scoped_ptr_malloc<char> is likely to see much more
+//  use than any other specializations.
+
+//  release() added in by Google. Use this to conditionally
+//  transfer ownership of a heap-allocated object to the caller, usually on
+//  method success.
+#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
+
+#ifdef _WIN32
+namespace std { using ::ptrdiff_t; };
+#endif // _WIN32
+
+namespace talk_base {
+
+template <typename T>
+class scoped_ptr {
+ private:
+
+  T* ptr;
+
+  scoped_ptr(scoped_ptr const &);
+  scoped_ptr & operator=(scoped_ptr const &);
+
+ public:
+
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = 0): ptr(p) {}
+
+  ~scoped_ptr() {
+    typedef char type_must_be_complete[sizeof(T)];
+    delete ptr;
+  }
+
+  void reset(T* p = 0) {
+    typedef char type_must_be_complete[sizeof(T)];
+
+    if (ptr != p) {
+      delete ptr;
+      ptr = p;
+    }
+  }
+
+  T& operator*() const {
+    assert(ptr != 0);
+    return *ptr;
+  }
+
+  T* operator->() const  {
+    assert(ptr != 0);
+    return ptr;
+  }
+
+  T* get() const  {
+    return ptr;
+  }
+
+  void swap(scoped_ptr & b) {
+    T* tmp = b.ptr;
+    b.ptr = ptr;
+    ptr = tmp;
+  }
+
+  T* release() {
+    T* tmp = ptr;
+    ptr = 0;
+    return tmp;
+  }
+  
+  T** accept() {
+    if (ptr) {
+      delete ptr;
+      ptr = 0;
+    }
+    return &ptr;
+  }
+
+  T** use() {
+    return &ptr;
+  }
+};
+
+template<typename T> inline
+void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
+  a.swap(b);
+}
+
+
+
+
+//  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
+//  is guaranteed, either on destruction of the scoped_array or via an explicit
+//  reset(). Use shared_array or std::vector if your needs are more complex.
+
+template<typename T>
+class scoped_array {
+ private:
+
+  T* ptr;
+
+  scoped_array(scoped_array const &);
+  scoped_array & operator=(scoped_array const &);
+
+ public:
+
+  typedef T element_type;
+
+  explicit scoped_array(T* p = 0) : ptr(p) {}
+
+  ~scoped_array() {
+    typedef char type_must_be_complete[sizeof(T)];
+    delete[] ptr;
+  }
+
+  void reset(T* p = 0) {
+    typedef char type_must_be_complete[sizeof(T)];
+
+    if (ptr != p) {
+      delete [] ptr;
+      ptr = p;
+    }
+  }
+
+  T& operator[](std::ptrdiff_t i) const {
+    assert(ptr != 0);
+    assert(i >= 0);
+    return ptr[i];
+  }
+
+  T* get() const {
+    return ptr;
+  }
+
+  void swap(scoped_array & b) {
+    T* tmp = b.ptr;
+    b.ptr = ptr;
+    ptr = tmp;
+  }
+
+  T* release() {
+    T* tmp = ptr;
+    ptr = 0;
+    return tmp;
+  }
+
+  T** accept() {
+    if (ptr) {
+      delete [] ptr;
+      ptr = 0;
+    }
+    return &ptr;
+  }
+};
+
+template<class T> inline
+void swap(scoped_array<T>& a, scoped_array<T>& b) {
+  a.swap(b);
+}
+
+// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
+// second template argument, the function used to free the object.
+
+template<typename T, void (*FF)(void*) = free> class scoped_ptr_malloc {
+ private:
+
+  T* ptr;
+
+  scoped_ptr_malloc(scoped_ptr_malloc const &);
+  scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
+
+ public:
+
+  typedef T element_type;
+
+  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;
+    }
+  }
+
+  T& operator*() const {
+    assert(ptr != 0);
+    return *ptr;
+  }
+
+  T* operator->() const {
+    assert(ptr != 0);
+    return ptr;
+  }
+
+  T* get() const {
+    return ptr;
+  }
+
+  void swap(scoped_ptr_malloc & b) {
+    T* tmp = b.ptr;
+    b.ptr = ptr;
+    ptr = tmp;
+  }
+
+  T* release() {
+    T* tmp = ptr;
+    ptr = 0;
+    return tmp;
+  }
+
+  T** accept() {
+    if (ptr) {
+      FF(static_cast<void*>(ptr));
+      ptr = 0;
+    }
+    return &ptr;
+  }
+};
+
+template<typename T, void (*FF)(void*)> inline
+void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) {
+  a.swap(b);
+}
+
+} // 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
new file mode 100755
index 0000000..585e27f
--- /dev/null
+++ b/talk/base/sec_buffer.h
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+// @file Contains utility classes that make it easier to use SecBuffers
+
+#ifndef TALK_BASE_SEC_BUFFER_H__
+#define TALK_BASE_SEC_BUFFER_H__
+
+namespace talk_base {
+
+// A base class for CSecBuffer<T>. Contains
+// all implementation that does not require
+// template arguments.
+class CSecBufferBase : public SecBuffer {
+ public:
+  CSecBufferBase() {
+    Clear();
+  }
+
+  // Uses the SSPI to free a pointer, must be
+  // used for buffers returned from SSPI APIs.
+  static void FreeSSPI(void *ptr) {
+    if ( ptr ) {
+      SECURITY_STATUS status;
+      status = ::FreeContextBuffer(ptr);
+      ASSERT(SEC_E_OK == status); // "Freeing context buffer"
+    }
+  }
+
+  // Deletes a buffer with operator delete
+  static void FreeDelete(void *ptr) {
+    delete [] reinterpret_cast<char*>(ptr);
+  }
+
+  // A noop delete, for buffers over other
+  // people's memory
+  static void FreeNone(void *ptr) {
+  }
+
+ protected:
+  // Clears the buffer to EMPTY & NULL
+  void Clear() {
+    this->BufferType = SECBUFFER_EMPTY;
+    this->cbBuffer = 0;
+    this->pvBuffer = NULL;
+  }
+};
+
+// Wrapper class for SecBuffer to take care
+// of initialization and destruction.
+template <void (*pfnFreeBuffer)(void *ptr)>
+class CSecBuffer: public CSecBufferBase {
+ public:
+  // Initializes buffer to empty & NULL
+  CSecBuffer() {
+  }
+
+  // Frees any allocated memory
+  ~CSecBuffer() {
+    Release();
+  }
+
+  // Frees the buffer appropriately, and re-nulls
+  void Release() {
+    pfnFreeBuffer(this->pvBuffer);
+    Clear();
+  }
+
+ private:
+  // A placeholder function for compile-time asserts on the class
+  void CompileAsserts() {
+    // never invoked...
+    assert(false); // _T("Notreached")
+
+    // This class must not extend the size of SecBuffer, since
+    // we use arrays of CSecBuffer in CSecBufferBundle below
+    cassert(sizeof(CSecBuffer<SSPIFree> == sizeof(SecBuffer)));
+  }
+};
+
+// Contains all generic implementation for the
+// SecBufferBundle class
+class SecBufferBundleBase {
+ public:
+};
+
+// A template class that bundles a SecBufferDesc with
+// one or more SecBuffers for convenience. Can take
+// care of deallocating buffers appropriately, as indicated
+// by pfnFreeBuffer function.
+// By default does no deallocation.
+template <int num_buffers,
+          void (*pfnFreeBuffer)(void *ptr) = CSecBufferBase::FreeNone>
+class CSecBufferBundle : public SecBufferBundleBase {
+ public:
+  // Constructs a security buffer bundle with num_buffers
+  // buffers, all of which are empty and nulled.
+  CSecBufferBundle() {
+    desc_.ulVersion = SECBUFFER_VERSION;
+    desc_.cBuffers = num_buffers;
+    desc_.pBuffers = buffers_;
+  }
+
+  // Frees all currently used buffers.
+  ~CSecBufferBundle() {
+    Release();
+  }
+
+  // Accessor for the descriptor
+  PSecBufferDesc desc() {
+    return &desc_;
+  }
+
+  // Accessor for the descriptor
+  const PSecBufferDesc desc() const {
+    return &desc_;
+  }
+
+  // returns the i-th security buffer
+  SecBuffer &operator[] (size_t num) {
+    ASSERT(num < num_buffers); // "Buffer index out of bounds"
+    return buffers_[num];
+  }
+
+  // returns the i-th security buffer
+  const SecBuffer &operator[] (size_t num) const {
+    ASSERT(num < num_buffers); // "Buffer index out of bounds"
+    return buffers_[num];
+  }
+
+  // Frees all non-NULL security buffers,
+  // using the deallocation function
+  void Release() {
+    for ( size_t i = 0; i < num_buffers; ++i ) {
+      buffers_[i].Release();
+    }
+  }
+
+ private:
+  // Our descriptor
+  SecBufferDesc               desc_;
+  // Our bundled buffers, each takes care of its own
+  // initialization and destruction
+  CSecBuffer<pfnFreeBuffer>   buffers_[num_buffers];
+};
+
+} // namespace talk_base
+
+#endif  // TALK_BASE_SEC_BUFFER_H__
diff --git a/talk/base/signalthread.cc b/talk/base/signalthread.cc
new file mode 100755
index 0000000..919d1c3
--- /dev/null
+++ b/talk/base/signalthread.cc
@@ -0,0 +1,93 @@
+#include "talk/base/common.h"
+#include "talk/base/signalthread.h"
+
+using namespace talk_base;
+
+///////////////////////////////////////////////////////////////////////////////
+// SignalThread
+///////////////////////////////////////////////////////////////////////////////
+
+SignalThread::SignalThread()
+: main_(Thread::Current()), state_(kInit)
+{
+  worker_.parent_ = this;
+}
+
+SignalThread::~SignalThread() {
+}
+
+void SignalThread::SetPriority(ThreadPriority priority) {
+  ASSERT(main_->IsCurrent());
+  ASSERT(kInit == state_);
+  worker_.SetPriority(priority);
+}
+
+void SignalThread::Start() {
+  ASSERT(main_->IsCurrent());
+  if (kInit == state_) {
+    state_ = kRunning;
+    OnWorkStart();
+    worker_.Start();
+  } else {
+    ASSERT(false);
+  }
+}
+
+void SignalThread::Destroy() {
+  ASSERT(main_->IsCurrent());
+  if ((kInit == state_) || (kComplete == state_)) {
+    delete this;
+  } else if (kRunning == 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();
+  } else {
+    ASSERT(false);
+  }
+}
+
+void SignalThread::Release() {
+  ASSERT(main_->IsCurrent());
+  if (kComplete == state_) {
+    delete this;
+  } else if (kRunning == state_) {
+    state_ = kReleasing;
+  } else {
+    // if (kInit == state_) use Destroy()
+    ASSERT(false);
+  }
+}
+
+bool SignalThread::ContinueWork() {
+  ASSERT(worker_.IsCurrent());
+  return worker_.ProcessMessages(0);
+}
+
+void SignalThread::OnMessage(Message *msg) {
+  if (ST_MSG_WORKER_DONE == msg->message_id) {
+    ASSERT(main_->IsCurrent());
+    OnWorkDone();
+    bool do_delete = false;
+    if (kRunning == state_) {
+      state_ = kComplete;
+    } else {
+      do_delete = true;
+    }
+    if (kStopping != state_) {
+      SignalWorkDone(this);
+    }
+    if (do_delete) {
+      delete this;
+    }
+  }
+}
+
+void SignalThread::Run() {
+  DoWork();
+  main_->Post(this, ST_MSG_WORKER_DONE);
+}
diff --git a/talk/base/signalthread.h b/talk/base/signalthread.h
new file mode 100755
index 0000000..9e6bd05
--- /dev/null
+++ b/talk/base/signalthread.h
@@ -0,0 +1,91 @@
+#ifndef _SIGNALTHREAD_H_
+#define _SIGNALTHREAD_H_
+
+#include "talk/base/thread.h"
+#include "talk/base/sigslot.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// SignalThread - Base class for worker threads.  The main thread should call
+//  Start() to begin work, and then follow one of these models:
+//   Normal: Wait for SignalWorkDone, and then call Release to destroy.
+//   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.
+//  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:
+  SignalThread();
+
+  // Context: Main Thread.  Call before Start to change the worker's priority.
+  void SetPriority(ThreadPriority priority);
+
+  // Context: Main Thread.  Call to begin the worker thread.
+  void Start();
+
+  // 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();
+
+  // Context: Main Thread.  If the worker thread is complete, deletes the
+  // object immediately.  Otherwise, schedules the object to be deleted once
+  // the worker thread completes.  SignalWorkDone will be signalled.
+  void Release();
+
+  // Context: Main Thread.  Signalled when work is complete.
+  sigslot::signal1<SignalThread *> SignalWorkDone;
+
+  enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE };
+
+protected:
+  virtual ~SignalThread();
+
+  // 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;
+
+  // Context: Worker Thread.  Subclass should call periodically to
+  // dispatch messages and determine if the thread should terminate.
+  bool ContinueWork();
+
+  // Context: Worker Thread.  Subclass should override when extra work is
+  // needed to abort the worker thread.
+  virtual void OnWorkStop() { }
+
+  // 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:
+  friend class Worker;
+  class Worker : public Thread {
+  public:
+    SignalThread* parent_;
+    virtual void Run() { parent_->Run(); }
+  };
+
+  void Run();
+
+  Thread* main_;
+  Worker worker_;
+  enum State { kInit, kRunning, kComplete, kStopping, kReleasing } state_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif  // _SIGNALTHREAD_H_
diff --git a/talk/base/sigslot.h b/talk/base/sigslot.h
new file mode 100755
index 0000000..539db8a
--- /dev/null
+++ b/talk/base/sigslot.h
@@ -0,0 +1,2699 @@
+// sigslot.h: Signal/Slot classes
+// 
+// Written by Sarah Thompson (sarah@telergy.com) 2002.
+//
+// License: Public domain. You are free to use this code however you like, with the proviso that
+//          the author takes on no responsibility or liability for any use.
+//
+// QUICK DOCUMENTATION 
+//		
+//				(see also the full documentation at http://sigslot.sourceforge.net/)
+//
+//		#define switches
+//			SIGSLOT_PURE_ISO			- Define this to force ISO C++ compliance. This also disables
+//										  all of the thread safety support on platforms where it is 
+//										  available.
+//
+//			SIGSLOT_USE_POSIX_THREADS	- Force use of Posix threads when using a C++ compiler other than
+//										  gcc on a platform that supports Posix threads. (When using gcc,
+//										  this is the default - use SIGSLOT_PURE_ISO to disable this if 
+//										  necessary)
+//
+//			SIGSLOT_DEFAULT_MT_POLICY	- Where thread support is enabled, this defaults to multi_threaded_global.
+//										  Otherwise, the default is single_threaded. #define this yourself to
+//										  override the default. In pure ISO mode, anything other than
+//										  single_threaded will cause a compiler error.
+//
+//		PLATFORM NOTES
+//
+//			Win32						- On Win32, the WIN32 symbol must be #defined. Most mainstream
+//										  compilers do this by default, but you may need to define it
+//										  yourself if your build environment is less standard. This causes
+//										  the Win32 thread support to be compiled in and used automatically.
+//
+//			Unix/Linux/BSD, etc.		- If you're using gcc, it is assumed that you have Posix threads
+//										  available, so they are used automatically. You can override this
+//										  (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
+//										  something other than gcc but still want to use Posix threads, you
+//										  need to #define SIGSLOT_USE_POSIX_THREADS.
+//
+//			ISO C++						- If none of the supported platforms are detected, or if
+//										  SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,
+//										  along with any code that might cause a pure ISO C++ environment to
+//										  complain. Before you ask, gcc -ansi -pedantic won't compile this 
+//										  library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
+//										  errors that aren't really there. If you feel like investigating this,
+//										  please contact the author.
+//
+//		
+//		THREADING MODES
+//
+//			single_threaded				- Your program is assumed to be single threaded from the point of view
+//										  of signal/slot usage (i.e. all objects using signals and slots are
+//										  created and destroyed from a single thread). Behaviour if objects are
+//										  destroyed concurrently is undefined (i.e. you'll get the occasional
+//										  segmentation fault/memory exception).
+//
+//			multi_threaded_global		- Your program is assumed to be multi threaded. Objects using signals and
+//										  slots can be safely created and destroyed from any thread, even when
+//										  connections exist. In multi_threaded_global mode, this is achieved by a
+//										  single global mutex (actually a critical section on Windows because they
+//										  are faster). This option uses less OS resources, but results in more
+//										  opportunities for contention, possibly resulting in more context switches
+//										  than are strictly necessary.
+//
+//			multi_threaded_local		- Behaviour in this mode is essentially the same as multi_threaded_global,
+//										  except that each signal, and each object that inherits has_slots, all 
+//										  have their own mutex/critical section. In practice, this means that
+//										  mutex collisions (and hence context switches) only happen if they are
+//										  absolutely essential. However, on some platforms, creating a lot of 
+//										  mutexes can slow down the whole OS, so use this option with care.
+//
+//		USING THE LIBRARY
+//
+//			See the full documentation at http://sigslot.sourceforge.net/
+//
+//
+
+#ifndef TALK_BASE_SIGSLOT_H__
+#define TALK_BASE_SIGSLOT_H__
+
+#include <set>
+#include <list>
+
+// On our copy of sigslot.h, we force single threading
+#define SIGSLOT_PURE_ISO
+
+#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS))
+#	define _SIGSLOT_SINGLE_THREADED
+#elif defined(WIN32)
+#	define _SIGSLOT_HAS_WIN32_THREADS
+#	include <windows.h>
+#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
+#	define _SIGSLOT_HAS_POSIX_THREADS
+#	include <pthread.h>
+#else
+#	define _SIGSLOT_SINGLE_THREADED
+#endif
+
+#ifndef SIGSLOT_DEFAULT_MT_POLICY
+#	ifdef _SIGSLOT_SINGLE_THREADED
+#		define SIGSLOT_DEFAULT_MT_POLICY single_threaded
+#	else
+#		define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
+#	endif
+#endif
+
+// TODO: change this namespace to talk_base?
+namespace sigslot {
+
+	class single_threaded
+	{
+	public:
+		single_threaded()
+		{
+			;
+		}
+
+		virtual ~single_threaded()
+		{
+			;
+		}
+
+		virtual void lock()
+		{
+			;
+		}
+
+		virtual void unlock()
+		{
+			;
+		}
+	};
+
+#ifdef _SIGSLOT_HAS_WIN32_THREADS
+	// The multi threading policies only get compiled in if they are enabled.
+	class multi_threaded_global
+	{
+	public:
+		multi_threaded_global()
+		{
+			static bool isinitialised = false;
+
+			if(!isinitialised)
+			{
+				InitializeCriticalSection(get_critsec());
+				isinitialised = true;
+			}
+		}
+
+		multi_threaded_global(const multi_threaded_global&)
+		{
+			;
+		}
+
+		virtual ~multi_threaded_global()
+		{
+			;
+		}
+
+		virtual void lock()
+		{
+			EnterCriticalSection(get_critsec());
+		}
+
+		virtual void unlock()
+		{
+			LeaveCriticalSection(get_critsec());
+		}
+
+	private:
+		CRITICAL_SECTION* get_critsec()
+		{
+			static CRITICAL_SECTION g_critsec;
+			return &g_critsec;
+		}
+	};
+
+	class multi_threaded_local
+	{
+	public:
+		multi_threaded_local()
+		{
+			InitializeCriticalSection(&m_critsec);
+		}
+
+		multi_threaded_local(const multi_threaded_local&)
+		{
+			InitializeCriticalSection(&m_critsec);
+		}
+
+		virtual ~multi_threaded_local()
+		{
+			DeleteCriticalSection(&m_critsec);
+		}
+
+		virtual void lock()
+		{
+			EnterCriticalSection(&m_critsec);
+		}
+
+		virtual void unlock()
+		{
+			LeaveCriticalSection(&m_critsec);
+		}
+
+	private:
+		CRITICAL_SECTION m_critsec;
+	};
+#endif // _SIGSLOT_HAS_WIN32_THREADS
+
+#ifdef _SIGSLOT_HAS_POSIX_THREADS
+	// The multi threading policies only get compiled in if they are enabled.
+	class multi_threaded_global
+	{
+	public:
+		multi_threaded_global()
+		{
+			pthread_mutex_init(get_mutex(), NULL);
+		}
+
+		multi_threaded_global(const multi_threaded_global&)
+		{
+			;
+		}
+
+		virtual ~multi_threaded_global()
+		{
+			;
+		}
+
+		virtual void lock()
+		{
+			pthread_mutex_lock(get_mutex());
+		}
+
+		virtual void unlock()
+		{
+			pthread_mutex_unlock(get_mutex());
+		}
+
+	private:
+		pthread_mutex_t* get_mutex()
+		{
+			static pthread_mutex_t g_mutex;
+			return &g_mutex;
+		}
+	};
+
+	class multi_threaded_local
+	{
+	public:
+		multi_threaded_local()
+		{
+			pthread_mutex_init(&m_mutex, NULL);
+		}
+
+		multi_threaded_local(const multi_threaded_local&)
+		{
+			pthread_mutex_init(&m_mutex, NULL);
+		}
+
+		virtual ~multi_threaded_local()
+		{
+			pthread_mutex_destroy(&m_mutex);
+		}
+
+		virtual void lock()
+		{
+			pthread_mutex_lock(&m_mutex);
+		}
+
+		virtual void unlock()
+		{
+			pthread_mutex_unlock(&m_mutex);
+		}
+
+	private:
+		pthread_mutex_t m_mutex;
+	};
+#endif // _SIGSLOT_HAS_POSIX_THREADS
+
+	template<class mt_policy>
+	class lock_block
+	{
+	public:
+		mt_policy *m_mutex;
+
+		lock_block(mt_policy *mtx)
+			: m_mutex(mtx)
+		{
+			m_mutex->lock();
+		}
+
+		~lock_block()
+		{
+			m_mutex->unlock();
+		}
+	};
+
+	template<class mt_policy>
+	class has_slots;
+
+	template<class mt_policy>
+	class _connection_base0
+	{
+	public:
+		virtual has_slots<mt_policy>* getdest() const = 0;
+		virtual void emit() = 0;
+		virtual _connection_base0* clone() = 0;
+		virtual _connection_base0* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class mt_policy>
+	class _connection_base1
+	{
+	public:
+		virtual has_slots<mt_policy>* getdest() const = 0;
+		virtual void emit(arg1_type) = 0;
+		virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;
+		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class arg2_type, class mt_policy>
+	class _connection_base2
+	{
+	public:
+		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;
+		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
+	class _connection_base3
+	{
+	public:
+		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;
+		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
+	class _connection_base4
+	{
+	public:
+		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;
+		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class mt_policy>
+	class _connection_base5
+	{
+	public:
+		virtual has_slots<mt_policy>* getdest() const = 0;
+		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type) = 0;
+		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, mt_policy>* clone() = 0;
+		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class mt_policy>
+	class _connection_base6
+	{
+	public:
+		virtual has_slots<mt_policy>* getdest() const = 0;
+		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
+			arg6_type) = 0;
+		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, mt_policy>* clone() = 0;
+		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class arg7_type, class mt_policy>
+	class _connection_base7
+	{
+	public:
+		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;
+		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, mt_policy>* clone() = 0;
+		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>
+	class _connection_base8
+	{
+	public:
+		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;
+		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone() = 0;
+		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+	};
+
+	template<class mt_policy>
+	class _signal_base : public mt_policy
+	{
+	public:
+		virtual void slot_disconnect(has_slots<mt_policy>* pslot) = 0;
+		virtual void slot_duplicate(const has_slots<mt_policy>* poldslot, has_slots<mt_policy>* pnewslot) = 0;
+	};
+
+	template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class has_slots : public mt_policy 
+	{
+	private:
+		typedef typename std::set<_signal_base<mt_policy> *> sender_set;
+		typedef typename sender_set::const_iterator const_iterator;
+
+	public:
+		has_slots()
+		{
+			;
+		}
+
+		has_slots(const has_slots& hs)
+			: mt_policy(hs)
+		{
+			lock_block<mt_policy> lock(this);
+			const_iterator it = hs.m_senders.begin();
+			const_iterator itEnd = hs.m_senders.end();
+
+			while(it != itEnd)
+			{
+				(*it)->slot_duplicate(&hs, this);
+				m_senders.insert(*it);
+				++it;
+			}
+		} 
+
+		void signal_connect(_signal_base<mt_policy>* sender)
+		{
+			lock_block<mt_policy> lock(this);
+			m_senders.insert(sender);
+		}
+
+		void signal_disconnect(_signal_base<mt_policy>* sender)
+		{
+			lock_block<mt_policy> lock(this);
+			m_senders.erase(sender);
+		}
+
+		virtual ~has_slots()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			lock_block<mt_policy> lock(this);
+			const_iterator it = m_senders.begin();
+			const_iterator itEnd = m_senders.end();
+
+			while(it != itEnd)
+			{
+				(*it)->slot_disconnect(this);
+				++it;
+			}
+
+			m_senders.erase(m_senders.begin(), m_senders.end());
+		}
+
+	private:
+		sender_set m_senders;
+	};
+
+	template<class mt_policy>
+	class _signal_base0 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base0<mt_policy> *>  connections_list;
+
+		_signal_base0()
+		{
+			;
+		}
+
+		_signal_base0(const _signal_base0& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		~_signal_base0()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class mt_policy>
+	class _signal_base1 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base1<arg1_type, mt_policy> *>  connections_list;
+
+		_signal_base1()
+		{
+			;
+		}
+
+		_signal_base1(const _signal_base1<arg1_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base1()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class arg2_type, class mt_policy>
+	class _signal_base2 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base2<arg1_type, arg2_type, mt_policy> *>
+			connections_list;
+
+		_signal_base2()
+		{
+			;
+		}
+
+		_signal_base2(const _signal_base2<arg1_type, arg2_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base2()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
+	class _signal_base3 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base3<arg1_type, arg2_type, arg3_type, mt_policy> *>
+			connections_list;
+
+		_signal_base3()
+		{
+			;
+		}
+
+		_signal_base3(const _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base3()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
+	class _signal_base4 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base4<arg1_type, arg2_type, arg3_type,
+			arg4_type, mt_policy> *>  connections_list;
+
+		_signal_base4()
+		{
+			;
+		}
+
+		_signal_base4(const _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base4()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class mt_policy>
+	class _signal_base5 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base5<arg1_type, arg2_type, arg3_type,
+			arg4_type, arg5_type, mt_policy> *>  connections_list;
+
+		_signal_base5()
+		{
+			;
+		}
+
+		_signal_base5(const _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base5()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class mt_policy>
+	class _signal_base6 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base6<arg1_type, arg2_type, arg3_type, 
+			arg4_type, arg5_type, arg6_type, mt_policy> *>  connections_list;
+
+		_signal_base6()
+		{
+			;
+		}
+
+		_signal_base6(const _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base6()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class arg7_type, class mt_policy>
+	class _signal_base7 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base7<arg1_type, arg2_type, arg3_type, 
+			arg4_type, arg5_type, arg6_type, arg7_type, mt_policy> *>  connections_list;
+
+		_signal_base7()
+		{
+			;
+		}
+
+		_signal_base7(const _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base7()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>
+	class _signal_base8 : public _signal_base<mt_policy>
+	{
+	public:
+		typedef std::list<_connection_base8<arg1_type, arg2_type, arg3_type, 
+			arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> *>
+			connections_list;
+
+		_signal_base8()
+		{
+			;
+		}
+
+		_signal_base8(const _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)
+			: _signal_base<mt_policy>(s)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator it = s.m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_connect(this);
+				m_connected_slots.push_back((*it)->clone());
+
+				++it;
+			}
+		}
+
+		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == oldtarget)
+				{
+					m_connected_slots.push_back((*it)->duplicate(newtarget));
+				}
+
+				++it;
+			}
+		}
+
+		~_signal_base8()
+		{
+			disconnect_all();
+		}
+
+		void disconnect_all()
+		{
+			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();
+
+			while(it != itEnd)
+			{
+				(*it)->getdest()->signal_disconnect(this);
+				delete *it;
+
+				++it;
+			}
+
+			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+		}
+
+#ifdef _DEBUG
+			bool connected(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+				if ((*it)->getdest() == pclass)
+					return true;
+				it = itNext;
+			}
+			return false;
+		}
+#endif
+
+		void disconnect(has_slots<mt_policy>* pclass)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				if((*it)->getdest() == pclass)
+				{
+					delete *it;
+					m_connected_slots.erase(it);
+					pclass->signal_disconnect(this);
+					return;
+				}
+
+				++it;
+			}
+		}
+
+		void slot_disconnect(has_slots<mt_policy>* pslot)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::iterator it = m_connected_slots.begin();
+			typename connections_list::iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				typename connections_list::iterator itNext = it;
+				++itNext;
+
+				if((*it)->getdest() == pslot)
+				{
+					m_connected_slots.erase(it);
+					//			delete *it;
+				}
+
+				it = itNext;
+			}
+		}
+
+	protected:
+		connections_list m_connected_slots;   
+	};
+
+
+	template<class dest_type, class mt_policy>
+	class _connection0 : public _connection_base0<mt_policy>
+	{
+	public:
+		_connection0()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection0(dest_type* pobject, void (dest_type::*pmemfun)())
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		virtual _connection_base0<mt_policy>* clone()
+		{
+			return new _connection0<dest_type, mt_policy>(*this);
+		}
+
+		virtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection0<dest_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit()
+		{
+			(m_pobject->*m_pmemfun)();
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)();
+	};
+
+	template<class dest_type, class arg1_type, class mt_policy>
+	class _connection1 : public _connection_base1<arg1_type, mt_policy>
+	{
+	public:
+		_connection1()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		virtual _connection_base1<arg1_type, mt_policy>* clone()
+		{
+			return new _connection1<dest_type, arg1_type, mt_policy>(*this);
+		}
+
+		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection1<dest_type, arg1_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1)
+		{
+			(m_pobject->*m_pmemfun)(a1);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type);
+	};
+
+	template<class dest_type, class arg1_type, class arg2_type, class mt_policy>
+	class _connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>
+	{
+	public:
+		_connection2()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
+			arg2_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()
+		{
+			return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);
+		}
+
+		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1, arg2_type a2)
+		{
+			(m_pobject->*m_pmemfun)(a1, a2);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type, arg2_type);
+	};
+
+	template<class dest_type, class arg1_type, class arg2_type, class arg3_type, class mt_policy>
+	class _connection3 : public _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>
+	{
+	public:
+		_connection3()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
+			arg2_type, arg3_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		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);
+		}
+
+		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3)
+		{
+			(m_pobject->*m_pmemfun)(a1, a2, a3);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type);
+	};
+
+	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+	class arg4_type, class mt_policy>
+	class _connection4 : public _connection_base4<arg1_type, arg2_type,
+		arg3_type, arg4_type, mt_policy>
+	{
+	public:
+		_connection4()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		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);
+		}
+
+		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, 
+			arg4_type a4)
+		{
+			(m_pobject->*m_pmemfun)(a1, a2, a3, a4);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type,
+			arg4_type);
+	};
+
+	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+	class arg4_type, class arg5_type, class mt_policy>
+	class _connection5 : public _connection_base5<arg1_type, arg2_type,
+		arg3_type, arg4_type, arg5_type, mt_policy>
+	{
+	public:
+		_connection5()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, mt_policy>* clone()
+		{
+			return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, mt_policy>(*this);
+		}
+
+		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5)
+		{
+			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type);
+	};
+
+	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+	class arg4_type, class arg5_type, class arg6_type, class mt_policy>
+	class _connection6 : public _connection_base6<arg1_type, arg2_type,
+		arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>
+	{
+	public:
+		_connection6()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, mt_policy>* clone()
+		{
+			return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, arg6_type, mt_policy>(*this);
+		}
+
+		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, arg6_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6)
+		{
+			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type);
+	};
+
+	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+	class arg4_type, class arg5_type, class arg6_type, class arg7_type, class mt_policy>
+	class _connection7 : public _connection_base7<arg1_type, arg2_type,
+		arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>
+	{
+	public:
+		_connection7()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, arg7_type, mt_policy>* clone()
+		{
+			return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, arg6_type, arg7_type, mt_policy>(*this);
+		}
+
+		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, arg6_type, arg7_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6, arg7_type a7)
+		{
+			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type);
+	};
+
+	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+	class arg4_type, class arg5_type, class arg6_type, class arg7_type, 
+	class arg8_type, class mt_policy>
+	class _connection8 : public _connection_base8<arg1_type, arg2_type,
+		arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>
+	{
+	public:
+		_connection8()
+		{
+			m_pobject = NULL;
+			m_pmemfun = NULL;
+		}
+
+		_connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, 
+			arg7_type, arg8_type))
+		{
+			m_pobject = pobject;
+			m_pmemfun = pmemfun;
+		}
+
+		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone()
+		{
+			return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(*this);
+		}
+
+		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+		{
+			return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, 
+				arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+		}
+
+		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
+		{
+			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8);
+		}
+
+		virtual has_slots<mt_policy>* getdest() const
+		{
+			return m_pobject;
+		}
+
+	private:
+		dest_type* m_pobject;
+		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, arg8_type);
+	};
+
+	template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal0 : public _signal_base0<mt_policy>
+	{
+	public:
+		typedef _signal_base0<mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal0()
+		{
+			;
+		}
+
+		signal0(const signal0<mt_policy>& s)
+			: _signal_base0<mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)())
+		{
+			lock_block<mt_policy> lock(this);
+			_connection0<desttype, mt_policy>* conn = 
+				new _connection0<desttype, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit()
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit();
+
+				it = itNext;
+			}
+		}
+
+		void operator()()
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit();
+
+				it = itNext;
+			}
+		}
+	};
+
+	template<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal1 : public _signal_base1<arg1_type, mt_policy>
+	{
+	public:
+		typedef _signal_base1<arg1_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal1()
+		{
+			;
+		}
+
+		signal1(const signal1<arg1_type, mt_policy>& s)
+			: _signal_base1<arg1_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection1<desttype, arg1_type, mt_policy>* conn = 
+				new _connection1<desttype, arg1_type, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1);
+
+				it = itNext;
+			}
+		}
+	};
+
+	template<class arg1_type, class arg2_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal2 : public _signal_base2<arg1_type, arg2_type, mt_policy>
+	{
+	public:
+		typedef _signal_base2<arg1_type, arg2_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal2()
+		{
+			;
+		}
+
+		signal2(const signal2<arg1_type, arg2_type, mt_policy>& s)
+			: _signal_base2<arg1_type, arg2_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+			arg2_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection2<desttype, arg1_type, arg2_type, mt_policy>* conn = new
+				_connection2<desttype, arg1_type, arg2_type, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1, arg2_type a2)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1, arg2_type a2)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2);
+
+				it = itNext;
+			}
+		}
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal3 : public _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>
+	{
+	public:
+		typedef _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal3()
+		{
+			;
+		}
+
+		signal3(const signal3<arg1_type, arg2_type, arg3_type, mt_policy>& s)
+			: _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+			arg2_type, arg3_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>* conn = 
+				new _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>(pclass,
+				pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1, arg2_type a2, arg3_type a3)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1, arg2_type a2, arg3_type a3)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3);
+
+				it = itNext;
+			}
+		}
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal4 : public _signal_base4<arg1_type, arg2_type, arg3_type,
+		arg4_type, mt_policy>
+	{
+	public:
+		typedef _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal4()
+		{
+			;
+		}
+
+		signal4(const signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)
+			: _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection4<desttype, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>*
+				conn = new _connection4<desttype, arg1_type, arg2_type, arg3_type,
+				arg4_type, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4);
+
+				it = itNext;
+			}
+		}
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal5 : public _signal_base5<arg1_type, arg2_type, arg3_type,
+		arg4_type, arg5_type, mt_policy>
+	{
+	public:
+		typedef _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal5()
+		{
+			;
+		}
+
+		signal5(const signal5<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, mt_policy>& s)
+			: _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection5<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+				arg5_type, mt_policy>* conn = new _connection5<desttype, arg1_type, arg2_type,
+				arg3_type, arg4_type, arg5_type, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5);
+
+				it = itNext;
+			}
+		}
+	};
+
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal6 : public _signal_base6<arg1_type, arg2_type, arg3_type,
+		arg4_type, arg5_type, arg6_type, mt_policy>
+	{
+	public:
+		typedef _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal6()
+		{
+			;
+		}
+
+		signal6(const signal6<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, mt_policy>& s)
+			: _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection6<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+				arg5_type, arg6_type, mt_policy>* conn = 
+				new _connection6<desttype, arg1_type, arg2_type, arg3_type,
+				arg4_type, arg5_type, arg6_type, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5, a6);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5, a6);
+
+				it = itNext;
+			}
+		}
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class arg7_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal7 : public _signal_base7<arg1_type, arg2_type, arg3_type,
+		arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>
+	{
+	public:
+		typedef _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, arg7_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal7()
+		{
+			;
+		}
+
+		signal7(const signal7<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, mt_policy>& s)
+			: _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, 
+			arg7_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection7<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+				arg5_type, arg6_type, arg7_type, mt_policy>* conn = 
+				new _connection7<desttype, arg1_type, arg2_type, arg3_type,
+				arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6, arg7_type a7)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5, a6, a7);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6, arg7_type a7)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5, a6, a7);
+
+				it = itNext;
+			}
+		}
+	};
+
+	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+	class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+	class signal8 : public _signal_base8<arg1_type, arg2_type, arg3_type,
+		arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>
+	{
+	public:
+		typedef _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type, 
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> base;
+		typedef typename base::connections_list connections_list;
+		using base::m_connected_slots;
+
+		signal8()
+		{
+			;
+		}
+
+		signal8(const signal8<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)
+			: _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(s)
+		{
+			;
+		}
+
+		template<class desttype>
+			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, 
+			arg7_type, arg8_type))
+		{
+			lock_block<mt_policy> lock(this);
+			_connection8<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+				arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* conn = 
+				new _connection8<desttype, arg1_type, arg2_type, arg3_type,
+				arg4_type, arg5_type, arg6_type, arg7_type, 
+				arg8_type, mt_policy>(pclass, pmemfun);
+			m_connected_slots.push_back(conn);
+			pclass->signal_connect(this);
+		}
+
+		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);
+
+				it = itNext;
+			}
+		}
+
+		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+			arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
+		{
+			lock_block<mt_policy> lock(this);
+			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
+			typename connections_list::const_iterator itEnd = m_connected_slots.end();
+
+			while(it != itEnd)
+			{
+				itNext = it;
+				++itNext;
+
+				(*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);
+
+				it = itNext;
+			}
+		}
+	};
+
+}; // namespace sigslot
+
+#endif // TALK_BASE_SIGSLOT_H__
diff --git a/talk/base/socket.h b/talk/base/socket.h
new file mode 100755
index 0000000..0a30c4b
--- /dev/null
+++ b/talk/base/socket.h
@@ -0,0 +1,160 @@
+/*
+ * 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_SOCKET_H__
+#define TALK_BASE_SOCKET_H__
+
+#include <errno.h>
+
+#ifdef POSIX
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#define SOCKET_EACCES EACCES
+#endif
+
+#ifdef WIN32
+#include "talk/base/win32.h"
+#endif
+
+#include "talk/base/basictypes.h"
+#include "talk/base/socketaddress.h"
+
+// Rather than converting errors into a private namespace,
+// Reuse the POSIX socket api errors. Note this depends on
+// Win32 compatibility.
+
+#ifdef WIN32
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define EALREADY WSAEALREADY
+#define ENOTSOCK WSAENOTSOCK
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#define EMSGSIZE WSAEMSGSIZE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EADDRINUSE WSAEADDRINUSE
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define ENETDOWN WSAENETDOWN
+#define ENETUNREACH WSAENETUNREACH
+#define ENETRESET WSAENETRESET
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET WSAECONNRESET
+#define ENOBUFS WSAENOBUFS
+#define EISCONN WSAEISCONN
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+#define ELOOP WSAELOOP
+#undef ENAMETOOLONG // remove errno.h's definition
+#define ENAMETOOLONG WSAENAMETOOLONG
+#define EHOSTDOWN WSAEHOSTDOWN
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#undef ENOTEMPTY // remove errno.h's definition
+#define ENOTEMPTY WSAENOTEMPTY
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+#undef EACCES
+#define SOCKET_EACCES WSAEACCES
+#endif // WIN32
+
+#ifdef POSIX
+#define INVALID_SOCKET (-1)
+#define SOCKET_ERROR (-1)
+#define closesocket(s) close(s)
+#endif // POSIX
+
+namespace talk_base {
+
+inline bool IsBlockingError(int e) {
+  return (e == EWOULDBLOCK) || (e == EAGAIN) || (e == EINPROGRESS);
+}
+
+// General interface for the socket implementations of various networks.  The
+// methods match those of normal UNIX sockets very closely.
+class Socket {
+public:
+  virtual ~Socket() {}
+ 
+  // Returns the address to which the socket is bound.  If the socket is not
+  // bound, then the any-address is returned.
+  virtual SocketAddress GetLocalAddress() const = 0;
+
+  // Returns the address to which the socket is connected.  If the socket is
+  // not connected, then the any-address is returned.
+  virtual SocketAddress GetRemoteAddress() const = 0;
+
+  virtual int Bind(const SocketAddress& addr) = 0;
+  virtual int Connect(const SocketAddress& addr) = 0;
+  virtual int Send(const void *pv, size_t cb) = 0;
+  virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr) = 0;
+  virtual int Recv(void *pv, size_t cb) = 0;
+  virtual int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) = 0;
+  virtual int Listen(int backlog) = 0;
+  virtual Socket *Accept(SocketAddress *paddr) = 0;
+  virtual int Close() = 0;
+  virtual int GetError() const = 0;
+  virtual void SetError(int error) = 0;
+  inline bool IsBlocking() const { return IsBlockingError(GetError()); }
+
+  enum ConnState {
+    CS_CLOSED,
+    CS_CONNECTING,
+    CS_CONNECTED
+  };
+  virtual ConnState GetState() const = 0;
+
+  // Fills in the given uint16 with the current estimate of the MTU along the
+  // path to the address to which this socket is connected.
+  virtual int EstimateMTU(uint16* mtu) = 0;
+
+  enum Option {
+    OPT_DONTFRAGMENT
+  };
+  virtual int SetOption(Option opt, int value) = 0;
+
+protected:
+  Socket() {}
+
+private:
+  DISALLOW_EVIL_CONSTRUCTORS(Socket);
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SOCKET_H__
diff --git a/talk/base/socketadapters.cc b/talk/base/socketadapters.cc
new file mode 100755
index 0000000..fcbc20b
--- /dev/null
+++ b/talk/base/socketadapters.cc
@@ -0,0 +1,677 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#include <time.h>
+#include <errno.h>
+
+#ifdef WIN32
+#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"
+#include "talk/base/logging.h"
+#include "talk/base/socketadapters.h"
+#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
+
+#ifdef WIN32
+#include "talk/base/sec_buffer.h"
+#endif // WIN32
+
+namespace talk_base {
+
+BufferedReadAdapter::BufferedReadAdapter(AsyncSocket* socket, size_t buffer_size)
+  : AsyncSocketAdapter(socket), buffer_size_(buffer_size), data_len_(0), buffering_(false) {
+  buffer_ = new char[buffer_size_];
+}
+
+BufferedReadAdapter::~BufferedReadAdapter() {
+  delete [] buffer_;
+}
+
+int BufferedReadAdapter::Send(const void *pv, size_t cb) {
+  if (buffering_) {
+    // TODO: Spoof error better; Signal Writeable
+    socket_->SetError(EWOULDBLOCK);
+    return -1;
+  }
+  return AsyncSocketAdapter::Send(pv, cb);
+}
+
+int BufferedReadAdapter::Recv(void *pv, size_t cb) {
+  if (buffering_) {
+    socket_->SetError(EWOULDBLOCK);
+    return -1;
+  }
+
+  size_t read = 0;
+
+  if (data_len_) {
+    read = _min(cb, data_len_);
+    memcpy(pv, buffer_, read);
+    data_len_ -= read;
+    if (data_len_ > 0) {
+      memmove(buffer_, buffer_ + read, data_len_);
+    }
+    pv = static_cast<char *>(pv) + read;
+    cb -= read;
+  }
+
+  // FIX: If cb == 0, we won't generate another read event
+
+  int res = AsyncSocketAdapter::Recv(pv, cb);
+  if (res < 0)
+    return res;
+
+  return res + static_cast<int>(read);
+}
+
+void BufferedReadAdapter::BufferInput(bool on) {
+  buffering_ = on;
+}
+
+void BufferedReadAdapter::OnReadEvent(AsyncSocket * socket) {
+  ASSERT(socket == socket_);
+
+  if (!buffering_) {
+    AsyncSocketAdapter::OnReadEvent(socket);
+    return;
+  }
+
+  if (data_len_ >= buffer_size_) {
+    LOG(INFO) << "Input buffer overflow";
+    ASSERT(false);
+    data_len_ = 0;
+  }
+
+  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);
+    return;
+  }
+
+  data_len_ += 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
+};
+
+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
+};
+
+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
+  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));
+}
+
+void AsyncSSLSocket::ProcessInput(char * data, size_t& len) {
+  if (len < sizeof(SSL_SERVER_HELLO))
+    return;
+
+  if (memcmp(SSL_SERVER_HELLO, data, sizeof(SSL_SERVER_HELLO)) != 0) {
+    Close();
+    SignalCloseEvent(this, 0); // TODO: error code?
+    return;
+  }
+
+  len -= sizeof(SSL_SERVER_HELLO);
+  if (len > 0) {
+    memmove(data, data + sizeof(SSL_SERVER_HELLO), len);
+  }
+
+  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);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket,
+                                             const std::string& user_agent,
+                                             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) {
+}
+
+AsyncHttpsProxySocket::~AsyncHttpsProxySocket() {
+  delete context_;
+}
+
+int AsyncHttpsProxySocket::Connect(const SocketAddress& addr) {
+  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::Connect("
+                  << proxy_.ToString() << ")";
+  dest_ = addr;
+  if (dest_.port() != 80) {
+    BufferInput(true);
+  }
+  return BufferedReadAdapter::Connect(proxy_);
+}
+
+SocketAddress AsyncHttpsProxySocket::GetRemoteAddress() const {
+  return dest_;
+}
+
+int AsyncHttpsProxySocket::Close() {
+  headers_.clear();
+  state_ = PS_ERROR;
+  delete context_;
+  context_ = 0;
+  return BufferedReadAdapter::Close();
+}
+
+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) {
+    state_ = PS_TUNNEL;
+    BufferedReadAdapter::OnConnectEvent(socket);
+    return;
+  }
+  SendRequest();
+}
+
+void AsyncHttpsProxySocket::OnCloseEvent(AsyncSocket * socket, int err) {
+  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnCloseEvent(" << err << ")";
+  if ((state_ == PS_WAIT_CLOSE) && (err == 0)) {
+    state_ = PS_ERROR;
+    Connect(dest_);
+  } else {
+    BufferedReadAdapter::OnCloseEvent(socket, err);
+  }
+}
+
+void AsyncHttpsProxySocket::ProcessInput(char * data, size_t& len) {
+  size_t start = 0;
+  for (size_t pos = start; (state_ < PS_TUNNEL) && (pos < len); ) {
+    if (state_ == PS_SKIP_BODY) {
+      size_t consume = _min(len - pos, content_length_);
+      pos += consume;
+      start = pos;
+      content_length_ -= consume;
+      if (content_length_ == 0) {
+        EndResponse();
+      }
+      continue;
+    }
+
+    if (data[pos++] != '\n')
+      continue;
+
+    size_t len = pos - start - 1;
+    if ((len > 0) && (data[start + len - 1] == '\r'))
+      --len;
+
+    data[start + len] = 0;
+    ProcessLine(data + start, len);
+    start = pos;
+  }
+
+  len -= start;
+  if (len > 0) {
+    memmove(data, data + start, len);
+  }
+
+  if (state_ != PS_TUNNEL)
+    return;
+
+  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??
+}
+
+void AsyncHttpsProxySocket::SendRequest() {
+  std::stringstream ss;
+  ss << "CONNECT " << dest_.ToString() << " HTTP/1.0\r\n";
+  ss << "User-Agent: " << agent_ << "\r\n";
+  ss << "Host: " << dest_.IPAsString() << "\r\n";
+  ss << "Content-Length: 0\r\n";
+  ss << "Proxy-Connection: Keep-Alive\r\n";
+  ss << headers_;
+  ss << "\r\n";
+  std::string str = ss.str();
+  DirectSend(str.c_str(), str.size());
+  state_ = PS_LEADER;
+  expect_close_ = true;
+  content_length_ = 0;
+  headers_.clear();
+
+  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket >> " << str;
+}
+
+void AsyncHttpsProxySocket::ProcessLine(char * data, size_t len) {
+  LOG(LS_VERBOSE) << "AsyncHttpsProxySocket << " << data;
+
+  if (len == 0) {
+    if (state_ == PS_TUNNEL_HEADERS) {
+      state_ = PS_TUNNEL;
+    } else if (state_ == PS_ERROR_HEADERS) {
+      Error(defer_error_);
+      return;
+    } else if (state_ == PS_SKIP_HEADERS) {
+      if (content_length_) {
+        state_ = PS_SKIP_BODY;
+      } else {
+        EndResponse();
+        return;
+      }
+    } else {
+      static bool report = false;
+      if (!unknown_mechanisms_.empty() && !report) {
+        report = true;
+        std::string msg(
+          "Unable to connect to the Google Talk service due to an incompatibility "
+          "with your proxy.\r\nPlease help us resolve this issue by submitting the "
+          "following information to us using our technical issue submission form "
+          "at:\r\n\r\n"
+          "http://www.google.com/support/talk/bin/request.py\r\n\r\n"
+          "We apologize for the inconvenience.\r\n\r\n"
+          "Information to submit to Google: "
+          );
+        //std::string msg("Please report the following information to foo@bar.com:\r\nUnknown methods: ");
+        msg.append(unknown_mechanisms_);
+#ifdef WIN32
+        MessageBoxA(0, msg.c_str(), "Oops!", MB_OK);
+#endif
+#ifdef POSIX
+        //TODO: Raise a signal or something so the UI can be separated.
+        LOG(LS_ERROR) << "Oops!\n\n" << msg;
+#endif
+      }
+      // Unexpected end of headers
+      Error(0);
+      return;
+    }
+  } else if (state_ == PS_LEADER) {
+    uint32 code;
+    if (sscanf(data, "HTTP/%*lu.%*lu %lu", &code) != 1) {
+      Error(0);
+      return;
+    }
+    switch (code) {
+    case 200:
+      // connection good!
+      state_ = PS_TUNNEL_HEADERS;
+      return;
+#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
+      state_ = PS_AUTHENTICATE;
+      return;
+    default:
+      defer_error_ = 0;
+      state_ = PS_ERROR_HEADERS;
+      return;
+    }
+  } else if ((state_ == PS_AUTHENTICATE)
+             && (_strnicmp(data, "Proxy-Authenticate:", 19) == 0)) {
+    std::string response, auth_method;
+    switch (HttpAuthenticate(data + 19, len - 19,
+                             proxy_, "CONNECT", "/",
+                             user_, pass_, context_, response, auth_method)) {
+    case HAR_IGNORE:
+      LOG(LS_VERBOSE) << "Ignoring Proxy-Authenticate: " << auth_method;
+      if (!unknown_mechanisms_.empty())
+        unknown_mechanisms_.append(", ");
+      unknown_mechanisms_.append(auth_method);
+      break;
+    case HAR_RESPONSE:
+      headers_ = "Proxy-Authorization: ";
+      headers_.append(response);
+      headers_.append("\r\n");
+      state_ = PS_SKIP_HEADERS;
+      unknown_mechanisms_.clear();
+      break;
+    case HAR_CREDENTIALS:
+      defer_error_ = SOCKET_EACCES;
+      state_ = PS_ERROR_HEADERS;
+      unknown_mechanisms_.clear();
+      break;
+    case HAR_ERROR:
+      defer_error_ = 0;
+      state_ = PS_ERROR_HEADERS;
+      unknown_mechanisms_.clear();
+      break;
+    }
+  } else if (_strnicmp(data, "Content-Length:", 15) == 0) {
+    content_length_ = strtoul(data + 15, 0, 0);
+  } else if (_strnicmp(data, "Proxy-Connection: Keep-Alive", 28) == 0) {
+    expect_close_ = false;
+    /*
+  } else if (_strnicmp(data, "Connection: close", 17) == 0) {
+    expect_close_ = true;
+    */
+  }
+}
+
+void AsyncHttpsProxySocket::EndResponse() {
+  if (!expect_close_) {
+    SendRequest();
+    return;
+  }
+
+  // No point in waiting for the server to close... let's close now
+  // TODO: Refactor out PS_WAIT_CLOSE
+  state_ = PS_WAIT_CLOSE;
+  BufferedReadAdapter::Close();
+  OnCloseEvent(this, 0);
+}
+
+void AsyncHttpsProxySocket::Error(int error) {
+  BufferInput(false);
+  Close();
+  SetError(error);
+  SignalCloseEvent(this, error);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+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) {
+}
+
+int AsyncSocksProxySocket::Connect(const SocketAddress& addr) {
+  dest_ = addr;
+  BufferInput(true);
+  return BufferedReadAdapter::Connect(proxy_);
+}
+
+SocketAddress AsyncSocksProxySocket::GetRemoteAddress() const {
+  return dest_;
+}
+
+void AsyncSocksProxySocket::OnConnectEvent(AsyncSocket * socket) {
+  SendHello();
+}
+
+void AsyncSocksProxySocket::ProcessInput(char * data, size_t& len) {
+  ASSERT(state_ < SS_TUNNEL);
+
+  ByteBuffer response(data, len);
+
+  if (state_ == SS_HELLO) {
+    uint8 ver, method;
+    if (!response.ReadUInt8(ver) ||
+        !response.ReadUInt8(method))
+      return;
+
+    if (ver != 5) {
+      Error(0);
+      return;
+    }
+
+    if (method == 0) {
+      SendConnect();
+    } else if (method == 2) {
+      SendAuth();
+    } else {
+      Error(0);
+      return;
+    }
+  } else if (state_ == SS_AUTH) {
+    uint8 ver, status;
+    if (!response.ReadUInt8(ver) ||
+        !response.ReadUInt8(status))
+      return;
+
+    if ((ver != 1) || (status != 0)) {
+      Error(SOCKET_EACCES);
+      return;
+    }
+
+    SendConnect();
+  } else if (state_ == SS_CONNECT) {
+    uint8 ver, rep, rsv, atyp;
+    if (!response.ReadUInt8(ver) ||
+        !response.ReadUInt8(rep) ||
+        !response.ReadUInt8(rsv) ||
+        !response.ReadUInt8(atyp))
+      return;
+
+    if ((ver != 5) || (rep != 0)) {
+      Error(0);
+      return;
+    }
+
+    uint16 port;
+    if (atyp == 1) {
+      uint32 addr;
+      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))
+        return;
+      LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
+    } else if (atyp == 4) {
+      std::string addr;
+      if (!response.ReadString(addr, 16) ||
+          !response.ReadUInt16(port))
+        return;
+      LOG(LS_VERBOSE) << "Bound on <IPV6>:" << port;
+    } else {
+      Error(0);
+      return;
+    }
+
+    state_ = SS_TUNNEL;
+  }
+
+  // Consume parsed data
+  len = response.Length();
+  memcpy(data, response.Data(), len);
+
+  if (state_ != SS_TUNNEL)
+    return;
+
+  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??
+}
+
+void AsyncSocksProxySocket::SendHello() {
+  ByteBuffer request;
+  request.WriteUInt8(5);   // Socks Version
+  if (user_.empty()) {
+    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
+  }
+  DirectSend(request.Data(), request.Length());
+  state_ = SS_HELLO;
+}
+
+void AsyncSocksProxySocket::SendAuth() {
+  ByteBuffer request;
+  request.WriteUInt8(1);      // Negotiation Version
+  request.WriteUInt8(static_cast<uint8>(user_.size()));
+  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
+  memset(sensitive, 0, len);
+  delete [] sensitive;
+  DirectSend(request.Data(), request.Length());
+  state_ = SS_AUTH;
+}
+
+void AsyncSocksProxySocket::SendConnect() {
+  ByteBuffer request;
+  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(static_cast<uint8>(hostname.size()));
+    request.WriteString(hostname);   // Destination Hostname
+  } else {
+    request.WriteUInt8(1);           // IPV4
+    request.WriteUInt32(dest_.ip()); // Destination IP
+  }
+  request.WriteUInt16(dest_.port()); // Destination Port
+  DirectSend(request.Data(), request.Length());
+  state_ = SS_CONNECT;
+}
+
+void AsyncSocksProxySocket::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)
+{
+  label_.append("[");
+  label_.append(label);
+  label_.append("]");
+}
+
+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_);
+  return res;
+}
+
+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_);
+  return res;
+}
+
+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_);
+  return res;
+}
+
+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_);
+  return res;
+}
+
+void
+LoggingSocketAdapter::OnConnectEvent(AsyncSocket * socket) {
+  LOG_V(level_) << label_ << " Connected";
+  AsyncSocketAdapter::OnConnectEvent(socket);
+}
+
+void
+LoggingSocketAdapter::OnCloseEvent(AsyncSocket * socket, int err) {
+  LOG_V(level_) << label_ << " Closed with error: " << err;
+  AsyncSocketAdapter::OnCloseEvent(socket, err);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/socketadapters.h b/talk/base/socketadapters.h
new file mode 100755
index 0000000..6cd6a8f
--- /dev/null
+++ b/talk/base/socketadapters.h
@@ -0,0 +1,170 @@
+/*
+ * 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_SOCKETADAPTERS_H__
+#define TALK_BASE_SOCKETADAPTERS_H__
+
+#include <map>
+#include <string>
+
+#include "talk/base/asyncsocket.h"
+#include "talk/base/cryptstring.h"
+#include "talk/base/logging.h"
+
+namespace talk_base {
+
+struct HttpAuthContext;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class BufferedReadAdapter : public AsyncSocketAdapter {
+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);
+
+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 OnReadEvent(AsyncSocket * socket);
+
+private:
+  char * buffer_;
+  size_t buffer_size_, data_len_;
+  bool buffering_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class AsyncSSLSocket : public BufferedReadAdapter {
+public:
+  AsyncSSLSocket(AsyncSocket* socket);
+
+  virtual int Connect(const SocketAddress& addr);
+
+protected:
+  virtual void OnConnectEvent(AsyncSocket * socket);
+  virtual void ProcessInput(char * data, size_t& len);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class AsyncHttpsProxySocket : public BufferedReadAdapter {
+public:
+  AsyncHttpsProxySocket(AsyncSocket* socket, const std::string& user_agent,
+    const SocketAddress& proxy,
+    const std::string& username, const CryptString& password);
+  virtual ~AsyncHttpsProxySocket();
+
+  virtual int Connect(const SocketAddress& addr);
+  virtual SocketAddress GetRemoteAddress() const;
+  virtual int Close();
+
+protected:
+  virtual void OnConnectEvent(AsyncSocket * socket);
+  virtual void OnCloseEvent(AsyncSocket * socket, int err);
+  virtual void ProcessInput(char * data, size_t& len);
+
+  void SendRequest();
+  void ProcessLine(char * data, size_t len);
+  void EndResponse();
+  void Error(int error);
+
+private:
+  SocketAddress proxy_, dest_;
+  std::string agent_, user_, headers_;
+  CryptString pass_;
+  size_t content_length_;
+  int defer_error_;
+  bool expect_close_;
+  enum ProxyState {
+    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_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class AsyncSocksProxySocket : public BufferedReadAdapter {
+public:
+  AsyncSocksProxySocket(AsyncSocket* socket, const SocketAddress& proxy,
+    const std::string& username, const CryptString& password);
+
+  virtual int Connect(const SocketAddress& addr);
+  virtual SocketAddress GetRemoteAddress() const;
+
+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:
+  SocketAddress proxy_, dest_;
+  std::string user_;
+  CryptString pass_;
+  enum SocksState { SS_HELLO, SS_AUTH, SS_CONNECT, SS_TUNNEL, SS_ERROR } state_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class LoggingSocketAdapter : public AsyncSocketAdapter {
+public:
+  LoggingSocketAdapter(AsyncSocket* socket, LoggingSeverity level,
+                 const char * label, bool hex_mode = false);
+
+  virtual int Send(const void *pv, size_t cb);
+  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);
+
+protected:
+  virtual void OnConnectEvent(AsyncSocket * socket);
+  virtual void OnCloseEvent(AsyncSocket * socket, int err);
+
+private:
+  LoggingSeverity level_;
+  std::string label_;
+  bool hex_mode_;
+  LogMultilineState lms_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SOCKETADAPTERS_H__
diff --git a/talk/base/socketaddress.cc b/talk/base/socketaddress.cc
new file mode 100755
index 0000000..e3a04d1
--- /dev/null
+++ b/talk/base/socketaddress.cc
@@ -0,0 +1,312 @@
+/*
+ * 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 POSIX
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif
+
+#include <cstring>
+#include <sstream>
+
+#include "talk/base/byteorder.h"
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/socketaddress.h"
+
+#ifdef WIN32
+#undef SetPort
+int inet_aton(const char * cp, struct in_addr * inp) {
+  inp->s_addr = inet_addr(cp);
+  return (inp->s_addr == INADDR_NONE) ? 0 : 1;
+}
+#endif // WIN32
+
+#ifdef _DEBUG
+#define DISABLE_DNS 0
+#else // !_DEBUG
+#define DISABLE_DNS 0
+#endif // !_DEBUG
+
+namespace talk_base {
+
+SocketAddress::SocketAddress() {
+  Clear();
+}
+
+SocketAddress::SocketAddress(const std::string& hostname, int port, bool use_dns) {
+  SetIP(hostname, use_dns);
+  SetPort(port);
+}
+
+SocketAddress::SocketAddress(uint32 ip, int port) {
+  SetIP(ip);
+  SetPort(port);
+}
+
+SocketAddress::SocketAddress(const SocketAddress& addr) {
+  this->operator=(addr);
+}
+
+void SocketAddress::Clear() {
+  hostname_.clear();
+  ip_ = 0;
+  port_ = 0;
+}
+
+SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
+  hostname_ = addr.hostname_;
+  ip_ = addr.ip_;
+  port_ = addr.port_;
+  return *this;
+}
+
+void SocketAddress::SetIP(uint32 ip) {
+  hostname_.clear();
+  ip_ = ip;
+}
+
+bool SocketAddress::SetIP(const std::string& hostname, bool use_dns) {
+  hostname_ = hostname;
+  ip_ = 0;
+  return Resolve(true, use_dns);
+}
+
+void SocketAddress::SetResolvedIP(uint32 ip) {
+  ip_ = ip;
+}
+
+void SocketAddress::SetPort(int port) {
+  ASSERT((0 <= port) && (port < 65536));
+  port_ = port;
+}
+
+uint32 SocketAddress::ip() const {
+  return ip_;
+}
+
+uint16 SocketAddress::port() const {
+  return port_;
+}
+
+std::string SocketAddress::IPAsString() const {
+  if (!hostname_.empty())
+    return hostname_;
+  return IPToString(ip_);
+}
+
+std::string SocketAddress::PortAsString() const {
+  std::ostringstream ost;
+  ost << port_;
+  return ost.str();
+}
+
+std::string SocketAddress::ToString() const {
+  std::ostringstream ost;
+  ost << IPAsString();
+  ost << ":";
+  ost << port();
+  return ost.str();
+}
+
+bool SocketAddress::IsAny() const {
+  return (ip_ == 0);
+}
+
+bool SocketAddress::IsLocalIP() const {
+  return (ip_ >> 24) == 127;
+}
+
+bool SocketAddress::IsPrivateIP() const {
+  return ((ip_ >> 24) == 127) ||
+         ((ip_ >> 24) == 10) ||
+         ((ip_ >> 20) == ((172 << 4) | 1)) ||
+         ((ip_ >> 16) == ((192 << 8) | 168));
+}
+
+bool SocketAddress::IsUnresolved() const {
+  return IsAny() && !hostname_.empty();
+}
+
+bool SocketAddress::Resolve(bool force, bool use_dns) {
+  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;
+  }
+  return true;
+}
+
+bool SocketAddress::operator ==(const SocketAddress& addr) const {
+  return EqualIPs(addr) && EqualPorts(addr);
+}
+
+bool SocketAddress::operator <(const SocketAddress& addr) const {
+  if (ip_ < addr.ip_)
+    return true;
+  else if (addr.ip_ < ip_)
+    return false;
+
+  // We only check hostnames if both IPs are zero.  This matches EqualIPs()
+  if (addr.ip_ == 0) {
+    if (hostname_ < addr.hostname_)
+      return true;
+    else if (addr.hostname_ < hostname_)
+      return false;
+  }
+
+  return port_ < addr.port_;
+}
+
+bool SocketAddress::EqualIPs(const SocketAddress& addr) const {
+  return (ip_ == addr.ip_) && ((ip_ != 0) || (hostname_ == addr.hostname_));
+}
+
+bool SocketAddress::EqualPorts(const SocketAddress& addr) const {
+  return (port_ == addr.port_);
+}
+
+size_t SocketAddress::Hash() const {
+  size_t h = 0;
+  h ^= ip_;
+  h ^= port_ | (port_ << 16);
+  return h;
+}
+
+size_t SocketAddress::Size_() const {
+  return sizeof(ip_) + sizeof(port_);
+}
+
+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_;
+}
+
+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];
+}
+
+void SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
+  memset(saddr, 0, sizeof(*saddr));
+  saddr->sin_family = AF_INET;
+  saddr->sin_port = HostToNetwork16(port_);
+  if (0 == ip_) {
+    saddr->sin_addr.s_addr = INADDR_ANY;
+  } else {
+    saddr->sin_addr.s_addr = HostToNetwork32(ip_);
+  }
+}
+
+void SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
+  SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
+  SetPort(NetworkToHost16(saddr.sin_port));
+}
+
+std::string SocketAddress::IPToString(uint32 ip) {
+  std::ostringstream ost;
+  ost << ((ip >> 24) & 0xff);
+  ost << '.';
+  ost << ((ip >> 16) & 0xff);
+  ost << '.';
+  ost << ((ip >> 8) & 0xff);
+  ost << '.';
+  ost << ((ip >> 0) & 0xff);
+  return ost.str();
+}
+
+uint32 SocketAddress::StringToIP(const std::string& hostname, bool use_dns) {
+  uint32 ip = 0;
+  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);
+  }
+  return ip;
+}
+
+std::string SocketAddress::GetHostname() {
+  char hostname[256];
+  if (gethostname(hostname, ARRAY_SIZE(hostname)) == 0)
+    return hostname;
+  return "";
+}
+
+bool SocketAddress::GetLocalIPs(std::vector<uint32>& ips) {
+  ips.clear();
+
+  const std::string hostname = GetHostname();
+  if (hostname.empty())
+    return false;
+
+  if (hostent * pHost = gethostbyname(hostname.c_str())) {
+    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);
+    }
+    return !ips.empty();
+  }
+#if WIN32
+  LOG(LS_ERROR) << "gethostbyname error: " << WSAGetLastError();
+#else
+  LOG(LS_ERROR) << "gethostbyname error: " << strerror(h_errno);
+#endif
+  return false;
+}
+
+} // namespace talk_base
diff --git a/talk/base/socketaddress.h b/talk/base/socketaddress.h
new file mode 100755
index 0000000..7fdc22f
--- /dev/null
+++ b/talk/base/socketaddress.h
@@ -0,0 +1,174 @@
+/*
+ * 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_SOCKETADDRESS_H__
+#define TALK_BASE_SOCKETADDRESS_H__
+
+#include <string>
+#include <vector>
+#include "talk/base/basictypes.h"
+struct sockaddr_in;
+
+#undef SetPort
+
+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.
+  SocketAddress();
+
+  // Creates the address with the given host and port.  If use_dns is true,
+  // the hostname will be immediately resolved to an IP (which may block for
+  // 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);
+
+  // Creates the address with the given IP and port.
+  SocketAddress(uint32 ip, int port);
+
+  // Creates a copy of the given address.
+  SocketAddress(const SocketAddress& addr);
+
+  // Resets to missing / unknown address.
+  void Clear();
+
+  // Replaces our address with the given one.
+  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);
+
+  // Sets the IP address while retaining the hostname.  Useful for bypassing
+  // DNS for a pre-resolved IP.
+  void SetResolvedIP(uint32 ip);
+
+  // Changes the port of this address to the given one.
+  void SetPort(int port);
+
+  // 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.
+  std::string ToString() const;
+
+  // Determines whether this represents a missing / any address.
+  bool IsAny() const;
+
+  // Synomym for missing / any.
+  bool IsNil() const { return IsAny(); }
+
+  // Determines whether the IP address refers to the local host, i.e. within
+  // the range 127.0.0.0/8.
+  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;
+
+  // Attempt to resolve a hostname to IP address.
+  // Returns false if resolution is required but failed.
+  // 'force' will cause re-resolution of hostname.
+  // 
+  bool Resolve(bool force = false, bool use_dns = true);
+
+  // 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);
+  }
+
+  // Compares based on IP and then port.
+  bool operator <(const SocketAddress& addr) const;
+
+  // 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.
+  bool EqualPorts(const SocketAddress& addr) const;
+
+  // Hashes this address into a small number.
+  size_t Hash() const;
+
+  // 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;
+
+  // Reads this address from the given buffer.
+  void Read_(const char* buf, int len);
+
+  // Convert to and from sockaddr_in
+  void ToSockAddr(sockaddr_in* saddr) const;
+  void 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);
+
+  // Get local machine's hostname
+  static std::string GetHostname();
+
+  // Get a list of the local machine's ip addresses
+  static bool GetLocalIPs(std::vector<uint32>& ips);
+
+private:
+  std::string hostname_;
+  uint32 ip_;
+  uint16 port_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SOCKETADDRESS_H__
diff --git a/talk/base/socketaddresspair.cc b/talk/base/socketaddresspair.cc
new file mode 100755
index 0000000..7f190a9
--- /dev/null
+++ b/talk/base/socketaddresspair.cc
@@ -0,0 +1,58 @@
+/*
+ * 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/socketaddresspair.h"
+
+namespace talk_base {
+
+SocketAddressPair::SocketAddressPair(
+    const SocketAddress& src, const SocketAddress& dest)
+    : src_(src), dest_(dest) {
+}
+
+
+bool SocketAddressPair::operator ==(const SocketAddressPair& p) const {
+  return (src_ == p.src_) && (dest_ == p.dest_);
+}
+
+bool SocketAddressPair::operator <(const SocketAddressPair& p) const {
+  if (src_ < p.src_)
+    return true;
+  if (p.src_ < src_)
+    return false;
+  if (dest_ < p.dest_)
+    return true;
+  if (p.dest_ < dest_)
+    return false;
+  return false;
+}
+
+size_t SocketAddressPair::Hash() const {
+  return src_.Hash() ^ dest_.Hash();
+}
+
+} // namespace talk_base
diff --git a/talk/base/socketaddresspair.h b/talk/base/socketaddresspair.h
new file mode 100755
index 0000000..10f5d30
--- /dev/null
+++ b/talk/base/socketaddresspair.h
@@ -0,0 +1,58 @@
+/*
+ * 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_SOCKETADDRESSPAIR_H__
+#define TALK_BASE_SOCKETADDRESSPAIR_H__
+
+#include "talk/base/socketaddress.h"
+
+namespace talk_base {
+
+// Records a pair (source,destination) of socket addresses.  The two addresses
+// identify a connection between two machines.  (For UDP, this "connection" is
+// not maintained explicitly in a socket.)
+class SocketAddressPair {
+public:
+  SocketAddressPair() {}
+  SocketAddressPair(const SocketAddress& srs, const SocketAddress& dest);
+
+  const SocketAddress& source() const { return src_; }
+  const SocketAddress& destination() const { return dest_; }
+
+  bool operator ==(const SocketAddressPair& r) const;
+  bool operator <(const SocketAddressPair& r) const;
+
+  size_t Hash() const;
+
+private:
+  SocketAddress src_;
+  SocketAddress dest_;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SOCKETADDRESSPAIR_H__
diff --git a/talk/base/socketfactory.h b/talk/base/socketfactory.h
new file mode 100755
index 0000000..2a4aee2
--- /dev/null
+++ b/talk/base/socketfactory.h
@@ -0,0 +1,51 @@
+/*
+ * 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_SOCKETFACTORY_H__
+#define TALK_BASE_SOCKETFACTORY_H__
+
+#include "talk/base/socket.h"
+#include "talk/base/asyncsocket.h"
+
+namespace talk_base {
+
+class SocketFactory {
+public:
+  virtual ~SocketFactory() {}
+
+  // Returns a new socket for blocking communication.  The type can be
+  // SOCK_DGRAM and SOCK_STREAM.
+  virtual Socket* CreateSocket(int type) = 0;
+
+  // Returns a new socket for nonblocking communication.  The type can be
+  // SOCK_DGRAM and SOCK_STREAM.
+  virtual AsyncSocket* CreateAsyncSocket(int type) = 0;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SOCKETFACTORY_H__
diff --git a/talk/base/socketpool.cc b/talk/base/socketpool.cc
new file mode 100755
index 0000000..614ce89
--- /dev/null
+++ b/talk/base/socketpool.cc
@@ -0,0 +1,263 @@
+/*
+ * 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 <errno.h>
+
+#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"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamCache - Caches a set of open streams, defers creation to a separate
+//  StreamPool.
+///////////////////////////////////////////////////////////////////////////////
+
+StreamCache::StreamCache(StreamPool* pool) : pool_(pool) {
+}
+
+StreamCache::~StreamCache() {
+  for (ConnectedList::iterator it = active_.begin(); it != active_.end();
+       ++it) {
+    delete it->second;
+  }
+  for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
+       ++it) {
+    delete it->second;
+  }
+}
+
+StreamInterface* StreamCache::RequestConnectedStream(
+    const SocketAddress& remote, int* err) {
+  LOG_F(LS_VERBOSE) << "(" << remote.ToString() << ")";
+  for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
+       ++it) {
+    if (remote == it->first) {
+      it->second->SignalEvent.disconnect(this);
+      // Move from cached_ to active_
+      active_.push_front(*it);
+      cached_.erase(it);
+      if (err)
+        *err = 0;
+      LOG_F(LS_VERBOSE) << "Providing cached stream";
+      return active_.front().second;
+    }
+  }
+  if (StreamInterface* stream = pool_->RequestConnectedStream(remote, err)) {
+    // We track active streams so that we can remember their address
+    active_.push_front(ConnectedStream(remote, stream));
+    LOG_F(LS_VERBOSE) << "Providing new stream";
+    return active_.front().second;
+  }
+  return NULL;
+}
+
+void StreamCache::ReturnConnectedStream(StreamInterface* stream) {
+  for (ConnectedList::iterator it = active_.begin(); it != active_.end();
+       ++it) {
+    if (stream == it->second) {
+      LOG_F(LS_VERBOSE) << "(" << it->first.ToString() << ")";
+      if (stream->GetState() == SS_CLOSED) {
+        // Return closed streams
+        LOG_F(LS_VERBOSE) << "Returning closed stream";
+        pool_->ReturnConnectedStream(it->second);
+      } else {
+        // Monitor open streams
+        stream->SignalEvent.connect(this, &StreamCache::OnStreamEvent);
+        LOG_F(LS_VERBOSE) << "Caching stream";
+        cached_.push_front(*it);
+      }
+      active_.erase(it);
+      return;
+    }
+  }
+  ASSERT(false);
+}
+
+void StreamCache::OnStreamEvent(StreamInterface* stream, int events, int err) {
+  if ((events & SE_CLOSE) == 0) {
+    LOG_F(LS_WARNING) << "(" << events << ", " << err
+                      << ") received non-close event";
+    return;
+  }
+  for (ConnectedList::iterator it = cached_.begin(); it != cached_.end();
+       ++it) {
+    if (stream == it->second) {
+      LOG_F(LS_VERBOSE) << "(" << it->first.ToString() << ")";
+      // We don't cache closed streams, so return it.
+      it->second->SignalEvent.disconnect(this);
+      LOG_F(LS_VERBOSE) << "Returning closed stream";
+      pool_->ReturnConnectedStream(it->second);
+      cached_.erase(it);
+      return;
+    }
+  }
+  ASSERT(false);
+}
+
+//////////////////////////////////////////////////////////////////////
+// NewSocketPool
+//////////////////////////////////////////////////////////////////////
+
+NewSocketPool::NewSocketPool(SocketFactory* factory) : factory_(factory) {
+}
+
+NewSocketPool::~NewSocketPool() {
+  for (size_t i = 0; i < used_.size(); ++i) {
+    delete used_[i];
+  }
+}
+
+StreamInterface* 
+NewSocketPool::RequestConnectedStream(const SocketAddress& remote, int* err) {
+  AsyncSocket* socket = factory_->CreateAsyncSocket(SOCK_STREAM);
+  if (!socket) {
+    ASSERT(false);
+    if (err)
+      *err = -1;
+    return NULL;
+  }
+  if ((socket->Connect(remote) != 0) && !socket->IsBlocking()) {
+    if (err)
+      *err = socket->GetError();
+    delete socket;
+    return NULL;
+  }
+  if (err)
+    *err = 0;
+  return new SocketStream(socket);
+}
+
+void
+NewSocketPool::ReturnConnectedStream(StreamInterface* stream) {
+  used_.push_back(stream);
+}
+
+//////////////////////////////////////////////////////////////////////
+// ReuseSocketPool
+//////////////////////////////////////////////////////////////////////
+
+ReuseSocketPool::ReuseSocketPool(SocketFactory* factory, AsyncSocket* socket)
+  : factory_(factory), stream_(NULL) {
+  stream_ = socket ? new SocketStream(socket) : NULL;
+}
+
+ReuseSocketPool::~ReuseSocketPool() {
+  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) {
+  if (!stream_) {
+    LOG(LS_INFO) << "ReuseSocketPool - Creating new socket";
+    AsyncSocket* socket = factory_->CreateAsyncSocket(SOCK_STREAM);
+    if (!socket) {
+      ASSERT(false);
+      if (err)
+        *err = -1;
+      return NULL;
+    }
+    stream_ = new SocketStream(socket);
+  }
+  if ((stream_->GetState() == SS_OPEN) &&
+      (stream_->GetSocket()->GetRemoteAddress() == remote)) {
+    LOG(LS_INFO) << "ReuseSocketPool - Reusing connection to: "
+                 << remote.ToString();
+  } else {
+    stream_->Close();
+    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();
+    }
+  }
+  if (err)
+    *err = 0;
+  return stream_;
+}
+
+void
+ReuseSocketPool::ReturnConnectedStream(StreamInterface* stream) {
+  // Note: this might not be true with the advent of setSocket
+  ASSERT(stream == stream_);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// LoggingPoolAdapter - Adapts a StreamPool to supply streams with attached
+// LoggingAdapters.
+///////////////////////////////////////////////////////////////////////////////
+
+LoggingPoolAdapter::LoggingPoolAdapter(
+    StreamPool* pool, LoggingSeverity level, const std::string& label,
+    bool binary_mode)
+  : pool_(pool), level_(level), label_(label), binary_mode_(binary_mode) {
+}
+
+LoggingPoolAdapter::~LoggingPoolAdapter() {
+  for (StreamList::iterator it = recycle_bin_.begin();
+       it != recycle_bin_.end(); ++it) {
+    delete *it;
+  }
+}
+
+StreamInterface* LoggingPoolAdapter::RequestConnectedStream(
+    const SocketAddress& remote, int* err) {
+  if (StreamInterface* stream = pool_->RequestConnectedStream(remote, err)) {
+    if (recycle_bin_.empty()) {
+      return new LoggingAdapter(stream, level_, label_, binary_mode_);
+    }
+    LoggingAdapter* logging = recycle_bin_.front();
+    recycle_bin_.pop_front();
+    logging->Attach(stream);
+    return logging;
+  }
+  return NULL;
+}
+
+void LoggingPoolAdapter::ReturnConnectedStream(StreamInterface* stream) {
+  LoggingAdapter* logging = static_cast<LoggingAdapter*>(stream);
+  pool_->ReturnConnectedStream(logging->Detach());
+  recycle_bin_.push_back(logging);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/socketpool.h b/talk/base/socketpool.h
new file mode 100755
index 0000000..edeebaa
--- /dev/null
+++ b/talk/base/socketpool.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.
+ */
+
+#ifndef TALK_BASE_SOCKETPOOL_H__
+#define TALK_BASE_SOCKETPOOL_H__
+
+#include <deque>
+#include <vector>
+#include "talk/base/logging.h"
+#include "talk/base/sigslot.h"
+
+namespace talk_base {
+
+class AsyncSocket;
+class LoggingAdapter;
+class SocketAddress;
+class SocketFactory;
+class SocketStream;
+class StreamInterface;
+
+//////////////////////////////////////////////////////////////////////
+// StreamPool
+//////////////////////////////////////////////////////////////////////
+
+class StreamPool {
+public:
+  virtual ~StreamPool() { }
+
+  virtual StreamInterface* RequestConnectedStream(const SocketAddress& remote,
+                                                  int* err) = 0;
+  virtual void ReturnConnectedStream(StreamInterface* stream) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamCache - Caches a set of open streams, defers creation/destruction to
+//  the supplied StreamPool.
+///////////////////////////////////////////////////////////////////////////////
+
+class StreamCache : public StreamPool, public sigslot::has_slots<> {
+public:
+  StreamCache(StreamPool* pool);
+  virtual ~StreamCache();
+
+  // StreamPool Interface
+  virtual StreamInterface* RequestConnectedStream(const SocketAddress& remote,
+                                                  int* err);
+  virtual void ReturnConnectedStream(StreamInterface* stream);
+
+private:
+  typedef std::pair<SocketAddress, StreamInterface*> ConnectedStream;
+  typedef std::list<ConnectedStream> ConnectedList;
+
+  void OnStreamEvent(StreamInterface* stream, int events, int err);
+
+  // We delegate stream creation and deletion to this pool.
+  StreamPool* pool_;
+  // Streams that are in use (returned from RequestConnectedStream).
+  ConnectedList active_;
+  // Streams which were returned to us, but are still open.
+  ConnectedList cached_;
+};
+
+//////////////////////////////////////////////////////////////////////
+// NewSocketPool //
+///////////////////
+// Creates a new PTcpSocket every time
+//////////////////////////////////////////////////////////////////////
+
+class NewSocketPool : public StreamPool {
+public:
+  NewSocketPool(SocketFactory* factory);
+  virtual ~NewSocketPool();
+  
+  // StreamPool Interface
+  virtual StreamInterface* RequestConnectedStream(const SocketAddress& remote,
+                                                  int* err);
+  virtual void ReturnConnectedStream(StreamInterface* stream);
+  
+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.
+//////////////////////////////////////////////////////////////////////
+
+class ReuseSocketPool : public StreamPool {
+public:
+  ReuseSocketPool(SocketFactory* factory, AsyncSocket* socket = 0);
+  virtual ~ReuseSocketPool();
+
+  void setSocket(AsyncSocket* socket);
+
+  // StreamPool Interface
+  virtual StreamInterface* RequestConnectedStream(const SocketAddress& remote,
+                                                  int* err);
+  virtual void ReturnConnectedStream(StreamInterface* stream);
+  
+private:
+  SocketFactory* factory_;
+  SocketStream* stream_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// LoggingPoolAdapter - Adapts a StreamPool to supply streams with attached
+// LoggingAdapters.
+///////////////////////////////////////////////////////////////////////////////
+
+class LoggingPoolAdapter : public StreamPool {
+public:
+  LoggingPoolAdapter(StreamPool* pool, LoggingSeverity level,
+                     const std::string& label, bool binary_mode);
+  virtual ~LoggingPoolAdapter();
+
+  // StreamPool Interface
+  virtual StreamInterface* RequestConnectedStream(const SocketAddress& remote,
+                                                  int* err);
+  virtual void ReturnConnectedStream(StreamInterface* stream);
+
+private:
+  StreamPool* pool_;
+  LoggingSeverity level_;
+  std::string label_;
+  bool binary_mode_;
+  typedef std::deque<LoggingAdapter*> StreamList;
+  StreamList recycle_bin_;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SOCKETPOOL_H__
diff --git a/talk/base/socketserver.h b/talk/base/socketserver.h
new file mode 100755
index 0000000..e06dd6b
--- /dev/null
+++ b/talk/base/socketserver.h
@@ -0,0 +1,57 @@
+/*
+ * 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_SOCKETSERVER_H__
+#define TALK_BASE_SOCKETSERVER_H__
+
+#include "talk/base/socketfactory.h"
+
+namespace talk_base {
+
+const int kForever = -1;
+
+// Provides the ability to wait for activity on a set of sockets.  The Thread
+// class provides a nice wrapper on a socket server.
+//
+// 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:
+
+  // Sleeps until:
+  //  1) cms milliseconds have elapsed (unless cms == kForever)
+  //  2) WakeUp() is called
+  // While sleeping, I/O is performed if process_io is true.
+  virtual bool Wait(int cms, bool process_io) = 0;
+
+  // Causes the current wait (if one is in progress) to wake up.
+  virtual void WakeUp() = 0;
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_SOCKETSERVER_H__
diff --git a/talk/base/socketstream.h b/talk/base/socketstream.h
new file mode 100755
index 0000000..4d56b75
--- /dev/null
+++ b/talk/base/socketstream.h
@@ -0,0 +1,153 @@
+/*
+ * 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_SOCKET_STREAM_H__
+#define TALK_BASE_SOCKET_STREAM_H__
+
+#include "talk/base/asyncsocket.h"
+#include "talk/base/common.h"
+#include "talk/base/stream.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SocketStream : public StreamInterface, public sigslot::has_slots<> {
+ public:
+  SocketStream(AsyncSocket* socket) : socket_(NULL) {
+    Attach(socket);
+  }
+  virtual ~SocketStream() { delete socket_; }
+
+  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;
+  }
+
+  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 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;
+  }
+
+  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;
+  }
+
+  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; }
+
+ 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);
+  }
+  
+  AsyncSocket* socket_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(SocketStream);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif  // TALK_BASE_SOCKET_STREAM_H__
diff --git a/talk/base/ssladapter.cc b/talk/base/ssladapter.cc
new file mode 100755
index 0000000..68fe038
--- /dev/null
+++ b/talk/base/ssladapter.cc
@@ -0,0 +1,191 @@
+/*
+ * 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/ssladapter.h"
+
+#if !defined(SSL_USE_SCHANNEL) && !defined(SSL_USE_OPENSSL)
+#ifdef WIN32
+#define SSL_USE_SCHANNEL 1
+#else  // !WIN32
+#define SSL_USE_OPENSSL 1
+#endif  // !WIN32
+#endif
+
+#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>
+#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
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace talk_base {
+
+SSLAdapter*
+SSLAdapter::Create(AsyncSocket* socket) {
+  return new DefaultSSLAdapter(socket);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#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 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 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;
+}
+
+#else  // !SSL_USE_OPENSSL
+
+bool InitializeSSL() {
+  return true;
+}
+
+bool InitializeSSLThread() {
+  return true;
+}
+
+bool CleanupSSL() {
+  return true;
+}
+
+#endif  // !SSL_USE_OPENSSL
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
diff --git a/talk/base/ssladapter.h b/talk/base/ssladapter.h
new file mode 100755
index 0000000..0f0155c
--- /dev/null
+++ b/talk/base/ssladapter.h
@@ -0,0 +1,74 @@
+/*
+ * 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_SSLADAPTER_H__
+#define TALK_BASE_SSLADAPTER_H__
+
+#include "talk/base/asyncsocket.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SSLAdapter : public AsyncSocketAdapter {
+public:
+  SSLAdapter(AsyncSocket* socket)
+    : AsyncSocketAdapter(socket), ignore_bad_cert_(false) { }
+
+  bool ignore_bad_cert() const { return ignore_bad_cert_; }
+  void set_ignore_bad_cert(bool ignore) { ignore_bad_cert_ = ignore; }
+
+  // StartSSL returns 0 if successful.
+  // If StartSSL is called while the socket is closed or connecting, the SSL
+  // negotiation will begin as soon as the socket connects.
+  virtual int StartSSL(const char* hostname, bool restartable) = 0;
+
+  // Create the default SSL adapter for this platform
+  static SSLAdapter* Create(AsyncSocket* socket);
+
+private:
+  // If true, the server certificate need not match the configured hostname.
+  bool ignore_bad_cert_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Call this on the main thread, before using SSL.
+// Call CleanupSSLThread when finished with SSL.
+bool InitializeSSL();
+
+// Call to initialize additional threads.
+bool InitializeSSLThread();
+
+// Call to cleanup additional threads, and also the main thread.
+bool CleanupSSL();
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif // TALK_BASE_SSLADAPTER_H__
diff --git a/talk/base/stl_decl.h b/talk/base/stl_decl.h
new file mode 100755
index 0000000..193e7af
--- /dev/null
+++ b/talk/base/stl_decl.h
@@ -0,0 +1,84 @@
+/*
+ * 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
new file mode 100755
index 0000000..50d49a6
--- /dev/null
+++ b/talk/base/stream.cc
@@ -0,0 +1,664 @@
+/*
+ * 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 <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/stream.h"
+#include "talk/base/stringencode.h"
+
+#ifdef WIN32
+#include "talk/base/win32.h"
+#define fileno _fileno
+#endif
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+StreamResult StreamInterface::WriteAll(const void* data, size_t data_len,
+                                       size_t* written, int* error) {
+  StreamResult result = SR_SUCCESS;
+  size_t total_written = 0, current_written;
+  while (total_written < data_len) {
+    result = Write(static_cast<const char*>(data) + total_written,
+                   data_len - total_written, &current_written, error);
+    if (result != SR_SUCCESS)
+      break;
+    total_written += current_written;
+  }
+  if (written)
+    *written = total_written;
+  return result;
+}
+
+StreamResult StreamInterface::ReadAll(void* buffer, size_t buffer_len,
+                                      size_t* read, int* error) {
+  StreamResult result = SR_SUCCESS;
+  size_t total_read = 0, current_read;
+  while (total_read < buffer_len) {
+    result = Read(static_cast<char*>(buffer) + total_read,
+                  buffer_len - total_read, &current_read, error);
+    if (result != SR_SUCCESS)
+      break;
+    total_read += current_read;
+  }
+  if (read)
+    *read = total_read;
+  return result;
+}
+
+StreamResult StreamInterface::ReadLine(std::string* line) {
+  StreamResult result = SR_SUCCESS;
+  while (true) {
+    char ch;
+    result = Read(&ch, sizeof(ch), NULL, NULL);
+    if (result != SR_SUCCESS) {
+      break;
+    }
+    if (ch == '\n') {
+      break;
+    }
+    line->push_back(ch);
+  }
+  if (!line->empty()) {   // give back the line we've collected so far with
+    result = SR_SUCCESS;  // a success code.  Otherwise return the last code
+  }
+  return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamTap
+///////////////////////////////////////////////////////////////////////////////
+
+StreamTap::StreamTap(StreamInterface* stream, StreamInterface* tap)
+: StreamAdapterInterface(stream), tap_(NULL), tap_result_(SR_SUCCESS),
+  tap_error_(0)
+{
+  AttachTap(tap);
+}
+
+void StreamTap::AttachTap(StreamInterface* tap) {
+  tap_.reset(tap);
+}
+
+StreamInterface* StreamTap::DetachTap() { 
+  return tap_.release();
+}
+
+StreamResult StreamTap::GetTapResult(int* error) {
+  if (error) {
+    *error = tap_error_;
+  }
+  return tap_result_;
+}
+
+StreamResult StreamTap::Read(void* buffer, size_t buffer_len,
+                             size_t* read, int* error) {
+  size_t backup_read;
+  if (!read) {
+    read = &backup_read;
+  }
+  StreamResult res = StreamAdapterInterface::Read(buffer, buffer_len,
+                                                  read, error);
+  if ((res == SR_SUCCESS) && (tap_result_ == SR_SUCCESS)) {
+    tap_result_ = tap_->WriteAll(buffer, *read, NULL, &tap_error_);
+  }
+  return res;
+}
+
+StreamResult StreamTap::Write(const void* data, size_t data_len,
+                              size_t* written, int* error) {
+  size_t backup_written;
+  if (!written) {
+    written = &backup_written;
+  }
+  StreamResult res = StreamAdapterInterface::Write(data, data_len,
+                                                   written, error);
+  if ((res == SR_SUCCESS) && (tap_result_ == SR_SUCCESS)) {
+    tap_result_ = tap_->WriteAll(data, *written, NULL, &tap_error_);
+  }
+  return res;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// NullStream
+///////////////////////////////////////////////////////////////////////////////
+
+NullStream::NullStream() {
+}
+
+NullStream::~NullStream() {
+}
+
+StreamState NullStream::GetState() const {
+  return SS_OPEN;
+}
+
+StreamResult NullStream::Read(void* buffer, size_t buffer_len,
+                              size_t* read, int* error) {
+  if (error) *error = -1;
+  return SR_ERROR;
+}
+
+
+StreamResult NullStream::Write(const void* data, size_t data_len,
+                               size_t* written, int* error) {
+  if (written) *written = data_len;
+  return SR_SUCCESS;
+}
+
+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
+///////////////////////////////////////////////////////////////////////////////
+
+FileStream::FileStream() : file_(NULL) {
+}
+
+FileStream::~FileStream() {
+  FileStream::Close();
+}
+
+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);
+  } else {
+    file_ = NULL;
+  }
+
+  delete[] wfilename;
+  delete[] wmode;
+#else
+  file_ = fopen(filename.c_str(), mode);
+#endif
+  return (file_ != NULL);
+}
+
+bool FileStream::OpenShare(const std::string& filename, const char* mode,
+                           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);
+  } else {
+    file_ = NULL;
+  }
+
+  delete[] wfilename;
+  delete[] wmode;
+#else
+  return Open(filename, mode);
+#endif
+  return (file_ != NULL);
+}
+
+bool FileStream::DisableBuffering() {
+  if (!file_)
+    return false;
+  return (setvbuf(file_, NULL, _IONBF, 0) == 0);
+}
+
+StreamState FileStream::GetState() const {
+  return (file_ == NULL) ? SS_CLOSED : SS_OPEN;
+}
+
+StreamResult FileStream::Read(void* buffer, size_t buffer_len,
+                              size_t* read, int* error) {
+  if (!file_)
+    return SR_EOS;
+  size_t result = fread(buffer, 1, buffer_len, file_);
+  if ((result == 0) && (buffer_len > 0)) {
+    if (feof(file_))
+      return SR_EOS;
+    if (error)
+      *error = errno;
+    return SR_ERROR;
+  }
+  if (read)
+    *read = result;
+  return SR_SUCCESS;
+}
+
+StreamResult FileStream::Write(const void* data, size_t data_len,
+                               size_t* written, int* error) {
+  if (!file_)
+    return SR_EOS;
+  size_t result = fwrite(data, 1, data_len, file_);
+  if ((result == 0) && (data_len > 0)) {
+    if (error)
+      *error = errno;
+    return SR_ERROR;
+  }
+  if (written)
+    *written = result;
+  return SR_SUCCESS;
+}
+
+void FileStream::Close() {
+  if (file_) {
+    fclose(file_);
+    file_ = NULL;
+  }
+}
+
+bool FileStream::SetPosition(size_t position) {
+  if (!file_)
+    return false;
+  return (fseek(file_, position, SEEK_SET) == 0);
+}
+
+bool FileStream::GetPosition(size_t * position) const {
+  ASSERT(position != NULL);
+  if (!file_ || !position)
+    return false;
+  long result = ftell(file_);
+  if (result < 0)
+    return false;
+  *position = result;
+  return true;
+}
+
+bool FileStream::GetSize(size_t * size) const {
+  ASSERT(size != NULL);
+  if (!file_ || !size)
+    return false;
+  struct stat file_stats;
+  if (fstat(fileno(file_), &file_stats) != 0)
+    return false;
+  *size = file_stats.st_size;
+  return true;
+}
+
+bool FileStream::ReserveSize(size_t size) {
+  // TODO: extend the file to the proper length
+  return true;
+}
+
+bool FileStream::GetSize(const std::string& filename, size_t* size) {
+  struct stat file_stats;
+  if (stat(filename.c_str(), &file_stats) != 0)
+    return false;
+  *size = file_stats.st_size;
+  return true;
+}
+
+int FileStream::Flush() {
+  if (file_) {
+    return fflush (file_);
+  }
+  // try to flush empty file?
+  ASSERT(false);
+  return 0;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+
+MemoryStream::MemoryStream()
+  : allocated_length_(0), buffer_(NULL), 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 {
+  return SS_OPEN;
+}
+
+StreamResult MemoryStream::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) {
+    // Read partial buffer
+    bytes = remaining_length;
+  }
+  memcpy(buffer, &buffer_[seek_position_], bytes);
+  seek_position_ += bytes;
+  if (bytes_read) {
+    *bytes_read = bytes;
+  }
+  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_) {
+    // 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;
+    }
+  }
+
+  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_written) {
+    *bytes_written = bytes_written_value;
+  }
+  if (error) {
+    *error = error_value;
+  }
+
+  return sr;
+}
+
+void MemoryStream::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) {
+    return false;
+  }
+  *position = seek_position_;
+  return true;
+}
+
+bool MemoryStream::GetSize(size_t *size) const {
+  if (!size) {
+    return false;
+  }
+  *size = data_length_;
+  return true;
+}
+
+bool MemoryStream::ReserveSize(size_t size) {
+  if (allocated_length_ >= size)
+    return true;
+
+  if (char* new_buffer = new char[size]) {
+    memcpy(new_buffer, buffer_, data_length_);
+    delete [] buffer_;
+    buffer_ = new_buffer;
+    allocated_length_ = size;
+    return true;
+  }
+
+  return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+StreamResult Flow(StreamInterface* source,
+                  char* buffer, size_t buffer_len,
+                  StreamInterface* sink) {
+  ASSERT(buffer_len > 0);
+
+  StreamResult result;
+  size_t count, read_pos, write_pos;
+
+  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));
+
+    // 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;
+
+      write_pos += count;
+    } while (write_pos < read_pos);
+  } while (!end_of_stream);
+
+  return SR_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+LoggingAdapter::LoggingAdapter(StreamInterface* stream, LoggingSeverity level,
+                               const std::string& label, bool hex_mode)
+: StreamAdapterInterface(stream), level_(level), hex_mode_(hex_mode)
+{
+  label_.append("[");
+  label_.append(label);
+  label_.append("]");
+}
+
+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);
+  if (result == SR_SUCCESS) {
+    LogMultiline(level_, label_.c_str(), true,
+                 static_cast<const char *>(buffer), *read, hex_mode_, &lms_);
+  }
+  return result;
+}
+
+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);
+  if (result == SR_SUCCESS) {
+    LogMultiline(level_, label_.c_str(), false,
+                 static_cast<const char *>(data), *written, hex_mode_, &lms_);
+  }
+  return result;
+}
+
+void LoggingAdapter::Close() {
+  LOG_V(level_) << label_ << " Closed locally";
+  StreamAdapterInterface::Close();
+}
+
+void LoggingAdapter::OnEvent(StreamInterface* stream, int events, int err) {
+  if (events & SE_OPEN) {
+    LOG_V(level_) << label_ << " Open";
+  } else if (events & SE_CLOSE) {
+    LOG_V(level_) << label_ << " Closed with error: " << err;
+  }
+  StreamAdapterInterface::OnEvent(stream, events, err);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream - Reads/Writes to an external std::string
+///////////////////////////////////////////////////////////////////////////////
+
+StringStream::StringStream(std::string& str)
+: str_(str), read_pos_(0), read_only_(false)
+{
+}
+
+StringStream::StringStream(const std::string& str)
+: str_(const_cast<std::string&>(str)), read_pos_(0), read_only_(true)
+{
+}
+
+StreamState StringStream::GetState() const {
+  return SS_OPEN;
+}
+
+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_);
+  if (!available)
+    return SR_EOS;
+  memcpy(buffer, str_.data() + read_pos_, available);
+  read_pos_ += available;
+  if (read)
+    *read = available;
+  return SR_SUCCESS;
+}
+
+StreamResult StringStream::Write(const void* data, size_t data_len,
+                                      size_t* written, int* error) {
+  if (read_only_) {
+    if (error) {
+      *error = -1;
+    }
+    return SR_ERROR;
+  }
+  str_.append(static_cast<const char*>(data),
+              static_cast<const char*>(data) + data_len);
+  if (written)
+    *written = data_len;
+  return SR_SUCCESS;
+}
+
+void StringStream::Close() {
+}
+
+bool StringStream::GetSize(size_t* size) const {
+  ASSERT(size != NULL);
+  *size = str_.size();
+  return true;
+}
+
+bool StringStream::ReserveSize(size_t size) {
+  if (read_only_)
+    return false;
+  str_.reserve(size);
+  return true;
+}
+
+bool StringStream::Rewind() {
+  read_pos_ = 0;
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
diff --git a/talk/base/stream.h b/talk/base/stream.h
new file mode 100755
index 0000000..cb91bb7
--- /dev/null
+++ b/talk/base/stream.h
@@ -0,0 +1,396 @@
+/*
+ * 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_STREAM_H__
+#define TALK_BASE_STREAM_H__
+
+#include "talk/base/basictypes.h"
+#include "talk/base/logging.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/sigslot.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+///////////////////////////////////////////////////////////////////////////////
+
+// The following enumerations are declared outside of the StreamInterface
+// class for brevity in use.
+
+// The SS_OPENING state indicates that the stream will signal open or closed
+// in the future.
+enum StreamState { SS_CLOSED, SS_OPENING, SS_OPEN };
+
+// Stream read/write methods return this value to indicate various success
+// and failure conditions described below.
+enum StreamResult { SR_ERROR, SR_SUCCESS, SR_BLOCK, SR_EOS };
+
+// StreamEvents are used to asynchronously signal state transitionss.  The flags
+// may be combined.
+//  SE_OPEN: The stream has transitioned to the SS_OPEN state
+//  SE_CLOSE: The stream has transitioned to the SS_CLOSED state
+//  SE_READ: Data is available, so Read is likely to not return SR_BLOCK
+//  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 {
+ public:
+  virtual ~StreamInterface() { }
+
+  virtual StreamState GetState() const = 0;
+
+  // Read attempts to fill buffer of size buffer_len.  Write attempts to send
+  // data_len bytes stored in data.  The variables read and write are set only
+  // on SR_SUCCESS (see below).  Likewise, error is only set on SR_ERROR.
+  // Read and Write return a value indicating:
+  //  SR_ERROR: an error occurred, which is returned in a non-null error
+  //    argument.  Interpretation of the error requires knowledge of the
+  //    stream's concrete type, which limits its usefulness.
+  //  SR_SUCCESS: some number of bytes were successfully written, which is
+  //    returned in a non-null read/write argument.
+  //  SR_BLOCK: the stream is in non-blocking mode, and the operation would
+  //    block, or the stream is in SS_OPENING state.
+  //  SR_EOS: the end-of-stream has been reached, or the stream is in the
+  //    SS_CLOSED state.
+  virtual StreamResult Read(void* buffer, size_t buffer_len,
+                            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;
+
+  // 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, 
+  // 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;
+
+  // Returns true if stream could be repositioned to the beginning.
+  virtual bool Rewind() = 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
+  // unlike Write, the argument 'written' is always set, and may be non-zero
+  // on results other than SR_SUCCESS.  The remaining arguments have the
+  // same semantics as Write.
+  StreamResult WriteAll(const void* data, size_t data_len,
+                        size_t* written, int* error);
+
+  // Similar to ReadAll.  Calls Read until buffer_len bytes have been read, or
+  // until a non-SR_SUCCESS result is returned.  'read' is always set.
+  StreamResult ReadAll(void* buffer, size_t buffer_len,
+                       size_t* read, int* error);
+
+  // ReadLine is a helper function which repeatedly calls Read until it hits
+  // the end-of-line character, or something other than SR_SUCCESS.
+  // TODO: this is too inefficient to keep here.  Break this out into a buffered
+  // 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() { }
+
+ private:
+  DISALLOW_EVIL_CONSTRUCTORS(StreamInterface);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+///////////////////////////////////////////////////////////////////////////////
+
+class StreamAdapterInterface : public StreamInterface,
+                               public sigslot::has_slots<> {
+ public:
+  explicit StreamAdapterInterface(StreamInterface* stream) {
+    Attach(stream);
+  }
+
+  virtual StreamState GetState() const {
+    return stream_->GetState();
+  }
+  virtual StreamResult Read(void* buffer, size_t buffer_len,
+                            size_t* read, int* error) {
+    return stream_->Read(buffer, buffer_len, read, error);
+  }
+  virtual StreamResult Write(const void* data, size_t data_len,
+                             size_t* written, int* error) {
+    return stream_->Write(data, data_len, written, error);
+  }
+  virtual void Close() {
+    stream_->Close();
+  }
+  virtual bool GetSize(size_t* size) const {
+    return stream_->GetSize(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();
+  }
+
+ protected:
+  // 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);
+  }
+
+ private:
+  scoped_ptr<StreamInterface> stream_;
+  DISALLOW_EVIL_CONSTRUCTORS(StreamAdapterInterface);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamTap is a non-modifying, pass-through adapter, which copies all data
+// in either direction to the tap.  Note that errors or blocking on writing to
+// the tap will prevent further tap writes from occurring.
+///////////////////////////////////////////////////////////////////////////////
+
+class StreamTap : public StreamAdapterInterface {
+ public:
+  explicit StreamTap(StreamInterface* stream, StreamInterface* tap);
+
+  void AttachTap(StreamInterface* tap);
+  StreamInterface* DetachTap();
+  StreamResult GetTapResult(int* error);
+
+  // StreamAdapterInterface Interface
+  virtual StreamResult Read(void* buffer, size_t buffer_len,
+                            size_t* read, int* error);
+  virtual StreamResult Write(const void* data, size_t data_len,
+                             size_t* written, int* error);
+
+ private:
+  scoped_ptr<StreamInterface> tap_;
+  StreamResult tap_result_;
+  int tap_error_;
+  DISALLOW_EVIL_CONSTRUCTORS(StreamTap);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// NullStream gives errors on read, and silently discards all written data.
+///////////////////////////////////////////////////////////////////////////////
+
+class NullStream : public StreamInterface {
+ public:
+  NullStream();
+  virtual ~NullStream();
+
+  // StreamInterface Interface
+  virtual StreamState GetState() const;
+  virtual StreamResult Read(void* buffer, size_t buffer_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 bool GetSize(size_t* size) const;
+  virtual bool ReserveSize(size_t size);
+  virtual bool Rewind();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// FileStream is a simple implementation of a StreamInterface, which does not
+// support asynchronous notification.
+///////////////////////////////////////////////////////////////////////////////
+
+class FileStream : public StreamInterface {
+ public:
+  FileStream();
+  virtual ~FileStream();
+
+  // The semantics of filename and mode are the same as stdio's fopen
+  virtual bool Open(const std::string& filename, const char* mode);
+  virtual bool OpenShare(const std::string& filename, const char* mode,
+                         int shflag);
+
+  // By default, reads and writes are buffered for efficiency.  Disabling
+  // buffering causes writes to block until the bytes on disk are updated.
+  virtual bool DisableBuffering();
+
+  virtual StreamState GetState() const;
+  virtual StreamResult Read(void* buffer, size_t buffer_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 bool GetSize(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();
+  static bool GetSize(const std::string& filename, size_t* size);
+
+ private:
+  FILE* file_;
+  DISALLOW_EVIL_CONSTRUCTORS(FileStream);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryStream is a simple implementation of a StreamInterface over in-memory
+// data.  It does not support asynchronous notification.
+///////////////////////////////////////////////////////////////////////////////
+
+class MemoryStream : 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 void Close();
+  virtual bool GetSize(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;
+
+ private:
+  void SetContents(const char* data, size_t length);
+
+  size_t   allocated_length_;
+  char*    buffer_;
+  size_t   data_length_;
+  size_t   seek_position_;
+
+ private:
+  DISALLOW_EVIL_CONSTRUCTORS(MemoryStream);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class LoggingAdapter : public StreamAdapterInterface {
+public:
+  LoggingAdapter(StreamInterface* stream, LoggingSeverity level,
+                 const std::string& label, bool hex_mode = false);
+
+  virtual StreamResult Read(void* buffer, size_t buffer_len,
+                            size_t* read, int* error);
+  virtual StreamResult Write(const void* data, size_t data_len,
+                             size_t* written, int* error);
+  virtual void Close();
+
+ protected:
+  virtual void OnEvent(StreamInterface* stream, int events, int err);
+
+ private:
+  LoggingSeverity level_;
+  std::string label_;
+  bool hex_mode_;
+  LogMultilineState lms_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(LoggingAdapter);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream - Reads/Writes to an external std::string
+///////////////////////////////////////////////////////////////////////////////
+
+class StringStream : public StreamInterface {
+public:
+  StringStream(std::string& str);
+  StringStream(const std::string& str);
+
+  virtual StreamState GetState() const;
+  virtual StreamResult Read(void* buffer, size_t buffer_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 bool GetSize(size_t* size) const;
+  virtual bool ReserveSize(size_t size);
+  virtual bool Rewind();
+
+private:
+  std::string& str_;
+  size_t read_pos_;
+  bool read_only_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Flow attempts to move bytes from source to sink via buffer of size
+// buffer_len.  The function returns SR_SUCCESS when source reaches
+// end-of-stream (returns SR_EOS), and all the data has been written successful
+// 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.
+
+StreamResult Flow(StreamInterface* source,
+                  char* buffer, size_t buffer_len,
+                  StreamInterface* sink);
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif  // TALK_BASE_STREAM_H__
diff --git a/talk/base/streamutils.cc b/talk/base/streamutils.cc
new file mode 100755
index 0000000..52e6da7
--- /dev/null
+++ b/talk/base/streamutils.cc
@@ -0,0 +1,194 @@
+/*
+ * 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
new file mode 100755
index 0000000..7bb07a3
--- /dev/null
+++ b/talk/base/streamutils.h
@@ -0,0 +1,94 @@
+/*
+ * 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
new file mode 100755
index 0000000..1f98124
--- /dev/null
+++ b/talk/base/stringdigest.cc
@@ -0,0 +1,49 @@
+/*
+ * 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/md5.h"
+#include "talk/base/stringdigest.h"
+#include "talk/base/stringencode.h"
+
+namespace talk_base {
+
+std::string MD5(const std::string& data) {
+  MD5_CTX ctx;
+  MD5Init(&ctx);
+  MD5Update(&ctx, const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(data.data())), static_cast<unsigned int>(data.size()));
+  unsigned char digest[16];
+  MD5Final(digest, &ctx);
+  std::string hex_digest;
+  for (int i=0; i<16; ++i) {
+    hex_digest += hex_encode(digest[i] >> 4);
+    hex_digest += hex_encode(digest[i] & 0xf);
+  }
+  return hex_digest;
+}
+
+}  // namespace talk_base
diff --git a/talk/base/stringdigest.h b/talk/base/stringdigest.h
new file mode 100755
index 0000000..d75d845
--- /dev/null
+++ b/talk/base/stringdigest.h
@@ -0,0 +1,47 @@
+/*
+ * 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_STRINGDIGEST_H__
+#define TALK_BASE_STRINGDIGEST_H__
+
+#include <string>
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// Message Digest Utilities
+//////////////////////////////////////////////////////////////////////
+
+// Compute the MD5 message digest of data, and return it in 
+std::string MD5(const std::string& data);
+
+//////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif  // TALK_BASE_STRINGDIGEST_H__
diff --git a/talk/base/stringencode.cc b/talk/base/stringencode.cc
new file mode 100755
index 0000000..ed6edfc
--- /dev/null
+++ b/talk/base/stringencode.cc
@@ -0,0 +1,579 @@
+/*
+ * 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 WIN32
+#include <malloc.h>
+#endif  // WIN32
+#ifdef POSIX
+#include <alloca.h>
+#define _alloca alloca
+#endif  // POSIX
+
+#include "talk/base/basictypes.h"
+#include "talk/base/common.h"
+#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
+
+namespace talk_base {
+
+/////////////////////////////////////////////////////////////////////////////
+// String Encoding Utilities
+/////////////////////////////////////////////////////////////////////////////
+
+static const char HEX[] = "0123456789abcdef";
+
+char hex_encode(unsigned char val) {
+  ASSERT(val < 16);
+  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);
+}
+
+size_t escape(char * buffer, size_t buflen,
+              const char * source, size_t srclen,
+              const char * illegal, char escape) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  size_t srcpos = 0, bufpos = 0;
+  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
+    char ch = source[srcpos++];
+    if ((ch == escape) || ::strchr(illegal, ch)) {
+      if (bufpos + 2 >= buflen)
+        break;
+      buffer[bufpos++] = escape;
+    }
+    buffer[bufpos++] = ch;
+  }
+
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t unescape(char * buffer, size_t buflen,
+                const char * source, size_t srclen,
+                char escape) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  size_t srcpos = 0, bufpos = 0;
+  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
+    char ch = source[srcpos++];
+    if ((ch == escape) && (srcpos < srclen)) {
+      ch = source[srcpos++];
+    }
+    buffer[bufpos++] = ch;
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t encode(char * buffer, size_t buflen,
+              const char * source, size_t srclen,
+              const char * illegal, char escape) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  size_t srcpos = 0, bufpos = 0;
+  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
+    char ch = source[srcpos++];
+    if ((ch != escape) && !::strchr(illegal, ch)) {
+      buffer[bufpos++] = ch;
+    } else if (bufpos + 3 >= buflen) {
+      break;
+    } else {
+      buffer[bufpos+0] = escape;
+      buffer[bufpos+1] = hex_encode((static_cast<unsigned char>(ch) >> 4) & 0xF);
+      buffer[bufpos+2] = hex_encode((static_cast<unsigned char>(ch)     ) & 0xF);
+      bufpos += 3;
+    }
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t decode(char * buffer, size_t buflen,
+              const char * source, size_t srclen,
+              char escape) {
+  if (buflen <= 0)
+    return 0;
+
+  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]);
+      srcpos += 2;
+    } else {
+      buffer[bufpos++] = ch;
+    }
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+const char* unsafe_filename_characters() {
+  // It might be better to have a single specification which is the union of
+  // all operating systems, unless one system is overly restrictive.
+#ifdef WIN32
+  return "\\/:*?\"<>|";
+#else  // !WIN32
+  // TODO
+#endif  // !WIN23
+}
+
+const unsigned char URL_UNSAFE  = 0x1; // 0-33 "#$%&+,/:;<=>?@[\]^`{|} 127
+const unsigned char XML_UNSAFE  = 0x2; // "&'<>
+const unsigned char HTML_UNSAFE = 0x2; // "&'<>
+
+//  ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 6 5 7 8 9 : ; < = > ?
+//@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
+//` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ 
+
+const unsigned char ASCII_CLASS[128] = {
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  1,0,3,1,1,1,3,2,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,3,1,3,1,
+  1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,
+  1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,
+};
+
+size_t url_encode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen) {
+  if (NULL == buffer)
+    return srclen * 3 + 1;
+  if (buflen <= 0)
+    return 0;
+
+  size_t srcpos = 0, bufpos = 0;
+  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
+    unsigned char ch = source[srcpos++];
+    if ((ch < 128) && (ASCII_CLASS[ch] & URL_UNSAFE)) {
+      if (bufpos + 3 >= buflen) {
+        break;
+      }
+      buffer[bufpos+0] = '%';
+      buffer[bufpos+1] = hex_encode((ch >> 4) & 0xF);
+      buffer[bufpos+2] = hex_encode((ch     ) & 0xF);
+      bufpos += 3;
+    } else {
+      buffer[bufpos++] = ch;
+    }
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t url_decode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen) {
+  if (NULL == buffer)
+    return srclen + 1;
+  if (buflen <= 0)
+    return 0;
+
+  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]);
+      srcpos += 2;
+    } else {
+      buffer[bufpos++] = ch;
+    }
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t utf8_decode(const char* source, size_t srclen, unsigned long* value) {
+  const unsigned char* s = reinterpret_cast<const unsigned char*>(source);
+  if ((s[0] & 0x80) == 0x00) {                    // Check s[0] == 0xxxxxxx
+    *value = s[0];
+    return 1;
+  }
+  if ((srclen < 2) || ((s[1] & 0xC0) != 0x80)) {  // Check s[1] != 10xxxxxx
+    return 0;
+  }
+  // Accumulate the trailer byte values in value16, and combine it with the
+  // relevant bits from s[0], once we've determined the sequence length.
+  unsigned long value16 = (s[1] & 0x3F);
+  if ((s[0] & 0xE0) == 0xC0) {                    // Check s[0] == 110xxxxx
+    *value = ((s[0] & 0x1F) << 6) | value16;
+    return 2;
+  }
+  if ((srclen < 3) || ((s[2] & 0xC0) != 0x80)) {  // Check s[2] != 10xxxxxx
+    return 0;
+  }
+  value16 = (value16 << 6) | (s[2] & 0x3F);
+  if ((s[0] & 0xF0) == 0xE0) {                    // Check s[0] == 1110xxxx 
+    *value = ((s[0] & 0x0F) << 12) | value16;
+    return 3;
+  }
+  if ((srclen < 4) || ((s[3] & 0xC0) != 0x80)) {  // Check s[3] != 10xxxxxx
+    return 0;
+  }
+  value16 = (value16 << 6) | (s[3] & 0x3F);
+  if ((s[0] & 0xF8) == 0xF0) {                    // Check s[0] == 11110xxx 
+    *value = ((s[0] & 0x07) << 18) | value16;
+    return 4;
+  }
+  return 0;
+}
+
+size_t utf8_encode(char* buffer, size_t buflen, unsigned long value) {
+  if ((value <= 0x7F) && (buflen >= 1)) {
+    buffer[0] = static_cast<unsigned char>(value);
+    return 1;
+  }
+  if ((value <= 0x7FF) && (buflen >= 2)) {
+    buffer[0] = 0xC0 | static_cast<unsigned char>(value >> 6);
+    buffer[1] = 0x80 | static_cast<unsigned char>(value & 0x3F);
+    return 2;
+  }
+  if ((value <= 0xFFFF) && (buflen >= 3)) {
+    buffer[0] = 0xE0 | static_cast<unsigned char>(value >> 12);
+    buffer[1] = 0x80 | static_cast<unsigned char>((value >> 6) & 0x3F);
+    buffer[2] = 0x80 | static_cast<unsigned char>(value & 0x3F);
+    return 3;
+  }
+  if ((value <= 0x1FFFFF) && (buflen >= 4)) {
+    buffer[0] = 0xF0 | static_cast<unsigned char>(value >> 18);
+    buffer[1] = 0x80 | static_cast<unsigned char>((value >> 12) & 0x3F);
+    buffer[2] = 0x80 | static_cast<unsigned char>((value >> 6) & 0x3F);
+    buffer[3] = 0x80 | static_cast<unsigned char>(value & 0x3F);
+    return 4;
+  }
+  return 0;
+}
+
+size_t html_encode(char * buffer, size_t buflen,
+                   const char * source, size_t srclen) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  size_t srcpos = 0, bufpos = 0;
+  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
+    unsigned char ch = source[srcpos];
+    if (ch < 128) {
+      srcpos += 1;
+      if (ASCII_CLASS[ch] & HTML_UNSAFE) {
+        const char * escseq = 0;
+        size_t esclen = 0;
+        switch (ch) {
+          case '<':  escseq = "&lt;";   esclen = 4; break;
+          case '>':  escseq = "&gt;";   esclen = 4; break;
+          case '\'': escseq = "&#39;";  esclen = 5; break;
+          case '\"': escseq = "&quot;"; esclen = 6; break;
+          case '&':  escseq = "&amp;";  esclen = 5; break;
+          default: ASSERT(false);
+        }
+        if (bufpos + esclen >= buflen) {
+          break;
+        }
+        memcpy(buffer + bufpos, escseq, esclen);
+        bufpos += esclen;
+      } else {
+        buffer[bufpos++] = ch;
+      }
+    } else {
+      // Largest value is 0x1FFFFF => &#2097151;  (10 characters)
+      char escseq[11];
+      unsigned long val;
+      if (size_t vallen = utf8_decode(&source[srcpos], srclen - srcpos, &val)) {
+        srcpos += vallen;
+      } else {
+        // Not a valid utf8 sequence, just use the raw character.
+        val = static_cast<unsigned char>(source[srcpos++]);
+      }
+      size_t esclen = sprintfn(escseq, ARRAY_SIZE(escseq), "&#%lu;", val);
+      if (bufpos + esclen >= buflen) {
+        break;
+      }
+      memcpy(buffer + bufpos, escseq, esclen);
+      bufpos += esclen;
+    }
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t html_decode(char * buffer, size_t buflen,
+                   const char * source, size_t srclen) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  return xml_decode(buffer, buflen, source, srclen);
+}
+
+size_t xml_encode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  size_t srcpos = 0, bufpos = 0;
+  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
+    unsigned char ch = source[srcpos++];
+    if ((ch < 128) && (ASCII_CLASS[ch] & XML_UNSAFE)) {
+      const char * escseq = 0;
+      size_t esclen = 0;
+      switch (ch) {
+        case '<':  escseq = "&lt;";   esclen = 4; break;
+        case '>':  escseq = "&gt;";   esclen = 4; break;
+        case '\'': escseq = "&apos;"; esclen = 6; break;
+        case '\"': escseq = "&quot;"; esclen = 6; break;
+        case '&':  escseq = "&amp;";  esclen = 5; break;
+        default: ASSERT(false);
+      }
+      if (bufpos + esclen >= buflen) {
+        break;
+      }
+      memcpy(buffer + bufpos, escseq, esclen);
+      bufpos += esclen;
+    } else {
+      buffer[bufpos++] = ch;
+    }
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t xml_decode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  size_t srcpos = 0, bufpos = 0;
+  while ((srcpos < srclen) && (bufpos + 1 < buflen)) {
+    unsigned char ch = source[srcpos++];
+    if (ch != '&') {
+      buffer[bufpos++] = ch;
+    } else if ((srcpos + 2 < srclen)
+               && (memcmp(source + srcpos, "lt;", 3) == 0)) {
+      buffer[bufpos++] = '<';
+      srcpos += 3;
+    } else if ((srcpos + 2 < srclen)
+               && (memcmp(source + srcpos, "gt;", 3) == 0)) {
+      buffer[bufpos++] = '>';
+      srcpos += 3;
+    } else if ((srcpos + 4 < srclen)
+               && (memcmp(source + srcpos, "apos;", 5) == 0)) {
+      buffer[bufpos++] = '\'';
+      srcpos += 5;
+    } else if ((srcpos + 4 < srclen)
+               && (memcmp(source + srcpos, "quot;", 5) == 0)) {
+      buffer[bufpos++] = '\"';
+      srcpos += 5;
+    } else if ((srcpos + 3 < srclen)
+               && (memcmp(source + srcpos, "amp;", 4) == 0)) {
+      buffer[bufpos++] = '&';
+      srcpos += 4;
+    } else if ((srcpos < srclen) && (source[srcpos] == '#')) {
+      int int_base = 10;
+      if ((srcpos + 1 < srclen) && (source[srcpos+1] == 'x')) {
+        int_base = 16;
+        srcpos += 1;
+      }
+      char * ptr;
+      // TODO: Fix hack (ptr may go past end of data)
+      unsigned long val = strtoul(source + srcpos + 1, &ptr, int_base);
+      if ((static_cast<size_t>(ptr - source) < srclen) && (*ptr == ';')) {
+        srcpos = ptr - source + 1;
+      } else {
+        // Not a valid escape sequence.
+        break;
+      }
+      if (size_t esclen = utf8_encode(buffer + bufpos, buflen - bufpos, val)) {
+        bufpos += esclen;
+      } else {
+        // Not enough room to encode the character, or illegal character
+        break;
+      }
+    } else {
+      // Unrecognized escape sequence.
+      break;
+    }
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t hex_encode(char * buffer, size_t buflen,
+                  const char * csource, size_t srclen) {
+  ASSERT(NULL != buffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  const unsigned char * bsource =
+    reinterpret_cast<const unsigned char *>(csource);
+
+  size_t srcpos = 0, bufpos = 0;
+  srclen = _min(srclen, (buflen - 1) / 2);
+  while (srcpos < srclen) {
+    unsigned char ch = bsource[srcpos++];
+    buffer[bufpos  ] = hex_encode((ch >> 4) & 0xF);
+    buffer[bufpos+1] = hex_encode((ch     ) & 0xF);
+    bufpos += 2;
+  }
+  buffer[bufpos] = '\0';
+  return bufpos;
+}
+
+size_t hex_decode(char * cbuffer, size_t buflen,
+                  const char * source, size_t srclen) {
+  ASSERT(NULL != cbuffer);  // TODO: estimate output size
+  if (buflen <= 0)
+    return 0;
+
+  unsigned char * bbuffer = reinterpret_cast<unsigned char *>(cbuffer);
+
+  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;
+    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()));
+}
+
+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));
+  size_t len = t(buffer, maxlen, source.data(), source.length());
+  std::string result(buffer, len);
+  return result;
+}
+
+char make_char_safe_for_filename(char c) {
+  if (c < 32)
+    return '_';
+
+  switch (c) {
+    case '<':
+    case '>':
+    case ':':
+    case '"':
+    case '/':
+    case '\\':
+    case '|':
+    case '*':
+    case '?':
+      return '_';
+
+    default:
+      return c;
+  }
+}
+
+/*
+void sprintf(std::string& value, size_t maxlen, const char * format, ...) {
+  char * buffer = static_cast<char *>(alloca(maxlen + 1));
+  va_list args;
+  va_start(args, format);
+  value.assign(buffer, vsprintfn(buffer, maxlen + 1, format, args));
+  va_end(args);
+}
+*/
+
+/////////////////////////////////////////////////////////////////////////////
+// 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
new file mode 100755
index 0000000..08e5e4f
--- /dev/null
+++ b/talk/base/stringencode.h
@@ -0,0 +1,166 @@
+/*
+ * 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_STRINGENCODE_H__
+#define TALK_BASE_STRINGENCODE_H__
+
+#include <string>
+#include <sstream>
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// String Encoding Utilities
+//////////////////////////////////////////////////////////////////////
+
+// 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);
+
+// 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.
+size_t utf8_encode(char* buffer, size_t buflen, unsigned long value);
+// Decode the utf8 encoded value pointed to by source.  Returns the number of
+// bytes used by the encoding, or 0 if the encoding is invalid.
+size_t utf8_decode(const char* source, size_t srclen, unsigned long* value);
+
+// Escaping prefixes illegal characters with the escape character.  Compact, but
+// illegal characters still appear in the string.
+size_t escape(char * buffer, size_t buflen,
+              const char * source, size_t srclen,
+              const char * illegal, char escape);
+// Note: in-place unescaping (buffer == source) is allowed.
+size_t unescape(char * buffer, size_t buflen,
+                const char * source, size_t srclen,
+                char escape); 
+
+// Encoding replaces illegal characters with the escape character and 2 hex
+// chars, so it's a little less compact than escape, but completely removes
+// illegal characters.  note that hex digits should not be used as illegal
+// characters.
+size_t encode(char * buffer, size_t buflen,
+              const char * source, size_t srclen,
+              const char * illegal, char escape);
+// Note: in-place decoding (buffer == source) is allowed.
+size_t decode(char * buffer, size_t buflen,
+              const char * source, size_t srclen,
+              char escape);
+
+// Returns a list of characters that may be unsafe for use in the name of a
+// file, suitable for passing to the 'illegal' member of escape or encode.
+const char* unsafe_filename_characters();
+
+// url_encode is an encode operation with a predefined set of illegal characters
+// and escape character (for use in URLs, obviously).
+size_t url_encode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen);
+// Note: in-place decoding (buffer == source) is allowed.
+size_t url_decode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen);
+
+// html_encode prevents data embedded in html from containing markup.
+size_t html_encode(char * buffer, size_t buflen,
+                   const char * source, size_t srclen);
+// Note: in-place decoding (buffer == source) is allowed.
+size_t html_decode(char * buffer, size_t buflen,
+                   const char * source, size_t srclen);
+
+// xml_encode makes data suitable for inside xml attributes and values.
+size_t xml_encode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen);
+// Note: in-place decoding (buffer == source) is allowed.
+size_t xml_decode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen);
+
+// hex_encode shows the hex representation of binary data in ascii.
+size_t hex_encode(char * buffer, size_t buflen,
+                  const char * source, size_t srclen);
+size_t hex_decode(char * buffer, size_t buflen,
+                  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);
+
+// Return the result of applying transform t to source.
+std::string s_transform(const std::string& source, Transform t);
+
+// Convenience wrappers
+inline std::string s_url_encode(const std::string& source) {
+  return s_transform(source, url_encode);
+}
+inline std::string s_url_decode(const std::string& source) {
+  return s_transform(source, url_decode);
+}
+
+// Safe sprintf to std::string
+//void sprintf(std::string& value, size_t maxlen, const char * format, ...)
+//     PRINTF_FORMAT(3);
+
+// Convert arbitrary values to/from a string.
+
+template <class T>
+static bool ToString(const T &t, std::string* s) {
+  std::ostringstream oss;
+  oss << t;
+  *s = oss.str();
+  return !oss.fail();
+}
+
+template <class T>
+static bool FromString(const std::string& s, T* t) {
+  std::istringstream iss(s);
+  iss >> *t;
+  return !iss.fail();
+}
+
+// Inline versions of the string conversion routines.
+
+template<typename T>
+static inline std::string ToString(T val) {
+  std::string str; ToString(val, &str); return str;
+}
+
+template<typename T>
+static inline T FromString(const std::string& str) {
+  T val; 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);
+
+//////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif  // TALK_BASE_STRINGENCODE_H__
diff --git a/talk/base/stringutils.cc b/talk/base/stringutils.cc
new file mode 100755
index 0000000..1e43637
--- /dev/null
+++ b/talk/base/stringutils.cc
@@ -0,0 +1,84 @@
+/*
+ * 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/stringutils.h"
+#include "talk/base/common.h"
+
+namespace talk_base {
+
+bool memory_check(const void* memory, int c, size_t count) {
+  const char* char_memory = static_cast<const char*>(memory);
+  char char_c = static_cast<char>(c);
+  for (size_t i=0; i<count; ++i) {
+    if (char_memory[i] != char_c) {
+      return false;
+    }
+  }
+  return true;
+}
+
+#ifdef WIN32
+int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
+                         CharacterTransformation transformation) {
+  wchar_t c1, c2;
+  while (true) {
+    if (n-- == 0) return 0;
+    c1 = transformation(*s1);
+    // Double check that characters are not UTF-8
+    ASSERT(static_cast<unsigned char>(*s2) < 128);
+    // Note: *s2 gets implicitly promoted to wchar_t
+    c2 = transformation(*s2);
+    if (c1 != c2) return (c1 < c2) ? -1 : 1;
+    if (!c1) return 0;
+    ++s1;
+    ++s2;
+  }
+}
+
+size_t asccpyn(wchar_t* buffer, size_t buflen,
+               const char* source, size_t srclen) {
+  if (buflen <= 0)
+    return 0;
+  
+  if (srclen == SIZE_UNKNOWN) {
+    srclen = strlenn(source, buflen - 1);
+  } else if (srclen >= buflen) {
+    srclen = buflen - 1;
+  }
+#if _DEBUG
+  // Double check that characters are not UTF-8
+  for (size_t pos = 0; pos < srclen; ++pos)
+    ASSERT(static_cast<unsigned char>(source[pos]) < 128);
+#endif  // _DEBUG
+  std::copy(source, source + srclen, buffer);
+  buffer[srclen] = 0;
+  return srclen;
+}
+
+#endif  // WIN32
+
+}  // namespace talk_base
diff --git a/talk/base/stringutils.h b/talk/base/stringutils.h
new file mode 100755
index 0000000..c3051fd
--- /dev/null
+++ b/talk/base/stringutils.h
@@ -0,0 +1,291 @@
+/*
+ * 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_STRINGUTILS_H__
+#define TALK_BASE_STRINGUTILS_H__
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#ifdef WIN32
+#include <wchar.h>
+#endif  // WIN32
+
+#include <string>
+
+///////////////////////////////////////////////////////////////////////////////
+// Generic string/memory utilities
+///////////////////////////////////////////////////////////////////////////////
+
+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);
+
+}  // namespace talk_base
+
+///////////////////////////////////////////////////////////////////////////////
+// Rename a bunch of common string functions so they are consistent across
+// platforms and between char and wchar_t variants.
+// Here is the full list of functions that are unified:
+//  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
+///////////////////////////////////////////////////////////////////////////////
+
+inline char tolowercase(char c) {
+  return static_cast<char>(tolower(c));
+}
+
+#ifdef WIN32
+
+inline size_t strlen(const wchar_t* s) {
+  return wcslen(s);
+}
+inline int strcmp(const wchar_t* s1, const wchar_t* s2) {
+  return wcscmp(s1, s2);
+}
+inline int stricmp(const wchar_t* s1, const wchar_t* s2) {
+  return _wcsicmp(s1, s2);
+}
+inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
+  return wcsncmp(s1, s2, n);
+}
+inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
+  return _wcsnicmp(s1, s2, n);
+}
+inline const wchar_t* strchr(const wchar_t* s, wchar_t c) {
+  return wcschr(s, c);
+}
+inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) {
+  return wcsstr(haystack, needle);
+}
+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);
+}
+inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) {
+  return wcstoul(snum, end, base);
+}
+inline wchar_t tolowercase(wchar_t c) {
+  return static_cast<wchar_t>(towlower(c));
+}
+
+#endif  // WIN32
+
+#ifdef POSIX
+
+inline int _stricmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline int _strnicmp(const char* s1, const char* s2, size_t n) {
+  return strncasecmp(s1, s2, n);
+}
+
+#endif // POSIX
+
+///////////////////////////////////////////////////////////////////////////////
+// Traits simplifies porting string functions to be CTYPE-agnostic
+///////////////////////////////////////////////////////////////////////////////
+
+namespace talk_base {
+
+const size_t SIZE_UNKNOWN = static_cast<size_t>(-1);
+
+template<class CTYPE>
+struct Traits {
+  // STL string type
+  //typedef XXX string;
+  // Null-terminated string
+  //inline static const CTYPE* empty_str();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// String utilities which work with char or wchar_t
+///////////////////////////////////////////////////////////////////////////////
+
+template<class CTYPE>
+inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = NULL) {
+  return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str());
+}
+
+template<class CTYPE>
+const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) {
+  for (size_t i=0; str[i]; ++i) {
+    for (size_t j=0; chs[j]; ++j) {
+      if (str[i] == chs[j]) {
+        return str + i;
+      }
+    }
+  }
+  return 0;
+}
+
+template<class CTYPE>
+const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) {
+  for (size_t i=0; i<slen && str[i]; ++i) {
+    if (str[i] == ch) {
+      return str + i;
+    }
+  }
+  return 0;
+}
+
+template<class CTYPE>
+size_t strlenn(const CTYPE* buffer, size_t buflen) {
+  size_t bufpos = 0;
+  while (buffer[bufpos] && (bufpos < buflen)) {
+    ++bufpos;
+  }
+  return bufpos;
+}
+
+// Safe versions of strncpy, strncat, snprintf and vsnprintf that always
+// null-terminate.
+
+template<class CTYPE>
+size_t strcpyn(CTYPE* buffer, size_t buflen,
+               const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
+  if (buflen <= 0)
+    return 0;
+
+  if (srclen == SIZE_UNKNOWN) {
+    srclen = strlenn(source, buflen - 1);
+  } else if (srclen >= buflen) {
+    srclen = buflen - 1;
+  }
+  memcpy(buffer, source, srclen * sizeof(CTYPE));
+  buffer[srclen] = 0;
+  return srclen;
+}
+
+template<class CTYPE>
+size_t strcatn(CTYPE* buffer, size_t buflen,
+               const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
+  if (buflen <= 0)
+    return 0;
+  
+  size_t bufpos = strlenn(buffer, buflen - 1);
+  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;
+}
+
+template<class CTYPE>
+size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format,
+                 va_list args) {
+  int len = vsnprintf(buffer, buflen, format, args);
+  if ((len < 0) || (static_cast<size_t>(len) >= buflen)) {
+    len = static_cast<int>(buflen - 1);
+    buffer[len] = 0;
+  }
+  return len;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Allow safe comparing and copying ascii (not UTF-8) with both wide and
+// non-wide character strings.
+///////////////////////////////////////////////////////////////////////////////
+
+inline int asccmp(const char* s1, const char* s2) {
+  return strcmp(s1, s2);
+}
+inline int ascicmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline int ascncmp(const char* s1, const char* s2, size_t n) {
+  return strncmp(s1, s2, n);
+}
+inline int ascnicmp(const char* s1, const char* s2, size_t n) {
+  return _strnicmp(s1, s2, n);
+}
+inline size_t asccpyn(char* buffer, size_t buflen,
+                      const char* source, size_t srclen = SIZE_UNKNOWN) {
+  return strcpyn(buffer, buflen, source, srclen);
+}
+
+#ifdef WIN32
+
+typedef wchar_t(*CharacterTransformation)(wchar_t);
+inline wchar_t identity(wchar_t c) { return c; }
+int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
+                         CharacterTransformation transformation);
+
+inline int asccmp(const wchar_t* s1, const char* s2) {
+  return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity);
+}
+inline int ascicmp(const wchar_t* s1, const char* s2) {
+  return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase);
+}
+inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) {
+  return ascii_string_compare(s1, s2, n, identity);
+}
+inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) {
+  return ascii_string_compare(s1, s2, n, tolowercase);
+}
+size_t asccpyn(wchar_t* buffer, size_t buflen,
+               const char* source, size_t srclen = SIZE_UNKNOWN);
+
+#endif  // WIN32
+
+///////////////////////////////////////////////////////////////////////////////
+// Traits<char> specializations
+///////////////////////////////////////////////////////////////////////////////
+
+template<>
+struct Traits<char> {
+  typedef std::string string;
+  inline static const char* Traits<char>::empty_str() { return ""; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Traits<wchar_t> specializations (Windows only, currently)
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef WIN32
+
+template<>
+struct Traits<wchar_t> {
+  typedef std::wstring string;
+  inline static const wchar_t* Traits<wchar_t>::empty_str() { return L""; }
+};
+
+#endif  // WIN32
+
+}  // namespace talk_base
+
+#endif // TALK_BASE_STRINGUTILS_H__
diff --git a/talk/base/tarstream.cc b/talk/base/tarstream.cc
new file mode 100755
index 0000000..e1f17b1
--- /dev/null
+++ b/talk/base/tarstream.cc
@@ -0,0 +1,601 @@
+#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
new file mode 100755
index 0000000..772fb14
--- /dev/null
+++ b/talk/base/tarstream.h
@@ -0,0 +1,104 @@
+#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
new file mode 100755
index 0000000..d7e0e82
--- /dev/null
+++ b/talk/base/task.cc
@@ -0,0 +1,299 @@
+/*
+ * 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/task.h"
+#include "talk/base/common.h"
+#include "talk/base/taskrunner.h"
+
+namespace talk_base {
+
+int32 Task::unique_id_seed_ = 0;
+
+Task::Task(Task *parent)
+    : state_(STATE_INIT),
+      parent_(parent),
+      blocked_(false),
+      done_(false),
+      aborted_(false),
+      busy_(false),
+      error_(false),
+      child_error_(false),
+      start_time_(0),
+      timeout_seconds_(0),
+      timeout_time_(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_);
+}
+
+int64 Task::CurrentTime() {
+  return runner_->CurrentTime();
+}
+
+int64 Task::ElapsedTime() {
+  return CurrentTime() - start_time_;
+}
+
+void Task::Start() {
+  if (state_ != STATE_INIT)
+    return;
+  // Set the start time before starting the task.  Otherwise if the task
+  // finishes quickly and deletes the Task object, setting start_time_
+  // will crash.
+  start_time_ = CurrentTime();
+  GetRunner()->StartTask(this);
+}
+
+void Task::Step() {
+  if (done_) {
+#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_);
+#else
+    blocked_ = true;
+#endif
+    return;
+  }
+
+  // Async Error() was called
+  if (error_) {
+    done_ = true;
+    state_ = STATE_ERROR;
+    blocked_ = true;
+//   obsolete - an errored task is not considered done now
+//   SignalDone();
+    Stop();
+    return;
+  }
+
+  busy_ = true;
+  int new_state = Process(state_);
+  busy_ = false;
+
+  if (aborted_) {
+    Abort(true);  // no need to wake because we're awake
+    return;
+  }
+
+  if (new_state == STATE_BLOCKED) {
+    blocked_ = true;
+    // Let the timeout continue
+  } else {
+    state_ = new_state;
+    blocked_ = false;
+    ResetTimeout();
+  }
+
+  if (new_state == STATE_DONE) {
+    done_ = true;
+  } else if (new_state == STATE_ERROR) {
+    done_ = true;
+    error_ = true;
+  }
+
+  if (done_) {
+//  obsolete - call this yourself
+//    SignalDone();
+    Stop();
+    blocked_ = true;
+  }
+}
+
+void Task::Abort(bool nowake) {
+  if (aborted_ || done_)
+    return;
+  aborted_ = true;
+  if (!busy_) {
+    done_ = true;
+    blocked_ = true;
+    error_ = true;
+    Stop();
+    if (!nowake)
+      Wake();  // to self-delete
+  }
+}
+
+void Task::Wake() {
+  if (done_)
+    return;
+  if (blocked_) {
+    blocked_ = false;
+    GetRunner()->WakeTasks();
+  }
+}
+
+void Task::Error() {
+  if (error_ || done_)
+    return;
+  error_ = true;
+  Wake();
+}
+
+std::string Task::GetStateName(int state) const {
+  static const std::string STR_BLOCKED("BLOCKED");
+  static const std::string STR_INIT("INIT");
+  static const std::string STR_START("START");
+  static const std::string STR_DONE("DONE");
+  static const std::string STR_ERROR("ERROR");
+  static const std::string STR_RESPONSE("RESPONSE");
+  static const std::string STR_HUH("??");
+  switch (state) {
+    case STATE_BLOCKED: return STR_BLOCKED;
+    case STATE_INIT: return STR_INIT;
+    case STATE_START: return STR_START;
+    case STATE_DONE: return STR_DONE;
+    case STATE_ERROR: return STR_ERROR;
+    case STATE_RESPONSE: return STR_RESPONSE;
+  }
+  return STR_HUH;
+}
+
+int Task::Process(int state) {
+  int newstate = STATE_ERROR;
+
+  if (TimedOut()) {
+    ClearTimeout();
+    newstate = OnTimeout();
+    SignalTimeout();
+  } else {
+    switch (state) {
+      case STATE_INIT:
+        newstate = STATE_START;
+        break;
+      case STATE_START:
+        newstate = ProcessStart();
+        break;
+      case STATE_RESPONSE:
+        newstate = ProcessResponse();
+        break;
+      case STATE_DONE:
+      case STATE_ERROR:
+        newstate = STATE_BLOCKED;
+        break;
+    }
+  }
+
+  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);
+}
+
+void Task::set_timeout_seconds(const int timeout_seconds) {
+  timeout_seconds_ = timeout_seconds;
+  ResetTimeout();
+}
+
+bool Task::TimedOut() {
+  return timeout_seconds_ &&
+    timeout_time_ &&
+    CurrentTime() > timeout_time_;
+}
+
+void Task::ResetTimeout() {
+  bool timeout_allowed = (state_ != STATE_INIT)
+                      && (state_ != STATE_DONE)
+                      && (state_ != STATE_ERROR);
+  if (timeout_seconds_ && timeout_allowed && !timeout_suspended_)
+    timeout_time_ = CurrentTime() +
+                    (timeout_seconds_ * kSecToMsec * kMsecTo100ns);
+  else
+    timeout_time_ = 0;
+
+  GetRunner()->UpdateTaskTimeout(this);
+}
+
+void Task::ClearTimeout() {
+  timeout_time_ = 0;
+  GetRunner()->UpdateTaskTimeout(this);
+}
+
+void Task::SuspendTimeout() {
+  if (!timeout_suspended_) {
+    timeout_suspended_ = true;
+    ResetTimeout();
+  }
+}
+
+void Task::ResumeTimeout() {
+  if (timeout_suspended_) {
+    timeout_suspended_ = false;
+    ResetTimeout();
+  }
+}
+
+} // namespace talk_base
diff --git a/talk/base/task.h b/talk/base/task.h
new file mode 100755
index 0000000..b524ab7
--- /dev/null
+++ b/talk/base/task.h
@@ -0,0 +1,218 @@
+/*
+ * 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_TASK_H__
+#define TALK_BASE_TASK_H__
+
+#include <string>
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/basictypes.h"
+#include "talk/base/sigslot.h"
+
+/////////////////////////////////////////////////////////////////////
+//
+// TASK
+//
+/////////////////////////////////////////////////////////////////////
+//
+// Task is a state machine infrastructure.  States are pushed forward by
+// pushing forwards a TaskRunner that holds on to all Tasks.  The purpose
+// of Task is threefold:
+//
+// (1) It manages ongoing work on the UI thread.  Multitasking without
+// threads, keeping it easy, keeping it real. :-)  It does this by
+// organizing a set of states for each task.  When you return from your
+// Process*() function, you return an integer for the next state.  You do
+// not go onto the next state yourself.  Every time you enter a state,
+// you check to see if you can do anything yet.  If not, you return
+// 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.
+//
+// (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
+// to have a queue in the task.
+//
+// (3) Finally it helps manage parent tasks and children.  If a parent
+// task gets aborted, all the children tasks are too.  The nice thing
+// about this, for example, is if you have one parent task that
+// represents, say, and Xmpp connection, then you can spawn a whole bunch
+// of infinite lifetime child tasks and now worry about cleaning them up.
+//  When the parent task goes to STATE_DONE, the task engine will make
+// sure all those children are aborted and get deleted.
+//
+// Notice that Task has a few built-in states, e.g.,
+//
+// STATE_INIT - the task isn't running yet
+// STATE_START - the task is in its first state
+// STATE_RESPONSE - the task is in its second state
+// STATE_DONE - the task is done
+//
+// STATE_ERROR - indicates an error - we should audit the error code in
+// light of any usage of it to see if it should be improved.  When I
+// first put down the task stuff I didn't have a good sense of what was
+// needed for Abort and Error, and now the subclasses of Task will ground
+// the design in a stronger way.
+//
+// STATE_NEXT - the first undefined state number.  (like WM_USER) - you
+// can start defining more task states there.
+//
+// When you define more task states, just override Process(int state) and
+// add your own switch statement.  If you want to delegate to
+// Task::Process, you can effectively delegate to its switch statement.
+// No fancy method pointers or such - this is all just pretty low tech,
+// easy to debug, and fast.
+//
+// Also notice that Task has some primitive built-in timeout functionality.
+//
+// A timeout is defined as "the task stays in STATE_BLOCKED longer than
+// timeout_seconds_."
+//
+// Descendant classes can override this behavior by calling the
+// various protected methods to change the timeout behavior.  For
+// instance, a descendand might call SuspendTimeout() when it knows
+// that it isn't waiting for anything that might timeout, but isn't
+// yet in the STATE_DONE state.
+//
+
+namespace talk_base {
+
+class TaskRunner;
+
+// A task executes a sequence of steps
+
+class Task;
+class RootTask;
+
+class Task {
+ public:
+  Task(Task *parent);
+  virtual ~Task() {}
+
+  int32 get_unique_id() { return unique_id_; }
+
+  void Start();
+  void Step();
+  int GetState() const { return state_; }
+  bool HasError() const { return (GetState() == STATE_ERROR); }
+  bool Blocked() const { return blocked_; }
+  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_; }
+  void set_timeout_seconds(int timeout_seconds);
+
+  sigslot::signal0<> SignalTimeout;
+
+  // Called inside the task to signal that the task may be unblocked
+  void Wake();
+
+ protected:
+
+  enum {
+    STATE_BLOCKED = -1,
+    STATE_INIT = 0,
+    STATE_START = 1,
+    STATE_DONE = 2,
+    STATE_ERROR = 3,
+    STATE_RESPONSE = 4,
+    STATE_NEXT = 5,  // Subclasses which need more states start here and higher
+  };
+
+  // Called inside to advise that the task should wake and signal an error
+  void Error();
+
+  int64 CurrentTime();
+
+  virtual std::string GetStateName(int state) const;
+  virtual int Process(int state);
+  virtual void Stop();
+  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();
+
+  void SuspendTimeout();
+  void ResumeTimeout();
+
+ protected:
+  virtual int OnTimeout() {
+    // by default, we are finished after timing out
+    return STATE_DONE;
+  }
+
+ 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
+
+#endif  // TALK_BASE_TASK_H__
diff --git a/talk/base/taskrunner.cc b/talk/base/taskrunner.cc
new file mode 100755
index 0000000..050171f
--- /dev/null
+++ b/talk/base/taskrunner.cc
@@ -0,0 +1,176 @@
+/*
+ * 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/taskrunner.h"
+
+#include "talk/base/common.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/task.h"
+#include "talk/base/logging.h"
+
+namespace talk_base {
+
+TaskRunner::TaskRunner()
+    : Task(NULL),
+      tasks_running_(false),
+      next_timeout_task_(NULL) {
+}
+
+TaskRunner::~TaskRunner() {
+  // this kills and deletes children silently!
+  AbortAllChildren();
+  RunTasks();
+}
+
+void TaskRunner::StartTask(Task * task) {
+  tasks_.push_back(task);
+
+  // the task we just started could be about to timeout --
+  // make sure our "next timeout task" is correct
+  UpdateTaskTimeout(task);
+
+  WakeTasks();
+}
+
+void TaskRunner::RunTasks() {
+  // Running continues until all tasks are Blocked (ok for a small # of tasks)
+  if (tasks_running_) {
+    return;  // don't reenter
+  }
+
+  tasks_running_ = true;
+
+  int did_run = true;
+  while (did_run) {
+    did_run = false;
+    // use indexing instead of iterators because tasks_ may grow
+    for (size_t i = 0; i < tasks_.size(); ++i) {
+      while (!tasks_[i]->Blocked()) {
+        tasks_[i]->Step();
+        did_run = true;
+      }
+    }
+  }
+  // Tasks are deleted when running has paused
+  bool need_timeout_recalc = false;
+  for (size_t i = 0; i < tasks_.size(); ++i) {
+    if (tasks_[i]->IsDone()) {
+      Task* task = tasks_[i];
+      if (next_timeout_task_ &&
+          task->get_unique_id() == next_timeout_task_->get_unique_id()) {
+        next_timeout_task_ = NULL;
+        need_timeout_recalc = true;
+      }
+
+      delete task;
+      tasks_[i] = NULL;
+    }
+  }
+  // Finally, remove nulls
+  std::vector<Task *>::iterator it;
+  it = std::remove(tasks_.begin(),
+                   tasks_.end(),
+                   reinterpret_cast<Task *>(NULL));
+
+  tasks_.erase(it, tasks_.end());
+
+  if (need_timeout_recalc)
+    RecalcNextTimeout(NULL);
+
+  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_ &&
+      next_timeout_task_->TimedOut()) {
+    next_timeout_task_->Wake();
+    WakeTasks();
+  }
+}
+
+// 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
+// the next timeout-able task hasn't changed.  The logic in this function
+// prevents RecalcNextTimeout() from getting called in most cases,
+// effectively making the task scheduler O-1 instead of O-N
+
+void TaskRunner::UpdateTaskTimeout(Task *task) {
+  ASSERT(task != NULL);
+
+  // 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 (next_timeout_task_ == NULL ||
+        (task->get_timeout_time() <=
+         next_timeout_task_->get_timeout_time())) {
+      next_timeout_task_ = task;
+    }
+  } else if (next_timeout_task_ != NULL &&
+             task->get_unique_id() == next_timeout_task_->get_unique_id()) {
+    // 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);
+  }
+}
+
+void TaskRunner::RecalcNextTimeout(Task *exclude_task) {
+  // walk through all the tasks looking for the one
+  // which satisfies the following:
+  //   it's not finished already
+  //   we're not excluding it
+  //   it has the closest timeout time
+
+  int64 next_timeout_time = 0;
+  next_timeout_task_ = NULL;
+
+  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 it doesn't match our "exclude" task
+      if (exclude_task == NULL ||
+          exclude_task->get_unique_id() != task->get_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) {
+          // set this task as our next-to-timeout
+          next_timeout_time = task->get_timeout_time();
+          next_timeout_task_ = task;
+        }
+  }
+}
+
+} // namespace talk_base
diff --git a/talk/base/taskrunner.h b/talk/base/taskrunner.h
new file mode 100755
index 0000000..e1c5ed6
--- /dev/null
+++ b/talk/base/taskrunner.h
@@ -0,0 +1,74 @@
+/*
+ * 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_TASKRUNNER_H__
+#define TALK_BASE_TASKRUNNER_H__
+
+#include <vector>
+
+#include "talk/base/sigslot.h"
+#include "talk/base/task.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<> {
+ 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.
+  virtual int64 CurrentTime() = 0 ;
+
+  void StartTask(Task *task);
+  void RunTasks();
+  void PollTasks();
+
+  void UpdateTaskTimeout(Task *task);
+
+  // dummy state machine - never run.
+  virtual int ProcessStart() { return STATE_DONE; }
+
+ private:
+  std::vector<Task *> tasks_;
+  Task *next_timeout_task_;
+  bool tasks_running_;
+
+  void RecalcNextTimeout(Task *exclude_task);
+};
+
+} // namespace talk_base
+
+#endif  // TASK_BASE_TASKRUNNER_H__
diff --git a/talk/base/testclient.cc b/talk/base/testclient.cc
new file mode 100755
index 0000000..ecb45fc
--- /dev/null
+++ b/talk/base/testclient.cc
@@ -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.
+ */
+
+#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
new file mode 100755
index 0000000..012e858
--- /dev/null
+++ b/talk/base/testclient.h
@@ -0,0 +1,89 @@
+/*
+ * 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
new file mode 100755
index 0000000..8fc45e1
--- /dev/null
+++ b/talk/base/thread.cc
@@ -0,0 +1,353 @@
+/*
+ * 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 POSIX
+extern "C" {
+#include <sys/time.h>
+}
+#endif
+
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/thread.h"
+#include "talk/base/time.h"
+
+#define MSDEV_SET_THREAD_NAME  0x406D1388
+
+namespace talk_base {
+
+ThreadManager g_thmgr;
+
+#ifdef POSIX
+pthread_key_t ThreadManager::key_;
+
+ThreadManager::ThreadManager() {
+  pthread_key_create(&key_, NULL);
+  main_thread_ = new Thread();
+  SetCurrent(main_thread_);
+}
+
+ThreadManager::~ThreadManager() {
+  pthread_key_delete(key_);
+  delete main_thread_;
+}
+
+Thread *ThreadManager::CurrentThread() {
+  return (Thread *)pthread_getspecific(key_);
+}
+
+void ThreadManager::SetCurrent(Thread *thread) {
+  pthread_setspecific(key_, thread);
+}
+#endif
+
+#ifdef WIN32
+DWORD ThreadManager::key_;
+
+ThreadManager::ThreadManager() {
+  key_ = TlsAlloc();
+  main_thread_ = new Thread();
+  SetCurrent(main_thread_);
+}
+
+ThreadManager::~ThreadManager() {
+  TlsFree(key_);
+  delete main_thread_;
+}
+
+Thread *ThreadManager::CurrentThread() {
+  return (Thread *)TlsGetValue(key_);
+}
+
+void ThreadManager::SetCurrent(Thread *thread) {
+  TlsSetValue(key_, thread);
+}
+#endif
+
+void ThreadManager::Add(Thread *thread) {
+  CritScope cs(&crit_);
+  threads_.push_back(thread);
+}
+
+void ThreadManager::Remove(Thread *thread) {
+  CritScope cs(&crit_);
+  threads_.erase(std::remove(threads_.begin(), threads_.end(), thread), threads_.end());
+}
+
+Thread::Thread(SocketServer* ss) : MessageQueue(ss), priority_(PRIORITY_NORMAL) {
+  g_thmgr.Add(this);
+  started_ = false;
+  has_sends_ = false;
+}
+
+Thread::~Thread() {
+  Stop();
+  if (active_)
+    Clear(NULL);
+  g_thmgr.Remove(this);
+}
+
+#ifdef POSIX
+void Thread::Start() {
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  if (priority_ == PRIORITY_IDLE) {
+    struct sched_param param;
+    pthread_attr_getschedparam(&attr, &param);
+    param.sched_priority = 15;           // +15 = 
+    pthread_attr_setschedparam(&attr, &param);
+  }
+  pthread_create(&thread_, &attr, PreRun, this);
+  started_ = true;
+}
+
+void Thread::Join() {
+  if (started_) {
+    void *pv;
+    pthread_join(thread_, &pv);
+  }
+}
+#endif
+
+#ifdef WIN32
+
+typedef struct tagTHREADNAME_INFO
+{
+  DWORD dwType;
+  LPCSTR szName;
+  DWORD dwThreadID;
+  DWORD dwFlags;
+} THREADNAME_INFO;
+
+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)
+  {
+  }
+}
+
+void Thread::Start() {
+  DWORD flags = 0;
+  if (priority_ != PRIORITY_NORMAL) {
+    flags = CREATE_SUSPENDED;
+  }
+  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_);
+    }
+  }
+  started_ = true;
+}
+
+void Thread::Join() {
+  if (started_) {
+    WaitForSingleObject(thread_, INFINITE);
+    CloseHandle(thread_);
+    started_ = false;
+  }
+}
+#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);
+#endif
+  thread->Run();
+  return NULL;
+}
+
+void Thread::Run() {
+  ProcessMessages(kForever);
+}
+
+void Thread::Stop() {
+  MessageQueue::Stop();
+  Join();
+}
+
+void Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) {
+  if (fStop_)
+    return;
+
+  // Sent messages are sent to the MessageHandler directly, in the context
+  // of "thread", like Win32 SendMessage. If in the right context,
+  // call the handler directly.
+
+  Message msg;
+  msg.phandler = phandler;
+  msg.message_id = id;
+  msg.pdata = pdata;
+  if (IsCurrent()) {
+    phandler->OnMessage(&msg);
+    return;
+  }
+
+  AutoThread thread; 
+  Thread *current_thread = Thread::Current();
+  ASSERT(current_thread != NULL);  // AutoThread ensures this
+
+  bool ready = false;
+  {
+    CritScope cs(&crit_);
+    EnsureActive();
+    _SendMessage smsg;
+    smsg.thread = current_thread;
+    smsg.msg = msg;
+    smsg.ready = &ready;
+    sendlist_.push_back(smsg);
+    has_sends_ = true;
+  }
+
+  // Wait for a reply
+
+  ss_->WakeUp();
+
+  bool waited = false;
+  while (!ready) {
+    current_thread->ReceiveSends();
+    current_thread->socketserver()->Wait(kForever, false);
+    waited = true;
+  }
+
+  // Our Wait loop above may have consumed some WakeUp events for this
+  // MessageQueue, that weren't relevant to this Send.  Losing these WakeUps can
+  // cause problems for some SocketServers.
+  //
+  // Concrete example:
+  // Win32SocketServer on thread A calls Send on thread B.  While processing the
+  // message, thread B Posts a message to A.  We consume the wakeup for that
+  // Post while waiting for the Send to complete, which means that when we exit
+  // this loop, we need to issue another WakeUp, or else the Posted message
+  // won't be processed in a timely manner.
+
+  if (waited) {
+    current_thread->socketserver()->WakeUp();
+  }
+}
+
+void Thread::ReceiveSends() {
+  // Before entering critical section, check boolean.
+
+  if (!has_sends_)
+    return;
+
+  // Receive a sent message. Cleanup scenarios:
+  // - thread sending exits: We don't allow this, since thread can exit
+  //   only via Join, so Send must complete.
+  // - thread receiving exits: Wakeup/set ready in Thread::Clear()
+  // - object target cleared: Wakeup/set ready in Thread::Clear()
+  crit_.Enter();
+  while (!sendlist_.empty()) {
+    _SendMessage smsg = sendlist_.front();
+    sendlist_.pop_front();
+    crit_.Leave();
+    smsg.msg.phandler->OnMessage(&smsg.msg);
+    crit_.Enter();
+    *smsg.ready = true;
+    smsg.thread->socketserver()->WakeUp();
+  }
+  has_sends_ = false;
+  crit_.Leave();
+}
+
+void Thread::Clear(MessageHandler *phandler, uint32 id) {
+  CritScope cs(&crit_);
+
+  // Remove messages on sendlist_ with phandler
+  // Object target cleared: remove from send list, wakeup/set ready
+  // if sender not NULL.
+
+  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;
+      }
+    }
+    ++iter;
+  }
+
+  MessageQueue::Clear(phandler, id);
+}
+
+bool Thread::ProcessMessages(int cmsLoop) {
+  uint32 msEnd;
+  if (cmsLoop != kForever)
+    msEnd = GetMillisecondCount() + cmsLoop;
+  int cmsNext = cmsLoop;
+
+  while (true) {
+    Message msg;
+    if (!Get(&msg, cmsNext))
+      return false;
+    Dispatch(&msg);
+    
+    if (cmsLoop != kForever) {
+      uint32 msCur = GetMillisecondCount();
+      if (msCur >= msEnd)
+        return true;
+      cmsNext = msEnd - msCur;
+    }
+  }
+}
+
+AutoThread::AutoThread(SocketServer* ss) : Thread(ss) {
+  if (!ThreadManager::CurrentThread()) {
+    ThreadManager::SetCurrent(this);
+  }
+}
+
+AutoThread::~AutoThread() {
+  if (ThreadManager::CurrentThread() == this) {
+    ThreadManager::SetCurrent(NULL);
+  }
+}
+
+} // namespace talk_base
diff --git a/talk/base/thread.h b/talk/base/thread.h
new file mode 100755
index 0000000..5da0aed
--- /dev/null
+++ b/talk/base/thread.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.
+ */
+
+#ifndef TALK_BASE_THREAD_H__
+#define TALK_BASE_THREAD_H__
+
+#include <algorithm>
+#include <list>
+#include <vector>
+
+#ifdef POSIX
+#include <pthread.h>
+#endif
+
+#include "talk/base/messagequeue.h"
+
+#ifdef WIN32
+#include "talk/base/win32.h"
+#endif
+
+namespace talk_base {
+
+class Thread;
+
+class ThreadManager {
+public:
+  ThreadManager();
+  ~ThreadManager();
+
+  static Thread *CurrentThread();
+  static void SetCurrent(Thread *thread);
+  void Add(Thread *thread);
+  void Remove(Thread *thread);
+
+private:
+  Thread *main_thread_;
+  std::vector<Thread *> threads_;
+  CriticalSection crit_;
+
+#ifdef POSIX
+  static pthread_key_t key_; 
+#endif
+
+#ifdef WIN32
+  static DWORD key_;
+#endif
+};
+
+class Thread;
+
+struct _SendMessage {
+  _SendMessage() {}
+  Thread *thread;
+  Message msg;
+  bool *ready;
+};
+
+enum ThreadPriority {
+  PRIORITY_NORMAL,
+  PRIORITY_IDLE,
+};
+
+class Thread : public MessageQueue {
+public:
+  Thread(SocketServer* ss = 0);
+  virtual ~Thread();
+
+  static inline Thread* Current() {
+    return ThreadManager::CurrentThread();
+  }
+  inline bool IsCurrent() const {
+    return (ThreadManager::CurrentThread() == this);
+  }
+
+  void SetPriority(ThreadPriority priority) {
+    priority_ = priority;
+  }
+    
+  virtual void Start();
+  virtual void Stop();
+
+  // By default, Thread::Run() calls ProcessMessages(kForever).  To do other
+  // work, override Run().  To receive and dispatch messages, call
+  // ProcessMessages occasionally.
+  virtual void Run();
+
+  virtual void Send(MessageHandler *phandler, uint32 id = 0,
+      MessageData *pdata = NULL);
+
+  // From MessageQueue
+  virtual void Clear(MessageHandler *phandler, uint32 id = (uint32)-1);
+  virtual void ReceiveSends();
+
+  // ProcessMessages will process I/O and dispatch messages until:
+  //  1) cms milliseconds have elapsed (returns true)
+  //  2) Stop() is called (returns false)
+  bool ProcessMessages(int cms);
+
+#ifdef WIN32
+  HANDLE GetHandle() {
+    return thread_;
+  }
+#endif
+
+private:
+  static void *PreRun(void *pv);
+  void Join();
+
+  std::list<_SendMessage> sendlist_;
+  ThreadPriority priority_;
+  bool started_;
+  bool has_sends_;
+
+#ifdef POSIX
+  pthread_t thread_;
+#endif
+
+#ifdef WIN32
+  HANDLE thread_;
+#endif
+
+  friend class ThreadManager;
+};
+
+// AutoThread automatically installs itself at construction
+// uninstalls at destruction, if a Thread object is
+// _not already_ associated with the current OS thread.
+
+class AutoThread : public Thread {
+public:
+  AutoThread(SocketServer* ss = 0);
+  virtual ~AutoThread();
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_THREAD_H__
diff --git a/talk/base/time.cc b/talk/base/time.cc
new file mode 100755
index 0000000..d4a61ac
--- /dev/null
+++ b/talk/base/time.cc
@@ -0,0 +1,91 @@
+/*
+ * 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 <cstdlib>
+#include <cstring>
+
+#include "talk/base/time.h"
+
+namespace talk_base {
+
+#ifdef POSIX
+#include <sys/time.h>
+uint32 Time() {
+  struct timeval tv;
+  gettimeofday(&tv, 0);
+  return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+uint32 Time() {
+  return GetTickCount();
+}
+#endif
+
+uint32 StartTime() {
+  // Close to program execution time
+  static const uint32 g_start = Time();
+  return g_start;
+}
+
+// Make sure someone calls it so that it gets initialized
+static uint32 ignore = StartTime();
+
+uint32 ElapsedTime() {
+  return TimeDiff(Time(), StartTime());
+}
+
+bool TimeIsBetween(uint32 later, uint32 middle, uint32 earlier) {
+  if (earlier <= later) {
+    return ((earlier <= middle) && (middle <= later));
+  } else {
+    return !((later < middle) && (middle < earlier));
+  }
+}
+
+int32 TimeDiff(uint32 later, uint32 earlier) {
+  uint32 LAST = 0xFFFFFFFF;
+  uint32 HALF = 0x80000000;
+  if (TimeIsBetween(earlier + HALF, later, earlier)) {
+    if (earlier <= later) {
+      return static_cast<long>(later - earlier);
+    } else {
+      return static_cast<long>(later + (LAST - earlier) + 1);
+    }
+  } else {
+    if (later <= earlier) {
+      return -static_cast<long>(earlier - later);
+    } else {
+      return -static_cast<long>(earlier + (LAST - later) + 1);
+    }
+  }
+}
+
+} // namespace talk_base
diff --git a/talk/base/time.h b/talk/base/time.h
new file mode 100755
index 0000000..9088aae
--- /dev/null
+++ b/talk/base/time.h
@@ -0,0 +1,53 @@
+/*
+ * 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_TIME_H__
+#define TALK_BASE_TIME_H__
+
+#include "talk/base/basictypes.h"
+
+namespace talk_base {
+
+// 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
+
+// Comparisons between time values, which can wrap around.
+bool TimeIsBetween(uint32 later, uint32 middle, uint32 earlier);
+int32 TimeDiff(uint32 later, uint32 earlier);
+
+} // namespace talk_base
+
+#endif // TALK_BASE_TIME_H__
diff --git a/talk/base/unixfilesystem.cc b/talk/base/unixfilesystem.cc
new file mode 100755
index 0000000..2c2732f
--- /dev/null
+++ b/talk/base/unixfilesystem.cc
@@ -0,0 +1,223 @@
+/*
+ * 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 <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"
+
+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] != '/'))
+    return false;
+  struct stat st;
+  int res = ::stat(pathname, &st);
+  if (res == 0) {
+    // Something exists at this location, check if it is a directory
+    return S_ISDIR(st.st_mode) != 0;
+  } else if (errno != ENOENT) {
+    // Unexpected error
+    return false;
+  }
+  // Directory doesn't exist, look up one directory level
+  do {
+    --len;
+  } 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;
+    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());
+  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);
+  }
+}
+
+std::string UnixFilesystem::TempFilenameI(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());
+  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();
+  if (rename(old_path.pathname().c_str(), new_path.pathname().c_str()) != 0) {
+    if (errno != EXDEV)
+      return false;
+    if (!CopyFile(old_path, new_path))
+      return false;
+    if (!DeleteFile(old_path))
+      return false;
+  }
+  return true;
+}
+
+bool UnixFilesystem::IsFolderI(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();
+  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)
+    return false;
+
+  StreamInterface *dest = OpenFile(new_path, "wb");
+  if (!dest) {
+    delete source;
+    return false;
+  }
+    
+  while (source->Read(buf, sizeof(buf), &len, NULL) == talk_base::SR_SUCCESS)
+    dest->Write(buf, len, NULL, NULL);
+
+  delete source;
+  delete dest;
+  return true;
+}
+
+bool UnixFilesystem::IsTemporaryPathI(const Pathname& pathname)
+{
+  return (!strncmp(pathname.pathname().c_str(), "/tmp/", strlen("/tmp/")));
+}
+
+bool UnixFilesystem::FileExistsI(const Pathname& pathname)
+{
+   struct stat st;
+   int res = ::stat(pathname.pathname().c_str(), &st);
+   return res == 0;
+}
+
+bool UnixFilesystem::GetFileSizeI(const Pathname& pathname, size_t *size)
+{
+  struct stat st;
+  if (::stat(pathname.pathname().c_str(), &st) != 0)
+    return false;
+  *size = st.st_size;
+  return true;
+}
+
+}
diff --git a/talk/base/unixfilesystem.h b/talk/base/unixfilesystem.h
new file mode 100755
index 0000000..bd145bb
--- /dev/null
+++ b/talk/base/unixfilesystem.h
@@ -0,0 +1,86 @@
+/*
+ * 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_UNIXFILESYSTEM_H__
+#define _TALK_BASE_UNIXFILESYSTEM_H__
+
+#include "fileutils.h"
+
+namespace talk_base {
+
+class UnixFilesystem : public Filesystem{
+ 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);
+
+  // 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);
+
+  // 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);
+  
+  // 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);
+
+  // Returns true if a pathname is a directory
+  virtual bool IsFolderI(const Pathname& pathname);
+
+  // Returns true if pathname represents a temporary location on the system.
+  virtual bool IsTemporaryPathI(const Pathname& pathname);
+
+  // Returns true of pathname represents an existing file
+  virtual bool FileExistsI(const Pathname& pathname);
+  
+  virtual std::string TempFilenameI(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,
+                                 const std::string *append);
+
+  virtual bool GetFileSizeI(const Pathname &path, size_t *size);
+
+  };
+
+}
+
+#endif  // _UNIXFILESYSTEM_H__
diff --git a/talk/base/urlencode.cc b/talk/base/urlencode.cc
new file mode 100755
index 0000000..b654c35
--- /dev/null
+++ b/talk/base/urlencode.cc
@@ -0,0 +1,120 @@
+#include "talk/base/urlencode.h"
+
+static int HexPairValue(const char * code) {
+  int value = 0;
+  const char * pch = code;
+  for (;;) {
+    int digit = *pch++;
+    if (digit >= '0' && digit <= '9') {
+      value += digit - '0';
+    }
+    else if (digit >= 'A' && digit <= 'F') {
+      value += digit - 'A' + 10;
+    }
+    else if (digit >= 'a' && digit <= 'f') {
+      value += digit - 'a' + 10;
+    }
+    else {
+      return -1;
+    }
+    if (pch == code + 2)
+      return value;
+    value <<= 4;
+  }
+}
+
+int UrlDecode(const char *source, char *dest)
+{
+  char * start = dest;
+
+  while (*source) {
+    switch (*source) {
+    case '+':
+      *(dest++) = ' ';
+      break;
+    case '%':
+      if (source[1] && source[2]) {
+        int value = HexPairValue(source + 1);
+        if (value >= 0) {
+          *(dest++) = value;
+          source += 2;
+        }
+        else {
+          *dest++ = '?';
+        }
+      }
+      else {
+        *dest++ = '?';
+      }
+      break;
+    default:
+      *dest++ = *source;
+    }
+    source++;
+  }
+  
+  *dest = 0;
+  return dest - start;
+}  
+
+int UrlEncode(const char *source, char *dest, unsigned max)  
+{
+  static const char *digits = "0123456789ABCDEF";
+  unsigned char ch;
+  unsigned len = 0;
+  char *start = dest;
+
+  while (len < max - 4 && *source)
+  {
+    ch = (unsigned char)*source;
+    if (*source == ' ') {
+      *dest++ = '+';
+    }
+    else if (isalnum(ch) || strchr("-_.!~*'()", ch)) {
+      *dest++ = *source;
+    }
+    else {
+      *dest++ = '%';
+      *dest++ = digits[(ch >> 4) & 0x0F];
+      *dest++ = digits[       ch & 0x0F];
+    }  
+    source++;
+  }
+  *dest = 0;
+  return start - dest;
+}
+
+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;
+}
+
+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;
+}
diff --git a/talk/base/urlencode.h b/talk/base/urlencode.h
new file mode 100755
index 0000000..9d2b3f6
--- /dev/null
+++ b/talk/base/urlencode.h
@@ -0,0 +1,12 @@
+#ifndef _URLENCODE_H_
+#define _URLENCODE_H_ 
+
+#include <string>
+
+int UrlDecode(const char *source, char *dest);
+int UrlEncode(const char *source, char *dest, unsigned max);
+std::string UrlDecodeString(const std::string & encoded);
+std::string UrlEncodeString(const std::string & decoded);
+
+#endif
+
diff --git a/talk/base/virtualsocket_unittest.cc b/talk/base/virtualsocket_unittest.cc
new file mode 100755
index 0000000..16456a2
--- /dev/null
+++ b/talk/base/virtualsocket_unittest.cc
@@ -0,0 +1,239 @@
+// 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
new file mode 100755
index 0000000..884b324
--- /dev/null
+++ b/talk/base/virtualsocketserver.cc
@@ -0,0 +1,616 @@
+/*
+ * 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
new file mode 100755
index 0000000..d2e894a
--- /dev/null
+++ b/talk/base/virtualsocketserver.h
@@ -0,0 +1,156 @@
+/*
+ * 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.h b/talk/base/win32.h
new file mode 100755
index 0000000..082e84f
--- /dev/null
+++ b/talk/base/win32.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 TALK_BASE_WIN32_H__
+#define TALK_BASE_WIN32_H__
+
+#include <winsock2.h>
+#include <windows.h>
+#include <malloc.h>
+
+#include <string>
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+
+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;
+}
+
+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;
+}
+
+// Convert FILETIME to time_t
+void FileTimeToUnixTime(const FILETIME& ft, time_t* ut);
+
+// Convert time_t to FILETIME
+void UnixTimeToFileTime(const time_t& ut, FILETIME * ft);
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace talk_base
+
+#endif  // TALK_BASE_WIN32_H__
diff --git a/talk/base/win32filesystem.cc b/talk/base/win32filesystem.cc
new file mode 100755
index 0000000..5b8b023
--- /dev/null
+++ b/talk/base/win32filesystem.cc
@@ -0,0 +1,194 @@
+/*
+ * 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 <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"
+
+namespace talk_base {
+
+bool Win32Filesystem::CreateFolderI(const Pathname &pathname) {
+  int len = pathname.pathname().length();
+
+  if ((len <= 0) || (pathname.pathname().c_str()[len-1] != '\\')) {
+    return false;
+  }
+
+  DWORD res = ::GetFileAttributes(Utf16(pathname.pathname()).AsWz());
+  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
+  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);
+  }
+}
+
+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());
+  return fs;
+}
+
+bool Win32Filesystem::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 ::RemoveDirectory(Utf16(no_slash).AsWz()) == 0;
+   } 
+   return ::DeleteFile(Utf16(filename.pathname()).AsWz()) == 0;
+}
+
+bool Win32Filesystem::GetTemporaryFolderI(Pathname &pathname, bool create,
+				    const std::string *append) {
+ ASSERT(!g_application_name_.empty());
+  wchar_t 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] != '\\')) {
+    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"\\");
+  }
+  if (len >= ARRAY_SIZE(buffer) - 1)
+    return false;
+  pathname.clear();
+  pathname.SetFolder(Utf8(buffer).AsSz());
+  if (append != NULL)
+    pathname.AppendFolder(*append);
+  if (create)
+    CreateFolderI(pathname);
+  return true;
+}
+
+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 "";
+}
+
+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);
+      return false;
+    }
+    if (!CopyFile(old_path, new_path))
+      return false;
+    if (!DeleteFile(old_path))
+      return false;
+  }
+  return true;
+}
+
+bool Win32Filesystem::IsFolderI(const Pathname &path)
+{
+  WIN32_FILE_ATTRIBUTE_DATA data = {0};
+  if (0 == ::GetFileAttributesEx(Utf16(path.pathname()).AsWz(), GetFileExInfoStandard, &data))
+    return false;
+  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::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::IsTemporaryPathI(const Pathname& pathname)
+{
+  TCHAR buffer[MAX_PATH + 1];
+  if (!::GetTempPath(ARRAY_SIZE(buffer), buffer))
+    return false;
+  if (!::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
+    return false;
+  return (::strnicmp(Utf16(pathname.pathname()).AsWz(), buffer, strlen(buffer)) == 0);
+}
+
+bool Win32Filesystem::GetFileSizeI(const Pathname &pathname, size_t *size)
+{
+  WIN32_FILE_ATTRIBUTE_DATA data = {0};
+  if (::GetFileAttributesEx(Utf16(pathname.pathname()).AsWz(), GetFileExInfoStandard, &data) == 0)
+	  return false;
+  *size = data.nFileSizeLow;
+  return true;
+}
+
+}
diff --git a/talk/base/win32filesystem.h b/talk/base/win32filesystem.h
new file mode 100755
index 0000000..1c13157
--- /dev/null
+++ b/talk/base/win32filesystem.h
@@ -0,0 +1,91 @@
+/*
+ * 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_WIN32FILESYSTEM_H__
+#define _TALK_BASE_WIN32FILESYSTEM_H__
+
+#include "fileutils.h"
+
+namespace talk_base {
+
+class Win32Filesystem : public Filesystem{
+ 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);
+
+  // 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);
+
+  // 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);
+  
+  // 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);
+
+  // Returns true if a pathname is a directory
+  virtual bool IsFolderI(const Pathname& pathname);
+  
+  // Returns true if a file exists at path
+  virtual bool FileExistsI(const Pathname &path);
+
+  // Returns true if pathname represents a temporary location on the system.
+  virtual bool IsTemporaryPathI(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 bool GetFileSizeI(const Pathname &pathname, size_t *size);
+  
+  // 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);
+  };
+
+}
+
+#endif  // _WIN32FILESYSTEM_H__
diff --git a/talk/base/win32socketserver.cc b/talk/base/win32socketserver.cc
new file mode 100755
index 0000000..49c8fee
--- /dev/null
+++ b/talk/base/win32socketserver.cc
@@ -0,0 +1,767 @@
+/*
+ * 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/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>
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// Win32Socket
+///////////////////////////////////////////////////////////////////////////////
+
+static const int kfRead  = 0x0001;
+static const int kfWrite = 0x0002;
+
+// 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)
+  4352,     // FDDI
+  //2048,   // Wideband Network
+  2002,     // IEEE 802.5 (4Mb recommended)
+  //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
+  508,      // IEEE 802/Source-Rt Bridge, ARCNET
+  296,      // Point-to-Point (low delay)
+  68,       // Official minimum
+  0,        // End of list marker
+};
+
+static const uint32 IP_HEADER_SIZE = 20;
+static const uint32 ICMP_HEADER_SIZE = 8;
+
+#ifdef DEBUG
+LPCSTR WSAErrorToString(int error, LPCSTR *description_result) {
+  LPCSTR string = "Unspecified";
+  LPCSTR description = "Unspecified description";
+  switch (error) {
+    case ERROR_SUCCESS:
+      string = "SUCCESS";
+      description = "Operation succeeded";
+      break;
+    case WSAEWOULDBLOCK:
+      string = "WSAEWOULDBLOCK";
+      description = "Using a non-blocking socket, will notify later";
+      break;
+    case WSAEACCES:
+      string = "WSAEACCES";
+      description = "Access denied, or sharing violation";
+      break;
+    case WSAEADDRNOTAVAIL:
+      string = "WSAEADDRNOTAVAIL";
+      description = "Address is not valid in this context";
+      break;
+    case WSAENETDOWN:
+      string = "WSAENETDOWN";
+      description = "Network is down";
+      break;
+    case WSAENETUNREACH:
+      string = "WSAENETUNREACH";
+      description = "Network is up, but unreachable";
+      break;
+    case WSAENETRESET:
+      string = "WSANETRESET";
+      description = "Connection has been reset due to keep-alive activity";
+      break;
+    case WSAECONNABORTED:
+      string = "WSAECONNABORTED";
+      description = "Aborted by host";
+      break;
+    case WSAECONNRESET:
+      string = "WSAECONNRESET";
+      description = "Connection reset by host";
+      break;
+    case WSAETIMEDOUT:
+      string = "WSAETIMEDOUT";
+      description = "Timed out, host failed to respond";
+      break;
+    case WSAECONNREFUSED:
+      string = "WSAECONNREFUSED";
+      description = "Host actively refused connection";
+      break;
+    case WSAEHOSTDOWN:
+      string = "WSAEHOSTDOWN";
+      description = "Host is down";
+      break;
+    case WSAEHOSTUNREACH:
+      string = "WSAEHOSTUNREACH";
+      description = "Host is unreachable";
+      break;
+    case WSAHOST_NOT_FOUND:
+      string = "WSAHOST_NOT_FOUND";
+      description = "No such host is known";
+      break;
+  }
+  if (description_result) {
+    *description_result = description;
+  }
+  return string;
+}
+
+void ReportWSAError(LPCSTR context, int error, const sockaddr_in& addr) {
+  talk_base::SocketAddress address;
+  address.FromSockAddr(addr);
+  LPCSTR description_string;
+  LPCSTR error_string = WSAErrorToString(error, &description_string);
+  LOG(LS_INFO) << context << " = " << error
+    << " (" << error_string << ":" << description_string << ") ["
+    << address.ToString() << "]";
+}
+#else
+void ReportWSAError(LPCSTR context, int error, const sockaddr_in& addr) { }
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// Win32Socket::EventSink
+/////////////////////////////////////////////////////////////////////////////
+
+#define WM_SOCKETNOTIFY  (WM_USER + 50)
+#define WM_DNSNOTIFY     (WM_USER + 51)
+
+struct Win32Socket::DnsLookup {
+  HANDLE handle;
+  uint16 port;
+  char buffer[MAXGETHOSTSTRUCT];
+};
+
+class Win32Socket::EventSink : public Win32Window {
+public:
+  EventSink(Win32Socket * parent) : parent_(parent) { }
+
+  void Dispose();
+
+  virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
+                         LRESULT& result);
+  virtual void OnFinalMessage(HWND hWnd);
+
+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() {
+  parent_ = NULL;
+  if (::IsWindow(handle())) {
+    ::DestroyWindow(handle());
+  } else {
+    delete this;
+  }
+}
+
+bool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
+                                       LRESULT& result) {
+  switch (uMsg) {
+  case WM_SOCKETNOTIFY:
+  case WM_TIMER:
+    return OnSocketNotify(uMsg, wParam, lParam, result);
+  case WM_DNSNOTIFY:
+    return OnDnsNotify(wParam, lParam, result);
+  }
+  return false;
+}
+
+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_error = WSAGETSELECTERROR(lParam);
+
+  if (uMsg == WM_TIMER) {
+    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);
+  return true;
+}
+
+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);
+  return true;
+}
+
+void
+Win32Socket::EventSink::OnFinalMessage(HWND hWnd) {
+  delete this;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Win32Socket
+/////////////////////////////////////////////////////////////////////////////
+
+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_));
+}
+
+Win32Socket::~Win32Socket() {
+  Close();
+}
+
+int
+Win32Socket::Attach(SOCKET s) {
+  ASSERT(socket_ == INVALID_SOCKET);
+  if (socket_ != INVALID_SOCKET)
+    return SOCKET_ERROR;
+
+  ASSERT(s != INVALID_SOCKET);
+  if (s == INVALID_SOCKET)
+    return SOCKET_ERROR;
+
+  socket_ = s;
+  state_ = CS_CONNECTED;
+
+  if (!Create(FD_READ | FD_WRITE | FD_CLOSE))
+    return SOCKET_ERROR;
+
+  return 0;
+}
+
+void
+Win32Socket::SetTimeout(int ms) {
+  if (sink_) 
+    ::SetTimer(sink_->handle(), 1, ms, 0);
+}
+
+talk_base::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;
+  if (result >= 0) {
+    address.FromSockAddr(addr);
+  } else {
+    ASSERT(result >= 0);
+  }
+  return address;
+}
+
+talk_base::SocketAddress 
+Win32Socket::GetRemoteAddress() const {
+  sockaddr_in addr;
+  socklen_t addrlen = sizeof(addr);
+  int result = ::getpeername(socket_, (sockaddr*)&addr, &addrlen);
+  ASSERT(addrlen == sizeof(addr));
+  talk_base::SocketAddress address;
+  if (result >= 0) {
+    address.FromSockAddr(addr);
+  } else {
+    ASSERT(errno == ENOTCONN);
+  }
+  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))
+    return SOCKET_ERROR;
+
+  sockaddr_in saddr;
+  addr.ToSockAddr(&saddr);
+  int err = ::bind(socket_, (sockaddr*)&saddr, sizeof(saddr));
+  UpdateLastError();
+  return err;
+}
+
+int
+Win32Socket::Connect(const talk_base::SocketAddress& addr) {
+  ASSERT(socket_ == INVALID_SOCKET);
+  if (socket_ != INVALID_SOCKET)
+    return SOCKET_ERROR;
+
+  if (!Create(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE))
+    return SOCKET_ERROR;
+
+  if (!addr.IsUnresolved()) {
+    sockaddr_in saddr;
+    addr.ToSockAddr(&saddr);
+
+    // now connect
+    return DoConnect(saddr);
+  }
+
+  LOG_F(LS_INFO) << "async dns lookup (" << addr.IPAsString() << ")";
+  DnsLookup * dns = new DnsLookup;
+  dns->handle = WSAAsyncGetHostByName(sink_->handle(), WM_DNSNOTIFY,
+        addr.IPAsString().c_str(), dns->buffer, sizeof(dns->buffer));
+
+  if (!dns->handle) {
+    LOG_F(LS_ERROR) << "WSAAsyncGetHostByName error: " << WSAGetLastError();
+    delete dns;
+    UpdateLastError();
+    Close();
+    return SOCKET_ERROR;
+  }
+
+  dns->port = addr.port();
+  dns_ = dns;
+  state_ = CS_CONNECTING;
+  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 code = WSAGetLastError();
+    if (code != WSAEWOULDBLOCK) {
+      ReportWSAError("WSAAsync:connect", code, addr);
+      error_ = code;
+      Close();
+      return SOCKET_ERROR;
+    }
+  }
+  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 {
+  return error_;
+}
+
+void
+Win32Socket::SetError(int error) {
+  error_ = error;
+}
+
+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::Send(const void *pv, size_t cb) {
+  int sent = ::send(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0);
+  UpdateLastError();
+  return sent;
+}
+
+int
+Win32Socket::SendTo(const void *pv, size_t cb, 
+    const talk_base::SocketAddress& addr) {
+  sockaddr_in saddr;
+  addr.ToSockAddr(&saddr);
+  int sent = ::sendto(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0, 
+      (sockaddr*)&saddr, sizeof(saddr));
+  UpdateLastError();
+  return sent;
+}
+
+int 
+Win32Socket::Recv(void *pv, size_t cb) {
+  int received = ::recv(socket_, (char *)pv, (int)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);
+    }
+  }
+  return received;
+}
+
+int
+Win32Socket::RecvFrom(void *pv, size_t cb, talk_base::SocketAddress *paddr) {
+  sockaddr_in saddr;
+  socklen_t cbAddr = sizeof(saddr);
+  int received = ::recvfrom(socket_, (char *)pv, (int)cb, 0, (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);
+    }
+  }
+  return received;
+}
+
+int 
+Win32Socket::Listen(int backlog) {
+  int err = ::listen(socket_, backlog);
+  UpdateLastError();
+  if (err == 0)
+    state_ = CS_CONNECTING;
+  return err;
+}
+
+talk_base::Socket* 
+Win32Socket::Accept(talk_base::SocketAddress *paddr) {
+  sockaddr_in saddr;
+  socklen_t cbAddr = sizeof(saddr);
+  SOCKET s = ::accept(socket_, (sockaddr*)&saddr, &cbAddr);
+  UpdateLastError();
+  if (s == INVALID_SOCKET)
+    return NULL;
+  if (paddr)
+    paddr->FromSockAddr(saddr);
+  Win32Socket* socket = new Win32Socket;
+  if (0 == socket->Attach(s))
+    return socket;
+  delete socket;
+  return NULL;
+}
+
+int 
+Win32Socket::Close() {
+  int err = 0;
+  if (socket_ != INVALID_SOCKET) {
+    err = ::closesocket(socket_);
+    socket_ = INVALID_SOCKET;
+    signal_close_ = false;
+    UpdateLastError();
+  }
+  if (dns_) {
+    WSACancelAsyncRequest(dns_->handle);
+    delete dns_;
+    dns_ = NULL;
+  }
+  if (sink_) {
+    sink_->Dispose();
+    sink_ = NULL;
+  }
+  memset(&addr_, 0, sizeof(addr_));        // no longer connected, zero ip/port
+  state_ = CS_CLOSED;
+  return err;
+}
+
+int 
+Win32Socket::EstimateMTU(uint16* mtu) {
+  talk_base::SocketAddress addr = GetRemoteAddress();
+  if (addr.IsAny()) {
+    error_ = ENOTCONN;
+    return -1;
+  }
+
+  talk_base::WinPing ping;
+  if (!ping.IsValid()) {
+    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
+      return -1;
+    }
+    if (result != talk_base::WinPing::PING_TOO_LARGE) {
+      *mtu = PACKET_MAXIMUMS[level];
+      return 0;
+    }
+  }
+
+  ASSERT(false);
+  return 0;
+}
+
+bool
+Win32Socket::Create(long 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);
+
+  // start the async select
+  if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events)
+      == SOCKET_ERROR) {
+    UpdateLastError();
+    Close();
+    return false;
+  }
+
+  return true;
+}
+
+void
+Win32Socket::UpdateLastError() {
+  error_ = WSAGetLastError();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Win32SocketServer
+///////////////////////////////////////////////////////////////////////////////
+
+static UINT s_wm_wakeup_id;
+
+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) {
+  if (s_wm_wakeup_id == 0)
+    s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP");
+  message_queue_ = message_queue;
+  hwnd_ = NULL;
+  CreateDummyWindow();
+}
+
+Win32SocketServer::~Win32SocketServer() {
+  if (hwnd_ != NULL) {
+    KillTimer(hwnd_, 1);
+    ::DestroyWindow(hwnd_);
+  }
+}
+
+Socket* Win32SocketServer::CreateSocket(int type) {
+  ASSERT(SOCK_STREAM == type);
+  return new Win32Socket;
+}
+
+AsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) {
+  ASSERT(SOCK_STREAM == type);
+  return new Win32Socket;
+}
+
+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) {
+    MSG msg;
+    GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);
+  } else if (cms != 0) {
+    Sleep(cms);
+  }
+  return true;
+}
+
+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);
+}
+
+void Win32SocketServer::Pump() {
+  // Process messages
+  Message msg;
+  while (message_queue_->Get(&msg, 0))
+    message_queue_->Dispatch(&msg);
+
+  // Anything remaining?
+  int delay = message_queue_->GetDelay();
+  if (delay == -1) {
+    KillTimer(hwnd_, 1);
+  } else {
+    SetTimer(hwnd_, 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)
+{
+  if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) {
+    Win32SocketServer *ss = (Win32SocketServer *)(LONG_PTR)GetWindowLong(hwnd, GWL_USERDATA);
+    ss->Pump();
+    return 0;
+  }
+  return ::DefWindowProc(hwnd, wm, wp, lp);
+}
+
+} // namespace talk_base
diff --git a/talk/base/win32socketserver.h b/talk/base/win32socketserver.h
new file mode 100755
index 0000000..770141a
--- /dev/null
+++ b/talk/base/win32socketserver.h
@@ -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.
+ */
+
+#ifndef TALK_BASE_WIN32SOCKETSERVER_H__
+#define TALK_BASE_WIN32SOCKETSERVER_H__
+
+#ifdef WIN32
+
+#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"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// Win32Socket
+///////////////////////////////////////////////////////////////////////////////
+
+class Win32Socket : public talk_base::AsyncSocket {
+public:
+  Win32Socket();
+  virtual ~Win32Socket();
+
+  int Attach(SOCKET s);
+  void SetTimeout(int ms);
+
+  // AsyncSocket Interface
+  virtual SocketAddress GetLocalAddress() const;
+  virtual SocketAddress GetRemoteAddress() const;
+  virtual int Bind(const SocketAddress& addr);
+  virtual int Connect(const SocketAddress& addr);
+  virtual int Send(const void *pv, size_t cb);
+  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 Listen(int backlog);
+  virtual Socket *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 SetOption(Option opt, int value);
+
+private:
+  bool Create(long events);
+  void UpdateLastError();
+  
+  int DoConnect(const sockaddr_in& addr);
+  void OnSocketNotify(int event, int error);
+  void OnDnsNotify(int ip, int error);
+
+  sockaddr_in addr_;         // address that we connected to (see DoConnect)
+  SOCKET socket_;
+  int error_;
+  uint32 connect_time_;
+  ConnState state_;
+  bool signal_close_;
+
+  class EventSink;
+  friend class EventSink;
+  EventSink * sink_;
+
+  struct DnsLookup;
+  DnsLookup * dns_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Win32SocketServer
+///////////////////////////////////////////////////////////////////////////////
+
+class Win32SocketServer : public SocketServer {
+public:
+  Win32SocketServer(MessageQueue *message_queue);
+  virtual ~Win32SocketServer();
+
+  // SocketServer Interface
+  virtual Socket* CreateSocket(int type);
+  virtual AsyncSocket* CreateAsyncSocket(int type);
+  virtual bool Wait(int cms, bool process_io);
+  virtual void WakeUp();
+
+  void Pump();
+
+private:
+  void CreateDummyWindow();
+
+  MessageQueue *message_queue_;
+  HWND hwnd_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif  // WIN32
+
+#endif  // TALK_BASE_WIN32SOCKETSERVER_H__
diff --git a/talk/base/win32window.h b/talk/base/win32window.h
new file mode 100755
index 0000000..a4cdb47
--- /dev/null
+++ b/talk/base/win32window.h
@@ -0,0 +1,72 @@
+/*
+ * 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_WIN32WINDOW_H__
+#define TALK_BASE_WIN32WINDOW_H__
+
+#ifdef WIN32
+
+#include "talk/base/win32.h"
+
+namespace talk_base {
+
+///////////////////////////////////////////////////////////////////////////////
+// Win32Window
+///////////////////////////////////////////////////////////////////////////////
+
+class Win32Window {
+public:
+  Win32Window();
+  virtual ~Win32Window();
+
+  HWND handle() { 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:
+  virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
+                         LRESULT& result);
+
+  virtual bool OnClose() { return true; }
+  virtual void OnDestroyed() { }
+
+private:
+  static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+                                  LPARAM lParam);
+
+  HWND wnd_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif  // WIN32
+
+#endif  // TALK_BASE_WIN32WINDOW_H__
diff --git a/talk/base/winfirewall.cc b/talk/base/winfirewall.cc
new file mode 100755
index 0000000..9323d01
--- /dev/null
+++ b/talk/base/winfirewall.cc
@@ -0,0 +1,141 @@
+/*
+ * 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 <comdef.h>
+#include "netfw.h"
+#include "winfirewall.h"
+
+#define RELEASE(lpUnk) do \
+	{ if ((lpUnk) != NULL) { (lpUnk)->Release(); (lpUnk) = NULL; } } while (0)
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// WinFirewall
+//////////////////////////////////////////////////////////////////////
+
+WinFirewall::WinFirewall() : mgr_(NULL), policy_(NULL), profile_(NULL) {
+}
+
+WinFirewall::~WinFirewall() {
+  Shutdown();
+}
+
+bool
+WinFirewall::Initialize() {
+  if (mgr_)
+    return true;
+
+  HRESULT hr = CoCreateInstance(__uuidof(NetFwMgr),
+                                0, CLSCTX_INPROC_SERVER,
+                                __uuidof(INetFwMgr),
+                                reinterpret_cast<void **>(&mgr_));
+  if (SUCCEEDED(hr) && (mgr_ != NULL))
+    hr = mgr_->get_LocalPolicy(&policy_);
+  if (SUCCEEDED(hr) && (policy_ != NULL))
+    hr = policy_->get_CurrentProfile(&profile_);
+  return SUCCEEDED(hr) && (profile_ != NULL);
+}
+
+void
+WinFirewall::Shutdown() {
+  RELEASE(profile_);
+  RELEASE(policy_);
+  RELEASE(mgr_);
+}
+
+bool
+WinFirewall::Enabled() {
+  if (!profile_)
+    return false;
+
+  VARIANT_BOOL fwEnabled = VARIANT_FALSE;
+  profile_->get_FirewallEnabled(&fwEnabled);
+  return (fwEnabled != VARIANT_FALSE);
+}
+
+bool
+WinFirewall::Authorized(const char * filename, bool * known) {
+  if (known) {
+    *known = false;
+  }
+
+  if (!profile_)
+    return false;
+
+  VARIANT_BOOL fwEnabled = VARIANT_FALSE;
+  _bstr_t bfilename = filename;
+
+  INetFwAuthorizedApplications * apps = NULL;
+  HRESULT hr = profile_->get_AuthorizedApplications(&apps);
+  if (SUCCEEDED(hr) && (apps != NULL)) {
+    INetFwAuthorizedApplication * app = NULL;
+    hr = apps->Item(bfilename, &app);
+    if (SUCCEEDED(hr) && (app != NULL)) {
+      hr = app->get_Enabled(&fwEnabled);
+      app->Release();
+      if (known) {
+        *known = true;
+      }
+    } else if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
+      // Unexpected error
+    }
+    apps->Release();
+  }
+
+  return (fwEnabled != VARIANT_FALSE);
+}
+
+bool
+WinFirewall::AddApplication(const char * filename, const char * friendly_name,
+                            bool authorized) {
+  INetFwAuthorizedApplications * apps = NULL;
+  HRESULT hr = profile_->get_AuthorizedApplications(&apps);
+  if (SUCCEEDED(hr) && (apps != NULL)) {
+    INetFwAuthorizedApplication * app = NULL;
+    hr = CoCreateInstance(__uuidof(NetFwAuthorizedApplication),
+                          0, CLSCTX_INPROC_SERVER,
+                          __uuidof(INetFwAuthorizedApplication),
+                          reinterpret_cast<void **>(&app));
+    if (SUCCEEDED(hr) && (app != NULL)) {
+      _bstr_t bstr = filename;
+      hr = app->put_ProcessImageFileName(bstr);
+      bstr = friendly_name;
+      if (SUCCEEDED(hr))
+        hr = app->put_Name(bstr);
+      if (SUCCEEDED(hr))
+        hr = app->put_Enabled(authorized ? VARIANT_TRUE : VARIANT_FALSE);
+      if (SUCCEEDED(hr))
+        hr = apps->Add(app);
+      app->Release();
+    }
+    apps->Release();
+  }
+  return SUCCEEDED(hr);
+}
+
+} // namespace talk_base
diff --git a/talk/base/winfirewall.h b/talk/base/winfirewall.h
new file mode 100755
index 0000000..09d5a2f
--- /dev/null
+++ b/talk/base/winfirewall.h
@@ -0,0 +1,64 @@
+/*
+ * 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_WINFIREWALL_H__
+#define TALK_BASE_WINFIREWALL_H__
+
+struct INetFwMgr;
+struct INetFwPolicy;
+struct INetFwProfile;
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// WinFirewall
+//////////////////////////////////////////////////////////////////////
+
+class WinFirewall {
+public:
+  WinFirewall();
+  ~WinFirewall();
+
+  bool Initialize();
+  void Shutdown();
+
+  bool Enabled();
+  bool Authorized(const char * filename, bool * known = 0);
+
+  bool AddApplication(const char * filename, const char * friendly_name, bool authorized = true);
+
+private:
+  INetFwMgr * mgr_;
+  INetFwPolicy * policy_;
+  INetFwProfile * profile_;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
+
+#endif // TALK_BASE_WINFIREWALL_H__
diff --git a/talk/base/winping.cc b/talk/base/winping.cc
new file mode 100755
index 0000000..401a1b2
--- /dev/null
+++ b/talk/base/winping.cc
@@ -0,0 +1,317 @@
+/*
+ * 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/byteorder.h"
+#include "talk/base/socketaddress.h"
+#include "talk/base/winping.h"
+#include "talk/base/logging.h"
+#include <cassert>
+
+namespace talk_base {
+
+//////////////////////////////////////////////////////////////////////
+// Found in IPExport.h
+//////////////////////////////////////////////////////////////////////
+
+typedef struct icmp_echo_reply {
+    ULONG   Address;            // Replying address
+    ULONG   Status;             // Reply IP_STATUS
+    ULONG   RoundTripTime;      // RTT in milliseconds
+    USHORT  DataSize;           // Reply data size in bytes
+    USHORT  Reserved;           // Reserved for system use
+    PVOID   Data;               // Pointer to the reply data
+    struct ip_option_information Options; // Reply options
+} ICMP_ECHO_REPLY, * PICMP_ECHO_REPLY;
+
+//
+// IP_STATUS codes returned from IP APIs
+//
+
+#define IP_STATUS_BASE              11000
+
+#define IP_SUCCESS                  0
+#define IP_BUF_TOO_SMALL            (IP_STATUS_BASE + 1)
+#define IP_DEST_NET_UNREACHABLE     (IP_STATUS_BASE + 2)
+#define IP_DEST_HOST_UNREACHABLE    (IP_STATUS_BASE + 3)
+#define IP_DEST_PROT_UNREACHABLE    (IP_STATUS_BASE + 4)
+#define IP_DEST_PORT_UNREACHABLE    (IP_STATUS_BASE + 5)
+#define IP_NO_RESOURCES             (IP_STATUS_BASE + 6)
+#define IP_BAD_OPTION               (IP_STATUS_BASE + 7)
+#define IP_HW_ERROR                 (IP_STATUS_BASE + 8)
+#define IP_PACKET_TOO_BIG           (IP_STATUS_BASE + 9)
+#define IP_REQ_TIMED_OUT            (IP_STATUS_BASE + 10)
+#define IP_BAD_REQ                  (IP_STATUS_BASE + 11)
+#define IP_BAD_ROUTE                (IP_STATUS_BASE + 12)
+#define IP_TTL_EXPIRED_TRANSIT      (IP_STATUS_BASE + 13)
+#define IP_TTL_EXPIRED_REASSEM      (IP_STATUS_BASE + 14)
+#define IP_PARAM_PROBLEM            (IP_STATUS_BASE + 15)
+#define IP_SOURCE_QUENCH            (IP_STATUS_BASE + 16)
+#define IP_OPTION_TOO_BIG           (IP_STATUS_BASE + 17)
+#define IP_BAD_DESTINATION          (IP_STATUS_BASE + 18)
+
+#define IP_ADDR_DELETED             (IP_STATUS_BASE + 19)
+#define IP_SPEC_MTU_CHANGE          (IP_STATUS_BASE + 20)
+#define IP_MTU_CHANGE               (IP_STATUS_BASE + 21)
+#define IP_UNLOAD                   (IP_STATUS_BASE + 22)
+#define IP_ADDR_ADDED               (IP_STATUS_BASE + 23)
+#define IP_MEDIA_CONNECT            (IP_STATUS_BASE + 24)
+#define IP_MEDIA_DISCONNECT         (IP_STATUS_BASE + 25)
+#define IP_BIND_ADAPTER             (IP_STATUS_BASE + 26)
+#define IP_UNBIND_ADAPTER           (IP_STATUS_BASE + 27)
+#define IP_DEVICE_DOES_NOT_EXIST    (IP_STATUS_BASE + 28)
+#define IP_DUPLICATE_ADDRESS        (IP_STATUS_BASE + 29)
+#define IP_INTERFACE_METRIC_CHANGE  (IP_STATUS_BASE + 30)
+#define IP_RECONFIG_SECFLTR         (IP_STATUS_BASE + 31)
+#define IP_NEGOTIATING_IPSEC        (IP_STATUS_BASE + 32)
+#define IP_INTERFACE_WOL_CAPABILITY_CHANGE  (IP_STATUS_BASE + 33)
+#define IP_DUPLICATE_IPADD          (IP_STATUS_BASE + 34)
+
+#define IP_GENERAL_FAILURE          (IP_STATUS_BASE + 50)
+#define MAX_IP_STATUS               IP_GENERAL_FAILURE
+#define IP_PENDING                  (IP_STATUS_BASE + 255)
+
+//
+// Values used in the IP header Flags field.
+//
+#define IP_FLAG_DF      0x2         // Don't fragment this packet.
+
+//
+// Supported IP Option Types.
+//
+// These types define the options which may be used in the OptionsData field
+// of the ip_option_information structure.  See RFC 791 for a complete
+// description of each.
+//
+#define IP_OPT_EOL      0          // End of list option
+#define IP_OPT_NOP      1          // No operation
+#define IP_OPT_SECURITY 0x82       // Security option
+#define IP_OPT_LSRR     0x83       // Loose source route
+#define IP_OPT_SSRR     0x89       // Strict source route
+#define IP_OPT_RR       0x7        // Record route
+#define IP_OPT_TS       0x44       // Timestamp
+#define IP_OPT_SID      0x88       // Stream ID (obsolete)
+#define IP_OPT_ROUTER_ALERT 0x94  // Router Alert Option
+
+#define MAX_OPT_SIZE    40         // Maximum length of IP options in bytes
+
+//////////////////////////////////////////////////////////////////////
+// Global Constants and Types
+//////////////////////////////////////////////////////////////////////
+
+const char * const ICMP_DLL_NAME = "icmp.dll";
+const char * const ICMP_CREATE_FUNC = "IcmpCreateFile";
+const char * const ICMP_CLOSE_FUNC = "IcmpCloseHandle";
+const char * const ICMP_SEND_FUNC = "IcmpSendEcho";
+
+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);
+}
+
+//////////////////////////////////////////////////////////////////////
+// WinPing
+//////////////////////////////////////////////////////////////////////
+
+WinPing::WinPing()
+    : dll_(0), hping_(INVALID_HANDLE_VALUE), create_(0), close_(0), send_(0),
+      data_(0), dlen_(0), reply_(0), rlen_(0), valid_(false) {
+
+  dll_ = LoadLibraryA(ICMP_DLL_NAME);
+  if (!dll_) {
+    LOG(LERROR) << "LoadLibrary: " << GetLastError();
+    return;
+  }
+
+  create_ = (PIcmpCreateFile) GetProcAddress(dll_, ICMP_CREATE_FUNC);
+  close_ = (PIcmpCloseHandle) GetProcAddress(dll_, ICMP_CLOSE_FUNC);
+  send_ = (PIcmpSendEcho) GetProcAddress(dll_, ICMP_SEND_FUNC);
+  if (!create_ || !close_ || !send_) {
+    LOG(LERROR) << "GetProcAddress(ICMP_*): " << GetLastError();
+    return;
+  }
+
+  hping_ = create_();
+  if (hping_ == INVALID_HANDLE_VALUE) {
+    LOG(LERROR) << "IcmpCreateFile: " << GetLastError();
+    return;
+  }
+
+  dlen_ = 0;
+  rlen_ = ReplySize(dlen_);
+  data_ = new char[dlen_];
+  reply_ = new char[rlen_];
+
+  valid_ = true;
+}
+
+WinPing::~WinPing() {
+  if (dll_)
+    FreeLibrary(dll_);
+
+  if ((hping_ != INVALID_HANDLE_VALUE) && close_) {
+    if (!close_(hping_))
+      LOG(WARNING) << "IcmpCloseHandle: " << GetLastError();
+  }
+
+  delete[] data_;
+  delete reply_;
+}
+
+WinPing::PingResult WinPing::Ping(
+    uint32 ip, uint32 data_size, uint32 timeout, uint8 ttl,
+    bool allow_fragments) {
+
+  assert(IsValid());
+
+  IP_OPTION_INFORMATION ipopt;
+  memset(&ipopt, 0, sizeof(ipopt));
+  if (!allow_fragments)
+    ipopt.Flags |= IP_FLAG_DF;
+  ipopt.Ttl = ttl;
+
+  uint32 reply_size = ReplySize(data_size);
+
+  if (data_size > dlen_) {
+    delete [] data_;
+    dlen_ = data_size;
+    data_ = new char[dlen_];
+    memset(data_, 'z', dlen_);
+  }
+
+  if (reply_size > rlen_) {
+    delete [] reply_;
+    rlen_ = reply_size;
+    reply_ = new char[rlen_];
+  }
+
+  DWORD result = send_(hping_, talk_base::HostToNetwork32(ip),
+                       data_, uint16(data_size), &ipopt,
+                       reply_, reply_size, timeout);
+  if (result == 0) {
+    long error = GetLastError();
+    if (error == IP_PACKET_TOO_BIG)
+      return PING_TOO_LARGE;
+    if (error == IP_REQ_TIMED_OUT)
+      return PING_TIMEOUT;
+    LOG(LERROR) << "IcmpSendEcho(" << talk_base::SocketAddress::IPToString(ip)
+                << ", " << data_size << "): " << error;
+    return PING_FAIL;
+  }
+
+  return PING_SUCCESS;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Microsoft Documenation
+//////////////////////////////////////////////////////////////////////
+//
+// Routine Name:
+//
+//     IcmpCreateFile
+//
+// Routine Description:
+//
+//     Opens a handle on which ICMP Echo Requests can be issued.
+//
+// Arguments:
+//
+//     None.
+//
+// Return Value:
+//
+//     An open file handle or INVALID_HANDLE_VALUE. Extended error information
+//     is available by calling GetLastError().
+//
+//////////////////////////////////////////////////////////////////////
+//
+// Routine Name:
+//
+//     IcmpCloseHandle
+//
+// Routine Description:
+//
+//     Closes a handle opened by ICMPOpenFile.
+//
+// Arguments:
+//
+//     IcmpHandle  - The handle to close.
+//
+// Return Value:
+//
+//     TRUE if the handle was closed successfully, otherwise FALSE. Extended
+//     error information is available by calling GetLastError().
+//
+//////////////////////////////////////////////////////////////////////
+//
+// Routine Name:
+//
+//     IcmpSendEcho
+//
+// Routine Description:
+//
+//     Sends an ICMP Echo request and returns any replies. The
+//     call returns when the timeout has expired or the reply buffer
+//     is filled.
+//
+// Arguments:
+//
+//     IcmpHandle           - An open handle returned by ICMPCreateFile.
+//
+//     DestinationAddress   - The destination of the echo request.
+//
+//     RequestData          - A buffer containing the data to send in the
+//                            request.
+//
+//     RequestSize          - The number of bytes in the request data buffer.
+//
+//     RequestOptions       - Pointer to the IP header options for the request.
+//                            May be NULL.
+//
+//     ReplyBuffer          - A buffer to hold any replies to the request.
+//                            On return, the buffer will contain an array of
+//                            ICMP_ECHO_REPLY structures followed by the
+//                            options and data for the replies. The buffer
+//                            should be large enough to hold at least one
+//                            ICMP_ECHO_REPLY structure plus
+//                            MAX(RequestSize, 8) bytes of data since an ICMP
+//                            error message contains 8 bytes of data.
+//
+//     ReplySize            - The size in bytes of the reply buffer.
+//
+//     Timeout              - The time in milliseconds to wait for replies.
+//
+// Return Value:
+//
+//     Returns the number of ICMP_ECHO_REPLY structures stored in ReplyBuffer.
+//     The status of each reply is contained in the structure. If the return
+//     value is zero, extended error information is available via
+//     GetLastError().
+//
+//////////////////////////////////////////////////////////////////////
+
+} // namespace talk_base
\ No newline at end of file
diff --git a/talk/base/winping.h b/talk/base/winping.h
new file mode 100755
index 0000000..0d0b051
--- /dev/null
+++ b/talk/base/winping.h
@@ -0,0 +1,105 @@
+/*
+ * 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_WINPING_H__
+#define TALK_BASE_WINPING_H__
+
+#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/basictypes.h"
+
+namespace talk_base {
+
+// This class wraps a Win32 API for doing ICMP pinging.  This API, unlike the
+// the normal socket APIs (as implemented on Win9x), will return an error if
+// an ICMP packet with the dont-fragment bit set is too large.  This means this
+// class can be used to detect the MTU to a given address.
+
+typedef struct ip_option_information {
+    UCHAR   Ttl;                // Time To Live
+    UCHAR   Tos;                // Type Of Service
+    UCHAR   Flags;              // IP header flags
+    UCHAR   OptionsSize;        // Size in bytes of options data
+    PUCHAR  OptionsData;        // Pointer to options data
+} IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION;
+
+typedef HANDLE (WINAPI *PIcmpCreateFile)();
+
+typedef BOOL (WINAPI *PIcmpCloseHandle)(HANDLE icmp_handle);
+
+typedef DWORD (WINAPI *PIcmpSendEcho)(
+    HANDLE                   IcmpHandle,
+    ULONG                    DestinationAddress,
+    LPVOID                   RequestData,
+    WORD                     RequestSize,
+    PIP_OPTION_INFORMATION   RequestOptions,
+    LPVOID                   ReplyBuffer,
+    DWORD                    ReplySize,
+    DWORD                    Timeout);
+
+class WinPing {
+public:
+    WinPing();
+    ~WinPing();
+
+    // Determines whether the class was initialized correctly.
+    bool IsValid() { return valid_; }
+
+    // Attempts to send a ping with the given parameters.
+    enum PingResult { PING_FAIL, PING_TOO_LARGE, PING_TIMEOUT, PING_SUCCESS };
+    PingResult Ping(
+        uint32 ip, uint32 data_size, uint32 timeout_millis, uint8 ttl,
+        bool allow_fragments);
+
+private:
+    HMODULE dll_;
+    HANDLE hping_;
+    PIcmpCreateFile create_;
+    PIcmpCloseHandle close_;
+    PIcmpSendEcho send_;
+    char* data_;
+    uint32 dlen_;
+    char* reply_;
+    uint32 rlen_;
+    bool valid_;
+};
+
+} // namespace talk_base
+
+#endif // WIN32
+
+#endif // TALK_BASE_WINPING_H__
+
diff --git a/talk/examples/Makefile.am b/talk/examples/Makefile.am
new file mode 100755
index 0000000..fd05e37
--- /dev/null
+++ b/talk/examples/Makefile.am
@@ -0,0 +1,5 @@
+if PHONE
+SUBDIRS=login call pcp
+else
+SUBDIRS=login pcp
+endif
diff --git a/talk/examples/Makefile.in b/talk/examples/Makefile.in
new file mode 100644
index 0000000..e06e7ec
--- /dev/null
+++ b/talk/examples/Makefile.in
@@ -0,0 +1,489 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/examples
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-exec-recursive install-info-recursive \
+	install-recursive installcheck-recursive installdirs-recursive \
+	pdf-recursive ps-recursive uninstall-info-recursive \
+	uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = login pcp call
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+@PHONE_FALSE@SUBDIRS = login pcp
+@PHONE_TRUE@SUBDIRS = login call pcp
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/examples/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/examples/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(mkdir_p) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
+	clean clean-generic clean-libtool clean-recursive ctags \
+	ctags-recursive distclean distclean-generic distclean-libtool \
+	distclean-recursive distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-recursive \
+	mostlyclean mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/examples/call/Makefile.am b/talk/examples/call/Makefile.am
new file mode 100755
index 0000000..30a3dc6
--- /dev/null
+++ b/talk/examples/call/Makefile.am
@@ -0,0 +1,15 @@
+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/Makefile.in b/talk/examples/call/Makefile.in
new file mode 100644
index 0000000..591d3aa
--- /dev/null
+++ b/talk/examples/call/Makefile.in
@@ -0,0 +1,537 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = call$(EXEEXT)
+subdir = talk/examples/call
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_call_OBJECTS = call-call_main.$(OBJEXT) call-callclient.$(OBJEXT) \
+	call-console.$(OBJEXT)
+call_OBJECTS = $(am_call_OBJECTS)
+am__DEPENDENCIES_1 =
+call_DEPENDENCIES =  \
+	$(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 \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(call_SOURCES)
+DIST_SOURCES = $(call_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+EXTRA_DIST = call.vcproj
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/examples/call/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/examples/call/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(bindir)/$$f"; \
+	done
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+call$(EXEEXT): $(call_OBJECTS) $(call_DEPENDENCIES) 
+	@rm -f call$(EXEEXT)
+	$(CXXLINK) $(call_LDFLAGS) $(call_OBJECTS) $(call_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-call_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-callclient.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-console.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+call-call_main.o: call_main.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -MT call-call_main.o -MD -MP -MF "$(DEPDIR)/call-call_main.Tpo" -c -o call-call_main.o `test -f 'call_main.cc' || echo '$(srcdir)/'`call_main.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/call-call_main.Tpo" "$(DEPDIR)/call-call_main.Po"; else rm -f "$(DEPDIR)/call-call_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='call_main.cc' object='call-call_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -c -o call-call_main.o `test -f 'call_main.cc' || echo '$(srcdir)/'`call_main.cc
+
+call-call_main.obj: call_main.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -MT call-call_main.obj -MD -MP -MF "$(DEPDIR)/call-call_main.Tpo" -c -o call-call_main.obj `if test -f 'call_main.cc'; then $(CYGPATH_W) 'call_main.cc'; else $(CYGPATH_W) '$(srcdir)/call_main.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/call-call_main.Tpo" "$(DEPDIR)/call-call_main.Po"; else rm -f "$(DEPDIR)/call-call_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='call_main.cc' object='call-call_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -c -o call-call_main.obj `if test -f 'call_main.cc'; then $(CYGPATH_W) 'call_main.cc'; else $(CYGPATH_W) '$(srcdir)/call_main.cc'; fi`
+
+call-callclient.o: callclient.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -MT call-callclient.o -MD -MP -MF "$(DEPDIR)/call-callclient.Tpo" -c -o call-callclient.o `test -f 'callclient.cc' || echo '$(srcdir)/'`callclient.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/call-callclient.Tpo" "$(DEPDIR)/call-callclient.Po"; else rm -f "$(DEPDIR)/call-callclient.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='callclient.cc' object='call-callclient.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -c -o call-callclient.o `test -f 'callclient.cc' || echo '$(srcdir)/'`callclient.cc
+
+call-callclient.obj: callclient.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -MT call-callclient.obj -MD -MP -MF "$(DEPDIR)/call-callclient.Tpo" -c -o call-callclient.obj `if test -f 'callclient.cc'; then $(CYGPATH_W) 'callclient.cc'; else $(CYGPATH_W) '$(srcdir)/callclient.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/call-callclient.Tpo" "$(DEPDIR)/call-callclient.Po"; else rm -f "$(DEPDIR)/call-callclient.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='callclient.cc' object='call-callclient.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -c -o call-callclient.obj `if test -f 'callclient.cc'; then $(CYGPATH_W) 'callclient.cc'; else $(CYGPATH_W) '$(srcdir)/callclient.cc'; fi`
+
+call-console.o: console.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -MT call-console.o -MD -MP -MF "$(DEPDIR)/call-console.Tpo" -c -o call-console.o `test -f 'console.cc' || echo '$(srcdir)/'`console.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/call-console.Tpo" "$(DEPDIR)/call-console.Po"; else rm -f "$(DEPDIR)/call-console.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='console.cc' object='call-console.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -c -o call-console.o `test -f 'console.cc' || echo '$(srcdir)/'`console.cc
+
+call-console.obj: console.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -MT call-console.obj -MD -MP -MF "$(DEPDIR)/call-console.Tpo" -c -o call-console.obj `if test -f 'console.cc'; then $(CYGPATH_W) 'console.cc'; else $(CYGPATH_W) '$(srcdir)/console.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/call-console.Tpo" "$(DEPDIR)/call-console.Po"; else rm -f "$(DEPDIR)/call-console.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='console.cc' object='call-console.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(call_CXXFLAGS) $(CXXFLAGS) -c -o call-console.obj `if test -f 'console.cc'; then $(CYGPATH_W) 'console.cc'; else $(CYGPATH_W) '$(srcdir)/console.cc'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+	clean-generic clean-libtool ctags distclean distclean-compile \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-binPROGRAMS install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-binPROGRAMS uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/examples/call/call.vcproj b/talk/examples/call/call.vcproj
new file mode 100755
index 0000000..14d126f
--- /dev/null
+++ b/talk/examples/call/call.vcproj
@@ -0,0 +1,261 @@
+<?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 &quot;$(SolutionDir)\third_party\gips\Library\gipsvoiceenginelite.lib&quot; 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 &quot;$(SolutionDir)\third_party\gips\Library\gipsvoiceenginelite.lib&quot;"

+				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
new file mode 100755
index 0000000..989e3a2
--- /dev/null
+++ b/talk/examples/call/call_main.cc
@@ -0,0 +1,256 @@
+/*
+ * 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 <iomanip>
+#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/examples/call/callclient.h"
+#include "talk/examples/call/console.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_;
+
+
+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 PhoneSessionClient as its worker thread.
+
+  bool debug = false;
+  if (argc > 1 && !strcmp(argv[1], "-d"))
+    debug = true;
+  
+  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;
+  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("call");
+  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));
+  printf("Logging in as %s\n", jid.Str().c_str());
+
+  talk_base::PhysicalSocketServer ss;
+
+  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);
+  client->SetConsole(console);
+  talk_base::Thread *console_thread = new talk_base::Thread(&ss);
+  console_thread->Start();
+  console_thread->Post(console, MSG_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();
+
+  return 0;
+}
diff --git a/talk/examples/call/callclient.cc b/talk/examples/call/callclient.cc
new file mode 100755
index 0000000..38b535b
--- /dev/null
+++ b/talk/examples/call/callclient.cc
@@ -0,0 +1,364 @@
+/*
+ * 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 <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/p2p/base/sessionmanager.h"
+#include "talk/p2p/client/httpportallocator.h"
+#include "talk/p2p/client/sessionmanagertask.h"
+#include "talk/session/phone/phonesessionclient.h"
+#include "talk/examples/call/callclient.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"
+
+namespace {
+
+const char* DescribeStatus(buzz::Status::Show show, const std::string& desc) {
+  switch (show) {
+  case buzz::Status::SHOW_XA:      return desc.c_str();
+  case buzz::Status::SHOW_ONLINE:  return "online";
+  case buzz::Status::SHOW_AWAY:    return "away";
+  case buzz::Status::SHOW_DND:     return "do not disturb";
+  case buzz::Status::SHOW_CHAT:    return "ready to chat";
+  default:                         return "offline";
+  }
+}
+
+} // namespace
+
+const char* CALL_COMMANDS =
+"Available commands:\n"
+"\n"
+"  hangup  Ends the call.\n"
+"  mute    Stops sending voice.\n"
+"  unmute  Re-starts sending voice.\n"
+"  quit    Quits the application.\n"
+"";
+
+const char* RECEIVE_COMMANDS =
+"Available commands:\n"
+"\n"
+"  accept  Accepts the incoming call and switches to it.\n"
+"  reject  Rejects the incoming call and stays with the current call.\n"
+"  quit    Quits the application.\n"
+"";
+
+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"
+"";
+
+void CallClient::ParseLine(const std::string& line) {
+  std::vector<std::string> words;
+  int start = -1;
+  int state = 0;
+  for (int index = 0; index <= static_cast<int>(line.size()); ++index) {
+    if (state == 0) {
+      if (!isspace(line[index])) {
+        start = index;
+        state = 1;
+      }
+    } else {
+      assert(state == 1);
+      assert(start >= 0);
+      if (isspace(line[index])) {
+        std::string word(line, start, index - start);
+		words.push_back(word);
+        start = -1;
+        state = 0;
+      }
+    }
+  }
+
+  // Global commands
+  if ((words.size() == 1) && (words[0] == "quit")) {
+      exit(0);
+  }
+
+  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;
+    } else if ((words.size() == 1) && (words[0] == "reject")) {
+      call_->RejectSession(call_->sessions()[0]);
+      incoming_call_ = false;
+    } else {
+      console_->Print(RECEIVE_COMMANDS);
+    }    
+  } else if (call_) {
+    if ((words.size() == 1) && (words[0] == "hangup")) {
+      call_->Terminate();
+	  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 {
+      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 {
+      console_->Print(CONSOLE_COMMANDS);
+    }
+  }
+}
+
+CallClient::CallClient(buzz::XmppClient* xmpp_client)
+    : xmpp_client_(xmpp_client), roster_(new RosterMap), call_(NULL),
+      incoming_call_(false) {
+  xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange);
+}
+
+CallClient::~CallClient() {
+  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";
+  }
+}
+
+void CallClient::OnCallDestroy(cricket::Call* call) {
+  if (call == call_) {
+	console_->SetPrompt(NULL);
+    console_->Print("call destroyed");
+    call_ = 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:
+    console_->Print("connecting...");
+    break;
+
+  case buzz::XmppEngine::STATE_OPENING:
+    console_->Print("logging in...");
+    break;
+
+  case buzz::XmppEngine::STATE_OPEN:
+    console_->Print("logged in...");
+    InitPhone();
+    InitPresence();
+    break;
+
+  case buzz::XmppEngine::STATE_CLOSED:
+    buzz::XmppEngine::Error error = xmpp_client_->GetError(NULL);
+    console_->Print("logged out..." + strerror(error));
+    exit(0);
+  }
+}
+
+void CallClient::InitPhone() {
+  std::string client_unique = xmpp_client_->jid().Str();
+  cricket::InitRandom(client_unique.c_str(), client_unique.size());
+
+  worker_thread_ = new talk_base::Thread();
+
+  port_allocator_ = new cricket::HttpPortAllocator(&network_manager_, "call");
+
+  session_manager_ = new cricket::SessionManager(
+      port_allocator_, worker_thread_);
+  session_manager_->SignalRequestSignaling.connect(
+      this, &CallClient::OnRequestSignaling);
+  session_manager_->OnSignalingReady();
+
+  session_manager_task_ =
+      new cricket::SessionManagerTask(xmpp_client_, session_manager_);
+  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);
+
+  worker_thread_->Start();
+}
+
+void CallClient::OnRequestSignaling() {
+  session_manager_->OnSignalingReady();
+}
+
+void CallClient::OnCallCreate(cricket::Call* call) {
+  call->SignalSessionState.connect(this, &CallClient::OnSessionState);
+}
+
+void CallClient::OnSessionState(cricket::Call* call,
+                                cricket::Session* session,
+                                cricket::Session::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;
+  } else if (state == cricket::Session::STATE_SENTINITIATE) {
+    console_->Print("calling...");
+  } else if (state == cricket::Session::STATE_RECEIVEDACCEPT) {
+    console_->Print("call answered");
+  } else if (state == cricket::Session::STATE_RECEIVEDREJECT) {
+    console_->Print("call not answered");
+  } else if (state == cricket::Session::STATE_INPROGRESS) {
+    console_->Print("call in progress");
+  } 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_->SignalStatusUpdate.connect(
+    this, &CallClient::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_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_->Start();
+}
+
+void CallClient::OnStatusUpdate(const buzz::Status& status) {
+  RosterItem item;
+  item.jid = status.jid();
+  item.show = status.show();
+  item.status = status.status();
+
+  std::string key = item.jid.Str();
+
+  if (status.available() && status.phone_capability()) {
+     console_->Printf("Adding to roster: %s", key.c_str());
+    (*roster_)[key] = item;
+  } else {
+    console_->Printf("Removing from roster: %s", key.c_str());
+    RosterMap::iterator iter = roster_->find(key);
+    if (iter != roster_->end())
+      roster_->erase(iter);
+  }
+}
+
+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);
+  RosterMap::iterator iter = roster_->begin();
+  while (iter != roster_->end()) {
+    if (iter->second.jid.BareEquals(callto_jid)) {
+      found = true;
+      found_jid = iter->second.jid;
+      break;
+    }
+    ++iter;
+  }
+
+
+  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_);
+  } else {
+    console_->Printf("Could not find online friend '%s'", name.c_str());
+  } 
+}
diff --git a/talk/examples/call/callclient.h b/talk/examples/call/callclient.h
new file mode 100755
index 0000000..1138f52
--- /dev/null
+++ b/talk/examples/call/callclient.h
@@ -0,0 +1,105 @@
+/*
+ * 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 CRICKET_EXAMPLES_CALL_CALLCLIENT_H__
+#define CRICKET_EXAMPLES_CALL_CALLCLIENT_H__
+
+#include <map>
+#include <string>
+#include "talk/base/autodetectproxy.h"
+#include "talk/p2p/base/session.h"
+#include "talk/p2p/client/httpportallocator.h"
+#include "talk/xmpp/xmppclient.h"
+#include "talk/examples/login/status.h"
+#include "talk/examples/call/console.h"
+
+namespace buzz {
+class PresencePushTask;
+class Status;
+}
+
+namespace talk_base {
+class Thread;
+class NetworkManager;
+}
+
+namespace cricket {
+class PortAllocator;
+class PhoneSessionClient;
+class Receiver;
+class Call;
+class SessionManagerTask;
+}
+
+struct RosterItem {
+  buzz::Jid jid;
+  buzz::Status::Show show;
+  std::string status;
+};
+
+class CallClient: public sigslot::has_slots<> {
+public:
+  CallClient(buzz::XmppClient* xmpp_client);
+  ~CallClient();
+
+  cricket::PhoneSessionClient* phone_client() const { return phone_client_; }
+
+  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;
+
+  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_;
+  cricket::SessionManager* session_manager_;
+  cricket::SessionManagerTask* session_manager_task_;
+  cricket::PhoneSessionClient* phone_client_;
+  
+  cricket::Call* call_; 
+  cricket::Session *session_;
+  bool incoming_call_;
+
+  buzz::PresencePushTask* presence_push_;
+  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);
+};
+
+#endif // CRICKET_EXAMPLES_CALL_CALLCLIENT_H__
diff --git a/talk/examples/call/console.cc b/talk/examples/call/console.cc
new file mode 100755
index 0000000..d489fd8
--- /dev/null
+++ b/talk/examples/call/console.cc
@@ -0,0 +1,77 @@
+/*
+ * 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
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <cassert>
+#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")),
+  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));
+  }
+}
+
+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::Print(const char* str) {
+  printf("\n%s", str);
+  if (prompting_)
+    printf("\n(%s) ", prompt_.c_str());
+}
+
+void Console::Print(const std::string& str) {
+  Print(str.c_str());
+}
+
+void Console::Printf(const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  char buf[4096];
+  int size = vsnprintf(buf, sizeof(buf), format, ap);
+  assert(size >= 0);
+  assert(size < static_cast<int>(sizeof(buf)));
+  buf[size] = '\0';
+  Print(buf);
+
+  va_end(ap);
+}
\ No newline at end of file
diff --git a/talk/examples/call/console.h b/talk/examples/call/console.h
new file mode 100755
index 0000000..264251a
--- /dev/null
+++ b/talk/examples/call/console.h
@@ -0,0 +1,60 @@
+/*
+ * 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 CRICKET_EXAMPLES_CALL_CONSOLE_H__
+#define CRICKET_EXAMPLES_CALL_CONSOLE_H__
+
+#include "talk/base/thread.h"
+#include "talk/base/messagequeue.h"
+
+class CallClient;
+
+enum {
+	MSG_START,
+	MSG_INPUT,
+};
+
+class Console : public talk_base::MessageHandler {
+ public:
+  Console(talk_base::Thread *thread, CallClient *client);
+  virtual void OnMessage(talk_base::Message *msg);
+  void SetPrompt(const char *prompt) {
+	  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_;}
+
+  void Print(const char* str);
+  void Print(const std::string& str);
+  void Printf(const char* format, ...);
+ private:
+  CallClient *client_;
+  talk_base::Thread *client_thread_;
+  void StartConsole();
+  void ParseLine(std::string &str);
+  std::string prompt_;
+  bool prompting_;
+};
+
+#endif // CRICKET_EXAMPLES_CALL_CONSOLE_H__
+
diff --git a/talk/examples/login/Makefile.am b/talk/examples/login/Makefile.am
new file mode 100755
index 0000000..7bb7804
--- /dev/null
+++ b/talk/examples/login/Makefile.am
@@ -0,0 +1,26 @@
+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/Makefile.in b/talk/examples/login/Makefile.in
new file mode 100644
index 0000000..3d70be5
--- /dev/null
+++ b/talk/examples/login/Makefile.in
@@ -0,0 +1,600 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = login$(EXEEXT)
+subdir = talk/examples/login
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketexampleslogin_la_LIBADD =
+am_libcricketexampleslogin_la_OBJECTS = xmppsocket.lo xmppauth.lo \
+	xmppthread.lo xmpppump.lo jingleinfotask.lo presenceouttask.lo \
+	presencepushtask.lo
+libcricketexampleslogin_la_OBJECTS =  \
+	$(am_libcricketexampleslogin_la_OBJECTS)
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_login_OBJECTS = login-login_main.$(OBJEXT) \
+	login-xmppsocket.$(OBJEXT) login-xmppthread.$(OBJEXT) \
+	login-xmpppump.$(OBJEXT) login-xmppauth.$(OBJEXT)
+login_OBJECTS = $(am_login_OBJECTS)
+am__DEPENDENCIES_1 =
+login_DEPENDENCIES = $(top_srcdir)/talk/xmpp/libcricketxmpp.la \
+	$(top_srcdir)/talk/xmllite/libcricketxmllite.la \
+	$(top_srcdir)/talk/base/libcricketbase.la \
+	$(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketexampleslogin_la_SOURCES) $(login_SOURCES)
+DIST_SOURCES = $(libcricketexampleslogin_la_SOURCES) $(login_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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
+
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/examples/login/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/examples/login/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketexampleslogin.la: $(libcricketexampleslogin_la_OBJECTS) $(libcricketexampleslogin_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketexampleslogin_la_LDFLAGS) $(libcricketexampleslogin_la_OBJECTS) $(libcricketexampleslogin_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(bindir)/$$f"; \
+	done
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+login$(EXEEXT): $(login_OBJECTS) $(login_DEPENDENCIES) 
+	@rm -f login$(EXEEXT)
+	$(CXXLINK) $(login_LDFLAGS) $(login_OBJECTS) $(login_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jingleinfotask.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/login-login_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/login-xmppauth.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/login-xmpppump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/login-xmppsocket.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/login-xmppthread.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/presenceouttask.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/presencepushtask.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmppauth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmpppump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmppsocket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmppthread.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+login-login_main.o: login_main.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-login_main.o -MD -MP -MF "$(DEPDIR)/login-login_main.Tpo" -c -o login-login_main.o `test -f 'login_main.cc' || echo '$(srcdir)/'`login_main.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-login_main.Tpo" "$(DEPDIR)/login-login_main.Po"; else rm -f "$(DEPDIR)/login-login_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='login_main.cc' object='login-login_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-login_main.o `test -f 'login_main.cc' || echo '$(srcdir)/'`login_main.cc
+
+login-login_main.obj: login_main.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-login_main.obj -MD -MP -MF "$(DEPDIR)/login-login_main.Tpo" -c -o login-login_main.obj `if test -f 'login_main.cc'; then $(CYGPATH_W) 'login_main.cc'; else $(CYGPATH_W) '$(srcdir)/login_main.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-login_main.Tpo" "$(DEPDIR)/login-login_main.Po"; else rm -f "$(DEPDIR)/login-login_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='login_main.cc' object='login-login_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-login_main.obj `if test -f 'login_main.cc'; then $(CYGPATH_W) 'login_main.cc'; else $(CYGPATH_W) '$(srcdir)/login_main.cc'; fi`
+
+login-xmppsocket.o: xmppsocket.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmppsocket.o -MD -MP -MF "$(DEPDIR)/login-xmppsocket.Tpo" -c -o login-xmppsocket.o `test -f 'xmppsocket.cc' || echo '$(srcdir)/'`xmppsocket.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmppsocket.Tpo" "$(DEPDIR)/login-xmppsocket.Po"; else rm -f "$(DEPDIR)/login-xmppsocket.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmppsocket.cc' object='login-xmppsocket.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmppsocket.o `test -f 'xmppsocket.cc' || echo '$(srcdir)/'`xmppsocket.cc
+
+login-xmppsocket.obj: xmppsocket.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmppsocket.obj -MD -MP -MF "$(DEPDIR)/login-xmppsocket.Tpo" -c -o login-xmppsocket.obj `if test -f 'xmppsocket.cc'; then $(CYGPATH_W) 'xmppsocket.cc'; else $(CYGPATH_W) '$(srcdir)/xmppsocket.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmppsocket.Tpo" "$(DEPDIR)/login-xmppsocket.Po"; else rm -f "$(DEPDIR)/login-xmppsocket.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmppsocket.cc' object='login-xmppsocket.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmppsocket.obj `if test -f 'xmppsocket.cc'; then $(CYGPATH_W) 'xmppsocket.cc'; else $(CYGPATH_W) '$(srcdir)/xmppsocket.cc'; fi`
+
+login-xmppthread.o: xmppthread.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmppthread.o -MD -MP -MF "$(DEPDIR)/login-xmppthread.Tpo" -c -o login-xmppthread.o `test -f 'xmppthread.cc' || echo '$(srcdir)/'`xmppthread.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmppthread.Tpo" "$(DEPDIR)/login-xmppthread.Po"; else rm -f "$(DEPDIR)/login-xmppthread.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmppthread.cc' object='login-xmppthread.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmppthread.o `test -f 'xmppthread.cc' || echo '$(srcdir)/'`xmppthread.cc
+
+login-xmppthread.obj: xmppthread.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmppthread.obj -MD -MP -MF "$(DEPDIR)/login-xmppthread.Tpo" -c -o login-xmppthread.obj `if test -f 'xmppthread.cc'; then $(CYGPATH_W) 'xmppthread.cc'; else $(CYGPATH_W) '$(srcdir)/xmppthread.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmppthread.Tpo" "$(DEPDIR)/login-xmppthread.Po"; else rm -f "$(DEPDIR)/login-xmppthread.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmppthread.cc' object='login-xmppthread.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmppthread.obj `if test -f 'xmppthread.cc'; then $(CYGPATH_W) 'xmppthread.cc'; else $(CYGPATH_W) '$(srcdir)/xmppthread.cc'; fi`
+
+login-xmpppump.o: xmpppump.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmpppump.o -MD -MP -MF "$(DEPDIR)/login-xmpppump.Tpo" -c -o login-xmpppump.o `test -f 'xmpppump.cc' || echo '$(srcdir)/'`xmpppump.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmpppump.Tpo" "$(DEPDIR)/login-xmpppump.Po"; else rm -f "$(DEPDIR)/login-xmpppump.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmpppump.cc' object='login-xmpppump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmpppump.o `test -f 'xmpppump.cc' || echo '$(srcdir)/'`xmpppump.cc
+
+login-xmpppump.obj: xmpppump.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmpppump.obj -MD -MP -MF "$(DEPDIR)/login-xmpppump.Tpo" -c -o login-xmpppump.obj `if test -f 'xmpppump.cc'; then $(CYGPATH_W) 'xmpppump.cc'; else $(CYGPATH_W) '$(srcdir)/xmpppump.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmpppump.Tpo" "$(DEPDIR)/login-xmpppump.Po"; else rm -f "$(DEPDIR)/login-xmpppump.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmpppump.cc' object='login-xmpppump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmpppump.obj `if test -f 'xmpppump.cc'; then $(CYGPATH_W) 'xmpppump.cc'; else $(CYGPATH_W) '$(srcdir)/xmpppump.cc'; fi`
+
+login-xmppauth.o: xmppauth.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmppauth.o -MD -MP -MF "$(DEPDIR)/login-xmppauth.Tpo" -c -o login-xmppauth.o `test -f 'xmppauth.cc' || echo '$(srcdir)/'`xmppauth.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmppauth.Tpo" "$(DEPDIR)/login-xmppauth.Po"; else rm -f "$(DEPDIR)/login-xmppauth.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmppauth.cc' object='login-xmppauth.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmppauth.o `test -f 'xmppauth.cc' || echo '$(srcdir)/'`xmppauth.cc
+
+login-xmppauth.obj: xmppauth.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -MT login-xmppauth.obj -MD -MP -MF "$(DEPDIR)/login-xmppauth.Tpo" -c -o login-xmppauth.obj `if test -f 'xmppauth.cc'; then $(CYGPATH_W) 'xmppauth.cc'; else $(CYGPATH_W) '$(srcdir)/xmppauth.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/login-xmppauth.Tpo" "$(DEPDIR)/login-xmppauth.Po"; else rm -f "$(DEPDIR)/login-xmppauth.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='xmppauth.cc' object='login-xmppauth.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(login_CXXFLAGS) $(CXXFLAGS) -c -o login-xmppauth.obj `if test -f 'xmppauth.cc'; then $(CYGPATH_W) 'xmppauth.cc'; else $(CYGPATH_W) '$(srcdir)/xmppauth.cc'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+	clean-generic clean-libtool clean-noinstLTLIBRARIES ctags \
+	distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-binPROGRAMS \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-man install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-binPROGRAMS \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/examples/login/jingleinfotask.cc b/talk/examples/login/jingleinfotask.cc
new file mode 100755
index 0000000..4f75853
--- /dev/null
+++ b/talk/examples/login/jingleinfotask.cc
@@ -0,0 +1,112 @@
+#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
new file mode 100755
index 0000000..be7073b
--- /dev/null
+++ b/talk/examples/login/jingleinfotask.h
@@ -0,0 +1,36 @@
+#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
new file mode 100755
index 0000000..186d6f7
--- /dev/null
+++ b/talk/examples/login/login_main.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/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);
+
+  char auth_cookie[256];
+  scanf("%s", auth_cookie);
+  
+  char username[256];
+  scanf("%s", username);
+
+  // Start xmpp on a different thread
+  XmppThread thread;
+  thread.Start();
+
+  buzz::XmppClientSettings xcs;
+  xcs.set_user(username);
+  xcs.set_host("gmail.com");
+  xcs.set_use_tls(false);
+  xcs.set_auth_cookie(auth_cookie);
+  xcs.set_server(talk_base::SocketAddress("talk.google.com", 5222));
+  thread.Login(xcs);
+
+  // Use main thread for console input
+  std::string line;
+  while (std::getline(std::cin, line)) {
+    if (line == "quit")
+      break;
+  }
+  return 0;
+}
+
diff --git a/talk/examples/login/presenceouttask.cc b/talk/examples/login/presenceouttask.cc
new file mode 100755
index 0000000..1eaf516
--- /dev/null
+++ b/talk/examples/login/presenceouttask.cc
@@ -0,0 +1,133 @@
+/*
+ * 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(&current_time_seconds);
+      struct tm* current_time = gmtime(&current_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
new file mode 100755
index 0000000..bd691f4
--- /dev/null
+++ b/talk/examples/login/presenceouttask.h
@@ -0,0 +1,46 @@
+/*
+ * 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
new file mode 100755
index 0000000..4895190
--- /dev/null
+++ b/talk/examples/login/presencepushtask.cc
@@ -0,0 +1,161 @@
+/*
+ * 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
new file mode 100755
index 0000000..23cd1b8
--- /dev/null
+++ b/talk/examples/login/presencepushtask.h
@@ -0,0 +1,44 @@
+/*
+ * 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/status.h b/talk/examples/login/status.h
new file mode 100755
index 0000000..69f82b1
--- /dev/null
+++ b/talk/examples/login/status.h
@@ -0,0 +1,212 @@
+/*
+ * 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 _STATUS_H_
+#define _STATUS_H_
+
+#include "talk/xmpp/jid.h"
+#include "talk/xmpp/constants.h"
+
+#define GOOGLE_CLIENT_NODE "http://www.google.com/xmpp/client/caps"
+
+namespace buzz {
+
+class Status {
+public:
+  Status() :
+    pri_(0),
+    show_(SHOW_NONE),
+    available_(false),
+    e_code_(0),
+    phone_capability_(false),
+    fileshare_capability_(false),
+    know_capabilities_(false),
+    is_google_client_(false),
+    feedback_probation_(false) {};
+
+  ~Status() {}
+
+  // These are arranged in "priority order", i.e., if we see
+  // two statuses at the same priority but with different Shows,
+  // we will show the one with the highest show in the following
+  // order.
+  enum Show {
+    SHOW_NONE     = 0,
+    SHOW_OFFLINE  = 1,
+    SHOW_XA       = 2,
+    SHOW_AWAY     = 3,
+    SHOW_DND      = 4,
+    SHOW_ONLINE   = 5,
+    SHOW_CHAT     = 6,
+  };
+
+  const Jid & jid() const { return jid_; }
+  int priority() const { return pri_; }
+  Show show() const { return show_; }
+  const std::string & status() const { return status_; }
+  bool available() const { return available_ ; }
+  int error_code() const { return e_code_; }
+  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 is_google_client() const { return is_google_client_; }
+  const std::string & version() const { return version_; }
+  bool feedback_probation() const { return feedback_probation_; }
+  const std::string& sent_time() const { return sent_time_; }
+
+  void set_jid(const Jid & jid) { jid_ = jid; }
+  void set_priority(int pri) { pri_ = pri; }
+  void set_show(Show show) { show_ = show; }
+  void set_status(const std::string & status) { status_ = status; }
+  void set_available(bool a) { available_ = a; }
+  void set_error(int e_code, const std::string e_str)
+      { 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_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; }
+  void set_sent_time(const std::string& time) { sent_time_ = time; }
+
+  void UpdateWith(const Status & new_value) {
+    if (!new_value.know_capabilities()) {
+       bool k = know_capabilities();
+       bool i = is_google_client();
+       bool p = phone_capability();
+       std::string v = version();
+
+       *this = new_value;
+
+       set_know_capabilities(k);
+       set_is_google_client(i);
+       set_phone_capability(p);
+       set_version(v);
+    }
+    else {
+      *this = new_value;
+    }
+  }
+
+  bool HasQuietStatus() const {
+    if (status_.empty())
+      return false;
+    return !(QuietStatus().empty());
+  }
+
+  // Knowledge of other clients' silly automatic status strings -
+  // Don't show these.
+  std::string QuietStatus() const {
+    if (jid_.resource().find("Psi") != std::string::npos) {
+      if (status_ == "Online" ||
+          status_.find("Auto Status") != std::string::npos)
+        return STR_EMPTY;
+    }
+    if (jid_.resource().find("Gaim") != std::string::npos) {
+      if (status_ == "Sorry, I ran out for a bit!")
+        return STR_EMPTY;
+    }
+    return TrimStatus(status_);
+  }
+
+  std::string ExplicitStatus() const {
+    std::string result = QuietStatus();
+    if (result.empty()) {
+      result = ShowStatus();
+    }
+    return result;
+  }
+
+  std::string ShowStatus() const {
+    std::string result;
+    if (!available()) {
+      result = "Offline";
+    }
+    else {
+      switch (show()) {
+        case SHOW_AWAY:
+        case SHOW_XA:
+          result = "Idle";
+          break;
+        case SHOW_DND:
+          result = "Busy";
+          break;
+        case SHOW_CHAT:
+          result = "Chatty";
+          break;
+        default:
+          result = "Available";
+          break;
+      }
+    }
+    return result;
+  }
+
+  static std::string TrimStatus(const std::string & st) {
+    std::string s(st);
+    int j = 0;
+    bool collapsing = true;
+    for (unsigned int i = 0; i < s.length(); i+= 1) {
+      if (s[i] <= ' ' && s[i] >= 0) {
+        if (collapsing) {
+          continue;
+        }
+        else {
+          s[j] = ' ';
+          j += 1;
+          collapsing = true;
+        }
+      }
+      else {
+        s[j] = s[i];
+        j += 1;
+        collapsing = false;
+      }
+    }
+    if (collapsing && j > 0) {
+      j -= 1;
+    }
+    s.erase(j, s.length());
+    return s;
+  }
+
+private:
+  Jid jid_;
+  int pri_;
+  Show show_;
+  std::string status_;
+  bool available_;
+  int e_code_;
+  std::string e_str_;
+  bool feedback_probation_;
+
+  // capabilities (valid only if know_capabilities_
+  bool know_capabilities_;
+  bool phone_capability_;
+  bool fileshare_capability_;
+  bool is_google_client_;
+  std::string version_;
+
+  std::string sent_time_; // from the jabber:x:delay element
+};
+
+}
+
+
+#endif
diff --git a/talk/examples/login/xmppauth.cc b/talk/examples/login/xmppauth.cc
new file mode 100755
index 0000000..8bbadb0
--- /dev/null
+++ b/talk/examples/login/xmppauth.cc
@@ -0,0 +1,86 @@
+/*
+ * 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/examples/login/xmppauth.h"
+#include "talk/xmpp/saslcookiemechanism.h"
+#include "talk/xmpp/saslplainmechanism.h"
+
+XmppAuth::XmppAuth() : done_(false), error_(false) {
+}
+
+XmppAuth::~XmppAuth() {
+}
+  
+void XmppAuth::StartPreXmppAuth(const buzz::Jid & jid,
+                                const talk_base::SocketAddress & server,
+                                const talk_base::CryptString & pass,
+                                const std::string & auth_cookie) {
+  jid_ = jid;
+  passwd_ = pass;
+  auth_cookie_ = auth_cookie;
+  error_ = auth_cookie.empty();
+  done_ = true;
+
+  SignalAuthDone();
+}
+  
+std::string XmppAuth::ChooseBestSaslMechanism(
+    const std::vector<std::string> & mechanisms,
+    bool encrypted) {
+  std::vector<std::string>::const_iterator it;
+
+  // 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())
+    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())
+    return "X-GOOGLE-COOKIE";
+
+    it = std::find(mechanisms.begin(), mechanisms.end(), "PLAIN");
+    if (it != mechanisms.end())
+      return "PLAIN";
+
+  // No good mechanism found
+ return "";
+}
+
+buzz::SaslMechanism* XmppAuth::CreateSaslMechanism(
+    const std::string & mechanism) {
+  if (mechanism == "X-GOOGLE-TOKEN") {
+    return new buzz::SaslCookieMechanism(mechanism, jid_.Str(), auth_cookie_);
+  //} else if (mechanism == "X-GOOGLE-COOKIE") {
+  //  return new buzz::SaslCookieMechanism(mechanism, jid.Str(), sid_);
+  } else if (mechanism == "PLAIN") {
+    return new buzz::SaslPlainMechanism(jid_, passwd_);
+  } else {
+    return NULL;
+  }
+}
diff --git a/talk/examples/login/xmppauth.h b/talk/examples/login/xmppauth.h
new file mode 100755
index 0000000..fe379fe
--- /dev/null
+++ b/talk/examples/login/xmppauth.h
@@ -0,0 +1,72 @@
+/*
+ * 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 _XMPPAUTH_H_
+#define _XMPPAUTH_H_
+
+#include <vector>
+
+#include "talk/base/cryptstring.h"
+#include "talk/base/sigslot.h"
+#include "talk/xmpp/jid.h"
+#include "talk/xmpp/saslhandler.h"
+#include "talk/xmpp/prexmppauth.h"
+
+class XmppAuth: public buzz::PreXmppAuth {
+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() {
+      return buzz::CaptchaChallenge();
+  }
+  virtual std::string GetAuthCookie() { return auth_cookie_; }
+
+  virtual std::string ChooseBestSaslMechanism(
+      const std::vector<std::string> & mechanisms,
+      bool encrypted);
+
+  virtual buzz::SaslMechanism * CreateSaslMechanism(
+      const std::string & mechanism);
+
+private:
+  buzz::Jid jid_;
+  talk_base::CryptString passwd_;
+  std::string auth_cookie_;
+  bool done_, error_;
+};
+
+#endif
diff --git a/talk/examples/login/xmpppump.cc b/talk/examples/login/xmpppump.cc
new file mode 100755
index 0000000..de4057b
--- /dev/null
+++ b/talk/examples/login/xmpppump.cc
@@ -0,0 +1,78 @@
+/*
+ * 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/login/xmpppump.h"
+#include "talk/examples/login/xmppauth.h"
+
+XmppPump::XmppPump(XmppPumpNotify * notify) {
+  state_ = buzz::XmppEngine::STATE_NONE;
+  notify_ = notify;
+  client_ = new buzz::XmppClient(this);  // NOTE: deleted by TaskRunner
+}
+
+void XmppPump::DoLogin(const buzz::XmppClientSettings & xcs,
+                       buzz::AsyncSocket* socket,
+                       buzz::PreXmppAuth* auth) {
+  OnStateChange(buzz::XmppEngine::STATE_START);
+  if (!AllChildrenDone()) {
+    client_->SignalStateChange.connect(this, &XmppPump::OnStateChange);
+    client_->Connect(xcs, "", socket, auth);
+    client_->Start();
+  }
+}
+
+void XmppPump::DoDisconnect() {
+  if (!AllChildrenDone())
+    client_->Disconnect();
+  OnStateChange(buzz::XmppEngine::STATE_CLOSED);
+}
+
+void XmppPump::OnStateChange(buzz::XmppEngine::State state) {
+  if (state_ == state)
+    return;
+  state_ = state;
+  if (notify_ != NULL)
+    notify_->OnStateChange(state);
+}
+
+void XmppPump::WakeTasks() {
+  talk_base::Thread::Current()->Post(this);
+}
+
+int64 XmppPump::CurrentTime() {
+  return (int64)talk_base::Time();
+}
+
+void XmppPump::OnMessage(talk_base::Message *pmsg) {
+  RunTasks();
+}
+
+buzz::XmppReturnStatus XmppPump::SendStanza(const buzz::XmlElement *stanza) {
+  if (!AllChildrenDone())
+    return client_->SendStanza(stanza);
+  return buzz::XMPP_RETURN_BADSTATE;
+}
diff --git a/talk/examples/login/xmpppump.h b/talk/examples/login/xmpppump.h
new file mode 100755
index 0000000..e982184
--- /dev/null
+++ b/talk/examples/login/xmpppump.h
@@ -0,0 +1,73 @@
+/*
+ * 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 _XMPPPUMP_H_
+#define _XMPPPUMP_H_
+
+#include "talk/base/messagequeue.h"
+#include "talk/base/taskrunner.h"
+#include "talk/base/thread.h"
+#include "talk/base/time.h"
+#include "talk/xmpp/xmppclient.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
+
+// Simple xmpp pump
+
+class XmppPumpNotify {
+public:
+  virtual void OnStateChange(buzz::XmppEngine::State state) = 0;
+};
+
+class XmppPump : public talk_base::MessageHandler, public talk_base::TaskRunner {
+public:
+  XmppPump(XmppPumpNotify * notify = NULL);
+
+  buzz::XmppClient *client() { return client_; }
+
+  void DoLogin(const buzz::XmppClientSettings & xcs,
+               buzz::AsyncSocket* socket,
+               buzz::PreXmppAuth* auth);
+  void DoDisconnect();
+
+  void OnStateChange(buzz::XmppEngine::State state);
+
+  void WakeTasks();
+
+  int64 CurrentTime();
+
+  void OnMessage(talk_base::Message *pmsg);
+
+  buzz::XmppReturnStatus SendStanza(const buzz::XmlElement *stanza);
+
+private:
+  buzz::XmppClient *client_;
+  buzz::XmppEngine::State state_;
+  XmppPumpNotify *notify_;
+};
+
+#endif // _XMPPPUMP_H_
diff --git a/talk/examples/login/xmppsocket.cc b/talk/examples/login/xmppsocket.cc
new file mode 100755
index 0000000..3c96413
--- /dev/null
+++ b/talk/examples/login/xmppsocket.cc
@@ -0,0 +1,153 @@
+/*
+ * 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
+
+#include <errno.h>
+#include "talk/base/basicdefs.h"
+#include "talk/base/logging.h"
+#include "talk/base/thread.h"
+#ifdef FEATURE_ENABLE_SSL
+#include "talk/base/ssladapter.h"
+#endif
+#include "xmppsocket.h"
+
+XmppSocket::XmppSocket(bool tls) : tls_(tls) {
+  talk_base::Thread* pth = talk_base::Thread::Current();
+  talk_base::AsyncSocket* socket =
+    pth->socketserver()->CreateAsyncSocket(SOCK_STREAM);
+#ifdef FEATURE_ENABLE_SSL
+  if (tls_) {
+    socket = talk_base::SSLAdapter::Create(socket);
+  }
+#endif
+  cricket_socket_ = socket;
+  cricket_socket_->SignalReadEvent.connect(this, &XmppSocket::OnReadEvent);
+  cricket_socket_->SignalWriteEvent.connect(this, &XmppSocket::OnWriteEvent);
+  cricket_socket_->SignalConnectEvent.connect(this,
+                                              &XmppSocket::OnConnectEvent);
+  state_ = buzz::AsyncSocket::STATE_CLOSED;
+}
+
+XmppSocket::~XmppSocket() {
+  Close();
+  delete cricket_socket_;
+}
+
+void XmppSocket::OnReadEvent(talk_base::AsyncSocket * socket) {
+  SignalRead(); 
+}
+
+void XmppSocket::OnWriteEvent(talk_base::AsyncSocket * socket) {
+  // Write bytes if there are any
+  while (buffer_.Length() != 0) {
+    int written = cricket_socket_->Send(buffer_.Data(), buffer_.Length());
+    if (written > 0) {
+      buffer_.Shift(written);
+      continue;
+    }
+    if (!cricket_socket_->IsBlocking())
+      LOG(LS_ERROR) << "Send error: " << cricket_socket_->GetError();
+    return;
+  }
+}
+
+void XmppSocket::OnConnectEvent(talk_base::AsyncSocket * socket) {
+#if defined(FEATURE_ENABLE_SSL)
+  if (state_ == buzz::AsyncSocket::STATE_TLS_CONNECTING) {
+    state_ = buzz::AsyncSocket::STATE_TLS_OPEN;
+    SignalSSLConnected();
+    OnWriteEvent(cricket_socket_);
+    return;
+  }
+#endif  // !defined(FEATURE_ENABLE_SSL)
+  state_ = buzz::AsyncSocket::STATE_OPEN;
+  SignalConnected();
+}
+
+buzz::AsyncSocket::State XmppSocket::state() {
+  return state_;
+}
+
+buzz::AsyncSocket::Error XmppSocket::error() {
+  return buzz::AsyncSocket::ERROR_NONE;
+}
+
+int XmppSocket::GetError() {
+  return 0;
+}
+
+bool XmppSocket::Connect(const talk_base::SocketAddress& addr) {
+  if (cricket_socket_->Connect(addr) < 0) {
+    return cricket_socket_->IsBlocking();
+  }
+  return true;
+}
+
+bool XmppSocket::Read(char * data, size_t len, size_t* len_read) {
+  int read = cricket_socket_->Recv(data, len);
+  if (read > 0) {
+    *len_read = (size_t)read;
+    return true;
+  }
+  return false;
+}
+
+bool XmppSocket::Write(const char * data, size_t len) {
+  buffer_.WriteBytes(data, len);
+  OnWriteEvent(cricket_socket_);
+  return true;
+}
+
+bool XmppSocket::Close() {
+  if (state_ != buzz::AsyncSocket::STATE_OPEN)
+    return false;
+  if (cricket_socket_->Close() == 0) {
+    state_ = buzz::AsyncSocket::STATE_CLOSED;
+    SignalClosed();
+    return true;
+  }
+  return false;
+}
+
+bool XmppSocket::StartTls(const std::string & domainname) {
+#if defined(FEATURE_ENABLE_SSL)
+  if (!tls_)
+    return false;
+  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;
+  state_ = buzz::AsyncSocket::STATE_TLS_CONNECTING;
+  return true;
+#else  // !defined(FEATURE_ENABLE_SSL)
+  return false;
+#endif  // !defined(FEATURE_ENABLE_SSL)
+}
diff --git a/talk/examples/login/xmppsocket.h b/talk/examples/login/xmppsocket.h
new file mode 100755
index 0000000..8ed7e3c
--- /dev/null
+++ b/talk/examples/login/xmppsocket.h
@@ -0,0 +1,64 @@
+/*
+ * 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 _XMPPSOCKET_H_
+#define _XMPPSOCKET_H_
+
+#include "talk/base/asyncsocket.h"
+#include "talk/base/bytebuffer.h"
+#include "talk/base/sigslot.h"
+#include "talk/xmpp/asyncsocket.h"
+
+extern talk_base::AsyncSocket* cricket_socket_;
+
+class XmppSocket : public buzz::AsyncSocket, public sigslot::has_slots<> {
+public:
+  XmppSocket(bool tls);
+  ~XmppSocket();
+
+  virtual buzz::AsyncSocket::State state();
+  virtual buzz::AsyncSocket::Error error();
+  virtual int GetError();
+
+  virtual bool Connect(const talk_base::SocketAddress& addr);
+  virtual bool Read(char * data, size_t len, size_t* len_read);
+  virtual bool Write(const char * data, size_t len);
+  virtual bool Close();
+  virtual bool StartTls(const std::string & domainname);
+
+private:
+  void OnReadEvent(talk_base::AsyncSocket * socket);
+  void OnWriteEvent(talk_base::AsyncSocket * socket);
+  void OnConnectEvent(talk_base::AsyncSocket * socket);
+
+  talk_base::AsyncSocket * cricket_socket_;
+  buzz::AsyncSocket::State state_;
+  talk_base::ByteBuffer buffer_;
+  bool tls_;
+};
+
+#endif // _XMPPSOCKET_H_
diff --git a/talk/examples/login/xmppthread.cc b/talk/examples/login/xmppthread.cc
new file mode 100755
index 0000000..bb5d8cd
--- /dev/null
+++ b/talk/examples/login/xmppthread.cc
@@ -0,0 +1,80 @@
+/*
+ * 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/xmppclientsettings.h"
+#include "talk/examples/login/xmppthread.h"
+#include "talk/examples/login/xmppauth.h"
+
+namespace {
+
+const uint32 MSG_LOGIN = 1;
+const uint32 MSG_DISCONNECT = 2;
+
+struct LoginData: public talk_base::MessageData {
+  LoginData(const buzz::XmppClientSettings& s) : xcs(s) {}
+  virtual ~LoginData() {}
+
+  buzz::XmppClientSettings xcs;
+};
+
+} // namespace
+
+XmppThread::XmppThread() {
+  pump_ = new XmppPump(this);
+}
+
+XmppThread::~XmppThread() {
+  delete pump_;
+}
+
+void XmppThread::ProcessMessages(int cms) {
+  talk_base::Thread::ProcessMessages(cms);
+}
+
+void XmppThread::Login(const buzz::XmppClientSettings& xcs) {
+  Post(this, MSG_LOGIN, new LoginData(xcs));
+}
+
+void XmppThread::Disconnect() {
+  Post(this, MSG_DISCONNECT);
+}
+
+void XmppThread::OnStateChange(buzz::XmppEngine::State state) {
+}
+
+void XmppThread::OnMessage(talk_base::Message* pmsg) {
+  if (pmsg->message_id == MSG_LOGIN) {
+    assert(pmsg->pdata);
+    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);
+  }
+}
diff --git a/talk/examples/login/xmppthread.h b/talk/examples/login/xmppthread.h
new file mode 100755
index 0000000..247b7bd
--- /dev/null
+++ b/talk/examples/login/xmppthread.h
@@ -0,0 +1,57 @@
+/*
+ * 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 _XMPPTHREAD_H_
+#define _XMPPTHREAD_H_
+
+#include "talk/xmpp/xmppclientsettings.h"
+#include "talk/base/thread.h"
+#include "talk/examples/login/xmpppump.h"
+#include "talk/examples/login/xmppsocket.h"
+#include <iostream>
+
+class XmppThread:
+    public talk_base::Thread, XmppPumpNotify, talk_base::MessageHandler {
+public:
+  XmppThread();
+  ~XmppThread();
+
+  buzz::XmppClient* client() { return pump_->client(); }
+
+  void ProcessMessages(int cms);
+
+  void Login(const buzz::XmppClientSettings & xcs);
+  void Disconnect();
+
+private:
+  XmppPump* pump_;
+
+  void OnStateChange(buzz::XmppEngine::State state);
+  void OnMessage(talk_base::Message* pmsg);
+};
+
+#endif // _XMPPTHREAD_H_
diff --git a/talk/examples/pcp/Makefile.am b/talk/examples/pcp/Makefile.am
new file mode 100755
index 0000000..de779cd
--- /dev/null
+++ b/talk/examples/pcp/Makefile.am
@@ -0,0 +1,15 @@
+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/Makefile.in b/talk/examples/pcp/Makefile.in
new file mode 100644
index 0000000..0bba040
--- /dev/null
+++ b/talk/examples/pcp/Makefile.in
@@ -0,0 +1,501 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = pcp$(EXEEXT)
+subdir = talk/examples/pcp
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am_pcp_OBJECTS = pcp-pcp_main.$(OBJEXT)
+pcp_OBJECTS = $(am_pcp_OBJECTS)
+am__DEPENDENCIES_1 =
+pcp_DEPENDENCIES =  \
+	$(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 \
+	$(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(pcp_SOURCES)
+DIST_SOURCES = $(pcp_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/examples/pcp/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/examples/pcp/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(bindir)/$$f"; \
+	done
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+pcp$(EXEEXT): $(pcp_OBJECTS) $(pcp_DEPENDENCIES) 
+	@rm -f pcp$(EXEEXT)
+	$(CXXLINK) $(pcp_LDFLAGS) $(pcp_OBJECTS) $(pcp_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcp-pcp_main.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+pcp-pcp_main.o: pcp_main.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcp_CXXFLAGS) $(CXXFLAGS) -MT pcp-pcp_main.o -MD -MP -MF "$(DEPDIR)/pcp-pcp_main.Tpo" -c -o pcp-pcp_main.o `test -f 'pcp_main.cc' || echo '$(srcdir)/'`pcp_main.cc; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/pcp-pcp_main.Tpo" "$(DEPDIR)/pcp-pcp_main.Po"; else rm -f "$(DEPDIR)/pcp-pcp_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='pcp_main.cc' object='pcp-pcp_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcp_CXXFLAGS) $(CXXFLAGS) -c -o pcp-pcp_main.o `test -f 'pcp_main.cc' || echo '$(srcdir)/'`pcp_main.cc
+
+pcp-pcp_main.obj: pcp_main.cc
+@am__fastdepCXX_TRUE@	if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcp_CXXFLAGS) $(CXXFLAGS) -MT pcp-pcp_main.obj -MD -MP -MF "$(DEPDIR)/pcp-pcp_main.Tpo" -c -o pcp-pcp_main.obj `if test -f 'pcp_main.cc'; then $(CYGPATH_W) 'pcp_main.cc'; else $(CYGPATH_W) '$(srcdir)/pcp_main.cc'; fi`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/pcp-pcp_main.Tpo" "$(DEPDIR)/pcp-pcp_main.Po"; else rm -f "$(DEPDIR)/pcp-pcp_main.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='pcp_main.cc' object='pcp-pcp_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcp_CXXFLAGS) $(CXXFLAGS) -c -o pcp-pcp_main.obj `if test -f 'pcp_main.cc'; then $(CYGPATH_W) 'pcp_main.cc'; else $(CYGPATH_W) '$(srcdir)/pcp_main.cc'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+	clean-generic clean-libtool ctags distclean distclean-compile \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-binPROGRAMS install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-binPROGRAMS uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/examples/pcp/pcp.vcproj b/talk/examples/pcp/pcp.vcproj
new file mode 100755
index 0000000..23ba860
--- /dev/null
+++ b/talk/examples/pcp/pcp.vcproj
@@ -0,0 +1,233 @@
+<?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
new file mode 100755
index 0000000..4d5646d
--- /dev/null
+++ b/talk/examples/pcp/pcp_main.cc
@@ -0,0 +1,615 @@
+/*
+ * 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.sln b/talk/libjingle.sln
new file mode 100755
index 0000000..fe0cf35
--- /dev/null
+++ b/talk/libjingle.sln
@@ -0,0 +1,37 @@
+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
new file mode 100755
index 0000000..2e3f7b2
--- /dev/null
+++ b/talk/libjingle.vcproj
@@ -0,0 +1,1131 @@
+<?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/p2p/Makefile.am b/talk/p2p/Makefile.am
new file mode 100755
index 0000000..c935a6b
--- /dev/null
+++ b/talk/p2p/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS=base client
diff --git a/talk/p2p/Makefile.in b/talk/p2p/Makefile.in
new file mode 100644
index 0000000..0e13b98
--- /dev/null
+++ b/talk/p2p/Makefile.in
@@ -0,0 +1,488 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/p2p
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-exec-recursive install-info-recursive \
+	install-recursive installcheck-recursive installdirs-recursive \
+	pdf-recursive ps-recursive uninstall-info-recursive \
+	uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+SUBDIRS = base client
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/p2p/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/p2p/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(mkdir_p) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
+	clean clean-generic clean-libtool clean-recursive ctags \
+	ctags-recursive distclean distclean-generic distclean-libtool \
+	distclean-recursive distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-recursive \
+	mostlyclean mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/p2p/base/Makefile.am b/talk/p2p/base/Makefile.am
new file mode 100755
index 0000000..537b6c2
--- /dev/null
+++ b/talk/p2p/base/Makefile.am
@@ -0,0 +1,68 @@
+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/Makefile.in b/talk/p2p/base/Makefile.in
new file mode 100644
index 0000000..c0dc08e
--- /dev/null
+++ b/talk/p2p/base/Makefile.in
@@ -0,0 +1,625 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = relayserver$(EXEEXT) stunserver$(EXEEXT)
+noinst_PROGRAMS = stunserver_unittest$(EXEEXT) \
+	session_unittest$(EXEEXT) port_unittest$(EXEEXT)
+subdir = talk/p2p/base
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketp2pbase_la_LIBADD =
+am_libcricketp2pbase_la_OBJECTS = stun.lo port.lo udpport.lo \
+	tcpport.lo stunport.lo relayport.lo stunrequest.lo \
+	sessionmanager.lo session.lo transport.lo transportchannel.lo \
+	transportchannelproxy.lo p2ptransport.lo \
+	p2ptransportchannel.lo rawtransport.lo rawtransportchannel.lo \
+	constants.lo pseudotcp.lo
+libcricketp2pbase_la_OBJECTS = $(am_libcricketp2pbase_la_OBJECTS)
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_port_unittest_OBJECTS = port_unittest.$(OBJEXT) \
+	stunserver.$(OBJEXT) relayserver.$(OBJEXT)
+port_unittest_OBJECTS = $(am_port_unittest_OBJECTS)
+am__DEPENDENCIES_1 = libcricketp2pbase.la ../../base/libcricketbase.la
+am__DEPENDENCIES_2 = ../../base/libcrickettest.la
+port_unittest_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_2)
+am_relayserver_OBJECTS = relayserver.$(OBJEXT) \
+	relayserver_main.$(OBJEXT)
+relayserver_OBJECTS = $(am_relayserver_OBJECTS)
+relayserver_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_session_unittest_OBJECTS = session_unittest.$(OBJEXT) \
+	stunserver.$(OBJEXT) relayserver.$(OBJEXT)
+session_unittest_OBJECTS = $(am_session_unittest_OBJECTS)
+am__DEPENDENCIES_3 =
+am__DEPENDENCIES_4 = ../../xmllite/libcricketxmllite.la \
+	../../xmpp/libcricketxmpp.la $(am__DEPENDENCIES_3)
+session_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_4)
+am_stunserver_OBJECTS = stunserver.$(OBJEXT) stunserver_main.$(OBJEXT)
+stunserver_OBJECTS = $(am_stunserver_OBJECTS)
+stunserver_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_stunserver_unittest_OBJECTS = stunserver_unittest.$(OBJEXT) \
+	stunserver.$(OBJEXT)
+stunserver_unittest_OBJECTS = $(am_stunserver_unittest_OBJECTS)
+stunserver_unittest_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_2)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketp2pbase_la_SOURCES) $(port_unittest_SOURCES) \
+	$(relayserver_SOURCES) $(session_unittest_SOURCES) \
+	$(stunserver_SOURCES) $(stunserver_unittest_SOURCES)
+DIST_SOURCES = $(libcricketp2pbase_la_SOURCES) \
+	$(port_unittest_SOURCES) $(relayserver_SOURCES) \
+	$(session_unittest_SOURCES) $(stunserver_SOURCES) \
+	$(stunserver_unittest_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/p2p/base/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/p2p/base/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketp2pbase.la: $(libcricketp2pbase_la_OBJECTS) $(libcricketp2pbase_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketp2pbase_la_LDFLAGS) $(libcricketp2pbase_la_OBJECTS) $(libcricketp2pbase_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(bindir)/$$f"; \
+	done
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+port_unittest$(EXEEXT): $(port_unittest_OBJECTS) $(port_unittest_DEPENDENCIES) 
+	@rm -f port_unittest$(EXEEXT)
+	$(CXXLINK) $(port_unittest_LDFLAGS) $(port_unittest_OBJECTS) $(port_unittest_LDADD) $(LIBS)
+relayserver$(EXEEXT): $(relayserver_OBJECTS) $(relayserver_DEPENDENCIES) 
+	@rm -f relayserver$(EXEEXT)
+	$(CXXLINK) $(relayserver_LDFLAGS) $(relayserver_OBJECTS) $(relayserver_LDADD) $(LIBS)
+session_unittest$(EXEEXT): $(session_unittest_OBJECTS) $(session_unittest_DEPENDENCIES) 
+	@rm -f session_unittest$(EXEEXT)
+	$(CXXLINK) $(session_unittest_LDFLAGS) $(session_unittest_OBJECTS) $(session_unittest_LDADD) $(LIBS)
+stunserver$(EXEEXT): $(stunserver_OBJECTS) $(stunserver_DEPENDENCIES) 
+	@rm -f stunserver$(EXEEXT)
+	$(CXXLINK) $(stunserver_LDFLAGS) $(stunserver_OBJECTS) $(stunserver_LDADD) $(LIBS)
+stunserver_unittest$(EXEEXT): $(stunserver_unittest_OBJECTS) $(stunserver_unittest_DEPENDENCIES) 
+	@rm -f stunserver_unittest$(EXEEXT)
+	$(CXXLINK) $(stunserver_unittest_LDFLAGS) $(stunserver_unittest_OBJECTS) $(stunserver_unittest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/p2ptransport.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/p2ptransportchannel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pseudotcp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rawtransport.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rawtransportchannel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relayport.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relayserver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relayserver_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sessionmanager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stun.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunport.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunrequest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunserver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunserver_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunserver_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcpport.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transportchannel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transportchannelproxy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udpport.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+	clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	clean-noinstPROGRAMS ctags distclean distclean-compile \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-binPROGRAMS install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-binPROGRAMS uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/p2p/base/candidate.h b/talk/p2p/base/candidate.h
new file mode 100755
index 0000000..ac41311
--- /dev/null
+++ b/talk/p2p/base/candidate.h
@@ -0,0 +1,119 @@
+/*
+ * 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 _CANDIDATE_H_
+#define _CANDIDATE_H_
+
+#include <string>
+#include <sstream>
+#include "talk/base/socketaddress.h"
+
+namespace cricket {
+
+// Candidate for ICE based connection discovery.
+
+class Candidate {
+public:
+
+  const std::string & name() const { return name_; }
+  void set_name(const std::string & name) { name_ = name; }
+
+  const std::string & protocol() const { return protocol_; }
+  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; }
+
+  const float preference() const { return preference_; }
+  void set_preference(const float preference) { preference_ = preference; }
+  const std::string preference_str() const {
+    std::ostringstream ost;
+    ost << preference_;
+    return ost.str();
+  }
+  void set_preference_str(const std::string & preference) {
+    std::istringstream ist(preference);
+    ist >> preference_;
+  }
+
+  const std::string & username() const { return username_; }
+  void set_username(const std::string & username) { username_ = username; }
+
+  const std::string & password() const { return password_; }
+  void set_password(const std::string & password) { password_ = password; }
+
+  const std::string & type() const { return type_; }
+  void set_type(const std::string & type) { type_ = type; }
+
+  const std::string & network_name() const { return network_name_; }
+  void set_network_name(const std::string & network_name) {
+    network_name_ = network_name;
+  }
+
+  // Candidates in a new generation replace those in the old generation.
+  uint32 generation() const { return generation_; }
+  void set_generation(uint32 generation) { generation_ = generation; }
+  const std::string generation_str() const {
+    std::ostringstream ost;
+    ost << generation_;
+    return ost.str();
+  }
+  void set_generation_str(const std::string& str) {
+    std::istringstream ist(str);
+    ist >> generation_;
+  }
+
+  // Determines whether this candidate is equivalent to the given one.
+  bool IsEquivalent(const Candidate& c) const {
+    // We ignore the network name, since that is just debug information, and
+    // the preference, since that should be the same if the rest is (and it's
+    // a float so equality checking is always worrisome).
+    return (name_ == c.name_) &&
+           (protocol_ == c.protocol_) &&
+           (address_ == c.address_) &&
+           (username_ == c.username_) &&
+           (password_ == c.password_) &&
+           (type_ == c.type_) &&
+           (generation_ == c.generation_);
+  }
+
+private:
+  std::string name_;
+  std::string protocol_;
+  talk_base::SocketAddress address_;
+  float preference_;
+  std::string username_;
+  std::string password_;
+  std::string type_;
+  std::string network_name_;
+  uint32 generation_;
+};
+
+} // namespace cricket
+
+#endif // _CANDIDATE_H_
diff --git a/talk/p2p/base/common.h b/talk/p2p/base/common.h
new file mode 100755
index 0000000..72f8cfa
--- /dev/null
+++ b/talk/p2p/base/common.h
@@ -0,0 +1,36 @@
+/*
+ * 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 CRICKET_P2P_BASE_COMMON_H__
+#define CRICKET_P2P_BASE_COMMON_H__
+
+#include "talk/base/logging.h"
+
+// Common log description format for jingle messages
+#define LOG_J(sev,obj) LOG(sev) << "Jingle:" << obj->ToString() << ": "
+
+#endif  // CRICKET_P2P_BASE_COMMON_H__
diff --git a/talk/p2p/base/constants.cc b/talk/p2p/base/constants.cc
new file mode 100755
index 0000000..13b9f2d
--- /dev/null
+++ b/talk/p2p/base/constants.cc
@@ -0,0 +1,62 @@
+/*
+ * 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/p2p/base/constants.h"
+
+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 buzz::QName QN_SESSION(true, NS_GOOGLESESSION, "session");
+
+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");
+
+#ifdef FEATURE_ENABLE_VOICEMAIL
+const buzz::QName QN_VOICEMAIL_REGARDING(true, NS_GOOGLEVOICEMAIL, "regarding");
+#endif
+
+const buzz::QName QN_INITIATOR(true, NS_EMPTY, "initiator");
+
+const buzz::QName QN_ADDRESS(true, cricket::NS_EMPTY, "address");
+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_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");
+
+// Legacy transport messages
+const buzz::QName kQnLegacyCandidate(true, cricket::NS_GOOGLESESSION, 
+                                     "candidate");
+}  // namespace cricket
diff --git a/talk/p2p/base/constants.h b/talk/p2p/base/constants.h
new file mode 100755
index 0000000..46315eb
--- /dev/null
+++ b/talk/p2p/base/constants.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 _CRICKET_P2P_BASE_CONSTANTS_H_
+#define _CRICKET_P2P_BASE_CONSTANTS_H_
+
+#include <string>
+#include "talk/xmllite/qname.h"
+
+// This file contains constants related to signaling that are used in various
+// classes in this directory.
+
+namespace cricket {
+
+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 buzz::QName QN_SESSION;
+
+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
+
+extern const buzz::QName QN_INITIATOR;
+
+extern const buzz::QName QN_ADDRESS;
+extern const buzz::QName QN_PORT;
+extern const buzz::QName QN_NETWORK;
+extern const buzz::QName QN_GENERATION;
+extern const buzz::QName QN_USERNAME;
+extern const buzz::QName QN_PASSWORD;
+extern const buzz::QName QN_PREFERENCE;
+extern const buzz::QName QN_PROTOCOL;
+
+// Legacy transport messages
+extern const buzz::QName kQnLegacyCandidate;
+
+}  // namespace cricket
+
+#endif  // _CRICKET_P2P_BASE_CONSTANTS_H_
diff --git a/talk/p2p/base/p2ptransport.cc b/talk/p2p/base/p2ptransport.cc
new file mode 100755
index 0000000..2221d8c
--- /dev/null
+++ b/talk/p2p/base/p2ptransport.cc
@@ -0,0 +1,209 @@
+/*
+ * 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/p2p/base/p2ptransport.h"
+#include "talk/base/common.h"
+#include "talk/p2p/base/candidate.h"
+#include "talk/p2p/base/constants.h"
+#include "talk/base/helpers.h"
+#include "talk/p2p/base/p2ptransportchannel.h"
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/constants.h"
+
+namespace {
+
+// We only allow usernames to be this many characters or fewer.
+const size_t kMaxUsernameSize = 16;
+
+}  // namespace
+
+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() {
+  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)
+      && error->HasAttr(buzz::QN_NAME)) {
+    std::string channel_name = error->Attr(buzz::QN_NAME);
+    if (HasChannel(channel_name)) {
+      SignalChannelGone(this, channel_name);
+    }
+  }
+  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) || 
+      !elem->HasAttr(QN_ADDRESS) ||
+      !elem->HasAttr(QN_PORT) ||
+      !elem->HasAttr(QN_USERNAME) ||
+      !elem->HasAttr(QN_PREFERENCE) ||
+      !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());
+  }
+
+  // Parse the address given.
+  talk_base::SocketAddress address;
+  if (!ParseAddress(stanza, elem, &address))
+    return false;
+
+  candidate->set_name(elem->Attr(buzz::QN_NAME));
+  candidate->set_address(address);
+  candidate->set_username(elem->Attr(QN_USERNAME));
+  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))
+    candidate->set_type(elem->Attr(buzz::QN_TYPE));
+  if (elem->HasAttr(QN_NETWORK))
+    candidate->set_network_name(elem->Attr(QN_NETWORK));
+
+  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;
+}
+
+TransportChannelImpl* P2PTransport::CreateTransportChannel(
+  const std::string& name, const std::string &session_type) {
+  return new P2PTransportChannel(
+    name, session_type, this, session_manager()->port_allocator());
+}
+
+void P2PTransport::DestroyTransportChannel(TransportChannelImpl* channel) {
+  delete channel;
+}
+
+}  // namespace cricket
diff --git a/talk/p2p/base/p2ptransport.h b/talk/p2p/base/p2ptransport.h
new file mode 100755
index 0000000..2027d4a
--- /dev/null
+++ b/talk/p2p/base/p2ptransport.h
@@ -0,0 +1,86 @@
+/*
+ * 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 _CRICKET_P2P_BASE_P2PTRANSPORT_H_
+#define _CRICKET_P2P_BASE_P2PTRANSPORT_H_
+
+#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);
+  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);
+
+ protected:
+  // Creates and destroys P2PTransportChannel.
+  virtual TransportChannelImpl* CreateTransportChannel(const std::string& name, const std::string &session_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);
+};
+
+}  // namespace cricket
+
+#endif  // _CRICKET_P2P_BASE_P2PTRANSPORT_H_
diff --git a/talk/p2p/base/p2ptransportchannel.cc b/talk/p2p/base/p2ptransportchannel.cc
new file mode 100755
index 0000000..717ae70
--- /dev/null
+++ b/talk/p2p/base/p2ptransportchannel.cc
@@ -0,0 +1,911 @@
+/*
+ * 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.
+ */
+
+#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"
+
+namespace {
+
+// messages for queuing up work for ourselves
+const uint32 MSG_SORT = 1;
+const uint32 MSG_PING = 2;
+const uint32 MSG_ALLOCATE = 3;
+
+// When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
+// for pinging.  When the socket is writable, we will use only 1 Kbps because
+// we don't want to degrade the quality on a modem.  These numbers should work
+// 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
+
+// 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
+
+// The minimum improvement in MOS 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
+
+// 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
+
+cricket::Port::CandidateOrigin GetOrigin(cricket::Port* port,
+                                         cricket::Port* origin_port) {
+  if (!origin_port)
+    return cricket::Port::ORIGIN_MESSAGE;
+  else if (port == origin_port)
+    return cricket::Port::ORIGIN_THIS_PORT;
+  else
+    return cricket::Port::ORIGIN_OTHER_PORT;
+}
+
+// Compares two connections based only on static information about them.
+int CompareConnectionCandidates(cricket::Connection* a,
+                                cricket::Connection* b) {
+  // 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() 
+                * a->remote_candidate().preference();
+  double b_pref = b->local_candidate().preference() 
+                * b->remote_candidate().preference();
+
+  // Now check combined preferences. Lower values get sorted last.
+  if (a_pref > b_pref)
+    return 1;
+  if (a_pref < b_pref)
+    return -1;
+
+  return 0;
+}
+
+// Compare two connections based on their writability and static preferences.
+int CompareConnections(cricket::Connection *a, cricket::Connection *b) {
+  // Sort based on write-state.  Better states have lower values.
+  if (a->write_state() < b->write_state())
+    return 1;
+  if (a->write_state() > b->write_state())
+    return -1;
+
+  // Compare the candidate information.
+  return CompareConnectionCandidates(a, b);
+}
+
+// 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, 
+                  const cricket::Connection *cb) {
+    cricket::Connection* a = const_cast<cricket::Connection*>(ca);
+    cricket::Connection* b = const_cast<cricket::Connection*>(cb);
+
+    // Compare first on writability and static preferences.
+    int cmp = CompareConnections(a, b);
+    if (cmp > 0)
+      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 
+    // data? It would help rendezvous on the connection that is also receiving
+    // packets.
+    //
+    // TODO: Yes we should definitely do this.  The TCP protocol gains
+    // efficiency by being used bidirectionally, as opposed to two separate
+    // unidirectional streams.  This test should probably occur before
+    // comparison of local prefs (assuming combined prefs are the same).  We
+    // need to be careful though, not to bounce back and forth with both sides
+    // trying to rendevous with the other.
+  }
+};
+
+// Determines whether we should switch between two connections, based first on
+// static preferences and then (if those are equal) on latency estimates.
+bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) {
+  if (a_conn == b_conn)
+    return false;
+
+  if ((a_conn == NULL) || (b_conn == NULL))  // don't think the latter should happen
+    return true;
+
+  int prefs_cmp = CompareConnections(a_conn, b_conn);
+  if (prefs_cmp < 0)
+    return true;
+  if (prefs_cmp > 0)
+    return false;
+
+  return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
+}
+
+}  // unnamed namespace
+
+namespace cricket {
+
+P2PTransportChannel::P2PTransportChannel(const std::string &name,
+					 const std::string &session_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) {
+}
+
+P2PTransportChannel::~P2PTransportChannel() {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  for (uint32 i = 0; i < allocator_sessions_.size(); ++i)
+    delete allocator_sessions_[i];
+}
+
+// Add the allocator session to our list so that we know which sessions
+// are still active.
+void P2PTransportChannel::AddAllocatorSession(PortAllocatorSession* session) {
+  session->set_generation(static_cast<uint32>(allocator_sessions_.size()));
+  allocator_sessions_.push_back(session);
+
+  // We now only want to apply new candidates that we receive to the ports
+  // created by this new session because these are replacing those of the
+  // previous sessions.
+  ports_.clear();
+
+  session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady);
+  session->SignalCandidatesReady.connect(
+      this, &P2PTransportChannel::OnCandidatesReady);
+  session->GetInitialPorts();
+  if (pinging_started_)
+    session->StartGetAllPorts();
+}
+
+// Go into the state of processing candidates, and running in general
+void P2PTransportChannel::Connect() {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  // Kick off an allocator session
+  OnAllocate();
+
+  // Start pinging as the ports come in.
+  thread()->Post(this, MSG_PING);
+}
+
+// Reset the socket, clear up any previous allocations and start over
+void P2PTransportChannel::Reset() {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  // Get rid of all the old allocators.  This should clean up everything.
+  for (uint32 i = 0; i < allocator_sessions_.size(); ++i)
+    delete allocator_sessions_[i];
+
+  allocator_sessions_.clear();
+  ports_.clear();
+  connections_.clear();
+  best_connection_ = NULL;
+
+  // Forget about all of the candidates we got before.
+  remote_candidates_.clear();
+
+  // Revert to the initial state.
+  set_readable(false);
+  set_writable(false);
+
+  // Reinitialize the rest of our state.
+  waiting_for_signaling_ = false;
+  pinging_started_ = false;
+  sort_dirty_ = false;
+  was_writable_ = false;
+  was_timed_out_ = true;
+
+  // If we allocated before, start a new one now.
+  if (transport_->connect_requested())
+    OnAllocate();
+
+  // Start pinging as the ports come in.
+  thread()->Clear(this);
+  thread()->Post(this, MSG_PING);
+}
+
+// A new port is available, attempt to make connections for it
+void P2PTransportChannel::OnPortReady(PortAllocatorSession *session,
+                                      Port* port) {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  // Set in-effect options on the new port
+  for (OptionMap::const_iterator it = options_.begin();
+       it != options_.end();
+       ++it) {
+    int val = port->SetOption(it->first, it->second);
+    if (val < 0) {
+      LOG_J(LS_WARNING, port) << "SetOption(" << it->first
+                              << ", " << it->second
+                              << ") failed: " << port->GetError();
+    }
+  }
+
+  // Remember the ports and candidates, and signal that candidates are ready.
+  // The session will handle this, and send an initiate/accept/modify message
+  // if one is pending.
+
+  ports_.push_back(port);
+  port->SignalUnknownAddress.connect(
+      this, &P2PTransportChannel::OnUnknownAddress);
+  port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed);
+
+  // Attempt to create a connection from this new port to all of the remote
+  // candidates that we were given so far.
+
+  std::vector<RemoteCandidate>::iterator iter;
+  for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); 
+       ++iter)
+    CreateConnection(port, *iter, iter->origin_port(), false);
+
+  SortConnections();
+}
+
+// A new candidate is available, let listeners know
+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);
+  }
+}
+
+// Handle stun packets                                  
+void P2PTransportChannel::OnUnknownAddress(
+    Port *port, const talk_base::SocketAddress &address, StunMessage *stun_msg,
+    const std::string &remote_username) {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  // Port has received a valid stun packet from an address that no Connection
+  // is currently available for. See if the remote user name is in the remote
+  // candidate list. If it isn't return error to the stun request.
+
+  const Candidate *candidate = NULL;
+  std::vector<RemoteCandidate>::iterator it;
+  for (it = remote_candidates_.begin(); it != remote_candidates_.end(); ++it) {
+    if ((*it).username() == remote_username) {
+      candidate = &(*it);
+      break;
+    }
+  }
+  if (candidate == NULL) {
+    // Don't know about this username, the request is bogus
+    // 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, 
+        STUN_ERROR_STALE_CREDENTIALS, STUN_ERROR_REASON_STALE_CREDENTIALS);
+    delete stun_msg;
+    return;
+  }
+
+  // Check for connectivity to this address. Create connections
+  // to this address across all local ports. First, add this as a new remote
+  // address
+
+  Candidate new_remote_candidate = *candidate;
+  new_remote_candidate.set_address(address);
+  //new_remote_candidate.set_protocol(port->protocol());
+
+  // This remote username exists. Now create connections using this candidate,
+  // and resort
+
+  if (CreateConnections(new_remote_candidate, port, true)) {
+    // Send the pinger a successful stun response.
+    port->SendBindingResponse(stun_msg, address);
+
+    // Update the list of connections since we just added another.  We do this
+    // after sending the response since it could (in principle) delete the
+    // connection in question.
+    SortConnections();
+  } else {
+    // Hopefully this won't occur, because changing a destination address
+    // shouldn't cause a new connection to fail
+    ASSERT(false);
+    port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR,
+        STUN_ERROR_REASON_SERVER_ERROR);
+  }
+
+  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) {
+  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);
+
+  // 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
+// the origin port.
+bool P2PTransportChannel::CreateConnections(const Candidate &remote_candidate,
+                                            Port* origin_port,
+                                            bool readable) {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  // Add a new connection for this candidate to every port that allows such a
+  // connection (i.e., if they have compatible protocols) and that does not
+  // already have a connection to an equivalent candidate.  We must be careful
+  // to make sure that the origin port is included, even if it was pruned,
+  // since that may be the only port that can create this connection.
+
+  bool created = false;
+
+  std::vector<Port *>::reverse_iterator it;
+  for (it = ports_.rbegin(); it != ports_.rend(); ++it) {
+    if (CreateConnection(*it, remote_candidate, origin_port, readable)) {
+      if (*it == origin_port)
+        created = true;
+    }
+  }
+
+  if ((origin_port != NULL) &&
+      find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) {
+    if (CreateConnection(origin_port, remote_candidate, origin_port, readable))
+      created = true;
+  }
+
+  // Remember this remote candidate so that we can add it to future ports.
+  RememberRemoteCandidate(remote_candidate, origin_port);
+
+  return created;
+}
+
+// Setup a connection object for the local and remote candidate combination.
+// And then listen to connection object for changes.
+bool P2PTransportChannel::CreateConnection(Port* port,
+                                           const Candidate& remote_candidate,
+                                           Port* origin_port,
+                                           bool readable) {
+  // Look for an existing connection with this remote address.  If one is not
+  // found, then we can create a new connection for this address.
+  Connection* connection = port->GetConnection(remote_candidate.address());
+  if (connection != NULL) {
+    // It is not legal to try to change any of the parameters of an existing
+    // connection; however, the other side can send a duplicate candidate.
+    if (!remote_candidate.IsEquivalent(connection->remote_candidate())) {
+      LOG(INFO) << "Attempt to change a remote candidate";
+      return false;
+    }
+  } else {
+    Port::CandidateOrigin origin = GetOrigin(port, origin_port);
+    connection = port->CreateConnection(remote_candidate, origin);
+    if (!connection)
+      return false;
+
+    connections_.push_back(connection);
+    connection->SignalReadPacket.connect(
+        this, &P2PTransportChannel::OnReadPacket);
+    connection->SignalStateChange.connect(
+        this, &P2PTransportChannel::OnConnectionStateChange);
+    connection->SignalDestroyed.connect(
+        this, &P2PTransportChannel::OnConnectionDestroyed);
+  }
+
+  // If we are readable, it is because we are creating this in response to a
+  // ping from the other side.  This will cause the state to become readable.
+  if (readable)
+    connection->ReceivedPing();
+
+  return true;
+}
+
+// Maintain our remote candidate list, adding this new remote one.
+void P2PTransportChannel::RememberRemoteCandidate(
+    const Candidate& remote_candidate, Port* origin_port) {
+  // Remove any candidates whose generation is older than this one.  The
+  // presence of a new generation indicates that the old ones are not useful.
+  uint32 i = 0;
+  while (i < remote_candidates_.size()) {
+    if (remote_candidates_[i].generation() < remote_candidate.generation()) {
+      LOG(INFO) << "Pruning candidate from old generation: "
+                << remote_candidates_[i].address().ToString();
+      remote_candidates_.erase(remote_candidates_.begin() + i);
+    } else {
+      i += 1;
+    }
+  }
+
+  // Make sure this candidate is not a duplicate.
+  for (uint32 i = 0; i < remote_candidates_.size(); ++i) {
+    if (remote_candidates_[i].IsEquivalent(remote_candidate)) {
+      LOG(INFO) << "Duplicate candidate: "
+                << remote_candidate.address().ToString();
+      return;
+    }
+  }
+
+  // Try this candidate for all future ports.
+  remote_candidates_.push_back(RemoteCandidate(remote_candidate, origin_port));
+
+  // We have some candidates from the other side, we are now serious about
+  // this connection.  Let's do the StartGetAllPorts thing.
+  if (!pinging_started_) {
+    pinging_started_ = true;
+    for (size_t i = 0; i < allocator_sessions_.size(); ++i) {
+      if (!allocator_sessions_[i]->IsGettingAllPorts())
+        allocator_sessions_[i]->StartGetAllPorts();
+    }
+  }
+}
+
+// Send data to the other side, using our best connection
+int P2PTransportChannel::SendPacket(const char *data, size_t len) {
+  // This can get called on any thread that is convenient to write from!
+  if (best_connection_ == NULL) {
+    error_ = EWOULDBLOCK;
+    return SOCKET_ERROR;
+  }
+  int sent = best_connection_->Send(data, len);
+  if (sent <= 0) {
+    ASSERT(sent < 0);
+    error_ = best_connection_->GetError();
+  }
+  return sent;
+}
+
+// Monitor connection states
+void P2PTransportChannel::UpdateConnectionStates() {
+  uint32 now = talk_base::Time();
+
+  // We need to copy the list of connections since some may delete themselves
+  // when we call UpdateState.
+  for (uint32 i = 0; i < connections_.size(); ++i)
+    connections_[i]->UpdateState(now);
+}
+
+// Prepare for best candidate sorting
+void P2PTransportChannel::RequestSort() {
+  if (!sort_dirty_) {
+    worker_thread_->Post(this, MSG_SORT);
+    sort_dirty_ = true;
+  }
+}
+
+// Sort the available connections to find the best one.  We also monitor
+// 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());
+
+  // Make sure the connection states are up-to-date since this affects how they
+  // will be sorted.
+  UpdateConnectionStates();
+
+  // Any changes after this point will require a re-sort.
+  sort_dirty_ = false;
+
+  // Get a list of the networks that we are using.
+  std::set<talk_base::Network*> networks;
+  for (uint32 i = 0; i < connections_.size(); ++i)
+    networks.insert(connections_[i]->port()->network());
+
+  // Find the best alternative connection by sorting.  It is important to note
+  // that amongst equal preference, writable connections, this will choose the
+  // one whose estimated latency is lowest.  So it is the only one that we
+  // need to consider switching to.
+
+  ConnectionCompare cmp;
+  std::stable_sort(connections_.begin(), connections_.end(), cmp);
+  Connection* top_connection = NULL;
+  if (connections_.size() > 0)
+    top_connection = connections_[0];
+
+  // If necessary, switch to the new choice.
+  if (ShouldSwitch(best_connection_, top_connection))
+    SwitchBestConnectionTo(top_connection);
+
+  // We can prune any connection for which there is a writable connection on
+  // the same network with better or equal prefences.  We leave those with
+  // better preference just in case they become writable later (at which point,
+  // we would prune out the current best connection).  We leave connections on
+  // other networks because they may not be using the same resources and they
+  // may represent very distinct paths over which we can switch.
+  std::set<talk_base::Network*>::iterator network;
+  for (network = networks.begin(); network != networks.end(); ++network) {
+    Connection* primier = GetBestConnectionOnNetwork(*network);
+    if (!primier || (primier->write_state() != Connection::STATE_WRITABLE))
+      continue;
+
+    for (uint32 i = 0; i < connections_.size(); ++i) {
+      if ((connections_[i] != primier) &&
+          (connections_[i]->port()->network() == *network) &&
+          (CompareConnectionCandidates(primier, connections_[i]) >= 0)) {
+        connections_[i]->Prune();
+      }
+    }
+  }
+
+  // Count the number of connections in the various states.
+
+  int writable = 0;
+  int write_connect = 0;
+  int write_timeout = 0;
+
+  for (uint32 i = 0; i < connections_.size(); ++i) {
+    switch (connections_[i]->write_state()) {
+    case Connection::STATE_WRITABLE:
+      ++writable;
+      break;
+    case Connection::STATE_WRITE_CONNECT:
+      ++write_connect;
+      break;
+    case Connection::STATE_WRITE_TIMEOUT:
+      ++write_timeout;
+      break;
+    default:
+      ASSERT(false);
+    }
+  }
+
+  if (writable > 0) {
+    HandleWritable();
+  } else if (write_connect > 0) {
+    HandleNotWritable();
+  } else {
+    HandleAllTimedOut();
+  }
+
+  // Update the state of this channel.  This method is called whenever the
+  // state of any connection changes, so this is a good place to do this.
+  UpdateChannelState();
+
+  // Notify of connection state change
+  SignalConnectionMonitor(this);
+}
+
+// Track the best connection, and let listeners know
+void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
+  // Note: the previous best_connection_ may be destroyed by now, so don't
+  // use it.
+  best_connection_ = conn;
+  if (best_connection_) {
+    LOG_J(LS_VERBOSE, this) << "New best connection: " << conn->ToString();
+    SignalRouteChange(this, best_connection_->remote_candidate().address());
+  }
+}
+
+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);
+  ASSERT(writable == this->writable());
+
+  bool readable = false;
+  for (uint32 i = 0; i < connections_.size(); ++i) {
+    if (connections_[i]->read_state() == Connection::STATE_READABLE)
+      readable = true;
+  }
+  set_readable(readable);
+}
+
+// We checked the status of our connections and we had at least one that
+// was writable, go into the writable state.
+void P2PTransportChannel::HandleWritable() {
+  //
+  // One or more connections writable!
+  //
+  if (!writable()) {
+    for (uint32 i = 0; i < allocator_sessions_.size(); ++i) {
+      if (allocator_sessions_[i]->IsGettingAllPorts()) {
+        allocator_sessions_[i]->StopGetAllPorts();
+      }
+    }
+
+    // Stop further allocations.
+    thread()->Clear(this, MSG_ALLOCATE);
+  }
+
+  // We're writable, obviously we aren't timed out
+  was_writable_ = true;
+  was_timed_out_ = false;
+  set_writable(true);
+}
+
+// We checked the status of our connections and we didn't have any that
+// were writable, go into the connecting state (kick off a new allocator
+// session).
+void P2PTransportChannel::HandleNotWritable() {
+  //
+  // No connections are writable but not timed out!
+  //
+  if (was_writable_) {
+    // If we were writable, let's kick off an allocator session immediately
+    was_writable_ = false;
+    OnAllocate();
+  }
+
+  // We were connecting, obviously not ALL timed out.
+  was_timed_out_ = false;
+  set_writable(false);
+}
+
+// We checked the status of our connections and not only weren't they writable
+// but they were also timed out, we really need a new allocator.
+void P2PTransportChannel::HandleAllTimedOut() {
+  //
+  // No connections... all are timed out!
+  //
+  if (!was_timed_out_) {
+    // 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();
+  }
+
+  // NOTE: we start was_timed_out_ in the true state so that we don't get
+  // another allocator created WHILE we are in the process of building up
+  // our first allocator.
+  was_timed_out_ = true;
+  was_writable_ = false;
+  set_writable(false);
+}
+
+// If we have a best connection, return it, otherwise return top one in the
+// list (later we will mark it best).
+Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
+    talk_base::Network* network) {
+  // If the best connection is on this network, then it wins.
+  if (best_connection_ && (best_connection_->port()->network() == network))
+    return best_connection_;
+
+  // Otherwise, we return the top-most in sorted order.
+  for (uint32 i = 0; i < connections_.size(); ++i) {
+    if (connections_[i]->port()->network() == network)
+      return connections_[i];
+  }
+
+  return NULL;
+}
+
+// Handle any queued up requests
+void P2PTransportChannel::OnMessage(talk_base::Message *pmsg) {
+  if (pmsg->message_id == MSG_SORT)
+    OnSort();
+  else if (pmsg->message_id == MSG_PING)
+    OnPing();
+  else if (pmsg->message_id == MSG_ALLOCATE)
+    OnAllocate();
+  else
+    ASSERT(false);
+}
+
+// Handle queued up sort request
+void P2PTransportChannel::OnSort() {
+  // Resort the connections based on the new statistics.
+  SortConnections();
+}
+
+// Handle queued up ping request
+void P2PTransportChannel::OnPing() {
+  // Make sure the states of the connections are up-to-date (since this affects
+  // which ones are pingable).
+  UpdateConnectionStates();
+
+  // Find the oldest pingable connection and have it do a ping.
+  Connection* conn = FindNextPingableConnection();
+  if (conn)
+    conn->Ping(talk_base::Time());
+
+  // Post ourselves a message to perform the next ping.
+  uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY;
+  thread()->PostDelayed(delay, this, MSG_PING);
+}
+
+// Is the connection in a state for us to even consider pinging the other side?
+bool P2PTransportChannel::IsPingable(Connection* conn) {
+  // An unconnected connection cannot be written to at all, so pinging is out
+  // of the question.
+  if (!conn->connected())
+    return false;
+
+  if (writable()) {
+    // If we are writable, then we only want to ping connections that could be
+    // better than this one, i.e., the ones that were not pruned.
+    return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT);
+  } else {
+    // If we are not writable, then we need to try everything that might work.
+    // This includes both connections that do not have write timeout as well as
+    // ones that do not have read timeout.  A connection could be readable but
+    // be in write-timeout if we pruned it before.  Since the other side is
+    // still pinging it, it very well might still work.
+    return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) ||
+           (conn->read_state() != Connection::STATE_READ_TIMEOUT);
+  }
+}
+
+// Returns the next pingable connection to ping.  This will be the oldest
+// pingable connection unless we have a writable connection that is past the
+// maximum acceptable ping delay.
+Connection* P2PTransportChannel::FindNextPingableConnection() {
+  uint32 now = talk_base::Time();
+  if (best_connection_ &&
+      (best_connection_->write_state() == Connection::STATE_WRITABLE) &&
+      (best_connection_->last_ping_sent() 
+       + MAX_CURRENT_WRITABLE_DELAY <= now)) {
+    return best_connection_;
+  }
+
+  Connection* oldest_conn = NULL;
+  uint32 oldest_time = 0xFFFFFFFF;
+  for (uint32 i = 0; i < connections_.size(); ++i) {
+    if (IsPingable(connections_[i])) {
+      if (connections_[i]->last_ping_sent() < oldest_time) {
+        oldest_time = connections_[i]->last_ping_sent();
+        oldest_conn = connections_[i];
+      }
+    }
+  }
+  return oldest_conn;
+}
+
+// return the number of "pingable" connections
+uint32 P2PTransportChannel::NumPingableConnections() {
+  uint32 count = 0;
+  for (uint32 i = 0; i < connections_.size(); ++i) {
+    if (IsPingable(connections_[i]))
+      count += 1;
+  }
+  return count;
+}
+
+// When a connection's state changes, we need to figure out who to use as
+// the best connection again.  It could have become usable, or become unusable.
+void P2PTransportChannel::OnConnectionStateChange(Connection *connection) {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  // We have to unroll the stack before doing this because we may be changing
+  // the state of connections while sorting.
+  RequestSort();
+}
+
+// When a connection is removed, edit it out, and then update our best
+// connection.
+void P2PTransportChannel::OnConnectionDestroyed(Connection *connection) {
+  ASSERT(worker_thread_ == talk_base::Thread::Current());
+
+  // Note: the previous best_connection_ may be destroyed by now, so don't
+  // use it.
+
+  // Remove this connection from the list.
+  std::vector<Connection*>::iterator iter =
+      find(connections_.begin(), connections_.end(), connection);
+  ASSERT(iter != connections_.end());
+  connections_.erase(iter);
+
+  LOG_J(LS_INFO, this) << "Removed connection ("
+    << static_cast<int>(connections_.size()) << " remaining)";
+
+  // If this is currently the best connection, then we need to pick a new one.
+  // The call to SortConnections will pick a new one.  It looks at the current
+  // best connection in order to avoid switching between fairly similar ones.
+  // Since this connection is no longer an option, we can just set best to NULL
+  // and re-choose a best assuming that there was no best connection.
+  if (best_connection_ == connection) {
+    SwitchBestConnectionTo(NULL);
+    RequestSort();
+  }
+}
+
+// When a port is destroyed remove it from our list of ports to use for
+// connection attempts.
+void P2PTransportChannel::OnPortDestroyed(Port* port) {
+  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);
+  if (iter != ports_.end())
+    ports_.erase(iter);
+
+  LOG(INFO) << "Removed port from p2p socket: "
+            << static_cast<int>(ports_.size()) << " remaining";
+}
+
+// We data is available, let listeners know
+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
+
+  SignalReadPacket(this, data, len);
+}
+
+// Set options on ourselves is simply setting options on all of our available
+// port objects.
+int P2PTransportChannel::SetOption(talk_base::Socket::Option opt, int value) {
+  OptionMap::iterator it = options_.find(opt);
+  if (it == options_.end()) {
+    options_.insert(std::make_pair(opt, value));
+  } else if (it->second == value) {
+    return 0;
+  } else {
+    it->second = value;
+  }
+
+  for (uint32 i = 0; i < ports_.size(); ++i) {
+    int val = ports_[i]->SetOption(opt, value);
+    if (val < 0) {
+      // Because this also occurs deferred, probably no point in reporting an
+      // error
+      LOG(WARNING) << "SetOption(" << opt << ", " << value << ") failed: "
+                   << ports_[i]->GetError();
+    }
+  }
+  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()));
+    thread()->PostDelayed(kAllocatePeriod, this, MSG_ALLOCATE);
+  }
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/p2ptransportchannel.h b/talk/p2p/base/p2ptransportchannel.h
new file mode 100755
index 0000000..bea1537
--- /dev/null
+++ b/talk/p2p/base/p2ptransportchannel.h
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+// P2PTransportChannel wraps up the state management of the connection between
+// two P2P clients.  Clients have candidate ports for connecting, and
+// connections which are combinations of candidates from each end (Alice and
+// Bob each have candidates, one candidate from Alice and one candidate from
+// Bob are used to make a connection, repeat to make many connections).
+//
+// 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_
+
+#include <vector>
+#include <string>
+#include "talk/base/sigslot.h"
+#include "talk/p2p/base/candidate.h"
+#include "talk/p2p/base/port.h"
+#include "talk/p2p/base/portallocator.h"
+#include "talk/p2p/base/transport.h"
+#include "talk/p2p/base/transportchannelimpl.h"
+#include "talk/p2p/base/p2ptransport.h"
+
+namespace cricket {
+
+// Adds the port on which the candidate originated.
+class RemoteCandidate : public Candidate {
+ public:
+  RemoteCandidate(const Candidate& c, Port* origin_port)
+    : Candidate(c), origin_port_(origin_port) {}
+
+  Port* origin_port() { return origin_port_; }
+
+ private:
+  Port* origin_port_;
+};
+
+// P2PTransportChannel manages the candidates and connection process to keep
+// two P2P clients connected to each other.
+class P2PTransportChannel : public TransportChannelImpl, 
+    public talk_base::MessageHandler {
+ public:
+  P2PTransportChannel(const std::string &name,
+		      const std::string &session_type,
+                      P2PTransport* transport,
+                      PortAllocator *allocator);
+  virtual ~P2PTransportChannel();
+
+  // From TransportChannelImpl:
+  virtual Transport* GetTransport() { return transport_; }
+  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_; }
+
+  // These are used by the connection monitor.
+  sigslot::signal1<P2PTransportChannel*> SignalConnectionMonitor;
+  const std::vector<Connection *>& connections() const { return connections_; }
+  Connection* best_connection() const { return best_connection_; }
+
+  // Handler for internal messages.
+  virtual void OnMessage(talk_base::Message *pmsg);
+
+ private:
+  void UpdateConnectionStates();
+  void RequestSort();
+  void SortConnections();
+  void SwitchBestConnectionTo(Connection* conn);
+  void UpdateChannelState();
+  void HandleWritable();
+  void HandleNotWritable();
+  void HandleAllTimedOut();
+  Connection* GetBestConnectionOnNetwork(talk_base::Network* network);
+  bool CreateConnections(const Candidate &remote_candidate, Port* origin_port, 
+                         bool readable);
+  bool CreateConnection(Port* port, const Candidate& remote_candidate, 
+                        Port* origin_port, bool readable);
+  void RememberRemoteCandidate(const Candidate& remote_candidate, 
+                               Port* origin_port);
+  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, 
+                         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();
+  bool IsPingable(Connection* conn);
+  Connection* FindNextPingableConnection();
+  uint32 NumPingableConnections();
+  PortAllocatorSession* allocator_session() {
+    return allocator_sessions_.back();
+  }
+  void AddAllocatorSession(PortAllocatorSession* session);
+
+  talk_base::Thread* thread() const { return worker_thread_; }
+
+  P2PTransport* transport_;
+  PortAllocator *allocator_;
+  talk_base::Thread *worker_thread_;
+  bool waiting_for_signaling_;
+  int error_;
+  std::vector<PortAllocatorSession*> allocator_sessions_;
+  std::vector<Port *> ports_;
+  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
+  bool was_writable_;
+  bool was_timed_out_;
+  typedef std::map<talk_base::Socket::Option, int> OptionMap;
+  OptionMap options_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(P2PTransportChannel);
+};
+
+} // namespace cricket
+
+#endif // _CRICKET_P2P_BASE_P2PTRANSPORTCHANNEL_H_
diff --git a/talk/p2p/base/port.cc b/talk/p2p/base/port.cc
new file mode 100755
index 0000000..b5395df
--- /dev/null
+++ b/talk/p2p/base/port.cc
@@ -0,0 +1,926 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#include <errno.h>
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "talk/base/asyncudpsocket.h"
+#include "talk/base/asynctcpsocket.h"
+#include "talk/base/helpers.h"
+#include "talk/base/logging.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/socketadapters.h"
+#include "talk/p2p/base/common.h"
+#include "talk/p2p/base/port.h"
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+namespace std {
+  using ::memcmp;
+}
+#endif
+
+namespace {
+
+// The length of time we wait before timing out readability on a connection.
+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
+
+// The length of time we wait before we become unwritable.
+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
+
+// Determines whether we have seen at least the given maximum number of
+// pings fail to have a response.
+inline bool TooManyFailures(
+    const std::vector<uint32>& pings_since_last_response,
+    uint32 maximum_failures,
+    uint32 rtt_estimate,
+    uint32 now) {
+
+  // If we haven't sent that many pings, then we can't have failed that many.
+  if (pings_since_last_response.size() < maximum_failures)
+    return false;
+
+  // Check if the window in which we would expect a response to the ping has
+  // already elapsed.
+  return pings_since_last_response[maximum_failures - 1] + rtt_estimate < now;
+}
+
+// Determines whether we have gone too long without seeing any response.
+inline bool TooLongWithoutResponse(
+    const std::vector<uint32>& pings_since_last_response,
+    uint32 maximum_time,
+    uint32 now) {
+
+  if (pings_since_last_response.size() == 0)
+    return false;
+
+  return pings_since_last_response[0] + maximum_time < now;
+}
+
+// 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
+
+// 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));
+}
+
+// Weighting of the old rtt value to new data.
+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 uint32 MSG_CHECKTIMEOUT = 1;
+const uint32 MSG_DELETE = 1;
+
+}
+
+namespace cricket {
+
+static const char * const PROTO_NAMES[PROTO_LAST+1] = { "udp", "tcp", "ssltcp" };
+
+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) {
+    if (strcmp(PROTO_NAMES[i], value) == 0) {
+      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, 
+           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));
+}
+
+Port::~Port() {
+  // Delete all of the remaining connections.  We copy the list up front
+  // because each deletion will cause it to be modified.
+
+  std::vector<Connection*> list;
+
+  AddressMap::iterator iter = connections_.begin();
+  while (iter != connections_.end()) {
+    list.push_back(iter->second);
+    ++iter;
+  }
+
+  for (uint32 i = 0; i < list.size(); i++)
+    delete list[i];
+}
+
+Connection* Port::GetConnection(const talk_base::SocketAddress& remote_addr) {
+  AddressMap::const_iterator iter = connections_.find(remote_addr);
+  if (iter != connections_.end())
+    return iter->second;
+  else
+    return NULL;
+}
+
+void Port::AddAddress(const talk_base::SocketAddress& address,
+                      const std::string& protocol,
+                      bool final) {
+  Candidate c;
+  c.set_name(name_);
+  c.set_type(type_);
+  c.set_protocol(protocol);
+  c.set_address(address);
+  c.set_preference(preference_);
+  c.set_username(username_frag_);
+  c.set_password(password_);
+  c.set_network_name(network_->name());
+  c.set_generation(generation_);
+  candidates_.push_back(c);
+
+  if (final)
+    SignalAddressReady(this);
+}
+
+void Port::AddConnection(Connection* conn) {
+  connections_[conn->remote_candidate().address()] = conn;
+  conn->SignalDestroyed.connect(this, &Port::OnConnectionDestroyed);
+  SignalConnectionCreated(this, conn);
+}
+
+void Port::OnReadPacket(
+    const char* data, size_t size, const talk_base::SocketAddress& addr) {
+  // If the user has enabled port packets, just hand this over.
+  if (enable_port_packets_) {
+    SignalReadPacket(this, data, size, addr);
+    return;
+  }
+
+  // If this is an authenticated STUN request, then signal unknown address and
+  // send back a proper binding response.
+  StunMessage* msg;
+  std::string remote_username;
+  if (!GetStunMessage(data, size, addr, msg, remote_username)) {
+    LOG_J(LS_ERROR, this) << "Received non-STUN packet from unknown address ("
+                          << addr.ToString() << ")";
+  } else if (!msg) {
+    // STUN message handled already
+  } else if (msg->type() == STUN_BINDING_REQUEST) {
+    SignalUnknownAddress(this, addr, msg, remote_username);
+  } else {
+    LOG_J(LS_ERROR, this) << "Received unexpected STUN message type ("
+                          << msg->type() << ") from unknown address ("
+                          << addr.ToString() << ")";
+    delete msg;
+  }
+}
+
+void Port::SendBindingRequest(Connection* conn) {
+
+  // Construct the request message.
+
+  StunMessage request;
+  request.SetType(STUN_BINDING_REQUEST);
+  request.SetTransactionID(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());
+  request.AddAttribute(username_attr);
+
+  // Send the request message.
+  // NOTE: If we wanted to, this is where we would add the HMAC.
+  talk_base::ByteBuffer buf;
+  request.Write(&buf);
+  SendTo(buf.Data(), buf.Length(), conn->remote_candidate().address(), false);
+}
+
+bool Port::GetStunMessage(const char* data, size_t size,
+                          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,
+  //       this probably isn't worth worrying about.
+
+  msg = 0;
+
+  // Parse the request message.  If the packet is not a complete and correct
+  // STUN message, then ignore it.
+  talk_base::scoped_ptr<StunMessage> stun_msg(new StunMessage());
+  talk_base::ByteBuffer buf(data, size);
+  if (!stun_msg->Read(&buf) || (buf.Length() > 0)) {
+    return false;
+  }
+
+  // The packet must include a username that either begins or ends with our
+  // fragment.  It should begin with our fragment if it is a request and it
+  // should end with our fragment if it is a response.
+  const StunByteStringAttribute* username_attr =
+      stun_msg->GetByteString(STUN_ATTR_USERNAME);
+
+  int remote_frag_len = (username_attr ? username_attr->length() : 0);
+  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)) {
+      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);
+      return true;
+    }
+
+    remote_username.assign(username_attr->bytes() + username_frag_.size(),
+      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";
+      // Do not send error response to a response
+      return true;
+    }
+
+    remote_username.assign(username_attr->bytes(),
+      username_attr->bytes() + remote_frag_len);
+
+    if (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE) {
+      if (const StunErrorCodeAttribute* error_code = stun_msg->GetErrorCode()) {
+        LOG_J(LS_ERROR, this) << "Received STUN binding error:"
+                              << " class=" << error_code->error_class()
+                              << " number=" << error_code->number()
+                              << " reason='" << error_code->reason() << "'";
+        // Return message to allow error-specific processing
+      } else {
+        LOG_J(LS_ERROR, this)
+          << "Received STUN error response with no error code";
+        // Drop corrupt message
+        return true;
+      }
+    }
+  } else {
+    LOG_J(LS_ERROR, this) << "Received STUN packet with invalid type ("
+                          << stun_msg->type() << ")";
+    return true;
+  }
+
+  // Return the STUN message found.
+  msg = stun_msg.release();
+  return true;
+}
+
+void Port::SendBindingResponse(
+    StunMessage* request, const talk_base::SocketAddress& addr) {
+
+  assert(request->type() == STUN_BINDING_REQUEST);
+
+  // Retrieve the username from the request.
+  const StunByteStringAttribute* username_attr =
+      request->GetByteString(STUN_ATTR_USERNAME);
+  assert(username_attr);
+
+  // Fill in the response message.
+
+  StunMessage response;
+  response.SetType(STUN_BINDING_RESPONSE);
+  response.SetTransactionID(request->transaction_id());
+
+  StunByteStringAttribute* username2_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  username2_attr->CopyBytes(username_attr->bytes(), username_attr->length());
+  response.AddAttribute(username2_attr);
+
+  StunAddressAttribute* addr_attr =
+      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  addr_attr->SetFamily(1);
+  addr_attr->SetPort(addr.port());
+  addr_attr->SetIP(addr.ip());
+  response.AddAttribute(addr_attr);
+
+  // Send the response message.
+  // NOTE: If we wanted to, this is where we would add the HMAC.
+  talk_base::ByteBuffer buf;
+  response.Write(&buf);
+  SendTo(buf.Data(), buf.Length(), addr, false);
+
+  // 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);
+  if (conn)
+    conn->ReceivedPing();
+}
+
+void Port::SendBindingErrorResponse(
+    StunMessage* request, const talk_base::SocketAddress& addr, int error_code,
+    const std::string& reason) {
+
+  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);
+
+  // Fill in the response message.
+
+  StunMessage response;
+  response.SetType(STUN_BINDING_ERROR_RESPONSE);
+  response.SetTransactionID(request->transaction_id());
+
+  StunByteStringAttribute* username2_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  username2_attr->CopyBytes(username_attr->bytes(), username_attr->length());
+  response.AddAttribute(username2_attr);
+
+  StunErrorCodeAttribute* error_attr = StunAttribute::CreateErrorCode();
+  error_attr->SetErrorCode(error_code);
+  error_attr->SetReason(reason);
+  response.AddAttribute(error_attr);
+
+  // Send the response message.
+  // NOTE: If we wanted to, this is where we would add the HMAC.
+  talk_base::ByteBuffer buf;
+  response.Write(&buf);
+  SendTo(buf.Data(), buf.Length(), addr, false);
+}
+
+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:
+      socket = new talk_base::AsyncSocksProxySocket(
+          socket, proxy().address, proxy().username, proxy().password);
+      break;
+    case talk_base::PROXY_HTTPS:
+    default:
+      socket = new talk_base::AsyncHttpsProxySocket(
+          socket, user_agent(), proxy().address, proxy().username, 
+          proxy().password);
+      break;
+    }
+    if (proto == PROTO_SSLTCP) {
+      socket = new talk_base::AsyncSSLSocket(socket);
+    }
+    return new talk_base::AsyncTCPSocket(socket);
+  } else {
+    LOG_J(LS_INFO, this) << "Unknown protocol (" << proto << ")";
+    return 0;
+  }
+}
+
+void Port::OnMessage(talk_base::Message *pmsg) {
+  assert(pmsg->message_id == MSG_CHECKTIMEOUT);
+  assert(lifetime_ == LT_PRETIMEOUT);
+  lifetime_ = LT_POSTTIMEOUT;
+  CheckTimeout();
+}
+
+std::string Port::ToString() const {
+  std::stringstream ss;
+  ss << "Port[" << name_ << ":" << type_ << ":" << network_->ToString() << "]";
+  return ss.str();
+}
+
+void Port::EnablePortPackets() {
+  enable_port_packets_ = true;
+}
+
+void Port::Start() {
+  // The port sticks around for a minimum lifetime, after which
+  // we destroy it when it drops to zero connections.
+  if (lifetime_ == LT_PRESTART) {
+    lifetime_ = LT_PRETIMEOUT;
+    thread_->PostDelayed(kPortTimeoutDelay, this, MSG_CHECKTIMEOUT);
+  } else {
+    LOG_J(LS_WARNING, this) << "Port restart attempted";
+  }
+}
+
+void Port::OnConnectionDestroyed(Connection* conn) {
+  AddressMap::iterator iter = connections_.find(conn->remote_candidate().address());
+  assert(iter != connections_.end());
+  connections_.erase(iter);
+
+  CheckTimeout();
+}
+
+void Port::Destroy() {
+  assert(connections_.empty());
+  LOG_J(LS_INFO, this) << "Port deleted";
+  SignalDestroyed(this);
+  delete this;
+}
+
+void Port::CheckTimeout() {
+  // If this port has no connections, then there's no reason to keep it around.
+  // When the connections time out (both read and write), they will delete
+  // themselves, so if we have any connections, they are either readable or
+  // writable (or still connecting).
+  if ((lifetime_ == LT_POSTTIMEOUT) && connections_.empty()) {
+    Destroy();
+  }
+}
+
+// A ConnectionRequest is a simple STUN ping used to determine writability.
+class ConnectionRequest : public StunRequest {
+public:
+  ConnectionRequest(Connection* connection) : connection_(connection) {
+  }
+
+  virtual ~ConnectionRequest() {
+  }
+
+  virtual void Prepare(StunMessage* request) {
+    request->SetType(STUN_BINDING_REQUEST);
+    StunByteStringAttribute* username_attr =
+        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());
+    request->AddAttribute(username_attr);
+  }
+
+  virtual void OnResponse(StunMessage* response) {
+    connection_->OnConnectionRequestResponse(response, Elapsed());
+  }
+
+  virtual void OnErrorResponse(StunMessage* response) {
+    connection_->OnConnectionRequestErrorResponse(response, Elapsed());
+  }
+
+  virtual void OnTimeout() {
+  }
+
+  virtual int GetNextDelay() {
+    // Each request is sent only once.  After a single delay , the request will
+    // time out.
+    timeout_ = true;
+    return CONNECTION_RESPONSE_TIMEOUT;
+  }
+
+private:
+  Connection* connection_;
+};
+
+//
+// Connection
+//
+
+Connection::Connection(Port* port, size_t index, const Candidate& remote_candidate)
+  : requests_(port->thread()), 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) {
+
+  // Wire up to send stun packets
+  requests_.SignalSendPacket.connect(this, &Connection::OnSendStunPacket);
+}
+
+Connection::~Connection() {
+}
+
+const Candidate& Connection::local_candidate() const {
+  if (local_candidate_index_ < port_->candidates().size())
+    return port_->candidates()[local_candidate_index_];
+  assert(false);
+  static Candidate foo;
+  return foo;
+}
+
+void Connection::set_read_state(ReadState value) {
+  ReadState old_value = read_state_;
+  read_state_ = value;
+  if (value != old_value) {
+    LOG_J(LS_VERBOSE, this) << "set_read_state";
+    SignalStateChange(this);
+    CheckTimeout();
+  }
+}
+
+void Connection::set_write_state(WriteState value) {
+  WriteState old_value = write_state_;
+  write_state_ = value;
+  if (value != old_value) {
+    LOG_J(LS_VERBOSE, this) << "set_write_state";
+    SignalStateChange(this);
+    CheckTimeout();
+  }
+}
+
+void Connection::set_connected(bool value) {
+  bool old_value = connected_;
+  connected_ = value;
+  if (value != old_value) {
+    LOG_J(LS_VERBOSE, this) << "set_connected";
+  }
+}
+
+void Connection::OnSendStunPacket(
+    const void* data, size_t size, StunRequest* req) {
+  port_->SendTo(data, size, remote_candidate_.address(), false);
+}
+
+void Connection::OnReadPacket(const char* data, size_t size) {
+  StunMessage* msg;
+  std::string remote_username;
+  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;
+      SignalReadPacket(this, data, size);
+
+      // If timed out sending writability checks, start up again
+      if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT))
+        set_write_state(STATE_WRITE_CONNECT);
+    } else {
+      // Not readable means the remote address hasn't send a valid
+      // binding request yet.
+
+      LOG_J(LS_WARNING, this)
+        << "Received non-STUN packet from an unreadable connection.";
+    }
+  } else if (!msg) {
+    // The packet was STUN, but was already handled
+  } else if (remote_username != remote_candidate_.username()) {
+    // Not destined this connection
+    LOG_J(LS_ERROR, this) << "Received STUN packet on wrong address.";
+    if (msg->type() == STUN_BINDING_REQUEST) {
+      port_->SendBindingErrorResponse(msg, addr, STUN_ERROR_BAD_REQUEST,
+                                      STUN_ERROR_REASON_BAD_REQUEST);
+    }
+    delete msg;
+  } else {
+    // The packet is STUN, with the current username
+    // If this is a STUN request, then update the readable bit and respond.
+    // If this is a STUN response, then update the writable bit.
+
+    switch (msg->type()) {
+    case STUN_BINDING_REQUEST:
+      // Incoming, validated stun request from remote peer.
+      // This call will also set the connection readable.
+
+      port_->SendBindingResponse(msg, addr);
+
+      // If timed out sending writability checks, start up again
+      if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT))
+        set_write_state(STATE_WRITE_CONNECT);
+      break;
+
+    case STUN_BINDING_RESPONSE:
+    case STUN_BINDING_ERROR_RESPONSE:
+      // Response from remote peer. Does it match request sent?
+      // This doesn't just check, it makes callbacks if transaction
+      // id's match
+      requests_.CheckResponse(msg);
+      break;
+
+    default:
+      assert(false);
+      break;
+    }
+
+    // Done with the message; delete
+
+    delete msg;
+  }
+}
+
+void Connection::Prune() {
+  if (!pruned_) {
+    LOG_J(LS_VERBOSE, this) << "Connection pruned";
+    pruned_ = true;
+    requests_.Clear();
+    set_write_state(STATE_WRITE_TIMEOUT);
+  }
+}
+
+void Connection::Destroy() {
+  LOG_J(LS_VERBOSE, this) << "Connection destroyed";
+  set_read_state(STATE_READ_TIMEOUT);
+  set_write_state(STATE_WRITE_TIMEOUT);
+}
+
+void Connection::UpdateState(uint32 now) {
+  // Check the readable state.
+  //
+  // Since we don't know how many pings the other side has attempted, the best
+  // test we can do is a simple window.
+
+  if ((read_state_ == STATE_READABLE) &&
+      (last_ping_received_ + CONNECTION_READ_TIMEOUT <= now)) {
+    set_read_state(STATE_READ_TIMEOUT);
+  }
+
+  // Check the writable state.  (The order of these checks is important.)
+  //
+  // Before becoming unwritable, we allow for a fixed number of pings to fail
+  // (i.e., receive no response).  We also have to give the response time to
+  // get back, so we include a conservative estimate of this.
+  //
+  // 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_);
+
+  if ((write_state_ == STATE_WRITABLE) &&
+      TooManyFailures(pings_since_last_response_,
+                      CONNECTION_WRITE_CONNECT_FAILURES,
+                      rtt,
+                      now) &&
+      TooLongWithoutResponse(pings_since_last_response_,
+                             CONNECTION_WRITE_CONNECT_TIMEOUT,
+                             now)) {
+    set_write_state(STATE_WRITE_CONNECT);
+  }
+
+  if ((write_state_ == STATE_WRITE_CONNECT) &&
+      TooLongWithoutResponse(pings_since_last_response_,
+                             CONNECTION_WRITE_TIMEOUT,
+                             now)) {
+    set_write_state(STATE_WRITE_TIMEOUT);
+  }
+}
+
+void Connection::Ping(uint32 now) {
+  assert(connected_);
+  last_ping_sent_ = now;
+  pings_since_last_response_.push_back(now);
+  requests_.Send(new ConnectionRequest(this));
+}
+
+void Connection::ReceivedPing() {
+  last_ping_received_ = talk_base::Time();
+  set_read_state(STATE_READABLE);
+}
+
+std::string Connection::ToString() const {
+  const char CONNECT_STATE_ABBREV[2] = {
+    '-', // not connected (false)
+    'C', // connected (true)
+  };
+  const char READ_STATE_ABBREV[2] = {
+    'R', // STATE_READABLE
+    '-', // STATE_READ_TIMEOUT
+  };
+  const char WRITE_STATE_ABBREV[3] = {
+    '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()
+     << "|" 
+     << CONNECT_STATE_ABBREV[connected()]
+     << READ_STATE_ABBREV[read_state()]
+     << WRITE_STATE_ABBREV[write_state()]
+     << "]";
+  return ss.str();
+}
+
+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.
+
+  // Check exact message type
+  bool valid = true;
+  if (response->type() != STUN_BINDING_RESPONSE)
+    valid = false;
+
+  // Must have username attribute
+  const StunByteStringAttribute* username_attr =
+      response->GetByteString(STUN_ATTR_USERNAME);
+  if (valid) {
+    if (!username_attr) {
+      LOG_J(LS_ERROR, this) << "Received likely STUN packet with no username";
+      valid = false;
+    }
+  }
+
+  // Length must be at least the size of our fragment (actually, should
+  // be bigger since our fragment is at the end!)
+  if (valid) {
+    if (username_attr->length() <= port_->username_fragment().size()) {
+      LOG_J(LS_ERROR, this) << "Received likely STUN packet with short username";
+      valid = false;
+    }
+  }
+
+  // Compare our fragment with the end of the username - must be exact match
+  if (valid) {
+    std::string username_fragment = port_->username_fragment();
+    int offset = (int)(username_attr->length() - username_fragment.size());
+    if (std::memcmp(username_attr->bytes() + offset,
+        username_fragment.c_str(), username_fragment.size()) != 0) {
+      LOG_J(LS_ERROR, this) << "Received STUN response with bad username";
+      valid = false;
+    }
+  }
+
+  if (valid) {
+    // Valid response. If we're not already, become writable.  We may be
+    // bringing a pruned connection back to life, but if we don't really want
+    // it, we can always prune it again.
+    set_write_state(STATE_WRITABLE);
+
+    pings_since_last_response_.clear();
+    rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1);
+    rtt_data_points_ += 1;
+  }
+}
+
+void Connection::OnConnectionRequestErrorResponse(StunMessage *response, uint32 rtt) {
+  const StunErrorCodeAttribute* error = response->GetErrorCode();
+  uint32 error_code = error ? error->error_code() : STUN_ERROR_GLOBAL_FAILURE;
+
+  if ((error_code == STUN_ERROR_UNKNOWN_ATTRIBUTE)
+      || (error_code == STUN_ERROR_SERVER_ERROR)
+      || (error_code == STUN_ERROR_UNAUTHORIZED)) {
+    // Recoverable error, retry
+  } else if (error_code == STUN_ERROR_STALE_CREDENTIALS) {
+    // Race failure, retry
+  } else {
+    // This is not a valid connection.
+    set_write_state(STATE_WRITE_TIMEOUT);
+  }
+}
+
+void Connection::CheckTimeout() {
+  // If both read and write have timed out, then this connection can contribute
+  // no more to p2p socket unless at some later date readability were to come
+  // back.  However, we gave readability a long time to timeout, so at this
+  // point, it seems fair to get rid of this connectoin.
+  if ((read_state_ == STATE_READ_TIMEOUT) &&
+      (write_state_ == STATE_WRITE_TIMEOUT)) {
+    port_->thread()->Post(this, MSG_DELETE);
+  }
+}
+
+void Connection::OnMessage(talk_base::Message *pmsg) {
+  assert(pmsg->message_id == MSG_DELETE);
+
+  LOG_J(LS_INFO, this) << "Connection deleted";
+  SignalDestroyed(this);
+  delete this;
+}
+
+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_;
+}
+
+size_t Connection::recv_total_bytes() {
+  return recv_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_;
+}
+
+size_t Connection::sent_total_bytes() {
+  return sent_total_bytes_;
+}
+
+ProxyConnection::ProxyConnection(Port* port, size_t index, const Candidate& candidate)
+  : Connection(port, index, candidate), error_(0) {
+}
+
+int ProxyConnection::Send(const void* data, size_t size) {
+  if (write_state() != STATE_WRITABLE) {
+    error_ = EWOULDBLOCK;
+    return SOCKET_ERROR;
+  }
+  int sent = port_->SendTo(data, size, remote_candidate_.address(), true);
+  if (sent <= 0) {
+    assert(sent < 0);
+    error_ = port_->GetError();
+  } else {
+    sent_total_bytes_ += sent;
+  }
+  return sent;
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/port.h b/talk/p2p/base/port.h
new file mode 100755
index 0000000..57c0727
--- /dev/null
+++ b/talk/p2p/base/port.h
@@ -0,0 +1,421 @@
+/*
+ * 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 __PORT_H__
+#define __PORT_H__
+
+#include "talk/base/network.h"
+#include "talk/base/socketaddress.h"
+#include "talk/base/proxyinfo.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/thread.h"
+#include "talk/p2p/base/candidate.h"
+#include "talk/p2p/base/stun.h"
+#include "talk/p2p/base/stunrequest.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace talk_base {
+class AsyncPacketSocket;
+}
+
+namespace cricket {
+
+class Connection;
+
+enum ProtocolType { 
+  PROTO_UDP, 
+  PROTO_TCP, 
+  PROTO_SSLTCP, 
+  PROTO_LAST = PROTO_SSLTCP 
+};
+
+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) 
+    : address(a), proto(p) { }
+};
+
+// 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, 
+       talk_base::SocketFactory* factory, talk_base::Network* network);
+  virtual ~Port();
+
+  // The thread on which this port performs its I/O.
+  talk_base::Thread* thread() { return thread_; }
+
+  // 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) 
+    { factory_ = factory; }
+
+  // Each port is identified by a name (for debugging purposes).
+  const std::string& name() const { return name_; }
+  void set_name(const std::string& name) { name_ = name; }
+
+  // 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.
+  const std::string& username_fragment() const { return username_frag_; }
+  const std::string& password() const { return password_; }
+
+  // A value in [0,1] that indicates the preference for this port versus other
+  // ports on this client.  (Larger indicates more preference.)
+  float preference() const { return preference_; }
+  void set_preference(float preference) { preference_ = preference; }
+
+  // Identifies the port type.
+  //const std::string& protocol() const { return proto_; }
+  const std::string& type() const { return type_; }
+
+  // Identifies network that this port was allocated on.
+  talk_base::Network* network() { return network_; }
+
+  // Identifies the generation that this port was created in.
+  uint32 generation() { return generation_; }
+  void set_generation(uint32 generation) { generation_ = generation; }
+
+  // PrepareAddress will attempt to get an address for this port that other
+  // clients can send to.  It may take some time before the address is read.
+  // Once it is ready, we will send SignalAddressReady.  If errors are
+  // preventing the port from getting an address, it may send
+  // SignalAddressError.
+  virtual void PrepareAddress() = 0;
+  sigslot::signal1<Port*> SignalAddressReady;
+  sigslot::signal1<Port*> SignalAddressError;
+
+  // Provides all of the above information in one handy object.
+  const std::vector<Candidate>& candidates() const { return candidates_; }
+
+  // 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_; }  
+
+  // 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, 
+    CandidateOrigin origin) = 0;
+
+  // Called each time a connection is created.
+  sigslot::signal2<Port*, Connection*> SignalConnectionCreated;
+
+  // 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, 
+      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*, 
+                   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, 
+                           const talk_base::SocketAddress& addr);
+  void SendBindingErrorResponse(
+      StunMessage* request, const talk_base::SocketAddress& addr, 
+      int error_code, const std::string& reason);
+
+  // Indicates that errors occurred when performing I/O.
+  sigslot::signal2<Port*, int> SignalReadError;
+  sigslot::signal2<Port*, int> SignalWriteError;
+
+  // Functions on the underlying socket(s).
+  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;
+  }
+  static const std::string& user_agent() { return agent_; }
+  static const talk_base::ProxyInfo& proxy() { return proxy_; }
+
+  talk_base::AsyncPacketSocket * CreatePacketSocket(ProtocolType proto);
+
+  // Normally, packets arrive through a connection (or they result signaling of
+  // unknown address).  Calling this method turns off delivery of packets
+  // through their respective connection and instead delivers every packet
+  // through this port.
+  void EnablePortPackets();
+  sigslot::signal4<Port*, const char*, size_t, const talk_base::SocketAddress&>
+      SignalReadPacket;
+
+  // Indicates to the port that its official use has now begun.  This will
+  // start the timer that checks to see if the port is being used.
+  void Start();
+
+  // Called if the port has no connections and is no longer useful.
+  void Destroy();
+
+  // Signaled when this port decides to delete itself because it no longer has
+  // any usefulness.
+  sigslot::signal1<Port*> SignalDestroyed;
+
+  virtual void OnMessage(talk_base::Message *pmsg);
+
+  // Debugging description of this port
+  std::string ToString() const;
+
+protected:
+  talk_base::Thread* thread_;
+  talk_base::SocketFactory* factory_;
+  std::string type_;
+  talk_base::Network* network_;
+  uint32 generation_;
+  std::string name_;
+  std::string username_frag_;
+  std::string password_;
+  float preference_;
+  std::vector<Candidate> candidates_;
+  AddressMap connections_;
+  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, 
+                  const std::string& protocol, bool final);
+
+  // Adds the given connection to the list.  (Deleting removes them.)
+  void AddConnection(Connection* conn);
+
+  // 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, 
+                    const talk_base::SocketAddress& addr);
+
+  // Constructs a STUN binding request for the given connection and sends it.
+  void SendBindingRequest(Connection* conn);
+
+  // If the given data comprises a complete and correct STUN message then the
+  // return value is true, otherwise false. If the message username corresponds
+  // 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, 
+                      const talk_base::SocketAddress& addr,
+                      StunMessage *& msg, std::string& remote_username);
+
+  friend class Connection;
+
+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_;
+};
+
+// Represents a communication link between a port on the local client and a
+// port on the remote client.
+class Connection : public talk_base::MessageHandler, 
+    public sigslot::has_slots<> {
+public:
+  virtual ~Connection();
+
+  // The local port where this connection sends and receives packets.
+  Port* port() { return port_; }
+  const Port* port() const { return port_; }
+
+  // Returns the description of the local port
+  virtual const Candidate& local_candidate() const;
+
+  // Returns the description of the remote port to which we communicate.
+  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
+  };
+
+  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
+  };
+
+  WriteState write_state() const { return write_state_; }
+
+  // Determines whether the connection has finished connecting.  This can only
+  // be false for TCP connections.
+  bool connected() const { return connected_; }
+
+  // Estimate of the round-trip time over this connection.
+  uint32 rtt() const { return rtt_; }
+
+  size_t sent_total_bytes();
+  size_t sent_bytes_second();
+  size_t recv_total_bytes();
+  size_t recv_bytes_second();
+  sigslot::signal1<Connection*> SignalStateChange;
+
+  // Sent when the connection has decided that it is no longer of value.  It
+  // will delete itself immediately after this call.
+  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 
+  // covers.
+  virtual int Send(const void* data, size_t size) = 0;
+
+  // Error if Send() returns < 0
+  virtual int GetError() = 0;
+
+  sigslot::signal3<Connection*, const char*, size_t> SignalReadPacket;
+
+  // Called when a packet is received on this connection.
+  void OnReadPacket(const char* data, size_t size);
+
+  // Called when a connection is determined to be no longer useful to us.  We
+  // still keep it around in case the other side wants to use it.  But we can
+  // safely stop pinging on it and we can allow it to time out if the other
+  // side stops using it as well.
+  bool pruned() { return pruned_; }
+  void Prune();
+
+  // Makes the connection go away.
+  void Destroy();
+
+  // Checks that the state of this connection is up-to-date.  The argument is
+  // the current time, which is compared against various timeouts.
+  void UpdateState(uint32 now);
+
+  // Called when this connection should try checking writability again.
+  uint32 last_ping_sent() { return last_ping_sent_; }
+  void Ping(uint32 now);
+
+  // Called whenever a valid ping is received on this connection.  This is
+  // public because the connection intercepts the first ping for us.
+  void ReceivedPing();
+
+  // Debugging description of this connection
+  std::string ToString() const;
+
+  bool reported() { return reported_; }
+  void set_reported(bool reported) { reported_ = reported;}
+
+protected:
+  Port* port_;
+  size_t local_candidate_index_;
+  Candidate remote_candidate_;
+  ReadState read_state_;
+  WriteState write_state_;
+  bool connected_;
+  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
+  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_;
+
+  // Callbacks from ConnectionRequest
+  void OnConnectionRequestResponse(StunMessage *response, uint32 rtt);
+  void OnConnectionRequestErrorResponse(StunMessage *response, uint32 rtt);
+
+  // Called back when StunRequestManager has a stun packet to send
+  void OnSendStunPacket(const void* data, size_t size, StunRequest* req);
+
+  // Constructs a new connection to the given remote port.
+  Connection(Port* port, size_t index, const Candidate& candidate);
+
+  // Changes the state and signals if necessary.
+  void set_read_state(ReadState value);
+  void set_write_state(WriteState value);
+  void set_connected(bool value);
+
+  // Checks if this connection is useless, and hence, should be destroyed.
+  void CheckTimeout();
+
+  void OnMessage(talk_base::Message *pmsg);
+
+  friend class Port;
+  friend class ConnectionRequest;
+
+private:
+  bool reported_;
+};
+
+// ProxyConnection defers all the interesting work to the port
+
+class ProxyConnection : public Connection {
+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:
+  int error_;
+};
+
+} // namespace cricket
+
+#endif // __PORT_H__
diff --git a/talk/p2p/base/port_unittest.cc b/talk/p2p/base/port_unittest.cc
new file mode 100755
index 0000000..4687c19
--- /dev/null
+++ b/talk/p2p/base/port_unittest.cc
@@ -0,0 +1,363 @@
+#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
new file mode 100755
index 0000000..50f52cf
--- /dev/null
+++ b/talk/p2p/base/portallocator.h
@@ -0,0 +1,104 @@
+/*
+ * 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 _PORTALLOCATOR_H_
+#define _PORTALLOCATOR_H_
+
+#include "talk/base/sigslot.h"
+#include "talk/p2p/base/port.h"
+#include <string>
+#undef SetPort
+
+namespace cricket {
+
+// PortAllocator is responsible for allocating Port types for a given
+// P2PSocket. It also handles port freeing.
+//
+// Clients can override this class to control port allocation, including
+// what kinds of ports are allocated.
+
+const uint32 PORTALLOCATOR_DISABLE_UDP = 0x01;
+const uint32 PORTALLOCATOR_DISABLE_STUN = 0x02;
+const uint32 PORTALLOCATOR_DISABLE_RELAY = 0x04;
+const uint32 PORTALLOCATOR_DISABLE_TCP = 0x08;
+const uint32 PORTALLOCATOR_ENABLE_SHAKER = 0x10;
+
+const uint32 kDefaultPortAllocatorFlags = 0;
+
+class PortAllocatorSession : public sigslot::has_slots<> {
+public:
+  PortAllocatorSession(uint32 flags) : flags_(flags) {}
+
+  // Subclasses should clean up any ports created.
+  virtual ~PortAllocatorSession() {}
+
+  uint32 flags() const { return flags_; }
+  void set_flags(uint32 flags) { flags_ = flags; }
+
+  // Prepares an initial set of ports to try.
+  virtual void GetInitialPorts() = 0;
+
+  // Starts and stops the flow of additional ports to try.
+  virtual void StartGetAllPorts() = 0;
+  virtual void StopGetAllPorts() = 0;
+  virtual bool IsGettingAllPorts() = 0;
+
+  sigslot::signal2<PortAllocatorSession*, Port*> SignalPortReady;
+  sigslot::signal2<PortAllocatorSession*, const std::vector<Candidate>&> SignalCandidatesReady;
+
+  uint32 generation() { return generation_; }
+  void set_generation(uint32 generation) { generation_ = generation; }
+
+private:
+  uint32 flags_;
+  uint32 generation_;
+};
+
+class PortAllocator {
+public:
+  PortAllocator() : flags_(kDefaultPortAllocatorFlags) {}
+
+    virtual PortAllocatorSession *CreateSession(const std::string &name, const std::string &session_type) = 0;
+
+  uint32 flags() const { return flags_; }
+  void set_flags(uint32 flags) { flags_ = flags; }
+
+  const std::string& user_agent() const { return agent_; }
+  const talk_base::ProxyInfo& proxy() const { return proxy_; }
+  void set_proxy(const std::string& agent, const talk_base::ProxyInfo& proxy) {
+    agent_ = agent; proxy_ = proxy;
+  }
+
+protected:
+  uint32 flags_;
+  std::string agent_;
+  talk_base::ProxyInfo proxy_;
+};
+
+} // namespace cricket
+
+#endif // _PORTALLOCATOR_H_
diff --git a/talk/p2p/base/pseudotcp.cc b/talk/p2p/base/pseudotcp.cc
new file mode 100755
index 0000000..2f52d65
--- /dev/null
+++ b/talk/p2p/base/pseudotcp.cc
@@ -0,0 +1,1071 @@
+/*
+ * 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/basicdefs.h"
+#include "talk/base/basictypes.h"
+#include "talk/base/byteorder.h"
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#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.
+#define _DBG_NONE     0
+#define _DBG_NORMAL   1
+#define _DBG_VERBOSE  2
+#define _DEBUGMSG _DBG_NONE
+
+namespace cricket {
+
+//////////////////////////////////////////////////////////////////////
+// Network Constants
+//////////////////////////////////////////////////////////////////////
+
+// Standard MTUs
+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)
+  4352,   // FDDI
+  //2048,   // Wideband Network
+  2002,   // IEEE 802.5 (4Mb recommended)
+  //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
+  508,    // IEEE 802/Source-Rt Bridge, ARCNET
+  296,    // Point-to-Point (low delay)
+  //68,     // Official minimum
+  0,      // End of list marker
+};
+
+const uint32 MAX_PACKET = 65535;
+// Note: we removed lowest level because packet overhead was larger!
+const uint32 MIN_PACKET = 296;
+
+const uint32 IP_HEADER_SIZE = 20; // (+ up to 40 bytes of options?)
+const uint32 ICMP_HEADER_SIZE = 8;
+const uint32 UDP_HEADER_SIZE = 8;
+// TODO: Make JINGLE_HEADER_SIZE transparent to this code?
+const uint32 JINGLE_HEADER_SIZE = 64; // when relay framing is in use
+
+//////////////////////////////////////////////////////////////////////
+// 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 |                      Conversation Number                      |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  4 |                        Sequence Number                        |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  8 |                     Acknowledgment Number                     |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//    |               |   |U|A|P|R|S|F|                               |
+// 12 |    Control    |   |R|C|S|S|Y|I|            Window             |
+//    |               |   |G|K|H|T|N|N|                               |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 16 |                       Timestamp sending                       |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 20 |                      Timestamp receiving                      |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 24 |                             data                              |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+//////////////////////////////////////////////////////////////////////
+
+#define PSEUDO_KEEPALIVE 0
+
+const uint32 MAX_SEQ = 0xFFFFFFFF;
+const uint32 HEADER_SIZE = 24;
+const uint32 PACKET_OVERHEAD = HEADER_SIZE + UDP_HEADER_SIZE + IP_HEADER_SIZE + JINGLE_HEADER_SIZE;
+
+const uint32 MIN_RTO   =   250; // 250 ms (RFC1122, Sec 4.2.3.1 "fractions of a second")
+const uint32 DEF_RTO   =  3000; // 3 seconds (RFC1122, Sec 4.2.3.1)
+const uint32 MAX_RTO   = 60000; // 60 seconds
+const uint32 ACK_DELAY =   100; // 100 milliseconds
+
+const uint8 FLAG_CTL = 0x02;
+const uint8 FLAG_RST = 0x04;
+
+const uint8 CTL_CONNECT = 0;
+//const uint8 CTL_REDIRECT = 1;
+const uint8 CTL_EXTRA = 255;
+
+/*
+const uint8 FLAG_FIN = 0x01;
+const uint8 FLAG_SYN = 0x02;
+const uint8 FLAG_ACK = 0x10;
+*/
+
+const uint32 CTRL_BOUND = 0x80000000;
+
+const long DEFAULT_TIMEOUT = 4000; // If there are no pending clocks, wake up every 4 seconds
+const long CLOSED_TIMEOUT = 60 * 1000; // If the connection is closed, once per minute
+
+#if PSEUDO_KEEPALIVE
+// !?! Rethink these times
+const uint32 IDLE_PING = 20 * 1000; // 20 seconds (note: WinXP SP2 firewall udp timeout is 90 seconds)
+const uint32 IDLE_TIMEOUT = 90 * 1000; // 90 seconds;
+#endif // PSEUDO_KEEPALIVE
+
+//////////////////////////////////////////////////////////////////////
+// Helper Functions
+//////////////////////////////////////////////////////////////////////
+
+inline void long_to_bytes(uint32 val, void* buf) {
+  *static_cast<uint32*>(buf) = talk_base::HostToNetwork32(val);
+}
+
+inline void short_to_bytes(uint16 val, void* buf) {
+  *static_cast<uint16*>(buf) = talk_base::HostToNetwork16(val);
+}
+
+inline uint32 bytes_to_long(const void* buf) {
+  return talk_base::NetworkToHost32(*static_cast<const uint32*>(buf));
+}
+
+inline uint16 bytes_to_short(const void* buf) {
+  return talk_base::NetworkToHost16(*static_cast<const uint16*>(buf));
+}
+
+uint32 bound(uint32 lower, uint32 middle, uint32 upper) {
+  return talk_base::_min(talk_base::_max(lower, middle), upper);
+}
+
+//////////////////////////////////////////////////////////////////////
+// Debugging Statistics
+//////////////////////////////////////////////////////////////////////
+
+#if 0  // Not used yet
+
+enum Stat {
+  S_SENT_PACKET,   // All packet sends
+  S_RESENT_PACKET, // All packet sends that are retransmits
+  S_RECV_PACKET,   // All packet receives
+  S_RECV_NEW,      // All packet receives that are too new
+  S_RECV_OLD,      // All packet receives that are too old
+  S_NUM_STATS
+};
+
+const char* const STAT_NAMES[S_NUM_STATS] = {
+  "snt",
+  "snt-r",
+  "rcv"
+  "rcv-n",
+  "rcv-o"
+};
+
+int g_stats[S_NUM_STATS];
+inline void Incr(Stat s) { ++g_stats[s]; }
+void ReportStats() {
+  char buffer[256];
+  size_t len = 0;
+  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;
+  }
+  LOG(LS_INFO) << "Stats[" << buffer << "]";
+}
+
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// PseudoTcp
+//////////////////////////////////////////////////////////////////////
+
+uint32 PseudoTcp::Now() {
+#if 0  // Use this to synchronize timers with logging timestamps (easier debug)
+  return talk_base::ElapsedTime();
+#else
+  return talk_base::Time();
+#endif
+}
+
+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)
+  ASSERT(sizeof(m_rbuf) + MIN_PACKET < sizeof(m_sbuf));
+
+  uint32 now = Now();
+
+  m_state = TCP_LISTEN;
+  m_conv = conv;
+  m_rcv_wnd = sizeof(m_rbuf);
+  m_snd_nxt = m_slen = 0;
+  m_snd_wnd = 1;
+  m_snd_una = m_rcv_nxt = m_rlen = 0;
+  m_bReadEnable = true;
+  m_bWriteEnable = false;
+  m_t_ack = 0;
+
+  m_msslevel = 0;
+  m_largest = 0;
+  ASSERT(MIN_PACKET > PACKET_OVERHEAD);
+  m_mss = MIN_PACKET - PACKET_OVERHEAD;
+  m_mtu_advise = MAX_PACKET;
+
+  m_rto_base = 0;
+
+  m_cwnd = 2 * m_mss;
+  m_ssthresh = sizeof(m_rbuf);
+  m_lastrecv = m_lastsend = m_lasttraffic = now;
+  m_bOutgoing = false;
+
+  m_dup_acks = 0;
+  m_recover = 0;
+
+  m_ts_recent = m_ts_lastack = 0;
+
+  m_rx_rto = DEF_RTO;
+  m_rx_srtt = m_rx_rttvar = 0;
+}
+
+PseudoTcp::~PseudoTcp() {
+}
+
+int
+PseudoTcp::Connect() {
+  if (m_state != TCP_LISTEN) {
+    m_error = EINVAL;
+    return -1;
+  }
+
+  m_state = TCP_SYN_SENT;
+  LOG(LS_INFO) << "State: TCP_SYN_SENT";
+
+  char buffer[1];
+  buffer[0] = CTL_CONNECT;
+  queue(buffer, 1, true);
+  attemptSend();
+
+  return 0;
+}
+
+void
+PseudoTcp::NotifyMTU(uint16 mtu) {
+  m_mtu_advise = mtu;
+  if (m_state == TCP_ESTABLISHED) {
+    adjustMTU();
+  }
+}
+
+void
+PseudoTcp::NotifyClock(uint32 now) {
+  if (m_state == TCP_CLOSED)
+    return;
+
+    // Check if it's time to retransmit a segment
+  if (m_rto_base && (talk_base::TimeDiff(m_rto_base + m_rx_rto, now) <= 0)) {
+    if (m_slist.empty()) {
+      ASSERT(false);
+    } else {
+      // Note: (m_slist.front().xmit == 0)) {
+      // retransmit segments
+#if _DEBUGMSG >= _DBG_NORMAL
+      LOG(LS_INFO) << "timeout retransmit (rto: " << m_rx_rto
+                   << ") (rto_base: " << m_rto_base
+                   << ") (now: " << now
+                   << ") (dup_acks: " << static_cast<unsigned>(m_dup_acks)
+                   << ")";
+#endif // _DEBUGMSG
+      if (!transmit(m_slist.begin(), now)) {
+        closedown(ECONNABORTED);
+        return;
+      }
+
+      uint32 nInFlight = m_snd_nxt - m_snd_una;
+      m_ssthresh = talk_base::_max(nInFlight / 2, 2 * m_mss);
+      //LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << "  nInFlight: " << nInFlight << "  m_mss: " << m_mss;
+      m_cwnd = m_mss;
+
+      // Back off retransmit timer.  Note: the limit is lower when connecting.
+      uint32 rto_limit = (m_state < TCP_ESTABLISHED) ? DEF_RTO : MAX_RTO;
+      m_rx_rto = talk_base::_min(rto_limit, m_rx_rto * 2);
+      m_rto_base = now;
+    }
+  }
+  
+  // Check if it's time to probe closed windows
+  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);
+      return;
+    }
+
+    // probe the window
+    packet(m_snd_nxt - 1, 0, 0, 0);
+    m_lastsend = now;
+
+    // back off retransmit timer
+    m_rx_rto = talk_base::_min(MAX_RTO, m_rx_rto * 2);
+  }
+
+  // Check if it's time to send delayed acks
+  if (m_t_ack && (talk_base::TimeDiff(m_t_ack + ACK_DELAY, now) <= 0)) {
+    packet(m_snd_nxt, 0, 0, 0);
+  }
+
+#if PSEUDO_KEEPALIVE
+  // Check for idle timeout
+  if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lastrecv + IDLE_TIMEOUT, now) <= 0)) {
+    closedown(ECONNABORTED);
+    return;
+  }
+
+  // Check for ping timeout (to keep udp mapping open)
+  if ((m_state == TCP_ESTABLISHED) && (TimeDiff(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3/2 : IDLE_PING), now) <= 0)) {
+    packet(m_snd_nxt, 0, 0, 0);
+  }
+#endif // PSEUDO_KEEPALIVE
+}
+
+bool
+PseudoTcp::NotifyPacket(const char * buffer, size_t len) {
+  if (len > MAX_PACKET) {
+    LOG_F(WARNING) << "packet too large";
+    return false;
+  }
+  return parse(reinterpret_cast<const uint8 *>(buffer), uint32(len));
+}
+
+bool
+PseudoTcp::GetNextClock(uint32 now, long& timeout) {
+  return clock_check(now, timeout);
+}
+
+// 
+// IPStream Implementation
+//
+
+int
+PseudoTcp::Recv(char * buffer, size_t len) {
+  if (m_state != TCP_ESTABLISHED) {
+    m_error = ENOTCONN;
+    return SOCKET_ERROR;
+  }
+
+  if (m_rlen == 0) {
+    m_bReadEnable = true;
+    m_error = EWOULDBLOCK;
+    return SOCKET_ERROR;
+  }
+
+  uint32 read = talk_base::_min(uint32(len), m_rlen);
+  memcpy(buffer, m_rbuf, read);
+  m_rlen -= read;
+
+  // !?! 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) 
+      >= talk_base::_min<uint32>(sizeof(m_rbuf) / 2, m_mss)) {
+    bool bWasClosed = (m_rcv_wnd == 0); // !?! Not sure about this was closed business
+
+    m_rcv_wnd = sizeof(m_rbuf) - m_rlen;
+
+    if (bWasClosed) {
+      attemptSend(sfImmediateAck);
+    }
+  }
+
+  return read;
+}
+
+int
+PseudoTcp::Send(const char * buffer, size_t len) {
+  if (m_state != TCP_ESTABLISHED) {
+    m_error = ENOTCONN;
+    return SOCKET_ERROR;
+  }
+
+  if (m_slen == sizeof(m_sbuf)) {
+    m_bWriteEnable = true;
+    m_error = EWOULDBLOCK;
+    return SOCKET_ERROR;
+  }
+
+  int written = queue(buffer, uint32(len), false);
+  attemptSend();
+  return written;
+}
+
+void
+PseudoTcp::Close(bool force) {
+  LOG_F(LS_VERBOSE) << "(" << (force ? "true" : "false") << ")";
+  m_shutdown = force ? SD_FORCEFUL : SD_GRACEFUL;
+}
+
+int PseudoTcp::GetError() {
+  return m_error;
+}
+
+//
+// Internal Implementation
+//
+
+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;
+  }
+
+  // We can concatenate data if the last segment is the same type
+  // (control v. regular data), and has not been transmitted yet
+  if (!m_slist.empty() && (m_slist.back().bCtrl == bCtrl) && (m_slist.back().xmit == 0)) {
+    m_slist.back().len += len;
+  } else {
+    SSegment sseg(m_snd_una + m_slen, len, bCtrl);
+    m_slist.push_back(sseg);
+  }
+
+  memcpy(m_sbuf + m_slen, data, len);
+  m_slen += len;
+  //LOG(LS_INFO) << "PseudoTcp::queue - m_slen = " << m_slen;
+  return len;
+}
+
+IPseudoTcpNotify::WriteResult
+PseudoTcp::packet(uint32 seq, uint8 flags, const char * data, uint32 len) {
+  ASSERT(HEADER_SIZE + len <= MAX_PACKET);
+
+  uint32 now = Now();
+
+  uint8 buffer[MAX_PACKET];
+  long_to_bytes(m_conv, buffer);
+  long_to_bytes(seq, buffer + 4);
+  long_to_bytes(m_rcv_nxt, buffer + 8);
+  buffer[12] = 0;
+  buffer[13] = flags;
+  short_to_bytes(uint16(m_rcv_wnd), buffer + 14);
+
+  // Timestamp computations
+  long_to_bytes(now, buffer + 16);
+  long_to_bytes(m_ts_recent, buffer + 20);
+  m_ts_lastack = m_rcv_nxt;
+
+  memcpy(buffer + HEADER_SIZE, data, len);
+
+#if _DEBUGMSG >= _DBG_VERBOSE
+  LOG(LS_INFO) << "<-- <CONV=" << m_conv
+               << "><FLG=" << static_cast<unsigned>(flags)
+               << "><SEQ=" << seq << ":" << seq + len
+               << "><ACK=" << m_rcv_nxt
+               << "><WND=" << m_rcv_wnd
+               << "><TS="  << (now % 10000)
+               << "><TSR=" << (m_ts_recent % 10000)
+               << "><LEN=" << len << ">";
+#endif // _DEBUGMSG
+
+  IPseudoTcpNotify::WriteResult wres = m_notify->TcpWritePacket(this, reinterpret_cast<char *>(buffer), len + HEADER_SIZE);
+  // Note: When data is NULL, this is an ACK packet.  We don't read the return value for those,
+  // and thus we won't retry.  So go ahead and treat the packet as a success (basically simulate
+  // as if it were dropped), which will prevent our timers from being messed up.
+  if ((wres != IPseudoTcpNotify::WR_SUCCESS) && (NULL != data))
+    return wres;
+
+  m_t_ack = 0;
+  if (len > 0) {
+    m_lastsend = now;
+  }
+  m_lasttraffic = now;
+  m_bOutgoing = true;
+
+  return IPseudoTcpNotify::WR_SUCCESS;
+}
+
+bool
+PseudoTcp::parse(const uint8 * buffer, uint32 size) {
+  if (size < 12)
+    return false;
+
+  Segment seg;
+  seg.conv = bytes_to_long(buffer);
+  seg.seq = bytes_to_long(buffer + 4);
+  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);
+
+  seg.data = reinterpret_cast<const char *>(buffer) + HEADER_SIZE;
+  seg.len = size - HEADER_SIZE;
+
+#if _DEBUGMSG >= _DBG_VERBOSE
+  LOG(LS_INFO) << "--> <CONV=" << seg.conv
+               << "><FLG=" << static_cast<unsigned>(seg.flags)
+               << "><SEQ=" << seg.seq << ":" << seg.seq + seg.len
+               << "><ACK=" << seg.ack
+               << "><WND=" << seg.wnd
+               << "><TS="  << (seg.tsval % 10000)
+               << "><TSR=" << (seg.tsecr % 10000)
+               << "><LEN=" << seg.len << ">";
+#endif // _DEBUGMSG
+
+  return process(seg);
+}
+
+bool
+PseudoTcp::clock_check(uint32 now, long& nTimeout) {
+  if (m_shutdown == SD_FORCEFUL)
+    return false;
+
+  if ((m_shutdown == SD_GRACEFUL)
+      && ((m_state != TCP_ESTABLISHED)
+          || ((m_slen == 0) && (m_t_ack == 0)))) {
+    return false;
+  }
+
+  if (m_state == TCP_CLOSED) {
+    nTimeout = CLOSED_TIMEOUT;
+    return true;
+  }
+
+  nTimeout = DEFAULT_TIMEOUT;
+
+  if (m_t_ack) {
+    nTimeout = talk_base::_min(nTimeout, 
+      talk_base::TimeDiff(m_t_ack + ACK_DELAY, now));
+  }
+  if (m_rto_base) {
+    nTimeout = talk_base::_min(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));
+  }
+#if PSEUDO_KEEPALIVE
+  if (m_state == TCP_ESTABLISHED) {
+    nTimeout = talk_base::_min(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) {
+  // If this is the wrong conversation, send a reset!?! (with the correct conversation?)
+  if (seg.conv != m_conv) {
+    //if ((seg.flags & FLAG_RST) == 0) {
+    //  packet(tcb, seg.ack, 0, FLAG_RST, 0, 0);
+    //}
+    LOG_F(LS_ERROR) << "wrong conversation";
+    return false;
+  }
+
+  uint32 now = Now();
+  m_lasttraffic = m_lastrecv = now;
+  m_bOutgoing = false;
+
+  if (m_state == TCP_CLOSED) {
+    // !?! send reset?
+    LOG_F(LS_ERROR) << "closed";
+    return false;
+  }
+
+  // Check if this is a reset segment
+  if (seg.flags & FLAG_RST) {
+    closedown(ECONNRESET);
+    return false;
+  }
+
+  // Check for control data
+  bool bConnect = false;
+  if (seg.flags & FLAG_CTL) {
+    if (seg.len == 0) {
+      LOG_F(LS_ERROR) << "Missing control code";
+      return false;
+    } else if (seg.data[0] == CTL_CONNECT) {
+      bConnect = true;
+      if (m_state == TCP_LISTEN) {
+        m_state = TCP_SYN_RECEIVED;
+        LOG(LS_INFO) << "State: TCP_SYN_RECEIVED";
+        //m_notify->associate(addr);
+        char buffer[1];
+        buffer[0] = CTL_CONNECT;
+        queue(buffer, 1, true);
+      } else if (m_state == TCP_SYN_SENT) {
+        m_state = TCP_ESTABLISHED;
+        LOG(LS_INFO) << "State: TCP_ESTABLISHED";
+        adjustMTU();
+        if (m_notify) {
+          m_notify->OnTcpOpen(this);
+        }
+        //notify(evOpen);
+      }
+    } else {
+      LOG_F(LS_WARNING) << "Unknown control code: " << seg.data[0];
+      return false;
+    }
+  }
+
+  // Update timestamp
+  if ((seg.seq <= m_ts_lastack) && (m_ts_lastack < seg.seq + seg.len)) {
+    m_ts_recent = seg.tsval;
+  }
+
+  // Check if this is a valuable ack
+  if ((seg.ack > m_snd_una) && (seg.ack <= m_snd_nxt)) {
+    // Calculate round-trip time
+    if (seg.tsecr) {
+      long rtt = talk_base::TimeDiff(now, seg.tsecr);
+      if (rtt >= 0) {
+        if (m_rx_srtt == 0) {
+          m_rx_srtt = rtt;
+          m_rx_rttvar = rtt / 2;
+        } else {
+          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);
+#if _DEBUGMSG >= _DBG_VERBOSE
+        LOG(LS_INFO) << "rtt: " << rtt
+                     << "  srtt: " << m_rx_srtt
+                     << "  rto: " << m_rx_rto;
+#endif // _DEBUGMSG
+      } else {
+        ASSERT(false);
+      }
+    }
+
+    m_snd_wnd = seg.wnd;
+
+    uint32 nAcked = seg.ack - m_snd_una;
+    m_snd_una = seg.ack;
+
+    m_rto_base = (m_snd_una == m_snd_nxt) ? 0 : now;
+
+    m_slen -= nAcked;
+    memmove(m_sbuf, m_sbuf + nAcked, m_slen);
+    //LOG(LS_INFO) << "PseudoTcp::process - m_slen = " << m_slen;
+
+    for (uint32 nFree = nAcked; nFree > 0; ) {
+      ASSERT(!m_slist.empty());
+      if (nFree < m_slist.front().len) {
+        m_slist.front().len -= nFree;
+        nFree = 0;
+      } else {
+        if (m_slist.front().len > m_largest) {
+          m_largest = m_slist.front().len;
+        }
+        nFree -= m_slist.front().len;
+        m_slist.pop_front();
+      }
+    }
+
+    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) 
+#if _DEBUGMSG >= _DBG_NORMAL
+        LOG(LS_INFO) << "exit recovery";
+#endif // _DEBUGMSG
+        m_dup_acks = 0;
+      } else {
+#if _DEBUGMSG >= _DBG_NORMAL
+        LOG(LS_INFO) << "recovery retransmit";
+#endif // _DEBUGMSG
+        if (!transmit(m_slist.begin(), now)) {
+          closedown(ECONNABORTED);
+          return false;
+        }
+        m_cwnd += m_mss - talk_base::_min(nAcked, m_cwnd);
+      }
+    } else {
+      m_dup_acks = 0;
+      // Slow start, congestion avoidance
+      if (m_cwnd < m_ssthresh) {
+        m_cwnd += m_mss;
+      } else {
+        m_cwnd += talk_base::_max(1LU, m_mss * m_mss / m_cwnd);
+      }
+    }
+
+    // !?! A bit hacky
+    if ((m_state == TCP_SYN_RECEIVED) && !bConnect) {
+      m_state = TCP_ESTABLISHED;
+      LOG(LS_INFO) << "State: TCP_ESTABLISHED";
+      adjustMTU();
+      if (m_notify) {
+        m_notify->OnTcpOpen(this);
+      }
+      //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.
+    const uint32 kIdealRefillSize = (sizeof(m_sbuf) + sizeof(m_rbuf)) / 2;
+    if (m_bWriteEnable && (m_slen < kIdealRefillSize)) {
+      m_bWriteEnable = false;
+      if (m_notify) {
+        m_notify->OnTcpWriteable(this);
+      }
+      //notify(evWrite);
+    }
+  } else if (seg.ack == m_snd_una) {
+    // !?! Note, tcp says don't do this... but otherwise how does a closed window become open?
+    m_snd_wnd = seg.wnd;
+
+    // Check duplicate acks
+    if (seg.len > 0) {
+      // it's a dup ack, but with a data payload, so don't modify m_dup_acks
+    } else if (m_snd_una != m_snd_nxt) {
+      m_dup_acks += 1;
+      if (m_dup_acks == 3) { // (Fast Retransmit)
+#if _DEBUGMSG >= _DBG_NORMAL
+        LOG(LS_INFO) << "enter recovery";
+        LOG(LS_INFO) << "recovery retransmit";
+#endif // _DEBUGMSG
+        if (!transmit(m_slist.begin(), now)) {
+          closedown(ECONNABORTED);
+          return false;
+        }
+        m_recover = m_snd_nxt;
+        uint32 nInFlight = m_snd_nxt - m_snd_una;
+        m_ssthresh = talk_base::_max(nInFlight / 2, 2 * m_mss);
+        //LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << "  nInFlight: " << nInFlight << "  m_mss: " << m_mss;
+        m_cwnd = m_ssthresh + 3 * m_mss;
+      } else if (m_dup_acks > 3) {
+        m_cwnd += m_mss;
+      }
+    } else {
+      m_dup_acks = 0;
+    }
+  }
+
+  // Conditions were acks must be sent:
+  // 1) Segment is too old (they missed an ACK) (immediately)
+  // 2) Segment is too new (we missed a segment) (immediately)
+  // 3) Segment has data (so we need to ACK!) (delayed)
+  // ... so the only time we don't need to ACK, is an empty segment that points to rcv_nxt!
+
+  SendFlags sflags = sfNone;
+  if (seg.seq != m_rcv_nxt) {
+    sflags = sfImmediateAck; // (Fast Recovery)
+  } else if (seg.len != 0) {
+    sflags = sfDelayedAck;
+  }
+#if _DEBUGMSG >= _DBG_NORMAL
+  if (sflags == sfImmediateAck) {
+    if (seg.seq > m_rcv_nxt) {
+      LOG_F(LS_INFO) << "too new";
+    } else if (seg.seq + seg.len <= m_rcv_nxt) {
+      LOG_F(LS_INFO) << "too old";
+    }
+  }
+#endif // _DEBUGMSG
+
+  // Adjust the incoming segment to fit our receive buffer
+  if (seg.seq < m_rcv_nxt) {
+    uint32 nAdjust = m_rcv_nxt - seg.seq;
+    if (nAdjust < seg.len) {
+      seg.seq += nAdjust;
+      seg.data += nAdjust;
+      seg.len -= nAdjust;
+    } else {
+      seg.len = 0;
+    }
+  }
+  if ((seg.seq + seg.len - m_rcv_nxt) > (sizeof(m_rbuf) - m_rlen)) {
+    uint32 nAdjust = seg.seq + seg.len - m_rcv_nxt - (sizeof(m_rbuf) - m_rlen);
+    if (nAdjust < seg.len) {
+      seg.len -= nAdjust;
+    } else {
+      seg.len = 0;
+    }
+  }
+
+  bool bIgnoreData = (seg.flags & FLAG_CTL) || (m_shutdown != SD_NONE);
+  bool bNewData = false;
+
+  if (seg.len > 0) {
+    if (bIgnoreData) {
+      if (seg.seq == m_rcv_nxt) {
+        m_rcv_nxt += seg.len;
+      }
+    } else {
+      uint32 nOffset = seg.seq - m_rcv_nxt;
+      memcpy(m_rbuf + m_rlen + nOffset, seg.data, seg.len);
+      if (seg.seq == m_rcv_nxt) {
+        m_rlen += seg.len;
+        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) {
+            sflags = sfImmediateAck; // (Fast Recovery)
+            uint32 nAdjust = (it->seq + it->len) - m_rcv_nxt;
+#if _DEBUGMSG >= _DBG_NORMAL
+            LOG(LS_INFO) << "Recovered " << nAdjust << " bytes (" << m_rcv_nxt << " -> " << m_rcv_nxt + nAdjust << ")";
+#endif // _DEBUGMSG
+            m_rlen += nAdjust;
+            m_rcv_nxt += nAdjust;
+            m_rcv_wnd -= nAdjust;
+          }
+          it = m_rlist.erase(it);
+        }
+      } else {
+#if _DEBUGMSG >= _DBG_NORMAL
+        LOG(LS_INFO) << "Saving " << seg.len << " bytes (" << seg.seq << " -> " << seg.seq + seg.len << ")";
+#endif // _DEBUGMSG
+        RSegment rseg;
+        rseg.seq = seg.seq;
+        rseg.len = seg.len;
+        RList::iterator it = m_rlist.begin();
+        while ((it != m_rlist.end()) && (it->seq < rseg.seq)) {
+          ++it;
+        }
+        m_rlist.insert(it, rseg);
+      }
+    }
+  }
+
+  attemptSend(sflags);
+
+  // If we have new data, notify the user
+  if (bNewData && m_bReadEnable) {
+    m_bReadEnable = false;
+    if (m_notify) {
+      m_notify->OnTcpReadable(this);
+    }
+    //notify(evRead);
+  }
+
+  return true;
+}
+
+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;
+  }
+
+  uint32 nTransmit = talk_base::_min(seg->len, m_mss);
+
+  while (true) {
+    uint32 seq = seg->seq;
+    uint8 flags = (seg->bCtrl ? FLAG_CTL : 0);
+    const char * buffer = m_sbuf + (seg->seq - m_snd_una);
+    IPseudoTcpNotify::WriteResult wres = this->packet(seq, flags, buffer, nTransmit);
+
+    if (wres == IPseudoTcpNotify::WR_SUCCESS)
+      break;
+
+    if (wres == IPseudoTcpNotify::WR_FAIL) {
+      LOG_F(LS_VERBOSE) << "packet failed";
+      return false;
+    }
+
+    ASSERT(wres == IPseudoTcpNotify::WR_TOO_LARGE);
+
+    while (true) {
+      if (PACKET_MAXIMUMS[m_msslevel + 1] == 0) {
+        LOG_F(LS_VERBOSE) << "MTU too small";
+        return false;
+      }
+      // !?! We need to break up all outstanding and pending packets and then retransmit!?!
+
+      m_mss = PACKET_MAXIMUMS[++m_msslevel] - PACKET_OVERHEAD;
+      m_cwnd = 2 * m_mss; // I added this... haven't researched actual formula
+      if (m_mss < nTransmit) {
+        nTransmit = m_mss;
+        break;
+      }
+    }
+#if _DEBUGMSG >= _DBG_NORMAL
+    LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes";
+#endif // _DEBUGMSG
+  }
+
+  if (nTransmit < seg->len) {
+    LOG_F(LS_VERBOSE) << "mss reduced to " << m_mss;
+
+    SSegment subseg(seg->seq + nTransmit, seg->len - nTransmit, seg->bCtrl);
+    //subseg.tstamp = seg->tstamp;
+    subseg.xmit = seg->xmit;
+    seg->len = nTransmit;
+
+    SList::iterator next = seg;
+    m_slist.insert(++next, subseg);
+  }
+
+  if (seg->xmit == 0) {
+    m_snd_nxt += seg->len;
+  }
+  seg->xmit += 1;
+  //seg->tstamp = now;
+  if (m_rto_base == 0) {
+    m_rto_base = now;
+  }
+
+  return true;
+}
+
+void
+PseudoTcp::attemptSend(SendFlags sflags) {
+  uint32 now = Now();
+
+  if (talk_base::TimeDiff(now, m_lastsend) > static_cast<long>(m_rx_rto)) {
+    m_cwnd = m_mss;
+  }
+
+#if _DEBUGMSG
+  bool bFirst = true;
+  UNUSED(bFirst);
+#endif // _DEBUGMSG
+
+  while (true) {
+    uint32 cwnd = m_cwnd;
+    if ((m_dup_acks == 1) || (m_dup_acks == 2)) { // Limited Transmit
+      cwnd += m_dup_acks * m_mss;
+    }
+    uint32 nWindow = talk_base::_min(m_snd_wnd, cwnd);
+    uint32 nInFlight = m_snd_nxt - m_snd_una;
+    uint32 nUseable = (nInFlight < nWindow) ? (nWindow - nInFlight) : 0;
+
+    uint32 nAvailable = talk_base::_min(m_slen - nInFlight, m_mss);
+
+    if (nAvailable > nUseable) {
+      if (nUseable * 4 < nWindow) {
+        // RFC 813 - avoid SWS
+        nAvailable = 0;
+      } else {
+        nAvailable = nUseable;
+      }
+    }
+
+#if _DEBUGMSG >= _DBG_VERBOSE
+    if (bFirst) {
+      bFirst = false;
+      LOG(LS_INFO) << "[cwnd: " << m_cwnd
+                   << "  nWindow: " << nWindow
+                   << "  nInFlight: " << nInFlight
+                   << "  nAvailable: " << nAvailable
+                   << "  nQueued: " << m_slen - nInFlight
+                   << "  nEmpty: " << sizeof(m_sbuf) - m_slen
+                   << "  ssthresh: " << m_ssthresh << "]";
+    }
+#endif // _DEBUGMSG
+
+    if (nAvailable == 0) {
+      if (sflags == sfNone)
+        return;
+
+      // If this is an immediate ack, or the second delayed ack
+      if ((sflags == sfImmediateAck) || m_t_ack) {
+        packet(m_snd_nxt, 0, 0, 0);
+      } else {
+        m_t_ack = Now();
+      }
+      return;       
+    }
+    
+    // Nagle algorithm
+    if ((m_snd_nxt > m_snd_una) && (nAvailable < m_mss))  {
+      return;
+    }
+
+    // Find the next segment to transmit
+    SList::iterator it = m_slist.begin();
+    while (it->xmit > 0) {
+      ++it;
+      ASSERT(it != m_slist.end());
+    }
+    SList::iterator seg = it;
+
+    // If the segment is too large, break it into two
+    if (seg->len > nAvailable) {
+      SSegment subseg(seg->seq + nAvailable, seg->len - nAvailable, seg->bCtrl);
+      seg->len = nAvailable;
+      m_slist.insert(++it, subseg);
+    }
+
+    if (!transmit(seg, now)) {
+      LOG_F(LS_VERBOSE) << "transmit failed";
+      // TODO: consider closing socket
+      return;
+    }
+
+    sflags = sfNone;
+  }
+}
+
+void
+PseudoTcp::closedown(uint32 err) {
+  m_slen = 0;
+
+  LOG(LS_INFO) << "State: TCP_CLOSED";
+  m_state = TCP_CLOSED;
+  if (m_notify) {
+    m_notify->OnTcpClosed(this, err);
+  }
+  //notify(evClose, err);
+}
+
+void
+PseudoTcp::adjustMTU() {
+  // Determine our current mss level, so that we can adjust appropriately later
+  for (m_msslevel = 0; PACKET_MAXIMUMS[m_msslevel + 1] > 0; ++m_msslevel) {
+    if (static_cast<uint16>(PACKET_MAXIMUMS[m_msslevel]) <= m_mtu_advise) {
+      break;
+    }
+  }
+  m_mss = m_mtu_advise - PACKET_OVERHEAD;
+  // !?! Should we reset m_largest here?
+#if _DEBUGMSG >= _DBG_NORMAL
+  LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes";
+#endif // _DEBUGMSG
+  // Enforce minimums on ssthresh and cwnd
+  m_ssthresh = talk_base::_max(m_ssthresh, 2 * m_mss);
+  m_cwnd = talk_base::_max(m_cwnd, m_mss);
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/pseudotcp.h b/talk/p2p/base/pseudotcp.h
new file mode 100755
index 0000000..cce23e1
--- /dev/null
+++ b/talk/p2p/base/pseudotcp.h
@@ -0,0 +1,182 @@
+/*
+ * 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 __PSEUDOTCP_H__
+#define __PSEUDOTCP_H__
+
+#include <list>
+#include "talk/base/basictypes.h"
+
+namespace cricket {
+
+//////////////////////////////////////////////////////////////////////
+// IPseudoTcpNotify
+//////////////////////////////////////////////////////////////////////
+
+class PseudoTcp;
+
+class IPseudoTcpNotify {
+public:
+  // 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;
+
+  // 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;
+};
+
+//////////////////////////////////////////////////////////////////////
+// PseudoTcp
+//////////////////////////////////////////////////////////////////////
+
+class PseudoTcp {
+public:
+  static uint32 Now();
+
+  PseudoTcp(IPseudoTcpNotify * notify, uint32 conv);
+  virtual ~PseudoTcp();
+
+  int Connect();
+  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 };
+  TcpState State() const { return m_state; }
+
+  // Call this when the PMTU changes.
+  void NotifyMTU(uint16 mtu);
+
+  // Call this based on timeout value returned from GetNextClock.
+  // It's ok to call this too frequently.
+  void NotifyClock(uint32 now);
+
+  // Call this whenever a packet arrives.
+  // Returns true if the packet was processed successfully.
+  bool NotifyPacket(const char * buffer, size_t len);
+
+  // Call this to determine the next time NotifyClock should be called.
+  // Returns false if the socket is ready to be destroyed.
+  bool GetNextClock(uint32 now, long& timeout);
+
+protected:
+  enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck };
+  enum {
+    // Note: can't go as high as 1024 * 64, because of uint16 precision
+    kRcvBufSize = 1024 * 60,
+    // 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;
+    uint8 flags;
+    uint16 wnd;
+    const char * data;
+    uint32 len;
+    uint32 tsval, tsecr;
+  };
+
+  struct SSegment {
+    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;
+
+  struct RSegment {
+    uint32 seq, len;
+  };
+
+  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);
+
+  void attemptSend(SendFlags sflags = sfNone);
+
+  void closedown(uint32 err = 0);
+
+  bool clock_check(uint32 now, long& nTimeout);
+
+  bool process(Segment& seg);
+  bool transmit(const SList::iterator& seg, uint32 now);
+
+  void adjustMTU();
+
+private:
+  IPseudoTcpNotify * m_notify;
+  enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown;
+  int m_error;
+
+  // TCB data
+  TcpState m_state;
+  uint32 m_conv;
+  bool m_bReadEnable, m_bWriteEnable, m_bOutgoing;
+  uint32 m_lasttraffic;
+
+  // Incoming data
+  typedef std::list<RSegment> RList;
+  RList m_rlist;
+  char m_rbuf[kRcvBufSize];
+  uint32 m_rcv_nxt, m_rcv_wnd, m_rlen, m_lastrecv;
+
+  // Outgoing data
+  SList m_slist;
+  char m_sbuf[kSndBufSize];
+  uint32 m_snd_nxt, m_snd_wnd, m_slen, m_lastsend, m_snd_una;
+  // Maximum segment size, estimated protocol level, largest segment sent
+  uint32 m_mss, m_msslevel, m_largest, m_mtu_advise;
+  // Retransmit timer
+  uint32 m_rto_base;
+
+  // Timestamp tracking
+  uint32 m_ts_recent, m_ts_lastack;
+
+  // Round-trip calculation
+  uint32 m_rx_rttvar, m_rx_srtt, m_rx_rto;
+
+  // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs
+  uint32 m_ssthresh, m_cwnd;
+  uint8 m_dup_acks;
+  uint32 m_recover;
+  uint32 m_t_ack;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+} // namespace cricket
+
+#endif // __PSEUDOTCP_H__
diff --git a/talk/p2p/base/rawtransport.cc b/talk/p2p/base/rawtransport.cc
new file mode 100755
index 0000000..f2e230b
--- /dev/null
+++ b/talk/p2p/base/rawtransport.cc
@@ -0,0 +1,150 @@
+/*
+ * 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/p2p/base/rawtransport.h"
+#include "talk/base/common.h"
+#include "talk/p2p/base/constants.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"
+
+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() {
+  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) {
+      talk_base::SocketAddress addr;
+      if (!ParseAddress(stanza, elem, &addr))
+        return false;
+
+      ForwardChannelMessage(elem->Attr(buzz::QN_NAME),
+                            new buzz::XmlElement(*elem));
+    }
+  }
+  return true;
+}
+
+bool RawTransport::OnTransportError(const buzz::XmlElement* session_msg,
+                                    const buzz::XmlElement* error) {
+  return true;
+}
+
+bool RawTransport::ParseAddress(const buzz::XmlElement* stanza,
+                                const buzz::XmlElement* elem,
+                                talk_base::SocketAddress* addr) {
+  // 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);
+  }
+
+  // Make sure the channel named actually exists.
+  if (!HasChannel(elem->Attr(buzz::QN_NAME)))
+    return BadRequest(stanza, "channel named does not exist", NULL);
+
+  // Parse the address.
+  return Transport::ParseAddress(stanza, elem, addr);
+}
+
+TransportChannelImpl* RawTransport::CreateTransportChannel(
+    const std::string& name, const std::string &session_type) {
+  return new RawTransportChannel(
+     name, session_type, this, session_manager()->port_allocator());
+}
+
+void RawTransport::DestroyTransportChannel(TransportChannelImpl* channel) {
+  delete channel;
+}
+
+}  // namespace cricket
diff --git a/talk/p2p/base/rawtransport.h b/talk/p2p/base/rawtransport.h
new file mode 100755
index 0000000..d273b40
--- /dev/null
+++ b/talk/p2p/base/rawtransport.h
@@ -0,0 +1,84 @@
+/*
+ * 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 _CRICKET_P2P_BASE_RAWTRANSPORT_H_
+#define _CRICKET_P2P_BASE_RAWTRANSPORT_H_
+
+#include "talk/p2p/base/transport.h"
+
+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 {
+ public:
+  RawTransport(SessionManager* session_manager);
+  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);
+
+ protected:
+  // Creates and destroys raw channels.
+  virtual TransportChannelImpl* CreateTransportChannel(
+     const std::string& name, const std::string &session_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);
+
+  friend class RawTransportChannel;  // For ParseAddress.
+
+  DISALLOW_EVIL_CONSTRUCTORS(RawTransport);
+};
+
+}  // namespace cricket
+
+
+#endif  // _CRICKET_P2P_BASE_RAWTRANSPORT_H_
diff --git a/talk/p2p/base/rawtransportchannel.cc b/talk/p2p/base/rawtransportchannel.cc
new file mode 100755
index 0000000..13c1886
--- /dev/null
+++ b/talk/p2p/base/rawtransportchannel.cc
@@ -0,0 +1,259 @@
+/*
+ * 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/p2p/base/rawtransportchannel.h"
+#include "talk/base/common.h"
+#include "talk/p2p/base/constants.h"
+#include "talk/p2p/base/port.h"
+#include "talk/p2p/base/portallocator.h"
+#include "talk/p2p/base/rawtransport.h"
+#include "talk/p2p/base/relayport.h"
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/base/stunport.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/constants.h"
+
+namespace {
+
+const int 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() {
+  delete allocator_session_;
+}
+
+int RawTransportChannel::SendPacket(const char *data, size_t size) {
+  if (port_ == NULL)
+    return -1;
+  if (remote_address_.IsAny())
+    return -1;
+  return port_->SendTo(data, size, remote_address_, true);
+}
+
+int RawTransportChannel::SetOption(talk_base::Socket::Option opt, int value) {
+  // TODO: allow these to be set before we have a port
+  if (port_ == NULL)
+    return -1;
+  return port_->SetOption(opt, value);
+}
+
+int RawTransportChannel::GetError() {
+  return (port_ != NULL) ? port_->GetError() : 0;
+}
+
+void RawTransportChannel::Connect() {
+  // Create an allocator that only returns stun and relay ports.
+  allocator_session_ = allocator_->CreateSession(name(), session_type());
+
+  uint32 flags = PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP;
+
+#if !defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
+  flags |= PORTALLOCATOR_DISABLE_RELAY;
+#endif
+  allocator_session_->set_flags(flags);
+  allocator_session_->SignalPortReady.connect(
+      this, &RawTransportChannel::OnPortReady);
+  allocator_session_->SignalCandidatesReady.connect(
+      this, &RawTransportChannel::OnCandidatesReady);
+
+  // The initial ports will include stun.
+  allocator_session_->GetInitialPorts();
+}
+
+void RawTransportChannel::Reset() {
+  set_readable(false);
+  set_writable(false);
+
+  delete allocator_session_;
+
+  allocator_session_ = NULL;
+  stun_port_ = NULL;
+  relay_port_ = NULL;
+  port_ = NULL;
+  remote_address_ = talk_base::SocketAddress();
+}
+
+void RawTransportChannel::OnChannelMessage(const buzz::XmlElement* msg) {
+  bool valid = raw_transport_->ParseAddress(NULL, msg, &remote_address_);
+  ASSERT(valid);
+  ASSERT(!remote_address_.IsAny());
+  set_readable(true);
+
+  // We can write once we have a port and a remote address.
+  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.  
+//
+// Another option is to classify the NAT type early and not offer the raw
+// transport type at all if we can't support it.
+
+void RawTransportChannel::OnPortReady(
+    PortAllocatorSession* session, Port* port) {
+  ASSERT(session == allocator_session_);
+
+  if (port->type() == STUN_PORT_TYPE) {
+    stun_port_ = static_cast<StunPort*>(port);
+
+#if defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
+    // We need a secondary address to determine the NAT type.
+    stun_port_->PrepareSecondaryAddress();
+#endif
+  } else if (port->type() == RELAY_PORT_TYPE) {
+    relay_port_ = static_cast<RelayPort*>(port);
+  } else {
+    ASSERT(false);
+  }
+}
+
+void RawTransportChannel::OnCandidatesReady(
+    PortAllocatorSession *session, const std::vector<Candidate>& candidates) {
+  ASSERT(session == allocator_session_);
+  ASSERT(candidates.size() >= 1);
+
+  // The most recent candidate is the one we haven't seen yet.
+  Candidate c = candidates[candidates.size() - 1];
+
+  if (c.type() == STUN_PORT_TYPE) {
+    ASSERT(stun_port_ != NULL);
+
+#if defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
+    // We need to wait until we have two addresses.
+    if (stun_port_->candidates().size() < 2)
+      return;
+
+    // This is the second address.  If these addresses are the same, then we
+    // are not behind a symmetric NAT.  Hence, a stun port should be sufficient.
+    if (stun_port_->candidates()[0].address() ==
+        stun_port_->candidates()[1].address()) {
+      SetPort(stun_port_);
+      return;
+    }
+
+    // We will need to use relay.
+    use_relay_ = true;
+
+    // If we weren't given a relay port, we'll need to request it.
+    if (relay_port_ == NULL) {
+      allocator_session_->StartGetAllPorts();
+      return;
+    }
+
+    // If we already have a relay address, we're good.  Otherwise, we will need
+    // to wait until one arrives.
+    if (relay_port_->candidates().size() > 0)
+      SetPort(relay_port_);
+#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_);
+#endif
+  } else if (c.type() == RELAY_PORT_TYPE) {
+    if (use_relay_)
+      SetPort(relay_port_);
+  } else {
+    ASSERT(false);
+  }
+}
+
+void RawTransportChannel::SetPort(Port* port) {
+  ASSERT(port_ == NULL);
+  port_ = port;
+
+  // We don't need any ports other than the one we picked.
+  allocator_session_->StopGetAllPorts();
+  raw_transport_->session_manager()->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);
+
+  // Read all packets from this port.
+  port_->EnablePortPackets();
+  port_->SignalReadPacket.connect(this, &RawTransportChannel::OnReadPacket);
+
+  // We can write once we have a port and a remote address.
+  if (!remote_address_.IsAny())
+    SetWritable();
+}
+
+void RawTransportChannel::SetWritable() {
+  ASSERT(port_ != NULL);
+  ASSERT(!remote_address_.IsAny());
+
+  set_writable(true);
+
+  SignalRouteChange(this, remote_address_);
+}
+
+void RawTransportChannel::OnReadPacket(
+    Port* port, const char* data, size_t size, 
+    const talk_base::SocketAddress& addr) {
+  ASSERT(port_ == port);
+  SignalReadPacket(this, data, size);
+}
+
+void RawTransportChannel::OnMessage(talk_base::Message* msg) {
+  ASSERT(msg->message_id == MSG_DESTROY_UNUSED_PORTS);
+  ASSERT(port_ != NULL);
+  if (port_ != stun_port_) {
+    stun_port_->Destroy();
+    stun_port_ = NULL;
+  }
+  if (port_ != relay_port_ && relay_port_ != NULL) {
+    relay_port_->Destroy();
+    relay_port_ = NULL;
+  }
+}
+
+}  // namespace cricket
diff --git a/talk/p2p/base/rawtransportchannel.h b/talk/p2p/base/rawtransportchannel.h
new file mode 100755
index 0000000..9dcbae2
--- /dev/null
+++ b/talk/p2p/base/rawtransportchannel.h
@@ -0,0 +1,117 @@
+/*
+ * 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 _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_
+#define _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_
+
+#include "talk/base/messagequeue.h"
+#include "talk/p2p/base/transportchannelimpl.h"
+#include "talk/p2p/base/rawtransport.h"
+#include "talk/p2p/base/candidate.h"
+
+namespace cricket {
+
+class Port;
+class Connection;
+class StunPort;
+class RelayPort;
+class PortAllocator;
+class PortAllocatorSession;
+
+// 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, 
+    public talk_base::MessageHandler {
+ public:
+  RawTransportChannel(const std::string &name,
+		      const std::string &session_type,
+                      RawTransport* transport,
+                      PortAllocator *allocator);
+  virtual ~RawTransportChannel();
+
+  // Implementation of normal channel packet sending.
+  virtual int SendPacket(const char *data, size_t len);
+  virtual int SetOption(talk_base::Socket::Option opt, int value);
+  virtual int GetError();
+
+  // 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.
+  virtual void Connect();
+
+  // Resets state back to unconnected.
+  virtual void Reset();
+
+  // We don't actually worry about signaling since we can't send new candidates.
+  virtual void OnSignalingReady() {}
+
+  // 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);
+
+ private:
+  RawTransport* raw_transport_;
+  PortAllocator* allocator_;
+  PortAllocatorSession* allocator_session_;
+  StunPort* stun_port_;
+  RelayPort* relay_port_;
+  Port* port_;
+  bool use_relay_;
+  talk_base::SocketAddress remote_address_;
+
+  // Called when the allocator creates another port.
+  void OnPortReady(PortAllocatorSession* session, Port* port);
+
+  // Called when one of the ports we are using has determined its address.
+  void OnCandidatesReady(PortAllocatorSession *session,
+                         const std::vector<Candidate>& candidates);
+
+  // Called once we have chosen the port to use for communication with the
+  // other client.  This will send its address and prepare the port for use.
+  void SetPort(Port* port);
+
+  // Called once we have a port and a remote address.  This will set mark the
+  // channel as writable and signal the route to the client.
+  void SetWritable();
+
+  // Called when we receive a packet from the other client.
+  void OnReadPacket(Port* port, const char* data, size_t size,
+                    const talk_base::SocketAddress& addr);
+
+  // Handles a message to destroy unused ports.
+  virtual void OnMessage(talk_base::Message *msg);
+
+  DISALLOW_EVIL_CONSTRUCTORS(RawTransportChannel);
+};
+
+}  // namespace cricket
+
+#endif  // _CRICKET_P2P_BASE_RAWTRANSPORTCHANNEL_H_
diff --git a/talk/p2p/base/relayport.cc b/talk/p2p/base/relayport.cc
new file mode 100755
index 0000000..a8a0527
--- /dev/null
+++ b/talk/p2p/base/relayport.cc
@@ -0,0 +1,634 @@
+/*
+ * 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.
+ */
+
+#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/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
+
+// 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);
+  ~RelayEntry();
+
+  RelayPort* port() { return port_; }
+
+  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(); }
+
+  // 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);
+
+  // 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, 
+    const talk_base::SocketAddress& addr);
+
+  // Schedules a keep-alive allocate request.
+  void ScheduleKeepAlive();
+
+  void SetServerIndex(size_t sindex) { server_index_ = sindex; }
+  size_t ServerIndex() const { return server_index_; }
+
+  // Try a different server address
+  void HandleConnectFailure();
+
+private:
+  RelayPort* port_;
+  talk_base::SocketAddress ext_addr_, local_addr_;
+  size_t server_index_;
+  talk_base::AsyncPacketSocket* socket_;
+  bool connected_;
+  bool locked_;
+  StunRequestManager requests_;
+
+  // Called when a TCP connection is established or fails
+  void OnSocketConnect(talk_base::AsyncTCPSocket* socket);
+  void OnSocketClose(talk_base::AsyncTCPSocket* socket, int error);
+
+  // Called when a packet is received on this socket.
+  void OnReadPacket(
+      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);
+};
+
+// Handles an allocate request for a particular RelayEntry.
+class AllocateRequest : public StunRequest {
+public:
+  AllocateRequest(RelayEntry* entry);
+  virtual ~AllocateRequest() {}
+
+  virtual void Prepare(StunMessage* request);
+
+  virtual int GetNextDelay();
+
+  virtual void OnResponse(StunMessage* response);
+  virtual void OnErrorResponse(StunMessage* response);
+  virtual void OnTimeout();
+
+private:
+  RelayEntry* entry_;
+  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, 
+    const std::string& magic_cookie)
+  : 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_));
+
+  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)
+    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))) {
+    server_addr_.push_front(addr);
+  } else {
+    server_addr_.push_back(addr);
+  }
+}
+
+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) {
+    if ((it->address() == addr.address) && (it->protocol() == proto_name)) {
+      LOG(INFO) << "Redundant relay address: " << proto_name << " @ " << addr.address.ToString();
+      return;
+    }
+  }
+  AddAddress(addr.address, proto_name, false);
+}
+
+void RelayPort::SetReady() {
+  if (!ready_) {
+    ready_ = true;
+    SignalAddressReady(this);
+  }
+}
+
+const ProtocolAddress * RelayPort::ServerAddress(size_t index) const {
+  if ((index >= 0) && (index < server_addr_.size()))
+    return &server_addr_[index];
+  return 0;
+}
+
+bool RelayPort::HasMagicCookie(const char* data, size_t size) {
+  if (size < 24 + magic_cookie_.size()) {
+    return false;
+  } else {
+    return 0 == std::memcmp(data + 24,
+                            magic_cookie_.c_str(),
+                            magic_cookie_.size());
+  }
+}
+
+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);
+  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))
+    return 0;
+
+  // We don't support loopback on relays
+  if (address.type() == type())
+    return 0;
+
+  size_t index = 0;
+  for (size_t i = 0; i < candidates().size(); ++i) {
+    const Candidate& local = candidates()[i];
+    if (local.protocol() == address.protocol()) {
+      index = i;
+      break;
+    }
+  }
+
+  Connection * conn = new ProxyConnection(this, index, address);
+  AddConnection(conn);
+  return conn;
+}
+
+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) {
+    if (entries_[i]->address().IsAny() && payload) {
+      entry = entries_[i];
+      entry->set_address(addr);
+      break;
+    } else if (entries_[i]->address() == addr) {
+      entry = entries_[i];
+      break;
+    }
+  }
+
+  // If we did not find one, then we make a new one.  This will not be useable
+  // until it becomes connected, however.
+  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();
+    entries_.push_back(entry);
+  }
+
+  // If the entry is connected, then we can send on it (though wrapping may
+  // 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());
+    entry = entries_[0];
+    if (!entry->connected()) {
+      error_ = EWOULDBLOCK;
+      return SOCKET_ERROR;
+    }
+  }
+
+  // Send the actual contents to the server using the usual mechanism.
+  int sent = entry->SendTo(data, size, addr);
+  if (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;
+}
+
+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) {
+      result = -1;
+      error_ = entries_[i]->socket()->GetError();
+    }
+  }
+  options_.push_back(OptionValue(opt, value));
+  return result;
+}
+
+int RelayPort::GetError() {
+  return error_;
+}
+
+void RelayPort::OnReadPacket(
+    const char* data, size_t size, 
+    const talk_base::SocketAddress& remote_addr) {
+  if (Connection* conn = GetConnection(remote_addr)) {
+    conn->OnReadPacket(data, size);
+  } else {
+    Port::OnReadPacket(data, size, remote_addr);
+  }
+}
+
+void RelayPort::DisposeSocket(talk_base::AsyncPacketSocket * socket) {
+  thread_->Dispose(socket);
+}
+
+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() {
+  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;
+  }
+
+  LOG(INFO) << "Connecting to relay via " << ProtoToString(ra->proto) << " @ " << ra->address.ToString();
+
+  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 RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr) {
+  ProtocolType proto = PROTO_UDP;
+  LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto) << " @ " << mapped_addr.ToString();
+  connected_ = true;
+
+  port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto));
+  port_->SetReady();
+}
+
+int RelayEntry::SendTo(const void* data, size_t size,
+                        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))
+    return SendPacket(data, size);
+
+  // Otherwise, we must wrap the given data in a STUN SEND request so that we
+  // can communicate the destination address to the server.
+  //
+  // Note that we do not use a StunRequest here.  This is because there is
+  // likely no reason to resend this packet. If it is late, we just drop it.
+  // The next send to this address will try again.
+
+  StunMessage request;
+  request.SetType(STUN_SEND_REQUEST);
+  request.SetTransactionID(CreateRandomString(16));
+
+  StunByteStringAttribute* magic_cookie_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
+  magic_cookie_attr->CopyBytes(port_->magic_cookie().c_str(),
+                               (uint16)port_->magic_cookie().size());
+  request.AddAttribute(magic_cookie_attr);
+
+  StunByteStringAttribute* username_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  username_attr->CopyBytes(port_->username_fragment().c_str(),
+                           (uint16)port_->username_fragment().size());
+  request.AddAttribute(username_attr);
+
+  StunAddressAttribute* addr_attr =
+      StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
+  addr_attr->SetFamily(1);
+  addr_attr->SetIP(addr.ip());
+  addr_attr->SetPort(addr.port());
+  request.AddAttribute(addr_attr);
+
+  // Attempt to lock
+  if (ext_addr_ == addr) {
+    StunUInt32Attribute* options_attr =
+      StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS);
+    options_attr->SetValue(0x1);
+    request.AddAttribute(options_attr);
+  }
+
+  StunByteStringAttribute* data_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_DATA);
+  data_attr->CopyBytes(data, (uint16)size);
+  request.AddAttribute(data_attr);
+
+  // TODO: compute the HMAC.
+
+  talk_base::ByteBuffer buf;
+  request.Write(&buf);
+
+  return SendPacket(buf.Data(), buf.Length());
+}
+
+void RelayEntry::ScheduleKeepAlive() {
+  requests_.SendDelayed(new AllocateRequest(this), KEEPALIVE_DELAY);
+}
+
+void RelayEntry::HandleConnectFailure() {
+  //if (GetMillisecondCount() - start_time_ > RETRY_TIMEOUT)
+  //  return;
+  //ScheduleKeepAlive();
+
+  connected_ = false;
+  port()->DisposeSocket(socket_);
+  socket_ = 0;
+  requests_.Clear();
+
+  server_index_ += 1;
+  Connect();
+}
+
+void RelayEntry::OnSocketConnect(talk_base::AsyncTCPSocket* socket) {
+  assert(socket == socket_);
+  LOG(INFO) << "relay tcp connected to " << socket->GetRemoteAddress().ToString();
+  requests_.Send(new AllocateRequest(this));
+}
+
+void RelayEntry::OnSocketClose(talk_base::AsyncTCPSocket* socket, int error) {
+  assert(socket == socket_);
+  PLOG(LERROR, error) << "relay tcp connect failed";
+  HandleConnectFailure();
+}
+
+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?
+
+  // 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.
+  if (!port_->HasMagicCookie(data, size)) {
+    if (locked_) {
+      port_->OnReadPacket(data, size, ext_addr_);
+    } else {
+      LOG(WARNING) << "Dropping packet: entry not locked";
+    }
+    return;
+  }
+
+  talk_base::ByteBuffer buf(data, size);
+  StunMessage msg;
+  if (!msg.Read(&buf)) {
+    LOG(INFO) << "Incoming packet was not STUN";
+    return;
+  }
+
+  // The incoming packet should be a STUN ALLOCATE response, SEND response, or
+  // DATA indication.
+  if (requests_.CheckResponse(&msg)) {
+    return;
+  } else if (msg.type() == STUN_SEND_RESPONSE) {
+    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()
+             ;
+    return;
+  }
+
+  // This must be a data indication.
+
+  const StunAddressAttribute* addr_attr =
+      msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
+  if (!addr_attr) {
+    LOG(INFO) << "Data indication has no source address";
+    return;
+  } else if (addr_attr->family() != 1) {
+    LOG(INFO) << "Source address has bad family";
+    return;
+  }
+
+  talk_base::SocketAddress remote_addr2(addr_attr->ip(), addr_attr->port());
+
+  const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA);
+  if (!data_attr) {
+    LOG(INFO) << "Data indication has no data";
+    return;
+  }
+
+  // Process the actual data and remote address in the normal manner.
+  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);
+  }
+  return sent;
+}
+
+AllocateRequest::AllocateRequest(RelayEntry* entry) : entry_(entry) {
+  start_time_ = talk_base::GetMillisecondCount();
+}
+
+void AllocateRequest::Prepare(StunMessage* request) {
+  request->SetType(STUN_ALLOCATE_REQUEST);
+
+  StunByteStringAttribute* magic_cookie_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
+  magic_cookie_attr->CopyBytes(
+      entry_->port()->magic_cookie().c_str(),
+      (uint16)entry_->port()->magic_cookie().size());
+  request->AddAttribute(magic_cookie_attr);
+
+  StunByteStringAttribute* username_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  username_attr->CopyBytes(
+      entry_->port()->username_fragment().c_str(),
+      (uint16)entry_->port()->username_fragment().size());
+  request->AddAttribute(username_attr);
+}
+
+int AllocateRequest::GetNextDelay() {
+  int delay = 100 * talk_base::_max(1 << count_, 2);
+  count_ += 1;
+  if (count_ == 5)
+    timeout_ = true;
+  return delay;
+}
+
+void AllocateRequest::OnResponse(StunMessage* response) {
+  const StunAddressAttribute* addr_attr =
+      response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
+  if (!addr_attr) {
+    LOG(INFO) << "Allocate response missing mapped address.";
+  } else if (addr_attr->family() != 1) {
+    LOG(INFO) << "Mapped address has bad family";
+  } else {
+    talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port());
+    entry_->OnConnect(addr);
+  }
+
+  // We will do a keep-alive regardless of whether this request suceeds.
+  // This should have almost no impact on network usage.
+  entry_->ScheduleKeepAlive();
+}
+
+void AllocateRequest::OnErrorResponse(StunMessage* response) {
+  const StunErrorCodeAttribute* attr = response->GetErrorCode();
+  if (!attr) {
+    LOG(INFO) << "Bad allocate response error code";
+  } else {
+    LOG(INFO) << "Allocate error response:"
+              << " code=" << static_cast<int>(attr->error_code())
+              << " reason='" << attr->reason() << "'";
+  }
+
+  if (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)
+    entry_->ScheduleKeepAlive();
+}
+
+void AllocateRequest::OnTimeout() {
+  LOG(INFO) << "Allocate request timed out";
+  entry_->HandleConnectFailure();
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/relayport.h b/talk/p2p/base/relayport.h
new file mode 100755
index 0000000..5691a6c
--- /dev/null
+++ b/talk/p2p/base/relayport.h
@@ -0,0 +1,94 @@
+/*
+ * 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 __RELAYPORT_H__
+#define __RELAYPORT_H__
+
+#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;
+
+// Communicates using an allocated port on the relay server.
+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);
+  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 int SetOption(talk_base::Socket::Option opt, int value);
+  virtual int GetError();
+
+  const ProtocolAddress * ServerAddress(size_t index) const;
+
+  void DisposeSocket(talk_base::AsyncPacketSocket * socket);
+
+protected:
+  void SetReady();
+
+  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);
+
+private:
+  friend class RelayEntry;
+
+  talk_base::SocketAddress local_addr_;
+  std::deque<ProtocolAddress> server_addr_;
+  bool ready_;
+  std::vector<RelayEntry*> entries_;
+  std::vector<OptionValue> options_;
+  std::string magic_cookie_;
+  int error_;
+};
+
+} // namespace cricket
+
+#endif // __RELAYPORT_H__
diff --git a/talk/p2p/base/relayserver.cc b/talk/p2p/base/relayserver.cc
new file mode 100755
index 0000000..1f4a979
--- /dev/null
+++ b/talk/p2p/base/relayserver.cc
@@ -0,0 +1,671 @@
+/*
+ * 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/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
+
+namespace cricket {
+
+// By default, we require a ping every 90 seconds.
+const int MAX_LIFETIME = 15 * 60 * 1000;
+
+// The number of bytes in each of the usernames we use.
+const uint32 USERNAME_LENGTH = 16;
+
+// 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;
+  } else if (result < 0) {
+    std::cerr << "SendTo: " << std::strerror(errno) << std::endl;
+  }
+}
+
+// Sends the given STUN message on the given socket.
+void SendStun(const StunMessage& msg,
+              talk_base::AsyncPacketSocket* socket,
+              const talk_base::SocketAddress& addr) {
+  talk_base::ByteBuffer buf;
+  msg.Write(&buf);
+  Send(socket, buf.Data(), buf.Length(), addr);
+}
+
+// Constructs a STUN error response and sends it on the given socket.
+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());
+
+  StunByteStringAttribute* magic_cookie_attr =
+      StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
+  if (magic_cookie.size() == 0)
+    magic_cookie_attr->CopyBytes(cricket::STUN_MAGIC_COOKIE_VALUE, 4);
+  else
+    magic_cookie_attr->CopyBytes(magic_cookie.c_str(), magic_cookie.size());
+  err_msg.AddAttribute(magic_cookie_attr);
+
+  StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode();
+  err_code->SetErrorClass(error_code / 100);
+  err_code->SetNumber(error_code % 100);
+  err_code->SetReason(error_desc);
+  err_msg.AddAttribute(err_code);
+
+  SendStun(err_msg, socket, remote_addr);
+}
+
+RelayServer::RelayServer(talk_base::Thread* thread)
+  : thread_(thread), log_bindings_(true) {
+}
+
+RelayServer::~RelayServer() {
+  for (unsigned i = 0; i < internal_sockets_.size(); i++)
+    delete internal_sockets_[i];
+  for (unsigned i = 0; i < external_sockets_.size(); i++)
+    delete external_sockets_[i];
+}
+
+void RelayServer::AddInternalSocket(talk_base::AsyncPacketSocket* socket) {
+  assert(internal_sockets_.end() ==
+      std::find(internal_sockets_.begin(), internal_sockets_.end(), socket));
+  internal_sockets_.push_back(socket);
+  socket->SignalReadPacket.connect(this, &RelayServer::OnInternalPacket);
+}
+
+void RelayServer::RemoveInternalSocket(talk_base::AsyncPacketSocket* socket) {
+  SocketList::iterator iter =
+      std::find(internal_sockets_.begin(), internal_sockets_.end(), socket);
+  assert(iter != internal_sockets_.end());
+  internal_sockets_.erase(iter);
+  socket->SignalReadPacket.disconnect(this);
+}
+
+void RelayServer::AddExternalSocket(talk_base::AsyncPacketSocket* socket) {
+  assert(external_sockets_.end() ==
+      std::find(external_sockets_.begin(), external_sockets_.end(), socket));
+  external_sockets_.push_back(socket);
+  socket->SignalReadPacket.connect(this, &RelayServer::OnExternalPacket);
+}
+
+void RelayServer::RemoveExternalSocket(talk_base::AsyncPacketSocket* socket) {
+  SocketList::iterator iter =
+      std::find(external_sockets_.begin(), external_sockets_.end(), socket);
+  assert(iter != external_sockets_.end());
+  external_sockets_.erase(iter);
+  socket->SignalReadPacket.disconnect(this);
+}
+
+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());
+
+  // If this did not come from an existing connection, it should be a STUN
+  // allocate request.
+  ConnectionMap::iterator piter = connections_.find(ap);
+  if (piter == connections_.end()) {
+    HandleStunAllocate(bytes, size, ap, socket);
+    return;
+  }
+
+  RelayServerConnection* int_conn = piter->second;
+
+  // Handle STUN requests to the server itself.
+  if (int_conn->binding()->HasMagicCookie(bytes, size)) {
+    HandleStun(int_conn, bytes, size);
+    return;
+  }
+
+  // Otherwise, this is a non-wrapped packet that we are to forward.  Make sure
+  // 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;
+    return;
+  }
+
+  // Forward this to the destination address into the connection.
+  RelayServerConnection* ext_conn = int_conn->binding()->GetExternalConnection(
+      int_conn->default_destination());
+  if (ext_conn && ext_conn->locked()) {
+    // TODO: Check the HMAC.
+    ext_conn->Send(bytes, size);
+  } else {
+    // This happens very often and is not an error.
+    //std::cerr << "Dropping packet: no external connection" << std::endl;
+  }
+}
+
+void RelayServer::OnExternalPacket(
+    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());
+
+  // If this connection already exists, then forward the traffic.
+  ConnectionMap::iterator piter = connections_.find(ap);
+  if (piter != connections_.end()) {
+    // TODO: Check the HMAC.
+    RelayServerConnection* ext_conn = piter->second;
+    RelayServerConnection* int_conn =
+        ext_conn->binding()->GetInternalConnection(
+            ext_conn->addr_pair().source());
+    assert(int_conn);
+    int_conn->Send(bytes, size, ext_conn->addr_pair().source());
+    ext_conn->Lock();  // allow outgoing packets
+    return;
+  }
+
+  // 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);
+  if (!msg.Read(&buf)) {
+    std::cerr << "Dropping packet: first packet not STUN" << std::endl;
+    return;
+  }
+
+  // The initial packet should have a username (which identifies the binding).
+  const StunByteStringAttribute* username_attr =
+      msg.GetByteString(STUN_ATTR_USERNAME);
+  if (!username_attr) {
+    std::cerr << "Dropping packet: no username" << std::endl;
+    return;
+  }
+
+  uint32 length = talk_base::_min(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;
+    return;
+  }
+
+  // Add this authenticted connection to the binding.
+  RelayServerConnection* ext_conn =
+      new RelayServerConnection(biter->second, ap, socket);
+  ext_conn->binding()->AddExternalConnection(ext_conn);
+  AddConnection(ext_conn);
+
+  // We always know where external packets should be forwarded, so we can lock
+  // them from the beginning.
+  ext_conn->Lock();
+
+  // Send this message on the appropriate internal connection.
+  RelayServerConnection* int_conn = ext_conn->binding()->GetInternalConnection(
+      ext_conn->addr_pair().source());
+  assert(int_conn);
+  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) {
+
+  // Parse this into a stun message.
+  talk_base::ByteBuffer buf = talk_base::ByteBuffer(bytes, size);
+  if (!msg->Read(&buf)) {
+    SendStunError(*msg, socket, remote_addr, 400, "Bad Request", "");
+    return false;
+  }
+
+  // The initial packet should have a username (which identifies the binding).
+  const StunByteStringAttribute* username_attr =
+      msg->GetByteString(STUN_ATTR_USERNAME);
+  if (!username_attr) {
+    SendStunError(*msg, socket, remote_addr, 432, "Missing Username", "");
+    return false;
+  }
+
+  // Record the username if requested.
+  if (username)
+    username->append(username_attr->bytes(), username_attr->length());
+
+  // TODO: Check for unknown attributes (<= 0x7fff)
+
+  return true;
+}
+
+void RelayServer::HandleStunAllocate(
+    const char* bytes, size_t size, const talk_base::SocketAddressPair& ap,
+    talk_base::AsyncPacketSocket* socket) {
+
+  // Make sure this is a valid STUN request.
+  StunMessage request;
+  std::string username;
+  if (!HandleStun(bytes, size, ap.source(), socket, &username, &request))
+    return;
+
+  // Make sure this is a an allocate request.
+  if (request.type() != STUN_ALLOCATE_REQUEST) {
+    SendStunError(request,
+                  socket,
+                  ap.source(),
+                  600,
+                  "Operation Not Supported",
+                  "");
+    return;
+  }
+
+  // TODO: Check the HMAC.
+
+  // Find or create the binding for this username.
+
+  RelayServerBinding* binding;
+
+  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.
+
+    // Compute the appropriate lifetime for this binding.
+    uint32 lifetime = MAX_LIFETIME;
+    const StunUInt32Attribute* lifetime_attr =
+        request.GetUInt32(STUN_ATTR_LIFETIME);
+    if (lifetime_attr)
+      lifetime = talk_base::_min(lifetime, lifetime_attr->value() * 1000);
+
+    binding = new RelayServerBinding(this, username, "0", lifetime);
+    binding->SignalTimeout.connect(this, &RelayServer::OnTimeout);
+    bindings_[username] = binding;
+
+    if (log_bindings_) {
+      std::cout << "Added new binding: " << bindings_.size() << " total"
+                << std::endl;
+    }
+  }
+
+  // Add this connection to the binding.  It starts out unlocked.
+  RelayServerConnection* int_conn =
+      new RelayServerConnection(binding, ap, socket);
+  binding->AddInternalConnection(int_conn);
+  AddConnection(int_conn);
+
+  // Now that we have a connection, this other method takes over.
+  HandleStunAllocate(int_conn, request);
+}
+
+void RelayServer::HandleStun(
+    RelayServerConnection* int_conn, const char* bytes, size_t size) {
+
+  // Make sure this is a valid STUN request.
+  StunMessage request;
+  std::string username;
+  if (!HandleStun(bytes, size, int_conn->addr_pair().source(),
+                  int_conn->socket(), &username, &request))
+    return;
+
+  // Make sure the username is the one were were expecting.
+  if (username != int_conn->binding()->username()) {
+    int_conn->SendStunError(request, 430, "Stale Credentials");
+    return;
+  }
+
+  // TODO: Check the HMAC.
+
+  // Send this request to the appropriate handler.
+  if (request.type() == STUN_SEND_REQUEST)
+    HandleStunSend(int_conn, request);
+  else if (request.type() == STUN_ALLOCATE_REQUEST)
+    HandleStunAllocate(int_conn, request);
+  else
+    int_conn->SendStunError(request, 600, "Operation Not Supported");
+}
+
+void RelayServer::HandleStunAllocate(
+    RelayServerConnection* int_conn, const StunMessage& request) {
+
+  // Create a response message that includes an address with which external
+  // clients can communicate.
+
+  StunMessage response;
+  response.SetType(STUN_ALLOCATE_RESPONSE);
+  response.SetTransactionID(request.transaction_id());
+
+  StunByteStringAttribute* magic_cookie_attr =
+      StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
+  magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
+                               int_conn->binding()->magic_cookie().size());
+  response.AddAttribute(magic_cookie_attr);
+
+  size_t index = rand() % external_sockets_.size();
+  talk_base::SocketAddress ext_addr = external_sockets_[index]->GetLocalAddress();
+
+  StunAddressAttribute* addr_attr =
+      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  addr_attr->SetFamily(1);
+  addr_attr->SetIP(ext_addr.ip());
+  addr_attr->SetPort(ext_addr.port());
+  response.AddAttribute(addr_attr);
+
+  StunUInt32Attribute* res_lifetime_attr =
+      StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
+  res_lifetime_attr->SetValue(int_conn->binding()->lifetime() / 1000);
+  response.AddAttribute(res_lifetime_attr);
+
+  // TODO: Support transport-prefs (preallocate RTCP port).
+  // TODO: Support bandwidth restrictions.
+  // TODO: Add message integrity check.
+
+  // Send a response to the caller.
+  int_conn->SendStun(response);
+}
+
+void RelayServer::HandleStunSend(
+    RelayServerConnection* int_conn, const StunMessage& request) {
+
+  const StunAddressAttribute* addr_attr =
+      request.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
+  if (!addr_attr) {
+    int_conn->SendStunError(request, 400, "Bad Request");
+    return;
+  }
+
+  const StunByteStringAttribute* data_attr =
+      request.GetByteString(STUN_ATTR_DATA);
+  if (!data_attr) {
+    int_conn->SendStunError(request, 400, "Bad Request");
+    return;
+  }
+
+  talk_base::SocketAddress ext_addr(addr_attr->ip(), addr_attr->port());
+  RelayServerConnection* ext_conn =
+      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);
+    talk_base::AsyncPacketSocket* socket = external_sockets_[0];
+    talk_base::SocketAddressPair ap(ext_addr, socket->GetLocalAddress());
+    ext_conn = new RelayServerConnection(int_conn->binding(), ap, socket);
+    ext_conn->binding()->AddExternalConnection(ext_conn);
+    AddConnection(ext_conn);
+  }
+
+  // If this connection has pinged us, then allow outgoing traffic.
+  if (ext_conn->locked())
+    ext_conn->Send(data_attr->bytes(), data_attr->length());
+
+  const StunUInt32Attribute* options_attr =
+      request.GetUInt32(STUN_ATTR_OPTIONS);
+  if (options_attr && (options_attr->value() & 0x01 != 0)) {
+    int_conn->set_default_destination(ext_addr);
+    int_conn->Lock();
+
+    StunMessage response;
+    response.SetType(STUN_SEND_RESPONSE);
+    response.SetTransactionID(request.transaction_id());
+
+    StunByteStringAttribute* magic_cookie_attr =
+        StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
+    magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
+                                 int_conn->binding()->magic_cookie().size());
+    response.AddAttribute(magic_cookie_attr);
+
+    StunUInt32Attribute* options2_attr =
+      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());
+  connections_[conn->addr_pair()] = conn;
+}
+
+void RelayServer::RemoveConnection(RelayServerConnection* conn) {
+  ConnectionMap::iterator iter = connections_.find(conn->addr_pair());
+  assert(iter != connections_.end());
+  connections_.erase(iter);
+}
+
+void RelayServer::RemoveBinding(RelayServerBinding* binding) {
+  BindingMap::iterator iter = bindings_.find(binding->username());
+  assert(iter != bindings_.end());
+  bindings_.erase(iter);
+
+  if (log_bindings_) {
+    std::cout << "Removed a binding: " << bindings_.size() << " remaining"
+              << std::endl;
+  }
+}
+
+void RelayServer::OnTimeout(RelayServerBinding* binding) {
+  // This call will result in all of the necessary clean-up.
+  delete binding;
+}
+
+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();
+}
+
+RelayServerConnection::~RelayServerConnection() {
+  // Remove this connection from the server's map (if it exists there).
+  binding_->server()->RemoveConnection(this);
+}
+
+void RelayServerConnection::Send(const char* data, size_t size) {
+  // Note that the binding has been used again.
+  binding_->NoteUsed();
+
+  cricket::Send(socket_, data, size, addr_pair_.source());
+}
+
+void RelayServerConnection::Send(
+    const char* data, size_t size, const talk_base::SocketAddress& from_addr) {
+  // If the from address is known to the client, we don't need to send it.
+  if (locked() && (from_addr == default_dest_)) {
+    Send(data, size);
+    return;
+  }
+
+  // Wrap the given data in a data-indication packet.
+
+  StunMessage msg;
+  msg.SetType(STUN_DATA_INDICATION);
+  msg.SetTransactionID("0000000000000000");
+
+  StunByteStringAttribute* magic_cookie_attr =
+      StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
+  magic_cookie_attr->CopyBytes(binding_->magic_cookie().c_str(),
+                               binding_->magic_cookie().size());
+  msg.AddAttribute(magic_cookie_attr);
+
+  StunAddressAttribute* addr_attr =
+      StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
+  addr_attr->SetFamily(1);
+  addr_attr->SetIP(from_addr.ip());
+  addr_attr->SetPort(from_addr.port());
+  msg.AddAttribute(addr_attr);
+
+  StunByteStringAttribute* data_attr =
+      StunAttribute::CreateByteString(STUN_ATTR_DATA);
+  assert(size <= 65536);
+  data_attr->CopyBytes(data, uint16(size));
+  msg.AddAttribute(data_attr);
+
+  SendStun(msg);
+}
+
+void RelayServerConnection::SendStun(const StunMessage& msg) {
+  // Note that the binding has been used again.
+  binding_->NoteUsed();
+
+  cricket::SendStun(msg, socket_, addr_pair_.source());
+}
+
+void RelayServerConnection::SendStunError(
+      const StunMessage& request, int error_code, const char* error_desc) {
+  // An error does not indicate use.  If no legitimate use off the binding
+  // occurs, we want it to be cleaned up even if errors are still occuring.
+
+  cricket::SendStunError(
+      request, socket_, addr_pair_.source(), error_code, error_desc,
+      binding_->magic_cookie());
+}
+
+void RelayServerConnection::Lock() {
+  locked_ = true;
+}
+
+void RelayServerConnection::Unlock() {
+  locked_ = false;
+}
+
+// IDs used for posted messages:
+const uint32 MSG_LIFETIME_TIMER = 1;
+
+RelayServerBinding::RelayServerBinding(
+    RelayServer* server, const std::string& username,
+    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);
+
+  // Initialize the last-used time to now.
+  NoteUsed();
+
+  // Set the first timeout check.
+  server_->thread()->PostDelayed(lifetime_, this, MSG_LIFETIME_TIMER);
+}
+
+RelayServerBinding::~RelayServerBinding() {
+  // Clear the outstanding timeout check.
+  server_->thread()->Clear(this);
+
+  // Clean up all of the connections.
+  for (size_t i = 0; i < internal_connections_.size(); ++i)
+    delete internal_connections_[i];
+  for (size_t i = 0; i < external_connections_.size(); ++i)
+    delete external_connections_[i];
+
+  // Remove this binding from the server's map.
+  server_->RemoveBinding(this);
+}
+
+void RelayServerBinding::AddInternalConnection(RelayServerConnection* conn) {
+  internal_connections_.push_back(conn);
+}
+
+void RelayServerBinding::AddExternalConnection(RelayServerConnection* conn) {
+  external_connections_.push_back(conn);
+}
+
+void RelayServerBinding::NoteUsed() {
+  last_used_ = talk_base::Time();
+}
+
+bool RelayServerBinding::HasMagicCookie(const char* bytes, size_t size) const {
+  if (size < 24 + magic_cookie_.size()) {
+    return false;
+  } else {
+    return 0 == std::memcmp(
+        bytes + 24, magic_cookie_.c_str(), magic_cookie_.size());
+  }
+}
+
+RelayServerConnection* RelayServerBinding::GetInternalConnection(
+    const talk_base::SocketAddress& ext_addr) {
+
+  // Look for an internal connection that is locked to this address.
+  for (size_t i = 0; i < internal_connections_.size(); ++i) {
+    if (internal_connections_[i]->locked() &&
+        (ext_addr == internal_connections_[i]->default_destination()))
+      return internal_connections_[i];
+  }
+
+  // If one was not found, we send to the first connection.
+  assert(internal_connections_.size() > 0);
+  return internal_connections_[0];
+}
+
+RelayServerConnection* RelayServerBinding::GetExternalConnection(
+    const talk_base::SocketAddress& ext_addr) {
+  for (size_t i = 0; i < external_connections_.size(); ++i) {
+    if (ext_addr == external_connections_[i]->addr_pair().source())
+      return external_connections_[i];
+  }
+  return 0;
+}
+
+void RelayServerBinding::OnMessage(talk_base::Message *pmsg) {
+  if (pmsg->message_id == MSG_LIFETIME_TIMER) {
+    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_) {
+      SignalTimeout(this);
+    } else {
+      server_->thread()->PostDelayed(lifetime_, this, MSG_LIFETIME_TIMER);
+    }
+
+  } else {
+    assert(false);
+  }
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/relayserver.h b/talk/p2p/base/relayserver.h
new file mode 100755
index 0000000..b99c632
--- /dev/null
+++ b/talk/p2p/base/relayserver.h
@@ -0,0 +1,215 @@
+/*
+ * 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 __RELAYSERVER_H__
+#define __RELAYSERVER_H__
+
+#include "talk/base/asyncudpsocket.h"
+#include "talk/base/socketaddresspair.h"
+#include "talk/base/thread.h"
+#include "talk/base/time.h"
+#include "talk/p2p/base/stun.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace cricket {
+
+class RelayServerBinding;
+class RelayServerConnection;
+
+// 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<> {
+public:
+  // Creates a server, which will use this thread to post messages to itself.
+  RelayServer(talk_base::Thread* thread);
+  ~RelayServer();
+
+  talk_base::Thread* thread() { return thread_; }
+
+  // Indicates whether we will print updates of the number of bindings.
+  bool log_bindings() const { return log_bindings_; }
+  void set_log_bindings(bool log_bindings) { log_bindings_ = log_bindings; }
+
+  // Updates the set of sockets that the server uses to talk to "internal"
+  // clients.  These are clients that do the "port allocations".
+  void AddInternalSocket(talk_base::AsyncPacketSocket* socket);
+  void RemoveInternalSocket(talk_base::AsyncPacketSocket* socket);
+
+  // Updates the set of sockets that the server uses to talk to "external"
+  // clients.  These are the clients that do not do allocations.  They do not
+  // know that these addresses represent a relay server.
+  void AddExternalSocket(talk_base::AsyncPacketSocket* socket);
+  void RemoveExternalSocket(talk_base::AsyncPacketSocket* socket);
+
+private:
+  typedef std::vector<talk_base::AsyncPacketSocket*> SocketList;
+  typedef std::map<std::string,RelayServerBinding*> BindingMap;
+  typedef std::map<talk_base::SocketAddressPair,RelayServerConnection*> ConnectionMap;
+
+  talk_base::Thread* thread_;
+  bool log_bindings_;
+  SocketList internal_sockets_;
+  SocketList external_sockets_;
+  BindingMap bindings_;
+  ConnectionMap connections_;
+
+  // Called when a packet is received by the server on one of its sockets.
+  void OnInternalPacket(
+      const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr,
+      talk_base::AsyncPacketSocket* socket);
+  void OnExternalPacket(
+      const char* bytes, size_t size, const talk_base::SocketAddress& remote_addr,
+      talk_base::AsyncPacketSocket* 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,
+                  std::string* username, StunMessage* msg);
+  void HandleStunAllocate(const char* bytes, size_t size,
+                          const talk_base::SocketAddressPair& ap,
+                          talk_base::AsyncPacketSocket* socket);
+  void HandleStun(RelayServerConnection* int_conn, const char* bytes,
+                  size_t size);
+  void HandleStunAllocate(RelayServerConnection* int_conn,
+                          const StunMessage& msg);
+  void HandleStunSend(RelayServerConnection* int_conn, const StunMessage& msg);
+
+  // Adds/Removes the a connection or binding.
+  void AddConnection(RelayServerConnection* conn);
+  void RemoveConnection(RelayServerConnection* conn);
+  void RemoveBinding(RelayServerBinding* binding);
+
+  // Called when the timer for checking lifetime times out.
+  void OnTimeout(RelayServerBinding* binding);
+
+  friend class RelayServerConnection;
+  friend class RelayServerBinding;
+};
+
+// Maintains information about a connection to the server.  Each connection is
+// part of one and only one binding.
+class RelayServerConnection {
+public:
+  RelayServerConnection(RelayServerBinding* binding,
+                        const talk_base::SocketAddressPair& addrs,
+                        talk_base::AsyncPacketSocket* socket);
+  ~RelayServerConnection();
+
+  RelayServerBinding* binding() { return binding_; }
+  talk_base::AsyncPacketSocket* socket() { return socket_; }
+
+  // Returns a pair where the source is the remote address and the destination
+  // is the local address.
+  const talk_base::SocketAddressPair& addr_pair() { return addr_pair_; }
+
+  // Sends a packet to the connected client.  If an address is provided, then
+  // we make sure the internal client receives it, wrapping if necessary.
+  void Send(const char* data, size_t size);
+  void Send(const char* data, size_t size, const talk_base::SocketAddress& ext_addr);
+
+  // Sends a STUN message to the connected client with no wrapping.
+  void SendStun(const StunMessage& msg);
+  void SendStunError(const StunMessage& request, int code, const char* desc);
+
+  // A locked connection is one for which we know the intended destination of
+  // any raw packet received.
+  bool locked() const { return locked_; }
+  void Lock();
+  void Unlock();
+
+  // Records the address that raw packets should be forwarded to (for internal
+  // packets only; for external, we already know where they go).
+  const talk_base::SocketAddress& default_destination() const { return default_dest_; }
+  void set_default_destination(const talk_base::SocketAddress& addr) {
+    default_dest_ = addr;
+  }
+
+private:
+  RelayServerBinding* binding_;
+  talk_base::SocketAddressPair addr_pair_;
+  talk_base::AsyncPacketSocket* socket_;
+  bool locked_;
+  talk_base::SocketAddress default_dest_;
+};
+
+// Records a set of internal and external connections that we relay between,
+// or in other words, that are "bound" together.
+class RelayServerBinding : public talk_base::MessageHandler {
+public:
+  RelayServerBinding(
+      RelayServer* server, const std::string& username,
+      const std::string& password, uint32 lifetime);
+  virtual ~RelayServerBinding();
+
+  RelayServer* server() { return server_; }
+  uint32 lifetime() { return lifetime_; }
+  const std::string& username() { return username_; }
+  const std::string& password() { return password_; }
+  const std::string& magic_cookie() { return magic_cookie_; }
+
+  // Adds/Removes a connection into the binding.
+  void AddInternalConnection(RelayServerConnection* conn);
+  void AddExternalConnection(RelayServerConnection* conn);
+
+  // We keep track of the use of each binding.  If we detect that it was not
+  // used for longer than the lifetime, then we send a signal.
+  void NoteUsed();
+  sigslot::signal1<RelayServerBinding*> SignalTimeout;
+
+  // Determines whether the given packet has the magic cookie present (in the
+  // right place).
+  bool HasMagicCookie(const char* bytes, size_t size) const;
+
+  // Determines the connection to use to send packets to or from the given
+  // external address.
+  RelayServerConnection* GetInternalConnection(const talk_base::SocketAddress& ext_addr);
+  RelayServerConnection* GetExternalConnection(const talk_base::SocketAddress& ext_addr);
+
+  // MessageHandler:
+  void OnMessage(talk_base::Message *pmsg);
+
+private:
+  RelayServer* server_;
+
+  std::string username_;
+  std::string password_;
+  std::string magic_cookie_;
+
+  std::vector<RelayServerConnection*> internal_connections_;
+  std::vector<RelayServerConnection*> external_connections_;
+
+  uint32 lifetime_;
+  uint32 last_used_;
+  // TODO: bandwidth
+};
+
+} // namespace cricket
+
+#endif // __RELAYSERVER_H__
diff --git a/talk/p2p/base/relayserver_main.cc b/talk/p2p/base/relayserver_main.cc
new file mode 100755
index 0000000..cdd5fff
--- /dev/null
+++ b/talk/p2p/base/relayserver_main.cc
@@ -0,0 +1,75 @@
+/*
+ * 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>
+#include "talk/base/host.h"
+#include "talk/base/thread.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;
+    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());
+  if (int_socket->Bind(int_addr) < 0) {
+    std::cerr << "bind: " << std::strerror(errno) << std::endl;
+    return 1;
+  }
+
+  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;
+    return 1;
+  }
+
+  RelayServer server(pthMain);
+  server.AddInternalSocket(int_socket);
+  server.AddExternalSocket(ext_socket);
+
+  std::cout << "Listening internally at " << int_addr.ToString() << std::endl;
+  std::cout << "Listening externally at " << ext_addr.ToString() << std::endl;
+
+  pthMain->Run();
+  return 0;
+}
diff --git a/talk/p2p/base/session.cc b/talk/p2p/base/session.cc
new file mode 100755
index 0000000..1ea0dc3
--- /dev/null
+++ b/talk/p2p/base/session.cc
@@ -0,0 +1,1029 @@
+/*
+ * 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/p2p/base/session.h"
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/helpers.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/constants.h"
+
+namespace {
+
+const uint32 MSG_TIMEOUT = 1;
+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) {
+  ASSERT(session_manager->signaling_thread()->IsCurrent());
+  ASSERT(client != NULL);
+  session_manager_ = session_manager;
+  name_ = name;
+  id_ = id;
+  session_type_ = session_type;
+  client_ = client;
+  error_ = ERROR_NONE;
+  state_ = STATE_INIT;
+  initiator_ = false;
+  description_ = NULL;
+  remote_description_ = NULL;
+  transport_ = NULL;
+  compatibility_mode_ = false;
+}
+
+Session::~Session() {
+  ASSERT(session_manager_->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);
+    delete iter->second;
+  }
+
+  for (TransportList::iterator iter = potential_transports_.begin();
+       iter != potential_transports_.end();
+       ++iter) {
+    delete *iter;
+  }
+
+  delete transport_;
+}
+
+bool Session::Initiate(const std::string &to,
+                       std::vector<buzz::XmlElement*>* extra_xml,
+                       const SessionDescription *description) {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+
+  // Only from STATE_INIT
+  if (state_ != STATE_INIT)
+    return false;
+
+  // 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);
+  }
+
+  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));
+    }
+  }
+      
+  SendSessionMessage("initiate", elems);
+
+  SetState(Session::STATE_SENTINITIATE);
+
+  // We speculatively start attempting connection of the P2P transports.
+  ConnectDefaultTransportChannels(true);
+  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());
+
+  // Only if just received initiate
+  if (state_ != STATE_RECEIVEDINITIATE)
+    return false;
+
+  // Setup for signaling.
+  initiator_ = false;
+  description_ = description;
+
+  // If we haven't selected a transport, wait for ChooseTransport to complete
+  if (transport_ == NULL)
+    return true;
+
+  // 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());
+
+  // Reject is sent in response to an initiate or modify, to reject the
+  // request
+  if (state_ != STATE_RECEIVEDINITIATE && state_ != STATE_RECEIVEDMODIFY)
+    return false;
+
+  // 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)
+    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);
+
+  return true;
+}
+
+bool Session::Terminate() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+
+  // Either side can terminate, at any time.
+  switch (state_) {
+    case STATE_SENTTERMINATE:
+    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...
+      // it's implicit.
+      break;
+
+    default:
+      SendSessionMessage("terminate", XmlElements());
+      break;
+  }
+
+  SetState(STATE_SENTTERMINATE);
+  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);
+    }
+  }
+}
+
+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;
+    }
+  }
+  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);
+  }
+  return channel;
+}
+
+TransportChannel* Session::GetChannel(const std::string& name) {
+  ChannelMap::iterator iter = channels_.find(name);
+  return (iter != channels_.end()) ? iter->second : NULL;
+}
+
+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;
+    }
+    SetPotentialTransports(gDefaultTransports, gNumDefaultTransports);
+  }
+}
+
+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;
+
+  // 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;
+    }
+  }
+  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);
+  }
+}
+
+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);
+  }
+}
+
+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();
+    }
+  }
+}
+
+void Session::OnTransportConnecting(Transport* transport) {
+  // This is an indication that we should begin watching the writability
+  // state of the transport.
+  OnTransportWritable(transport);
+}
+
+void Session::OnTransportWritable(Transport* transport) {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  ASSERT((NULL == transport_) || (transport == transport_));
+
+  // 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);
+  if (transport->HasChannels() && !transport->writable()) {
+    session_manager_->signaling_thread()->PostDelayed(
+        session_manager_->session_timeout() * 1000, this, MSG_TIMEOUT);
+  }
+}
+
+void Session::OnTransportRequestSignaling(Transport* transport) {
+  ASSERT(session_manager_->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];
+    }
+
+    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]));
+    }
+
+    SendSessionMessage("transport-info", elems);
+  }
+}
+
+void Session::OnTransportSendError(Transport* transport,
+                                   const buzz::XmlElement* stanza,
+                                   const buzz::QName& name,
+                                   const std::string& type,
+                                   const std::string& text,
+                                   const buzz::XmlElement* extra_info) {
+  ASSERT(session_manager_->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());
+  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);
+
+  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;
+  }
+
+  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);
+  }
+
+  // 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);
+}
+
+void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
+                           const buzz::XmlElement* error_stanza) {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+
+  const buzz::XmlElement* orig_session = orig_stanza->FirstNamed(QN_SESSION);
+  ASSERT(orig_session != NULL);
+
+  std::string error_type = "cancel";
+
+  const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR);
+  ASSERT(error != NULL);
+  if (error) {
+    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();
+  }
+
+  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")) {
+    // 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.
+    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;
+        }
+      }
+    }
+  } 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))
+    return false;
+  if (!FindRemoteSessionDescription(stanza, session))
+    return false;
+
+  initiator_ = false;
+  remote_name_ = stanza->Attr(buzz::QN_FROM);
+  SetState(STATE_RECEIVEDINITIATE);
+  return true;
+}
+
+bool Session::OnAcceptMessage(const buzz::XmlElement* stanza,
+                              const buzz::XmlElement* session) {
+  if (!CheckState(stanza, STATE_SENTINITIATE))
+    return false;
+  if (!FindRemoteSessionDescription(stanza, session))
+    return false;
+
+  SetState(STATE_RECEIVEDACCEPT);
+  return true;
+}
+
+bool Session::OnRejectMessage(const buzz::XmlElement* stanza,
+                              const buzz::XmlElement* session) {
+  if (!CheckState(stanza, STATE_SENTINITIATE))
+    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);
+  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))
+    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);
+      }
+    }
+  }
+
+  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;
+
+    scoped_ptr<buzz::XmlElement> transport_accept(
+        new buzz::XmlElement(QN_SESSION));
+    transport_accept->SetAttr(buzz::QN_TYPE, "transport-accept");
+
+    buzz::XmlElement* transport_offer =
+        new buzz::XmlElement(kQnP2pTransport, true);
+    transport_accept->AddElement(transport_offer);
+
+    // 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);
+  }
+
+  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);
+}
+
+bool Session::CheckState(const buzz::XmlElement* stanza, State state) {
+  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 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;
+
+  case MSG_ERROR:
+    // Any of the defined errors is most likely fatal.
+    Terminate();
+    break;
+
+  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;
+
+    case STATE_SENTTERMINATE:
+    case STATE_RECEIVEDTERMINATE:
+      session_manager_->DestroySession(this);
+      break;
+
+    default:
+      // Explicitly ignoring some states here.
+      break;
+    }
+    break;
+  }
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/session.h b/talk/p2p/base/session.h
new file mode 100755
index 0000000..5146ea0
--- /dev/null
+++ b/talk/p2p/base/session.h
@@ -0,0 +1,357 @@
+/*
+ * 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 _SESSION_H_
+#define _SESSION_H_
+
+#include "talk/base/socketaddress.h"
+#include "talk/p2p/base/sessiondescription.h"
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/base/sessionclient.h"
+#include "talk/p2p/base/sessionid.h"
+#include "talk/p2p/base/port.h"
+#include "talk/xmllite/xmlelement.h"
+#include <string>
+
+namespace cricket {
+
+class SessionManager;
+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
+// 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<> {
+ 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
+  };
+
+  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
+  };
+
+  // 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();
+
+  // Updates the state, signaling if necessary.
+  void SetState(State state);
+
+  // 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);
+
+  // 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);
+
+  // Creates a default set of transports if the client did not specify some.
+  void CreateTransports();
+
+  // 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);
+
+  // Called when a single transport has been negotiated.
+  void SetTransport(Transport* transport);
+
+  // 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
+  // reasonable amount of time.
+  void OnTransportConnecting(Transport* transport);
+
+  // Called when a transport changes its writable state.  We track this to make
+  // sure that the transport becomes writable within a reasonable amount of
+  // time.  If this does not occur, we signal an error.
+  void OnTransportWritable(Transport* transport);
+
+  // Called when a transport requests signaling.
+  void OnTransportRequestSignaling(Transport* transport);
+
+  // 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);
+
+  // Called when a transport signals that it found an error in an incoming
+  // message.
+  void OnTransportSendError(Transport* transport,
+                            const buzz::XmlElement* stanza,
+                            const buzz::QName& name,
+                            const std::string& type,
+                            const std::string& text,
+                            const buzz::XmlElement* extra_info);
+
+  // Called when we notice that one of our local channels has no peer, so it
+  // should be destroyed.
+  void OnTransportChannelGone(Transport* transport, const std::string& name);
+
+  // When the session needs to send signaling messages, it beings by requesting
+  // signaling.  The client should handle this by calling OnSignalingReady once
+  // it is ready to send the messages.
+  // (These are called only by SessionManager.)
+  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);
+
+  // Sends a message back to the other client indicating that we have received
+  // and accepted their message.
+  void SendAcknowledgementMessage(const buzz::XmlElement* stanza);
+
+  // Once signaling is ready, the session will use this signal to request the
+  // sending of each message.  When messages are received by the other client,
+  // 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 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*,
+                   const buzz::XmlElement*,
+                   const buzz::QName&,
+                   const std::string&,
+                   const std::string&,
+                   const buzz::XmlElement*> SignalErrorMessage;
+
+  // 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);
+
+  // 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);
+
+  // Handles messages posted to us.
+  void OnMessage(talk_base::Message *pmsg);
+
+  friend class SessionManager;  // For access to constructor, destructor,
+                                // and signaling related methods.
+};
+
+} // namespace cricket
+
+#endif // _SESSION_H_
diff --git a/talk/p2p/base/session_unittest.cc b/talk/p2p/base/session_unittest.cc
new file mode 100755
index 0000000..972ed9d
--- /dev/null
+++ b/talk/p2p/base/session_unittest.cc
@@ -0,0 +1,1039 @@
+#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
new file mode 100755
index 0000000..a92df1d
--- /dev/null
+++ b/talk/p2p/base/sessionclient.h
@@ -0,0 +1,71 @@
+/*
+ * 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 _CRICKET_P2P_BASE_SESSIONCLIENT_H_
+#define _CRICKET_P2P_BASE_SESSIONCLIENT_H_
+
+namespace buzz {
+class XmlElement;
+}
+
+namespace cricket {
+
+class Session;
+class SessionDescription;
+
+// 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 {
+ public:
+  // Notifies the client of the creation / destruction of sessions of this type.
+  //
+  // IMPORTANT: The SessionClient, in its handling of OnSessionCreate, must
+  // create whatever channels are indicate in the description.  This is because
+  // the remote client may already be attempting to connect those channels. If
+  // we do not create our channel right away, then connection may fail or be
+  // delayed.
+  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:
+  // The SessionClient interface explicitly does not include destructor
+  virtual ~SessionClient() { }
+};
+
+}  // namespace cricket
+
+#endif // _CRICKET_P2P_BASE_SESSIONCLIENT_H_
diff --git a/talk/p2p/base/sessiondescription.h b/talk/p2p/base/sessiondescription.h
new file mode 100755
index 0000000..28b7084
--- /dev/null
+++ b/talk/p2p/base/sessiondescription.h
@@ -0,0 +1,42 @@
+/*
+ * 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 _SESSIONDESCRIPTION_H_
+#define _SESSIONDESCRIPTION_H_
+
+namespace cricket {
+
+// The client overrides this with whatever 
+
+class SessionDescription {
+public:
+  virtual ~SessionDescription() {}
+};
+
+} // namespace cricket
+
+#endif // _SESSIONDESCRIPTION_H_
diff --git a/talk/p2p/base/sessionid.h b/talk/p2p/base/sessionid.h
new file mode 100755
index 0000000..a12535c
--- /dev/null
+++ b/talk/p2p/base/sessionid.h
@@ -0,0 +1,94 @@
+/*
+ * 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 _SESSIONID_H_
+#define _SESSIONID_H_
+
+#include "talk/base/basictypes.h"
+#include <string>
+#include <sstream>
+
+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_) {
+  }
+
+  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_
diff --git a/talk/p2p/base/sessionmanager.cc b/talk/p2p/base/sessionmanager.cc
new file mode 100755
index 0000000..ae71a75
--- /dev/null
+++ b/talk/p2p/base/sessionmanager.cc
@@ -0,0 +1,331 @@
+/*
+ * 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/p2p/base/sessionmanager.h"
+#include "talk/base/common.h"
+#include "talk/base/helpers.h"
+#include "talk/p2p/base/constants.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/jid.h"
+
+namespace cricket {
+
+SessionManager::SessionManager(PortAllocator *allocator, 
+                               talk_base::Thread *worker) {
+  allocator_ = allocator;
+  signaling_thread_ = talk_base::Thread::Current();
+  if (worker == NULL) {
+    worker_thread_ = talk_base::Thread::Current();
+  } else {
+    worker_thread_ = worker;
+  }
+  timeout_ = 50;
+}
+
+SessionManager::~SessionManager() {
+  // Note: Session::Terminate occurs asynchronously, so it's too late to
+  // delete them now.  They better be all gone.
+  ASSERT(session_map_.empty());
+  //TerminateAll();
+}
+
+void SessionManager::AddClient(const std::string& session_type,
+                               SessionClient* client) {
+  ASSERT(client_map_.find(session_type) == client_map_.end());
+  client_map_[session_type] = client;
+}
+
+void SessionManager::RemoveClient(const std::string& session_type) {
+  ClientMap::iterator iter = client_map_.find(session_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);
+  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 &name, const SessionID& id,
+    const std::string& session_type, bool received_initiate) {
+  SessionClient* client = GetClient(session_type);
+  ASSERT(client != NULL);
+
+  Session *session = new Session(this, name, id, session_type, client);
+  session_map_[session->id()] = session;
+  session->SignalRequestSignaling.connect(
+      this, &SessionManager::OnRequestSignaling);
+  session->SignalOutgoingMessage.connect(
+      this, &SessionManager::OnOutgoingMessage);
+  session->SignalErrorMessage.connect(this, &SessionManager::OnErrorMessage);
+  SignalSessionCreate(session, received_initiate);
+  session->client()->OnSessionCreate(session, received_initiate);
+  return session;
+}
+
+void SessionManager::DestroySession(Session *session) {
+  if (session != NULL) {
+    SessionMap::iterator it = session_map_.find(session->id());
+    if (it != session_map_.end()) {
+      SignalSessionDestroy(session);
+      session->client()->OnSessionDestroy(session);
+      session_map_.erase(it);
+      delete session;
+    }
+  }
+}
+
+Session *SessionManager::GetSession(const SessionID& id) {
+  SessionMap::iterator it = session_map_.find(id);
+  if (it != session_map_.end())
+    return it->second;
+  return NULL;
+}
+
+void SessionManager::TerminateAll() {
+  while (session_map_.begin() != session_map_.end()) {
+    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;
+}
+
+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);
+  if (iter == session_map_.end())
+    return NULL;
+
+  Session* session = iter->second;
+
+  // 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;
+}
+
+void SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) {
+  ASSERT(stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET);
+
+  Session* session = FindSessionForStanza(stanza, true);
+  if (session) {
+    session->OnIncomingMessage(stanza);
+    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);
+      }
+    }
+    return;
+  }
+
+  SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
+                  "unknown session", NULL);
+}
+
+void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
+    const buzz::XmlElement* response_stanza) {
+  // We don't do anything with the response now.  If we need to we can forward
+  // it to the session.
+  return;
+}
+
+void SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza, 
+                                  const buzz::XmlElement* error_stanza) {
+  Session* session = FindSessionForStanza(orig_stanza, false);
+  if (session) {
+    scoped_ptr<buzz::XmlElement> synthetic_error;
+    if (!error_stanza) {
+      // 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, 
+                           "cancel", "Recipient did not respond", NULL));
+      error_stanza = synthetic_error.get();
+    }
+
+    session->OnFailedSend(orig_stanza, error_stanza);
+  }
+}
+
+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(
+      CreateErrorMessage(stanza, name, type, text, extra_info));
+  SignalOutgoingMessage(msg.get());
+}
+
+buzz::XmlElement* SessionManager::CreateErrorMessage(
+    const buzz::XmlElement* stanza,
+    const buzz::QName& name,
+    const std::string& type,
+    const std::string& text,
+    const buzz::XmlElement* extra_info) {
+  buzz::XmlElement* iq = new buzz::XmlElement(buzz::QN_IQ);
+  iq->SetAttr(buzz::QN_TO, stanza->Attr(buzz::QN_FROM));
+  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));
+  }
+
+  buzz::XmlElement* error = new buzz::XmlElement(buzz::QN_ERROR);
+  error->SetAttr(buzz::QN_TYPE, type);
+  iq->AddElement(error);
+
+  // If the error name is not in the standard namespace, we have to first add
+  // some error from that namespace.
+  if (name.Namespace() != buzz::NS_STANZA) {
+     error->AddElement(
+         new buzz::XmlElement(buzz::QN_STANZA_UNDEFINED_CONDITION));
+  }
+  error->AddElement(new buzz::XmlElement(name));
+
+  if (extra_info)
+    error->AddElement(new buzz::XmlElement(*extra_info));
+
+  if (text.size() > 0) {
+    // It's okay to always use English here.  This text is for debugging
+    // purposes only.
+    buzz::XmlElement* text_elem = new buzz::XmlElement(buzz::QN_STANZA_TEXT);
+    text_elem->SetAttr(buzz::QN_XML_LANG, "en");
+    text_elem->SetBodyText(text);
+    error->AddElement(text_elem);
+  }
+
+  // TODO: Should we include error codes as well for SIP compatibility?
+
+  return iq;
+}
+
+void SessionManager::OnOutgoingMessage(Session* session,
+                                       const buzz::XmlElement* stanza) {
+  SignalOutgoingMessage(stanza);
+}
+
+void SessionManager::OnErrorMessage(Session* session,
+                                    const buzz::XmlElement* stanza,
+                                    const buzz::QName& name,
+                                    const std::string& type,
+                                    const std::string& text,
+                                    const buzz::XmlElement* extra_info) {
+  SendErrorMessage(stanza, name, type, text, extra_info);
+}
+
+void SessionManager::OnSignalingReady() {
+  for (SessionMap::iterator it = session_map_.begin();
+      it != session_map_.end();
+      ++it) {
+    it->second->OnSignalingReady();
+  }
+}
+
+void SessionManager::OnRequestSignaling(Session* session) {
+  SignalRequestSignaling();
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/sessionmanager.h b/talk/p2p/base/sessionmanager.h
new file mode 100755
index 0000000..423af65
--- /dev/null
+++ b/talk/p2p/base/sessionmanager.h
@@ -0,0 +1,181 @@
+/*
+ * 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 _SESSIONMANAGER_H_
+#define _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 <string>
+#include <utility>
+#include <map>
+
+namespace buzz {
+class QName;
+class XmlElement;
+}
+
+namespace cricket {
+
+class Session;
+class SessionClient;
+
+// SessionManager manages session instances
+
+class SessionManager : public sigslot::has_slots<> {
+ public:
+  SessionManager(PortAllocator *allocator, 
+                 talk_base::Thread *worker_thread = NULL);
+  virtual ~SessionManager();
+
+  PortAllocator *port_allocator() const { return allocator_; }
+  talk_base::Thread *worker_thread() const { return worker_thread_; }
+  talk_base::Thread *signaling_thread() const { return signaling_thread_; }
+
+  int session_timeout() const { return timeout_; }
+  void set_session_timeout(int timeout) { timeout_ = timeout; }
+
+  // Registers support for the given client.  If we receive an initiate
+  // 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);
+
+  // 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);
+
+  // 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);
+
+  // Terminates all of the sessions created by this manager.
+  void TerminateAll();
+
+  // These are signaled whenever the set of existing sessions changes.
+  sigslot::signal2<Session *, bool> SignalSessionCreate;
+  sigslot::signal1<Session *> SignalSessionDestroy;
+
+  // 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);
+
+  // 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);
+
+  // Called if an attempted to send times out or an error is returned.  In the
+  // timeout case error_stanza will be NULL
+  void OnFailedSend(const buzz::XmlElement* orig_stanza,
+                    const buzz::XmlElement* error_stanza);
+
+  // Signalled each time a session generates a signaling message to send.
+  sigslot::signal1<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
+  // steps are taken so that we don't send signaling messages trying to
+  // re-establish the connectivity of a session when the client cannot send
+  // the messages (and would probably just drop them on the floor).
+  //
+  // Note: you can connect this directly to OnSignalingReady(), if a signalling
+  // check is not supported.
+  sigslot::signal0<> SignalRequestSignaling;
+  void OnSignalingReady();
+
+ private:
+  typedef std::map<SessionID, Session *> SessionMap;
+  typedef std::map<std::string, SessionClient*> ClientMap;
+
+  PortAllocator *allocator_;
+  talk_base::Thread *signaling_thread_;
+  talk_base::Thread *worker_thread_;
+  int timeout_;
+  SessionMap session_map_;
+  ClientMap client_map_;
+
+  // 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,
+                         bool received_initiate);
+
+  // Attempts to find a registered session type whose description appears as
+  // a child of the session element.  Such a child should be present indicating
+  // the application they hope to initiate.
+  std::string FindClient(const buzz::XmlElement* session);
+
+  // Sends a message back to the other client indicating that we found an error
+  // in the stanza they sent.  name identifies the error, type is one of the
+  // standard XMPP types (cancel, continue, modify, auth, wait), and text is a
+  // description for debugging purposes.
+  void SendErrorMessage(const buzz::XmlElement* stanza,
+                        const buzz::QName& name,
+                        const std::string& type,
+                        const std::string& text,
+                        const buzz::XmlElement* extra_info);
+
+  // Creates and returns an error message from the given components.  The
+  // caller is responsible for deleting this.
+  buzz::XmlElement* SessionManager::CreateErrorMessage(
+      const buzz::XmlElement* stanza,
+      const buzz::QName& name,
+      const std::string& type,
+      const std::string& text,
+      const buzz::XmlElement* extra_info);
+
+  // Called each time a session requests signaling.
+  void OnRequestSignaling(Session* session);
+
+  // Called each time a session has an outgoing message.
+  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,
+                      const std::string& text,
+                      const buzz::XmlElement* extra_info);
+};
+
+} // namespace cricket
+
+#endif // _SESSIONMANAGER_H_
diff --git a/talk/p2p/base/stun.cc b/talk/p2p/base/stun.cc
new file mode 100755
index 0000000..c4a89e8
--- /dev/null
+++ b/talk/p2p/base/stun.cc
@@ -0,0 +1,578 @@
+/*
+ * 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/p2p/base/stun.h"
+#include <iostream>
+#include <cassert>
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+namespace std {
+  using ::memcpy;
+}
+#endif
+
+using talk_base::ByteBuffer;
+
+namespace cricket {
+
+const std::string STUN_ERROR_REASON_BAD_REQUEST = "BAD REQUEST";
+const std::string STUN_ERROR_REASON_UNAUTHORIZED = "UNAUTHORIZED";
+const std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE = "UNKNOWN ATTRIBUTE";
+const std::string STUN_ERROR_REASON_STALE_CREDENTIALS = "STALE CREDENTIALS";
+const std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE = "INTEGRITY CHECK FAILURE";
+const std::string STUN_ERROR_REASON_MISSING_USERNAME = "MISSING USERNAME";
+const std::string STUN_ERROR_REASON_USE_TLS = "USE TLS";
+const std::string STUN_ERROR_REASON_SERVER_ERROR = "SERVER ERROR";
+const std::string STUN_ERROR_REASON_GLOBAL_FAILURE = "GLOBAL FAILURE";
+
+StunMessage::StunMessage() : type_(0), length_(0),
+    transaction_id_("0000000000000000") {
+  assert(transaction_id_.size() == 16);
+  attrs_ = new std::vector<StunAttribute*>();
+}
+
+StunMessage::~StunMessage() {
+  for (unsigned i = 0; i < attrs_->size(); i++)
+    delete (*attrs_)[i];
+  delete attrs_;
+}
+
+void StunMessage::SetTransactionID(const std::string& str) {
+  assert(str.size() == 16);
+  transaction_id_ = str;
+}
+
+void StunMessage::AddAttribute(StunAttribute* attr) {
+  attrs_->push_back(attr);
+  length_ += attr->length() + 4;
+}
+
+const StunAddressAttribute*
+StunMessage::GetAddress(StunAttributeType type) const {
+  switch (type) {
+  case STUN_ATTR_MAPPED_ADDRESS:
+  case STUN_ATTR_RESPONSE_ADDRESS:
+  case STUN_ATTR_SOURCE_ADDRESS:
+  case STUN_ATTR_CHANGED_ADDRESS:
+  case STUN_ATTR_REFLECTED_FROM:
+  case STUN_ATTR_ALTERNATE_SERVER:
+  case STUN_ATTR_DESTINATION_ADDRESS:
+  case STUN_ATTR_SOURCE_ADDRESS2:
+    return reinterpret_cast<const StunAddressAttribute*>(GetAttribute(type));
+
+  default:
+    assert(0);
+    return 0;
+  }
+}
+
+const StunUInt32Attribute*
+StunMessage::GetUInt32(StunAttributeType type) const {
+  switch (type) {
+  case STUN_ATTR_CHANGE_REQUEST:
+  case STUN_ATTR_LIFETIME:
+  case STUN_ATTR_BANDWIDTH:
+  case STUN_ATTR_OPTIONS:
+    return reinterpret_cast<const StunUInt32Attribute*>(GetAttribute(type));
+
+  default:
+    assert(0);
+    return 0;
+  }
+}
+
+const StunByteStringAttribute*
+StunMessage::GetByteString(StunAttributeType type) const {
+  switch (type) {
+  case STUN_ATTR_USERNAME:
+  case STUN_ATTR_PASSWORD:
+  case STUN_ATTR_MESSAGE_INTEGRITY:
+  case STUN_ATTR_DATA:
+  case STUN_ATTR_MAGIC_COOKIE:
+    return reinterpret_cast<const StunByteStringAttribute*>(GetAttribute(type));
+
+  default:
+    assert(0);
+    return 0;
+  }
+}
+
+const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
+  return reinterpret_cast<const StunErrorCodeAttribute*>(
+      GetAttribute(STUN_ATTR_ERROR_CODE));
+}
+
+const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
+  return reinterpret_cast<const StunUInt16ListAttribute*>(
+      GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
+}
+
+const StunTransportPrefsAttribute* StunMessage::GetTransportPrefs() const {
+  return reinterpret_cast<const StunTransportPrefsAttribute*>(
+      GetAttribute(STUN_ATTR_TRANSPORT_PREFERENCES));
+}
+
+const StunAttribute* StunMessage::GetAttribute(StunAttributeType type) const {
+  for (unsigned i = 0; i < attrs_->size(); i++) {
+    if ((*attrs_)[i]->type() == type)
+      return (*attrs_)[i];
+  }
+  return 0;
+}
+
+bool StunMessage::Read(ByteBuffer* buf) {
+  if (!buf->ReadUInt16(type_))
+    return false;
+
+  if (!buf->ReadUInt16(length_))
+    return false;
+
+  std::string transaction_id;
+  if (!buf->ReadString(transaction_id, 16))
+    return false;
+  assert(transaction_id.size() == 16);
+  transaction_id_ = transaction_id;
+
+  if (length_ > buf->Length())
+    return false;
+
+  attrs_->resize(0);
+
+  size_t rest = buf->Length() - length_;
+  while (buf->Length() > rest) {
+    uint16 attr_type, attr_length;
+    if (!buf->ReadUInt16(attr_type))
+      return false;
+    if (!buf->ReadUInt16(attr_length))
+      return false;
+
+    StunAttribute* attr = StunAttribute::Create(attr_type, attr_length);
+    if (!attr || !attr->Read(buf))
+      return false;
+
+    attrs_->push_back(attr);
+  }
+
+  if (buf->Length() != rest) {
+    // fixme: shouldn't be doing this
+    LOG(LERROR) << "wrong message length" 
+               << " (" << (int)rest << " != " << (int)buf->Length() << ")";
+    return false;
+  }
+
+  return true;
+}
+
+void StunMessage::Write(ByteBuffer* buf) const {
+  buf->WriteUInt16(type_);
+  buf->WriteUInt16(length_);
+  buf->WriteString(transaction_id_);
+
+  for (unsigned i = 0; i < attrs_->size(); i++) {
+    buf->WriteUInt16((*attrs_)[i]->type());
+    buf->WriteUInt16((*attrs_)[i]->length());
+    (*attrs_)[i]->Write(buf);
+  }
+}
+
+StunAttribute::StunAttribute(uint16 type, uint16 length)
+    : type_(type), length_(length) {
+}
+
+StunAttribute* StunAttribute::Create(uint16 type, uint16 length) {
+  switch (type) {
+  case STUN_ATTR_MAPPED_ADDRESS:
+  case STUN_ATTR_RESPONSE_ADDRESS:
+  case STUN_ATTR_SOURCE_ADDRESS:
+  case STUN_ATTR_CHANGED_ADDRESS:
+  case STUN_ATTR_REFLECTED_FROM:
+  case STUN_ATTR_ALTERNATE_SERVER:
+  case STUN_ATTR_DESTINATION_ADDRESS:
+  case STUN_ATTR_SOURCE_ADDRESS2:
+    if (length != StunAddressAttribute::SIZE)
+      return 0;
+    return new StunAddressAttribute(type);
+
+  case STUN_ATTR_CHANGE_REQUEST:
+  case STUN_ATTR_LIFETIME:
+  case STUN_ATTR_BANDWIDTH:
+  case STUN_ATTR_OPTIONS:
+    if (length != StunUInt32Attribute::SIZE)
+      return 0;
+    return new StunUInt32Attribute(type);
+
+  case STUN_ATTR_USERNAME:
+  case STUN_ATTR_PASSWORD:
+  case STUN_ATTR_MAGIC_COOKIE:
+    return (length % 4 == 0) ? new StunByteStringAttribute(type, length) : 0;
+
+  case STUN_ATTR_MESSAGE_INTEGRITY:
+    return (length == 20) ? new StunByteStringAttribute(type, length) : 0;
+
+  case STUN_ATTR_DATA:
+    return new StunByteStringAttribute(type, length);
+
+  case STUN_ATTR_ERROR_CODE:
+    if (length < StunErrorCodeAttribute::MIN_SIZE)
+      return 0;
+    return new StunErrorCodeAttribute(type, length);
+
+  case STUN_ATTR_UNKNOWN_ATTRIBUTES:
+    return (length % 2 == 0) ? new StunUInt16ListAttribute(type, length) : 0;
+
+  case STUN_ATTR_TRANSPORT_PREFERENCES:
+    if ((length != StunTransportPrefsAttribute::SIZE1) &&
+	(length != StunTransportPrefsAttribute::SIZE2))
+      return 0;
+    return new StunTransportPrefsAttribute(type, length);
+
+  default:
+    return 0;
+  }
+}
+
+StunAddressAttribute* StunAttribute::CreateAddress(uint16 type) {
+  switch (type) {
+  case STUN_ATTR_MAPPED_ADDRESS:
+  case STUN_ATTR_RESPONSE_ADDRESS:
+  case STUN_ATTR_SOURCE_ADDRESS:
+  case STUN_ATTR_CHANGED_ADDRESS:
+  case STUN_ATTR_REFLECTED_FROM:
+  case STUN_ATTR_ALTERNATE_SERVER:
+  case STUN_ATTR_DESTINATION_ADDRESS:
+  case STUN_ATTR_SOURCE_ADDRESS2:
+    return new StunAddressAttribute(type);
+
+  default:
+    assert(false);
+    return 0;
+  }
+}
+
+StunUInt32Attribute* StunAttribute::CreateUInt32(uint16 type) {
+  switch (type) {
+  case STUN_ATTR_CHANGE_REQUEST:
+  case STUN_ATTR_LIFETIME:
+  case STUN_ATTR_BANDWIDTH:
+  case STUN_ATTR_OPTIONS:
+    return new StunUInt32Attribute(type);
+
+  default:
+    assert(false);
+    return 0;
+  }
+}
+
+StunByteStringAttribute* StunAttribute::CreateByteString(uint16 type) {
+  switch (type) {
+  case STUN_ATTR_USERNAME:
+  case STUN_ATTR_PASSWORD:
+  case STUN_ATTR_MESSAGE_INTEGRITY:
+  case STUN_ATTR_DATA:
+  case STUN_ATTR_MAGIC_COOKIE:
+    return new StunByteStringAttribute(type, 0);
+
+  default:
+    assert(false);
+    return 0;
+  }
+}
+
+StunErrorCodeAttribute* StunAttribute::CreateErrorCode() {
+  return new StunErrorCodeAttribute(
+      STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE);
+}
+
+StunUInt16ListAttribute* StunAttribute::CreateUnknownAttributes() {
+  return new StunUInt16ListAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
+}
+
+StunTransportPrefsAttribute* StunAttribute::CreateTransportPrefs() {
+  return new StunTransportPrefsAttribute(
+      STUN_ATTR_TRANSPORT_PREFERENCES, StunTransportPrefsAttribute::SIZE1);
+}
+
+StunAddressAttribute::StunAddressAttribute(uint16 type)
+    : StunAttribute(type, SIZE), family_(0), port_(0), ip_(0) {
+}
+
+bool StunAddressAttribute::Read(ByteBuffer* buf) {
+  uint8 dummy;
+  if (!buf->ReadUInt8(dummy))
+    return false;
+  if (!buf->ReadUInt8(family_))
+    return false;
+  if (!buf->ReadUInt16(port_))
+    return false;
+  if (!buf->ReadUInt32(ip_))
+    return false;
+  return true;
+}
+
+void StunAddressAttribute::Write(ByteBuffer* buf) const {
+  buf->WriteUInt8(0);
+  buf->WriteUInt8(family_);
+  buf->WriteUInt16(port_);
+  buf->WriteUInt32(ip_);
+}
+
+StunUInt32Attribute::StunUInt32Attribute(uint16 type)
+    : StunAttribute(type, SIZE), bits_(0) {
+}
+
+bool StunUInt32Attribute::GetBit(int index) const {
+  assert((0 <= index) && (index < 32));
+  return static_cast<bool>((bits_ >> index) & 0x1);
+}
+
+void StunUInt32Attribute::SetBit(int index, bool value) {
+  assert((0 <= index) && (index < 32));
+  bits_ &= ~(1 << index);
+  bits_ |= value ? (1 << index) : 0;
+}
+
+bool StunUInt32Attribute::Read(ByteBuffer* buf) {
+  if (!buf->ReadUInt32(bits_))
+    return false;
+  return true;
+}
+
+void StunUInt32Attribute::Write(ByteBuffer* buf) const {
+  buf->WriteUInt32(bits_);
+}
+
+StunByteStringAttribute::StunByteStringAttribute(uint16 type, uint16 length)
+    : StunAttribute(type, length), bytes_(0) {
+}
+
+StunByteStringAttribute::~StunByteStringAttribute() {
+  delete [] bytes_;
+}
+
+void StunByteStringAttribute::SetBytes(char* bytes, uint16 length) {
+  delete [] bytes_;
+  bytes_ = bytes;
+  SetLength(length);
+}
+
+void StunByteStringAttribute::CopyBytes(const char* bytes) {
+  CopyBytes(bytes, (uint16)strlen(bytes));
+}
+
+void StunByteStringAttribute::CopyBytes(const void* bytes, uint16 length) {
+  char* new_bytes = new char[length];
+  std::memcpy(new_bytes, bytes, length);
+  SetBytes(new_bytes, length);
+}
+
+uint8 StunByteStringAttribute::GetByte(int index) const {
+  assert(bytes_);
+  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()));
+  bytes_[index] = value;
+}
+
+bool StunByteStringAttribute::Read(ByteBuffer* buf) {
+  bytes_ = new char[length()];
+  if (!buf->ReadBytes(bytes_, length()))
+    return false;
+  return true;
+}
+
+void StunByteStringAttribute::Write(ByteBuffer* buf) const {
+  buf->WriteBytes(bytes_, length());
+}
+
+StunErrorCodeAttribute::StunErrorCodeAttribute(uint16 type, uint16 length)
+    : StunAttribute(type, length), class_(0), number_(0) {
+}
+
+StunErrorCodeAttribute::~StunErrorCodeAttribute() {
+}
+
+void StunErrorCodeAttribute::SetErrorCode(uint32 code) {
+  class_ = (uint8)((code >> 8) & 0x7);
+  number_ = (uint8)(code & 0xff);
+}
+
+void StunErrorCodeAttribute::SetReason(const std::string& reason) {
+  SetLength(MIN_SIZE + (uint16)reason.size());
+  reason_ = reason;
+}
+
+bool StunErrorCodeAttribute::Read(ByteBuffer* buf) {
+  uint32 val;
+  if (!buf->ReadUInt32(val))
+    return false;
+
+  if ((val >> 11) != 0)
+    LOG(LERROR) << "error-code bits not zero";
+
+  SetErrorCode(val);
+
+  if (!buf->ReadString(reason_, length() - 4))
+    return false;
+
+  return true;
+}
+
+void StunErrorCodeAttribute::Write(ByteBuffer* buf) const {
+  buf->WriteUInt32(error_code());
+  buf->WriteString(reason_);
+}
+
+StunUInt16ListAttribute::StunUInt16ListAttribute(uint16 type, uint16 length)
+    : StunAttribute(type, length) {
+  attr_types_ = new std::vector<uint16>();
+}
+
+StunUInt16ListAttribute::~StunUInt16ListAttribute() {
+  delete attr_types_;
+}
+
+size_t StunUInt16ListAttribute::Size() const {
+  return attr_types_->size();
+}
+
+uint16 StunUInt16ListAttribute::GetType(int index) const {
+  return (*attr_types_)[index];
+}
+
+void StunUInt16ListAttribute::SetType(int index, uint16 value) {
+  (*attr_types_)[index] = value;
+}
+
+void StunUInt16ListAttribute::AddType(uint16 value) {
+  attr_types_->push_back(value);
+  SetLength((uint16)attr_types_->size() * 2);
+}
+
+bool StunUInt16ListAttribute::Read(ByteBuffer* buf) {
+  for (int i = 0; i < length() / 2; i++) {
+    uint16 attr;
+    if (!buf->ReadUInt16(attr))
+      return false;
+    attr_types_->push_back(attr);
+  }
+  return true;
+}
+
+void StunUInt16ListAttribute::Write(ByteBuffer* buf) const {
+  for (unsigned i = 0; i < attr_types_->size(); i++)
+    buf->WriteUInt16((*attr_types_)[i]);
+}
+
+StunTransportPrefsAttribute::StunTransportPrefsAttribute(
+    uint16 type, uint16 length)
+    : StunAttribute(type, length), preallocate_(false), prefs_(0), addr_(0) { 
+}
+
+StunTransportPrefsAttribute::~StunTransportPrefsAttribute() {
+  delete addr_;
+}
+
+void StunTransportPrefsAttribute::SetPreallocateAddress(
+    StunAddressAttribute* addr) {
+  if (!addr) {
+    preallocate_ = false;
+    addr_ = 0;
+    SetLength(SIZE1);
+  } else {
+    preallocate_ = true;
+    addr_ = addr;
+    SetLength(SIZE2);
+  }
+}
+
+bool StunTransportPrefsAttribute::Read(ByteBuffer* buf) {
+  uint32 val;
+  if (!buf->ReadUInt32(val))
+    return false;
+
+  if ((val >> 3) != 0)
+    LOG(LERROR) << "transport-preferences bits not zero";
+
+  preallocate_ = static_cast<bool>((val >> 2) & 0x1);
+  prefs_ = (uint8)(val & 0x3);
+
+  if (preallocate_ && (prefs_ == 3))
+    LOG(LERROR) << "transport-preferences imcompatible P and Typ";
+
+  if (!preallocate_) {
+    if (length() != StunUInt32Attribute::SIZE)
+      return false;
+  } else {
+    if (length() != StunUInt32Attribute::SIZE + StunAddressAttribute::SIZE)
+      return false;
+
+    addr_ = new StunAddressAttribute(STUN_ATTR_SOURCE_ADDRESS);
+    addr_->Read(buf);
+  }
+
+  return true;
+}
+
+void StunTransportPrefsAttribute::Write(ByteBuffer* buf) const {
+  buf->WriteUInt32((preallocate_ ? 4 : 0) | prefs_);
+
+  if (preallocate_)
+    addr_->Write(buf);
+}
+
+StunMessageType GetStunResponseType(StunMessageType request_type) {
+  switch (request_type) {
+  case STUN_SHARED_SECRET_REQUEST:
+    return STUN_SHARED_SECRET_RESPONSE;
+  case STUN_ALLOCATE_REQUEST:
+    return STUN_ALLOCATE_RESPONSE;
+  case STUN_SEND_REQUEST:
+    return STUN_SEND_RESPONSE;
+  default:
+    return STUN_BINDING_RESPONSE;
+  }
+}
+
+StunMessageType GetStunErrorResponseType(StunMessageType request_type) {
+  switch (request_type) {
+  case STUN_SHARED_SECRET_REQUEST:
+    return STUN_SHARED_SECRET_ERROR_RESPONSE;
+  case STUN_ALLOCATE_REQUEST:
+    return STUN_ALLOCATE_ERROR_RESPONSE;
+  case STUN_SEND_REQUEST:
+    return STUN_SEND_ERROR_RESPONSE;
+  default:
+    return STUN_BINDING_ERROR_RESPONSE;
+  }
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/stun.h b/talk/p2p/base/stun.h
new file mode 100755
index 0000000..4c0459b
--- /dev/null
+++ b/talk/p2p/base/stun.h
@@ -0,0 +1,364 @@
+/*
+ * 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 __STUN_H__
+#define __STUN_H__
+
+// 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>
+
+namespace cricket {
+
+// These are the types of STUN & TURN messages as of last check.
+enum StunMessageType {
+  STUN_BINDING_REQUEST              = 0x0001,
+  STUN_BINDING_RESPONSE             = 0x0101,
+  STUN_BINDING_ERROR_RESPONSE       = 0x0111,
+  STUN_SHARED_SECRET_REQUEST        = 0x0002,
+  STUN_SHARED_SECRET_RESPONSE       = 0x0102,
+  STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112,
+  STUN_ALLOCATE_REQUEST             = 0x0003,
+  STUN_ALLOCATE_RESPONSE            = 0x0103,
+  STUN_ALLOCATE_ERROR_RESPONSE      = 0x0113,
+  STUN_SEND_REQUEST                 = 0x0004,
+  STUN_SEND_RESPONSE                = 0x0104,
+  STUN_SEND_ERROR_RESPONSE          = 0x0114,
+  STUN_DATA_INDICATION              = 0x0115
+};
+
+// These are the types of attributes defined in STUN & TURN.  Next to each is
+// the name of the class (T is StunTAttribute) that implements that type.
+enum StunAttributeType {
+  STUN_ATTR_MAPPED_ADDRESS        = 0x0001, // Address
+  STUN_ATTR_RESPONSE_ADDRESS      = 0x0002, // Address
+  STUN_ATTR_CHANGE_REQUEST        = 0x0003, // UInt32
+  STUN_ATTR_SOURCE_ADDRESS        = 0x0004, // Address
+  STUN_ATTR_CHANGED_ADDRESS       = 0x0005, // Address
+  STUN_ATTR_USERNAME              = 0x0006, // ByteString, multiple of 4 bytes
+  STUN_ATTR_PASSWORD              = 0x0007, // ByteString, multiple of 4 bytes
+  STUN_ATTR_MESSAGE_INTEGRITY     = 0x0008, // ByteString, 20 bytes
+  STUN_ATTR_ERROR_CODE            = 0x0009, // ErrorCode
+  STUN_ATTR_UNKNOWN_ATTRIBUTES    = 0x000a, // UInt16List
+  STUN_ATTR_REFLECTED_FROM        = 0x000b, // Address
+  STUN_ATTR_TRANSPORT_PREFERENCES = 0x000c, // TransportPrefs
+  STUN_ATTR_LIFETIME              = 0x000d, // UInt32
+  STUN_ATTR_ALTERNATE_SERVER      = 0x000e, // Address
+  STUN_ATTR_MAGIC_COOKIE          = 0x000f, // ByteString, 4 bytes
+  STUN_ATTR_BANDWIDTH             = 0x0010, // UInt32
+  STUN_ATTR_DESTINATION_ADDRESS   = 0x0011, // Address
+  STUN_ATTR_SOURCE_ADDRESS2       = 0x0012, // Address
+  STUN_ATTR_DATA                  = 0x0013, // ByteString
+  STUN_ATTR_OPTIONS               = 0x8001  // UInt32
+};
+
+enum StunErrorCodes {
+  STUN_ERROR_BAD_REQUEST          = 400,
+  STUN_ERROR_UNAUTHORIZED         = 401,
+  STUN_ERROR_UNKNOWN_ATTRIBUTE    = 420,
+  STUN_ERROR_STALE_CREDENTIALS    = 430,
+  STUN_ERROR_INTEGRITY_CHECK_FAILURE = 431,
+  STUN_ERROR_MISSING_USERNAME     = 432,
+  STUN_ERROR_USE_TLS              = 433,
+  STUN_ERROR_SERVER_ERROR         = 500,
+  STUN_ERROR_GLOBAL_FAILURE       = 600
+};
+
+extern const std::string STUN_ERROR_REASON_BAD_REQUEST;
+extern const std::string STUN_ERROR_REASON_UNAUTHORIZED;
+extern const std::string STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE;
+extern const std::string STUN_ERROR_REASON_STALE_CREDENTIALS;
+extern const std::string STUN_ERROR_REASON_INTEGRITY_CHECK_FAILURE;
+extern const std::string STUN_ERROR_REASON_MISSING_USERNAME;
+extern const std::string STUN_ERROR_REASON_USE_TLS;
+extern const std::string STUN_ERROR_REASON_SERVER_ERROR;
+extern const std::string STUN_ERROR_REASON_GLOBAL_FAILURE;
+
+class StunAttribute;
+class StunAddressAttribute;
+class StunUInt32Attribute;
+class StunByteStringAttribute;
+class StunErrorCodeAttribute;
+class StunUInt16ListAttribute;
+class StunTransportPrefsAttribute;
+
+// Records a complete STUN/TURN message.  Each message consists of a type and
+// any number of attributes.  Each attribute is parsed into an instance of an
+// appropriate class (see above).  The Get* methods will return instances of
+// that attribute class.
+class StunMessage {
+public:
+  StunMessage();
+  ~StunMessage();
+
+  StunMessageType type() const { return static_cast<StunMessageType>(type_); }
+  uint16 length() const { return length_; }
+  const std::string& transaction_id() const { return transaction_id_; }
+
+  void SetType(StunMessageType type) { type_ = type; }
+  void SetTransactionID(const std::string& str);
+
+  const StunAddressAttribute* GetAddress(StunAttributeType type) const;
+  const StunUInt32Attribute* GetUInt32(StunAttributeType type) const;
+  const StunByteStringAttribute* GetByteString(StunAttributeType type) const;
+  const StunErrorCodeAttribute* GetErrorCode() const;
+  const StunUInt16ListAttribute* GetUnknownAttributes() const;
+  const StunTransportPrefsAttribute* GetTransportPrefs() const;
+
+  void AddAttribute(StunAttribute* attr);
+
+  // Parses the STUN/TURN packet in the given buffer and records it here.  The
+  // return value indicates whether this was successful.
+  bool Read(talk_base::ByteBuffer* buf);
+
+  // Writes this object into a STUN/TURN packet.  Return value is true if
+  // successful.
+  void Write(talk_base::ByteBuffer* buf) const;
+
+private:
+  uint16 type_;
+  uint16 length_;
+  std::string transaction_id_;
+  std::vector<StunAttribute*>* attrs_;
+
+  const StunAttribute* GetAttribute(StunAttributeType type) const;
+};
+
+// Base class for all STUN/TURN attributes.
+class StunAttribute {
+public:
+  virtual ~StunAttribute() {}
+
+  StunAttributeType type() const {
+    return static_cast<StunAttributeType>(type_);
+  } 
+  uint16 length() const { return length_; }
+
+  // Reads the body (not the type or length) for this type of attribute from
+  // the given buffer.  Return value is true if successful.
+  virtual bool Read(talk_base::ByteBuffer* buf) = 0;
+
+  // Writes the body (not the type or length) to the given buffer.  Return
+  // value is true if successful.
+  virtual void Write(talk_base::ByteBuffer* buf) const = 0;
+
+  // Creates an attribute object with the given type and len.
+  static StunAttribute* Create(uint16 type, uint16 length);
+
+  // Creates an attribute object with the given type and smallest length.
+  static StunAddressAttribute* CreateAddress(uint16 type);
+  static StunUInt32Attribute* CreateUInt32(uint16 type);
+  static StunByteStringAttribute* CreateByteString(uint16 type);
+  static StunErrorCodeAttribute* CreateErrorCode();
+  static StunUInt16ListAttribute* CreateUnknownAttributes();
+  static StunTransportPrefsAttribute* CreateTransportPrefs();
+
+protected:
+  StunAttribute(uint16 type, uint16 length);
+
+  void SetLength(uint16 length) { length_ = length; }
+
+private:
+  uint16 type_;
+  uint16 length_;
+};
+
+// Implements STUN/TURN attributes that record an Internet address.
+class StunAddressAttribute : public StunAttribute {
+public:
+  StunAddressAttribute(uint16 type);
+
+#if (_MSC_VER < 1300)
+  enum { SIZE = 8 };
+#else
+  static const uint16 SIZE = 8;
+#endif
+
+  uint8 family() const { return family_; }
+  uint16 port() const { return port_; }
+  uint32 ip() const { return ip_; }
+
+  void SetFamily(uint8 family) { family_ = family; }
+  void SetIP(uint32 ip) { ip_ = ip; }
+  void SetPort(uint16 port) { port_ = port; }
+
+  bool Read(talk_base::ByteBuffer* buf);
+  void Write(talk_base::ByteBuffer* buf) const;
+
+private:
+  uint8 family_;
+  uint16 port_;
+  uint32 ip_;
+};
+
+// Implements STUN/TURN attributs that record a 32-bit integer.
+class StunUInt32Attribute : public StunAttribute {
+public:
+  StunUInt32Attribute(uint16 type);
+
+#if (_MSC_VER < 1300)
+  enum { SIZE = 4 };
+#else
+  static const uint16 SIZE = 4;
+#endif
+
+  uint32 value() const { return bits_; }
+
+  void SetValue(uint32 bits) { bits_ = bits; }
+
+  bool GetBit(int index) const;
+  void SetBit(int index, bool value);
+
+  bool Read(talk_base::ByteBuffer* buf);
+  void Write(talk_base::ByteBuffer* buf) const;
+
+private:
+  uint32 bits_;
+};
+
+// Implements STUN/TURN attributs that record an arbitrary byte string
+class StunByteStringAttribute : public StunAttribute {
+public:
+  StunByteStringAttribute(uint16 type, uint16 length);
+  ~StunByteStringAttribute();
+
+  const char* bytes() const { return bytes_; }
+
+  void SetBytes(char* bytes, uint16 length);
+
+  void CopyBytes(const char* bytes); // uses strlen
+  void CopyBytes(const void* bytes, uint16 length);
+
+  uint8 GetByte(int index) const;
+  void SetByte(int index, uint8 value);
+
+  bool Read(talk_base::ByteBuffer* buf);
+  void Write(talk_base::ByteBuffer* buf) const;
+
+private:
+  char* bytes_;
+};
+
+// Implements STUN/TURN attributs that record an error code.
+class StunErrorCodeAttribute : public StunAttribute {
+public:
+  StunErrorCodeAttribute(uint16 type, uint16 length);
+  ~StunErrorCodeAttribute();
+
+#if (_MSC_VER < 1300)
+  enum { MIN_SIZE = 4 };
+#else
+  static const uint16 MIN_SIZE = 4;
+#endif
+
+  uint32 error_code() const { return (class_ << 8) | number_; }
+  uint8 error_class() const { return class_; }
+  uint8 number() const { return number_; }
+  const std::string& reason() const { return reason_; }
+
+  void SetErrorCode(uint32 code);
+  void SetErrorClass(uint8 eclass) { class_ = eclass; }
+  void SetNumber(uint8 number) { number_ = number; }
+  void SetReason(const std::string& reason);
+
+  bool Read(talk_base::ByteBuffer* buf);
+  void Write(talk_base::ByteBuffer* buf) const;
+
+private:
+  uint8 class_;
+  uint8 number_;
+  std::string reason_;
+};
+
+// Implements STUN/TURN attributs that record a list of attribute names.
+class StunUInt16ListAttribute : public StunAttribute {
+public:
+  StunUInt16ListAttribute(uint16 type, uint16 length);
+  ~StunUInt16ListAttribute();
+
+  size_t Size() const;
+  uint16 GetType(int index) const;
+  void SetType(int index, uint16 value);
+  void AddType(uint16 value);
+
+  bool Read(talk_base::ByteBuffer* buf);
+  void Write(talk_base::ByteBuffer* buf) const;
+
+private:
+  std::vector<uint16>* attr_types_;
+};
+
+// Implements the TURN TRANSPORT-PREFS attribute, which provides information
+// about the ports to allocate.
+class StunTransportPrefsAttribute : public StunAttribute {
+public:
+  StunTransportPrefsAttribute(uint16 type, uint16 length);
+  ~StunTransportPrefsAttribute();
+
+#if (_MSC_VER < 1300)
+  enum { SIZE1 = 4, SIZE2 = 12 };
+#else
+  static const uint16 SIZE1 = 4;
+  static const uint16 SIZE2 = 12;
+#endif
+
+  bool preallocate() const { return preallocate_; }
+  uint8 preference_type() const { return prefs_; }
+  const StunAddressAttribute* address() const { return addr_; }
+
+  void SetPreferenceType(uint8 prefs) { prefs_ = prefs; }
+
+  // Sets the preallocate address to the given value, or if 0 is given, it sets
+  // to not preallocate.
+  void SetPreallocateAddress(StunAddressAttribute* addr);
+
+  bool Read(talk_base::ByteBuffer* buf);
+  void Write(talk_base::ByteBuffer* buf) const;
+
+private:
+  bool preallocate_;
+  uint8 prefs_;
+  StunAddressAttribute* addr_;
+};
+
+// The special MAGIC-COOKIE attribute is used to distinguish TURN packets from
+// other kinds of traffic.
+const char STUN_MAGIC_COOKIE_VALUE[] = { 0x72, char(0xc6), 0x4b, char(0xc6) };
+
+// Returns the (successful) response type for the given request type.
+StunMessageType GetStunResponseType(StunMessageType request_type);
+
+// Returns the error response type for the given request type.
+StunMessageType GetStunErrorResponseType(StunMessageType request_type);
+
+} // namespace cricket
+
+#endif // __STUN_H__
diff --git a/talk/p2p/base/stunport.cc b/talk/p2p/base/stunport.cc
new file mode 100755
index 0000000..8fa3fd8
--- /dev/null
+++ b/talk/p2p/base/stunport.cc
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+#include <iostream>
+#include <cassert>
+#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
+
+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
+
+// Handles a binding request sent to the STUN server.
+class StunPortBindingRequest : public StunRequest {
+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();
+  }
+
+  virtual ~StunPortBindingRequest() {
+  }
+
+  const talk_base::SocketAddress& server_addr() const { return server_addr_; }
+
+  virtual void Prepare(StunMessage* request) {
+    request->SetType(STUN_BINDING_REQUEST);
+  }
+
+  virtual void OnResponse(StunMessage* response) {
+    const StunAddressAttribute* addr_attr =
+        response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
+    if (!addr_attr) {
+      LOG(LERROR) << "Binding response missing mapped address.";
+    } else if (addr_attr->family() != 1) {
+      LOG(LERROR) << "Binding address has bad family";
+    } else {
+      talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port());
+      port_->AddAddress(addr, "udp", true);
+    }
+
+    // We will do a keep-alive regardless of whether this request suceeds.
+    // This should have almost no impact on network usage.
+    if (keep_alive_) {
+      port_->requests_.SendDelayed(
+          new StunPortBindingRequest(port_, true, server_addr_),
+          KEEPALIVE_DELAY);
+    }
+  }
+
+  virtual void OnErrorResponse(StunMessage* response) {
+    const StunErrorCodeAttribute* attr = response->GetErrorCode();
+    if (!attr) {
+      LOG(LERROR) << "Bad allocate response error code";
+    } else {
+      LOG(LERROR) << "Binding error response:"
+                 << " class=" << attr->error_class()
+                 << " number=" << attr->number()
+                 << " reason='" << attr->reason() << "'";
+    }
+
+    port_->SignalAddressError(port_);
+
+    if (keep_alive_ 
+        && (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)) {
+      port_->requests_.SendDelayed(
+          new StunPortBindingRequest(port_, true, server_addr_),
+          KEEPALIVE_DELAY);
+    }
+  }
+
+  virtual void OnTimeout() {
+    LOG(LERROR) << "Binding request timed out from " 
+      << port_->GetLocalAddress().ToString() 
+      << " (" << port_->network()->name() << ")";
+
+    port_->SignalAddressError(port_);
+
+    if (keep_alive_ 
+        && (talk_base::GetMillisecondCount() - start_time_ <= RETRY_TIMEOUT)) {
+      port_->requests_.SendDelayed(
+          new StunPortBindingRequest(port_, true, server_addr_),
+          RETRY_DELAY);
+    }
+  }
+
+private:
+  StunPort* port_;
+  bool keep_alive_;
+  talk_base::SocketAddress server_addr_;
+  uint32 start_time_;
+};
+
+const std::string STUN_PORT_TYPE("stun");
+
+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";
+
+  requests_.SignalSendPacket.connect(this, &StunPort::OnSendPacket);
+}
+
+StunPort::~StunPort() {
+  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_));
+}
+
+void StunPort::PrepareSecondaryAddress() {
+  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) {
+  int sent = socket_->SendTo(data, size, addr);
+  if (sent < 0)
+    error_ = socket_->GetError();
+  return sent;
+}
+
+int StunPort::SetOption(talk_base::Socket::Option opt, int value) {
+  return socket_->SetOption(opt, value);
+}
+
+int StunPort::GetError() {
+  return error_;
+}
+
+void StunPort::OnReadPacket(
+    const char* data, size_t size, const talk_base::SocketAddress& remote_addr,
+    talk_base::AsyncPacketSocket* 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);
+}
+
+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
diff --git a/talk/p2p/base/stunport.h b/talk/p2p/base/stunport.h
new file mode 100755
index 0000000..4b62181
--- /dev/null
+++ b/talk/p2p/base/stunport.h
@@ -0,0 +1,94 @@
+/*
+ * 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 __STUNPORT_H__
+#define __STUNPORT_H__
+
+#include "talk/base/asyncudpsocket.h"
+#include "talk/p2p/base/udpport.h"
+#include "talk/p2p/base/stunrequest.h"
+
+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, 
+           const talk_base::SocketAddress& server_addr);
+  virtual ~StunPort();
+
+  const talk_base::SocketAddress& server_addr() const { return server_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; }
+
+  virtual void PrepareAddress();
+
+  // This will contact the secondary server and signal another candidate
+  // 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 int SetOption(talk_base::Socket::Option opt, int value);
+  virtual int GetError();
+
+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,
+      talk_base::AsyncPacketSocket* socket);
+
+private:
+  talk_base::AsyncPacketSocket* socket_;
+  talk_base::SocketAddress server_addr_;
+  talk_base::SocketAddress server_addr2_;
+  StunRequestManager requests_;
+  int error_;
+
+  friend class StunPortBindingRequest;
+
+  // Sends STUN requests to the server.
+  void OnSendPacket(const void* data, size_t size, StunRequest* req);
+};
+
+} // namespace cricket
+
+#endif // __STUNPORT_H__
diff --git a/talk/p2p/base/stunrequest.cc b/talk/p2p/base/stunrequest.cc
new file mode 100755
index 0000000..66b8ef6
--- /dev/null
+++ b/talk/p2p/base/stunrequest.cc
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+#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>
+
+namespace cricket {
+
+const uint32 MSG_STUN_SEND = 1;
+
+const int MAX_SENDS = 9;
+const int DELAY_UNIT = 100; // 100 milliseconds
+const int DELAY_MAX_FACTOR = 16;
+
+StunRequestManager::StunRequestManager(talk_base::Thread* thread) 
+    : thread_(thread) {
+    }
+
+StunRequestManager::~StunRequestManager() {
+  while (requests_.begin() != requests_.end()) {
+    StunRequest *request = requests_.begin()->second;
+    requests_.erase(requests_.begin());
+    delete request;
+  }
+}
+
+void StunRequestManager::Send(StunRequest* request) {
+  SendDelayed(request, 0);
+}
+
+void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
+  request->set_manager(this);
+  assert(requests_.find(request->id()) == requests_.end());
+  requests_[request->id()] = request;
+  thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL);
+}
+
+void StunRequestManager::Remove(StunRequest* request) {
+  assert(request->manager() == this);
+  RequestMap::iterator iter = requests_.find(request->id());
+  if (iter != requests_.end()) {
+    assert(iter->second == request);
+    requests_.erase(iter);
+    thread_->Clear(request);
+  }
+}
+
+void StunRequestManager::Clear() {
+  std::vector<StunRequest*> requests;
+  for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i)
+    requests.push_back(i->second);
+
+  for (uint32 i = 0; i < requests.size(); ++i)
+    Remove(requests[i]);
+}
+
+bool StunRequestManager::CheckResponse(StunMessage* msg) {
+  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);
+  } else if (msg->type() == GetStunErrorResponseType(request->type())) {
+    request->OnErrorResponse(msg);
+  } else {
+    LOG(LERROR) << "Received response with wrong type: " << msg->type()
+               << " (expecting " << GetStunResponseType(request->type()) << ")";
+    return false;
+  }
+
+  delete request;
+  return true;
+}
+
+bool StunRequestManager::CheckResponse(const char* data, size_t size) {
+  // Check the appropriate bytes of the stream to see if they match the
+  // transaction ID of a response we are expecting.
+
+  if (size < 20)
+    return false;
+
+  std::string id;
+  id.append(data + 4, 16);
+
+  RequestMap::iterator iter = requests_.find(id);
+  if (iter == requests_.end())
+    return false;
+
+  // Parse the STUN message and continue processing as usual.
+
+  talk_base::ByteBuffer buf(data, size);
+  StunMessage msg;
+  if (!msg.Read(&buf))
+    return false;
+
+  return CheckResponse(&msg);
+}
+
+StunRequest::StunRequest()
+  : manager_(0), id_(CreateRandomString(16)), msg_(0), count_(0),
+    timeout_(false), tstamp_(0) {
+}
+
+StunRequest::StunRequest(StunMessage* request)
+  : manager_(0), id_(request->transaction_id()), msg_(request),
+    count_(0), timeout_(false) {
+}
+
+StunRequest::~StunRequest() {
+  assert(manager_ != NULL);
+  if (manager_) {
+    manager_->Remove(this);
+    manager_->thread_->Clear(this);
+  }
+  delete msg_;
+}
+
+const StunMessageType StunRequest::type() {
+  assert(msg_);
+  return msg_->type();
+}
+
+void StunRequest::set_manager(StunRequestManager* 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_);
+  }
+
+  if (timeout_) {
+    OnTimeout();
+    delete this;
+    return;
+  }
+
+  tstamp_ = talk_base::GetMillisecondCount();
+
+  talk_base::ByteBuffer buf;
+  msg_->Write(&buf);
+  manager_->SignalSendPacket(buf.Data(), buf.Length(), this);
+
+  int delay = GetNextDelay();
+  manager_->thread_->PostDelayed(delay, this, MSG_STUN_SEND, NULL);
+}
+
+uint32 StunRequest::Elapsed() const {
+  return (talk_base::GetMillisecondCount() - tstamp_);
+}
+
+int StunRequest::GetNextDelay() {
+  int delay = DELAY_UNIT * talk_base::_min(1 << count_, DELAY_MAX_FACTOR);
+  count_ += 1;
+  if (count_ == MAX_SENDS)
+    timeout_ = true;
+  return delay;
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/stunrequest.h b/talk/p2p/base/stunrequest.h
new file mode 100755
index 0000000..b36861c
--- /dev/null
+++ b/talk/p2p/base/stunrequest.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.
+ */
+
+#ifndef __STUNREQUESTMANAGER_H__
+#define __STUNREQUESTMANAGER_H__
+
+#include "talk/base/sigslot.h"
+#include "talk/base/thread.h"
+#include "talk/p2p/base/stun.h"
+#include <map>
+#include <string>
+
+namespace cricket {
+
+class StunRequest;
+
+// Manages a set of STUN requests, sending and resending until we receive a
+// response or determine that the request has timed out.
+class StunRequestManager {
+public:
+  StunRequestManager(talk_base::Thread* thread);
+  ~StunRequestManager();
+
+  // Starts sending the given request (perhaps after a delay).
+  void Send(StunRequest* request);
+  void SendDelayed(StunRequest* request, int delay);
+
+  // Removes a stun request that was added previously.  This will happen
+  // automatically when a request succeeds, fails, or times out.
+  void Remove(StunRequest* request);
+
+  // Removes all stun requests that were added previously.
+  void Clear();
+
+  // Determines whether the given message is a response to one of the
+  // outstanding requests, and if so, processes it appropriately.
+  bool CheckResponse(StunMessage* msg);
+  bool CheckResponse(const char* data, size_t size);
+
+  // Raised when there are bytes to be sent.
+  sigslot::signal3<const void*, size_t, StunRequest*> SignalSendPacket;
+
+private:
+  typedef std::map<std::string, StunRequest*> RequestMap;
+
+  talk_base::Thread* thread_;
+  RequestMap requests_;
+
+  friend class StunRequest;
+};
+
+// Represents an individual request to be sent.  The STUN message can either be
+// constructed beforehand or built on demand.
+class StunRequest : public talk_base::MessageHandler {
+public:
+  StunRequest();
+  StunRequest(StunMessage* request);
+  virtual ~StunRequest();
+
+  // The manager handling this request (if it has been scheduled for sending).
+  StunRequestManager* manager() { return manager_; }
+
+  // Returns the transaction ID of this request.
+  const std::string& id() { return id_; }
+
+  // Returns the STUN type of the request message.
+  const StunMessageType type();
+
+  // Handles messages for sending and timeout.
+  void OnMessage(talk_base::Message* pmsg);
+
+  // Time elapsed since last send (in ms)
+  uint32 Elapsed() const;
+
+protected:
+  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.
+  virtual void Prepare(StunMessage* request) {}
+
+  // Called when the message receives a response or times out.
+  virtual void OnResponse(StunMessage* response) {}
+  virtual void OnErrorResponse(StunMessage* response) {}
+  virtual void OnTimeout() {}
+  virtual int GetNextDelay();
+
+private:
+  StunRequestManager* manager_;
+  std::string id_;
+  StunMessage* msg_;
+  uint32 tstamp_;
+
+  void set_manager(StunRequestManager* manager);
+
+  friend class StunRequestManager;
+};
+
+} // namespace cricket
+
+#endif // __STUNREQUESTMANAGER_H__
diff --git a/talk/p2p/base/stunserver.cc b/talk/p2p/base/stunserver.cc
new file mode 100755
index 0000000..5fc61ac
--- /dev/null
+++ b/talk/p2p/base/stunserver.cc
@@ -0,0 +1,160 @@
+/*
+ * 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/bytebuffer.h"
+#include "talk/p2p/base/stunserver.h"
+#include <iostream>
+
+#ifdef POSIX
+extern "C" {
+#include <errno.h>
+}
+#endif // POSIX
+
+namespace cricket {
+
+StunServer::StunServer(talk_base::AsyncUDPSocket* socket) : socket_(socket) {
+  socket_->SignalReadPacket.connect(this, &StunServer::OnPacket);
+}
+
+StunServer::~StunServer() {
+  socket_->SignalReadPacket.disconnect(this);
+}
+
+void StunServer::OnPacket(
+    const char* buf, size_t size, const talk_base::SocketAddress& remote_addr,
+    talk_base::AsyncPacketSocket* socket) {
+
+  // TODO: If appropriate, look for the magic cookie before parsing.
+
+  // Parse the STUN message.
+  talk_base::ByteBuffer bbuf(buf, size);
+  StunMessage msg;
+  if (!msg.Read(&bbuf)) {
+    SendErrorResponse(msg, remote_addr, 400, "Bad Request");
+    return;
+  }
+
+  // TODO: If this is UDP, then we shouldn't allow non-fully-parsed messages.
+
+  // TODO: If unknown non-optiional (<= 0x7fff) attributes are found, send a
+  //       420 "Unknown Attribute" response.
+
+  // TODO: Check that a message-integrity attribute was given (or send 401
+  //       "Unauthorized").  Check that a username attribute was given (or send
+  //       432 "Missing Username").  Look up the username and password.  If it
+  //       is missing or the HMAC is wrong, send 431 "Integrity Check Failure".
+
+  // Send the message to the appropriate handler function.
+  switch (msg.type()) {
+  case STUN_BINDING_REQUEST:
+    OnBindingRequest(&msg, remote_addr);
+    return;
+
+  case STUN_ALLOCATE_REQUEST:
+    OnAllocateRequest(&msg, remote_addr);
+    return;
+
+  default:
+    SendErrorResponse(msg, remote_addr, 600, "Operation Not Supported");
+  }
+}
+
+void StunServer::OnBindingRequest(
+    StunMessage* msg, const talk_base::SocketAddress& remote_addr) {
+  StunMessage response;
+  response.SetType(STUN_BINDING_RESPONSE);
+  response.SetTransactionID(msg->transaction_id());
+
+  // Tell the user the address that we received their request from.
+  StunAddressAttribute* mapped_addr =
+      StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
+  mapped_addr->SetFamily(1);
+  mapped_addr->SetPort(remote_addr.port());
+  mapped_addr->SetIP(remote_addr.ip());
+  response.AddAttribute(mapped_addr);
+
+  // Tell the user the address that we are sending the response from.
+  talk_base::SocketAddress local_addr = socket_->GetLocalAddress();
+  StunAddressAttribute* source_addr =
+      StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS);
+  source_addr->SetFamily(1);
+  source_addr->SetPort(local_addr.port());
+  source_addr->SetIP(local_addr.ip());
+  response.AddAttribute(source_addr);
+
+  // TODO: Add username and message-integrity.
+
+  // TODO: Add changed-address.  (Keep information about three other servers.)
+
+  SendResponse(response, remote_addr);
+}
+
+void StunServer::OnAllocateRequest(
+    StunMessage* msg, const talk_base::SocketAddress& addr) {
+  SendErrorResponse(*msg, addr, 600, "Operation Not Supported");
+}
+
+void StunServer::OnSharedSecretRequest(
+    StunMessage* msg, const talk_base::SocketAddress& addr) {
+  SendErrorResponse(*msg, addr, 600, "Operation Not Supported");
+}
+
+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) {
+
+  StunMessage err_msg;
+  err_msg.SetType(GetStunErrorResponseType(msg.type()));
+  err_msg.SetTransactionID(msg.transaction_id());
+
+  StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode();
+  err_code->SetErrorClass(error_code / 100);
+  err_code->SetNumber(error_code % 100);
+  err_code->SetReason(error_desc);
+  err_msg.AddAttribute(err_code);
+
+  SendResponse(err_msg, addr);
+}
+
+void StunServer::SendResponse(
+    const StunMessage& msg, const talk_base::SocketAddress& addr) {
+
+  talk_base::ByteBuffer buf;
+  msg.Write(&buf);
+
+  // 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;
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/stunserver.h b/talk/p2p/base/stunserver.h
new file mode 100755
index 0000000..0e57a18
--- /dev/null
+++ b/talk/p2p/base/stunserver.h
@@ -0,0 +1,73 @@
+/*
+ * 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 __STUNSERVER_H__
+#define __STUNSERVER_H__
+
+#include "talk/base/asyncudpsocket.h"
+#include "talk/p2p/base/stun.h"
+
+namespace cricket {
+
+const int STUN_SERVER_PORT = 3478;
+
+class StunServer : public sigslot::has_slots<> {
+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.
+  ~StunServer();
+
+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);
+
+  // 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);
+
+  // Sends the given message to the appropriate destination.
+  void SendResponse(const StunMessage& msg, const talk_base::SocketAddress& addr);
+
+private:
+  talk_base::AsyncUDPSocket* socket_;
+};
+
+} // namespace cricket
+
+#endif // __STUNSERVER_H__
diff --git a/talk/p2p/base/stunserver_main.cc b/talk/p2p/base/stunserver_main.cc
new file mode 100755
index 0000000..8aa200e
--- /dev/null
+++ b/talk/p2p/base/stunserver_main.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/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;
+    return 1;
+  }
+
+  talk_base::SocketAddress server_addr(talk_base::LocalHost().networks()[1]->ip(), 7000);
+
+  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;
+  }
+
+  StunServer* server = new StunServer(server_socket);
+
+  std::cout << "Listening at " << server_addr.ToString() << std::endl;
+
+  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
new file mode 100755
index 0000000..b56da4e
--- /dev/null
+++ b/talk/p2p/base/stunserver_unittest.cc
@@ -0,0 +1,107 @@
+#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
new file mode 100755
index 0000000..57e2a4f
--- /dev/null
+++ b/talk/p2p/base/tcpport.cc
@@ -0,0 +1,271 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#ifdef POSIX
+extern "C" {
+#include <errno.h>
+}
+#endif // POSIX
+
+#include <cassert>
+#include <iostream>
+
+#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"
+
+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)
+    : 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();
+  }
+}
+
+TCPPort::~TCPPort() {
+  delete socket_;
+}
+
+Connection* TCPPort::CreateConnection(const Candidate& address,
+                                      CandidateOrigin origin) {
+  // We only support TCP protocols
+  if ((address.protocol() != "tcp") && (address.protocol() != "ssltcp"))
+    return 0;
+
+  // We can't accept TCP connections incoming on other ports
+  if (origin == ORIGIN_OTHER_PORT)
+    return 0;
+
+  // Check if we are allowed to make outgoing TCP connections
+  if (incoming_only_ && (origin == ORIGIN_MESSAGE))
+    return 0;
+
+  // We don't know how to act as an ssl server yet
+  if ((address.protocol() == "ssltcp") && (origin == ORIGIN_THIS_PORT))
+    return 0;
+
+  TCPConnection* conn = 0;
+  if (talk_base::AsyncTCPSocket * socket 
+        = GetIncoming(address.address(), true)) {
+    socket->SignalReadPacket.disconnect(this);
+    conn = new TCPConnection(this, address, socket);
+  } else {
+    conn = new TCPConnection(this, address);
+  }
+  AddConnection(conn);
+  return conn;
+}
+
+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";
+  } else if (socket_->Listen(5) < 0) {
+    LOG_F(LS_ERROR) << "Listen 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, 
+                    const talk_base::SocketAddress& addr, bool payload) {
+  talk_base::AsyncTCPSocket * socket = 0;
+
+  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_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_;
+  }
+  return sent;
+}
+
+int TCPPort::SetOption(talk_base::Socket::Option opt, int value) {
+  return socket_->SetOption(opt, value);
+}
+
+int TCPPort::GetError() {
+  assert(socket_);
+  return error_;
+}
+
+void TCPPort::OnAcceptEvent(talk_base::AsyncSocket* socket) {
+  assert(socket == socket_);
+
+  Incoming incoming;
+  talk_base::AsyncSocket * newsocket 
+    = static_cast<talk_base::AsyncSocket *>(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();
+    return;
+  }
+  incoming.socket = new talk_base::AsyncTCPSocket(newsocket);
+  incoming.socket->SignalReadPacket.connect(this, &TCPPort::OnReadPacket);
+
+  LOG_F(LS_VERBOSE) << "(" << incoming.addr.ToString() << ")";
+  incoming_.push_back(incoming);
+
+  // Prime a read event in case data is waiting
+  newsocket->SignalReadEvent(newsocket);
+}
+
+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(); 
+       it != incoming_.end(); ++it) {
+    if (it->addr == addr) {
+      socket = it->socket;
+      if (remove)
+        incoming_.erase(it);
+      break;
+    }
+  }
+  return socket;
+}
+
+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, 
+                             talk_base::AsyncTCPSocket* socket)
+    : Connection(port, 0, candidate), socket_(socket), error_(0) {
+  bool outgoing = (socket_ == 0);
+  if (outgoing) {
+    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_));
+  }
+  socket_->SignalReadPacket.connect(this, &TCPConnection::OnReadPacket);
+  socket_->SignalClose.connect(this, &TCPConnection::OnClose);
+  if (outgoing) {
+    set_connected(false);
+    talk_base::SocketAddress local_address(port->address_.ip(), 0);
+    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();
+  }
+}
+
+TCPConnection::~TCPConnection() {
+  delete socket_;
+}
+
+int TCPConnection::Send(const void* data, size_t size) {
+  if (write_state() != STATE_WRITABLE) {
+    // TODO: Should STATE_WRITE_TIMEOUT return a non-blocking error?
+    error_ = EWOULDBLOCK;
+    return SOCKET_ERROR;
+  }
+  int sent = socket_->Send(data, size);
+  if (sent < 0) {
+    error_ = socket_->GetError();
+  } else {
+    sent_total_bytes_ += sent;
+  }
+  return sent;
+}
+
+int TCPConnection::GetError() {
+  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() << ")";
+  set_connected(true);
+}
+
+void TCPConnection::OnClose(talk_base::AsyncTCPSocket* socket, int error) {
+  assert(socket == socket_);
+  LOG_F(LS_VERBOSE) << "(" << error << ")";
+  set_connected(false);
+  set_write_state(STATE_WRITE_TIMEOUT);
+}
+
+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() << ")";
+  Connection::OnReadPacket(data, size);
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/tcpport.h b/talk/p2p/base/tcpport.h
new file mode 100755
index 0000000..24555ae
--- /dev/null
+++ b/talk/p2p/base/tcpport.h
@@ -0,0 +1,122 @@
+/*
+ * 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 __TCPPORT_H__
+#define __TCPPORT_H__
+
+#include <list>
+#include "talk/base/asynctcpsocket.h"
+#include "talk/p2p/base/port.h"
+
+namespace cricket {
+
+class TCPConnection;
+
+extern const std::string LOCAL_PORT_TYPE; // type of TCP ports
+
+// Communicates using a local TCP 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 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);
+  virtual ~TCPPort();
+
+  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:
+  // Handles sending using the local TCP socket.
+  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_;
+
+  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);
+
+  // 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);
+
+  friend class TCPConnection;
+};
+
+class TCPConnection : public Connection {
+public:
+  // Connection is outgoing unless socket is specified
+  TCPConnection(TCPPort* port, const Candidate& candidate, 
+    talk_base::AsyncTCPSocket* socket = 0);
+  virtual ~TCPConnection();
+
+  virtual int Send(const void* data, size_t size);
+  virtual int GetError();
+
+  talk_base::AsyncTCPSocket * socket() { return socket_; }
+
+private:
+  TCPPort* tcpport();
+  talk_base::AsyncTCPSocket* socket_;
+  int error_;
+
+  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);
+
+  friend class TCPPort;
+};
+
+} // namespace cricket
+
+#endif // __TCPPORT_H__
diff --git a/talk/p2p/base/transport.cc b/talk/p2p/base/transport.cc
new file mode 100755
index 0000000..dfa2dfd
--- /dev/null
+++ b/talk/p2p/base/transport.cc
@@ -0,0 +1,441 @@
+/*
+ * 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/p2p/base/transport.h"
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/base/transportchannelimpl.h"
+#include "talk/p2p/base/constants.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/constants.h"
+
+namespace {
+
+struct ChannelParams {
+  std::string name;
+  std::string session_type;
+  cricket::TransportChannelImpl* channel;
+  buzz::XmlElement* elem;
+
+  ChannelParams() : channel(NULL), elem(NULL) {}
+};
+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;
+
+}  // 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() {
+  ASSERT(session_manager_->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;
+  ChannelMessage msg(&params);
+  session_manager_->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* impl = CreateTransportChannel(name, session_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);
+
+  talk_base::CritScope cs(&crit_);
+  ASSERT(channels_.find(name) == channels_.end());
+  channels_[name] = impl;
+  destroyed_ = false;
+  if (connect_requested_) {
+    impl->Connect();
+    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);
+    }
+  }
+  return impl;
+}
+
+TransportChannelImpl* Transport::GetChannel(const std::string& name) {
+  talk_base::CritScope cs(&crit_);
+  ChannelMap::iterator iter = channels_.find(name);
+  return (iter != channels_.end()) ? iter->second : NULL;
+}
+
+bool Transport::HasChannels() {
+  talk_base::CritScope cs(&crit_);
+  return !channels_.empty();
+}
+
+void Transport::DestroyChannel(const std::string& name) {
+  ChannelParams params;
+  params.name = name;
+  ChannelMessage msg(&params);
+  session_manager_->worker_thread()->Send(this, MSG_DESTROYCHANNEL, &msg);
+}
+
+void Transport::DestroyChannel_w(const std::string& name) {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  TransportChannelImpl* impl = NULL;
+  {
+    talk_base::CritScope cs(&crit_);
+    ChannelMap::iterator iter = channels_.find(name);
+    ASSERT(iter != channels_.end());
+    impl = iter->second;
+    channels_.erase(iter);
+  }
+
+  if (connect_requested_ && channels_.empty()) {
+    // We're not longer attempting to connect.
+    session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL);
+  }
+
+  if (impl)
+    DestroyTransportChannel(impl);
+}
+
+void Transport::ConnectChannels() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  session_manager_->worker_thread()->Post(this, MSG_CONNECTCHANNELS, NULL);
+}
+
+void Transport::ConnectChannels_w() {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  if (connect_requested_)
+    return;
+  connect_requested_ = true;
+  session_manager_->signaling_thread()->Post(this, MSG_ONCHANNELMESSAGE, NULL);
+  CallChannels_w(&TransportChannelImpl::Connect);
+  if (!channels_.empty()) {
+    session_manager_->signaling_thread()->Post(this, MSG_CONNECTING, NULL);
+  }
+}
+
+void Transport::OnConnecting_s() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  SignalConnecting(this);
+}
+ 
+void Transport::DestroyAllChannels() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  session_manager_->worker_thread()->Send(this, MSG_DESTROYALLCHANNELS, NULL);
+  destroyed_ = true;
+}
+
+void Transport::DestroyAllChannels_w() {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  std::vector<TransportChannelImpl*> impls;
+  {
+    talk_base::CritScope cs(&crit_);
+    for (ChannelMap::iterator iter = channels_.begin();
+         iter != channels_.end();
+         ++iter) {
+      impls.push_back(iter->second);
+    }
+    channels_.clear();
+  }
+
+  for (size_t i = 0; i < impls.size(); ++i)
+    DestroyTransportChannel(impls[i]);
+}
+
+void Transport::ResetChannels() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  session_manager_->worker_thread()->Post(this, MSG_RESETCHANNELS, NULL);
+}
+
+void Transport::ResetChannels_w() {
+  ASSERT(session_manager_->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();
+
+  // 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);
+
+  // Notify the subclass.
+  OnTransportSignalingReady();
+}
+
+void Transport::CallChannels_w(TransportChannelFunc func) {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  talk_base::CritScope cs(&crit_);
+  for (ChannelMap::iterator iter = channels_.begin();
+       iter != channels_.end();
+       ++iter) {
+    ((iter->second)->*func)();
+  }
+}
+
+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);
+}
+
+void Transport::ForwardChannelMessage_w(const std::string& name,
+                                        buzz::XmlElement* elem) {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  ChannelMap::iterator iter = channels_.find(name);
+  // It's ok for a channel to go away while this message is in transit.
+  if (iter != channels_.end()) {
+    iter->second->OnChannelMessage(elem);
+  }
+  delete elem;
+}
+
+void Transport::OnChannelReadableState(TransportChannel* channel) {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  session_manager_->signaling_thread()->Post(this, MSG_READSTATE, NULL);
+}
+
+void Transport::OnChannelReadableState_s() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  bool readable = GetTransportState_s(true);
+  if (readable_ != readable) {
+    readable_ = readable;
+    SignalReadableState(this);
+  }
+}
+
+void Transport::OnChannelWritableState(TransportChannel* channel) {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  session_manager_->signaling_thread()->Post(this, MSG_WRITESTATE, NULL);
+}
+
+void Transport::OnChannelWritableState_s() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  bool writable = GetTransportState_s(false);
+  if (writable_ != writable) {
+    writable_ = writable;
+    SignalWritableState(this);
+  }
+}
+
+bool Transport::GetTransportState_s(bool read) {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  bool result = false;
+  talk_base::CritScope cs(&crit_);
+  for (ChannelMap::iterator iter = channels_.begin();
+       iter != channels_.end();
+       ++iter) {
+    bool b = (read ? iter->second->readable() : iter->second->writable());
+    result = result || b;
+  }
+  return result;
+}
+
+void Transport::OnChannelRequestSignaling() {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  session_manager_->signaling_thread()->Post(this, MSG_REQUESTSIGNALING, NULL);
+}
+
+void Transport::OnChannelRequestSignaling_s() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  SignalRequestSignaling(this);
+}
+
+void Transport::OnChannelMessage(TransportChannelImpl* impl,
+                                 buzz::XmlElement* elem) {
+  ASSERT(session_manager_->worker_thread()->IsCurrent());
+  talk_base::CritScope cs(&crit_);
+  messages_.push_back(elem);
+
+  // We hold any messages until the client lets us connect.
+  if (connect_requested_) {
+    session_manager_->signaling_thread()->Post(
+        this, MSG_ONCHANNELMESSAGE, NULL);
+  }
+}
+
+void Transport::OnChannelMessage_s() {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  ASSERT(connect_requested_);
+
+  std::vector<buzz::XmlElement*> msgs;
+  {
+    talk_base::CritScope cs(&crit_);
+    msgs.swap(messages_);
+  }
+
+  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);
+  }
+  SignalTransportMessage(this, elems);
+}
+
+void Transport::OnMessage(talk_base::Message* msg) {
+  switch (msg->message_id) {
+  case MSG_CREATECHANNEL:
+    {
+      ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data();
+      params->channel = CreateChannel_w(params->name, params->session_type);
+    }
+    break;
+  case MSG_DESTROYCHANNEL:
+    {
+      ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data();
+      DestroyChannel_w(params->name);
+    }
+    break;
+  case MSG_CONNECTCHANNELS:
+    ConnectChannels_w();
+    break;
+  case MSG_RESETCHANNELS:
+    ResetChannels_w();
+    break;
+  case MSG_DESTROYALLCHANNELS:
+    DestroyAllChannels_w();
+    break;
+  case MSG_ONSIGNALINGREADY:
+    CallChannels_w(&TransportChannelImpl::OnSignalingReady);
+    break;
+  case MSG_FORWARDCHANNELMESSAGE:
+    {
+      ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data();
+      ForwardChannelMessage_w(params->name, params->elem);
+      delete params;
+    }
+    break;
+  case MSG_CONNECTING:
+    OnConnecting_s();
+    break;
+  case MSG_READSTATE:
+    OnChannelReadableState_s();
+    break;
+  case MSG_WRITESTATE:
+    OnChannelWritableState_s();
+    break;
+  case MSG_REQUESTSIGNALING:
+    OnChannelRequestSignaling_s();
+    break;
+  case MSG_ONCHANNELMESSAGE:
+    OnChannelMessage_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 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));
+  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;
+}
+
+}  // namespace cricket
diff --git a/talk/p2p/base/transport.h b/talk/p2p/base/transport.h
new file mode 100755
index 0000000..826fd26
--- /dev/null
+++ b/talk/p2p/base/transport.h
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+
+// A Transport manages a set of named channels of the same type.
+//
+// Subclasses choose the appropriate class to instantiate for each channel;
+// however, this base class keeps track of the channels by name, watches their
+// state changes (in order to update the manager's state), and forwards
+// requests to begin connecting or to reset to each of the channels.
+//
+// On Threading:  Transport performs work on both the signaling and worker
+// threads.  For subclasses, the rule is that all signaling related calls will
+// 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).
+//
+// 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_
+
+#include <string>
+#include <map>
+#include <vector>
+#include "talk/base/criticalsection.h"
+#include "talk/base/messagequeue.h"
+#include "talk/base/sigslot.h"
+
+namespace buzz {
+class QName;
+class XmlElement;
+}
+
+namespace cricket {
+
+class SessionManager;
+class Session;
+class TransportChannel;
+class TransportChannelImpl;
+
+class Transport : public talk_base::MessageHandler, public sigslot::has_slots<> {
+ public:
+  Transport(SessionManager* session_manager, const std::string& name);
+  virtual ~Transport();
+
+  // Returns a pointer to the singleton session manager.
+  SessionManager* session_manager() const { return session_manager_; }
+
+  // Returns the name of this transport.
+  const std::string& name() const { return name_; }
+
+  // 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
+  // states changes, a signal is raised.
+  bool readable() const { return readable_; }
+  bool writable() const { return writable_; }
+  sigslot::signal1<Transport*> SignalReadableState;
+  sigslot::signal1<Transport*> SignalWritableState;
+
+  // Returns whether the client has requested the channels to connect.
+  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);
+  // 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 HasChannels();
+  void DestroyChannel(const std::string& name);
+
+  // Tells all current and future channels to start connecting.  When the first
+  // channel begins connecting, the following signal is raised.
+  void ConnectChannels();
+  sigslot::signal1<Transport*> SignalConnecting;
+
+  // Resets all of the channels back to their initial state.  They are no
+  // longer connecting.
+  void ResetChannels();
+
+  // 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.
+  // OnSignalingReady invokes OnTransportSignalingReady and then forwards this
+  // signal to each channel.
+  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;
+
+  // 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;
+  sigslot::signal6<Transport*, const buzz::XmlElement*, const buzz::QName&,
+                   const std::string&, const std::string&,
+                   const buzz::XmlElement*>
+      SignalTransportError;
+
+  sigslot::signal2<Transport*, const std::string&> SignalChannelGone;
+
+  // (For testing purposes only.)  This indicates whether we will allow local
+  // IPs (e.g. 127.*) to be used as addresses for P2P.
+  bool allow_local_ips() const { return allow_local_ips_; }
+  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;
+  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);
+  void OnChannelWritableState(TransportChannel* channel);
+
+  // 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);
+
+  // Dispatches messages to the appropriate handler (below).
+  void OnMessage(talk_base::Message* msg);
+
+  // 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);
+  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 OnChannelReadableState_s();
+  void OnChannelWritableState_s();
+  void OnChannelRequestSignaling_s();
+  void OnConnecting_s();
+
+  // Helper function that invokes the given function on every channel.
+  typedef void (TransportChannelImpl::* TransportChannelFunc)();
+  void CallChannels_w(TransportChannelFunc func);
+
+  // 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();
+
+  DISALLOW_EVIL_CONSTRUCTORS(Transport);
+};
+
+}  // namespace cricket
+
+#endif  // _CRICKET_P2P_BASE_TRANSPORT_H_
diff --git a/talk/p2p/base/transportchannel.cc b/talk/p2p/base/transportchannel.cc
new file mode 100755
index 0000000..ba076ac
--- /dev/null
+++ b/talk/p2p/base/transportchannel.cc
@@ -0,0 +1,56 @@
+/*
+ * 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 <sstream>
+#include "talk/p2p/base/transportchannel.h"
+
+namespace cricket {
+
+std::string TransportChannel::ToString() const {
+  const char READABLE_ABBREV[2] = { '_', 'R' };
+  const char WRITABLE_ABBREV[2] = { '_', 'W' };
+  std::stringstream ss;
+  ss << "Channel[" << name_ << "|" << READABLE_ABBREV[readable_]
+      << WRITABLE_ABBREV[writable_] << "]";
+  return ss.str();
+}
+
+void TransportChannel::set_readable(bool readable) {
+  if (readable_ != readable) {
+    readable_ = readable;
+    SignalReadableState(this);
+  }
+}
+
+void TransportChannel::set_writable(bool writable) {
+  if (writable_ != writable) {
+    writable_ = writable;
+    SignalWritableState(this);
+  }
+}
+
+}  // namespace cricket
diff --git a/talk/p2p/base/transportchannel.h b/talk/p2p/base/transportchannel.h
new file mode 100755
index 0000000..68b8fd1
--- /dev/null
+++ b/talk/p2p/base/transportchannel.h
@@ -0,0 +1,104 @@
+/*
+ * 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 _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_
+#define _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_
+
+#include <string>
+#include "talk/base/basictypes.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/socket.h"
+
+namespace cricket {
+
+// 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) {}
+  virtual ~TransportChannel() {}
+
+  // Returns the name of this channel.
+  const std::string& name() const { return name_; }
+  const std::string& session_type() const { return session_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
+  // TransportManager.
+  bool readable() const { return readable_; }
+  bool writable() const { return writable_; }
+  sigslot::signal1<TransportChannel*> SignalReadableState;
+  sigslot::signal1<TransportChannel*> SignalWritableState;
+
+  // Attempts to send the given packet.  The return value is < 0 on failure.
+  virtual int SendPacket(const char *data, size_t len) = 0;
+
+  // Sets a socket option on this channel.  Note that not all options are
+  // supported by all transport types.
+  virtual int SetOption(talk_base::Socket::Option opt, int value) = 0;
+
+  // Returns the most recent error that occurred on this channel.
+  virtual int GetError() = 0;
+
+  // Signalled each time a packet is received  on this channel.
+  sigslot::signal3<TransportChannel*, const char*, size_t> SignalReadPacket;
+
+  // This signal occurs when there is a change in the way that packets are
+  // 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&> 
+      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;
+
+ protected:
+  // Sets the readable state, signaling if necessary.
+  void set_readable(bool readable);
+
+  // Sets the writable state, signaling if necessary.
+  void set_writable(bool writable);
+
+ private:
+  std::string name_;
+  std::string session_type_;
+  bool readable_;
+  bool writable_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(TransportChannel);
+};
+
+}  // namespace cricket
+
+#endif  // _CRICKET_P2P_BASE_TRANSPORTCHANNEL_H_
diff --git a/talk/p2p/base/transportchannelimpl.h b/talk/p2p/base/transportchannelimpl.h
new file mode 100755
index 0000000..742d307
--- /dev/null
+++ b/talk/p2p/base/transportchannelimpl.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 _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_
+#define _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_
+
+#include <string>
+#include "talk/p2p/base/transportchannel.h"
+
+namespace buzz { class XmlElement; }
+
+namespace cricket {
+
+class Transport;
+
+// 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 {
+ public:
+  TransportChannelImpl(const std::string& name, const std::string& session_type)
+    : TransportChannel(name, session_type) {}
+
+  // Returns the transport that created this channel.
+  virtual Transport* GetTransport() = 0;
+
+  // Begins the process of attempting to make a connection to the other client.
+  virtual void Connect() = 0;
+
+  // Resets this channel back to the initial state (i.e., not connecting).
+  virtual void Reset() = 0;
+
+  // Allows an individual channel to request signaling and be notified when it
+  // is ready.  This is useful if the individual named channels have need to
+  // send their own transport-info stanzas.
+  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.
+  //
+  // 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;
+  sigslot::signal2<TransportChannelImpl*,
+                   buzz::XmlElement*> SignalChannelMessage;
+
+ private:
+  DISALLOW_EVIL_CONSTRUCTORS(TransportChannelImpl);
+};
+
+}  // namespace cricket
+
+#endif  // _CRICKET_P2P_BASE_TRANSPORTCHANNELIMPL_H_
diff --git a/talk/p2p/base/transportchannelproxy.cc b/talk/p2p/base/transportchannelproxy.cc
new file mode 100755
index 0000000..bc94d67
--- /dev/null
+++ b/talk/p2p/base/transportchannelproxy.cc
@@ -0,0 +1,99 @@
+/*
+ * 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/p2p/base/transportchannelproxy.h"
+#include "talk/base/common.h"
+#include "talk/p2p/base/transport.h"
+#include "talk/p2p/base/transportchannelimpl.h"
+
+namespace cricket {
+
+TransportChannelProxy::TransportChannelProxy(const std::string& name, const std::string &session_type)
+  : TransportChannel(name, session_type), impl_(NULL) {
+}
+
+TransportChannelProxy::~TransportChannelProxy() {
+  if (impl_)
+    impl_->GetTransport()->DestroyChannel(impl_->name());
+}
+
+void TransportChannelProxy::SetImplementation(TransportChannelImpl* impl) {
+  impl_ = impl;
+  impl_->SignalReadableState.connect(
+      this, &TransportChannelProxy::OnReadableState);
+  impl_->SignalWritableState.connect(
+      this, &TransportChannelProxy::OnWritableState);
+  impl_->SignalReadPacket.connect(this, &TransportChannelProxy::OnReadPacket);
+  impl_->SignalRouteChange.connect(this, &TransportChannelProxy::OnRouteChange);
+  for (OptionList::iterator it = pending_options_.begin();
+       it != pending_options_.end();
+       ++it) {
+    impl_->SetOption(it->first, it->second);
+  }
+  pending_options_.clear();
+}
+
+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);
+}
+
+int TransportChannelProxy::SetOption(talk_base::Socket::Option opt, int value) {
+  if (impl_)
+    return impl_->SetOption(opt, value);
+  pending_options_.push_back(OptionPair(opt, value));
+  return 0;
+}
+
+int TransportChannelProxy::GetError() {
+  ASSERT(impl_ != NULL);  // should not be used until channel is writable
+  return impl_->GetError();
+}
+
+void TransportChannelProxy::OnReadableState(TransportChannel* channel) {
+  ASSERT(channel == impl_);
+  set_readable(impl_->readable());
+}
+
+void TransportChannelProxy::OnWritableState(TransportChannel* channel) {
+  ASSERT(channel == impl_);
+  set_writable(impl_->writable());
+}
+
+void TransportChannelProxy::OnReadPacket(
+    TransportChannel* channel, const char* data, size_t size) {
+  ASSERT(channel == impl_);
+  SignalReadPacket(this, data, size);
+}
+
+void TransportChannelProxy::OnRouteChange(TransportChannel* channel,
+                                          const talk_base::SocketAddress& address) {
+  ASSERT(channel == impl_);
+  SignalRouteChange(this, address);
+}
+
+}  // namespace cricket
diff --git a/talk/p2p/base/transportchannelproxy.h b/talk/p2p/base/transportchannelproxy.h
new file mode 100755
index 0000000..46d8a44
--- /dev/null
+++ b/talk/p2p/base/transportchannelproxy.h
@@ -0,0 +1,77 @@
+/*
+ * 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 _CRICKET_P2P_BASE_TRANSPORTCHANNELPROXY_H_
+#define _CRICKET_P2P_BASE_TRANSPORTCHANNELPROXY_H_
+
+#include <string>
+#include <vector>
+#include "talk/p2p/base/transportchannel.h"
+
+namespace cricket {
+
+class TransportChannelImpl;
+
+// Proxies calls between the client and the transport channel implementation.
+// This is needed because clients are allowed to create channels before the
+// network negotiation is complete.  Hence, we create a proxy up front, and
+// when negotiation completes, connect the proxy to the implementaiton.
+class TransportChannelProxy: public TransportChannel {
+ public:
+  TransportChannelProxy(const std::string& name, const std::string &session_type);
+  virtual ~TransportChannelProxy();
+
+  TransportChannelImpl* impl() const { return impl_; }
+
+  // Sets the implementation to which we will proxy.
+  void SetImplementation(TransportChannelImpl* impl);
+
+  // Implementation of the TransportChannel interface.  These simply forward to
+  // the implementation.
+  virtual int SendPacket(const char *data, size_t len);
+  virtual int SetOption(talk_base::Socket::Option opt, int value);
+  virtual int GetError();
+
+ private:
+  typedef std::pair<talk_base::Socket::Option, int> OptionPair;
+  typedef std::vector<OptionPair> OptionList;
+  TransportChannelImpl* impl_;
+  OptionList pending_options_;
+
+  // Catch signals from the implementation channel.  These just forward to the
+  // client (after updating our state to match).
+  void OnReadableState(TransportChannel* channel);
+  void OnWritableState(TransportChannel* channel);
+  void OnReadPacket(TransportChannel* channel, const char* data, size_t size);
+  void OnRouteChange(TransportChannel* channel, const talk_base::SocketAddress& address);
+
+  DISALLOW_EVIL_CONSTRUCTORS(TransportChannelProxy);
+};
+
+}  // namespace cricket
+
+#endif  // _CRICKET_P2P_BASE_TRANSPORTCHANNELPROXY_H_
diff --git a/talk/p2p/base/udpport.cc b/talk/p2p/base/udpport.cc
new file mode 100755
index 0000000..fa47eba
--- /dev/null
+++ b/talk/p2p/base/udpport.cc
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#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
+
+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, const std::string &type,
+                 talk_base::SocketFactory* factory, talk_base::Network* network)
+  : Port(thread, type, factory, network), socket_(0), error_(0) {
+}
+
+UDPPort::~UDPPort() {
+  delete socket_;
+}
+
+void UDPPort::PrepareAddress() {
+  assert(socket_);
+  AddAddress(socket_->GetLocalAddress(), "udp", true);
+}
+
+Connection* UDPPort::CreateConnection(const Candidate& address, 
+                                      CandidateOrigin origin) {
+  if (address.protocol() != "udp")
+    return 0;
+
+  Connection * conn = new ProxyConnection(this, 0, address);
+  AddConnection(conn);
+  return conn;
+}
+
+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)
+    error_ = socket_->GetError();
+  return sent;
+}
+
+int UDPPort::SetOption(talk_base::Socket::Option opt, int value) {
+  return socket_->SetOption(opt, value);
+}
+
+int UDPPort::GetError() {
+  assert(socket_);
+  return error_;
+}
+
+void UDPPort::OnReadPacketSlot(
+    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) {
+  if (Connection* conn = GetConnection(remote_addr)) {
+    conn->OnReadPacket(data, size);
+  } else {
+    Port::OnReadPacket(data, size, remote_addr);
+  }
+}
+
+} // namespace cricket
diff --git a/talk/p2p/base/udpport.h b/talk/p2p/base/udpport.h
new file mode 100755
index 0000000..9fcfa69
--- /dev/null
+++ b/talk/p2p/base/udpport.h
@@ -0,0 +1,90 @@
+/*
+ * 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 __UDPPORT_H__
+#define __UDPPORT_H__
+
+#include "talk/base/asyncudpsocket.h"
+#include "talk/p2p/base/port.h"
+
+namespace talk_base {
+  class Thread;
+  class Network;
+  class SocketAddress;
+} // namespace talk_base
+
+namespace cricket {
+
+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);
+  virtual ~UDPPort();
+
+  virtual void PrepareAddress();
+  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);
+
+  // Handles sending using the local UDP socket.
+  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);
+
+  talk_base::AsyncPacketSocket* socket() { return socket_; }
+
+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
+
+#endif // __UDPPORT_H__
diff --git a/talk/p2p/client/Makefile.am b/talk/p2p/client/Makefile.am
new file mode 100755
index 0000000..11447f7
--- /dev/null
+++ b/talk/p2p/client/Makefile.am
@@ -0,0 +1,13 @@
+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/Makefile.in b/talk/p2p/client/Makefile.in
new file mode 100644
index 0000000..7b484e5
--- /dev/null
+++ b/talk/p2p/client/Makefile.in
@@ -0,0 +1,456 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/p2p/client
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketp2pclient_la_LIBADD =
+am_libcricketp2pclient_la_OBJECTS = basicportallocator.lo \
+	httpportallocator.lo socketmonitor.lo
+libcricketp2pclient_la_OBJECTS = $(am_libcricketp2pclient_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketp2pclient_la_SOURCES)
+DIST_SOURCES = $(libcricketp2pclient_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/p2p/client/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/p2p/client/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketp2pclient.la: $(libcricketp2pclient_la_OBJECTS) $(libcricketp2pclient_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketp2pclient_la_LDFLAGS) $(libcricketp2pclient_la_OBJECTS) $(libcricketp2pclient_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basicportallocator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpportallocator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socketmonitor.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/p2p/client/basicportallocator.cc b/talk/p2p/client/basicportallocator.cc
new file mode 100755
index 0000000..b7960f4
--- /dev/null
+++ b/talk/p2p/client/basicportallocator.cc
@@ -0,0 +1,690 @@
+/*
+ * 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.
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+
+#include "talk/base/common.h"
+#include "talk/base/helpers.h"
+#include "talk/base/host.h"
+#include "talk/base/logging.h"
+#include "talk/p2p/client/basicportallocator.h"
+#include "talk/p2p/base/common.h"
+#include "talk/p2p/base/port.h"
+#include "talk/p2p/base/relayport.h"
+#include "talk/p2p/base/stunport.h"
+#include "talk/p2p/base/tcpport.h"
+#include "talk/p2p/base/udpport.h"
+
+namespace {
+
+const uint32 MSG_CONFIG_START = 1;
+const uint32 MSG_CONFIG_READY = 2;
+const uint32 MSG_ALLOCATE = 3;
+const uint32 MSG_ALLOCATION_PHASE = 4;
+const uint32 MSG_SHAKE = 5;
+
+const uint32 ALLOCATE_DELAY = 250;
+const uint32 ALLOCATION_STEP_DELAY = 1 * 1000;
+
+const int PHASE_UDP = 0;
+const int PHASE_RELAY = 1;
+const int PHASE_TCP = 2;
+const int PHASE_SSLTCP = 3;
+const int kNumPhases = 4;
+
+const float PREF_LOCAL_UDP = 1.0f;
+const float PREF_LOCAL_STUN = 0.9f;
+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
+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);
+  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);
+      }
+    } else if (candidate.type() == cricket::STUN_PORT_TYPE) {
+      return PHASE_UDP;
+    } else if (candidate.type() == cricket::RELAY_PORT_TYPE) {
+      switch (proto) {
+      case cricket::PROTO_UDP: return PHASE_RELAY;
+      case cricket::PROTO_TCP: return PHASE_TCP;
+      case cricket::PROTO_SSLTCP: return PHASE_SSLTCP;
+      default: assert(false);
+      }
+    } else {
+      assert(false);
+    }
+  } else {
+    assert(false);
+  }
+  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
+
+int ShakeDelay() {
+  int range = SHAKE_MAX_DELAY - SHAKE_MIN_DELAY + 1;
+  return SHAKE_MIN_DELAY + cricket::CreateRandomId() % range;
+}
+
+}
+
+namespace cricket {
+
+// Performs the allocation of ports, in a sequenced (timed) manner, for a given
+// network and IP address.
+class AllocationSequence : public talk_base::MessageHandler {
+public:
+  AllocationSequence(BasicPortAllocatorSession* session,
+                     talk_base::Network* network,
+                     PortConfiguration* config);
+  ~AllocationSequence();
+
+  // Determines whether this sequence is operating on an equivalent network
+  // setup to the one given.
+  bool IsEquivalent(talk_base::Network* network);
+
+  // Starts and stops the sequence.  When started, it will continue allocating
+  // new ports on its own timed schedule.
+  void Start();
+  void Stop();
+
+  // MessageHandler:
+  void OnMessage(talk_base::Message* msg);
+
+  void EnableProtocol(ProtocolType proto);
+  bool ProtocolEnabled(ProtocolType proto) const;
+
+private:
+  BasicPortAllocatorSession* session_;
+  talk_base::Network* network_;
+  uint32 ip_;
+  PortConfiguration* config_;
+  bool running_;
+  int step_;
+  int step_of_phase_[kNumPhases];
+
+  typedef std::vector<ProtocolType> ProtocolList;
+  ProtocolList protocols_;
+
+  void CreateUDPPorts();
+  void CreateTCPPorts();
+  void CreateStunPorts();
+  void CreateRelayPorts();
+};
+
+
+// BasicPortAllocator
+
+BasicPortAllocator::BasicPortAllocator(
+    talk_base::NetworkManager* network_manager)
+  : network_manager_(network_manager), best_writable_phase_(-1), 
+    stun_address_(NULL), relay_address_(NULL) {
+}
+
+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) {
+}
+
+BasicPortAllocator::~BasicPortAllocator() {
+}
+
+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_UNKNOWN))) {
+    return PHASE_RELAY;
+  }
+  return best_writable_phase_;
+}
+
+PortAllocatorSession *BasicPortAllocator::CreateSession(
+ const std::string &name, const std::string &session_type) {
+  return new BasicPortAllocatorSession(this, name, session_type, stun_address_, 
+    relay_address_);
+}
+
+void BasicPortAllocator::AddWritablePhase(int phase) {
+  if ((best_writable_phase_ == -1) || (phase < best_writable_phase_))
+    best_writable_phase_ = phase;
+}
+
+// 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) {
+}
+
+BasicPortAllocatorSession::~BasicPortAllocatorSession() {
+  if (network_thread_ != NULL)
+    network_thread_->Clear(this);
+
+  std::vector<PortData>::iterator it;
+  for (it = ports_.begin(); it != ports_.end(); it++)
+    delete it->port;
+
+  for (uint32 i = 0; i < configs_.size(); ++i)
+    delete configs_[i];
+
+  for (uint32 i = 0; i < sequences_.size(); ++i)
+    delete sequences_[i];
+}
+
+void BasicPortAllocatorSession::GetInitialPorts() {
+  network_thread_ = talk_base::Thread::Current();
+
+  network_thread_->Post(this, MSG_CONFIG_START);
+
+  if (flags() & PORTALLOCATOR_ENABLE_SHAKER)
+    network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
+}
+
+void BasicPortAllocatorSession::StartGetAllPorts() {
+  assert(talk_base::Thread::Current() == network_thread_);
+  running_ = true;
+  if (allocation_started_)
+    network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE);
+  for (uint32 i = 0; i < sequences_.size(); ++i)
+    sequences_[i]->Start();
+  for (size_t i = 0; i < ports_.size(); ++i)
+    ports_[i].port->Start();
+}
+
+void BasicPortAllocatorSession::StopGetAllPorts() {
+  assert(talk_base::Thread::Current() == network_thread_);
+  running_ = false;
+  network_thread_->Clear(this, MSG_ALLOCATE);
+  for (uint32 i = 0; i < sequences_.size(); ++i)
+    sequences_[i]->Stop();
+}
+
+void BasicPortAllocatorSession::OnMessage(talk_base::Message *message) {
+  switch (message->message_id) {
+  case MSG_CONFIG_START:
+    assert(talk_base::Thread::Current() == network_thread_);
+    GetPortConfigurations();
+    break;
+
+  case MSG_CONFIG_READY:
+    assert(talk_base::Thread::Current() == network_thread_);
+    OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
+    break;
+
+  case MSG_ALLOCATE:
+    assert(talk_base::Thread::Current() == network_thread_);
+    OnAllocate();
+    break;
+
+  case MSG_SHAKE:
+    assert(talk_base::Thread::Current() == network_thread_);
+    OnShake();
+    break;
+
+  default:
+    assert(false);
+  }
+}
+
+void BasicPortAllocatorSession::GetPortConfigurations() {
+  PortConfiguration* config = NULL;
+  if (stun_address_ != NULL)
+    config = new PortConfiguration(*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);
+  }
+
+  ConfigReady(config);
+}
+
+void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
+  network_thread_->Post(this, MSG_CONFIG_READY, config);
+}
+
+// Adds a configuration to the list.
+void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
+  if (config)
+    configs_.push_back(config);
+
+  AllocatePorts();
+}
+
+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());
+
+  network_thread_->Post(this, MSG_ALLOCATE);
+}
+
+// For each network, see if we have a sequence that covers it already.  If not,
+// 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;
+
+    PortConfiguration* config = NULL;
+    if (configs_.size() > 0)
+      config = configs_.back();
+
+    AllocationSequence* sequence =
+        new AllocationSequence(this, networks[i], config);
+    if (running_)
+      sequence->Start();
+
+    sequences_.push_back(sequence);
+  }
+
+  allocation_started_ = true;
+  if (running_)
+    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::AddAllocatedPort(Port* port,
+                                                 AllocationSequence * seq,
+                                                 float pref,
+                                                 bool prepare_address) {
+  if (!port)
+    return;
+
+  port->set_name(name_);
+  port->set_preference(pref);
+  port->set_generation(generation());
+  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);
+  LOG_J(LS_INFO, port) << "Added port to allocator";
+  if (prepare_address)
+    port->PrepareAddress();
+  if (running_)
+    port->Start();
+}
+
+void BasicPortAllocatorSession::OnAddressReady(Port *port) {
+  assert(talk_base::Thread::Current() == network_thread_);
+  std::vector<PortData>::iterator it 
+    = std::find(ports_.begin(), ports_.end(), port);
+  assert(it != ports_.end());
+  if (it->ready)
+    return;
+  it->ready = true;
+  SignalPortReady(this, port);
+
+  // 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) {
+    ProtocolType pvalue;
+    if (!StringToProto(potentials[i].protocol().c_str(), pvalue))
+      continue;
+    if (it->sequence->ProtocolEnabled(pvalue)) {
+      candidates.push_back(potentials[i]);
+    }
+  }
+  if (!candidates.empty()) {
+    SignalCandidatesReady(this, candidates);
+  }
+}
+
+void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence * seq, 
+                                                  ProtocolType proto) {
+  std::vector<Candidate> candidates;
+  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) {
+      ProtocolType pvalue;
+      if (!StringToProto(potentials[i].protocol().c_str(), pvalue))
+        continue;
+      if (pvalue == proto) {
+        candidates.push_back(potentials[i]);
+      }
+    }
+  }
+  if (!candidates.empty()) {
+    SignalCandidatesReady(this, candidates);
+  }
+}
+
+void BasicPortAllocatorSession::OnPortDestroyed(Port* port) {
+  assert(talk_base::Thread::Current() == network_thread_);
+  std::vector<PortData>::iterator iter =
+      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, 
+                                                    Connection* conn) {
+  conn->SignalStateChange.connect(this, 
+    &BasicPortAllocatorSession::OnConnectionStateChange);
+}
+
+void BasicPortAllocatorSession::OnConnectionStateChange(Connection* conn) {
+  if (conn->write_state() == Connection::STATE_WRITABLE)
+    allocator_->AddWritablePhase(
+      LocalCandidateToPhase(conn->local_candidate()));
+}
+
+void BasicPortAllocatorSession::OnShake() {
+  LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<";
+
+  std::vector<Port*> ports;
+  std::vector<Connection*> connections;
+
+  for (size_t i = 0; i < ports_.size(); ++i) {
+    if (ports_[i].ready)
+      ports.push_back(ports_[i].port);
+  }
+
+  for (size_t i = 0; i < ports.size(); ++i) {
+    Port::AddressMap::const_iterator iter;
+    for (iter = ports[i]->connections().begin();
+         iter != ports[i]->connections().end();
+         ++iter) {
+      connections.push_back(iter->second);
+    }
+  }
+
+  LOG(INFO) << ">>>>> Destroying " << (int)ports.size() << " ports and "
+            << (int)connections.size() << " connections";
+
+  for (size_t i = 0; i < connections.size(); ++i)
+    connections[i]->Destroy();
+
+  if (running_ || (ports.size() > 0) || (connections.size() > 0))
+    network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
+}
+
+// AllocationSequence
+
+AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
+                                       talk_base::Network* network,
+                                       PortConfiguration* config)
+  : session_(session), network_(network), ip_(network->ip()), config_(config),
+    running_(false), step_(0) {
+
+  // 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.
+  int last_phase_in_step_zero =
+      talk_base::_max(0, session->allocator()->best_writable_phase());
+  for (int phase = 0; phase < kNumPhases; ++phase)
+    step_of_phase_[phase] = talk_base::_max(0, phase - last_phase_in_step_zero);
+
+  // Immediately perform phase 0.
+  OnMessage(NULL);
+}
+
+AllocationSequence::~AllocationSequence() {
+  session_->network_thread()->Clear(this);
+}
+
+bool AllocationSequence::IsEquivalent(talk_base::Network* network) {
+  return (network == network_) && (ip_ == network->ip());
+}
+
+void AllocationSequence::Start() {
+  running_ = true;
+  session_->network_thread()->PostDelayed(ALLOCATION_STEP_DELAY,
+                                          this,
+                                          MSG_ALLOCATION_PHASE);
+}
+
+void AllocationSequence::Stop() {
+  running_ = false;
+  session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
+}
+
+void AllocationSequence::OnMessage(talk_base::Message* msg) {
+  assert(talk_base::Thread::Current() == session_->network_thread());
+  if (msg)
+    assert(msg->message_id == MSG_ALLOCATION_PHASE);
+
+  const char* const PHASE_NAMES[kNumPhases] = {
+    "Udp", "Relay", "Tcp", "SslTcp"
+  };
+
+  // Perform all of the phases in the current step.
+  for (int phase = 0; phase < kNumPhases; phase++) {
+    if (step_of_phase_[phase] != step_)
+      continue;
+
+    LOG_J(LS_INFO, network_) << "Allocation Phase=" << PHASE_NAMES[phase]
+                             << " (Step=" << step_ << ")";
+
+    switch (phase) {
+    case PHASE_UDP:
+      CreateUDPPorts();
+      CreateStunPorts();
+      EnableProtocol(PROTO_UDP);
+      break;
+
+    case PHASE_RELAY:
+      CreateRelayPorts();
+      break;
+
+    case PHASE_TCP:
+      CreateTCPPorts();
+      EnableProtocol(PROTO_TCP);
+      break;
+
+    case PHASE_SSLTCP:
+      EnableProtocol(PROTO_SSLTCP);
+      break;
+
+    default:
+      ASSERT(false);
+    }
+  }
+
+  // TODO: use different delays for each stage
+  step_ += 1;
+  if (running_) {
+    session_->network_thread()->PostDelayed(ALLOCATION_STEP_DELAY,
+                                            this,
+                                            MSG_ALLOCATION_PHASE);
+  }
+}
+
+void AllocationSequence::EnableProtocol(ProtocolType proto) {
+  if (!ProtocolEnabled(proto)) {
+    protocols_.push_back(proto);
+    session_->OnProtocolEnabled(this, proto);
+  }
+}
+
+bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
+  for (ProtocolList::const_iterator it = protocols_.begin(); it != protocols_.end(); ++it) {
+    if (*it == proto)
+      return true;
+  }
+  return false;
+}
+
+void AllocationSequence::CreateUDPPorts() {
+  if (session_->flags() & PORTALLOCATOR_DISABLE_UDP)
+    return;
+
+  Port* port = new UDPPort(session_->network_thread(), NULL, network_,
+                           talk_base::SocketAddress(ip_, 0));
+  session_->AddAllocatedPort(port, this, PREF_LOCAL_UDP);
+}
+
+void AllocationSequence::CreateTCPPorts() {
+  if (session_->flags() & PORTALLOCATOR_DISABLE_TCP)
+    return;
+
+  Port* port = new TCPPort(session_->network_thread(), NULL, network_,
+                           talk_base::SocketAddress(ip_, 0));
+  session_->AddAllocatedPort(port, this, PREF_LOCAL_TCP); 
+}
+
+void AllocationSequence::CreateStunPorts() {
+  if (session_->flags() & PORTALLOCATOR_DISABLE_STUN)
+    return;
+
+  if (!config_ || config_->stun_address.IsAny())
+    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); 
+}
+
+void AllocationSequence::CreateRelayPorts() {
+  if (session_->flags() & PORTALLOCATOR_DISABLE_RELAY)
+    return;
+
+  if (!config_)
+    return;
+
+  PortConfiguration::RelayList::const_iterator relay;
+  for (relay = config_->relays.begin();
+       relay != config_->relays.end();
+       ++relay) {
+
+    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);
+    }
+
+    // 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) {
+}
+
+void PortConfiguration::AddRelay(const PortList& ports, float pref_modifier) {
+  RelayServer relay;
+  relay.ports = ports;
+  relay.pref_modifier = pref_modifier;
+  relays.push_back(relay);
+}
+
+bool PortConfiguration::SupportsProtocol(
+    const PortConfiguration::RelayServer& relay, ProtocolType type) {
+  PortConfiguration::PortList::const_iterator relay_port;
+  for (relay_port = relay.ports.begin();
+        relay_port != relay.ports.end();
+        ++relay_port) {
+    if (relay_port->proto == type)
+      return true;
+  }
+  return false;
+}
+
+} // namespace cricket
diff --git a/talk/p2p/client/basicportallocator.h b/talk/p2p/client/basicportallocator.h
new file mode 100755
index 0000000..0e3d313
--- /dev/null
+++ b/talk/p2p/client/basicportallocator.h
@@ -0,0 +1,175 @@
+/*
+ * 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 _BASICPORTALLOCATOR_H_
+#define _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>
+
+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);
+  virtual ~BasicPortAllocator();
+
+  talk_base::NetworkManager* network_manager() { return network_manager_; }
+
+  // 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);
+
+  // Called whenever a connection becomes writable with the argument being the
+  // phase that the corresponding port was created in.
+  void AddWritablePhase(int phase);
+
+private:
+  talk_base::NetworkManager* network_manager_;
+  talk_base::SocketAddress* stun_address_;
+  talk_base::SocketAddress* relay_address_;
+  int best_writable_phase_;
+};
+
+struct PortConfiguration;
+class AllocationSequence;
+
+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);
+  ~BasicPortAllocatorSession();
+
+  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_; }
+
+  virtual void GetInitialPorts();
+  virtual void StartGetAllPorts();
+  virtual void StopGetAllPorts();
+  virtual bool IsGettingAllPorts() { return running_; }
+
+protected:
+  // Starts the process of getting the port configurations.
+  virtual void GetPortConfigurations();
+
+  // Adds a port configuration that is now ready.  Once we have one for each
+  // network (or a timeout occurs), we will start allocating ports.
+  void ConfigReady(PortConfiguration* config);
+
+  // MessageHandler.  Can be overriden if message IDs do not conflict.
+  virtual void OnMessage(talk_base::Message *message);
+
+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, 
+      bool prepare_address = true);
+  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_;
+  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
+  std::vector<PortConfiguration*> configs_;
+  std::vector<AllocationSequence*> sequences_;
+  talk_base::SocketAddress *stun_address_;
+  talk_base::SocketAddress *relay_address_;
+
+  struct PortData {
+    Port * port;
+    AllocationSequence * sequence;
+    bool ready;
+
+    bool operator==(Port * rhs) const { return (port == rhs); }
+  };
+  std::vector<PortData> ports_;
+
+  friend class AllocationSequence;
+};
+
+// Records configuration information useful in creating ports.
+struct PortConfiguration : public talk_base::MessageData {
+  talk_base::SocketAddress stun_address;
+  std::string username;
+  std::string password;
+  std::string magic_cookie;
+
+  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
+  };
+
+  typedef std::vector<RelayServer> RelayList;
+  RelayList relays;
+
+  PortConfiguration(const talk_base::SocketAddress& stun_address,
+                    const std::string& username,
+                    const std::string& password,
+                    const std::string& magic_cookie);
+
+  // Adds another relay server, with the given ports and modifier, to the list.
+  void AddRelay(const PortList& ports, float pref_modifier);
+
+  // Determines whether the given relay server supports the given protocol.
+  static bool SupportsProtocol(const PortConfiguration::RelayServer& relay,
+                               ProtocolType type);
+};
+
+} // namespace cricket
+
+#endif // _BASICPORTALLOCATOR_H_
diff --git a/talk/p2p/client/httpportallocator.cc b/talk/p2p/client/httpportallocator.cc
new file mode 100755
index 0000000..de8edaf
--- /dev/null
+++ b/talk/p2p/client/httpportallocator.cc
@@ -0,0 +1,185 @@
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#pragma warning(disable:4786)
+#endif
+#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/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
+
+// Helper routine to remove whitespace from the ends of a string.
+void Trim(std::string& str) {
+  size_t first = str.find_first_not_of(" \t\r\n");
+  if (first == std::string::npos) {
+    str.clear();
+    return;
+  }
+
+  size_t last = str.find_last_not_of(" \t\r\n");
+  ASSERT(last != 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;
+void ParseMap(const std::string& string, StringMap& map) {
+  size_t start_of_line = 0;
+  size_t end_of_line = 0;
+
+  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;
+
+    end_of_line = string.find_first_of("\r\n", start_of_line);
+    if (end_of_line == std::string::npos) {
+      end_of_line = string.length();
+    }
+
+    size_t equals = string.find('=', start_of_line);
+    if ((equals >= end_of_line) || (equals == std::string::npos))
+      continue;
+
+    std::string key(string, start_of_line, equals - start_of_line);
+    std::string value(string, equals + 1, end_of_line - equals - 1);
+
+    Trim(key);
+    Trim(value);
+
+    if ((key.size() > 0) && (value.size() > 0))
+      map[key] = value;
+  }
+}
+
+}
+
+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));
+}
+
+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_);
+}
+
+// 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) {
+}
+
+void HttpPortAllocatorSession::GetPortConfigurations() {
+
+  if (attempts_ == kNumRetries) {
+    LOG(WARNING) << "HttpPortAllocator: maximum number of requests reached";
+    return;
+  }
+
+  // Choose the next host to try.
+  std::string host = relay_hosts_[attempts_ % relay_hosts_.size()];
+  attempts_++;
+  LOG(INFO) << "HTTPPortAllocator: sending to host " << host;
+
+  // 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);
+
+  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().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->set_host(host);
+  request->set_port(kHostPort);
+  request->Start(); 
+  request->Release();
+}
+
+void HttpPortAllocatorSession::OnRequestDone(talk_base::SignalThread* 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();
+    return;
+  }
+  LOG(INFO) << "HTTPPortAllocator: request succeeded";
+
+  StringMap map;
+  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);
+
+  std::string username = map["username"];
+  std::string password = map["password"];
+  std::string magic_cookie = map["magic_cookie"];
+
+  std::string relay_ip = map["relay.ip"];
+  std::string relay_udp_port = map["relay.udp_port"];
+  std::string relay_tcp_port = map["relay.tcp_port"];
+  std::string relay_ssltcp_port = map["relay.ssltcp_port"];
+
+  PortConfiguration* config = new PortConfiguration(stun_hosts_[0],
+                                                    username,
+                                                    password,
+                                                    magic_cookie);
+
+  PortConfiguration::PortList ports;
+  if (!relay_udp_port.empty()) {
+    talk_base::SocketAddress address(relay_ip, atoi(relay_udp_port.c_str()));
+    ports.push_back(ProtocolAddress(address, PROTO_UDP));
+  }
+  if (!relay_tcp_port.empty()) {
+    talk_base::SocketAddress address(relay_ip, atoi(relay_tcp_port.c_str()));
+    ports.push_back(ProtocolAddress(address, PROTO_TCP));
+  }
+  if (!relay_ssltcp_port.empty()) {
+    talk_base::SocketAddress address(relay_ip, atoi(relay_ssltcp_port.c_str()));
+    ports.push_back(ProtocolAddress(address, PROTO_SSLTCP));
+  }
+  config->AddRelay(ports, 0.0f);
+  ConfigReady(config);
+}
+
+} // namespace cricket
diff --git a/talk/p2p/client/httpportallocator.h b/talk/p2p/client/httpportallocator.h
new file mode 100755
index 0000000..96f3e72
--- /dev/null
+++ b/talk/p2p/client/httpportallocator.h
@@ -0,0 +1,61 @@
+#ifndef _HTTPPORTALLOCATOR_H_
+#define _HTTPPORTALLOCATOR_H_
+
+#include "talk/p2p/client/basicportallocator.h"
+
+namespace talk_base {
+  class SignalThread;
+}
+
+namespace cricket {
+
+class HttpPortAllocator : public BasicPortAllocator {
+public:
+  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:
+  std::vector<talk_base::SocketAddress> stun_hosts_;
+  std::vector<std::string> relay_hosts_;
+  std::string relay_token_;
+  std::string agent_;
+};
+
+class RequestData;
+
+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() {};
+
+protected:
+  virtual void GetPortConfigurations();
+
+private:
+  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
+
+#endif // _XMPPPORTALLOCATOR_H_
diff --git a/talk/p2p/client/sessionmanagertask.h b/talk/p2p/client/sessionmanagertask.h
new file mode 100755
index 0000000..2a05357
--- /dev/null
+++ b/talk/p2p/client/sessionmanagertask.h
@@ -0,0 +1,91 @@
+/*
+ * 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 _SESSIONMANAGERTASK_H_
+#define _SESSIONMANAGERTASK_H_
+
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/client/sessionsendtask.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
+
+namespace cricket {
+
+// This class handles sending and receiving XMPP messages on behalf of the
+// SessionManager.  The sending part is handed over to SessionSendTask.
+
+class SessionManagerTask : public buzz::XmppTask {
+ public:
+  SessionManagerTask(Task *parent, SessionManager *session_manager)
+      : buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE) {
+    session_manager_ = session_manager;
+  }
+
+  ~SessionManagerTask() {
+  }
+
+  // Turns on simple support for sending messages, using SessionSendTask.
+  void EnableOutgoingMessages() {
+    session_manager_->SignalOutgoingMessage.connect(
+        this, &SessionManagerTask::OnOutgoingMessage);
+    session_manager_->SignalRequestSignaling.connect(
+        session_manager_, &SessionManager::OnSignalingReady);
+  }
+
+  virtual int ProcessStart() {
+    const buzz::XmlElement *stanza = NextStanza();
+    if (stanza == NULL)
+      return STATE_BLOCKED;
+    session_manager_->OnIncomingMessage(stanza);
+    return STATE_START;
+  }
+
+ protected:
+  virtual bool HandleStanza(const buzz::XmlElement *stanza) {
+    if (!session_manager_->IsSessionMessage(stanza))
+      return false;
+    // Responses are handled by the SessionSendTask that sent the request.
+    //if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_SET)
+    //  return false;
+    QueueStanza(stanza);
+    return true;
+  }
+
+ private:
+  SessionManager* session_manager_;
+
+  void OnOutgoingMessage(const buzz::XmlElement* stanza) {
+    cricket::SessionSendTask* sender =
+        new cricket::SessionSendTask(GetParent(), session_manager_);
+    sender->Send(stanza);
+    sender->Start();
+  }
+};
+
+}  // namespace cricket
+
+#endif // _SESSIONMANAGERTASK_H_
diff --git a/talk/p2p/client/sessionsendtask.h b/talk/p2p/client/sessionsendtask.h
new file mode 100755
index 0000000..3beb9d4
--- /dev/null
+++ b/talk/p2p/client/sessionsendtask.h
@@ -0,0 +1,137 @@
+/*
+ * 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 _CRICKET_P2P_CLIENT_SESSIONSENDTASK_H_
+#define _CRICKET_P2P_CLIENT_SESSIONSENDTASK_H_
+
+#include "talk/base/common.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/xmppclient.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmpptask.h"
+#include "talk/p2p/base/sessionmanager.h"
+
+namespace cricket {
+
+// The job of this task is to send an IQ stanza out (after stamping it with
+// an ID attribute) and then wait for a response.  If not response happens
+// within 5 seconds, it will signal failure on a SessionManager.  If an error
+// happens it will also signal failure.  If, however, the send succeeds this
+// task will quietly go away.
+
+class SessionSendTask : public buzz::XmppTask {
+public:
+  SessionSendTask(Task *parent, SessionManager *session_manager)
+    : buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE),
+      session_manager_(session_manager) {
+    set_timeout_seconds(15);
+  }
+
+  virtual ~SessionSendTask() {
+    SignalDone(this);
+  }
+
+  void Send(const buzz::XmlElement* stanza) {
+    ASSERT(stanza_.get() == NULL);
+
+    // This should be an IQ of type set, result, or error.  In the first case,
+    // we supply an ID.  In the others, it should be present.
+    ASSERT(stanza->Name() == buzz::QN_IQ);
+    ASSERT(stanza->HasAttr(buzz::QN_TYPE));
+    if (stanza->Attr(buzz::QN_TYPE) == "set") {
+      ASSERT(!stanza->HasAttr(buzz::QN_ID));
+    } else {
+      ASSERT((stanza->Attr(buzz::QN_TYPE) == "result") ||
+             (stanza->Attr(buzz::QN_TYPE) == "error"));
+      ASSERT(stanza->HasAttr(buzz::QN_ID));
+    }
+
+    stanza_.reset(new buzz::XmlElement(*stanza));
+    if (stanza_->HasAttr(buzz::QN_ID)) {
+      set_task_id(stanza_->Attr(buzz::QN_ID));
+    } else {
+      stanza_->SetAttr(buzz::QN_ID, task_id());
+    }
+  }
+
+  sigslot::signal1<SessionSendTask *> SignalDone;
+
+protected:
+  virtual int OnTimeout() {
+    session_manager_->OnFailedSend(stanza_.get(), NULL);
+
+    return XmppTask::OnTimeout();
+  }
+
+  virtual int ProcessStart() {
+    SendStanza(stanza_.get());
+    if (stanza_->Attr(buzz::QN_TYPE) == buzz::STR_SET) {
+      return STATE_RESPONSE;
+    } else {
+      return STATE_DONE;
+    }
+  }
+
+  virtual int ProcessResponse() {
+    if (GetClient()->GetState() != buzz::XmppEngine::STATE_OPEN) {
+      return STATE_DONE;
+    }
+
+    const buzz::XmlElement* next = NextStanza();
+    if (next == NULL)
+      return STATE_BLOCKED;
+
+    if (next->Attr(buzz::QN_TYPE) == buzz::STR_RESULT) {
+      session_manager_->OnIncomingResponse(stanza_.get(), next);
+    } else {
+      session_manager_->OnFailedSend(stanza_.get(), next);
+    }
+
+    return STATE_DONE;
+  }
+
+  virtual bool HandleStanza(const buzz::XmlElement *stanza) {
+    if (!MatchResponseIq(stanza,
+                         buzz::Jid(stanza_->Attr(buzz::QN_TO)), task_id()))
+      return false;
+    if (stanza->Attr(buzz::QN_TYPE) == buzz::STR_RESULT ||
+        stanza->Attr(buzz::QN_TYPE) == buzz::STR_ERROR) {
+      QueueStanza(stanza);
+      return true;
+    }
+    return false;
+  }
+
+private:
+  SessionManager *session_manager_;
+  talk_base::scoped_ptr<buzz::XmlElement> stanza_;
+  bool timed_out_;
+};
+
+}
+
+#endif // _CRICKET_P2P_CLIENT_SESSIONSENDTASK_H_
diff --git a/talk/p2p/client/socketmonitor.cc b/talk/p2p/client/socketmonitor.cc
new file mode 100755
index 0000000..88d37ce
--- /dev/null
+++ b/talk/p2p/client/socketmonitor.cc
@@ -0,0 +1,164 @@
+/*
+ * 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/p2p/client/socketmonitor.h"
+#include "talk/base/common.h"
+
+namespace cricket {
+
+const uint32 MSG_MONITOR_POLL = 1;
+const uint32 MSG_MONITOR_START = 2;
+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;
+  channel_ = channel;
+  channel_thread_ = session->session_manager()->worker_thread();
+  monitoring_thread_ = monitor_thread;
+  monitoring_ = false;
+}
+
+SocketMonitor::~SocketMonitor() {
+  channel_thread_->Clear(this);
+  monitoring_thread_->Clear(this);
+}
+
+void SocketMonitor::Start(int milliseconds) {
+  rate_ = milliseconds;
+  if (rate_ < 250)
+    rate_ = 250;
+  channel_thread_->Post(this, MSG_MONITOR_START);
+}
+
+void SocketMonitor::Stop() {
+  channel_thread_->Post(this, MSG_MONITOR_STOP);
+}
+
+void SocketMonitor::OnMessage(talk_base::Message *message) {
+  talk_base::CritScope cs(&crit_);
+
+  switch (message->message_id) {
+  case MSG_MONITOR_START:
+    ASSERT(talk_base::Thread::Current() == channel_thread_);
+    if (!monitoring_) {
+      monitoring_ = true;
+      if (GetP2PChannel() != NULL) {
+        GetP2PChannel()->SignalConnectionMonitor.connect(
+            this, &SocketMonitor::OnConnectionMonitor);
+      }
+      PollSocket(true);
+    }
+    break;
+
+  case MSG_MONITOR_STOP:
+    ASSERT(talk_base::Thread::Current() == channel_thread_);
+    if (monitoring_) {
+      monitoring_ = false;
+      if (GetP2PChannel() != NULL)
+        GetP2PChannel()->SignalConnectionMonitor.disconnect(this);
+      channel_thread_->Clear(this);
+    }
+    break;
+
+  case MSG_MONITOR_POLL:
+    ASSERT(talk_base::Thread::Current() == channel_thread_);
+    PollSocket(true);
+    break;
+
+  case MSG_MONITOR_SIGNAL:
+    {
+      ASSERT(talk_base::Thread::Current() == monitoring_thread_);
+      std::vector<ConnectionInfo> infos = connection_infos_;
+      crit_.Leave();
+      SignalUpdate(this, infos);
+      crit_.Enter();
+    }
+    break;
+  }
+}
+
+void SocketMonitor::OnConnectionMonitor(P2PTransportChannel* channel) {
+  talk_base::CritScope cs(&crit_);
+  if (monitoring_)
+    PollSocket(false);
+}
+
+void SocketMonitor::PollSocket(bool poll) {
+  ASSERT(talk_base::Thread::Current() == channel_thread_);
+  talk_base::CritScope cs(&crit_);
+
+  // Gather connection infos
+
+  P2PTransportChannel* p2p_channel = GetP2PChannel();
+  if (p2p_channel != NULL) {
+    connection_infos_.clear();
+    const std::vector<Connection *> &connections = p2p_channel->connections();
+    std::vector<Connection *>::const_iterator it;
+    for (it = connections.begin(); it != connections.end(); it++) {
+      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.new_connection = !connection->reported();
+      connection->set_reported(true);
+      info.rtt = connection->rtt();
+      info.sent_total_bytes = connection->sent_total_bytes();
+      info.sent_bytes_second = connection->sent_bytes_second();
+      info.recv_total_bytes = connection->recv_total_bytes();
+      info.recv_bytes_second = connection->recv_bytes_second();
+      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);
+      connection_infos_.push_back(info);
+    }
+  }
+
+  // Signal the monitoring thread, start another poll timer
+
+  monitoring_thread_->Post(this, MSG_MONITOR_SIGNAL);
+  if (poll)
+    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
new file mode 100755
index 0000000..ced86b8
--- /dev/null
+++ b/talk/p2p/client/socketmonitor.h
@@ -0,0 +1,91 @@
+/*
+ * 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 _SOCKETMONITOR_H_
+#define _SOCKETMONITOR_H_
+
+#include "talk/base/thread.h"
+#include "talk/base/sigslot.h"
+#include "talk/base/criticalsection.h"
+#include "talk/p2p/base/session.h"
+#include "talk/p2p/base/p2ptransportchannel.h"
+#include "talk/p2p/base/port.h"
+#include <vector>
+
+namespace cricket {
+
+struct ConnectionInfo {
+  bool best_connection;
+  bool writable;
+  bool readable;
+  bool timeout;
+  bool new_connection;
+  size_t rtt;
+  size_t sent_total_bytes;
+  size_t sent_bytes_second;
+  size_t recv_total_bytes;
+  size_t recv_bytes_second;
+  Candidate local_candidate;
+  Candidate remote_candidate;
+  double est_quality;
+  void *key;
+};
+
+class SocketMonitor : public talk_base::MessageHandler, 
+    public sigslot::has_slots<> {
+public:
+  SocketMonitor(Session* session, TransportChannel* channel,
+                talk_base::Thread *monitor_thread);
+  ~SocketMonitor();
+
+  void Start(int cms);
+  void Stop();
+
+  talk_base::Thread *monitor_thread() { return monitoring_thread_; }
+
+  sigslot::signal2<SocketMonitor *,
+                   const std::vector<ConnectionInfo> &> SignalUpdate;
+
+protected:
+  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_;
+  talk_base::CriticalSection crit_;
+  uint32 rate_;
+  bool monitoring_;
+};
+
+}
+
+#endif // _SOCKETMONITOR_H_
diff --git a/talk/pkg.m4 b/talk/pkg.m4
new file mode 100755
index 0000000..c80e0ac
--- /dev/null
+++ b/talk/pkg.m4
@@ -0,0 +1,57 @@
+
+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
new file mode 100755
index 0000000..e55f7f1
--- /dev/null
+++ b/talk/session/Makefile.am
@@ -0,0 +1,5 @@
+if PHONE
+SUBDIRS = phone tunnel fileshare
+else
+SUBDIRS = tunnel fileshare
+endif
diff --git a/talk/session/Makefile.in b/talk/session/Makefile.in
new file mode 100644
index 0000000..43addf5
--- /dev/null
+++ b/talk/session/Makefile.in
@@ -0,0 +1,489 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/session
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-exec-recursive install-info-recursive \
+	install-recursive installcheck-recursive installdirs-recursive \
+	pdf-recursive ps-recursive uninstall-info-recursive \
+	uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = tunnel fileshare phone
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+@PHONE_FALSE@SUBDIRS = tunnel fileshare
+@PHONE_TRUE@SUBDIRS = phone tunnel fileshare
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/session/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/session/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(mkdir_p) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
+	clean clean-generic clean-libtool clean-recursive ctags \
+	ctags-recursive distclean distclean-generic distclean-libtool \
+	distclean-recursive distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-recursive \
+	mostlyclean mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/session/fileshare/Makefile.am b/talk/session/fileshare/Makefile.am
new file mode 100755
index 0000000..a6eebf6
--- /dev/null
+++ b/talk/session/fileshare/Makefile.am
@@ -0,0 +1,7 @@
+libcricketsessionfileshare_la_SOURCES = fileshare.cc
+
+noinst_HEADERS =                    fileshare.h 
+
+AM_CPPFLAGS := -DPOSIX 
+noinst_LTLIBRARIES = libcricketsessionfileshare.la
+				    
diff --git a/talk/session/fileshare/Makefile.in b/talk/session/fileshare/Makefile.in
new file mode 100644
index 0000000..3c9cd69
--- /dev/null
+++ b/talk/session/fileshare/Makefile.in
@@ -0,0 +1,446 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/session/fileshare
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketsessionfileshare_la_LIBADD =
+am_libcricketsessionfileshare_la_OBJECTS = fileshare.lo
+libcricketsessionfileshare_la_OBJECTS =  \
+	$(am_libcricketsessionfileshare_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketsessionfileshare_la_SOURCES)
+DIST_SOURCES = $(libcricketsessionfileshare_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+libcricketsessionfileshare_la_SOURCES = fileshare.cc
+noinst_HEADERS = fileshare.h 
+AM_CPPFLAGS := -DPOSIX 
+noinst_LTLIBRARIES = libcricketsessionfileshare.la
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/session/fileshare/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/session/fileshare/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketsessionfileshare.la: $(libcricketsessionfileshare_la_OBJECTS) $(libcricketsessionfileshare_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketsessionfileshare_la_LDFLAGS) $(libcricketsessionfileshare_la_OBJECTS) $(libcricketsessionfileshare_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileshare.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/session/fileshare/fileshare.cc b/talk/session/fileshare/fileshare.cc
new file mode 100755
index 0000000..863c352
--- /dev/null
+++ b/talk/session/fileshare/fileshare.cc
@@ -0,0 +1,1313 @@
+/*
+ * 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
new file mode 100755
index 0000000..b0802b4
--- /dev/null
+++ b/talk/session/fileshare/fileshare.h
@@ -0,0 +1,250 @@
+#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
new file mode 100755
index 0000000..5d489b6
--- /dev/null
+++ b/talk/session/phone/Makefile.am
@@ -0,0 +1,27 @@
+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/Makefile.in b/talk/session/phone/Makefile.in
new file mode 100644
index 0000000..8dfdbc8
--- /dev/null
+++ b/talk/session/phone/Makefile.in
@@ -0,0 +1,485 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/session/phone
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketsessionphone_la_LIBADD =
+am_libcricketsessionphone_la_OBJECTS = audiomonitor.lo \
+	channelmanager.lo voicechannel.lo call.lo \
+	phonesessionclient.lo
+am__dist_libcricketsessionphone_la_SOURCES_DIST =  \
+	linphonemediaengine.cc
+@GIPS_FALSE@dist_libcricketsessionphone_la_OBJECTS =  \
+@GIPS_FALSE@	linphonemediaengine.lo
+@GIPS_TRUE@nodist_libcricketsessionphone_la_OBJECTS =  \
+@GIPS_TRUE@	gipsmediaengine.lo gipsstatsmonitor.lo
+libcricketsessionphone_la_OBJECTS =  \
+	$(am_libcricketsessionphone_la_OBJECTS) \
+	$(dist_libcricketsessionphone_la_OBJECTS) \
+	$(nodist_libcricketsessionphone_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketsessionphone_la_SOURCES) \
+	$(dist_libcricketsessionphone_la_SOURCES) \
+	$(nodist_libcricketsessionphone_la_SOURCES)
+DIST_SOURCES = $(libcricketsessionphone_la_SOURCES) \
+	$(am__dist_libcricketsessionphone_la_SOURCES_DIST)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+EXTRA_DIST = gipslitemediaengine.cc gipslitemediaengine.h
+@GIPS_TRUE@nodist_libcricketsessionphone_la_SOURCES = gipsmediaengine.cc \
+@GIPS_TRUE@					 gipsstatsmonitor.cc
+
+@GIPS_FALSE@dist_libcricketsessionphone_la_SOURCES = linphonemediaengine.cc
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/session/phone/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/session/phone/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketsessionphone.la: $(libcricketsessionphone_la_OBJECTS) $(libcricketsessionphone_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketsessionphone_la_LDFLAGS) $(libcricketsessionphone_la_OBJECTS) $(libcricketsessionphone_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audiomonitor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channelmanager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gipsmediaengine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gipsstatsmonitor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linphonemediaengine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phonesessionclient.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/voicechannel.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/session/phone/audiomonitor.cc b/talk/session/phone/audiomonitor.cc
new file mode 100755
index 0000000..c1f3614
--- /dev/null
+++ b/talk/session/phone/audiomonitor.cc
@@ -0,0 +1,120 @@
+/*
+ * 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/audiomonitor.h"
+#include "talk/session/phone/voicechannel.h"
+#include <cassert>
+
+namespace cricket {
+
+const uint32 MSG_MONITOR_POLL = 1;
+const uint32 MSG_MONITOR_START = 2;
+const uint32 MSG_MONITOR_STOP = 3;
+const uint32 MSG_MONITOR_SIGNAL = 4;
+
+AudioMonitor::AudioMonitor(VoiceChannel *voice_channel, 
+                           talk_base::Thread *monitor_thread) {
+  voice_channel_ = voice_channel;
+  monitoring_thread_ = monitor_thread;
+  monitoring_ = false;
+}
+
+AudioMonitor::~AudioMonitor() {
+  voice_channel_->worker_thread()->Clear(this);
+  monitoring_thread_->Clear(this);
+}
+
+void AudioMonitor::Start(int milliseconds) {
+  rate_ = milliseconds;
+  if (rate_ < 100)
+    rate_ = 100;
+  voice_channel_->worker_thread()->Post(this, MSG_MONITOR_START);
+}
+
+void AudioMonitor::Stop() {
+  voice_channel_->worker_thread()->Post(this, MSG_MONITOR_STOP);
+}
+
+void AudioMonitor::OnMessage(talk_base::Message *message) {
+  talk_base::CritScope cs(&crit_);
+
+  switch (message->message_id) {
+  case MSG_MONITOR_START:
+    assert(talk_base::Thread::Current() == voice_channel_->worker_thread());
+    if (!monitoring_) {
+      monitoring_ = true;
+      PollVoiceChannel();
+    }
+    break;
+
+  case MSG_MONITOR_STOP:
+    assert(talk_base::Thread::Current() == voice_channel_->worker_thread());
+    if (monitoring_) {
+      monitoring_ = false;
+      voice_channel_->worker_thread()->Clear(this);
+    }
+    break;
+
+  case MSG_MONITOR_POLL:
+    assert(talk_base::Thread::Current() == voice_channel_->worker_thread());
+    PollVoiceChannel();
+    break;
+
+  case MSG_MONITOR_SIGNAL:
+    {
+      assert(talk_base::Thread::Current() == monitoring_thread_);
+      AudioInfo info = audio_info_;
+      crit_.Leave();
+      SignalUpdate(this, audio_info_);
+      crit_.Enter();
+    }
+    break;
+  }
+}
+
+void AudioMonitor::PollVoiceChannel() {
+  talk_base::CritScope cs(&crit_);
+  assert(talk_base::Thread::Current() == voice_channel_->worker_thread());
+
+  // Gather connection infos
+  audio_info_.input_level = voice_channel_->GetInputLevel_w();
+  audio_info_.output_level = voice_channel_->GetOutputLevel_w();
+
+  // Signal the monitoring thread, start another poll timer
+  monitoring_thread_->Post(this, MSG_MONITOR_SIGNAL);
+  voice_channel_->worker_thread()->PostDelayed(rate_, this, MSG_MONITOR_POLL);
+}
+
+VoiceChannel *AudioMonitor::voice_channel() {
+  return voice_channel_;
+}
+
+talk_base::Thread *AudioMonitor::monitor_thread() {
+  return monitoring_thread_;
+}
+
+}
diff --git a/talk/session/phone/audiomonitor.h b/talk/session/phone/audiomonitor.h
new file mode 100755
index 0000000..2bfd784
--- /dev/null
+++ b/talk/session/phone/audiomonitor.h
@@ -0,0 +1,74 @@
+/*
+ * 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 _CRICKET_PHONE_AUDIOMONITOR_H_
+#define _CRICKET_PHONE_AUDIOMONITOR_H_
+
+#include "talk/base/thread.h"
+#include "talk/base/sigslot.h"
+#include "talk/p2p/base/port.h"
+#include <vector>
+
+namespace cricket {
+
+class VoiceChannel;
+
+
+struct AudioInfo {
+  int input_level;
+  int output_level;
+};
+
+class AudioMonitor : public talk_base::MessageHandler, 
+    public sigslot::has_slots<> {
+public:
+  AudioMonitor(VoiceChannel* voice_channel, talk_base::Thread *monitor_thread);
+  ~AudioMonitor();
+
+  void Start(int cms);
+  void Stop();
+
+  VoiceChannel* voice_channel();
+  talk_base::Thread *monitor_thread();
+
+  sigslot::signal2<AudioMonitor*, const AudioInfo&> SignalUpdate;
+
+protected:
+  void OnMessage(talk_base::Message *message);
+  void PollVoiceChannel();
+
+  AudioInfo audio_info_;
+  VoiceChannel* voice_channel_;
+  talk_base::Thread* monitoring_thread_;
+  talk_base::CriticalSection crit_;
+  uint32 rate_;
+  bool monitoring_;
+};
+
+}
+
+#endif // _CRICKET_PHONE_AUDIOMONITOR_H_
diff --git a/talk/session/phone/call.cc b/talk/session/phone/call.cc
new file mode 100755
index 0000000..1676945
--- /dev/null
+++ b/talk/session/phone/call.cc
@@ -0,0 +1,336 @@
+/*
+ * 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/helpers.h"
+#include "talk/base/logging.h"
+#include "talk/base/thread.h"
+#include "talk/session/phone/call.h"
+
+namespace cricket {
+
+const uint32 MSG_CHECKAUTODESTROY = 1;
+const uint32 MSG_TERMINATECALL = 2;
+
+namespace {
+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() {
+  while (sessions_.begin() != sessions_.end()) {
+    Session *session = sessions_[0];
+    RemoveSession(session);
+    session_client_->session_manager()->DestroySession(session);
+  }
+  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());
+
+  // After this timeout, terminate the call because the callee isn't 
+  // answering
+  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);
+  return session;
+}
+
+void Call::AcceptSession(Session *session) {
+  std::vector<Session *>::iterator it;
+  it = std::find(sessions_.begin(), sessions_.end(), session);
+  assert(it != sessions_.end());
+  if (it != sessions_.end()) {
+    session->Accept(session_client_->CreateAcceptSessionDescription(
+      session->remote_description()));
+  }
+}
+
+void Call::RedirectSession(Session *session, const buzz::Jid &to) {
+  std::vector<Session *>::iterator it;
+  it = std::find(sessions_.begin(), sessions_.end(), session);
+  assert(it != sessions_.end());
+  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);
+}
+
+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) 
+         != sessions_.end());
+  std::vector<Session *>::iterator it;
+  it = std::find(sessions_.begin(), sessions_.end(), session);
+  if (it != sessions_.end())
+    (*it)->Terminate();
+}
+
+void Call::Terminate() {
+  // Copy the list so that we can iterate over it in a stable way
+  std::vector<Session *> sessions = sessions_;
+
+  // There may be more than one session to terminate
+  std::vector<Session *>::iterator it;
+  for (it = sessions.begin(); it != sessions.end(); it++)
+    TerminateSession(*it);
+  
+}
+
+void Call::OnMessage(talk_base::Message *message) {
+  switch (message->message_id) {
+  case MSG_CHECKAUTODESTROY:
+    // If no more sessions for this call, delete it
+    if (sessions_.size() == 0)
+      session_client_->DestroyCall(this);
+    break;
+  case MSG_TERMINATECALL:
+    // Signal to the user that a timeout has happened and the call should
+    // be sent to voicemail.
+    if (send_to_voicemail_) {
+      SignalSetupToCallVoicemail();
+    }
+
+    // Callee didn't answer - terminate call
+    Terminate();
+    break;
+  }
+}
+
+const std::vector<Session *> &Call::sessions() {
+  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);
+
+  VoiceChannel *channel 
+    = session_client_->channel_manager()->CreateVoiceChannel(session);
+  channel_map_[session->id()] = channel;
+
+  // Start the media monitor for this voicechannel
+  channel->SignalMediaMonitor.connect(this, &Call::OnMediaMonitor);
+  channel->StartMediaMonitor(kMediaMonitorInterval);
+
+  // If this call has the focus, enable this channel
+  if (session_client_->GetFocus() == this)
+    channel->Enable(true);
+
+  // Signal client
+  SignalAddSession(this, session);
+}
+
+void Call::RemoveSession(Session *session) {
+  // Remove session from list
+  std::vector<Session *>::iterator it_session;
+  it_session = std::find(sessions_.begin(), sessions_.end(), session);
+  if (it_session == sessions_.end())
+    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);
+  }
+
+  // Signal client
+  SignalRemoveSession(this, session);
+
+  
+
+  // The call auto destroys when the lass 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;
+}
+
+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);
+  }
+}
+
+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);
+  }
+}
+
+
+void Call::Join(Call *call, bool enable) {
+  while (call->sessions_.size() != 0) {
+    // Move session
+    Session *session = call->sessions_[0];
+    call->sessions_.erase(call->sessions_.begin());
+    sessions_.push_back(session);
+    session->SignalState.connect(this, &Call::OnSessionState);
+    session->SignalError.connect(this, &Call::OnSessionError);
+    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);
+    }
+  }
+}
+
+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::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::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::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::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);
+}
+
+void Call::OnMediaMonitor(VoiceChannel *channel, const MediaInfo& info) {
+  SignalMediaMonitor(this, channel->session(), info);
+}
+
+uint32 Call::id() {
+  return id_;
+}
+
+void Call::OnSessionState(Session *session, Session::State state) {
+  switch (state) {
+    case Session::STATE_RECEIVEDACCEPT:
+    case Session::STATE_RECEIVEDREJECT:
+    case Session::STATE_RECEIVEDTERMINATE:
+      session_client_->session_manager()->signaling_thread()->Clear(this, 
+          MSG_TERMINATECALL);
+      break;
+  }
+  SignalSessionState(this, session, state);
+}
+
+void Call::OnSessionError(Session *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) {
+  session_client_->session_manager()->signaling_thread()->Clear(this,
+    MSG_TERMINATECALL);
+  SignalReceivedTerminateReason(this, session, reason);
+}
+
+}
diff --git a/talk/session/phone/call.h b/talk/session/phone/call.h
new file mode 100755
index 0000000..7b8d9b6
--- /dev/null
+++ b/talk/session/phone/call.h
@@ -0,0 +1,116 @@
+/*
+ * 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 _CALL_H_
+#define _CALL_H_
+
+#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/voicechannel.h"
+#include "talk/session/phone/audiomonitor.h"
+
+#include <map>
+#include <vector>
+#include <deque>
+
+namespace cricket {
+
+class PhoneSessionClient;
+
+class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
+public:
+  Call(PhoneSessionClient *session_client);
+  ~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);
+  void Terminate();
+  void StartConnectionMonitor(Session *session, int cms);
+  void StopConnectionMonitor(Session *session);
+  void StartAudioMonitor(Session *session, int cms);
+  void StopAudioMonitor(Session *session);
+  void Mute(bool mute);
+
+
+  const std::vector<Session *> &sessions();
+  uint32 id();
+  bool muted() const { return muted_; }
+
+  // Setting this to false will cause the call to have a longer timeout and
+  // for the SignalSetupToCallVoicemail to never fire.
+  void set_send_to_voicemail(bool send_to_voicemail) {
+    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;
+
+private:
+  void OnMessage(talk_base::Message *message);
+  void OnSessionState(Session *session, Session::State state);
+  void OnSessionError(Session *session, Session::Error error);
+  void OnReceivedTerminateReason(Session *session, const std::string &reason);
+  void AddSession(Session *session);
+  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 OnMediaMonitor(VoiceChannel *channel, const MediaInfo& info);
+  VoiceChannel* GetChannel(Session* session);
+
+  uint32 id_;
+  PhoneSessionClient *session_client_;
+  std::vector<Session *> sessions_;
+  std::map<SessionID, VoiceChannel *> channel_map_;
+  bool muted_;
+  bool send_to_voicemail_;
+
+
+  friend class PhoneSessionClient;
+};
+
+}
+
+#endif // _CALL_H_
diff --git a/talk/session/phone/channelmanager.cc b/talk/session/phone/channelmanager.cc
new file mode 100755
index 0000000..77b7a73
--- /dev/null
+++ b/talk/session/phone/channelmanager.cc
@@ -0,0 +1,219 @@
+/*
+ * 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
+
+#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"
+#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;
+
+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();
+#endif
+  worker_thread_ = worker_thread;
+  initialized_ = false;
+  Init();
+}
+
+ChannelManager::~ChannelManager() {
+  Exit();
+}
+
+MediaEngine *ChannelManager::media_engine() {
+  return media_engine_;
+}
+
+bool ChannelManager::Init() {
+  initialized_ =  media_engine_->Init();
+  return initialized_;
+}
+
+void ChannelManager::Exit() {
+  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;
+  }
+  media_engine_->Terminate();
+}
+
+struct CreateParams {
+  Session *session;
+  VoiceChannel *channel;
+};
+
+VoiceChannel *ChannelManager::CreateVoiceChannel(Session *session) {
+  CreateParams params;
+  params.session = session;
+  params.channel = NULL;
+  talk_base::TypedMessageData<CreateParams *> data(&params);
+  worker_thread_->Send(this, MSG_CREATEVOICECHANNEL, &data);
+  return params.channel;
+}
+
+VoiceChannel *ChannelManager::CreateVoiceChannel_w(Session *session) {
+  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)
+    return NULL;
+
+  VoiceChannel *voice_channel = new VoiceChannel(this, session, channel);
+  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_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())
+    return;
+ 
+  channels_.erase(it);
+  MediaChannel *channel = voice_channel->channel();
+  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);
+}
+
+void ChannelManager::SetAudioOptions_w(AudioOptions options) {
+  assert(worker_thread_ == talk_base::Thread::Current());
+
+  // 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.
+  }
+
+  // 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.
+  {
+    talk_base::CritScope cs(&crit_);
+    for (VoiceChannels::iterator it = channels_.begin();
+         it < channels_.end();
+         ++it) {
+      (*it)->PauseMedia_w();
+    }
+
+    if (media_engine_->SetSoundDevices(options.wave_in_device, 
+        options.wave_out_device) == -1) {
+      // TODO: We need to log these failures.
+    }
+
+    for (VoiceChannels::iterator it = channels_.begin();
+         it < channels_.end();
+         ++it) {
+      (*it)->UnpauseMedia_w();
+    }
+  }
+}
+
+talk_base::Thread *ChannelManager::worker_thread() {
+  return worker_thread_;
+}
+
+void ChannelManager::OnMessage(talk_base::Message *message) {
+  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);
+    }
+    break;
+
+  case MSG_DESTROYVOICECHANNEL:
+    {
+      talk_base::TypedMessageData<VoiceChannel *> *data 
+        = static_cast<talk_base::TypedMessageData<VoiceChannel *> *>(
+          message->pdata);
+      DestroyVoiceChannel_w(data->data());
+    }
+    break;
+  case MSG_SETAUDIOOPTIONS:
+    {
+      talk_base::TypedMessageData<AudioOptions> *data 
+        = static_cast<talk_base::TypedMessageData<AudioOptions> *>(
+          message->pdata);
+      SetAudioOptions_w(data->data());
+    }
+    break;
+  }
+}
+
+}
diff --git a/talk/session/phone/channelmanager.h b/talk/session/phone/channelmanager.h
new file mode 100755
index 0000000..c17d5bb
--- /dev/null
+++ b/talk/session/phone/channelmanager.h
@@ -0,0 +1,80 @@
+/*
+ * 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 _CHANNELMANAGER_H_
+#define _CHANNELMANAGER_H_
+
+#include "talk/base/thread.h"
+#include "talk/base/criticalsection.h"
+#include "talk/p2p/base/session.h"
+#include "talk/session/phone/voicechannel.h"
+#include "talk/session/phone/mediaengine.h"
+#include <vector>
+
+namespace cricket {
+
+class VoiceChannel;
+
+class ChannelManager : public talk_base::MessageHandler {
+public:
+  ChannelManager(talk_base::Thread *worker_thread);
+  ~ChannelManager();
+
+  VoiceChannel *CreateVoiceChannel(Session *session);
+  void DestroyVoiceChannel(VoiceChannel *voice_channel);
+  void SetAudioOptions(bool auto_gain_control, int wave_in_device,
+                       int wave_out_device);
+
+  MediaEngine *media_engine();
+  talk_base::Thread *worker_thread();
+
+private:
+  VoiceChannel *CreateVoiceChannel_w(Session *session);
+  void DestroyVoiceChannel_w(VoiceChannel *voice_channel);
+  void OnMessage(talk_base::Message *message);
+  bool Init();
+  void Exit();
+
+  struct AudioOptions {
+    bool auto_gain_control;
+    int wave_in_device;
+    int wave_out_device;
+  };
+  void SetAudioOptions_w(AudioOptions options);
+
+  talk_base::Thread *worker_thread_;
+  MediaEngine *media_engine_;
+  bool initialized_;
+  talk_base::CriticalSection crit_;
+
+  typedef std::vector<VoiceChannel*> VoiceChannels;
+  VoiceChannels channels_;
+};
+
+}
+
+#endif // _CHANNELMANAGER_H_
diff --git a/talk/session/phone/codec.h b/talk/session/phone/codec.h
new file mode 100755
index 0000000..ef99c2b
--- /dev/null
+++ b/talk/session/phone/codec.h
@@ -0,0 +1,47 @@
+/*
+ * 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 _CODEC_H_
+#define _CODEC_H_
+
+struct Codec {
+  int id;
+  std::string name;
+  int clockrate;
+  int bitrate;
+  int channels;
+
+  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.
+};
+
+#endif // CODEC_H_
diff --git a/talk/session/phone/gipslitemediaengine.cc b/talk/session/phone/gipslitemediaengine.cc
new file mode 100755
index 0000000..87ff5c4
--- /dev/null
+++ b/talk/session/phone/gipslitemediaengine.cc
@@ -0,0 +1,239 @@
+/*
+ * 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
new file mode 100755
index 0000000..ea144d8
--- /dev/null
+++ b/talk/session/phone/gipslitemediaengine.h
@@ -0,0 +1,93 @@
+/*
+ * 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
new file mode 100755
index 0000000..8b285f6
--- /dev/null
+++ b/talk/session/phone/linphonemediaengine.cc
@@ -0,0 +1,201 @@
+/*
+ * 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
new file mode 100755
index 0000000..5a12693
--- /dev/null
+++ b/talk/session/phone/linphonemediaengine.h
@@ -0,0 +1,88 @@
+/*
+ * 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
new file mode 100755
index 0000000..65463a5
--- /dev/null
+++ b/talk/session/phone/mediachannel.h
@@ -0,0 +1,78 @@
+/*
+ * 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_MEDIACHANNEL_H_
+#define TALK_SESSION_PHONE_MEDIACHANNEL_H_
+
+#include "talk/base/basictypes.h"
+#include "talk/base/sigslot.h"
+#include "talk/session/phone/codec.h"
+
+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;
+};
+
+class MediaChannel : public sigslot::has_slots<> {
+ public:
+  class NetworkInterface {
+  public:
+    virtual void SendPacket(const void *data, size_t len) = 0;
+  };
+  MediaChannel() {network_interface_ = NULL;}
+  virtual ~MediaChannel() {};
+  void SetInterface(NetworkInterface *iface) {network_interface_ = iface;}
+  virtual void SetCodecs(const std::vector<Codec> &codecs) = 0;
+  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;
+
+  virtual void StartMediaMonitor(VoiceChannel * voice_channel, uint32 cms) = 0;
+  virtual void StopMediaMonitor() = 0;
+  sigslot::signal2<MediaChannel *, const MediaInfo &> SignalMediaMonitor;
+
+
+  NetworkInterface *network_interface() {return network_interface_;}
+ protected:
+  NetworkInterface *network_interface_;
+};
+
+};  // namespace cricket
+
+#endif  // TALK_SESSION_PHONE_MEDIACHANNEL_H_
diff --git a/talk/session/phone/mediaengine.h b/talk/session/phone/mediaengine.h
new file mode 100755
index 0000000..e8081db
--- /dev/null
+++ b/talk/session/phone/mediaengine.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.
+ */
+
+// 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>  
+#include <vector>
+
+#include "talk/session/phone/codec.h"
+#include "talk/session/phone/mediachannel.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,
+  };
+
+  // Initialize 
+  virtual bool Init() = 0;
+  virtual void Terminate() = 0;
+  virtual MediaChannel *CreateChannel() = 0;
+
+  virtual int SetAudioOptions(int options) = 0;
+  virtual int SetSoundDevices(int wave_in_device, int wave_out_device) = 0;
+  virtual int GetInputLevel() = 0;
+
+  virtual std::vector<Codec> codecs() = 0;
+
+  virtual bool FindCodec(const Codec &codec) = 0;
+  
+  int GetCodecPreference (Codec codec);
+};  
+
+}  // namespace cricket
+
+#endif  // TALK_SESSION_PHONE_MEDIAENGINE_H_
diff --git a/talk/session/phone/phonesessionclient.cc b/talk/session/phone/phonesessionclient.cc
new file mode 100755
index 0000000..60daf18
--- /dev/null
+++ b/talk/session/phone/phonesessionclient.cc
@@ -0,0 +1,278 @@
+/*
+ * 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
new file mode 100755
index 0000000..0b4ce25
--- /dev/null
+++ b/talk/session/phone/phonesessionclient.h
@@ -0,0 +1,125 @@
+/*
+ * 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/voicechannel.cc b/talk/session/phone/voicechannel.cc
new file mode 100755
index 0000000..58b8760
--- /dev/null
+++ b/talk/session/phone/voicechannel.cc
@@ -0,0 +1,330 @@
+/*
+ * 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
new file mode 100755
index 0000000..3d0be12
--- /dev/null
+++ b/talk/session/phone/voicechannel.h
@@ -0,0 +1,137 @@
+/*
+ * 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 _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_;
+};
+
+}
+
+#endif // _VOICECHANNEL_H_
diff --git a/talk/session/tunnel/Makefile.am b/talk/session/tunnel/Makefile.am
new file mode 100755
index 0000000..3a8d244
--- /dev/null
+++ b/talk/session/tunnel/Makefile.am
@@ -0,0 +1,7 @@
+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/Makefile.in b/talk/session/tunnel/Makefile.in
new file mode 100644
index 0000000..4df78cc
--- /dev/null
+++ b/talk/session/tunnel/Makefile.in
@@ -0,0 +1,452 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/session/tunnel
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketsessiontunnel_la_LIBADD =
+am_libcricketsessiontunnel_la_OBJECTS = tunnelsessionclient.lo \
+	pseudotcpchannel.lo
+libcricketsessiontunnel_la_OBJECTS =  \
+	$(am_libcricketsessiontunnel_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketsessiontunnel_la_SOURCES)
+DIST_SOURCES = $(libcricketsessiontunnel_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+libcricketsessiontunnel_la_SOURCES = tunnelsessionclient.cc \
+                                     pseudotcpchannel.cc
+
+noinst_HEADERS = tunnelsessionclient.h \
+                 pseudotcpchannel.h
+
+noinst_LTLIBRARIES = libcricketsessiontunnel.la
+AM_CXXFLAGS = -DPOSIX
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/session/tunnel/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/session/tunnel/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketsessiontunnel.la: $(libcricketsessiontunnel_la_OBJECTS) $(libcricketsessiontunnel_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketsessiontunnel_la_LDFLAGS) $(libcricketsessiontunnel_la_OBJECTS) $(libcricketsessiontunnel_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pseudotcpchannel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tunnelsessionclient.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/session/tunnel/pseudotcpchannel.cc b/talk/session/tunnel/pseudotcpchannel.cc
new file mode 100755
index 0000000..54515c0
--- /dev/null
+++ b/talk/session/tunnel/pseudotcpchannel.cc
@@ -0,0 +1,554 @@
+/*
+ * 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/basictypes.h"
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/stringutils.h"
+#include "talk/p2p/base/transportchannel.h"
+#include "pseudotcpchannel.h"
+
+using namespace talk_base;
+
+namespace cricket {
+
+extern const talk_base::ConstantLabel SESSION_STATES[];
+
+// MSG_WK_* - worker thread messages
+// MSG_ST_* - stream thread messages
+// MSG_SI_* - signal thread messages
+
+enum {
+  MSG_WK_CLOCK = 1,
+  MSG_WK_PURGE,
+  MSG_ST_EVENT,
+  MSG_SI_DESTROYCHANNEL,
+  MSG_SI_DESTROY,
+};
+
+struct EventData : public MessageData {
+  int event, error;
+  EventData(int ev, int err = 0) : event(ev), error(err) { }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// PseudoTcpChannel::InternalStream
+///////////////////////////////////////////////////////////////////////////////
+
+class PseudoTcpChannel::InternalStream : public StreamInterface {
+public:
+  InternalStream(PseudoTcpChannel* parent);
+  virtual ~InternalStream();
+
+  virtual StreamState GetState() const;
+  virtual StreamResult Read(void* buffer, size_t buffer_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 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
+  // away until after it receives a Close() from TunnelStream.
+  PseudoTcpChannel* parent_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// PseudoTcpChannel
+// Member object lifetime summaries:
+//   session_ - passed in constructor, cleared when channel_ goes away.
+//   channel_ - created in Connect, destroyed when session_ or tcp_ goes away.
+//   tcp_ - created in Connect, destroyed when channel_ goes away, or connection
+//     closes.
+//   worker_thread_ - created when channel_ is created, purged when channel_ is
+//     destroyed.
+//   stream_ - created in GetStream, destroyed by owner at arbitrary time.
+//   this - created in constructor, destroyed when worker_thread_ and stream_
+//     are both gone.
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Signal thread methods
+//
+
+PseudoTcpChannel::PseudoTcpChannel(Thread* stream_thread, Session* session)
+  : signal_thread_(session->session_manager()->signaling_thread()),
+    worker_thread_(NULL),
+    stream_thread_(stream_thread),
+    session_(session), channel_(NULL), tcp_(NULL), stream_(NULL),
+    stream_readable_(false), pending_read_event_(false),
+    ready_to_connect_(false) {
+  ASSERT(signal_thread_->IsCurrent());
+}
+
+PseudoTcpChannel::~PseudoTcpChannel() {
+  ASSERT(signal_thread_->IsCurrent());
+  ASSERT(worker_thread_ == NULL);
+  ASSERT(session_ == NULL);
+  ASSERT(channel_ == NULL);
+  ASSERT(stream_ == NULL);
+  ASSERT(tcp_ == NULL);
+}
+
+bool PseudoTcpChannel::Connect(const std::string& channel_name) {
+  ASSERT(signal_thread_->IsCurrent());
+  CritScope lock(&cs_);
+
+  if (channel_)
+    return false;
+
+  ASSERT(session_ != NULL);
+  worker_thread_ = session_->session_manager()->worker_thread();
+  channel_ = session_->CreateChannel(channel_name);
+  channel_name_ = channel_name;
+  channel_->SetOption(Socket::OPT_DONTFRAGMENT, 1);
+
+  channel_->SignalDestroyed.connect(this,
+    &PseudoTcpChannel::OnChannelDestroyed);
+  channel_->SignalWritableState.connect(this,
+    &PseudoTcpChannel::OnChannelWritableState);
+  channel_->SignalReadPacket.connect(this,
+    &PseudoTcpChannel::OnChannelRead);
+  channel_->SignalRouteChange.connect(this,
+    &PseudoTcpChannel::OnChannelConnectionChanged);
+
+  ASSERT(tcp_ == NULL);
+  tcp_ = new PseudoTcp(this, 0);
+  if (session_->initiator()) {
+    // Since we may try several protocols and network adapters that won't work,
+    // waiting until we get our first writable notification before initiating
+    // TCP negotiation.
+    ready_to_connect_ = true;
+  }
+
+  return true;
+}
+
+StreamInterface* PseudoTcpChannel::GetStream() {
+  ASSERT(signal_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  ASSERT(NULL != session_);
+  if (!stream_)
+    stream_ = new PseudoTcpChannel::InternalStream(this);
+  //TODO("should we disallow creation of new stream at some point?");
+  return stream_;
+}
+
+void PseudoTcpChannel::OnChannelDestroyed(TransportChannel* channel) {
+  LOG_F(LS_INFO) << "(" << channel->name() << ")";
+  ASSERT(signal_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  ASSERT(channel == channel_);
+  signal_thread_->Clear(this, MSG_SI_DESTROYCHANNEL);
+  // When MSG_WK_PURGE is received, we know there will be no more messages from
+  // the worker thread.
+  worker_thread_->Clear(this, MSG_WK_CLOCK);
+  worker_thread_->Post(this, MSG_WK_PURGE);
+  session_ = NULL;
+  channel_ = NULL;
+  if ((stream_ != NULL)
+      && ((tcp_ == NULL) || (tcp_->State() != PseudoTcp::TCP_CLOSED)))
+    stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, 0));
+  if (tcp_) {
+    tcp_->Close(true);
+    AdjustClock();
+  }
+}
+
+//
+// Stream thread methods
+//
+
+StreamState PseudoTcpChannel::GetState() const {
+  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  if (!tcp_)
+    return SS_OPENING;
+  switch (tcp_->State()) {
+    case PseudoTcp::TCP_LISTEN:
+    case PseudoTcp::TCP_SYN_SENT:
+    case PseudoTcp::TCP_SYN_RECEIVED:
+      return SS_OPENING;
+    case PseudoTcp::TCP_ESTABLISHED:
+      return SS_OPEN;
+    case PseudoTcp::TCP_CLOSED:
+    default:
+      return SS_CLOSED;
+  }
+}
+
+StreamResult PseudoTcpChannel::Read(void* buffer, size_t buffer_len,
+                                    size_t* read, int* error) {
+  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  if (!tcp_)
+    return SR_BLOCK;
+
+  stream_readable_ = false;
+  int result = tcp_->Recv(static_cast<char*>(buffer), buffer_len);
+  //LOG_F(LS_VERBOSE) << "Recv returned: " << result;
+  if (result > 0) {
+    if (read)
+      *read = result;
+    // PseudoTcp doesn't currently support repeated Readable signals.  Simulate
+    // them here.
+    stream_readable_ = true;
+    if (!pending_read_event_) {
+      pending_read_event_ = true;
+      stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_READ), true);
+    }
+    return SR_SUCCESS;
+  } else if (IsBlockingError(tcp_->GetError())) {
+    return SR_BLOCK;
+  } else {
+    if (error)
+      *error = tcp_->GetError();
+    return SR_ERROR;
+  }
+  AdjustClock();
+}
+
+StreamResult PseudoTcpChannel::Write(const void* data, size_t data_len,
+                                     size_t* written, int* error) {
+  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  if (!tcp_)
+    return SR_BLOCK;
+  int result = tcp_->Send(static_cast<const char*>(data), data_len);
+  //LOG_F(LS_VERBOSE) << "Send returned: " << result;
+  if (result > 0) {
+    if (written)
+      *written = result;
+    return SR_SUCCESS;
+  } else if (IsBlockingError(tcp_->GetError())) {
+    return SR_BLOCK;
+  } else {
+    if (error)
+      *error = tcp_->GetError();
+    return SR_ERROR;
+  }
+  AdjustClock();
+}
+
+void PseudoTcpChannel::Close() {
+  ASSERT(stream_ != NULL && stream_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  stream_ = NULL;
+  // Clear out any pending event notifications
+  stream_thread_->Clear(this, MSG_ST_EVENT);
+  if (tcp_) {
+    tcp_->Close(false);
+    AdjustClock();
+  } else {
+    CheckDestroy();
+  }
+}
+
+//
+// Worker thread methods
+//
+
+void PseudoTcpChannel::OnChannelWritableState(TransportChannel* channel) {
+  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
+  ASSERT(worker_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  if (!channel_) {
+    LOG_F(LS_WARNING) << "NULL channel";
+    return;
+  }
+  ASSERT(channel == channel_);
+  if (!tcp_) {
+    LOG_F(LS_WARNING) << "NULL tcp";
+    return;
+  }
+  if (!ready_to_connect_ || !channel->writable())
+    return;
+
+  ready_to_connect_ = false;
+  tcp_->Connect();
+  AdjustClock();
+}
+
+void PseudoTcpChannel::OnChannelRead(TransportChannel* channel,
+                                     const char* data, size_t size) {
+  //LOG_F(LS_VERBOSE) << "(" << size << ")";
+  ASSERT(worker_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  if (!channel_) {
+    LOG_F(LS_WARNING) << "NULL channel";
+    return;
+  }
+  ASSERT(channel == channel_);
+  if (!tcp_) {
+    LOG_F(LS_WARNING) << "NULL tcp";
+    return;
+  }
+  tcp_->NotifyPacket(data, size);
+  AdjustClock();
+}
+
+void PseudoTcpChannel::OnChannelConnectionChanged(TransportChannel* channel,
+                                                  const SocketAddress& addr) {
+  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
+  ASSERT(worker_thread_->IsCurrent());
+  CritScope lock(&cs_);
+  if (!channel_) {
+    LOG_F(LS_WARNING) << "NULL channel";
+    return;
+  }
+  ASSERT(channel == channel_);
+  if (!tcp_) {
+    LOG_F(LS_WARNING) << "NULL tcp";
+    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();
+  }
+}
+
+void PseudoTcpChannel::OnTcpOpen(PseudoTcp* tcp) {
+  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
+  ASSERT(cs_.CurrentThreadIsOwner());
+  ASSERT(worker_thread_->IsCurrent());
+  ASSERT(tcp == tcp_);
+  if (stream_) {
+    stream_readable_ = true;
+    pending_read_event_ = true;
+    stream_thread_->Post(this, MSG_ST_EVENT,
+                         new EventData(SE_OPEN | SE_READ | SE_WRITE));
+  }
+}
+
+void PseudoTcpChannel::OnTcpReadable(PseudoTcp* tcp) {
+  //LOG_F(LS_VERBOSE);
+  ASSERT(cs_.CurrentThreadIsOwner());
+  ASSERT(worker_thread_->IsCurrent());
+  ASSERT(tcp == tcp_);
+  if (stream_) {
+    stream_readable_ = true;
+    if (!pending_read_event_) {
+      pending_read_event_ = true;
+      stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_READ));
+    }
+  }
+}
+
+void PseudoTcpChannel::OnTcpWriteable(PseudoTcp* tcp) {
+  //LOG_F(LS_VERBOSE);
+  ASSERT(cs_.CurrentThreadIsOwner());
+  ASSERT(worker_thread_->IsCurrent());
+  ASSERT(tcp == tcp_);
+  if (stream_)
+    stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_WRITE));
+}
+
+void PseudoTcpChannel::OnTcpClosed(PseudoTcp* tcp, uint32 nError) {
+  LOG_F(LS_VERBOSE) << "[" << channel_name_ << "]";
+  ASSERT(cs_.CurrentThreadIsOwner());
+  ASSERT(worker_thread_->IsCurrent());
+  ASSERT(tcp == tcp_);
+  if (stream_)
+    stream_thread_->Post(this, MSG_ST_EVENT, new EventData(SE_CLOSE, nError));
+}
+
+//
+// Multi-thread methods
+//
+
+void PseudoTcpChannel::OnMessage(Message* pmsg) {
+  if (pmsg->message_id == MSG_WK_CLOCK) {
+
+    ASSERT(worker_thread_->IsCurrent());
+    //LOG(LS_INFO) << "PseudoTcpChannel::OnMessage(MSG_WK_CLOCK)";
+    CritScope lock(&cs_);
+    if (tcp_) {
+      tcp_->NotifyClock(PseudoTcp::Now());
+      AdjustClock(false);
+    }
+
+  } else if (pmsg->message_id == MSG_WK_PURGE) {
+
+    ASSERT(worker_thread_->IsCurrent());
+    LOG_F(LS_INFO) << "(MSG_WK_PURGE)";
+    // At this point, we know there are no additional worker thread messages.
+    CritScope lock(&cs_);
+    ASSERT(NULL == session_);
+    ASSERT(NULL == channel_);
+    worker_thread_ = NULL;
+    CheckDestroy();
+
+  } else if (pmsg->message_id == MSG_ST_EVENT) {
+
+    ASSERT(stream_thread_->IsCurrent());
+    //LOG(LS_INFO) << "PseudoTcpChannel::OnMessage(MSG_ST_EVENT, "
+    //             << data->event << ", " << data->error << ")";
+    ASSERT(stream_ != NULL);
+    EventData* data = static_cast<EventData*>(pmsg->pdata);
+    if (data->event & SE_READ) {
+      CritScope lock(&cs_);
+      pending_read_event_ = false;
+    }
+    stream_->SignalEvent(stream_, data->event, data->error);
+    delete data;
+
+  } else if (pmsg->message_id == MSG_SI_DESTROYCHANNEL) {
+
+    ASSERT(signal_thread_->IsCurrent());
+    LOG_F(LS_INFO) << "(MSG_SI_DESTROYCHANNEL)";
+    ASSERT(session_ != NULL);
+    ASSERT(channel_ != NULL);
+    session_->DestroyChannel(channel_);
+
+  } else if (pmsg->message_id == MSG_SI_DESTROY) {
+
+    ASSERT(signal_thread_->IsCurrent());
+    LOG_F(LS_INFO) << "(MSG_SI_DESTROY)";
+    // The message queue is empty, so it is safe to destroy ourselves.
+    delete this;
+
+  } else {
+    ASSERT(false);
+  }
+}
+
+IPseudoTcpNotify::WriteResult PseudoTcpChannel::TcpWritePacket(
+    PseudoTcp* tcp, const char* buffer, size_t len) {
+  ASSERT(cs_.CurrentThreadIsOwner());
+  ASSERT(tcp == tcp_);
+  ASSERT(NULL != channel_);
+  int sent = channel_->SendPacket(buffer, len);
+  if (sent > 0) {
+    //LOG_F(LS_VERBOSE) << "(" << sent << ") Sent";
+    return IPseudoTcpNotify::WR_SUCCESS;
+  } else if (IsBlockingError(channel_->GetError())) {
+    LOG_F(LS_VERBOSE) << "Blocking";
+    return IPseudoTcpNotify::WR_SUCCESS;
+  } else if (channel_->GetError() == EMSGSIZE) {
+    LOG_F(LS_ERROR) << "EMSGSIZE";
+    return IPseudoTcpNotify::WR_TOO_LARGE;
+  } else {
+    PLOG(LS_ERROR, channel_->GetError()) << "PseudoTcpChannel::TcpWritePacket";
+    ASSERT(false);
+    return IPseudoTcpNotify::WR_FAIL;
+  }
+}
+
+void PseudoTcpChannel::AdjustClock(bool clear) {
+  ASSERT(cs_.CurrentThreadIsOwner());
+  ASSERT(NULL != tcp_);
+
+  long timeout = 0;
+  if (tcp_->GetNextClock(PseudoTcp::Now(), timeout)) {
+    ASSERT(NULL != channel_);
+    // Reset the next clock, by clearing the old and setting a new one.
+    if (clear)
+      worker_thread_->Clear(this, MSG_WK_CLOCK);
+    worker_thread_->PostDelayed(_max(timeout, 0L), this, MSG_WK_CLOCK);
+    return;
+  }
+
+  delete tcp_;
+  tcp_ = NULL;
+  ready_to_connect_ = false;
+
+  if (channel_) {
+    // If TCP has failed, no need for channel_ anymore
+    signal_thread_->Post(this, MSG_SI_DESTROYCHANNEL);
+  }
+}
+
+void PseudoTcpChannel::CheckDestroy() {
+  ASSERT(cs_.CurrentThreadIsOwner());
+  if ((worker_thread_ != NULL) || (stream_ != NULL))
+    return;
+  signal_thread_->Post(this, MSG_SI_DESTROY);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PseudoTcpChannel::InternalStream
+///////////////////////////////////////////////////////////////////////////////
+
+PseudoTcpChannel::InternalStream::InternalStream(PseudoTcpChannel* parent)
+  : parent_(parent) {
+}
+
+PseudoTcpChannel::InternalStream::~InternalStream() {
+  Close();
+}
+
+StreamState PseudoTcpChannel::InternalStream::GetState() const {
+  if (!parent_)
+    return SS_CLOSED;
+  return parent_->GetState();
+}
+
+StreamResult PseudoTcpChannel::InternalStream::Read(
+    void* buffer, size_t buffer_len, size_t* read, int* error) {
+  if (!parent_) {
+    if (error)
+      *error = ENOTCONN;
+    return SR_ERROR;
+  }
+  return parent_->Read(buffer, buffer_len, read, error);
+}
+
+StreamResult PseudoTcpChannel::InternalStream::Write(
+    const void* data, size_t data_len,  size_t* written, int* error) {
+  if (!parent_) {
+    if (error)
+      *error = ENOTCONN;
+    return SR_ERROR;
+  }
+  return parent_->Write(data, data_len, written, error);
+}
+
+void PseudoTcpChannel::InternalStream::Close() {
+  if (!parent_)
+    return;
+  parent_->Close(); 
+  parent_ = NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace cricket
diff --git a/talk/session/tunnel/pseudotcpchannel.h b/talk/session/tunnel/pseudotcpchannel.h
new file mode 100755
index 0000000..27574ea
--- /dev/null
+++ b/talk/session/tunnel/pseudotcpchannel.h
@@ -0,0 +1,125 @@
+/*
+ * 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 __PSEUDOTCPCHANNEL_H__
+#define __PSEUDOTCPCHANNEL_H__
+
+#include "talk/base/criticalsection.h"
+#include "talk/base/messagequeue.h"
+#include "talk/base/stream.h"
+#include "talk/p2p/base/pseudotcp.h"
+#include "talk/p2p/base/session.h"
+
+namespace talk_base {
+class Thread;
+}
+
+namespace cricket {
+
+class TransportChannel;
+
+///////////////////////////////////////////////////////////////////////////////
+// ChannelStream
+// Note: The lifetime of TunnelSession is complicated.  It needs to survive
+// until the following three conditions are true:
+// 1) TunnelStream has called Close (tracked via non-null stream_)
+// 2) PseudoTcp has completed (tracked via non-null tcp_)
+// 3) Session has been destroyed (tracked via non-null session_)
+// This is accomplished by calling CheckDestroy after these indicators change.
+///////////////////////////////////////////////////////////////////////////////
+// TunnelStream
+// Note: Because TunnelStream provides a stream interface, it's 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.
+///////////////////////////////////////////////////////////////////////////////
+
+class PseudoTcpChannel
+  : public IPseudoTcpNotify,
+    public talk_base::MessageHandler,
+    public sigslot::has_slots<> {
+public:
+  // Signal thread methods
+  PseudoTcpChannel(talk_base::Thread* stream_thread,
+                   Session* session);
+
+  bool Connect(const std::string& channel_name);
+  talk_base::StreamInterface* GetStream();
+
+  sigslot::signal1<PseudoTcpChannel*> SignalChannelClosed;
+
+private:
+  class InternalStream;
+  friend class InternalStream;
+
+  virtual ~PseudoTcpChannel();
+
+  // Stream thread methods
+  talk_base::StreamState GetState() const;
+  talk_base::StreamResult Read(void* buffer, size_t buffer_len,
+                               size_t* read, int* error);
+  talk_base::StreamResult Write(const void* data, size_t data_len,
+                                size_t* written, int* error);
+  void Close();
+
+  // Multi-thread methods
+  void OnMessage(talk_base::Message* pmsg);
+  void AdjustClock(bool clear = true);
+  void CheckDestroy();
+
+  // Signal thread methods
+  void OnChannelDestroyed(TransportChannel* channel);
+
+  // Worker thread methods
+  void OnChannelWritableState(TransportChannel* channel);
+  void OnChannelRead(TransportChannel* channel, const char* data, size_t size);
+  void OnChannelConnectionChanged(TransportChannel* channel,
+                                  const talk_base::SocketAddress& addr);
+
+  virtual void OnTcpOpen(PseudoTcp* ptcp);
+  virtual void OnTcpReadable(PseudoTcp* ptcp);
+  virtual void OnTcpWriteable(PseudoTcp* ptcp);
+  virtual void OnTcpClosed(PseudoTcp* ptcp, uint32 nError);
+  virtual IPseudoTcpNotify::WriteResult TcpWritePacket(PseudoTcp* tcp,
+                                                       const char* buffer,
+                                                       size_t len);
+
+  talk_base::Thread* signal_thread_, * worker_thread_, * stream_thread_;
+  Session* session_;
+  TransportChannel* channel_;
+  std::string channel_name_;
+  PseudoTcp* tcp_;
+  InternalStream* stream_;
+  bool stream_readable_, pending_read_event_;
+  bool ready_to_connect_;
+  mutable talk_base::CriticalSection cs_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace cricket
+
+#endif // __PSEUDOTCPCHANNEL_H__
diff --git a/talk/session/tunnel/tunnelsessionclient.cc b/talk/session/tunnel/tunnelsessionclient.cc
new file mode 100755
index 0000000..855f0db
--- /dev/null
+++ b/talk/session/tunnel/tunnelsessionclient.cc
@@ -0,0 +1,316 @@
+/*
+ * 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/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/p2p/base/transportchannel.h"
+#include "talk/xmllite/xmlelement.h"
+#include "pseudotcpchannel.h"
+#include "tunnelsessionclient.h"
+
+namespace cricket {
+
+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");
+
+enum {
+  MSG_CLOCK = 1,
+  MSG_DESTROY,
+  MSG_TERMINATE,
+  MSG_EVENT,
+  MSG_CREATE_TUNNEL,
+};
+
+struct EventData : public talk_base::MessageData {
+  int event, error;
+  EventData(int ev, int err = 0) : event(ev), error(err) { }
+};
+
+struct CreateTunnelData : public talk_base::MessageData {
+  buzz::Jid jid;
+  std::string description;
+  talk_base::Thread* thread;
+  talk_base::StreamInterface* stream;
+};
+
+extern const talk_base::ConstantLabel SESSION_STATES[];
+
+const talk_base::ConstantLabel SESSION_STATES[] = {
+  KLABEL(Session::STATE_INIT),
+  KLABEL(Session::STATE_SENTINITIATE),
+  KLABEL(Session::STATE_RECEIVEDINITIATE),
+  KLABEL(Session::STATE_SENTACCEPT),
+  KLABEL(Session::STATE_RECEIVEDACCEPT),
+  KLABEL(Session::STATE_SENTMODIFY),
+  KLABEL(Session::STATE_RECEIVEDMODIFY),
+  KLABEL(Session::STATE_SENTREJECT),
+  KLABEL(Session::STATE_RECEIVEDREJECT),
+  KLABEL(Session::STATE_SENTREDIRECT),
+  KLABEL(Session::STATE_SENTTERMINATE),
+  KLABEL(Session::STATE_RECEIVEDTERMINATE),
+  KLABEL(Session::STATE_INPROGRESS),
+  KLABEL(Session::STATE_DEINIT),
+  LASTLABEL
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// TunnelSessionDescription
+///////////////////////////////////////////////////////////////////////////////
+
+struct TunnelSessionDescription : public SessionDescription {
+  std::string description;
+
+  TunnelSessionDescription(const std::string& desc) : description(desc) { }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// TunnelSessionClient
+///////////////////////////////////////////////////////////////////////////////
+
+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);
+}
+
+TunnelSessionClient::~TunnelSessionClient() {
+  shutdown_ = true;
+  for (std::vector<TunnelSession*>::iterator it = sessions_.begin();
+       it != sessions_.end();
+       ++it) {
+     Session* session = (*it)->ReleaseSession(true);
+     session_manager_->DestroySession(session);
+  }
+  session_manager_->RemoveClient(NS_TUNNEL);
+}
+
+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;
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  if (received)
+    sessions_.push_back(
+      new TunnelSession(this, session, talk_base::Thread::Current()));
+}
+
+void TunnelSessionClient::OnSessionDestroy(Session* session) {
+  LOG(LS_INFO) << "TunnelSessionClient::OnSessionDestroy";
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  if (shutdown_)
+    return;
+  for (std::vector<TunnelSession*>::iterator it = sessions_.begin();
+       it != sessions_.end();
+       ++it) {
+    if ((*it)->HasSession(session)) {
+      VERIFY((*it)->ReleaseSession(false) == session);
+      sessions_.erase(it);
+      return;
+    }
+  }
+}
+
+talk_base::StreamInterface* TunnelSessionClient::CreateTunnel(
+    const buzz::Jid& to, const std::string& description) {
+  // Valid from any thread
+  CreateTunnelData data;
+  data.jid = to;
+  data.description = description;
+  data.thread = talk_base::Thread::Current();
+  session_manager_->signaling_thread()->Send(this, MSG_CREATE_TUNNEL, &data);
+  return data.stream;
+}
+
+talk_base::StreamInterface* TunnelSessionClient::AcceptTunnel(
+    Session* session) {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  TunnelSession* tunnel = NULL;
+  for (std::vector<TunnelSession*>::iterator it = sessions_.begin();
+       it != sessions_.end();
+       ++it) {
+    if ((*it)->HasSession(session)) {
+      tunnel = *it;
+      break;
+    }
+  }
+  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);
+  return tunnel->GetStream();
+}
+
+void TunnelSessionClient::DeclineTunnel(Session* session) {
+  ASSERT(session_manager_->signaling_thread()->IsCurrent());
+  session->Reject();
+}
+
+void TunnelSessionClient::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);
+    sessions_.push_back(tunnel);
+    TunnelSessionDescription* desc = new TunnelSessionDescription(data->description);
+    session->Initiate(data->jid.Str(), NULL, desc);
+    data->stream = tunnel->GetStream();
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TunnelSession
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Signalling thread methods
+//
+
+TunnelSession::TunnelSession(TunnelSessionClient* client, Session* session,
+                             talk_base::Thread* stream_thread)
+    : client_(client), session_(session), channel_(NULL) {
+  ASSERT(client_ != NULL);
+  ASSERT(session_ != NULL);
+  session_->SignalState.connect(this, &TunnelSession::OnSessionState);
+  channel_ = new PseudoTcpChannel(stream_thread, session_);
+  channel_->SignalChannelClosed.connect(this, &TunnelSession::OnChannelClosed);
+}
+
+TunnelSession::~TunnelSession() {
+  ASSERT(client_ != NULL);
+  ASSERT(session_ == NULL);
+  ASSERT(channel_ == NULL);
+}
+
+talk_base::StreamInterface* TunnelSession::GetStream() {
+  ASSERT(channel_ != NULL);
+  return channel_->GetStream();
+}
+
+bool TunnelSession::HasSession(Session* session) {
+  ASSERT(NULL != session_);
+  return (session_ == session);
+}
+
+Session* TunnelSession::ReleaseSession(bool channel_exists) {
+  ASSERT(NULL != session_);
+  ASSERT(NULL != channel_);
+  Session* session = session_;
+  session_->SignalState.disconnect(this);
+  session_ = NULL;
+  if (channel_exists)
+    channel_->SignalChannelClosed.disconnect(this);
+  channel_ = NULL;
+  delete this;
+  return session;
+}
+
+void TunnelSession::OnSessionState(Session* session, Session::State state) {
+  LOG(LS_INFO) << "TunnelSession::OnSessionState("
+               << talk_base::nonnull(
+                    talk_base::FindLabel(state, SESSION_STATES), "Unknown")
+               << ")";
+  ASSERT(session == session_);
+
+  switch (state) {
+  case Session::STATE_RECEIVEDINITIATE:
+    OnInitiate();
+    break;
+  case Session::STATE_SENTACCEPT:
+  case Session::STATE_RECEIVEDACCEPT:
+    OnAccept();
+    break;
+  case Session::STATE_SENTTERMINATE:
+  case Session::STATE_RECEIVEDTERMINATE:
+    OnTerminate();
+    break;
+  case Session::STATE_DEINIT:
+    // ReleaseSession should have been called before this.
+    ASSERT(false);
+    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_);
+}
+
+void TunnelSession::OnAccept() {
+  ASSERT(channel_ != NULL);
+  VERIFY(channel_->Connect("tcp"));
+}
+
+void TunnelSession::OnTerminate() {
+}
+
+void TunnelSession::OnChannelClosed(PseudoTcpChannel* channel) {
+  ASSERT(channel_ == channel);
+  ASSERT(session_ != NULL);
+  session_->Terminate();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace cricket
diff --git a/talk/session/tunnel/tunnelsessionclient.h b/talk/session/tunnel/tunnelsessionclient.h
new file mode 100755
index 0000000..34c05bf
--- /dev/null
+++ b/talk/session/tunnel/tunnelsessionclient.h
@@ -0,0 +1,135 @@
+/*
+ * 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 __TUNNELSESSIONCLIENT_H__
+#define __TUNNELSESSIONCLIENT_H__
+
+#include <vector>
+#include "talk/base/criticalsection.h"
+#include "talk/base/stream.h"
+#include "talk/p2p/base/pseudotcp.h"
+#include "talk/p2p/base/session.h"
+#include "talk/p2p/base/sessiondescription.h"
+#include "talk/p2p/base/sessionmanager.h"
+#include "talk/p2p/base/sessionclient.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmpp/constants.h"
+
+namespace cricket {
+
+class TunnelSession;
+class TunnelStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// TunnelSessionClient
+///////////////////////////////////////////////////////////////////////////////
+
+class TunnelSessionClient
+  : public SessionClient, public talk_base::MessageHandler, 
+    public sigslot::has_slots<> {
+public:
+  TunnelSessionClient(const buzz::Jid& jid, SessionManager* manager);
+  virtual ~TunnelSessionClient();
+
+  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.
+  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:
+  void OnMessage(talk_base::Message* pmsg);
+
+  buzz::Jid jid_;
+  SessionManager* session_manager_;
+  std::vector<TunnelSession*> sessions_;
+  bool shutdown_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// TunnelSession
+// Note: The lifetime of TunnelSession is complicated.  It needs to survive
+// until the following three conditions are true:
+// 1) TunnelStream has called Close (tracked via non-null stream_)
+// 2) PseudoTcp has completed (tracked via non-null tcp_)
+// 3) Session has been destroyed (tracked via non-null session_)
+// This is accomplished by calling CheckDestroy after these indicators change.
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// TunnelStream
+// Note: Because TunnelStream provides a stream interface, it's 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.
+///////////////////////////////////////////////////////////////////////////////
+
+class PseudoTcpChannel;
+
+class TunnelSession : public sigslot::has_slots<> {
+public:
+  // Signalling thread methods
+  TunnelSession(TunnelSessionClient* client, Session* session,
+                talk_base::Thread* stream_thread);
+
+  talk_base::StreamInterface* GetStream();
+  bool HasSession(Session* session);
+  Session* ReleaseSession(bool channel_exists);
+
+private:
+  virtual ~TunnelSession();
+
+  void OnSessionState(Session* session, Session::State state);
+  void OnInitiate();
+  void OnAccept();
+  void OnTerminate();
+  void OnChannelClosed(PseudoTcpChannel* channel);
+
+  TunnelSessionClient* client_;
+  Session* session_;
+  PseudoTcpChannel* channel_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace cricket
+
+#endif // __TUNNELSESSIONCLIENT_H__
diff --git a/talk/third_party/Makefile.am b/talk/third_party/Makefile.am
new file mode 100755
index 0000000..e2d0b36
--- /dev/null
+++ b/talk/third_party/Makefile.am
@@ -0,0 +1,9 @@
+if PHONE
+
+if !GIPS
+SUBDIRS=mediastreamer
+else
+SUBDIRS=gips 
+endif
+
+endif
diff --git a/talk/third_party/Makefile.in b/talk/third_party/Makefile.in
new file mode 100644
index 0000000..4f59295
--- /dev/null
+++ b/talk/third_party/Makefile.in
@@ -0,0 +1,489 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/third_party
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-exec-recursive install-info-recursive \
+	install-recursive installcheck-recursive installdirs-recursive \
+	pdf-recursive ps-recursive uninstall-info-recursive \
+	uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = mediastreamer gips
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+@GIPS_FALSE@@PHONE_TRUE@SUBDIRS = mediastreamer
+@GIPS_TRUE@@PHONE_TRUE@SUBDIRS = gips 
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/third_party/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/third_party/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(mkdir_p) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
+	clean clean-generic clean-libtool clean-recursive ctags \
+	ctags-recursive distclean distclean-generic distclean-libtool \
+	distclean-recursive distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-exec install-exec-am install-info \
+	install-info-am install-man install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-recursive \
+	mostlyclean mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/third_party/gips/Makefile.am b/talk/third_party/gips/Makefile.am
new file mode 100755
index 0000000..f98dbb7
--- /dev/null
+++ b/talk/third_party/gips/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST=expiration.h
diff --git a/talk/third_party/gips/Makefile.in b/talk/third_party/gips/Makefile.in
new file mode 100644
index 0000000..2c54a2e
--- /dev/null
+++ b/talk/third_party/gips/Makefile.in
@@ -0,0 +1,331 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/third_party/gips
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+EXTRA_DIST = expiration.h
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/third_party/gips/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/third_party/gips/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	distclean distclean-generic distclean-libtool distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-man install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/third_party/gips/expiration.h b/talk/third_party/gips/expiration.h
new file mode 100755
index 0000000..8dc22d1
--- /dev/null
+++ b/talk/third_party/gips/expiration.h
@@ -0,0 +1,6 @@
+#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
new file mode 100755
index 0000000..9dcf686
--- /dev/null
+++ b/talk/third_party/mediastreamer/Makefile.am
@@ -0,0 +1,91 @@
+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/Makefile.in b/talk/third_party/mediastreamer/Makefile.in
new file mode 100644
index 0000000..379dcf9
--- /dev/null
+++ b/talk/third_party/mediastreamer/Makefile.in
@@ -0,0 +1,573 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/third_party/mediastreamer
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libmediastreamer_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+am_libmediastreamer_la_OBJECTS = msfilter.lo mscodec.lo mssoundread.lo \
+	mssoundwrite.lo msbuffer.lo msqueue.lo msfifo.lo ms.lo \
+	mssync.lo msnosync.lo msread.lo mswrite.lo mscopy.lo \
+	msosswrite.lo msossread.lo msringplayer.lo msrtprecv.lo \
+	msrtpsend.lo msAlawenc.lo msAlawdec.lo msMUlawenc.lo \
+	msMUlawdec.lo mstimer.lo msqdispatcher.lo msfdispatcher.lo \
+	sndcard.lo osscard.lo hpuxsndcard.lo alsacard.lo jackcard.lo \
+	audiostream.lo msspeexenc.lo msspeexdec.lo msilbcdec.lo \
+	msilbcenc.lo
+libmediastreamer_la_OBJECTS = $(am_libmediastreamer_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libmediastreamer_la_SOURCES)
+DIST_SOURCES = $(libmediastreamer_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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) 
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/third_party/mediastreamer/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/third_party/mediastreamer/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libmediastreamer.la: $(libmediastreamer_la_OBJECTS) $(libmediastreamer_la_DEPENDENCIES) 
+	$(LINK)  $(libmediastreamer_la_LDFLAGS) $(libmediastreamer_la_OBJECTS) $(libmediastreamer_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alsacard.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audiostream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hpuxsndcard.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jackcard.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ms.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msAlawdec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msAlawenc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msMUlawdec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msMUlawenc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msbuffer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mscodec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mscopy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msfdispatcher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msfifo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msfilter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msilbcdec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msilbcenc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msnosync.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msossread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msosswrite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msqdispatcher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msqueue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msringplayer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msrtprecv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msrtpsend.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mssoundread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mssoundwrite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msspeexdec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msspeexenc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mssync.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mstimer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mswrite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osscard.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sndcard.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/third_party/mediastreamer/affine.h b/talk/third_party/mediastreamer/affine.h
new file mode 100755
index 0000000..620fdc9
--- /dev/null
+++ b/talk/third_party/mediastreamer/affine.h
@@ -0,0 +1,43 @@
+/*
+ * 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
new file mode 100755
index 0000000..ebf2909
--- /dev/null
+++ b/talk/third_party/mediastreamer/alsacard.c
@@ -0,0 +1,640 @@
+/*
+  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
new file mode 100755
index 0000000..e96abc7
--- /dev/null
+++ b/talk/third_party/mediastreamer/alsacard.h
@@ -0,0 +1,49 @@
+/*
+  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
new file mode 100755
index 0000000..67a4485
--- /dev/null
+++ b/talk/third_party/mediastreamer/audiostream.c
@@ -0,0 +1,343 @@
+/*
+  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
new file mode 100755
index 0000000..3f5ad16
--- /dev/null
+++ b/talk/third_party/mediastreamer/g711common.h
@@ -0,0 +1,171 @@
+/*
+ *  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
new file mode 100755
index 0000000..8210e29
--- /dev/null
+++ b/talk/third_party/mediastreamer/hpuxsndcard.c
@@ -0,0 +1,301 @@
+/*
+  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
new file mode 100755
index 0000000..b929cce
--- /dev/null
+++ b/talk/third_party/mediastreamer/jackcard.c
@@ -0,0 +1,574 @@
+/*
+  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
new file mode 100755
index 0000000..33ec46d
--- /dev/null
+++ b/talk/third_party/mediastreamer/jackcard.h
@@ -0,0 +1,81 @@
+/*
+  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
new file mode 100755
index 0000000..3ccbab6
--- /dev/null
+++ b/talk/third_party/mediastreamer/mediastream.h
@@ -0,0 +1,130 @@
+/*
+  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
new file mode 100755
index 0000000..a4a57f8
--- /dev/null
+++ b/talk/third_party/mediastreamer/ms.c
@@ -0,0 +1,342 @@
+/*
+  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
new file mode 100755
index 0000000..51c69b9
--- /dev/null
+++ b/talk/third_party/mediastreamer/ms.h
@@ -0,0 +1,81 @@
+/*
+  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
new file mode 100755
index 0000000..70cc906
--- /dev/null
+++ b/talk/third_party/mediastreamer/msAlawdec.c
@@ -0,0 +1,132 @@
+ /*
+  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
new file mode 100755
index 0000000..7db4c75
--- /dev/null
+++ b/talk/third_party/mediastreamer/msAlawdec.h
@@ -0,0 +1,65 @@
+/*
+  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
new file mode 100755
index 0000000..fd1f9ab
--- /dev/null
+++ b/talk/third_party/mediastreamer/msAlawenc.c
@@ -0,0 +1,124 @@
+ /*
+  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
new file mode 100755
index 0000000..608a988
--- /dev/null
+++ b/talk/third_party/mediastreamer/msAlawenc.h
@@ -0,0 +1,64 @@
+/*
+  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
new file mode 100755
index 0000000..e73fb33
--- /dev/null
+++ b/talk/third_party/mediastreamer/msGSMdecoder.h
@@ -0,0 +1,64 @@
+/*
+  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
new file mode 100755
index 0000000..2deae38
--- /dev/null
+++ b/talk/third_party/mediastreamer/msGSMencoder.h
@@ -0,0 +1,61 @@
+/*
+  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
new file mode 100755
index 0000000..59d9dec
--- /dev/null
+++ b/talk/third_party/mediastreamer/msLPC10decoder.h
@@ -0,0 +1,64 @@
+/*
+  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
new file mode 100755
index 0000000..4db1643
--- /dev/null
+++ b/talk/third_party/mediastreamer/msLPC10encoder.h
@@ -0,0 +1,74 @@
+/*
+  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
new file mode 100755
index 0000000..500f238
--- /dev/null
+++ b/talk/third_party/mediastreamer/msMUlawdec.c
@@ -0,0 +1,130 @@
+ /*
+  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
new file mode 100755
index 0000000..c135d21
--- /dev/null
+++ b/talk/third_party/mediastreamer/msMUlawdec.h
@@ -0,0 +1,66 @@
+/*
+  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
new file mode 100755
index 0000000..2f740d8
--- /dev/null
+++ b/talk/third_party/mediastreamer/msMUlawenc.c
@@ -0,0 +1,99 @@
+ /*
+  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
new file mode 100755
index 0000000..52f7666
--- /dev/null
+++ b/talk/third_party/mediastreamer/msMUlawenc.h
@@ -0,0 +1,63 @@
+/*
+  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
new file mode 100755
index 0000000..e7c880b
--- /dev/null
+++ b/talk/third_party/mediastreamer/msavdecoder.h
@@ -0,0 +1,87 @@
+/*
+  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
new file mode 100755
index 0000000..6fe5cad
--- /dev/null
+++ b/talk/third_party/mediastreamer/msavencoder.h
@@ -0,0 +1,90 @@
+/*
+  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
new file mode 100755
index 0000000..4ca3c92
--- /dev/null
+++ b/talk/third_party/mediastreamer/msbuffer.c
@@ -0,0 +1,94 @@
+/*
+  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
new file mode 100755
index 0000000..f96b35a
--- /dev/null
+++ b/talk/third_party/mediastreamer/msbuffer.h
@@ -0,0 +1,75 @@
+/*
+  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
new file mode 100755
index 0000000..7677dbe
--- /dev/null
+++ b/talk/third_party/mediastreamer/mscodec.c
@@ -0,0 +1,250 @@
+/*
+  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
new file mode 100755
index 0000000..6c6847d
--- /dev/null
+++ b/talk/third_party/mediastreamer/mscodec.h
@@ -0,0 +1,67 @@
+/*
+  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
new file mode 100755
index 0000000..3040b2e
--- /dev/null
+++ b/talk/third_party/mediastreamer/mscopy.c
@@ -0,0 +1,96 @@
+/*
+  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
new file mode 100755
index 0000000..2b5749b
--- /dev/null
+++ b/talk/third_party/mediastreamer/mscopy.h
@@ -0,0 +1,61 @@
+/*
+  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
new file mode 100755
index 0000000..692bbb7
--- /dev/null
+++ b/talk/third_party/mediastreamer/msfdispatcher.c
@@ -0,0 +1,94 @@
+/*
+  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
new file mode 100755
index 0000000..b1b457d
--- /dev/null
+++ b/talk/third_party/mediastreamer/msfdispatcher.h
@@ -0,0 +1,61 @@
+/*
+  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
new file mode 100755
index 0000000..9897e08
--- /dev/null
+++ b/talk/third_party/mediastreamer/msfifo.c
@@ -0,0 +1,168 @@
+/*
+  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
new file mode 100755
index 0000000..fde1bec
--- /dev/null
+++ b/talk/third_party/mediastreamer/msfifo.h
@@ -0,0 +1,73 @@
+/*
+  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
new file mode 100755
index 0000000..c67e9f0
--- /dev/null
+++ b/talk/third_party/mediastreamer/msfilter.c
@@ -0,0 +1,537 @@
+/*
+  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
new file mode 100755
index 0000000..71ec81a
--- /dev/null
+++ b/talk/third_party/mediastreamer/msfilter.h
@@ -0,0 +1,201 @@
+/*
+  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
new file mode 100755
index 0000000..b2dfff9
--- /dev/null
+++ b/talk/third_party/mediastreamer/msilbcdec.c
@@ -0,0 +1,194 @@
+/*
+  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
new file mode 100755
index 0000000..c219aab
--- /dev/null
+++ b/talk/third_party/mediastreamer/msilbcdec.h
@@ -0,0 +1,72 @@
+/*
+  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
new file mode 100755
index 0000000..76d8b64
--- /dev/null
+++ b/talk/third_party/mediastreamer/msilbcenc.c
@@ -0,0 +1,244 @@
+/*
+  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
new file mode 100755
index 0000000..bd8f3bf
--- /dev/null
+++ b/talk/third_party/mediastreamer/msilbcenc.h
@@ -0,0 +1,84 @@
+/*
+  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
new file mode 100755
index 0000000..af5141c
--- /dev/null
+++ b/talk/third_party/mediastreamer/msnosync.c
@@ -0,0 +1,82 @@
+/*
+  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
new file mode 100755
index 0000000..eef52d4
--- /dev/null
+++ b/talk/third_party/mediastreamer/msnosync.h
@@ -0,0 +1,60 @@
+/*
+  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
new file mode 100755
index 0000000..2e7b032
--- /dev/null
+++ b/talk/third_party/mediastreamer/msossread.c
@@ -0,0 +1,148 @@
+/*
+  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
new file mode 100755
index 0000000..89d5a40
--- /dev/null
+++ b/talk/third_party/mediastreamer/msossread.h
@@ -0,0 +1,77 @@
+/*
+  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
new file mode 100755
index 0000000..13a0dfe
--- /dev/null
+++ b/talk/third_party/mediastreamer/msosswrite.c
@@ -0,0 +1,247 @@
+/*
+  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
new file mode 100755
index 0000000..d477534
--- /dev/null
+++ b/talk/third_party/mediastreamer/msosswrite.h
@@ -0,0 +1,78 @@
+/*
+  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
new file mode 100755
index 0000000..6bd073b
--- /dev/null
+++ b/talk/third_party/mediastreamer/msqdispatcher.c
@@ -0,0 +1,91 @@
+/*
+  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
new file mode 100755
index 0000000..3b0c566
--- /dev/null
+++ b/talk/third_party/mediastreamer/msqdispatcher.h
@@ -0,0 +1,60 @@
+/*
+  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
new file mode 100755
index 0000000..4636895
--- /dev/null
+++ b/talk/third_party/mediastreamer/msqueue.c
@@ -0,0 +1,56 @@
+/*
+  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
new file mode 100755
index 0000000..73ab8d8
--- /dev/null
+++ b/talk/third_party/mediastreamer/msqueue.h
@@ -0,0 +1,49 @@
+/*
+  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
new file mode 100755
index 0000000..6f0ec99
--- /dev/null
+++ b/talk/third_party/mediastreamer/msread.c
@@ -0,0 +1,182 @@
+/*
+  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
new file mode 100755
index 0000000..93177f3
--- /dev/null
+++ b/talk/third_party/mediastreamer/msread.h
@@ -0,0 +1,80 @@
+/*
+  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
new file mode 100755
index 0000000..fb2006e
--- /dev/null
+++ b/talk/third_party/mediastreamer/msringplayer.c
@@ -0,0 +1,246 @@
+/*
+  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
new file mode 100755
index 0000000..1f5e67d
--- /dev/null
+++ b/talk/third_party/mediastreamer/msringplayer.h
@@ -0,0 +1,81 @@
+/*
+  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
new file mode 100755
index 0000000..9b82e93
--- /dev/null
+++ b/talk/third_party/mediastreamer/msrtprecv.c
@@ -0,0 +1,163 @@
+/*
+  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
new file mode 100755
index 0000000..8c2c2ed
--- /dev/null
+++ b/talk/third_party/mediastreamer/msrtprecv.h
@@ -0,0 +1,80 @@
+/*
+  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
new file mode 100755
index 0000000..5e781ff
--- /dev/null
+++ b/talk/third_party/mediastreamer/msrtpsend.c
@@ -0,0 +1,211 @@
+/*
+  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
new file mode 100755
index 0000000..b70f4e5
--- /dev/null
+++ b/talk/third_party/mediastreamer/msrtpsend.h
@@ -0,0 +1,85 @@
+/*
+  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
new file mode 100755
index 0000000..fd6ec54
--- /dev/null
+++ b/talk/third_party/mediastreamer/mssdlout.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ *            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
new file mode 100755
index 0000000..3803b01
--- /dev/null
+++ b/talk/third_party/mediastreamer/mssoundread.c
@@ -0,0 +1,39 @@
+/*
+  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
new file mode 100755
index 0000000..7f2cab9
--- /dev/null
+++ b/talk/third_party/mediastreamer/mssoundread.h
@@ -0,0 +1,80 @@
+/*
+  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
new file mode 100755
index 0000000..9c5879f
--- /dev/null
+++ b/talk/third_party/mediastreamer/mssoundwrite.c
@@ -0,0 +1,39 @@
+/*
+  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
new file mode 100755
index 0000000..e6d7987
--- /dev/null
+++ b/talk/third_party/mediastreamer/mssoundwrite.h
@@ -0,0 +1,80 @@
+/*
+  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
new file mode 100755
index 0000000..f3fd4d2
--- /dev/null
+++ b/talk/third_party/mediastreamer/msspeexdec.c
@@ -0,0 +1,218 @@
+/*
+  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
new file mode 100755
index 0000000..d4e745f
--- /dev/null
+++ b/talk/third_party/mediastreamer/msspeexdec.h
@@ -0,0 +1,69 @@
+/*
+  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
new file mode 100755
index 0000000..abf976e
--- /dev/null
+++ b/talk/third_party/mediastreamer/msspeexenc.c
@@ -0,0 +1,192 @@
+/*
+  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
new file mode 100755
index 0000000..41655b9
--- /dev/null
+++ b/talk/third_party/mediastreamer/msspeexenc.h
@@ -0,0 +1,66 @@
+/*
+  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
new file mode 100755
index 0000000..9e32a8a
--- /dev/null
+++ b/talk/third_party/mediastreamer/mssync.c
@@ -0,0 +1,193 @@
+/*
+  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
new file mode 100755
index 0000000..012c068
--- /dev/null
+++ b/talk/third_party/mediastreamer/mssync.h
@@ -0,0 +1,136 @@
+/*
+  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
new file mode 100755
index 0000000..1955ef2
--- /dev/null
+++ b/talk/third_party/mediastreamer/mstimer.c
@@ -0,0 +1,114 @@
+ /*
+  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
new file mode 100755
index 0000000..5c7e8ed
--- /dev/null
+++ b/talk/third_party/mediastreamer/mstimer.h
@@ -0,0 +1,68 @@
+/*
+  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
new file mode 100755
index 0000000..6247743
--- /dev/null
+++ b/talk/third_party/mediastreamer/mstruespeechdecoder.h
@@ -0,0 +1,55 @@
+/*
+  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
new file mode 100755
index 0000000..04e40bb
--- /dev/null
+++ b/talk/third_party/mediastreamer/mstruespeechencoder.h
@@ -0,0 +1,62 @@
+/*
+  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
new file mode 100755
index 0000000..012b87d
--- /dev/null
+++ b/talk/third_party/mediastreamer/msutils.h
@@ -0,0 +1,61 @@
+/*
+  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
new file mode 100755
index 0000000..e19ac9e
--- /dev/null
+++ b/talk/third_party/mediastreamer/msv4l.h
@@ -0,0 +1,96 @@
+ /*
+  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
new file mode 100755
index 0000000..9a27f83
--- /dev/null
+++ b/talk/third_party/mediastreamer/msvideosource.h
@@ -0,0 +1,74 @@
+/*
+  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
new file mode 100755
index 0000000..178e294
--- /dev/null
+++ b/talk/third_party/mediastreamer/mswrite.c
@@ -0,0 +1,121 @@
+/*
+  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
new file mode 100755
index 0000000..cd766d1
--- /dev/null
+++ b/talk/third_party/mediastreamer/mswrite.h
@@ -0,0 +1,63 @@
+/*
+  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
new file mode 100755
index 0000000..636c579
--- /dev/null
+++ b/talk/third_party/mediastreamer/osscard.c
@@ -0,0 +1,495 @@
+/*
+  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
new file mode 100755
index 0000000..30b96c2
--- /dev/null
+++ b/talk/third_party/mediastreamer/osscard.h
@@ -0,0 +1,47 @@
+/*
+  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
new file mode 100755
index 0000000..ada3e6d
--- /dev/null
+++ b/talk/third_party/mediastreamer/sndcard.c
@@ -0,0 +1,204 @@
+/*
+  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
new file mode 100755
index 0000000..d84757f
--- /dev/null
+++ b/talk/third_party/mediastreamer/sndcard.h
@@ -0,0 +1,143 @@
+/*
+  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
new file mode 100755
index 0000000..6768d8f
--- /dev/null
+++ b/talk/third_party/mediastreamer/waveheader.h
@@ -0,0 +1,111 @@
+/*
+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
new file mode 100755
index 0000000..deaf2bf
--- /dev/null
+++ b/talk/xmllite/Makefile.am
@@ -0,0 +1,18 @@
+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/Makefile.in b/talk/xmllite/Makefile.in
new file mode 100644
index 0000000..a20b860
--- /dev/null
+++ b/talk/xmllite/Makefile.in
@@ -0,0 +1,467 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/xmllite
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketxmllite_la_LIBADD =
+am_libcricketxmllite_la_OBJECTS = qname.lo xmlbuilder.lo \
+	xmlconstants.lo xmlelement.lo xmlnsstack.lo xmlparser.lo \
+	xmlprinter.lo
+libcricketxmllite_la_OBJECTS = $(am_libcricketxmllite_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketxmllite_la_SOURCES)
+DIST_SOURCES = $(libcricketxmllite_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/xmllite/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/xmllite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketxmllite.la: $(libcricketxmllite_la_OBJECTS) $(libcricketxmllite_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketxmllite_la_LDFLAGS) $(libcricketxmllite_la_OBJECTS) $(libcricketxmllite_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qname.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlbuilder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlconstants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlelement.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlnsstack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlparser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlprinter.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/xmllite/qname.cc b/talk/xmllite/qname.cc
new file mode 100755
index 0000000..626cfa9
--- /dev/null
+++ b/talk/xmllite/qname.cc
@@ -0,0 +1,167 @@
+/*
+ * 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 <string>
+#include "talk/base/common.h"
+#include "talk/xmllite/xmlelement.h"
+#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;
+  while (*local) {
+    result *= 19;
+    result += *local;
+    local += 1;
+  }
+  return result;
+}
+
+static const int bits = 9;
+static QName::Data * get_qname_table() {
+  static QName::Data qname_table[1 << bits];
+  return qname_table;
+}
+
+static QName::Data *
+AllocateOrFind(const std::string & ns, const char * local) {
+  int index = QName_Hash(ns, local);
+  int increment = index >> (bits - 1) | 1;
+  QName::Data * qname_table = get_qname_table();
+  for (;;) {
+    index &= ((1 << bits) - 1);
+    if (!qname_table[index].Occupied()) {
+      return new QName::Data(ns, local);
+    }
+    if (qname_table[index].localPart_ == local &&
+        qname_table[index].namespace_ == ns) {
+      qname_table[index].AddRef();
+      return qname_table + index;
+    }
+    index += increment;
+  }
+}
+
+static QName::Data *
+Add(const std::string & ns, const char * local) {
+  int index = QName_Hash(ns, local);
+  int increment = index >> (bits - 1) | 1;
+  QName::Data * qname_table = get_qname_table();
+  for (;;) {
+    index &= ((1 << bits) - 1);
+    if (!qname_table[index].Occupied()) {
+      qname_table[index].namespace_ = ns;
+      qname_table[index].localPart_ = local;
+      qname_table[index].AddRef(); // AddRef twice so it's never deleted
+      qname_table[index].AddRef();
+      return qname_table + index;
+    }
+    if (qname_table[index].localPart_ == local &&
+        qname_table[index].namespace_ == ns) {
+      qname_table[index].AddRef();
+      return qname_table + index;
+    }
+    index += increment;
+  }
+}
+
+QName::~QName() {
+  data_->Release();
+}
+
+QName::QName() : data_(QN_EMPTY.data_) {
+  data_->AddRef();
+}
+
+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)) {}
+
+static std::string
+QName_LocalPart(const std::string & name) {
+  size_t i = name.rfind(':');
+  if (i == std::string::npos)
+    return name;
+  return name.substr(i + 1);
+}
+
+static std::string
+QName_Namespace(const std::string & name) {
+  size_t i = name.rfind(':');
+  if (i == std::string::npos)
+    return STR_EMPTY;
+  return name.substr(0, i);
+}
+
+QName::QName(const std::string & mergedOrLocal) :
+  data_(AllocateOrFind(QName_Namespace(mergedOrLocal),
+                 QName_LocalPart(mergedOrLocal).c_str())) {}
+
+std::string
+QName::Merged() const {
+  if (data_->namespace_ == STR_EMPTY)
+    return data_->localPart_;
+
+  std::string result(data_->namespace_);
+  result.reserve(result.length() + 1 + data_->localPart_.length());
+  result += ':';
+  result += data_->localPart_;
+  return result;
+}
+
+bool
+QName::operator==(const QName & other) const {
+  return other.data_ == data_ ||
+    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;
+
+  return data_->namespace_.compare(other.data_->namespace_);
+}
+
+}
+
+
+
diff --git a/talk/xmllite/qname.h b/talk/xmllite/qname.h
new file mode 100755
index 0000000..b1bcec6
--- /dev/null
+++ b/talk/xmllite/qname.h
@@ -0,0 +1,87 @@
+/*
+ * 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 _qname_h_
+#define _qname_h_
+
+#include <string>
+
+namespace buzz {
+
+
+class QName
+{
+public:
+  explicit QName();
+  QName(const QName & qname) : data_(qname.data_) { data_->AddRef(); }
+  explicit QName(bool add, const std::string & ns, const char * local);
+  explicit QName(bool add, const std::string & ns, const std::string & local);
+  explicit QName(const std::string & ns, const char * local);
+  explicit QName(const std::string & mergedOrLocal);
+  QName & operator=(const QName & qn) {
+    qn.data_->AddRef();
+    data_->Release();
+    data_ = qn.data_;
+    return *this;
+  }
+  ~QName();
+  
+  const std::string & Namespace() const { return data_->namespace_; }
+  const std::string & LocalPart() const { return data_->localPart_; }
+  std::string Merged() const;
+  int Compare(const QName & other) const;
+  bool operator==(const QName & other) const;
+  bool operator!=(const QName & other) const { return !operator==(other); }
+  bool operator<(const QName & other) const { return Compare(other) < 0; }
+  
+  class Data {
+  public:
+    Data(const std::string & ns, const std::string & local) :
+      refcount_(1),
+      namespace_(ns),
+      localPart_(local) {}
+
+    Data() : refcount_(0) {}
+      
+    std::string namespace_;
+    std::string localPart_;
+    void AddRef() { refcount_++; }
+    void Release() { if (!--refcount_) { delete this; } }
+    bool Occupied() { return !!refcount_; }
+
+  private:
+    int refcount_;
+  };
+
+private:
+  Data * data_;
+};
+
+
+}
+
+#endif
diff --git a/talk/xmllite/xmlbuilder.cc b/talk/xmllite/xmlbuilder.cc
new file mode 100755
index 0000000..3e2964f
--- /dev/null
+++ b/talk/xmllite/xmlbuilder.cc
@@ -0,0 +1,149 @@
+/*
+ * 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/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"
+
+namespace buzz {
+
+XmlBuilder::XmlBuilder() :
+  pelCurrent_(NULL),
+  pelRoot_(NULL),
+  pvParents_(new std::vector<XmlElement *>()) {
+}
+
+void
+XmlBuilder::Reset() {
+  pelRoot_.reset();
+  pelCurrent_ = NULL;
+  pvParents_->clear();
+}
+
+XmlElement *
+XmlBuilder::BuildElement(XmlParseContext * pctx,
+                              const char * name, const char ** atts) {
+  QName tagName(pctx->ResolveQName(name, false));
+  if (tagName == QN_EMPTY)
+    return NULL;
+
+  XmlElement * pelNew = new XmlElement(tagName);
+
+  if (!*atts)
+    return pelNew;
+
+  std::set<QName> seenNonlocalAtts;
+
+  while (*atts) {
+    QName attName(pctx->ResolveQName(*atts, true));
+    if (attName == QN_EMPTY) {
+      delete pelNew;
+      return NULL;
+    }
+
+    // verify that namespaced names are unique
+    if (!attName.Namespace().empty()) {
+      if (seenNonlocalAtts.count(attName)) {
+        delete pelNew;
+        return NULL;
+      }
+      seenNonlocalAtts.insert(attName);
+    }
+
+    pelNew->AddAttr(attName, std::string(*(atts + 1)));
+    atts += 2;
+  }
+
+  return pelNew;
+}
+
+void
+XmlBuilder::StartElement(XmlParseContext * pctx,
+                              const char * name, const char ** atts) {
+  XmlElement * pelNew = BuildElement(pctx, name, atts);
+  if (pelNew == NULL) {
+    pctx->RaiseError(XML_ERROR_SYNTAX);
+    return;
+  }
+
+  if (!pelCurrent_) {
+    pelCurrent_ = pelNew;
+    pelRoot_.reset(pelNew);
+    pvParents_->push_back(NULL);
+  } else {
+    pelCurrent_->AddElement(pelNew);
+    pvParents_->push_back(pelCurrent_);
+    pelCurrent_ = pelNew;
+  }
+}
+
+void
+XmlBuilder::EndElement(XmlParseContext * pctx, const char * name) {
+  UNUSED(pctx);
+  UNUSED(name);
+  pelCurrent_ = pvParents_->back();
+  pvParents_->pop_back();
+}
+
+void
+XmlBuilder::CharacterData(XmlParseContext * pctx,
+                               const char * text, int len) {
+  UNUSED(pctx);
+  if (pelCurrent_) {
+    pelCurrent_->AddParsedText(text, len);
+  }
+}
+
+void
+XmlBuilder::Error(XmlParseContext * pctx, XML_Error err) {
+  UNUSED(pctx);
+  UNUSED(err);
+  pelRoot_.reset(NULL);
+  pelCurrent_ = NULL;
+  pvParents_->clear();
+}
+
+XmlElement *
+XmlBuilder::CreateElement() {
+  return pelRoot_.release();
+}
+
+XmlElement *
+XmlBuilder::BuiltElement() {
+  return pelRoot_.get();
+}
+
+XmlBuilder::~XmlBuilder() {
+}
+
+
+
+}
diff --git a/talk/xmllite/xmlbuilder.h b/talk/xmllite/xmlbuilder.h
new file mode 100755
index 0000000..5de31b2
--- /dev/null
+++ b/talk/xmllite/xmlbuilder.h
@@ -0,0 +1,75 @@
+/*
+ * 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 _xmlbuilder_h_
+#define _xmlbuilder_h_
+
+#include <string>
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/stl_decl.h"
+#include "talk/xmllite/xmlparser.h"
+
+#include <expat.h>
+
+namespace buzz {
+
+class XmlElement;
+class XmlParseContext;
+
+
+class XmlBuilder : public XmlParseHandler {
+public:
+  XmlBuilder();
+
+  static XmlElement * BuildElement(XmlParseContext * pctx,
+                                  const char * name, const char ** atts);
+  virtual void StartElement(XmlParseContext * pctx,
+                            const char * name, const char ** atts);
+  virtual void EndElement(XmlParseContext * pctx, const char * name);
+  virtual void CharacterData(XmlParseContext * pctx,
+                             const char * text, int len);
+  virtual void Error(XmlParseContext * pctx, XML_Error);
+  virtual ~XmlBuilder();
+
+  void Reset();
+
+  // Take ownership of the built element; second call returns NULL
+  XmlElement * CreateElement();
+
+  // Peek at the built element without taking ownership
+  XmlElement * BuiltElement();
+
+private:
+  XmlElement * pelCurrent_;
+  scoped_ptr<XmlElement> pelRoot_;
+  scoped_ptr<std::vector<XmlElement *, std::allocator<XmlElement *> > >
+    pvParents_;
+};
+
+}
+
+#endif
diff --git a/talk/xmllite/xmlconstants.cc b/talk/xmllite/xmlconstants.cc
new file mode 100755
index 0000000..503f832
--- /dev/null
+++ b/talk/xmllite/xmlconstants.cc
@@ -0,0 +1,65 @@
+/*
+ * 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 "xmlconstants.h"
+
+using namespace buzz;
+
+const std::string & XmlConstants::str_empty() {
+  static const std::string str_empty_;
+  return str_empty_;
+}
+
+const std::string & XmlConstants::ns_xml() {
+  static const std::string ns_xml_("http://www.w3.org/XML/1998/namespace");
+  return ns_xml_;
+}
+
+const std::string & XmlConstants::ns_xmlns() {
+  static const std::string ns_xmlns_("http://www.w3.org/2000/xmlns/");
+  return ns_xmlns_;
+}
+
+const std::string & XmlConstants::str_xmlns() {
+  static const std::string str_xmlns_("xmlns");
+  return str_xmlns_;
+}
+
+const std::string & XmlConstants::str_xml() {
+  static const std::string str_xml_("xml");
+  return str_xml_;
+}
+
+const std::string & XmlConstants::str_version() {
+  static const std::string str_version_("version");
+  return str_version_;
+}
+
+const std::string & XmlConstants::str_encoding() {
+  static const std::string str_encoding_("encoding");
+  return str_encoding_;
+}
diff --git a/talk/xmllite/xmlconstants.h b/talk/xmllite/xmlconstants.h
new file mode 100755
index 0000000..8514d6f
--- /dev/null
+++ b/talk/xmllite/xmlconstants.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+// Because global constant initialization order is undefined
+// globals cannot depend on other objects to be instantiated.
+// This class creates string objects within static methods 
+// such that globals may refer to these constants by the
+// accessor function and they are guaranteed to be initialized.
+
+#ifndef TALK_XMLLITE_CONSTANTS_H_
+#define TALK_XMLLITE_CONSTANTS_H_
+
+#include <string>
+
+#define STR_EMPTY    XmlConstants::str_empty()
+#define NS_XML       XmlConstants::ns_xml()
+#define NS_XMLNS     XmlConstants::ns_xmlns()
+#define STR_XMLNS    XmlConstants::str_xmlns()
+#define STR_XML      XmlConstants::str_xml()
+#define STR_VERSION  XmlConstants::str_version()
+#define STR_ENCODING XmlConstants::str_encoding()
+namespace buzz {
+	
+class XmlConstants {
+ public:
+  static const std::string & str_empty();
+  static const std::string & ns_xml();
+  static const std::string & ns_xmlns();
+  static const std::string & str_xmlns();
+  static const std::string & str_xml();
+  static const std::string & str_version();
+  static const std::string & str_encoding();
+};
+
+}
+
+#endif  // TALK_XMLLITE_CONSTANTS_H_
diff --git a/talk/xmllite/xmlelement.cc b/talk/xmllite/xmlelement.cc
new file mode 100755
index 0000000..a4be297
--- /dev/null
+++ b/talk/xmllite/xmlelement.cc
@@ -0,0 +1,499 @@
+/*
+ * 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 <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+
+#include "talk/base/common.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmllite/xmlparser.h"
+#include "talk/xmllite/xmlbuilder.h"
+#include "talk/xmllite/xmlprinter.h"
+#include "talk/xmllite/xmlconstants.h"
+
+namespace buzz {
+
+const QName QN_EMPTY(true, STR_EMPTY, STR_EMPTY);
+const QName QN_XMLNS(true, STR_EMPTY, STR_XMLNS);
+
+
+XmlChild::~XmlChild() {
+}
+
+bool
+XmlText::IsTextImpl() const {
+  return true;
+}
+
+XmlElement *
+XmlText::AsElementImpl() const {
+  return NULL;
+}
+
+XmlText *
+XmlText::AsTextImpl() const {
+  return const_cast<XmlText *>(this);
+}
+
+void
+XmlText::SetText(const std::string & text) {
+  text_ = text;
+}
+
+void
+XmlText::AddParsedText(const char * buf, int len) {
+  text_.append(buf, len);
+}
+
+void
+XmlText::AddText(const std::string & text) {
+  text_ += text;
+}
+
+XmlText::~XmlText() {
+}
+
+XmlElement::XmlElement(const QName & name) :
+    name_(name),
+    pFirstAttr_(NULL),
+    pLastAttr_(NULL),
+    pFirstChild_(NULL),
+    pLastChild_(NULL) {
+}
+
+XmlElement::XmlElement(const XmlElement & elt) :
+    XmlChild(),
+    name_(elt.name_),
+    pFirstAttr_(NULL),
+    pLastAttr_(NULL),
+    pFirstChild_(NULL),
+    pLastChild_(NULL) {
+
+  // copy attributes
+  XmlAttr * pAttr;
+  XmlAttr ** ppLastAttr = &pFirstAttr_;
+  XmlAttr * newAttr = NULL;
+  for (pAttr = elt.pFirstAttr_; pAttr; pAttr = pAttr->NextAttr()) {
+    newAttr = new XmlAttr(*pAttr);
+    *ppLastAttr = newAttr;
+    ppLastAttr = &(newAttr->pNextAttr_);
+  }
+  pLastAttr_ = newAttr;
+
+  // copy children
+  XmlChild * pChild;
+  XmlChild ** ppLast = &pFirstChild_;
+  XmlChild * newChild = NULL;
+
+  for (pChild = elt.pFirstChild_; pChild; pChild = pChild->NextChild()) {
+    if (pChild->IsText()) {
+      newChild = new XmlText(*(pChild->AsText()));
+    } else {
+      newChild = new XmlElement(*(pChild->AsElement()));
+    }
+    *ppLast = newChild;
+    ppLast = &(newChild->pNextChild_);
+  }
+  pLastChild_ = newChild;
+
+}
+
+XmlElement::XmlElement(const QName & name, bool useDefaultNs) :
+  name_(name),
+  pFirstAttr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
+  pLastAttr_(pFirstAttr_),
+  pFirstChild_(NULL),
+  pLastChild_(NULL) {
+}
+
+bool
+XmlElement::IsTextImpl() const {
+  return false;
+}
+
+XmlElement *
+XmlElement::AsElementImpl() const {
+  return const_cast<XmlElement *>(this);
+}
+
+XmlText *
+XmlElement::AsTextImpl() const {
+  return NULL;
+}
+
+const std::string &
+XmlElement::BodyText() const {
+  if (pFirstChild_ && pFirstChild_->IsText() && pLastChild_ == pFirstChild_) {
+    return pFirstChild_->AsText()->Text();
+  }
+
+  return STR_EMPTY;
+}
+
+void
+XmlElement::SetBodyText(const std::string & text) {
+  if (text == STR_EMPTY) {
+    ClearChildren();
+  } else if (pFirstChild_ == NULL) {
+    AddText(text);
+  } else if (pFirstChild_->IsText() && pLastChild_ == pFirstChild_) {
+    pFirstChild_->AsText()->SetText(text);
+  } else {
+    ClearChildren();
+    AddText(text);
+  }
+}
+
+const QName &
+XmlElement::FirstElementName() const {
+  const XmlElement * element = FirstElement();
+  if (element == NULL)
+    return QN_EMPTY;
+  return element->Name();
+}
+
+XmlAttr *
+XmlElement::FirstAttr() {
+  return pFirstAttr_;
+}
+
+const std::string &
+XmlElement::Attr(const QName & name) const {
+  XmlAttr * pattr;
+  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
+    if (pattr->name_ == name)
+      return pattr->value_;
+  }
+  return STR_EMPTY;
+}
+
+bool
+XmlElement::HasAttr(const QName & name) const {
+  XmlAttr * pattr;
+  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
+    if (pattr->name_ == name)
+      return true;
+  }
+  return false;
+}
+
+void
+XmlElement::SetAttr(const QName & name, const std::string & value) {
+  XmlAttr * pattr;
+  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
+    if (pattr->name_ == name)
+      break;
+  }
+  if (!pattr) {
+    pattr = new XmlAttr(name, value);
+    if (pLastAttr_)
+      pLastAttr_->pNextAttr_ = pattr;
+    else
+      pFirstAttr_ = pattr;
+    pLastAttr_ = pattr;
+    return;
+  }
+  pattr->value_ = value;
+}
+
+void
+XmlElement::ClearAttr(const QName & name) {
+  XmlAttr * pattr;
+  XmlAttr *pLastAttr = NULL;
+  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
+    if (pattr->name_ == name)
+      break;
+    pLastAttr = pattr;
+  }
+  if (!pattr)
+    return;
+  if (!pLastAttr)
+    pFirstAttr_ = pattr->pNextAttr_;
+  else
+    pLastAttr->pNextAttr_ = pattr->pNextAttr_;
+  if (pLastAttr_ == pattr)
+    pLastAttr_ = pLastAttr;
+  delete pattr;
+}
+
+XmlChild *
+XmlElement::FirstChild() {
+  return pFirstChild_;
+}
+
+XmlElement *
+XmlElement::FirstElement() {
+  XmlChild * pChild;
+  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
+    if (!pChild->IsText())
+      return pChild->AsElement();
+  }
+  return NULL;
+}
+
+XmlElement *
+XmlElement::NextElement() {
+  XmlChild * pChild;
+  for (pChild = pNextChild_; pChild; pChild = pChild->pNextChild_) {
+    if (!pChild->IsText())
+      return pChild->AsElement();
+  }
+  return NULL;
+}
+
+XmlElement *
+XmlElement::FirstWithNamespace(const std::string & ns) {
+  XmlChild * pChild;
+  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
+    if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
+      return pChild->AsElement();
+  }
+  return NULL;
+}
+
+XmlElement *
+XmlElement::NextWithNamespace(const std::string & ns) {
+  XmlChild * pChild;
+  for (pChild = pNextChild_; pChild; pChild = pChild->pNextChild_) {
+    if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
+      return pChild->AsElement();
+  }
+  return NULL;
+}
+
+XmlElement *
+XmlElement::FirstNamed(const QName & name) {
+  XmlChild * pChild;
+  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
+    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
+      return pChild->AsElement();
+  }
+  return NULL;
+}
+
+XmlElement *
+XmlElement::NextNamed(const QName & name) {
+  XmlChild * pChild;
+  for (pChild = pNextChild_; pChild; pChild = pChild->pNextChild_) {
+    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
+      return pChild->AsElement();
+  }
+  return NULL;
+}
+
+XmlElement* XmlElement::FindOrAddNamedChild(const QName& name) {
+  XmlElement* child = FirstNamed(name);
+  if (!child) {
+    child = new XmlElement(name);
+    AddElement(child);
+  }
+
+  return child;
+}
+
+const std::string &
+XmlElement::TextNamed(const QName & name) const {
+  XmlChild * pChild;
+  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
+    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
+      return pChild->AsElement()->BodyText();
+  }
+  return STR_EMPTY;
+}
+
+void
+XmlElement::InsertChildAfter(XmlChild * pPredecessor, XmlChild * pNext) {
+  if (pPredecessor == NULL) {
+    pNext->pNextChild_ = pFirstChild_;
+    pFirstChild_ = pNext;
+  }
+  else {
+    pNext->pNextChild_ = pPredecessor->pNextChild_;
+    pPredecessor->pNextChild_ = pNext;
+  }
+}
+
+void
+XmlElement::RemoveChildAfter(XmlChild * pPredecessor) {
+  XmlChild * pNext;
+
+  if (pPredecessor == NULL) {
+    pNext = pFirstChild_;
+    pFirstChild_ = pNext->pNextChild_;
+  }
+  else {
+    pNext = pPredecessor->pNextChild_;
+    pPredecessor->pNextChild_ = pNext->pNextChild_;
+  }
+
+  if (pLastChild_ == pNext)
+    pLastChild_ = pPredecessor;
+
+  delete pNext;
+}
+
+void
+XmlElement::AddAttr(const QName & name, const std::string & value) {
+  ASSERT(!HasAttr(name));
+
+  XmlAttr ** pprev = pLastAttr_ ? &(pLastAttr_->pNextAttr_) : &pFirstAttr_;
+  pLastAttr_ = (*pprev = new XmlAttr(name, value));
+}
+
+void
+XmlElement::AddAttr(const QName & name, const std::string & value,
+                         int depth) {
+  XmlElement * element = this;
+  while (depth--) {
+    element = element->pLastChild_->AsElement();
+  }
+  element->AddAttr(name, value);
+}
+
+void
+XmlElement::AddParsedText(const char * cstr, int len) {
+  if (len == 0)
+    return;
+
+  if (pLastChild_ && pLastChild_->IsText()) {
+    pLastChild_->AsText()->AddParsedText(cstr, len);
+    return;
+  }
+  XmlChild ** pprev = pLastChild_ ? &(pLastChild_->pNextChild_) : &pFirstChild_;
+  pLastChild_ = *pprev = new XmlText(cstr, len);
+}
+
+void
+XmlElement::AddText(const std::string & text) {
+  if (text == STR_EMPTY)
+    return;
+
+  if (pLastChild_ && pLastChild_->IsText()) {
+    pLastChild_->AsText()->AddText(text);
+    return;
+  }
+  XmlChild ** pprev = pLastChild_ ? &(pLastChild_->pNextChild_) : &pFirstChild_;
+  pLastChild_ = *pprev = new XmlText(text);
+}
+
+void
+XmlElement::AddText(const std::string & text, int depth) {
+  // note: the first syntax is ambigious for msvc 6
+  // XmlElement * pel(this);
+  XmlElement * element = this;
+  while (depth--) {
+    element = element->pLastChild_->AsElement();
+  }
+  element->AddText(text);
+}
+
+void
+XmlElement::AddElement(XmlElement *pelChild) {
+  if (pelChild == NULL)
+    return;
+
+  XmlChild ** pprev = pLastChild_ ? &(pLastChild_->pNextChild_) : &pFirstChild_;
+  pLastChild_ = *pprev = pelChild;
+  pelChild->pNextChild_ = NULL;
+}
+
+void
+XmlElement::AddElement(XmlElement *pelChild, int depth) {
+  XmlElement * element = this;
+  while (depth--) {
+    element = element->pLastChild_->AsElement();
+  }
+  element->AddElement(pelChild);
+}
+
+void
+XmlElement::ClearNamedChildren(const QName & name) {
+  XmlChild * prev_child = NULL;
+  XmlChild * next_child;
+  XmlChild * child;
+  for (child = FirstChild(); child; child = next_child) {
+    next_child = child->NextChild();
+    if (!child->IsText() && child->AsElement()->Name() == name)
+    {
+      RemoveChildAfter(prev_child);
+      continue;
+    }
+    prev_child = child;
+  }
+}
+
+void
+XmlElement::ClearChildren() {
+  XmlChild * pchild;
+  for (pchild = pFirstChild_; pchild; ) {
+    XmlChild * pToDelete = pchild;
+    pchild = pchild->pNextChild_;
+    delete pToDelete;
+  }
+  pFirstChild_ = pLastChild_ = NULL;
+}
+
+std::string
+XmlElement::Str() const {
+  std::stringstream ss;
+  Print(&ss, NULL, 0);
+  return ss.str();
+}
+
+XmlElement *
+XmlElement::ForStr(const std::string & str) {
+  XmlBuilder builder;
+  XmlParser::ParseXml(&builder, str);
+  return builder.CreateElement();
+}
+
+void
+XmlElement::Print(
+    std::ostream * pout, std::string xmlns[], int xmlnsCount) const {
+  XmlPrinter::PrintXml(pout, this, xmlns, xmlnsCount);
+}
+
+XmlElement::~XmlElement() {
+  XmlAttr * pattr;
+  for (pattr = pFirstAttr_; pattr; ) {
+    XmlAttr * pToDelete = pattr;
+    pattr = pattr->pNextAttr_;
+    delete pToDelete;
+  }
+
+  XmlChild * pchild;
+  for (pchild = pFirstChild_; pchild; ) {
+    XmlChild * pToDelete = pchild;
+    pchild = pchild->pNextChild_;
+    delete pToDelete;
+  }
+}
+
+}
diff --git a/talk/xmllite/xmlelement.h b/talk/xmllite/xmlelement.h
new file mode 100755
index 0000000..7419c03
--- /dev/null
+++ b/talk/xmllite/xmlelement.h
@@ -0,0 +1,232 @@
+/*
+ * 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 _xmlelement_h_
+#define _xmlelement_h_
+
+#include <iosfwd>
+#include <string>
+#include "talk/base/scoped_ptr.h"
+#include "talk/xmllite/qname.h"
+
+namespace buzz {
+
+extern const QName QN_EMPTY;
+extern const QName QN_XMLNS;
+
+
+class XmlChild;
+class XmlText;
+class XmlElement;
+class XmlAttr;
+
+class XmlChild {
+friend class XmlElement;
+
+public:
+
+  XmlChild * NextChild() { return pNextChild_; }
+  const XmlChild * NextChild() const { return pNextChild_; }
+
+  bool IsText() const { return IsTextImpl(); }
+
+  XmlElement * AsElement() { return AsElementImpl(); }
+  const XmlElement * AsElement() const { return AsElementImpl(); }
+
+  XmlText * AsText() { return AsTextImpl(); }
+  const XmlText * AsText() const { return AsTextImpl(); }
+
+
+protected:
+
+  XmlChild() :
+    pNextChild_(NULL) {
+  }
+
+  virtual bool IsTextImpl() const = 0;
+  virtual XmlElement * AsElementImpl() const = 0;
+  virtual XmlText * AsTextImpl() const = 0;
+
+
+  virtual ~XmlChild();
+
+private:
+  XmlChild(const XmlChild & noimpl);
+
+  XmlChild * pNextChild_;
+
+};
+
+class XmlText : public XmlChild {
+public:
+  explicit XmlText(const std::string & text) :
+    XmlChild(),
+    text_(text) {
+  }
+  explicit XmlText(const XmlText & t) :
+    XmlChild(),
+    text_(t.text_) {
+  }
+  explicit XmlText(const char * cstr, size_t len) :
+    XmlChild(),
+    text_(cstr, len) {
+  }
+  virtual ~XmlText();
+
+  const std::string & Text() const { return text_; }
+  void SetText(const std::string & text);
+  void AddParsedText(const char * buf, int len);
+  void AddText(const std::string & text);
+
+protected:
+  virtual bool IsTextImpl() const;
+  virtual XmlElement * AsElementImpl() const;
+  virtual XmlText * AsTextImpl() const;
+
+private:
+  std::string text_;
+};
+
+class XmlAttr {
+friend class XmlElement;
+
+public:
+  XmlAttr * NextAttr() const { return pNextAttr_; }
+  const QName & Name() const { return name_; }
+  const std::string & Value() const { return value_; }
+
+private:
+  explicit XmlAttr(const QName & name, const std::string & value) :
+    pNextAttr_(NULL),
+    name_(name),
+    value_(value) {
+  }
+  explicit XmlAttr(const XmlAttr & att) :
+    pNextAttr_(NULL),
+    name_(att.name_),
+    value_(att.value_) {
+  }
+
+  XmlAttr * pNextAttr_;
+  QName name_;
+  std::string value_;
+};
+
+class XmlElement : public XmlChild {
+public:
+  explicit XmlElement(const QName & name);
+  explicit XmlElement(const QName & name, bool useDefaultNs);
+  explicit XmlElement(const XmlElement & elt);
+
+  virtual ~XmlElement();
+
+  const QName& Name() const { return name_; }
+  void SetName(const QName& name) { name_ = name; }
+
+  const std::string & BodyText() const;
+  void SetBodyText(const std::string & text);
+
+  const QName & FirstElementName() const;
+
+  XmlAttr * FirstAttr();
+  const XmlAttr * FirstAttr() const
+    { return const_cast<XmlElement *>(this)->FirstAttr(); }
+
+  //! Attr will return STR_EMPTY if the attribute isn't there:
+  //! use HasAttr to test presence of an attribute. 
+  const std::string & Attr(const QName & name) const;
+  bool HasAttr(const QName & name) const;
+  void SetAttr(const QName & name, const std::string & value);
+  void ClearAttr(const QName & name);
+
+  XmlChild * FirstChild();
+  const XmlChild * FirstChild() const
+    { return const_cast<XmlElement *>(this)->FirstChild(); }
+
+  XmlElement * FirstElement();
+  const XmlElement * FirstElement() const
+    { return const_cast<XmlElement *>(this)->FirstElement(); }
+
+  XmlElement * NextElement();
+  const XmlElement * NextElement() const
+    { return const_cast<XmlElement *>(this)->NextElement(); }
+
+  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); }
+
+  XmlElement * FirstNamed(const QName & name);
+  const XmlElement * FirstNamed(const QName & name) const
+    { return const_cast<XmlElement *>(this)->FirstNamed(name); }
+
+  XmlElement * NextNamed(const QName & name);
+  const XmlElement * NextNamed(const QName & name) const
+    { return const_cast<XmlElement *>(this)->NextNamed(name); }
+
+  // Finds the first element named 'name'.  If that element can't be found then
+  // adds one and returns it.
+  XmlElement* FindOrAddNamedChild(const QName& name);
+
+  const std::string & TextNamed(const QName & name) const;
+
+  void InsertChildAfter(XmlChild * pPredecessor, XmlChild * pNewChild);
+  void RemoveChildAfter(XmlChild * pPredecessor);
+
+  void AddParsedText(const char * buf, int len);
+  void AddText(const std::string & text);
+  void AddText(const std::string & text, int depth);
+  void AddElement(XmlElement * pelChild);
+  void AddElement(XmlElement * pelChild, int depth);
+  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 ClearChildren();
+
+  static XmlElement * ForStr(const std::string & str);
+  std::string Str() const;
+
+  void Print(std::ostream * pout, std::string xmlns[], int xmlnsCount) const;
+
+protected:
+  virtual bool IsTextImpl() const;
+  virtual XmlElement * AsElementImpl() const;
+  virtual XmlText * AsTextImpl() const;
+
+private:
+  QName name_;
+  XmlAttr * pFirstAttr_;
+  XmlAttr * pLastAttr_;
+  XmlChild * pFirstChild_;
+  XmlChild * pLastChild_;
+};
+
+}
+#endif
diff --git a/talk/xmllite/xmlnsstack.cc b/talk/xmllite/xmlnsstack.cc
new file mode 100755
index 0000000..4dcb649
--- /dev/null
+++ b/talk/xmllite/xmlnsstack.cc
@@ -0,0 +1,205 @@
+/*
+ * 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/stl_decl.h"
+#include <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmllite/xmlnsstack.h"
+#include "talk/xmllite/xmlconstants.h"
+
+namespace buzz {
+
+XmlnsStack::XmlnsStack() :
+  pxmlnsStack_(new std::vector<std::string>),
+  pxmlnsDepthStack_(new std::vector<size_t>) {
+}
+
+XmlnsStack::~XmlnsStack() {}
+
+void
+XmlnsStack::PushFrame() {
+  pxmlnsDepthStack_->push_back(pxmlnsStack_->size());
+}
+
+void
+XmlnsStack::PopFrame() {
+  size_t prev_size = pxmlnsDepthStack_->back();
+  pxmlnsDepthStack_->pop_back();
+  if (prev_size < pxmlnsStack_->size()) {
+    pxmlnsStack_->erase(pxmlnsStack_->begin() + prev_size,
+                        pxmlnsStack_->end());
+  }
+}
+const std::pair<std::string, bool> NS_NOT_FOUND(STR_EMPTY, false);
+const std::pair<std::string, bool> EMPTY_NS_FOUND(STR_EMPTY, true);
+const std::pair<std::string, bool> XMLNS_DEFINITION_FOUND(NS_XMLNS, true);
+
+const std::string *
+XmlnsStack::NsForPrefix(const std::string & prefix) {
+  if (prefix.length() >= 3 &&
+      (prefix[0] == 'x' || prefix[0] == 'X') &&
+      (prefix[1] == 'm' || prefix[1] == 'M') &&
+      (prefix[2] == 'l' || prefix[2] == 'L')) {
+    if (prefix == "xml")
+      return &(NS_XML);
+    if (prefix == "xmlns")
+      return &(NS_XMLNS);
+    return NULL;
+  }
+
+  std::vector<std::string>::iterator pos;
+  for (pos = pxmlnsStack_->end(); pos > pxmlnsStack_->begin(); ) {
+    pos -= 2;
+    if (*pos == prefix)
+      return &(*(pos + 1));
+  }
+
+  if (prefix == STR_EMPTY)
+    return &(STR_EMPTY); // default namespace
+
+  return NULL; // none found
+}
+
+bool
+XmlnsStack::PrefixMatchesNs(const std::string & prefix, const std::string & ns) {
+  const std::string * match = NsForPrefix(prefix);
+  if (match == NULL)
+    return false;
+  return (*match == ns);
+}
+
+std::pair<std::string, bool>
+XmlnsStack::PrefixForNs(const std::string & ns, bool isattr) {
+  if (ns == NS_XML)
+    return std::make_pair(std::string("xml"), true);
+  if (ns == NS_XMLNS)
+    return std::make_pair(std::string("xmlns"), true);
+  if (isattr ? ns == STR_EMPTY : PrefixMatchesNs(STR_EMPTY, ns))
+    return std::make_pair(STR_EMPTY, true);
+
+  std::vector<std::string>::iterator pos;
+  for (pos = pxmlnsStack_->end(); pos > pxmlnsStack_->begin(); ) {
+    pos -= 2;
+    if (*(pos + 1) == ns &&
+        (!isattr || !pos->empty()) && PrefixMatchesNs(*pos, ns))
+      return std::make_pair(*pos, true);
+  }
+
+  return std::make_pair(STR_EMPTY, false); // none found
+}
+
+std::string
+XmlnsStack::FormatQName(const QName & name, bool isAttr) {
+  std::string prefix(PrefixForNs(name.Namespace(), isAttr).first);
+  if (prefix == STR_EMPTY)
+    return name.LocalPart();
+  else
+    return prefix + ':' + name.LocalPart();
+}
+
+void
+XmlnsStack::AddXmlns(const std::string & prefix, const std::string & ns) {
+  pxmlnsStack_->push_back(prefix);
+  pxmlnsStack_->push_back(ns);
+}
+
+void
+XmlnsStack::RemoveXmlns() {
+  pxmlnsStack_->pop_back();
+  pxmlnsStack_->pop_back();
+}
+
+static bool IsAsciiLetter(char ch) {
+  return ((ch >= 'a' && ch <= 'z') ||
+          (ch >= 'A' && ch <= 'Z'));
+}
+
+static std::string AsciiLower(const std::string & s) {
+  std::string result(s);
+  size_t i;
+  for (i = 0; i < result.length(); i++) {
+    if (result[i] >= 'A' && result[i] <= 'Z')
+      result[i] += 'a' - 'A';
+  }
+  return result;
+}
+
+static std::string SuggestPrefix(const std::string & ns) {
+  size_t len = ns.length();
+  size_t i = ns.find_last_of('.');
+  if (i != std::string::npos && len - i <= 4 + 1)
+    len = i; // chop off ".html" or ".xsd" or ".?{0,4}"
+  size_t last = len;
+  while (last > 0) {
+    last -= 1;
+    if (IsAsciiLetter(ns[last])) {
+      size_t first = last;
+      last += 1;
+      while (first > 0) {
+        if (!IsAsciiLetter(ns[first - 1]))
+          break;
+        first -= 1;
+      }
+      if (last - first > 4)
+        last = first + 3;
+      std::string candidate(AsciiLower(ns.substr(first, last - first)));
+      if (candidate.find("xml") != 0)
+        return candidate;
+      break;
+    }
+  }
+  return "ns";
+}
+
+
+std::pair<std::string, bool>
+XmlnsStack::AddNewPrefix(const std::string & ns, bool isAttr) {
+  if (PrefixForNs(ns, isAttr).second)
+    return std::make_pair(STR_EMPTY, false);
+
+  std::string base(SuggestPrefix(ns));
+  std::string result(base);
+  int i = 2;
+  while (NsForPrefix(result) != NULL) {
+    std::stringstream ss;
+    ss << base;
+    ss << (i++);
+    ss >> result;
+  }
+  AddXmlns(result, ns);
+  return std::make_pair(result, true);
+}
+
+void XmlnsStack::Reset() {
+  pxmlnsStack_->clear();
+  pxmlnsDepthStack_->clear();
+}
+
+}
diff --git a/talk/xmllite/xmlnsstack.h b/talk/xmllite/xmlnsstack.h
new file mode 100755
index 0000000..299ec1c
--- /dev/null
+++ b/talk/xmllite/xmlnsstack.h
@@ -0,0 +1,62 @@
+/*
+ * 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 _xmlnsstack_h_
+#define _xmlnsstack_h_
+
+#include <string>
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/stl_decl.h"
+#include "talk/xmllite/qname.h"
+
+namespace buzz {
+
+class XmlnsStack {
+public:
+  XmlnsStack();
+  ~XmlnsStack();
+
+  void AddXmlns(const std::string & prefix, const std::string & ns);
+  void RemoveXmlns();
+  void PushFrame();
+  void PopFrame();
+  void Reset();
+
+  const std::string * NsForPrefix(const std::string & prefix);
+  bool PrefixMatchesNs(const std::string & prefix, const std::string & ns);
+  std::pair<std::string, bool> PrefixForNs(const std::string & ns, bool isAttr);
+  std::pair<std::string, bool> AddNewPrefix(const std::string & ns, bool isAttr);
+  std::string FormatQName(const QName & name, bool isAttr);
+
+private:
+
+  scoped_ptr<std::vector<std::string, std::allocator<std::string> > > pxmlnsStack_;
+  scoped_ptr<std::vector<size_t, std::allocator<size_t> > > pxmlnsDepthStack_;
+};
+}
+
+#endif
diff --git a/talk/xmllite/xmlparser.cc b/talk/xmllite/xmlparser.cc
new file mode 100755
index 0000000..338da8d
--- /dev/null
+++ b/talk/xmllite/xmlparser.cc
@@ -0,0 +1,251 @@
+/*
+ * 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/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
+
+namespace buzz {
+
+
+static void
+StartElementCallback(void * userData, const char *name, const char **atts) {
+  (static_cast<XmlParser *>(userData))->ExpatStartElement(name, atts);
+}
+
+static void
+EndElementCallback(void * userData, const char *name) {
+  (static_cast<XmlParser *>(userData))->ExpatEndElement(name);
+}
+
+static void
+CharacterDataCallback(void * userData, const char *text, int len) {
+  (static_cast<XmlParser *>(userData))->ExpatCharacterData(text, len);
+}
+
+static void
+XmlDeclCallback(void * userData, const char * ver, const char * enc, int st) {
+  (static_cast<XmlParser *>(userData))->ExpatXmlDecl(ver, enc, st);
+}
+
+XmlParser::XmlParser(XmlParseHandler *pxph) :
+    context_(this), pxph_(pxph), sentError_(false) {
+  expat_ = XML_ParserCreate(NULL);
+  XML_SetUserData(expat_, this);
+  XML_SetElementHandler(expat_, StartElementCallback, EndElementCallback);
+  XML_SetCharacterDataHandler(expat_, CharacterDataCallback);
+  XML_SetXmlDeclHandler(expat_, XmlDeclCallback);
+}
+
+void
+XmlParser::Reset() {
+  if (!XML_ParserReset(expat_, NULL)) {
+    XML_ParserFree(expat_);
+    expat_ = XML_ParserCreate(NULL);
+  }
+  XML_SetUserData(expat_, this);
+  XML_SetElementHandler(expat_, StartElementCallback, EndElementCallback);
+  XML_SetCharacterDataHandler(expat_, CharacterDataCallback);
+  XML_SetXmlDeclHandler(expat_, XmlDeclCallback);
+  context_.Reset();
+  sentError_ = false;
+}
+
+static bool
+XmlParser_StartsWithXmlns(const char *name) {
+  return name[0] == 'x' &&
+         name[1] == 'm' &&
+         name[2] == 'l' &&
+         name[3] == 'n' &&
+         name[4] == 's';
+}
+
+void
+XmlParser::ExpatStartElement(const char *name, const char **atts) {
+  if (context_.RaisedError() != XML_ERROR_NONE)
+    return;
+  const char **att;
+  context_.StartElement();
+  for (att = atts; *att; att += 2) {
+    if (XmlParser_StartsWithXmlns(*att)) {
+      if ((*att)[5] == '\0') {
+        context_.StartNamespace("", *(att + 1));
+      }
+      else if ((*att)[5] == ':') {
+        if (**(att + 1) == '\0') {
+          // In XML 1.0 empty namespace illegal with prefix (not in 1.1)
+          context_.RaiseError(XML_ERROR_SYNTAX);
+          return;
+        }
+        context_.StartNamespace((*att) + 6, *(att + 1));
+      }
+    }
+  }
+  pxph_->StartElement(&context_, name, atts);
+}
+
+void
+XmlParser::ExpatEndElement(const char *name) {
+  if (context_.RaisedError() != XML_ERROR_NONE)
+    return;
+  context_.EndElement();
+  pxph_->EndElement(&context_, name);
+}
+
+void
+XmlParser::ExpatCharacterData(const char *text, int len) {
+  if (context_.RaisedError() != XML_ERROR_NONE)
+    return;
+  pxph_->CharacterData(&context_, text, len);
+}
+
+void
+XmlParser::ExpatXmlDecl(const char * ver, const char * enc, int standalone) {
+  if (context_.RaisedError() != XML_ERROR_NONE)
+    return;
+
+  if (ver && std::string("1.0") != ver) {
+    context_.RaiseError(XML_ERROR_SYNTAX);
+    return;
+  }
+
+  if (standalone == 0) {
+    context_.RaiseError(XML_ERROR_SYNTAX);
+    return;
+  }
+
+  if (enc && !((enc[0] == 'U' || enc[0] == 'u') &&
+               (enc[1] == 'T' || enc[1] == 't') &&
+               (enc[2] == 'F' || enc[2] == 'f') &&
+                enc[3] == '-' && enc[4] =='8')) {
+    context_.RaiseError(XML_ERROR_INCORRECT_ENCODING);
+    return;
+  }
+
+}
+
+bool
+XmlParser::Parse(const char *data, size_t len, bool isFinal) {
+  if (sentError_)
+    return false;
+
+  if (XML_Parse(expat_, data, static_cast<int>(len), isFinal) != XML_STATUS_OK)
+    context_.RaiseError(XML_GetErrorCode(expat_));
+
+  if (context_.RaisedError() != XML_ERROR_NONE) {
+    sentError_ = true;
+    pxph_->Error(&context_, context_.RaisedError());
+    return false;
+  }
+
+  return true;
+}
+
+XmlParser::~XmlParser() {
+  XML_ParserFree(expat_);
+}
+
+void
+XmlParser::ParseXml(XmlParseHandler *pxph, std::string text) {
+  XmlParser parser(pxph);
+  parser.Parse(text.c_str(), text.length(), true);
+}
+
+XmlParser::ParseContext::ParseContext(XmlParser *parser) :
+    parser_(parser),
+    xmlnsstack_(),
+    raised_(XML_ERROR_NONE) {
+}
+
+void
+XmlParser::ParseContext::StartNamespace(const char *prefix, const char *ns) {
+  xmlnsstack_.AddXmlns(
+    *prefix ? std::string(prefix) : STR_EMPTY,
+//    ns == NS_CLIENT ? NS_CLIENT :
+//    ns == NS_ROSTER ? NS_ROSTER :
+//    ns == NS_GR ? NS_GR :
+    std::string(ns));
+}
+
+void
+XmlParser::ParseContext::StartElement() {
+  xmlnsstack_.PushFrame();
+}
+
+void
+XmlParser::ParseContext::EndElement() {
+  xmlnsstack_.PopFrame();
+}
+
+QName
+XmlParser::ParseContext::ResolveQName(const char *qname, bool isAttr) {
+  const char *c;
+  for (c = qname; *c; ++c) {
+    if (*c == ':') {
+      const std::string * result;
+      result = xmlnsstack_.NsForPrefix(std::string(qname, c - qname));
+      if (result == NULL)
+        return QN_EMPTY;
+      const char * localname = c + 1;
+      return QName(*result, localname); 
+    }
+  }
+  if (isAttr) {
+    return QName(STR_EMPTY, qname);
+  }
+  
+  const std::string * result;
+  result = xmlnsstack_.NsForPrefix(STR_EMPTY);
+  if (result == NULL)
+    return QN_EMPTY;
+
+  return QName(*result, qname);
+}
+
+void
+XmlParser::ParseContext::Reset() {
+  xmlnsstack_.Reset();
+  raised_ = XML_ERROR_NONE;
+}
+
+XmlParser::ParseContext::~ParseContext() {
+}
+
+}
+
diff --git a/talk/xmllite/xmlparser.h b/talk/xmllite/xmlparser.h
new file mode 100755
index 0000000..7533a45
--- /dev/null
+++ b/talk/xmllite/xmlparser.h
@@ -0,0 +1,107 @@
+/*
+ * 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 _xmlparser_h_
+#define _xmlparser_h_
+
+#include <string>
+#include <expat.h>
+
+#include "talk/xmllite/xmlnsstack.h"
+
+struct XML_ParserStruct;
+typedef struct XML_ParserStruct* XML_Parser;
+
+namespace buzz {
+
+class XmlParseHandler;
+class XmlParseContext;
+class XmlParser;
+
+class XmlParseContext {
+public:
+  virtual QName ResolveQName(const char * qname, bool isAttr) = 0;
+  virtual void RaiseError(XML_Error err) = 0;
+};
+
+class XmlParseHandler {
+public:
+  virtual void StartElement(XmlParseContext * pctx,
+               const char * name, const char ** atts) = 0;
+  virtual void EndElement(XmlParseContext * pctx,
+               const char * name) = 0;
+  virtual void CharacterData(XmlParseContext * pctx,
+               const char * text, int len) = 0;
+  virtual void Error(XmlParseContext * pctx,
+               XML_Error errorCode) = 0;
+};
+
+class XmlParser {
+public:
+  static void ParseXml(XmlParseHandler * pxph, std::string text);
+
+  explicit XmlParser(XmlParseHandler * pxph);
+  bool Parse(const char * data, size_t len, bool isFinal);
+  void Reset();
+  virtual ~XmlParser();
+
+  // expat callbacks
+  void ExpatStartElement(const char * name, const char ** atts);
+  void ExpatEndElement(const char * name);
+  void ExpatCharacterData(const char * text, int len);
+  void ExpatXmlDecl(const char * ver, const char * enc, int standalone);
+
+private:
+
+  class ParseContext : public XmlParseContext {
+  public:
+    ParseContext(XmlParser * parser);
+    virtual ~ParseContext();
+    virtual QName ResolveQName(const char * qname, bool isAttr);
+    virtual void RaiseError(XML_Error err) { if (!raised_) raised_ = err; }
+    XML_Error RaisedError() { return raised_; }
+    void Reset();
+
+    void StartElement();
+    void EndElement();
+    void StartNamespace(const char * prefix, const char * ns);
+
+  private:
+    const XmlParser * parser_;
+    XmlnsStack xmlnsstack_;
+    XML_Error raised_;
+  };
+
+  ParseContext context_;
+  XML_Parser expat_;
+  XmlParseHandler * pxph_;
+  bool sentError_;
+};
+
+}
+
+#endif
diff --git a/talk/xmllite/xmlprinter.cc b/talk/xmllite/xmlprinter.cc
new file mode 100755
index 0000000..86f143a
--- /dev/null
+++ b/talk/xmllite/xmlprinter.cc
@@ -0,0 +1,190 @@
+/*
+ * 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/stl_decl.h"
+#include <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmllite/xmlprinter.h"
+#include "talk/xmllite/xmlnsstack.h"
+#include "talk/xmllite/xmlconstants.h"
+
+namespace buzz {
+
+class XmlPrinterImpl {
+public:
+  XmlPrinterImpl(std::ostream * pout,
+    const std::string * const xmlns, int xmlnsCount);
+  void PrintElement(const XmlElement * element);
+  void PrintQuotedValue(const std::string & text);
+  void PrintBodyText(const std::string & text);
+
+private:
+  std::ostream *pout_;
+  XmlnsStack xmlnsStack_;
+};
+
+void
+XmlPrinter::PrintXml(std::ostream * pout, const XmlElement * element) {
+  PrintXml(pout, element, NULL, 0);
+}
+
+void
+XmlPrinter::PrintXml(std::ostream * pout, const XmlElement * element,
+    const std::string * const xmlns, int xmlnsCount) {
+  XmlPrinterImpl printer(pout, xmlns, xmlnsCount);
+  printer.PrintElement(element);
+}
+
+XmlPrinterImpl::XmlPrinterImpl(std::ostream * pout,
+    const std::string * const xmlns, int xmlnsCount) :
+  pout_(pout),
+  xmlnsStack_() {
+  int i;
+  for (i = 0; i < xmlnsCount; i += 2) {
+    xmlnsStack_.AddXmlns(xmlns[i], xmlns[i + 1]);
+  }
+}
+
+void
+XmlPrinterImpl::PrintElement(const XmlElement * element) {
+  xmlnsStack_.PushFrame();
+
+  // first go through attrs of pel to add xmlns definitions
+  const XmlAttr * pattr;
+  for (pattr = element->FirstAttr(); pattr; pattr = pattr->NextAttr()) {
+    if (pattr->Name() == QN_XMLNS)
+      xmlnsStack_.AddXmlns(STR_EMPTY, pattr->Value());
+    else if (pattr->Name().Namespace() == NS_XMLNS)
+      xmlnsStack_.AddXmlns(pattr->Name().LocalPart(),
+        pattr->Value());
+  }
+
+  // then go through qnames to make sure needed xmlns definitons are added
+  std::vector<std::string> newXmlns;
+  std::pair<std::string, bool> prefix;
+  prefix = xmlnsStack_.AddNewPrefix(element->Name().Namespace(), false);
+  if (prefix.second) {
+    newXmlns.push_back(prefix.first);
+    newXmlns.push_back(element->Name().Namespace());
+  }
+
+  for (pattr = element->FirstAttr(); pattr; pattr = pattr->NextAttr()) {
+    prefix = xmlnsStack_.AddNewPrefix(pattr->Name().Namespace(), true);
+    if (prefix.second) {
+      newXmlns.push_back(prefix.first);
+      newXmlns.push_back(pattr->Name().Namespace());
+    }
+  }
+
+  // print the element name
+  *pout_ << '<' << xmlnsStack_.FormatQName(element->Name(), false);
+
+  // and the attributes
+  for (pattr = element->FirstAttr(); pattr; pattr = pattr->NextAttr()) {
+    *pout_ << ' ' << xmlnsStack_.FormatQName(pattr->Name(), true) << "=\"";
+    PrintQuotedValue(pattr->Value());
+    *pout_ << '"';
+  }
+
+  // and the extra xmlns declarations
+  std::vector<std::string>::iterator i(newXmlns.begin());
+  while (i < newXmlns.end()) {
+    if (*i == STR_EMPTY)
+      *pout_ << " xmlns=\"" << *(i + 1) << '"';
+    else
+      *pout_ << " xmlns:" << *i << "=\"" << *(i + 1) << '"';
+    i += 2;
+  }
+
+  // now the children
+  const XmlChild * pchild = element->FirstChild();
+
+  if (pchild == NULL)
+    *pout_ << "/>";
+  else {
+    *pout_ << '>';
+    while (pchild) {
+      if (pchild->IsText())
+        PrintBodyText(pchild->AsText()->Text());
+      else
+        PrintElement(pchild->AsElement());
+      pchild = pchild->NextChild();
+    }
+    *pout_ << "</" << xmlnsStack_.FormatQName(element->Name(), false) << '>';
+  }
+
+  xmlnsStack_.PopFrame();
+}
+
+void
+XmlPrinterImpl::PrintQuotedValue(const std::string & text) {
+  size_t safe = 0;
+  for (;;) {
+    size_t unsafe = text.find_first_of("<>&\"", safe);
+    if (unsafe == std::string::npos)
+      unsafe = text.length();
+    *pout_ << text.substr(safe, unsafe - safe);
+    if (unsafe == text.length())
+      return;
+    switch (text[unsafe]) {
+      case '<': *pout_ << "&lt;"; break;
+      case '>': *pout_ << "&gt;"; break;
+      case '&': *pout_ << "&amp;"; break;
+      case '"': *pout_ << "&quot;"; break;
+    }
+    safe = unsafe + 1;
+    if (safe == text.length())
+      return;
+  }
+}
+
+void
+XmlPrinterImpl::PrintBodyText(const std::string & text) {
+  size_t safe = 0;
+  for (;;) {
+    size_t unsafe = text.find_first_of("<>&", safe);
+    if (unsafe == std::string::npos)
+      unsafe = text.length();
+    *pout_ << text.substr(safe, unsafe - safe);
+    if (unsafe == text.length())
+      return;
+    switch (text[unsafe]) {
+      case '<': *pout_ << "&lt;"; break;
+      case '>': *pout_ << "&gt;"; break;
+      case '&': *pout_ << "&amp;"; break;
+    }
+    safe = unsafe + 1;
+    if (safe == text.length())
+      return;
+  }
+}
+
+
+}
diff --git a/talk/xmllite/xmlprinter.h b/talk/xmllite/xmlprinter.h
new file mode 100755
index 0000000..96900d0
--- /dev/null
+++ b/talk/xmllite/xmlprinter.h
@@ -0,0 +1,49 @@
+/*
+ * 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 _xmlprinter_h_
+#define _xmlprinter_h_
+
+#include <iosfwd>
+#include <string>
+#include "talk/base/scoped_ptr.h"
+
+namespace buzz {
+
+class XmlElement;
+
+class XmlPrinter {
+public:
+  static void PrintXml(std::ostream * pout, const XmlElement * pelt);
+
+  static void PrintXml(std::ostream * pout, const XmlElement * pelt,
+    const std::string * const xmlns, int xmlnsCount);
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/Makefile.am b/talk/xmpp/Makefile.am
new file mode 100755
index 0000000..ad75fbc
--- /dev/null
+++ b/talk/xmpp/Makefile.am
@@ -0,0 +1,33 @@
+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/Makefile.in b/talk/xmpp/Makefile.in
new file mode 100644
index 0000000..801122b
--- /dev/null
+++ b/talk/xmpp/Makefile.in
@@ -0,0 +1,484 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = talk/xmpp
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/talk/pkg.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libcricketxmpp_la_LIBADD =
+am_libcricketxmpp_la_OBJECTS = constants.lo jid.lo saslmechanism.lo \
+	xmppclient.lo xmppengineimpl.lo xmppengineimpl_iq.lo \
+	xmpplogintask.lo xmppstanzaparser.lo xmpptask.lo \
+	ratelimitmanager.lo
+libcricketxmpp_la_OBJECTS = $(am_libcricketxmpp_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcricketxmpp_la_SOURCES)
+DIST_SOURCES = $(libcricketxmpp_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_LIBS = @ALSA_LIBS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GIPS_FALSE = @GIPS_FALSE@
+GIPS_TRUE = @GIPS_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+ILBC_CFLAGS = @ILBC_CFLAGS@
+ILBC_LIBS = @ILBC_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MEDIA_LIBS = @MEDIA_LIBS@
+OBJEXT = @OBJEXT@
+ORTP_CFLAGS = @ORTP_CFLAGS@
+ORTP_LIBS = @ORTP_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PHONE_FALSE = @PHONE_FALSE@
+PHONE_TRUE = @PHONE_TRUE@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPEEX_CFLAGS = @SPEEX_CFLAGS@
+SPEEX_LIBS = @SPEEX_LIBS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+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
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  talk/xmpp/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  talk/xmpp/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcricketxmpp.la: $(libcricketxmpp_la_OBJECTS) $(libcricketxmpp_la_DEPENDENCIES) 
+	$(CXXLINK)  $(libcricketxmpp_la_LDFLAGS) $(libcricketxmpp_la_OBJECTS) $(libcricketxmpp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ratelimitmanager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saslmechanism.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmppclient.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmppengineimpl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmppengineimpl_iq.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmpplogintask.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmppstanzaparser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmpptask.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/talk/xmpp/asyncsocket.h b/talk/xmpp/asyncsocket.h
new file mode 100755
index 0000000..e4bce7f
--- /dev/null
+++ b/talk/xmpp/asyncsocket.h
@@ -0,0 +1,86 @@
+/*
+ * 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 _ASYNCSOCKET_H_
+#define _ASYNCSOCKET_H_
+
+#include "talk/base/sigslot.h"
+
+namespace talk_base {
+  class SocketAddress;
+}
+
+namespace buzz {
+
+class AsyncSocket {
+public:
+  enum State {
+    STATE_CLOSED = 0,      //!< Socket is not open.
+    STATE_CLOSING,         //!< Socket is closing but can have buffered data
+    STATE_CONNECTING,      //!< In the process of
+    STATE_OPEN,            //!< Socket is connected
+#if defined(FEATURE_ENABLE_SSL)
+    STATE_TLS_CONNECTING,  //!< Establishing TLS connection
+    STATE_TLS_OPEN,        //!< TLS connected
+#endif
+  };
+
+  enum Error {
+    ERROR_NONE = 0,         //!< No error
+    ERROR_WINSOCK,          //!< Winsock error
+    ERROR_DNS,              //!< Couldn't resolve host name
+    ERROR_WRONGSTATE,       //!< Call made while socket is in the wrong state
+#if defined(FEATURE_ENABLE_SSL)
+    ERROR_SSL,              //!< Something went wrong with OpenSSL
+#endif
+  };
+
+  virtual ~AsyncSocket() {}
+  virtual State state() = 0;
+  virtual Error error() = 0;
+  virtual int GetError() = 0;    // winsock error code
+
+  virtual bool Connect(const talk_base::SocketAddress& addr) = 0;
+  virtual bool Read(char * data, size_t len, size_t* len_read) = 0;
+  virtual bool Write(const char * data, size_t len) = 0;
+  virtual bool Close() = 0;
+#if defined(FEATURE_ENABLE_SSL)
+  // We allow matching any passed domain.
+  // If both names are passed as empty, we do not require a match.
+  virtual bool StartTls(const std::string & domainname) = 0;
+#endif
+
+  sigslot::signal0<> SignalConnected;
+  sigslot::signal0<> SignalSSLConnected;
+  sigslot::signal0<> SignalClosed;
+  sigslot::signal0<> SignalRead;
+  sigslot::signal0<> SignalError;
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/constants.cc b/talk/xmpp/constants.cc
new file mode 100755
index 0000000..9388aae
--- /dev/null
+++ b/talk/xmpp/constants.cc
@@ -0,0 +1,398 @@
+/*
+ * 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 <string>
+#include "talk/base/basicdefs.h"
+#include "talk/xmllite/xmlconstants.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmpp/jid.h"
+#include "talk/xmpp/constants.h"
+namespace buzz {
+
+const Jid JID_EMPTY(STR_EMPTY);
+
+const std::string & Constants::ns_client() {
+  static const std::string ns_client_("jabber:client");
+  return ns_client_;
+}
+
+const std::string & Constants::ns_server() {
+  static const std::string ns_server_("jabber:server");
+  return ns_server_;
+}
+
+const std::string & Constants::ns_stream() {
+  static const std::string ns_stream_("http://etherx.jabber.org/streams");
+  return ns_stream_;
+}
+
+const std::string & Constants::ns_xstream() {
+  static const std::string ns_xstream_("urn:ietf:params:xml:ns:xmpp-streams");
+  return ns_xstream_;
+}
+
+const std::string & Constants::ns_tls() {
+  static const std::string ns_tls_("urn:ietf:params:xml:ns:xmpp-tls");
+  return ns_tls_;
+}
+
+const std::string & Constants::ns_sasl() {
+  static const std::string ns_sasl_("urn:ietf:params:xml:ns:xmpp-sasl");
+  return ns_sasl_;
+}
+
+const std::string & Constants::ns_bind() {
+  static const std::string ns_bind_("urn:ietf:params:xml:ns:xmpp-bind");
+  return ns_bind_;
+}
+
+const std::string & Constants::ns_dialback() {
+  static const std::string ns_dialback_("jabber:server:dialback");
+  return ns_dialback_;
+}
+
+const std::string & Constants::ns_session() {
+  static const std::string ns_session_("urn:ietf:params:xml:ns:xmpp-session");
+  return ns_session_;
+}
+
+const std::string & Constants::ns_stanza() {
+  static const std::string ns_stanza_("urn:ietf:params:xml:ns:xmpp-stanzas");
+  return ns_stanza_;
+}
+
+const std::string & Constants::ns_privacy() {
+  static const std::string ns_privacy_("jabber:iq:privacy");
+  return ns_privacy_;
+}
+
+const std::string & Constants::ns_roster() {
+  static const std::string ns_roster_("jabber:iq:roster");
+  return ns_roster_;
+}
+
+const std::string & Constants::ns_vcard() {
+  static const std::string ns_vcard_("vcard-temp");
+  return ns_vcard_;
+}
+
+const std::string & Constants::ns_avatar_hash() {
+  static const std::string ns_avatar_hash_("google:avatar");
+  return ns_avatar_hash_;
+}
+
+const std::string & Constants::ns_vcard_update() {
+  static const std::string ns_vcard_update_("vcard-temp:x:update");
+  return ns_vcard_update_;
+}
+
+const std::string & Constants::str_client() {
+  static const std::string str_client_("client");
+  return str_client_;
+}
+
+const std::string & Constants::str_server() {
+  static const std::string str_server_("server");
+  return str_server_;
+}
+
+const std::string & Constants::str_stream() {
+  static const std::string str_stream_("stream");
+  return str_stream_;
+}
+
+const std::string STR_GET("get");
+const std::string STR_SET("set");
+const std::string STR_RESULT("result");
+const std::string STR_ERROR("error");
+
+
+const std::string STR_FROM("from");
+const std::string STR_TO("to");
+const std::string STR_BOTH("both");
+const std::string STR_REMOVE("remove");
+
+const std::string STR_UNAVAILABLE("unavailable");
+
+const std::string STR_GOOGLE_COM("google.com");
+const std::string STR_GMAIL_COM("gmail.com");
+const std::string STR_GOOGLEMAIL_COM("googlemail.com");
+const std::string STR_DEFAULT_DOMAIN("default.talk.google.com");
+const std::string STR_TALK_GOOGLE_COM("talk.google.com");
+const std::string STR_TALKX_L_GOOGLE_COM("talkx.l.google.com");
+
+const std::string STR_X("x");
+
+#ifdef FEATURE_ENABLE_VOICEMAIL
+const std::string STR_VOICEMAIL("voicemail");
+const std::string STR_OUTGOINGVOICEMAIL("outgoingvoicemail");
+#endif
+
+const QName QN_STREAM_STREAM(true, NS_STREAM, STR_STREAM);
+const QName QN_STREAM_FEATURES(true, NS_STREAM, "features");
+const QName QN_STREAM_ERROR(true, NS_STREAM, "error");
+
+const QName QN_XSTREAM_BAD_FORMAT(true, NS_XSTREAM, "bad-format");
+const QName QN_XSTREAM_BAD_NAMESPACE_PREFIX(true, NS_XSTREAM, "bad-namespace-prefix");
+const QName QN_XSTREAM_CONFLICT(true, NS_XSTREAM, "conflict");
+const QName QN_XSTREAM_CONNECTION_TIMEOUT(true, NS_XSTREAM, "connection-timeout");
+const QName QN_XSTREAM_HOST_GONE(true, NS_XSTREAM, "host-gone");
+const QName QN_XSTREAM_HOST_UNKNOWN(true, NS_XSTREAM, "host-unknown");
+const QName QN_XSTREAM_IMPROPER_ADDRESSIING(true, NS_XSTREAM, "improper-addressing");
+const QName QN_XSTREAM_INTERNAL_SERVER_ERROR(true, NS_XSTREAM, "internal-server-error");
+const QName QN_XSTREAM_INVALID_FROM(true, NS_XSTREAM, "invalid-from");
+const QName QN_XSTREAM_INVALID_ID(true, NS_XSTREAM, "invalid-id");
+const QName QN_XSTREAM_INVALID_NAMESPACE(true, NS_XSTREAM, "invalid-namespace");
+const QName QN_XSTREAM_INVALID_XML(true, NS_XSTREAM, "invalid-xml");
+const QName QN_XSTREAM_NOT_AUTHORIZED(true, NS_XSTREAM, "not-authorized");
+const QName QN_XSTREAM_POLICY_VIOLATION(true, NS_XSTREAM, "policy-violation");
+const QName QN_XSTREAM_REMOTE_CONNECTION_FAILED(true, NS_XSTREAM, "remote-connection-failed");
+const QName QN_XSTREAM_RESOURCE_CONSTRAINT(true, NS_XSTREAM, "resource-constraint");
+const QName QN_XSTREAM_RESTRICTED_XML(true, NS_XSTREAM, "restricted-xml");
+const QName QN_XSTREAM_SEE_OTHER_HOST(true, NS_XSTREAM, "see-other-host");
+const QName QN_XSTREAM_SYSTEM_SHUTDOWN(true, NS_XSTREAM, "system-shutdown");
+const QName QN_XSTREAM_UNDEFINED_CONDITION(true, NS_XSTREAM, "undefined-condition");
+const QName QN_XSTREAM_UNSUPPORTED_ENCODING(true, NS_XSTREAM, "unsupported-encoding");
+const QName QN_XSTREAM_UNSUPPORTED_STANZA_TYPE(true, NS_XSTREAM, "unsupported-stanza-type");
+const QName QN_XSTREAM_UNSUPPORTED_VERSION(true, NS_XSTREAM, "unsupported-version");
+const QName QN_XSTREAM_XML_NOT_WELL_FORMED(true, NS_XSTREAM, "xml-not-well-formed");
+const QName QN_XSTREAM_TEXT(true, NS_XSTREAM, "text");
+
+const QName QN_TLS_STARTTLS(true, NS_TLS, "starttls");
+const QName QN_TLS_REQUIRED(true, NS_TLS, "required");
+const QName QN_TLS_PROCEED(true, NS_TLS, "proceed");
+const QName QN_TLS_FAILURE(true, NS_TLS, "failure");
+
+const QName QN_SASL_MECHANISMS(true, NS_SASL, "mechanisms");
+const QName QN_SASL_MECHANISM(true, NS_SASL, "mechanism");
+const QName QN_SASL_AUTH(true, NS_SASL, "auth");
+const QName QN_SASL_CHALLENGE(true, NS_SASL, "challenge");
+const QName QN_SASL_RESPONSE(true, NS_SASL, "response");
+const QName QN_SASL_ABORT(true, NS_SASL, "abort");
+const QName QN_SASL_SUCCESS(true, NS_SASL, "success");
+const QName QN_SASL_FAILURE(true, NS_SASL, "failure");
+const QName QN_SASL_ABORTED(true, NS_SASL, "aborted");
+const QName QN_SASL_INCORRECT_ENCODING(true, NS_SASL, "incorrect-encoding");
+const QName QN_SASL_INVALID_AUTHZID(true, NS_SASL, "invalid-authzid");
+const QName QN_SASL_INVALID_MECHANISM(true, NS_SASL, "invalid-mechanism");
+const QName QN_SASL_MECHANISM_TOO_WEAK(true, NS_SASL, "mechanism-too-weak");
+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");
+
+const QName QN_STANZA_BAD_REQUEST(true, NS_STANZA, "bad-request");
+const QName QN_STANZA_CONFLICT(true, NS_STANZA, "conflict");
+const QName QN_STANZA_FEATURE_NOT_IMPLEMENTED(true, NS_STANZA, "feature-not-implemented");
+const QName QN_STANZA_FORBIDDEN(true, NS_STANZA, "forbidden");
+const QName QN_STANZA_GONE(true, NS_STANZA, "gone");
+const QName QN_STANZA_INTERNAL_SERVER_ERROR(true, NS_STANZA, "internal-server-error");
+const QName QN_STANZA_ITEM_NOT_FOUND(true, NS_STANZA, "item-not-found");
+const QName QN_STANZA_JID_MALFORMED(true, NS_STANZA, "jid-malformed");
+const QName QN_STANZA_NOT_ACCEPTABLE(true, NS_STANZA, "not-acceptable");
+const QName QN_STANZA_NOT_ALLOWED(true, NS_STANZA, "not-allowed");
+const QName QN_STANZA_PAYMENT_REQUIRED(true, NS_STANZA, "payment-required");
+const QName QN_STANZA_RECIPIENT_UNAVAILABLE(true, NS_STANZA, "recipient-unavailable");
+const QName QN_STANZA_REDIRECT(true, NS_STANZA, "redirect");
+const QName QN_STANZA_REGISTRATION_REQUIRED(true, NS_STANZA, "registration-required");
+const QName QN_STANZA_REMOTE_SERVER_NOT_FOUND(true, NS_STANZA, "remote-server-not-found");
+const QName QN_STANZA_REMOTE_SERVER_TIMEOUT(true, NS_STANZA, "remote-server-timeout");
+const QName QN_STANZA_RESOURCE_CONSTRAINT(true, NS_STANZA, "resource-constraint");
+const QName QN_STANZA_SERVICE_UNAVAILABLE(true, NS_STANZA, "service-unavailable");
+const QName QN_STANZA_SUBSCRIPTION_REQUIRED(true, NS_STANZA, "subscription-required");
+const QName QN_STANZA_UNDEFINED_CONDITION(true, NS_STANZA, "undefined-condition");
+const QName QN_STANZA_UNEXPECTED_REQUEST(true, NS_STANZA, "unexpected-request");
+const QName QN_STANZA_TEXT(true, NS_STANZA, "text");
+
+const QName QN_BIND_BIND(true, NS_BIND, "bind");
+const QName QN_BIND_RESOURCE(true, NS_BIND, "resource");
+const QName QN_BIND_JID(true, NS_BIND, "jid");
+
+const QName QN_MESSAGE(true, NS_CLIENT, "message");
+const QName QN_BODY(true, NS_CLIENT, "body");
+const QName QN_SUBJECT(true, NS_CLIENT, "subject");
+const QName QN_THREAD(true, NS_CLIENT, "thread");
+const QName QN_PRESENCE(true, NS_CLIENT, "presence");
+const QName QN_SHOW(true, NS_CLIENT, "show");
+const QName QN_STATUS(true, NS_CLIENT, "status");
+const QName QN_LANG(true, NS_CLIENT, "lang");
+const QName QN_PRIORITY(true, NS_CLIENT, "priority");
+const QName QN_IQ(true, NS_CLIENT, "iq");
+const QName QN_ERROR(true, NS_CLIENT, "error");
+
+const QName QN_SERVER_MESSAGE(true, NS_SERVER, "message");
+const QName QN_SERVER_BODY(true, NS_SERVER, "body");
+const QName QN_SERVER_SUBJECT(true, NS_SERVER, "subject");
+const QName QN_SERVER_THREAD(true, NS_SERVER, "thread");
+const QName QN_SERVER_PRESENCE(true, NS_SERVER, "presence");
+const QName QN_SERVER_SHOW(true, NS_SERVER, "show");
+const QName QN_SERVER_STATUS(true, NS_SERVER, "status");
+const QName QN_SERVER_LANG(true, NS_SERVER, "lang");
+const QName QN_SERVER_PRIORITY(true, NS_SERVER, "priority");
+const QName QN_SERVER_IQ(true, NS_SERVER, "iq");
+const QName QN_SERVER_ERROR(true, NS_SERVER, "error");
+
+const QName QN_SESSION_SESSION(true, NS_SESSION, "session");
+
+const QName QN_PRIVACY_QUERY(true, NS_PRIVACY, "query");
+const QName QN_PRIVACY_ACTIVE(true, NS_PRIVACY, "active");
+const QName QN_PRIVACY_DEFAULT(true, NS_PRIVACY, "default");
+const QName QN_PRIVACY_LIST(true, NS_PRIVACY, "list");
+const QName QN_PRIVACY_ITEM(true, NS_PRIVACY, "item");
+const QName QN_PRIVACY_IQ(true, NS_PRIVACY, "iq");
+const QName QN_PRIVACY_MESSAGE(true, NS_PRIVACY, "message");
+const QName QN_PRIVACY_PRESENCE_IN(true, NS_PRIVACY, "presence-in");
+const QName QN_PRIVACY_PRESENCE_OUT(true, NS_PRIVACY, "presence-out");
+
+const QName QN_ROSTER_QUERY(true, NS_ROSTER, "query");
+const QName QN_ROSTER_ITEM(true, NS_ROSTER, "item");
+const QName QN_ROSTER_GROUP(true, NS_ROSTER, "group");
+
+const QName QN_VCARD(true, NS_VCARD, "vCard");
+const QName QN_VCARD_FN(true, NS_VCARD, "FN");
+const QName QN_VCARD_PHOTO(true, NS_VCARD, "PHOTO");
+const QName QN_VCARD_PHOTO_BINVAL(true, NS_VCARD, "BINVAL");
+const QName QN_VCARD_AVATAR_HASH(true, NS_AVATAR_HASH, "hash");
+const QName QN_VCARD_AVATAR_HASH_MODIFIED(true, NS_AVATAR_HASH, "modified");
+
+const buzz::QName QN_NAME(true, STR_EMPTY, "name");
+const QName QN_XML_LANG(true, NS_XML, "lang");
+
+const std::string STR_TYPE("type");
+const std::string STR_ID("id");
+const std::string STR_NAME("name");
+const std::string STR_JID("jid");
+const std::string STR_SUBSCRIPTION("subscription");
+const std::string STR_ASK("ask");
+
+const QName QN_ENCODING(true, STR_EMPTY, STR_ENCODING);
+const QName QN_VERSION(true, STR_EMPTY, STR_VERSION);
+const QName QN_TO(true, STR_EMPTY, "to");
+const QName QN_FROM(true, STR_EMPTY, "from");
+const QName QN_TYPE(true, STR_EMPTY, "type");
+const QName QN_ID(true, STR_EMPTY, "id");
+const QName QN_CODE(true, STR_EMPTY, "code");
+
+const QName QN_VALUE(true, STR_EMPTY, "value");
+const QName QN_ACTION(true, STR_EMPTY, "action");
+const QName QN_ORDER(true, STR_EMPTY, "order");
+const QName QN_MECHANISM(true, STR_EMPTY, "mechanism");
+const QName QN_ASK(true, STR_EMPTY, "ask");
+const QName QN_JID(true, STR_EMPTY, "jid");
+const QName QN_SUBSCRIPTION(true, STR_EMPTY, "subscription");
+const QName QN_TITLE1(true, STR_EMPTY, "title1");
+const QName QN_TITLE2(true, STR_EMPTY, "title2");
+const QName QN_SOURCE(true, STR_EMPTY, "source");
+
+const QName QN_XMLNS_CLIENT(true, NS_XMLNS, STR_CLIENT);
+const QName QN_XMLNS_SERVER(true, NS_XMLNS, STR_SERVER);
+const QName QN_XMLNS_STREAM(true, NS_XMLNS, STR_STREAM);
+
+
+
+// Presence
+const std::string STR_SHOW_AWAY("away");
+const std::string STR_SHOW_CHAT("chat");
+const std::string STR_SHOW_DND("dnd");
+const std::string STR_SHOW_XA("xa");
+const std::string STR_SHOW_OFFLINE("offline");
+
+// Subscription
+const std::string STR_SUBSCRIBE("subscribe");
+const std::string STR_SUBSCRIBED("subscribed");
+const std::string STR_UNSUBSCRIBE("unsubscribe");
+const std::string STR_UNSUBSCRIBED("unsubscribed");
+
+
+// JEP 0030
+const QName QN_NODE(true, STR_EMPTY, "node");
+const QName QN_CATEGORY(true, STR_EMPTY, "category");
+const QName QN_VAR(true, STR_EMPTY, "var");
+const std::string NS_DISCO_INFO("http://jabber.org/protocol/disco#info");
+const std::string NS_DISCO_ITEMS("http://jabber.org/protocol/disco#items");
+const QName QN_DISCO_INFO_QUERY(true, NS_DISCO_INFO, "query");
+const QName QN_DISCO_IDENTITY(true, NS_DISCO_INFO, "identity");
+const QName QN_DISCO_FEATURE(true, NS_DISCO_INFO, "feature");
+
+const QName QN_DISCO_ITEMS_QUERY(true, NS_DISCO_ITEMS, "query");
+const QName QN_DISCO_ITEM(true, NS_DISCO_ITEMS, "item");
+
+
+// JEP 0115
+const std::string NS_CAPS("http://jabber.org/protocol/caps");
+const QName QN_CAPS_C(true, NS_CAPS, "c");
+const QName QN_VER(true, STR_EMPTY, "ver");
+const QName QN_EXT(true, STR_EMPTY, "ext");
+
+// JEP 0153
+const std::string kNSVCard("vcard-temp:x:update");
+const QName kQnVCardX(true, kNSVCard, "x");
+const QName kQnVCardPhoto(true, kNSVCard, "photo");
+
+// JEP 0172 User Nickname
+const std::string kNSNickname("http://jabber.org/protocol/nick");
+const QName kQnNickname(true, kNSNickname, "nick");
+
+
+// JEP 0085 chat state
+const std::string NS_CHATSTATE("http://jabber.org/protocol/chatstates");
+const QName QN_CS_ACTIVE(true, NS_CHATSTATE, "active");
+const QName QN_CS_COMPOSING(true, NS_CHATSTATE, "composing");
+const QName QN_CS_PAUSED(true, NS_CHATSTATE, "paused");
+const QName QN_CS_INACTIVE(true, NS_CHATSTATE, "inactive");
+const QName QN_CS_GONE(true, NS_CHATSTATE, "gone");
+
+// JEP 0091 Delayed Delivery
+const std::string kNSDelay("jabber:x:delay");
+const QName kQnDelayX(true, kNSDelay, "x");
+const QName kQnStamp(true, STR_EMPTY, "stamp");
+
+// Google time stamping (higher resolution)
+const std::string kNSTimestamp("google:timestamp");
+const QName kQnTime(true, kNSTimestamp, "time");
+const QName kQnMilliseconds(true, STR_EMPTY, "ms");
+
+
+
+// Jingle Info
+const std::string NS_JINGLE_INFO("google:jingleinfo");
+const QName QN_JINGLE_INFO_QUERY(true, NS_JINGLE_INFO, "query");
+const QName QN_JINGLE_INFO_STUN(true, NS_JINGLE_INFO, "stun");
+const QName QN_JINGLE_INFO_RELAY(true, NS_JINGLE_INFO, "relay");
+const QName QN_JINGLE_INFO_SERVER(true, NS_JINGLE_INFO, "server");
+const QName QN_JINGLE_INFO_TOKEN(true, NS_JINGLE_INFO, "token");
+const QName QN_JINGLE_INFO_HOST(true, STR_EMPTY, "host");
+const QName QN_JINGLE_INFO_TCP(true, STR_EMPTY, "tcp");
+const QName QN_JINGLE_INFO_UDP(true, STR_EMPTY, "udp");
+const QName QN_JINGLE_INFO_TCPSSL(true, STR_EMPTY, "tcpssl");
+
+}
diff --git a/talk/xmpp/constants.h b/talk/xmpp/constants.h
new file mode 100755
index 0000000..2f06f75
--- /dev/null
+++ b/talk/xmpp/constants.h
@@ -0,0 +1,358 @@
+/*
+ * 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 _CRICKET_XMPP_XMPPLIB_BUZZ_CONSTANTS_H_
+#define _CRICKET_XMPP_XMPPLIB_BUZZ_CONSTANTS_H_
+
+#include <string>
+#include "talk/xmllite/qname.h"
+#include "talk/xmpp/jid.h"
+
+
+#define NS_CLIENT Constants::ns_client()
+#define NS_SERVER Constants::ns_server()
+#define NS_STREAM Constants::ns_stream()
+#define NS_XSTREAM Constants::ns_xstream()
+#define NS_TLS Constants::ns_tls()
+#define NS_SASL Constants::ns_sasl()
+#define NS_BIND Constants::ns_bind()
+#define NS_DIALBACK Constants::ns_dialback()
+#define NS_SESSION Constants::ns_session()
+#define NS_STANZA Constants::ns_stanza()
+#define NS_PRIVACY Constants::ns_privacy()
+#define NS_ROSTER Constants::ns_roster()
+#define NS_VCARD Constants::ns_vcard()
+#define NS_AVATAR_HASH Constants::ns_avatar_hash()
+#define NS_VCARD_UPDATE Constants::ns_vcard_update()
+#define STR_CLIENT Constants::str_client()
+#define STR_SERVER Constants::str_server()
+#define STR_STREAM Constants::str_stream()
+
+
+namespace buzz {
+
+extern const Jid JID_EMPTY;
+
+class Constants {
+ public:
+  static const std::string & ns_client();
+  static const std::string & ns_server();
+  static const std::string & ns_stream();
+  static const std::string & ns_xstream();
+  static const std::string & ns_tls();
+  static const std::string & ns_sasl();
+  static const std::string & ns_bind();
+  static const std::string & ns_dialback();
+  static const std::string & ns_session();
+  static const std::string & ns_stanza();
+  static const std::string & ns_privacy();
+  static const std::string & ns_roster();
+  static const std::string & ns_vcard();
+  static const std::string & ns_avatar_hash();
+  static const std::string & ns_vcard_update();
+
+  static const std::string & str_client();
+  static const std::string & str_server();
+  static const std::string & str_stream();
+};
+
+extern const std::string STR_GET;
+extern const std::string STR_SET;
+extern const std::string STR_RESULT;
+extern const std::string STR_ERROR;
+
+
+extern const std::string STR_FROM;
+extern const std::string STR_TO;
+extern const std::string STR_BOTH;
+extern const std::string STR_REMOVE;
+
+extern const std::string STR_MESSAGE;
+extern const std::string STR_BODY;
+extern const std::string STR_PRESENCE;
+extern const std::string STR_STATUS;
+extern const std::string STR_SHOW;
+extern const std::string STR_PRIOIRTY;
+extern const std::string STR_IQ;
+
+extern const std::string STR_TYPE;
+extern const std::string STR_NAME;
+extern const std::string STR_ID;
+extern const std::string STR_JID;
+extern const std::string STR_SUBSCRIPTION;
+extern const std::string STR_ASK;
+extern const std::string STR_X;
+extern const std::string STR_GOOGLE_COM;
+extern const std::string STR_GMAIL_COM;
+extern const std::string STR_GOOGLEMAIL_COM;
+extern const std::string STR_DEFAULT_DOMAIN;
+extern const std::string STR_TALK_GOOGLE_COM;
+extern const std::string STR_TALKX_L_GOOGLE_COM;
+
+#ifdef FEATURE_ENABLE_VOICEMAIL
+extern const std::string STR_VOICEMAIL;
+extern const std::string STR_OUTGOINGVOICEMAIL;
+#endif
+
+extern const std::string STR_UNAVAILABLE;
+
+extern const QName QN_STREAM_STREAM;
+extern const QName QN_STREAM_FEATURES;
+extern const QName QN_STREAM_ERROR;
+
+extern const QName QN_XSTREAM_BAD_FORMAT;
+extern const QName QN_XSTREAM_BAD_NAMESPACE_PREFIX;
+extern const QName QN_XSTREAM_CONFLICT;
+extern const QName QN_XSTREAM_CONNECTION_TIMEOUT;
+extern const QName QN_XSTREAM_HOST_GONE;
+extern const QName QN_XSTREAM_HOST_UNKNOWN;
+extern const QName QN_XSTREAM_IMPROPER_ADDRESSIING;
+extern const QName QN_XSTREAM_INTERNAL_SERVER_ERROR;
+extern const QName QN_XSTREAM_INVALID_FROM;
+extern const QName QN_XSTREAM_INVALID_ID;
+extern const QName QN_XSTREAM_INVALID_NAMESPACE;
+extern const QName QN_XSTREAM_INVALID_XML;
+extern const QName QN_XSTREAM_NOT_AUTHORIZED;
+extern const QName QN_XSTREAM_POLICY_VIOLATION;
+extern const QName QN_XSTREAM_REMOTE_CONNECTION_FAILED;
+extern const QName QN_XSTREAM_RESOURCE_CONSTRAINT;
+extern const QName QN_XSTREAM_RESTRICTED_XML;
+extern const QName QN_XSTREAM_SEE_OTHER_HOST;
+extern const QName QN_XSTREAM_SYSTEM_SHUTDOWN;
+extern const QName QN_XSTREAM_UNDEFINED_CONDITION;
+extern const QName QN_XSTREAM_UNSUPPORTED_ENCODING;
+extern const QName QN_XSTREAM_UNSUPPORTED_STANZA_TYPE;
+extern const QName QN_XSTREAM_UNSUPPORTED_VERSION;
+extern const QName QN_XSTREAM_XML_NOT_WELL_FORMED;
+extern const QName QN_XSTREAM_TEXT;
+
+extern const QName QN_TLS_STARTTLS;
+extern const QName QN_TLS_REQUIRED;
+extern const QName QN_TLS_PROCEED;
+extern const QName QN_TLS_FAILURE;
+
+extern const QName QN_SASL_MECHANISMS;
+extern const QName QN_SASL_MECHANISM;
+extern const QName QN_SASL_AUTH;
+extern const QName QN_SASL_CHALLENGE;
+extern const QName QN_SASL_RESPONSE;
+extern const QName QN_SASL_ABORT;
+extern const QName QN_SASL_SUCCESS;
+extern const QName QN_SASL_FAILURE;
+extern const QName QN_SASL_ABORTED;
+extern const QName QN_SASL_INCORRECT_ENCODING;
+extern const QName QN_SASL_INVALID_AUTHZID;
+extern const QName QN_SASL_INVALID_MECHANISM;
+extern const QName QN_SASL_MECHANISM_TOO_WEAK;
+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;
+
+extern const QName QN_STANZA_BAD_REQUEST;
+extern const QName QN_STANZA_CONFLICT;
+extern const QName QN_STANZA_FEATURE_NOT_IMPLEMENTED;
+extern const QName QN_STANZA_FORBIDDEN;
+extern const QName QN_STANZA_GONE;
+extern const QName QN_STANZA_INTERNAL_SERVER_ERROR;
+extern const QName QN_STANZA_ITEM_NOT_FOUND;
+extern const QName QN_STANZA_JID_MALFORMED;
+extern const QName QN_STANZA_NOT_ACCEPTABLE;
+extern const QName QN_STANZA_NOT_ALLOWED;
+extern const QName QN_STANZA_PAYMENT_REQUIRED;
+extern const QName QN_STANZA_RECIPIENT_UNAVAILABLE;
+extern const QName QN_STANZA_REDIRECT;
+extern const QName QN_STANZA_REGISTRATION_REQUIRED;
+extern const QName QN_STANZA_REMOTE_SERVER_NOT_FOUND;
+extern const QName QN_STANZA_REMOTE_SERVER_TIMEOUT;
+extern const QName QN_STANZA_RESOURCE_CONSTRAINT;
+extern const QName QN_STANZA_SERVICE_UNAVAILABLE;
+extern const QName QN_STANZA_SUBSCRIPTION_REQUIRED;
+extern const QName QN_STANZA_UNDEFINED_CONDITION;
+extern const QName QN_STANZA_UNEXPECTED_REQUEST;
+extern const QName QN_STANZA_TEXT;
+
+extern const QName QN_BIND_BIND;
+extern const QName QN_BIND_RESOURCE;
+extern const QName QN_BIND_JID;
+
+extern const QName QN_MESSAGE;
+extern const QName QN_BODY;
+extern const QName QN_SUBJECT;
+extern const QName QN_THREAD;
+extern const QName QN_PRESENCE;
+extern const QName QN_SHOW;
+extern const QName QN_STATUS;
+extern const QName QN_LANG;
+extern const QName QN_PRIORITY;
+extern const QName QN_IQ;
+extern const QName QN_ERROR;
+
+extern const QName QN_SERVER_MESSAGE;
+extern const QName QN_SERVER_BODY;
+extern const QName QN_SERVER_SUBJECT;
+extern const QName QN_SERVER_THREAD;
+extern const QName QN_SERVER_PRESENCE;
+extern const QName QN_SERVER_SHOW;
+extern const QName QN_SERVER_STATUS;
+extern const QName QN_SERVER_LANG;
+extern const QName QN_SERVER_PRIORITY;
+extern const QName QN_SERVER_IQ;
+extern const QName QN_SERVER_ERROR;
+
+extern const QName QN_SESSION_SESSION;
+
+extern const QName QN_PRIVACY_QUERY;
+extern const QName QN_PRIVACY_ACTIVE;
+extern const QName QN_PRIVACY_DEFAULT;
+extern const QName QN_PRIVACY_LIST;
+extern const QName QN_PRIVACY_ITEM;
+extern const QName QN_PRIVACY_IQ;
+extern const QName QN_PRIVACY_MESSAGE;
+extern const QName QN_PRIVACY_PRESENCE_IN;
+extern const QName QN_PRIVACY_PRESENCE_OUT;
+
+extern const QName QN_ROSTER_QUERY;
+extern const QName QN_ROSTER_ITEM;
+extern const QName QN_ROSTER_GROUP;
+
+extern const QName QN_VCARD;
+extern const QName QN_VCARD_FN;
+extern const QName QN_VCARD_PHOTO;
+extern const QName QN_VCARD_PHOTO_BINVAL;
+extern const QName QN_VCARD_AVATAR_HASH;
+extern const QName QN_VCARD_AVATAR_HASH_MODIFIED;
+
+
+extern const QName QN_XML_LANG;
+
+extern const QName QN_ENCODING;
+extern const QName QN_VERSION;
+extern const QName QN_TO;
+extern const QName QN_FROM;
+extern const QName QN_TYPE;
+extern const QName QN_ID;
+extern const QName QN_CODE;
+extern const QName QN_NAME;
+extern const QName QN_VALUE;
+extern const QName QN_ACTION;
+extern const QName QN_ORDER;
+extern const QName QN_MECHANISM;
+extern const QName QN_ASK;
+extern const QName QN_JID;
+extern const QName QN_SUBSCRIPTION;
+extern const QName QN_TITLE1;
+extern const QName QN_TITLE2;
+
+
+extern const QName QN_XMLNS_CLIENT;
+extern const QName QN_XMLNS_SERVER;
+extern const QName QN_XMLNS_STREAM;
+
+// Presence
+extern const std::string STR_SHOW_AWAY;
+extern const std::string STR_SHOW_CHAT;
+extern const std::string STR_SHOW_DND;
+extern const std::string STR_SHOW_XA;
+extern const std::string STR_SHOW_OFFLINE;
+
+// Subscription
+extern const std::string STR_SUBSCRIBE;
+extern const std::string STR_SUBSCRIBED;
+extern const std::string STR_UNSUBSCRIBE;
+extern const std::string STR_UNSUBSCRIBED;
+
+
+// JEP 0030
+extern const QName QN_NODE;
+extern const QName QN_CATEGORY;
+extern const QName QN_VAR;
+extern const std::string NS_DISCO_INFO;
+extern const std::string NS_DISCO_ITEMS;
+
+extern const QName QN_DISCO_INFO_QUERY;
+extern const QName QN_DISCO_IDENTITY;
+extern const QName QN_DISCO_FEATURE;
+
+extern const QName QN_DISCO_ITEMS_QUERY;
+extern const QName QN_DISCO_ITEM;
+
+
+// JEP 0115
+extern const std::string NS_CAPS;
+extern const QName QN_CAPS_C;
+extern const QName QN_VER;
+extern const QName QN_EXT;
+
+
+// Avatar - JEP 0153
+extern const std::string kNSVCard;
+extern const QName kQnVCardX;
+extern const QName kQnVCardPhoto;
+
+// JEP 0172 User Nickname
+extern const std::string kNSNickname;
+extern const QName kQnNickname;
+
+
+// JEP 0085 chat state
+extern const std::string NS_CHATSTATE;
+extern const QName QN_CS_ACTIVE;
+extern const QName QN_CS_COMPOSING;
+extern const QName QN_CS_PAUSED;
+extern const QName QN_CS_INACTIVE;
+extern const QName QN_CS_GONE;
+
+// JEP 0091 Delayed Delivery
+extern const std::string kNSDelay;
+extern const QName kQnDelayX;
+extern const QName kQnStamp;
+
+// Google time stamping (higher resolution)
+extern const std::string kNSTimestamp;
+extern const QName kQnTime;
+extern const QName kQnMilliseconds;
+
+
+extern const std::string NS_JINGLE_INFO;
+extern const QName QN_JINGLE_INFO_QUERY;
+extern const QName QN_JINGLE_INFO_STUN;
+extern const QName QN_JINGLE_INFO_RELAY;
+extern const QName QN_JINGLE_INFO_SERVER;
+extern const QName QN_JINGLE_INFO_TOKEN;
+extern const QName QN_JINGLE_INFO_HOST;
+extern const QName QN_JINGLE_INFO_TCP;
+extern const QName QN_JINGLE_INFO_UDP;
+extern const QName QN_JINGLE_INFO_TCPSSL;
+
+}
+
+#endif // _CRICKET_XMPP_XMPPLIB_BUZZ_CONSTANTS_H_
diff --git a/talk/xmpp/jid.cc b/talk/xmpp/jid.cc
new file mode 100755
index 0000000..ead2074
--- /dev/null
+++ b/talk/xmpp/jid.cc
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ */
+
+extern "C" {
+#include <ctype.h>
+}
+#include <string>
+#include "talk/xmpp/jid.h"
+#include "talk/xmpp/constants.h"
+#include "talk/base/common.h"
+#include <algorithm>
+#include "talk/base/logging.h"
+
+namespace buzz {
+
+static int AsciiToLower(int x) {
+  return (x <= 'Z' && x >= 'A') ? (x + ('a' - 'A')) : x;
+}
+
+Jid::Jid() : data_(NULL) {
+}
+
+Jid::Jid(bool is_special, const std::string & special) {
+  data_ = is_special ? new Data(special, STR_EMPTY, STR_EMPTY) : NULL;
+}
+
+Jid::Jid(const std::string & jid_string) {
+  if (jid_string == STR_EMPTY) {
+    data_ = NULL;
+    return;
+  }
+
+  // First find the slash and slice of that part
+  size_t slash = jid_string.find('/');
+  std::string resource_name = (slash == std::string::npos ? STR_EMPTY :
+                    jid_string.substr(slash + 1));
+
+  // Now look for the node
+  std::string node_name;
+  size_t at = jid_string.find('@');
+  size_t domain_begin;
+  if (at < slash && at != std::string::npos) {
+    node_name = jid_string.substr(0, at);
+    domain_begin = at + 1;
+  } else {
+    domain_begin = 0;
+  }
+
+  // Now take what is left as the domain
+  size_t domain_length =
+    (  slash == std::string::npos
+     ? jid_string.length() - domain_begin
+     : slash - domain_begin);
+
+  // avoid allocating these constants repeatedly
+  std::string domain_name;
+
+  if (domain_length == 9  && jid_string.find("gmail.com", domain_begin) == domain_begin) {
+    domain_name = STR_GMAIL_COM;
+  }
+  else if (domain_length == 14 && jid_string.find("googlemail.com", domain_begin) == domain_begin) {
+    domain_name = STR_GOOGLEMAIL_COM;
+  }
+  else if (domain_length == 10 && jid_string.find("google.com", domain_begin) == domain_begin) {
+    domain_name = STR_GOOGLE_COM;
+  }
+  else {
+    domain_name = jid_string.substr(domain_begin, domain_length);
+  }
+
+  // If the domain is empty we have a non-valid jid and we should empty
+  // everything else out
+  if (domain_name.empty()) {
+    data_ = NULL;
+    return;
+  }
+  
+  bool valid_node;
+  std::string validated_node = prepNode(node_name, 
+      node_name.begin(), node_name.end(), &valid_node);
+  bool valid_domain;
+  std::string validated_domain = prepDomain(domain_name,
+      domain_name.begin(), domain_name.end(), &valid_domain);
+  bool valid_resource;
+  std::string validated_resource = prepResource(resource_name,
+      resource_name.begin(), resource_name.end(), &valid_resource);
+
+  if (!valid_node || !valid_domain || !valid_resource) {
+    data_ = NULL;
+    return;
+  }
+
+  data_ = new Data(validated_node, validated_domain, validated_resource);
+}
+
+Jid::Jid(const std::string & node_name,
+         const std::string & domain_name,
+         const std::string & resource_name) {
+  if (domain_name.empty()) {
+    data_ = NULL;
+    return;
+  }
+
+  bool valid_node;
+  std::string validated_node = prepNode(node_name, 
+      node_name.begin(), node_name.end(), &valid_node);
+  bool valid_domain;
+  std::string validated_domain = prepDomain(domain_name,
+      domain_name.begin(), domain_name.end(), &valid_domain);
+  bool valid_resource;
+  std::string validated_resource = prepResource(resource_name,
+      resource_name.begin(), resource_name.end(), &valid_resource);
+
+  if (!valid_node || !valid_domain || !valid_resource) {
+    data_ = NULL;
+    return;
+  }
+
+  data_ = new Data(validated_node, validated_domain, validated_resource);
+}
+
+std::string Jid::Str() const {
+  if (!IsValid())
+    return STR_EMPTY;
+
+  std::string ret;
+
+  if (!data_->node_name_.empty())
+    ret = data_->node_name_ + "@";
+
+  ASSERT(data_->domain_name_ != STR_EMPTY);
+  ret += data_->domain_name_;
+
+  if (!data_->resource_name_.empty())
+    ret += "/" + data_->resource_name_;
+
+  return ret;
+}
+
+bool
+Jid::IsValid() const {
+  return data_ != NULL && !data_->domain_name_.empty();
+}
+
+bool
+Jid::IsBare() const {
+  if (Compare(JID_EMPTY) == 0) {
+    LOG(LS_VERBOSE) << "Warning: Calling IsBare() on the empty jid";
+    return true;
+  }
+  return IsValid() &&
+         data_->resource_name_.empty();
+}
+
+bool
+Jid::IsFull() const {
+  return IsValid() &&
+         !data_->resource_name_.empty();
+}
+
+Jid
+Jid::BareJid() const {
+  if (!IsValid())
+    return Jid();
+  if (!IsFull())
+    return *this;
+  return Jid(data_->node_name_, data_->domain_name_, STR_EMPTY);
+}
+
+#if 0
+void
+Jid::set_node(const std::string & node_name) {
+    data_->node_name_ = node_name;
+}
+void
+Jid::set_domain(const std::string & domain_name) {
+    data_->domain_name_ = domain_name;
+}
+void
+Jid::set_resource(const std::string & res_name) {
+    data_->resource_name_ = res_name;
+}
+#endif
+
+bool
+Jid::BareEquals(const Jid & other) const {
+  return (other.data_ == data_ ||
+          data_ != NULL &&
+          other.data_ != NULL &&
+          other.data_->node_name_ == data_->node_name_ &&
+          other.data_->domain_name_ == data_->domain_name_);
+}
+
+bool
+Jid::operator==(const Jid & other) const {
+  return (other.data_ == data_ ||
+          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_);
+}
+
+int
+Jid::Compare(const Jid & other) const {
+  if (other.data_ == data_)
+    return 0;
+  if (data_ == NULL)
+    return -1;
+  if (other.data_ == NULL)
+    return 1;
+  
+  int compare_result;
+  compare_result = data_->node_name_.compare(other.data_->node_name_);
+  if (0 != compare_result)
+    return compare_result;
+  compare_result = data_->domain_name_.compare(other.data_->domain_name_);
+  if (0 != compare_result)
+    return compare_result;
+  compare_result = data_->resource_name_.compare(other.data_->resource_name_);
+  return compare_result;
+}
+
+uint32 Jid::ComputeLameHash() const {
+  uint32 hash = 0;
+  // Hash the node portion
+  {
+    const std::string &str = node();
+    for (int i = 0; i < static_cast<int>(str.size()); ++i) {
+      hash = ((hash << 2) + hash) + str[i];
+    }
+  }
+
+  // Hash the domain portion
+  {
+    const std::string &str = domain();
+    for (int i = 0; i < static_cast<int>(str.size()); ++i)
+      hash = ((hash << 2) + hash) + str[i];
+  }
+
+  // Hash the resource portion
+  {
+    const std::string &str = resource();
+    for (int i = 0; i < static_cast<int>(str.size()); ++i)
+      hash = ((hash << 2) + hash) + str[i];
+  }
+
+  return hash;
+}
+
+// --- JID parsing code: ---
+
+// Checks and normalizes the node part of a JID.
+std::string
+Jid::prepNode(const std::string str, std::string::const_iterator start, 
+    std::string::const_iterator end, bool *valid) {
+  *valid = false;
+  std::string result;
+
+  for (std::string::const_iterator i = start; i < end; i++) {
+    bool char_valid = true;
+    unsigned char ch = *i;
+    if (ch <= 0x7F) {
+      result += prepNodeAscii(ch, &char_valid);
+    }
+    else {
+      // TODO: implement the correct stringprep protocol for these
+      result += tolower(ch);
+    }
+    if (!char_valid) {
+      return STR_EMPTY;
+    }
+  }
+
+  if (result.length() > 1023) {
+    return STR_EMPTY;
+  }
+  *valid = true;
+  return result;
+}
+
+
+// Returns the appropriate mapping for an ASCII character in a node.
+char
+Jid::prepNodeAscii(char ch, bool *valid) {
+  *valid = true;
+  switch (ch) {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
+    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
+    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
+    case 'V': case 'W': case 'X': case 'Y': case 'Z':
+      return (char)(ch + ('a' - 'A'));
+
+    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
+    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
+    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
+    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+    case ' ': case '&': case '/': case ':': case '<': case '>': case '@':
+    case '\"': case '\'':
+    case 0x7F:
+      *valid = false;
+      return 0;
+
+    default:
+      return ch;
+  }
+}
+
+
+// Checks and normalizes the resource part of a JID.
+std::string
+Jid::prepResource(const std::string str, std::string::const_iterator start, 
+    std::string::const_iterator end, bool *valid) {
+  *valid = false;
+  std::string result;
+
+  for (std::string::const_iterator i = start; i < end; i++) {
+    bool char_valid = true;
+    unsigned char ch = *i;
+    if (ch <= 0x7F) {
+      result += prepResourceAscii(ch, &char_valid);
+    }
+    else {
+      // TODO: implement the correct stringprep protocol for these
+      result += ch;
+    }
+  }
+
+  if (result.length() > 1023) {
+    return STR_EMPTY;
+  }
+  *valid = true;
+  return result;
+}
+
+// Returns the appropriate mapping for an ASCII character in a resource.
+char
+Jid::prepResourceAscii(char ch, bool *valid) {
+  *valid = true;
+  switch (ch) {
+    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
+    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
+    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
+    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+    case 0x7F:
+      *valid = false;
+      return 0;
+
+    default:
+      return ch;
+  }
+}
+
+// Checks and normalizes the domain part of a JID.
+std::string 
+Jid::prepDomain(const std::string str, std::string::const_iterator start, 
+    std::string::const_iterator end, bool *valid) {
+  *valid = false;
+  std::string result;
+
+  // TODO: if the domain contains a ':', then we should parse it
+  // as an IPv6 address rather than giving an error about illegal domain.
+  prepDomain(str, start, end, &result, valid);
+  if (!*valid) {
+    return STR_EMPTY;
+  }
+
+  if (result.length() > 1023) {
+    return STR_EMPTY;
+  }
+  *valid = true;
+  return result;
+}
+
+
+// Checks and normalizes an IDNA domain.
+void
+Jid::prepDomain(const std::string str, std::string::const_iterator start, 
+    std::string::const_iterator end, std::string *buf, bool *valid) {
+  *valid = false;
+  std::string::const_iterator last = start;
+  for (std::string::const_iterator i = start; i < end; i++) {
+    bool label_valid = true;
+    char ch = *i;
+    switch (ch) {
+      case 0x002E:
+#if 0 // FIX: This isn't UTF-8-aware.
+      case 0x3002:
+      case 0xFF0E:
+      case 0xFF61:
+#endif
+        prepDomainLabel(str, last, i, buf, &label_valid);
+        *buf += '.';
+        last = i + 1;
+        break;
+    }
+    if (!label_valid) {
+      return;
+    }
+  }
+  prepDomainLabel(str, last, end, buf, valid);
+}
+
+// Checks and normalizes a domain label.
+void
+Jid::prepDomainLabel(const std::string str, std::string::const_iterator start, 
+    std::string::const_iterator end, std::string *buf, bool *valid) {
+  *valid = false;
+
+  int startLen = buf->length();
+  for (std::string::const_iterator i = start; i < end; i++) {
+    bool char_valid = true;
+    unsigned char ch = *i;
+    if (ch <= 0x7F) {
+      *buf += prepDomainLabelAscii(ch, &char_valid);
+    }
+    else {
+      // TODO: implement ToASCII for these
+      *buf += ch;
+    }
+    if (!char_valid) {
+      return;
+    }
+  }
+
+  int count = buf->length() - startLen;
+  if (count == 0) {
+    return;
+  }
+  else if (count > 63) {
+    return;
+  }
+
+  // Is this check needed? See comment in prepDomainLabelAscii.
+  if ((*buf)[startLen] == '-') {
+    return;
+  }
+  if ((*buf)[buf->length() - 1] == '-') {
+    return;
+  }
+  *valid = true;
+}
+
+
+// Returns the appropriate mapping for an ASCII character in a domain label.
+char
+Jid::prepDomainLabelAscii(char ch, bool *valid) {
+  *valid = true;
+  // TODO: A literal reading of the spec seems to say that we do
+  // not need to check for these illegal characters (an "internationalized
+  // domain label" runs ToASCII with UseSTD3... set to false).  But that
+  // can't be right.  We should at least be checking that there are no '/'
+  // or '@' characters in the domain.  Perhaps we should see what others
+  // do in this case.
+
+  switch (ch) {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
+    case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
+    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
+    case 'V': case 'W': case 'X': case 'Y': case 'Z':
+      return (char)(ch + ('a' - 'A'));
+
+    case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
+    case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B:
+    case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11:
+    case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+    case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D:
+    case 0x1E: case 0x1F: case 0x20: case 0x21: case 0x22: case 0x23:
+    case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29:
+    case 0x2A: case 0x2B: case 0x2C: case 0x2E: case 0x2F: case 0x3A:
+    case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: case 0x40:
+    case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: case 0x60:
+    case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
+      *valid = false;
+      return 0;
+
+    default:
+      return ch;
+  }
+}
+
+}
diff --git a/talk/xmpp/jid.h b/talk/xmpp/jid.h
new file mode 100755
index 0000000..6831bda
--- /dev/null
+++ b/talk/xmpp/jid.h
@@ -0,0 +1,148 @@
+/*
+ * 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 _jid_h_
+#define _jid_h_
+
+#include <string>
+#include "talk/base/basictypes.h"
+#include "talk/xmllite/xmlconstants.h"
+
+namespace buzz {
+
+//! The Jid class encapsulates and provides parsing help for Jids
+//! A Jid consists of three parts. The node, the domain and the resource.
+//!
+//! node@domain/resource
+//!
+//! The node and resource are both optional.  A valid jid is defined to have
+//! a domain.  A bare jid is defined to not have a resource and a full jid
+//! *does* have a resource.
+class Jid {
+public:
+  explicit Jid();
+  explicit Jid(const std::string & jid_string);
+  explicit Jid(const std::string & node_name,
+               const std::string & domain_name,
+               const std::string & resource_name);
+  explicit Jid(bool special, const std::string & special_string);
+  Jid(const Jid & jid) : data_(jid.data_) {
+    if (data_ != NULL) {
+      data_->AddRef();
+    }
+  }
+  Jid & operator=(const Jid & jid) {
+    if (jid.data_ != NULL) {
+      jid.data_->AddRef();
+    }
+    if (data_ != NULL) {
+      data_->Release();
+    }
+    data_ = jid.data_;
+    return *this;
+  }
+  ~Jid() {
+    if (data_ != NULL) {
+      data_->Release();
+    }
+  }
+  
+
+  const std::string & node() const { return !data_ ? STR_EMPTY : data_->node_name_; }
+  // void set_node(const std::string & node_name);
+  const std::string & domain() const { return !data_ ? STR_EMPTY : data_->domain_name_; }
+  // void set_domain(const std::string & domain_name);
+  const std::string & resource() const { return !data_ ? STR_EMPTY : data_->resource_name_; }
+  // void set_resource(const std::string & res_name);
+
+  std::string Str() const;
+  Jid BareJid() const;
+
+  bool IsValid() const;
+  bool IsBare() const;
+  bool IsFull() const;
+
+  bool BareEquals(const Jid & other) const;
+
+  bool operator==(const Jid & other) const;
+  bool operator!=(const Jid & other) const { return !operator==(other); }
+
+  bool operator<(const Jid & other) const { return Compare(other) < 0; };
+  bool operator>(const Jid & other) const { return Compare(other) > 0; };
+  
+  int Compare(const Jid & other) const;
+
+  // A quick and dirty hash.  Don't count on this producing a great 
+  // distribution.
+  uint32 ComputeLameHash() const;
+
+private:
+
+  static std::string prepNode(const std::string str, 
+      std::string::const_iterator start, std::string::const_iterator end, 
+      bool *valid);
+  static char prepNodeAscii(char ch, bool *valid);
+  static std::string prepResource(const std::string str, 
+      std::string::const_iterator start, std::string::const_iterator end, 
+      bool *valid);
+  static char prepResourceAscii(char ch, bool *valid);
+  static std::string prepDomain(const std::string str, 
+      std::string::const_iterator start,  std::string::const_iterator end, 
+      bool *valid);
+  static void prepDomain(const std::string str, 
+      std::string::const_iterator start, std::string::const_iterator end, 
+      std::string *buf, bool *valid);
+  static void prepDomainLabel(const std::string str, 
+      std::string::const_iterator start, std::string::const_iterator end, 
+      std::string *buf, bool *valid);
+  static char prepDomainLabelAscii(char ch, bool *valid);
+
+  class Data {
+  public:
+    Data() : refcount_(1) {}
+    Data(const std::string & node, const std::string &domain, const std::string & resource) :
+      node_name_(node),
+      domain_name_(domain),
+      resource_name_(resource),
+      refcount_(1) {}
+    const std::string node_name_;
+    const std::string domain_name_;
+    const std::string resource_name_;
+
+    void AddRef() { refcount_++; }
+    void Release() { if (!--refcount_) delete this; }
+  private:
+    int refcount_;
+  };
+
+  Data * data_;
+};
+
+}
+
+
+
+#endif
diff --git a/talk/xmpp/plainsaslhandler.h b/talk/xmpp/plainsaslhandler.h
new file mode 100755
index 0000000..e7d44b9
--- /dev/null
+++ b/talk/xmpp/plainsaslhandler.h
@@ -0,0 +1,80 @@
+/*
+ * 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 _PLAINSASLHANDLER_H_
+#define _PLAINSASLHANDLER_H_
+
+#include "talk/xmpp/saslhandler.h"
+#include <algorithm>
+
+namespace buzz {
+
+class PlainSaslHandler : public SaslHandler {
+public:
+  PlainSaslHandler(const Jid & jid, const talk_base::CryptString & password, 
+      bool allow_plain) : jid_(jid), password_(password), 
+                          allow_plain_(allow_plain) {}
+    
+  virtual ~PlainSaslHandler() {}
+
+  // Should pick the best method according to this handler
+  // returns the empty string if none are suitable
+  virtual std::string ChooseBestSaslMechanism(const std::vector<std::string> & mechanisms, bool encrypted) {
+  
+    if (!encrypted && !allow_plain_) {
+      return "";
+    }
+    
+    std::vector<std::string>::const_iterator it = std::find(mechanisms.begin(), mechanisms.end(), "PLAIN");
+    if (it == mechanisms.end()) {
+      return "";
+    }
+    else {
+      return "PLAIN";
+    }
+  }
+
+  // Creates a SaslMechanism for the given mechanism name (you own it
+  // once you get it).  If not handled, return NULL.
+  virtual SaslMechanism * CreateSaslMechanism(const std::string & mechanism) {
+    if (mechanism == "PLAIN") {
+      return new SaslPlainMechanism(jid_, password_);
+    }
+    return NULL;
+  }
+  
+private:
+  Jid jid_;
+  talk_base::CryptString password_;
+  bool allow_plain_;
+};
+
+
+}
+
+#endif
+
diff --git a/talk/xmpp/prexmppauth.h b/talk/xmpp/prexmppauth.h
new file mode 100755
index 0000000..f94bd3d
--- /dev/null
+++ b/talk/xmpp/prexmppauth.h
@@ -0,0 +1,86 @@
+/*
+ * 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 _PREXMPPAUTH_H_
+#define _PREXMPPAUTH_H_
+
+#include "talk/base/cryptstring.h"
+#include "talk/base/sigslot.h"
+#include "talk/xmpp/saslhandler.h"
+
+namespace talk_base {
+  class SocketAddress;
+}
+
+namespace buzz {
+
+class Jid;
+class SaslMechanism;
+
+class CaptchaChallenge {
+ public:
+  CaptchaChallenge() : captcha_needed_(false) {}
+  CaptchaChallenge(const std::string& token, const std::string& url) 
+    : captcha_needed_(true), captcha_token_(token), captcha_image_url_(url) {
+  }
+
+  bool captcha_needed() const { return captcha_needed_; }
+  const std::string& captcha_token() const { return captcha_token_; }
+
+  // This url is relative to the gaia server.  Once we have better tools
+  // for cracking URLs, we should probably make this a full URL
+  const std::string& captcha_image_url() const { return captcha_image_url_; }
+
+ private:
+  bool captcha_needed_;
+  std::string captcha_token_;
+  std::string captcha_image_url_;
+};
+
+class PreXmppAuth : public SaslHandler {
+public:
+  virtual ~PreXmppAuth() {}
+  
+  virtual void StartPreXmppAuth(
+    const Jid & jid,
+    const talk_base::SocketAddress & server,
+    const talk_base::CryptString & pass,
+    const std::string & auth_cookie) = 0;
+  
+  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;
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/ratelimitmanager.cc b/talk/xmpp/ratelimitmanager.cc
new file mode 100755
index 0000000..81c55ac
--- /dev/null
+++ b/talk/xmpp/ratelimitmanager.cc
@@ -0,0 +1,77 @@
+/*
+ * 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/xmpp/ratelimitmanager.h"
+
+namespace buzz {
+
+RateLimitManager::RateLimit* RateLimitManager::GetRateLimit(
+    const std::string event_name) {
+  RateLimitMap::iterator it = rate_limits_.find(event_name);
+  if (it != rate_limits_.end()) {
+    return it->second;
+  }
+  return NULL;
+}
+
+bool RateLimitManager::IsWithinRateLimit(const std::string event_name) {
+  RateLimit* current_rate = GetRateLimit(event_name);
+  if (current_rate) {
+    return current_rate->IsWithinRateLimit();
+  }
+  return true; // If no rate limit is set, then you must be under the limit
+}
+
+void RateLimitManager::UpdateRateLimit(const std::string event_name, 
+                                       int max_count, 
+                                       int per_x_seconds) {
+  RateLimit* current_rate = GetRateLimit(event_name);
+  if (!current_rate) {
+    current_rate = new RateLimit(max_count, per_x_seconds);
+    rate_limits_[event_name] = current_rate;
+  }
+  current_rate->UpdateRateLimit();
+}                            
+
+bool RateLimitManager::VerifyRateLimit(const std::string event_name, 
+                                       int max_count, 
+                                       int per_x_seconds) {
+  return VerifyRateLimit(event_name, max_count, per_x_seconds, false);
+}
+
+bool RateLimitManager::VerifyRateLimit(const std::string event_name, 
+                                       int max_count, 
+                                       int per_x_seconds, 
+                                       bool always_update) {
+  bool within_rate_limit = IsWithinRateLimit(event_name);
+  if (within_rate_limit || always_update) {
+    UpdateRateLimit(event_name, max_count, per_x_seconds);
+  }
+  return within_rate_limit;
+}
+
+}
diff --git a/talk/xmpp/ratelimitmanager.h b/talk/xmpp/ratelimitmanager.h
new file mode 100755
index 0000000..79960d8
--- /dev/null
+++ b/talk/xmpp/ratelimitmanager.h
@@ -0,0 +1,146 @@
+/*
+ * 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 _RATELIMITMANAGER_H_
+#define _RATELIMITMANAGER_H_
+
+#include "talk/base/time.h"
+#include "talk/base/taskrunner.h"
+#include <map>
+
+namespace buzz {
+
+/////////////////////////////////////////////////////////////////////
+//
+// RATELIMITMANAGER
+//
+/////////////////////////////////////////////////////////////////////
+//
+// RateLimitManager imposes client-side rate limiting for xmpp tasks and
+// other events.  It ensures that no more than i events with a given name 
+// can occur within k seconds. 
+//
+// A buffer tracks the previous max_count events.  Before an event is allowed
+// to occur, it can check its rate limit with a call to VerifyRateLimit.  
+// VerifyRateLimit will look up the i-th to last event and if more than
+// k seconds have passed since then, it will return true and update the 
+// appropriate rate limits.  Else, it will return false. 
+//
+/////////////////////////////////////////////////////////////////////
+
+class RateLimitManager {
+ public:
+
+  RateLimitManager() { };
+  ~RateLimitManager() { 
+    for (RateLimitMap::iterator it = rate_limits_.begin();
+         it != rate_limits_.end(); ++it) {
+      delete it->second;
+    }
+  };
+
+  // Checks if the event is under the defined rate limit and updates the
+  // rate limit if so.  Returns true if it's under the rate limit.
+  bool VerifyRateLimit(const std::string event_name, int max_count, 
+                       int per_x_seconds);
+
+  // Checks if the event is under the defined rate limit and updates the
+  // rate limit if so *or* if always_update = true.  
+  bool VerifyRateLimit(const std::string event_name, int max_count, 
+                       int per_x_seconds, bool always_update);
+
+ private:
+  class RateLimit {
+   public:
+    RateLimit(int max, int per_x_secs) : counter_(0), max_count_(max),
+                                         per_x_seconds_(per_x_secs) {
+      event_times_ = new uint32[max_count_];                                                 
+      for (int i = 0; i < max_count_; i++) {
+        event_times_[i] = 0;
+      }
+    }
+
+    ~RateLimit() {
+      if (event_times_) {
+        delete[] event_times_;
+      }
+    }
+
+    // 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;
+      }
+    }
+    
+    // Updates time and counter for rate limit
+    void UpdateRateLimit() {
+      event_times_[counter_] = talk_base::Time();
+      counter_ = (counter_ + 1) % max_count_;
+    }
+
+   private:
+
+    // The time at which the i-th (where i = max_count) event occured
+    uint32 PreviousTimeAtCounter() {
+      return event_times_[counter_];
+    }
+
+    // The time that the next event is allowed to occur
+    uint32 NextTimeAllowedForCounter() {
+      return PreviousTimeAtCounter() + per_x_seconds_ * talk_base::kSecToMsec;
+    }
+
+    int counter_; // count modulo max_count of the current event
+    int max_count_; // max number of events that can occur within per_x_seconds
+    int per_x_seconds_; // interval size for rate limit
+    uint32* event_times_; // buffer of previous max_count event
+  };
+
+  typedef std::map<const std::string, RateLimit*> RateLimitMap;
+
+  // Maps from event name to its rate limit
+  RateLimitMap rate_limits_;
+
+  // Returns rate limit for event with specified name
+  RateLimit* GetRateLimit(const std::string event_name);
+
+  // True iff the current time >= to the next song allowed time
+  bool IsWithinRateLimit(const std::string event_name);
+
+  // Updates time and counter for rate limit
+  void UpdateRateLimit(const std::string event_name, int max_count, 
+                       int per_x_seconds); 
+
+};
+
+}
+
+#endif //_RATELIMITMANAGER_H_
diff --git a/talk/xmpp/saslcookiemechanism.h b/talk/xmpp/saslcookiemechanism.h
new file mode 100755
index 0000000..a6630d9
--- /dev/null
+++ b/talk/xmpp/saslcookiemechanism.h
@@ -0,0 +1,67 @@
+/*
+ * 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 _SASLCOOKIEMECHANISM_H_
+#define _SASLCOOKIEMECHANISM_H_
+
+#include "talk/xmpp/saslmechanism.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/constants.h"
+
+namespace buzz {
+
+class SaslCookieMechanism : public SaslMechanism {
+
+public:
+  SaslCookieMechanism(const std::string & mechanism, const std::string & username, const std::string & cookie) :
+    mechanism_(mechanism), username_(username), cookie_(cookie) {}
+
+  virtual std::string GetMechanismName() { return mechanism_; }
+    
+  virtual XmlElement * StartSaslAuth() {
+    // send initial request
+    XmlElement * el = new XmlElement(QN_SASL_AUTH, true);
+    el->AddAttr(QN_MECHANISM, mechanism_);
+    
+    std::string credential;
+    credential.append("\0", 1);
+    credential.append(username_);
+    credential.append("\0", 1);
+    credential.append(cookie_);
+    el->AddText(Base64Encode(credential));
+    return el;
+  }
+  
+private:
+  std::string mechanism_;
+  std::string username_;
+  std::string cookie_;
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/saslhandler.h b/talk/xmpp/saslhandler.h
new file mode 100755
index 0000000..b57d3ba
--- /dev/null
+++ b/talk/xmpp/saslhandler.h
@@ -0,0 +1,59 @@
+/*
+ * 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 _SASLHANDLER_H_
+#define _SASLHANDLER_H_
+
+#include <string>
+
+namespace buzz {
+
+class XmlElement;
+class SaslMechanism;
+
+// Creates mechanisms to deal with a given mechanism
+class SaslHandler {
+
+public:
+  
+  // Intended to be subclassed
+  virtual ~SaslHandler() {}
+
+  // Should pick the best method according to this handler
+  // returns the empty string if none are suitable
+  virtual std::string ChooseBestSaslMechanism(const std::vector<std::string> & mechanisms, bool encrypted) = 0;
+
+  // Creates a SaslMechanism for the given mechanism name (you own it
+  // once you get it).
+  // If not handled, return NULL.
+  virtual SaslMechanism * CreateSaslMechanism(const std::string & mechanism) = 0;
+};
+
+}
+
+#endif
+
diff --git a/talk/xmpp/saslmechanism.cc b/talk/xmpp/saslmechanism.cc
new file mode 100755
index 0000000..45c947a
--- /dev/null
+++ b/talk/xmpp/saslmechanism.cc
@@ -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.
+ */
+
+#include "talk/base/base64.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/saslmechanism.h"
+
+using talk_base::Base64;
+
+namespace buzz {
+
+XmlElement *
+SaslMechanism::StartSaslAuth() {
+  return new XmlElement(QN_SASL_AUTH, true);
+}
+
+XmlElement *
+SaslMechanism::HandleSaslChallenge(const XmlElement * challenge) {
+  return new XmlElement(QN_SASL_ABORT, true);
+}
+
+void
+SaslMechanism::HandleSaslSuccess(const XmlElement * success) {
+}
+
+void
+SaslMechanism::HandleSaslFailure(const XmlElement * failure) {
+}
+
+std::string
+SaslMechanism::Base64Encode(const std::string & plain) {
+  return Base64::encode(plain);
+}
+
+std::string
+SaslMechanism::Base64Decode(const std::string & encoded) {
+  return Base64::decode(encoded);
+}
+
+std::string
+SaslMechanism::Base64EncodeFromArray(const char * plain, size_t length) {
+  return Base64::encodeFromArray(plain, length);
+}
+
+}
diff --git a/talk/xmpp/saslmechanism.h b/talk/xmpp/saslmechanism.h
new file mode 100755
index 0000000..f2e5adc
--- /dev/null
+++ b/talk/xmpp/saslmechanism.h
@@ -0,0 +1,74 @@
+/*
+ * 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 _SASLMECHANISM_H_
+#define _SASLMECHANISM_H_
+
+#include <string>
+
+namespace buzz {
+
+class XmlElement;
+
+
+// Defines a mechnanism to do SASL authentication.
+// Subclass instances should have a self-contained way to present
+// credentials.
+class SaslMechanism {
+
+public:
+  
+  // Intended to be subclassed
+  virtual ~SaslMechanism() {}
+
+  // Should return the name of the SASL mechanism, e.g., "PLAIN"
+  virtual std::string GetMechanismName() = 0;
+
+  // Should generate the initial "auth" request.  Default is just <auth/>.
+  virtual XmlElement * StartSaslAuth();
+
+  // Should respond to a SASL "<challenge>" request.  Default is
+  // to abort (for mechanisms that do not do challenge-response)
+  virtual XmlElement * HandleSaslChallenge(const XmlElement * challenge);
+
+  // Notification of a SASL "<success>".  Sometimes information
+  // is passed on success.
+  virtual void HandleSaslSuccess(const XmlElement * success);
+
+  // Notification of a SASL "<failure>".  Sometimes information
+  // for the user is passed on failure.
+  virtual void HandleSaslFailure(const XmlElement * failure);
+
+protected:
+  static std::string Base64Encode(const std::string & plain);
+  static std::string Base64Decode(const std::string & encoded);
+  static std::string Base64EncodeFromArray(const char * plain, size_t length);
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/saslplainmechanism.h b/talk/xmpp/saslplainmechanism.h
new file mode 100755
index 0000000..72532e6
--- /dev/null
+++ b/talk/xmpp/saslplainmechanism.h
@@ -0,0 +1,65 @@
+/*
+ * 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 _SASLPLAINMECHANISM_H_
+#define _SASLPLAINMECHANISM_H_
+
+#include "talk/base/cryptstring.h"
+#include "talk/xmpp/saslmechanism.h"
+
+namespace buzz {
+
+class SaslPlainMechanism : public SaslMechanism {
+
+public:
+  SaslPlainMechanism(const buzz::Jid user_jid, const talk_base::CryptString & password) :
+    user_jid_(user_jid), password_(password) {}
+
+  virtual std::string GetMechanismName() { return "PLAIN"; }
+    
+  virtual XmlElement * StartSaslAuth() {
+    // send initial request
+    XmlElement * el = new XmlElement(QN_SASL_AUTH, true);
+    el->AddAttr(QN_MECHANISM, "PLAIN");
+
+    talk_base::FormatCryptString credential;
+    credential.Append("\0", 1);
+    credential.Append(user_jid_.node());
+    credential.Append("\0", 1);
+    credential.Append(&password_);
+    el->AddText(Base64EncodeFromArray(credential.GetData(), credential.GetLength()));
+    return el;
+  }
+  
+private:
+  Jid user_jid_;
+  talk_base::CryptString password_;
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/xmppclient.cc b/talk/xmpp/xmppclient.cc
new file mode 100755
index 0000000..0db9b1d
--- /dev/null
+++ b/talk/xmpp/xmppclient.cc
@@ -0,0 +1,416 @@
+/*
+ * 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 "xmppclient.h"
+#include "xmpptask.h"
+#include "talk/xmpp/constants.h"
+#include "talk/base/sigslot.h"
+#include "talk/xmpp/saslplainmechanism.h"
+#include "talk/xmpp/prexmppauth.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/xmpp/plainsaslhandler.h"
+
+namespace buzz {
+
+talk_base::Task* XmppClient::GetParent(int code) {
+  if (code == XMPP_CLIENT_TASK_CODE)
+    return this;
+  else
+    return talk_base::Task::GetParent(code);
+}
+
+class XmppClient::Private :
+    public sigslot::has_slots<>,
+    public XmppSessionHandler,
+    public XmppOutputHandler {
+public:
+
+  Private(XmppClient * client) :
+    client_(client),
+    socket_(NULL),
+    engine_(NULL),
+    proxy_port_(0),
+    pre_engine_error_(XmppEngine::ERROR_NONE),
+    pre_engine_subcode_(0),
+    signal_closed_(false),
+    allow_plain_(false) {}
+
+  // the owner
+  XmppClient * const client_;
+
+  // the two main objects
+  scoped_ptr<AsyncSocket> socket_;
+  scoped_ptr<XmppEngine> engine_;
+  scoped_ptr<PreXmppAuth> pre_auth_;
+  talk_base::CryptString pass_;
+  std::string auth_cookie_;
+  talk_base::SocketAddress server_;
+  std::string proxy_host_;
+  int proxy_port_;
+  XmppEngine::Error pre_engine_error_;
+  int pre_engine_subcode_;
+  CaptchaChallenge captcha_challenge_;
+  bool signal_closed_;
+  bool allow_plain_;
+
+  // implementations of interfaces
+  void OnStateChange(int state);
+  void WriteOutput(const char * bytes, size_t len);
+  void StartTls(const std::string & domainname);
+  void CloseConnection();
+
+  // slots for socket signals
+  void OnSocketConnected();
+  void OnSocketRead();
+  void OnSocketClosed();
+};
+
+XmppReturnStatus
+XmppClient::Connect(const XmppClientSettings & settings, const std::string & lang, AsyncSocket * socket, PreXmppAuth * pre_auth) {
+  if (socket == NULL)
+    return XMPP_RETURN_BADARGUMENT;
+  if (d_->socket_.get() != NULL)
+    return XMPP_RETURN_BADSTATE;
+
+  d_->socket_.reset(socket);
+
+  d_->socket_->SignalConnected.connect(d_.get(), &Private::OnSocketConnected);
+  d_->socket_->SignalRead.connect(d_.get(), &Private::OnSocketRead);
+  d_->socket_->SignalClosed.connect(d_.get(), &Private::OnSocketClosed);
+
+  d_->engine_.reset(XmppEngine::Create());
+  d_->engine_->SetSessionHandler(d_.get());
+  d_->engine_->SetOutputHandler(d_.get());
+  if (!settings.resource().empty()) {
+    d_->engine_->SetRequestedResource(settings.resource());
+  }
+  d_->engine_->SetUseTls(settings.use_tls());
+
+  //
+  // The talk.google.com server expects you to use "gmail.com" in the
+  // stream, and expects the domain certificate to be "gmail.com" as well.
+  // For all other servers, we leave the strings empty, which causes
+  // the jid's domain to be used.  "foo@example.com" -> stream to="example.com"
+  // tls certificate for "example.com"
+  //
+  // 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) && 
+      pre_auth != NULL) {
+    d_->engine_->SetTlsServer(buzz::STR_GMAIL_COM, buzz::STR_GMAIL_COM);
+  }
+
+  // Set language
+  d_->engine_->SetLanguage(lang);
+
+  d_->engine_->SetUser(buzz::Jid(settings.user(), settings.host(), STR_EMPTY));
+
+  d_->pass_ = settings.pass();
+  d_->auth_cookie_ = settings.auth_cookie();
+  d_->server_ = settings.server();
+  d_->proxy_host_ = settings.proxy_host();
+  d_->proxy_port_ = settings.proxy_port();
+  d_->allow_plain_ = settings.allow_plain();
+  d_->pre_auth_.reset(pre_auth);
+
+  return XMPP_RETURN_OK;
+}
+
+XmppEngine::State
+XmppClient::GetState() {
+  if (d_->engine_.get() == NULL)
+    return XmppEngine::STATE_NONE;
+  return d_->engine_->GetState();
+}
+
+XmppEngine::Error
+XmppClient::GetError(int *subcode) {
+  if (subcode) {
+    *subcode = 0;
+  }
+  if (d_->engine_.get() == NULL)
+    return XmppEngine::ERROR_NONE;
+  if (d_->pre_engine_error_ != XmppEngine::ERROR_NONE) {
+    if (subcode) {
+      *subcode = d_->pre_engine_subcode_;
+    }
+    return d_->pre_engine_error_;
+  }
+  return d_->engine_->GetError(subcode);
+}
+
+const XmlElement *
+XmppClient::GetStreamError() {
+  if (d_->engine_.get() == NULL) {
+    return NULL;
+  }
+  return d_->engine_->GetStreamError();
+}
+
+CaptchaChallenge XmppClient::GetCaptchaChallenge() {
+  if (d_->engine_.get() == NULL)
+    return CaptchaChallenge();
+  return d_->captcha_challenge_;
+}
+
+std::string
+XmppClient::GetAuthCookie() {
+  if (d_->engine_.get() == NULL)
+    return "";
+  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()) {
+    d_->pre_auth_->SignalAuthDone.connect(this, &XmppClient::OnAuthDone);
+    d_->pre_auth_->StartPreXmppAuth(
+        d_->engine_->GetUser(), d_->server_, d_->pass_, d_->auth_cookie_);
+    d_->pass_.Clear(); // done with this;
+    return STATE_PRE_XMPP_LOGIN;
+  }
+  else {
+    d_->engine_->SetSaslHandler(new PlainSaslHandler(
+              d_->engine_->GetUser(), d_->pass_, d_->allow_plain_));
+    d_->pass_.Clear(); // done with this;
+    return STATE_START_XMPP_LOGIN;
+  }
+}
+
+void
+XmppClient::OnAuthDone() {
+  Wake();
+}
+
+int
+XmppClient::ProcessCookieLogin() {
+  // Don't know how this could happen, but crash reports show it as NULL
+  if (!d_->pre_auth_.get()) {
+    d_->pre_engine_error_ = XmppEngine::ERROR_AUTH;
+    EnsureClosed();
+    return STATE_ERROR;
+  }
+
+  // Wait until pre authentication is done is done
+  if (!d_->pre_auth_->IsAuthDone())
+    return STATE_BLOCKED;
+
+  if (!d_->pre_auth_->IsAuthorized()) {
+    // maybe split out a case when gaia is down?
+    if (d_->pre_auth_->HadError()) {
+      d_->pre_engine_error_ = XmppEngine::ERROR_AUTH;
+      d_->pre_engine_subcode_ = d_->pre_auth_->GetError();
+    }
+    else {
+      d_->pre_engine_error_ = XmppEngine::ERROR_UNAUTHORIZED;
+      d_->pre_engine_subcode_ = 0;
+      d_->captcha_challenge_ = d_->pre_auth_->GetCaptchaChallenge();
+    }
+    d_->pre_auth_.reset(NULL); // done with this
+    EnsureClosed();
+    return STATE_ERROR;
+  }
+
+  // Save auth cookie as a result
+  d_->auth_cookie_ = d_->pre_auth_->GetAuthCookie();
+
+  // transfer ownership of pre_auth_ to engine
+  d_->engine_->SetSaslHandler(d_->pre_auth_.release());
+  return STATE_START_XMPP_LOGIN;
+}
+
+int
+XmppClient::ProcessStartXmppLogin() {
+  // Done with pre-connect tasks - connect!
+  if (!d_->socket_->Connect(d_->server_)) {
+    EnsureClosed();
+    return STATE_ERROR;
+  }
+  
+  return STATE_RESPONSE;
+}
+
+int
+XmppClient::ProcessResponse() {
+  // Hang around while we are connected.
+  if (!delivering_signal_ && (d_->engine_.get() == NULL ||
+    d_->engine_->GetState() == XmppEngine::STATE_CLOSED))
+    return STATE_DONE;
+  return STATE_BLOCKED;
+}
+
+XmppReturnStatus
+XmppClient::Disconnect() {
+  if (d_->socket_.get() == NULL)
+    return XMPP_RETURN_BADSTATE;
+  d_->engine_->Disconnect();
+  return XMPP_RETURN_OK;
+}
+
+XmppClient::XmppClient(Task * parent) 
+    : Task(parent), 
+      delivering_signal_(false),
+      valid_(false) {
+  d_.reset(new Private(this));
+  valid_ = true;
+}
+
+XmppClient::~XmppClient() {
+  valid_ = false;
+}
+
+const Jid &
+XmppClient::jid() {
+  return d_->engine_->FullJid();
+}
+
+
+std::string
+XmppClient::NextId() {
+  return d_->engine_->NextId();
+}
+
+XmppReturnStatus
+XmppClient::SendStanza(const XmlElement * stanza) {
+  return d_->engine_->SendStanza(stanza);
+}
+
+XmppReturnStatus
+XmppClient::SendStanzaError(const XmlElement * old_stanza, XmppStanzaError xse, const std::string & message) {
+  return d_->engine_->SendStanzaError(old_stanza, xse, message);
+}
+
+XmppReturnStatus
+XmppClient::SendRaw(const std::string & text) {
+  return d_->engine_->SendRaw(text);
+}
+
+XmppEngine*
+XmppClient::engine() {
+  return d_->engine_.get();
+}
+
+void
+XmppClient::Private::OnSocketConnected() {
+  engine_->Connect();
+}
+
+void
+XmppClient::Private::OnSocketRead() {
+  char bytes[4096];
+  size_t bytes_read;
+  for (;;) {
+    if (!socket_->Read(bytes, sizeof(bytes), &bytes_read)) {
+      // TODO: deal with error information
+      return;
+    }
+
+    if (bytes_read == 0)
+      return;
+
+//#ifdef _DEBUG
+    client_->SignalLogInput(bytes, bytes_read);
+//#endif
+
+    engine_->HandleInput(bytes, bytes_read);
+  }
+}
+
+void
+XmppClient::Private::OnSocketClosed() {
+  int code = socket_->GetError();  
+  engine_->ConnectionClosed(code);
+}
+
+void
+XmppClient::Private::OnStateChange(int state) {
+  if (state == XmppEngine::STATE_CLOSED) {
+    client_->EnsureClosed();
+  }
+  else {
+    client_->SignalStateChange((XmppEngine::State)state);
+  }
+  client_->Wake();
+}
+
+void
+XmppClient::Private::WriteOutput(const char * bytes, size_t len) {
+
+//#ifdef _DEBUG
+  client_->SignalLogOutput(bytes, len);
+//#endif
+
+  socket_->Write(bytes, len);
+  // TODO: deal with error information
+}
+
+void
+XmppClient::Private::StartTls(const std::string & domain) {
+#if defined(FEATURE_ENABLE_SSL)
+  socket_->StartTls(domain);
+#endif
+}
+
+void
+XmppClient::Private::CloseConnection() {
+  socket_->Close();
+}
+
+void
+XmppClient::AddXmppTask(XmppTask * task, XmppEngine::HandlerLevel level) {
+  d_->engine_->AddStanzaHandler(task, level);
+}
+
+void
+XmppClient::RemoveXmppTask(XmppTask * task) {
+  d_->engine_->RemoveStanzaHandler(task);
+}
+
+void
+XmppClient::EnsureClosed() {
+  if (!d_->signal_closed_) {
+    d_->signal_closed_ = true;
+    delivering_signal_ = true;
+    SignalStateChange(XmppEngine::STATE_CLOSED);
+    delivering_signal_ = false;
+  }
+}
+
+
+}
diff --git a/talk/xmpp/xmppclient.h b/talk/xmpp/xmppclient.h
new file mode 100755
index 0000000..1c4b947
--- /dev/null
+++ b/talk/xmpp/xmppclient.h
@@ -0,0 +1,163 @@
+/*
+ * 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 _XMPPCLIENT_H_
+#define _XMPPCLIENT_H_
+
+#include <string>
+#include "talk/base/basicdefs.h"
+#include "talk/base/sigslot.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/asyncsocket.h"
+#include "talk/xmpp/xmppclientsettings.h"
+#include "talk/base/task.h"
+
+namespace buzz {
+
+class XmppTask;
+class PreXmppAuth;
+class CaptchaChallenge;
+
+// Just some non-colliding number.  Could have picked "1".
+#define XMPP_CLIENT_TASK_CODE 0x366c1e47
+
+/////////////////////////////////////////////////////////////////////
+//
+// XMPPCLIENT
+//
+/////////////////////////////////////////////////////////////////////
+//
+// See Task first.  XmppClient is a parent task for XmppTasks.
+//
+// XmppClient is a task which is designed to be the parent task for
+// all tasks that depend on a single Xmpp connection.  If you want to,
+// for example, listen for subscription requests forever, then your
+// 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
+// should just be the same kind of Task instead of an XmppEngine specific
+// thing.  It would help do certain things like GAIA auth cleaner.
+//
+/////////////////////////////////////////////////////////////////////
+
+class XmppClient : public talk_base::Task, public sigslot::has_slots<>
+{
+public:
+  XmppClient(talk_base::Task * parent);
+  ~XmppClient();
+
+  XmppReturnStatus Connect(const XmppClientSettings & settings,
+                           const std::string & lang,
+                           AsyncSocket * socket,
+                           PreXmppAuth * preauth);
+  
+  virtual talk_base::Task* 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);
+
+  // When there is a <stream:error> stanza, return the stanza
+  // so that they can be handled.
+  const XmlElement *GetStreamError();
+
+  // When there is an authentication error, we may have captcha info
+  // that the user can use to unlock their account
+  CaptchaChallenge GetCaptchaChallenge();
+
+  // When authentication is successful, this returns the service cookie
+  // (if we used GAIA authentication)
+  std::string GetAuthCookie();
+
+  std::string NextId();
+  XmppReturnStatus SendStanza(const XmlElement *stanza);
+  XmppReturnStatus SendRaw(const std::string & text);
+  XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal,
+                       XmppStanzaError code,
+                       const std::string & text);
+
+  XmppEngine* engine();
+
+  sigslot::signal2<const char *, int> SignalLogInput;
+  sigslot::signal2<const char *, int> SignalLogOutput;
+
+private:
+  friend class XmppTask;
+
+  void OnAuthDone();
+
+  // managed tasks and dispatching
+  void AddXmppTask(XmppTask *, XmppEngine::HandlerLevel);
+  void RemoveXmppTask(XmppTask *);
+
+  sigslot::signal0<> SignalDisconnected;
+
+private:
+  // Internal state management
+  enum {
+    STATE_PRE_XMPP_LOGIN = STATE_NEXT,
+    STATE_START_XMPP_LOGIN = STATE_NEXT + 1,
+  };
+  int Process(int state) {
+    switch (state) {
+      case STATE_PRE_XMPP_LOGIN: return ProcessCookieLogin();
+      case STATE_START_XMPP_LOGIN: return ProcessStartXmppLogin();
+      default: return Task::Process(state);
+    }
+  }
+
+  std::string XmppClient::GetStateName(int state) const {
+    switch (state) {
+      case STATE_PRE_XMPP_LOGIN:      return "PRE_XMPP_LOGIN";
+      case STATE_START_XMPP_LOGIN:  return "START_XMPP_LOGIN";
+      default: return Task::GetStateName(state);
+    }
+  }
+
+  int ProcessCookieLogin();
+  int ProcessStartXmppLogin();
+  void EnsureClosed();
+  
+  class Private;
+  friend class Private;
+  scoped_ptr<Private> d_;
+  
+  bool delivering_signal_;
+  bool valid_;
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/xmppclientsettings.h b/talk/xmpp/xmppclientsettings.h
new file mode 100755
index 0000000..281e1bb
--- /dev/null
+++ b/talk/xmpp/xmppclientsettings.h
@@ -0,0 +1,98 @@
+/*
+ * 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 _XMPPCLIENTSETTINGS_H_
+#define _XMPPCLIENTSETTINGS_H_
+
+#include "talk/p2p/base/port.h"
+#include "talk/base/cryptstring.h"
+
+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) {}
+
+  void set_user(const std::string & user) { user_ = user; }
+  void set_host(const std::string & host) { host_ = host; }
+  void set_pass(const talk_base::CryptString & pass) { pass_ = pass; }
+  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_server(const talk_base::SocketAddress & server) { 
+      server_ = server; 
+  }
+  void set_protocol(cricket::ProtocolType protocol) { protocol_ = protocol; }
+  void set_proxy(talk_base::ProxyType f) { proxy_ = f; }
+  void set_proxy_host(const std::string & host) { proxy_host_ = host; }
+  void set_proxy_port(int port) { proxy_port_ = port; };
+  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_; }
+  const std::string & proxy_host() const { return proxy_host_; }
+  int proxy_port() const { return proxy_port_; }
+  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_;
+  talk_base::SocketAddress server_;
+  cricket::ProtocolType protocol_;
+  talk_base::ProxyType proxy_;
+  std::string proxy_host_;
+  int proxy_port_;
+  bool use_proxy_auth_;
+  std::string proxy_user_;
+  talk_base::CryptString proxy_pass_;
+  bool allow_plain_;
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/xmppengine.h b/talk/xmpp/xmppengine.h
new file mode 100755
index 0000000..45d2875
--- /dev/null
+++ b/talk/xmpp/xmppengine.h
@@ -0,0 +1,338 @@
+/*
+ * 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 _xmppengine_h_
+#define _xmppengine_h_
+
+// also part of the API
+#include "talk/xmpp/jid.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmllite/xmlelement.h"
+
+
+namespace buzz {
+
+class XmppEngine;
+class SaslHandler;
+typedef void * XmppIqCookie;
+
+//! XMPP stanza error codes.
+//! Used in XmppEngine.SendStanzaError().
+enum XmppStanzaError {
+  XSE_BAD_REQUEST,
+  XSE_CONFLICT,
+  XSE_FEATURE_NOT_IMPLEMENTED,
+  XSE_FORBIDDEN,
+  XSE_GONE,
+  XSE_INTERNAL_SERVER_ERROR,
+  XSE_ITEM_NOT_FOUND,
+  XSE_JID_MALFORMED,
+  XSE_NOT_ACCEPTABLE,
+  XSE_NOT_ALLOWED,
+  XSE_PAYMENT_REQUIRED,
+  XSE_RECIPIENT_UNAVAILABLE,
+  XSE_REDIRECT,
+  XSE_REGISTRATION_REQUIRED,
+  XSE_SERVER_NOT_FOUND,
+  XSE_SERVER_TIMEOUT,
+  XSE_RESOURCE_CONSTRAINT,
+  XSE_SERVICE_UNAVAILABLE,
+  XSE_SUBSCRIPTION_REQUIRED,
+  XSE_UNDEFINED_CONDITION,
+  XSE_UNEXPECTED_REQUEST,
+};
+
+// XmppReturnStatus
+//    This is used by API functions to synchronously return status.
+enum XmppReturnStatus {
+  XMPP_RETURN_OK,
+  XMPP_RETURN_BADARGUMENT,
+  XMPP_RETURN_BADSTATE,
+  XMPP_RETURN_PENDING,
+  XMPP_RETURN_UNEXPECTED,
+  XMPP_RETURN_NOTYETIMPLEMENTED,
+};
+
+//! Callback for socket output for an XmppEngine connection.
+//! Register via XmppEngine.SetOutputHandler.  An XmppEngine
+//! can call back to this handler while it is processing
+//! Connect, SendStanza, SendIq, Disconnect, or HandleInput.
+class XmppOutputHandler {
+public:
+
+  //! Deliver the specified bytes to the XMPP socket.
+  virtual void WriteOutput(const char * bytes, size_t len) = 0;
+
+  //! Initiate TLS encryption on the socket.
+  //! The implementation must verify that the SSL
+  //! certificate matches the given domainname.
+  virtual void StartTls(const std::string & domainname) = 0;
+
+  //! Called when engine wants the connecton closed.
+  virtual void CloseConnection() = 0;
+};
+
+//! Callback to deliver engine state change notifications
+//! to the object managing the engine.
+class XmppSessionHandler {
+public:
+  //! Called when engine changes state. Argument is new state.
+  virtual void OnStateChange(int state) = 0;
+};
+
+//! Callback to deliver stanzas to an Xmpp application module.
+//! Register via XmppEngine.SetDefaultSessionHandler or via
+//! XmppEngine.AddSessionHAndler.  
+class XmppStanzaHandler {
+public:
+
+  //! 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
+  //! the next registered handler.
+  virtual bool HandleStanza(const XmlElement * stanza) = 0;
+};
+
+//! Callback to deliver iq responses (results and errors).
+//! Register while sending an iq via XmppEngine.SendIq.
+//! Iq responses are routed to matching XmppIqHandlers in preference
+//! to sending to any registered SessionHandlers.
+class XmppIqHandler {
+public:
+  //! 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
+  //! 'to' of the request.  Called no more than once; once this is
+  //! called, the handler is automatically unregistered.
+  virtual void IqResponse(XmppIqCookie cookie, const XmlElement * pelStanza) = 0;
+};
+
+//! The XMPP connection engine.
+//! This engine implements the client side of the 'core' XMPP protocol.
+//! To use it, register an XmppOutputHandler to handle socket output
+//! and pass socket input to HandleInput.  Then application code can
+//! set up the connection with a user, password, and other settings,
+//! and then call Connect() to initiate the connection.
+//! An application can listen for events and receive stanzas by
+//! registering an XmppStanzaHandler via AddStanzaHandler().
+class XmppEngine {
+public:
+  static XmppEngine * Create();
+  virtual ~XmppEngine() {}
+
+  //! Error codes. See GetError().
+  enum Error {
+    ERROR_NONE = 0,         //!< No error
+    ERROR_XML,              //!< Malformed XML or encoding error
+    ERROR_STREAM,           //!< XMPP stream error - see GetStreamError()
+    ERROR_VERSION,          //!< XMPP version error
+    ERROR_UNAUTHORIZED,     //!< User is not authorized (rejected credentials)
+    ERROR_TLS,              //!< TLS could not be negotiated
+    ERROR_AUTH,             //!< Authentication could not be negotiated
+    ERROR_BIND,             //!< Resource or session binding could not be negotiated
+    ERROR_CONNECTION_CLOSED,//!< Connection closed by output handler.
+    ERROR_DOCUMENT_CLOSED,  //!< Closed by </stream:stream>
+    ERROR_SOCKET,           //!< Socket error
+    ERROR_NETWORK_TIMEOUT,  //!< Some sort of timeout (eg., we never got the roster)
+    ERROR_MISSING_USERNAME  //!< User has a Google Account but no nickname
+  };
+
+  //! States.  See GetState().
+  enum State {
+    STATE_NONE = 0,        //!< Nonexistent state
+    STATE_START,           //!< Initial state.
+    STATE_OPENING,         //!< Exchanging stream headers, authenticating and so on.
+    STATE_OPEN,            //!< Authenticated and bound.
+    STATE_CLOSED,          //!< Session closed, possibly due to error.
+  };
+
+  // SOCKET INPUT AND OUTPUT ------------------------------------------------
+
+  //! Registers the handler for socket output
+  virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh) = 0;
+
+  //! Provides socket input to the engine
+  virtual XmppReturnStatus HandleInput(const char * bytes, size_t len) = 0;
+
+  //! Advises the engine that the socket has closed
+  virtual XmppReturnStatus ConnectionClosed(int subcode) = 0;
+
+  // SESSION SETUP ---------------------------------------------------------
+
+  //! Indicates the (bare) JID for the user to use.
+  virtual XmppReturnStatus SetUser(const Jid & jid)= 0;
+
+  //! Get the login (bare) JID.
+  virtual const Jid & GetUser() = 0;
+
+  //! Provides different methods for credentials for login.
+  //! Takes ownership of this object; deletes when login is done
+  virtual XmppReturnStatus SetSaslHandler(SaslHandler * h) = 0;
+
+  //! Sets whether TLS will be used within the connection (default true).
+  virtual XmppReturnStatus SetUseTls(bool useTls) = 0;
+
+  //! Sets an alternate domain from which we allows TLS certificates.
+  //! This is for use in the case where a we want to allow a proxy to
+  //! serve up its own certificate rather than one owned by the underlying
+  //! domain.
+  virtual XmppReturnStatus SetTlsServer(const std::string & proxy_hostname, 
+                                        const std::string & proxy_domain) = 0;
+
+  //! Gets whether TLS will be used within the connection.
+  virtual bool GetUseTls() = 0;
+
+  //! Sets the request resource name, if any (optional).
+  //! Note that the resource name may be overridden by the server; after
+  //! binding, the actual resource name is available as part of FullJid().
+  virtual XmppReturnStatus SetRequestedResource(const std::string& resource) = 0;
+
+  //! Gets the request resource name.
+  virtual const std::string & GetRequestedResource() = 0;
+
+  //! Sets language
+  virtual void SetLanguage(const std::string & lang) = 0;
+
+  // SESSION MANAGEMENT ---------------------------------------------------
+
+  //! Set callback for state changes.
+  virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler) = 0;
+
+  //! Initiates the XMPP connection.
+  //! After supplying connection settings, call this once to initiate,
+  //! (optionally) encrypt, authenticate, and bind the connection.
+  virtual XmppReturnStatus Connect() = 0;
+
+  //! The current engine state.
+  virtual State GetState() = 0;
+
+  //! Returns true if the connection is encrypted (under TLS)
+  virtual bool IsEncrypted() = 0;
+
+  //! The error code.
+  //! Consult this after XmppOutputHandler.OnClose().
+  virtual Error GetError(int *subcode) = 0;
+
+  //! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM.
+  //! Notice the stanza returned is owned by the XmppEngine and
+  //! is deleted when the engine is destroyed.
+  virtual const XmlElement * GetStreamError() = 0;
+
+  //! Closes down the connection.
+  //! Sends CloseConnection to output, and disconnects and registered
+  //! session handlers.  After Disconnect completes, it is guaranteed
+  //! that no further callbacks will be made.
+  virtual XmppReturnStatus Disconnect() = 0;
+
+  // APPLICATION USE -------------------------------------------------------
+
+  enum HandlerLevel {
+    HL_NONE = 0,
+    HL_PEEK,   //!< Sees messages before all other processing; cannot abort
+    HL_SINGLE, //!< Watches for a single message, e.g., by id and sender
+    HL_SENDER, //!< Watches for a type of message from a specific sender
+    HL_TYPE,   //!< Watches a type of message, e.g., all groupchat msgs
+    HL_ALL,    //!< Watches all messages - gets last shot
+    HL_COUNT,  //!< Count of handler levels
+  };
+
+  //! Adds a listener for session events.
+  //! Stanza delivery is chained to session handlers; the first to
+  //! return 'true' is the last to get each stanza.
+  virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler, HandlerLevel level = HL_PEEK) = 0;
+
+  //! Removes a listener for session events.
+  virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler) = 0;
+
+  //! Sends a stanza to the server.
+  virtual XmppReturnStatus SendStanza(const XmlElement * pelStanza) = 0;
+
+  //! Sends raw text to the server
+  virtual XmppReturnStatus SendRaw(const std::string & text) = 0;
+
+  //! Sends an iq to the server, and registers a callback for the result.
+  //! Returns the cookie passed to the result handler.
+  virtual XmppReturnStatus SendIq(const XmlElement* pelStanza,
+                                  XmppIqHandler* iq_handler,
+                                  XmppIqCookie* cookie) = 0;
+
+  //! Unregisters an iq callback handler given its cookie.
+  //! No callback will come to this handler after it's unregistered.
+  virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie,
+                                      XmppIqHandler** iq_handler) = 0;
+
+
+  //! Forms and sends an error in response to the given stanza.
+  //! Swaps to and from, sets type to "error", and adds error information
+  //! based on the passed code.  Text is optional and may be STR_EMPTY.
+  virtual XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal,
+                                           XmppStanzaError code,
+                                           const std::string & text) = 0;
+
+  //! The fullly bound JID.
+  //! This JID is only valid after binding has succeeded.  If the value
+  //! is JID_NULL, the binding has not succeeded.
+  virtual const Jid & FullJid() = 0;
+
+  //! The next unused iq id for this connection.
+  //! Call this when building iq stanzas, to ensure that each iq
+  //! gets its own unique id.
+  virtual std::string NextId() = 0;
+
+};
+
+}
+
+
+// Move these to a better location
+
+#define XMPP_FAILED(x)                      \
+  ( (x) == buzz::XMPP_RETURN_OK ? false : true)   \
+
+
+#define XMPP_SUCCEEDED(x)                   \
+  ( (x) == buzz::XMPP_RETURN_OK ? true : false)   \
+
+#define IFR(x)                        \
+  do {                                \
+    xmpp_status = (x);                \
+    if (XMPP_FAILED(xmpp_status)) {   \
+      return xmpp_status;             \
+    }                                 \
+  } while (false)                     \
+
+
+#define IFC(x)                        \
+  do {                                \
+    xmpp_status = (x);                \
+    if (XMPP_FAILED(xmpp_status)) {   \
+      goto Cleanup;                   \
+    }                                 \
+  } while (false)                     \
+
+
+#endif
diff --git a/talk/xmpp/xmppengineimpl.cc b/talk/xmpp/xmppengineimpl.cc
new file mode 100755
index 0000000..64ff957
--- /dev/null
+++ b/talk/xmpp/xmppengineimpl.cc
@@ -0,0 +1,498 @@
+/*
+ * 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.
+ */
+
+#define TRACK_ARRAY_ALLOC_PROBLEM
+
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include "talk/xmllite/xmlelement.h"
+#include "talk/base/common.h"
+#include "talk/xmpp/xmppengineimpl.h"
+#include "talk/xmpp/xmpplogintask.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmllite/xmlprinter.h"
+#include "talk/xmpp/saslhandler.h"
+
+namespace buzz {
+
+static const std::string XMPP_CLIENT_NAMESPACES[] = {
+  "stream", "http://etherx.jabber.org/streams",
+  "", "jabber:client",
+};
+
+static const size_t XMPP_CLIENT_NAMESPACES_LEN = 4;
+
+XmppEngine * XmppEngine::Create() {
+  return new XmppEngineImpl();
+}
+
+
+XmppEngineImpl::XmppEngineImpl() :
+    stanzaParseHandler_(this),
+    stanzaParser_(&stanzaParseHandler_),
+    engine_entered_(0),
+    user_jid_(JID_EMPTY),
+    password_(),
+    requested_resource_(STR_EMPTY),
+    tls_needed_(true),
+    login_task_(new XmppLoginTask(this)),
+    next_id_(0),
+    bound_jid_(JID_EMPTY),
+    state_(STATE_START),
+    encrypted_(false),
+    error_code_(ERROR_NONE),
+    subcode_(0),
+    stream_error_(NULL),
+    raised_reset_(false),
+    output_handler_(NULL),
+    session_handler_(NULL),
+    iq_entries_(new IqEntryVector()),
+    output_(new std::stringstream()),
+    sasl_handler_(NULL) {
+  for (int i = 0; i < HL_COUNT; i+= 1) {
+    stanza_handlers_[i].reset(new StanzaHandlerVector());
+  }
+}
+
+XmppEngineImpl::~XmppEngineImpl() {
+  DeleteIqCookies();
+}
+
+XmppReturnStatus
+XmppEngineImpl::SetOutputHandler(XmppOutputHandler* output_handler) {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  output_handler_ = output_handler;
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SetSessionHandler(XmppSessionHandler* session_handler) {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  session_handler_ = session_handler;
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::HandleInput(const char * bytes, size_t len) {
+  if (state_ < STATE_OPENING || state_ > STATE_OPEN)
+    return XMPP_RETURN_BADSTATE;
+
+  EnterExit ee(this);
+
+  // TODO(jliaw): The return value of the xml parser is not checked.
+  stanzaParser_.Parse(bytes, len, false);
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::ConnectionClosed(int subcode) {
+  if (state_ != STATE_CLOSED) {
+    EnterExit ee(this);
+    // If told that connection closed and not already closed,
+    // then connection was unpexectedly dropped.
+    if (subcode) {
+      SignalError(ERROR_SOCKET, subcode);
+    } else {
+      SignalError(ERROR_CONNECTION_CLOSED, 0);  // no subcode
+    }
+  }
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SetUseTls(bool useTls) {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  tls_needed_ = useTls;
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SetTlsServer(const std::string & tls_server_hostname,
+                             const std::string & tls_server_domain) {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  tls_server_hostname_ = tls_server_hostname;
+  tls_server_domain_= tls_server_domain;
+
+  return XMPP_RETURN_OK;
+}
+
+bool
+XmppEngineImpl::GetUseTls() {
+  return tls_needed_;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SetUser(const Jid & jid) {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  user_jid_ = jid;
+
+  return XMPP_RETURN_OK;
+}
+
+const Jid &
+XmppEngineImpl::GetUser() {
+  return user_jid_;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SetSaslHandler(SaslHandler * sasl_handler) {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  sasl_handler_.reset(sasl_handler);
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SetRequestedResource(const std::string & resource) {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  requested_resource_ = resource;
+
+  return XMPP_RETURN_OK;
+}
+
+const std::string &
+XmppEngineImpl::GetRequestedResource() {
+  return requested_resource_;
+}
+
+XmppReturnStatus
+XmppEngineImpl::AddStanzaHandler(XmppStanzaHandler * stanza_handler,
+                                 XmppEngine::HandlerLevel level) {
+  if (state_ == STATE_CLOSED)
+    return XMPP_RETURN_BADSTATE;
+
+  stanza_handlers_[level]->push_back(stanza_handler);
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::RemoveStanzaHandler(XmppStanzaHandler * stanza_handler) {
+
+  bool found = false;
+
+  for (int level = 0; level < HL_COUNT; level += 1) {
+    StanzaHandlerVector::iterator new_end =
+      std::remove(stanza_handlers_[level]->begin(),
+      stanza_handlers_[level]->end(),
+      stanza_handler);
+
+    if (new_end != stanza_handlers_[level]->end()) {
+      stanza_handlers_[level]->erase(new_end, stanza_handlers_[level]->end());
+      found = true;
+    }
+  }
+
+  if (!found) {
+    return XMPP_RETURN_BADARGUMENT;
+  }
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::Connect() {
+  if (state_ != STATE_START)
+    return XMPP_RETURN_BADSTATE;
+
+  EnterExit ee(this);
+
+  // get the login task started
+  state_ = STATE_OPENING;
+  if (login_task_.get()) {
+    login_task_->IncomingStanza(NULL, false);
+    if (login_task_->IsDone())
+      login_task_.reset();
+  }
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SendStanza(const XmlElement * element) {
+  if (state_ == STATE_CLOSED)
+    return XMPP_RETURN_BADSTATE;
+
+  EnterExit ee(this);
+
+  if (login_task_.get()) {
+    // still handshaking - then outbound stanzas are queued
+    login_task_->OutgoingStanza(element);
+  } else {
+    // handshake done - send straight through
+    InternalSendStanza(element);
+  }
+
+  return XMPP_RETURN_OK;
+}
+
+XmppReturnStatus
+XmppEngineImpl::SendRaw(const std::string & text) {
+  if (state_ == STATE_CLOSED || login_task_.get())
+    return XMPP_RETURN_BADSTATE;
+
+  EnterExit ee(this);
+
+  (*output_) << text;
+
+  return XMPP_RETURN_OK;
+}
+
+std::string
+XmppEngineImpl::NextId() {
+  std::stringstream ss;
+  ss << next_id_++;
+  return ss.str();
+}
+
+XmppReturnStatus
+XmppEngineImpl::Disconnect() {
+
+  if (state_ != STATE_CLOSED) {
+    EnterExit ee(this);
+    if (state_ == STATE_OPEN)
+      *output_ << "</stream:stream>";
+    state_ = STATE_CLOSED;
+  }
+
+  return XMPP_RETURN_OK;
+}
+
+void
+XmppEngineImpl::IncomingStart(const XmlElement * pelStart) {
+  if (HasError() || raised_reset_)
+    return;
+
+  if (login_task_.get()) {
+    // start-stream should go to login task
+    login_task_->IncomingStanza(pelStart, true);
+    if (login_task_->IsDone())
+      login_task_.reset();
+  }
+  else {
+    // if not logging in, it's an error to see a start
+    SignalError(ERROR_XML, 0);
+  }
+}
+
+void
+XmppEngineImpl::IncomingStanza(const XmlElement * stanza) {
+  if (HasError() || raised_reset_)
+    return;
+
+  if (stanza->Name() == QN_STREAM_ERROR) {
+    // Explicit XMPP stream error
+    SignalStreamError(stanza);
+  } else if (login_task_.get()) {
+    // Handle login handshake
+    login_task_->IncomingStanza(stanza, false);
+    if (login_task_->IsDone())
+      login_task_.reset();
+  } else if (HandleIqResponse(stanza)) {
+    // iq is handled by above call
+  } else {
+    // give every "peek" handler a shot at all stanzas
+    for (size_t i = 0; i < stanza_handlers_[HL_PEEK]->size(); i += 1) {
+      (*stanza_handlers_[HL_PEEK])[i]->HandleStanza(stanza);
+    }
+
+    // give other handlers a shot in precedence order, stopping after handled
+    for (int level = HL_SINGLE; level <= HL_ALL; level += 1) {
+      for (size_t i = 0; i < stanza_handlers_[level]->size(); i += 1) {
+        if ((*stanza_handlers_[level])[i]->HandleStanza(stanza))
+          goto Handled;
+      }
+    }
+
+    // If nobody wants to handle a stanza then send back an error.
+    // Only do this for IQ stanzas as messages should probably just be dropped
+    // and presence stanzas should certainly be dropped.
+    std::string type = stanza->Attr(QN_TYPE);
+    if (stanza->Name() == QN_IQ && 
+        !(type == "error" || type == "result")) {
+      SendStanzaError(stanza, XSE_FEATURE_NOT_IMPLEMENTED, STR_EMPTY);
+    }
+  }
+  Handled:
+    ; // handled - we're done
+}
+
+void
+XmppEngineImpl::IncomingEnd(bool isError) {
+  if (HasError() || raised_reset_)
+    return;
+
+  SignalError(isError ? ERROR_XML : ERROR_DOCUMENT_CLOSED, 0);
+}
+
+void
+XmppEngineImpl::InternalSendStart(const std::string & to) {
+  std::string hostname = tls_server_hostname_;
+  if (hostname.empty()) {
+    hostname = to;
+  }
+
+  // If not language is specified, the spec says use *
+  std::string lang = lang_;
+  if (lang.length() == 0)
+    lang = "*";
+
+  // send stream-beginning
+  // note, we put a \r\n at tne end fo the first line to cause non-XMPP
+  // line-oriented servers (e.g., Apache) to reveal themselves more quickly.
+  *output_ << "<stream:stream to=\"" << hostname << "\" "
+           << "xml:lang=\"" << lang << "\" "
+           << "version=\"1.0\" "
+           << "xmlns:stream=\"http://etherx.jabber.org/streams\" "
+           << "xmlns=\"jabber:client\">\r\n";
+}
+
+void
+XmppEngineImpl::InternalSendStanza(const XmlElement * element) {
+  // It should really never be necessary to set a FROM attribute on a stanza.
+  // It is implied by the bind on the stream and if you get it wrong
+  // (by flipping from/to on a message?) the server will close the stream.
+  ASSERT(!element->HasAttr(QN_FROM));
+
+  // TODO: consider caching the XmlPrinter
+  XmlPrinter::PrintXml(output_.get(), element,
+            XMPP_CLIENT_NAMESPACES, XMPP_CLIENT_NAMESPACES_LEN);
+}
+
+std::string
+XmppEngineImpl::ChooseBestSaslMechanism(const std::vector<std::string> & mechanisms, bool encrypted) {
+  return sasl_handler_->ChooseBestSaslMechanism(mechanisms, encrypted);
+}
+
+SaslMechanism *
+XmppEngineImpl::GetSaslMechanism(const std::string & name) {
+  return sasl_handler_->CreateSaslMechanism(name);
+}
+
+void
+XmppEngineImpl::SignalBound(const Jid & fullJid) {
+  if (state_ == STATE_OPENING) {
+    bound_jid_ = fullJid;
+    state_ = STATE_OPEN;
+  }
+}
+
+void
+XmppEngineImpl::SignalStreamError(const XmlElement * pelStreamError) {
+  if (state_ != STATE_CLOSED) {
+    stream_error_.reset(new XmlElement(*pelStreamError));
+    SignalError(ERROR_STREAM, 0);
+  }
+}
+
+void
+XmppEngineImpl::SignalError(Error errorCode, int subCode) {
+  if (state_ != STATE_CLOSED) {
+    error_code_ = errorCode;
+    subcode_ = subCode;
+    state_ = STATE_CLOSED;
+  }
+}
+
+bool
+XmppEngineImpl::HasError() {
+  return error_code_ != ERROR_NONE;
+}
+
+void
+XmppEngineImpl::StartTls(const std::string & domain) {
+  if (output_handler_) {
+    output_handler_->StartTls(
+      tls_server_domain_.empty() ? domain : tls_server_domain_);
+    encrypted_ = true;
+  }
+}
+
+XmppEngineImpl::EnterExit::EnterExit(XmppEngineImpl* engine)
+  : engine_(engine),
+  state_(engine->state_),
+  error_(engine->error_code_) {
+  engine->engine_entered_ += 1;
+}
+
+XmppEngineImpl::EnterExit::~EnterExit()  {
+ XmppEngineImpl* engine = engine_;
+
+ engine->engine_entered_ -= 1;
+
+ bool closing = (engine->state_ != state_ &&
+       engine->state_ == STATE_CLOSED);
+ bool flushing = closing || (engine->engine_entered_ == 0);
+
+ if (engine->output_handler_ && flushing) {
+   std::string output = engine->output_->str();
+   if (output.length() > 0)
+     engine->output_handler_->WriteOutput(output.c_str(), output.length());
+   engine->output_->str("");
+
+   if (closing) {
+     engine->output_handler_->CloseConnection();
+     engine->output_handler_ = 0;
+   }
+ }
+
+ if (engine->engine_entered_)
+   return;
+
+ if (engine->raised_reset_) {
+   engine->stanzaParser_.Reset();
+   engine->raised_reset_ = false;
+ }
+
+ if (engine->session_handler_) {
+   if (engine->state_ != state_)
+     engine->session_handler_->OnStateChange(engine->state_);
+     // Note: Handling of OnStateChange(CLOSED) should allow for the
+     // deletion of the engine, so no members should be accessed
+     // after this line.
+ }
+}
+
+}
diff --git a/talk/xmpp/xmppengineimpl.h b/talk/xmpp/xmppengineimpl.h
new file mode 100755
index 0000000..1981035
--- /dev/null
+++ b/talk/xmpp/xmppengineimpl.h
@@ -0,0 +1,276 @@
+/*
+ * 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 _xmppengineimpl_h_
+#define _xmppengineimpl_h_
+
+#include <sstream>
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/xmppstanzaparser.h"
+
+namespace buzz {
+
+class XmppLoginTask;
+class XmppEngine;
+class XmppIqEntry;
+class SaslHandler;
+class SaslMechanism;
+
+
+//! The XMPP connection engine.
+//! This engine implements the client side of the 'core' XMPP protocol.
+//! To use it, register an XmppOutputHandler to handle socket output
+//! and pass socket input to HandleInput.  Then application code can
+//! set up the connection with a user, password, and other settings,
+//! and then call Connect() to initiate the connection.
+//! An application can listen for events and receive stanzas by
+//! registering an XmppStanzaHandler via AddStanzaHandler().
+class XmppEngineImpl : public XmppEngine {
+public:
+  XmppEngineImpl();
+  virtual ~XmppEngineImpl();
+
+  // SOCKET INPUT AND OUTPUT ------------------------------------------------
+
+  //! Registers the handler for socket output
+  virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh);
+
+  //! Provides socket input to the engine
+  virtual XmppReturnStatus HandleInput(const char * bytes, size_t len);
+
+  //! Advises the engine that the socket has closed
+  virtual XmppReturnStatus ConnectionClosed(int subcode);
+
+  // SESSION SETUP ---------------------------------------------------------
+
+  //! Indicates the (bare) JID for the user to use.
+  virtual XmppReturnStatus SetUser(const Jid & jid);
+
+  //! Get the login (bare) JID.
+  virtual const Jid & GetUser();
+
+  //! Indicates the autentication to use.  Takes ownership of the object.
+  virtual XmppReturnStatus SetSaslHandler(SaslHandler * sasl_handler);
+
+  //! Sets whether TLS will be used within the connection (default true).
+  virtual XmppReturnStatus SetUseTls(bool useTls);
+
+  //! Sets an alternate domain from which we allows TLS certificates.
+  //! This is for use in the case where a we want to allow a proxy to
+  //! serve up its own certificate rather than one owned by the underlying
+  //! domain.
+  virtual XmppReturnStatus SetTlsServer(const std::string & proxy_hostname,
+                                        const std::string & proxy_domain);
+
+  //! Gets whether TLS will be used within the connection.
+  virtual bool GetUseTls();
+
+  //! Sets the request resource name, if any (optional).
+  //! Note that the resource name may be overridden by the server; after
+  //! binding, the actual resource name is available as part of FullJid().
+  virtual XmppReturnStatus SetRequestedResource(const std::string& resource);
+
+  //! Gets the request resource name.
+  virtual const std::string & GetRequestedResource();
+
+  //! Sets language
+  virtual void SetLanguage(const std::string & lang) {
+    lang_ = lang;
+  }
+
+  // SESSION MANAGEMENT ---------------------------------------------------
+
+  //! Set callback for state changes.
+  virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler);
+
+  //! Initiates the XMPP connection.
+  //! After supplying connection settings, call this once to initiate,
+  //! (optionally) encrypt, authenticate, and bind the connection.
+  virtual XmppReturnStatus Connect();
+
+  //! The current engine state.
+  virtual State GetState() { return state_; }
+
+  //! Returns true if the connection is encrypted (under TLS)
+  virtual bool IsEncrypted() { return encrypted_; }
+
+  //! The error code.
+  //! Consult this after XmppOutputHandler.OnClose().
+  virtual Error GetError(int *subcode) {
+     if (subcode) {
+       *subcode = subcode_;
+     }
+     return error_code_; 
+  }
+
+  //! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM.
+  //! Notice the stanza returned is owned by the XmppEngine and
+  //! is deleted when the engine is destroyed.
+  virtual const XmlElement * GetStreamError() { return stream_error_.get(); }
+
+  //! Closes down the connection.
+  //! Sends CloseConnection to output, and disconnects and registered
+  //! session handlers.  After Disconnect completes, it is guaranteed
+  //! that no further callbacks will be made.
+  virtual XmppReturnStatus Disconnect();
+
+  // APPLICATION USE -------------------------------------------------------
+
+  //! Adds a listener for session events.
+  //! Stanza delivery is chained to session handlers; the first to
+  //! return 'true' is the last to get each stanza.
+  virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler,
+                                            XmppEngine::HandlerLevel level);
+
+  //! Removes a listener for session events.
+  virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler);
+
+  //! Sends a stanza to the server.
+  virtual XmppReturnStatus SendStanza(const XmlElement * pelStanza);
+
+  //! Sends raw text to the server
+  virtual XmppReturnStatus SendRaw(const std::string & text);
+
+  //! Sends an iq to the server, and registers a callback for the result.
+  //! Returns the cookie passed to the result handler.
+  virtual XmppReturnStatus SendIq(const XmlElement* pelStanza,
+                                  XmppIqHandler* iq_handler,
+                                  XmppIqCookie* cookie);
+
+  //! Unregisters an iq callback handler given its cookie.
+  //! No callback will come to this handler after it's unregistered.
+  virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie,
+                                      XmppIqHandler** iq_handler);
+
+  //! Forms and sends an error in response to the given stanza.
+  //! Swaps to and from, sets type to "error", and adds error information
+  //! based on the passed code.  Text is optional and may be STR_EMPTY.
+  virtual XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal,
+                                           XmppStanzaError code,
+                                           const std::string & text);
+
+  //! The fullly bound JID.
+  //! This JID is only valid after binding has succeeded.  If the value
+  //! is JID_NULL, the binding has not succeeded.
+  virtual const Jid & FullJid() { return bound_jid_; }
+
+  //! The next unused iq id for this connection.
+  //! Call this when building iq stanzas, to ensure that each iq
+  //! gets its own unique id.
+  virtual std::string NextId();
+
+private:
+  friend class XmppLoginTask;
+  friend class XmppIqEntry;
+
+  void IncomingStanza(const XmlElement *pelStanza);
+  void IncomingStart(const XmlElement *pelStanza);
+  void IncomingEnd(bool isError);
+
+  void InternalSendStart(const std::string & domainName);
+  void InternalSendStanza(const XmlElement * pelStanza);
+  std::string ChooseBestSaslMechanism(const std::vector<std::string> & mechanisms, bool encrypted);
+  SaslMechanism * GetSaslMechanism(const std::string & name);
+  void SignalBound(const Jid & fullJid);
+  void SignalStreamError(const XmlElement * pelStreamError);
+  void SignalError(Error errorCode, int subCode);
+  bool HasError();
+  void DeleteIqCookies();
+  bool HandleIqResponse(const XmlElement * element);
+  void StartTls(const std::string & domain);
+  void RaiseReset() { raised_reset_ = true; }
+
+  class StanzaParseHandler : public XmppStanzaParseHandler {
+  public:
+    StanzaParseHandler(XmppEngineImpl * outer) : outer_(outer) {}
+    virtual void StartStream(const XmlElement * pelStream)
+      { outer_->IncomingStart(pelStream); }
+    virtual void Stanza(const XmlElement * pelStanza)
+      { outer_->IncomingStanza(pelStanza); }
+    virtual void EndStream()
+      { outer_->IncomingEnd(false); }
+    virtual void XmlError()
+      { outer_->IncomingEnd(true); }
+  private:
+    XmppEngineImpl * const outer_;
+  };
+
+  class EnterExit {
+   public:
+    EnterExit(XmppEngineImpl* engine);
+    ~EnterExit();
+   private:
+    XmppEngineImpl* engine_;
+    State state_;
+    Error error_;  
+    
+  };
+
+  friend class StanzaParseHandler;
+  friend class EnterExit;
+
+  StanzaParseHandler stanzaParseHandler_;
+  XmppStanzaParser stanzaParser_;
+
+
+  // state
+  int engine_entered_;
+  Jid user_jid_;
+  std::string password_;
+  std::string requested_resource_;
+  bool tls_needed_;
+  std::string tls_server_hostname_;
+  std::string tls_server_domain_;
+  scoped_ptr<XmppLoginTask> login_task_;
+  std::string lang_;
+
+  int next_id_;
+  Jid bound_jid_;
+  State state_;
+  bool encrypted_;
+  Error error_code_;
+  int subcode_;
+  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(XmppIqEntry*) IqEntryVector;
+  scoped_ptr<IqEntryVector> iq_entries_;
+
+  scoped_ptr<SaslHandler> sasl_handler_;
+
+  scoped_ptr<std::stringstream> output_;
+};
+
+}
+
+
+#endif
diff --git a/talk/xmpp/xmppengineimpl_iq.cc b/talk/xmpp/xmppengineimpl_iq.cc
new file mode 100755
index 0000000..5834b90
--- /dev/null
+++ b/talk/xmpp/xmppengineimpl_iq.cc
@@ -0,0 +1,277 @@
+/*
+ * 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 <vector>
+#include <algorithm>
+#include "talk/base/common.h"
+#include "talk/xmpp/xmppengineimpl.h"
+#include "talk/xmpp/constants.h"
+
+namespace buzz {
+
+class XmppIqEntry {
+  XmppIqEntry(const std::string & id, const std::string & to,
+               XmppEngine * pxce, XmppIqHandler * iq_handler) :
+    id_(id),
+    to_(to),
+    engine_(pxce),
+    iq_handler_(iq_handler) {
+  }
+
+private:
+  friend class XmppEngineImpl;
+
+  const std::string id_;
+  const std::string to_;
+  XmppEngine * const engine_;
+  XmppIqHandler * const iq_handler_;
+};
+
+
+XmppReturnStatus
+XmppEngineImpl::SendIq(const XmlElement * element, XmppIqHandler * iq_handler,
+  XmppIqCookie* cookie) {
+  if (state_ == STATE_CLOSED)
+    return XMPP_RETURN_BADSTATE;
+  if (NULL == iq_handler)
+    return XMPP_RETURN_BADARGUMENT;
+  if (!element || element->Name() != QN_IQ)
+    return XMPP_RETURN_BADARGUMENT;
+
+  const std::string& type = element->Attr(QN_TYPE);
+  if (type != "get" && type != "set")
+    return XMPP_RETURN_BADARGUMENT;
+
+  if (!element->HasAttr(QN_ID))
+    return XMPP_RETURN_BADARGUMENT;
+  const std::string& id = element->Attr(QN_ID);
+
+  XmppIqEntry * iq_entry = new XmppIqEntry(id,
+                                              element->Attr(QN_TO),
+                                              this, iq_handler);
+  iq_entries_->push_back(iq_entry);
+  SendStanza(element);
+
+  if (cookie)
+    *cookie = iq_entry;
+
+  return XMPP_RETURN_OK;
+}
+
+
+XmppReturnStatus
+XmppEngineImpl::RemoveIqHandler(XmppIqCookie cookie,
+    XmppIqHandler ** iq_handler) {
+
+  std::vector<XmppIqEntry*, std::allocator<XmppIqEntry*> >::iterator pos;
+
+  pos = std::find(iq_entries_->begin(),
+                  iq_entries_->end(),
+                  reinterpret_cast<XmppIqEntry*>(cookie));
+
+  if (pos == iq_entries_->end())
+    return XMPP_RETURN_BADARGUMENT;
+
+  XmppIqEntry* entry = *pos;
+  iq_entries_->erase(pos);
+  if (iq_handler)
+    *iq_handler = entry->iq_handler_;
+  delete entry;
+
+  return XMPP_RETURN_OK;
+}
+
+void
+XmppEngineImpl::DeleteIqCookies() {
+  for (size_t i = 0; i < iq_entries_->size(); i += 1) {
+    XmppIqEntry * iq_entry_ = (*iq_entries_)[i];
+    (*iq_entries_)[i] = NULL;
+    delete iq_entry_;
+  }
+  iq_entries_->clear();
+}
+
+static void
+AecImpl(XmlElement * error_element, const QName & name,
+        const char * type, const char * code) {
+  error_element->AddElement(new XmlElement(QN_ERROR));
+  error_element->AddAttr(QN_CODE, code, 1);
+  error_element->AddAttr(QN_TYPE, type, 1);
+  error_element->AddElement(new XmlElement(name, true), 1);
+}
+
+
+static void
+AddErrorCode(XmlElement * error_element, XmppStanzaError code) {
+  switch (code) {
+    case XSE_BAD_REQUEST:
+      AecImpl(error_element, QN_STANZA_BAD_REQUEST, "modify", "400");
+      break;
+    case XSE_CONFLICT:
+      AecImpl(error_element, QN_STANZA_CONFLICT, "cancel", "409");
+      break;
+    case XSE_FEATURE_NOT_IMPLEMENTED:
+      AecImpl(error_element, QN_STANZA_FEATURE_NOT_IMPLEMENTED,
+              "cancel", "501");
+      break;
+    case XSE_FORBIDDEN:
+      AecImpl(error_element, QN_STANZA_FORBIDDEN, "auth", "403");
+      break;
+    case XSE_GONE:
+      AecImpl(error_element, QN_STANZA_GONE, "modify", "302");
+      break;
+    case XSE_INTERNAL_SERVER_ERROR:
+      AecImpl(error_element, QN_STANZA_INTERNAL_SERVER_ERROR, "wait", "500");
+      break;
+    case XSE_ITEM_NOT_FOUND:
+      AecImpl(error_element, QN_STANZA_ITEM_NOT_FOUND, "cancel", "404");
+      break;
+    case XSE_JID_MALFORMED:
+      AecImpl(error_element, QN_STANZA_JID_MALFORMED, "modify", "400");
+      break;
+    case XSE_NOT_ACCEPTABLE:
+      AecImpl(error_element, QN_STANZA_NOT_ACCEPTABLE, "cancel", "406");
+      break;
+    case XSE_NOT_ALLOWED:
+      AecImpl(error_element, QN_STANZA_NOT_ALLOWED, "cancel", "405");
+      break;
+    case XSE_PAYMENT_REQUIRED:
+      AecImpl(error_element, QN_STANZA_PAYMENT_REQUIRED, "auth", "402");
+      break;
+    case XSE_RECIPIENT_UNAVAILABLE:
+      AecImpl(error_element, QN_STANZA_RECIPIENT_UNAVAILABLE, "wait", "404");
+      break;
+    case XSE_REDIRECT:
+      AecImpl(error_element, QN_STANZA_REDIRECT, "modify", "302");
+      break;
+    case XSE_REGISTRATION_REQUIRED:
+      AecImpl(error_element, QN_STANZA_REGISTRATION_REQUIRED, "auth", "407");
+      break;
+    case XSE_SERVER_NOT_FOUND:
+      AecImpl(error_element, QN_STANZA_REMOTE_SERVER_NOT_FOUND,
+              "cancel", "404");
+      break;
+    case XSE_SERVER_TIMEOUT:
+      AecImpl(error_element, QN_STANZA_REMOTE_SERVER_TIMEOUT, "wait", "502");
+      break;
+    case XSE_RESOURCE_CONSTRAINT:
+      AecImpl(error_element, QN_STANZA_RESOURCE_CONSTRAINT, "wait", "500");
+      break;
+    case XSE_SERVICE_UNAVAILABLE:
+      AecImpl(error_element, QN_STANZA_SERVICE_UNAVAILABLE, "cancel", "503");
+      break;
+    case XSE_SUBSCRIPTION_REQUIRED:
+      AecImpl(error_element, QN_STANZA_SUBSCRIPTION_REQUIRED, "auth", "407");
+      break;
+    case XSE_UNDEFINED_CONDITION:
+      AecImpl(error_element, QN_STANZA_UNDEFINED_CONDITION, "wait", "500");
+      break;
+    case XSE_UNEXPECTED_REQUEST:
+      AecImpl(error_element, QN_STANZA_UNEXPECTED_REQUEST, "wait", "400");
+      break;
+  }
+}
+
+
+XmppReturnStatus
+XmppEngineImpl::SendStanzaError(const XmlElement * element_original,
+                                XmppStanzaError code,
+                                const std::string & text) {
+
+  if (state_ == STATE_CLOSED)
+    return XMPP_RETURN_BADSTATE;
+
+  XmlElement error_element(element_original->Name());
+  error_element.AddAttr(QN_TYPE, "error");
+
+  // copy attrs, copy 'from' to 'to' and strip 'from'
+  for (const XmlAttr * attribute = element_original->FirstAttr();
+       attribute; attribute = attribute->NextAttr()) {
+    QName name = attribute->Name();
+    if (name == QN_TO)
+      continue; // no need to put a from attr.  Server will stamp stanza
+    else if (name == QN_FROM)
+      name = QN_TO;
+    else if (name == QN_TYPE)
+      continue;
+    error_element.AddAttr(name, attribute->Value());
+  }
+
+  // copy children
+  for (const XmlChild * child = element_original->FirstChild();
+       child;
+       child = child->NextChild()) {
+    if (child->IsText()) {
+      error_element.AddText(child->AsText()->Text());
+    } else {
+      error_element.AddElement(new XmlElement(*(child->AsElement())));
+    }
+  }
+
+  // add error information
+  AddErrorCode(&error_element, code);
+  if (text != STR_EMPTY) {
+    XmlElement * text_element = new XmlElement(QN_STANZA_TEXT, true);
+    text_element->AddText(text);
+    error_element.AddElement(text_element);
+  }
+
+  SendStanza(&error_element);
+
+  return XMPP_RETURN_OK;
+}
+
+
+bool
+XmppEngineImpl::HandleIqResponse(const XmlElement * element) {
+  if (iq_entries_->empty())
+    return false;
+  if (element->Name() != QN_IQ)
+    return false;
+  std::string type = element->Attr(QN_TYPE);
+  if (type != "result" && type != "error")
+    return false;
+  if (!element->HasAttr(QN_ID))
+    return false;
+  std::string id = element->Attr(QN_ID);
+  std::string from = element->Attr(QN_FROM);
+
+  for (std::vector<XmppIqEntry *>::iterator it = iq_entries_->begin();
+       it != iq_entries_->end(); it += 1) {
+    XmppIqEntry * iq_entry = *it;
+    if (iq_entry->id_ == id && iq_entry->to_ == from) {
+      iq_entries_->erase(it);
+      iq_entry->iq_handler_->IqResponse(iq_entry, element);
+      delete iq_entry;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+}
diff --git a/talk/xmpp/xmpplogintask.cc b/talk/xmpp/xmpplogintask.cc
new file mode 100755
index 0000000..5101089
--- /dev/null
+++ b/talk/xmpp/xmpplogintask.cc
@@ -0,0 +1,383 @@
+/*
+ * 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 <string>
+#include <vector>
+#include "talk/base/base64.h"
+#include "talk/base/common.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/jid.h"
+#include "talk/xmpp/saslmechanism.h"
+#include "talk/xmpp/xmppengineimpl.h"
+#include "talk/xmpp/xmpplogintask.h"
+
+using talk_base::ConstantLabel;
+
+namespace buzz {
+
+#ifdef _DEBUG
+const ConstantLabel XmppLoginTask::LOGINTASK_STATES[] = {
+  KLABEL(LOGINSTATE_INIT),
+  KLABEL(LOGINSTATE_STREAMSTART_SENT),
+  KLABEL(LOGINSTATE_STARTED_XMPP),
+  KLABEL(LOGINSTATE_TLS_INIT),
+  KLABEL(LOGINSTATE_AUTH_INIT),
+  KLABEL(LOGINSTATE_BIND_INIT),
+  KLABEL(LOGINSTATE_TLS_REQUESTED),
+  KLABEL(LOGINSTATE_SASL_RUNNING),
+  KLABEL(LOGINSTATE_BIND_REQUESTED),
+  KLABEL(LOGINSTATE_SESSION_REQUESTED),
+  KLABEL(LOGINSTATE_DONE),
+  LASTLABEL
+};
+#endif  // _DEBUG
+
+XmppLoginTask::XmppLoginTask(XmppEngineImpl * pctx) :
+  pctx_(pctx),
+  authNeeded_(true),
+  state_(LOGINSTATE_INIT),
+  pelStanza_(NULL),
+  isStart_(false),
+  iqId_(STR_EMPTY),
+  pelFeatures_(NULL),
+  fullJid_(STR_EMPTY),
+  streamId_(STR_EMPTY),
+  pvecQueuedStanzas_(new std::vector<XmlElement *>()),
+  sasl_mech_(NULL) {
+}
+
+XmppLoginTask::~XmppLoginTask() {
+  for (size_t i = 0; i < pvecQueuedStanzas_->size(); i += 1)
+    delete (*pvecQueuedStanzas_)[i];
+}
+
+void
+XmppLoginTask::IncomingStanza(const XmlElement *element, bool isStart) {
+  pelStanza_ = element;
+  isStart_ = isStart;
+  Advance();
+  pelStanza_ = NULL;
+  isStart_ = false;
+}
+
+const XmlElement *
+XmppLoginTask::NextStanza() {
+  const XmlElement * result = pelStanza_;
+  pelStanza_ = NULL;
+  return result;
+}
+
+bool
+XmppLoginTask::Advance() {
+
+  for (;;) {
+
+    const XmlElement * element = NULL;
+
+#if _DEBUG
+    LOG(LS_VERBOSE) << "XmppLoginTask::Advance - "
+      << talk_base::ErrorName(state_, LOGINTASK_STATES);
+#endif  // _DEBUG
+
+    switch (state_) {
+
+      case LOGINSTATE_INIT: {
+        pctx_->RaiseReset();
+        pelFeatures_.reset(NULL);
+
+        // The proper domain to verify against is the real underlying
+        // domain - i.e., the domain that owns the JID.  Our XmppEngineImpl
+        // also allows matching against a proxy domain instead, if it is told
+        // to do so - see the implementation of XmppEngineImpl::StartTls and
+        // XmppEngine::SetTlsServerDomain to see how you can use that feature
+        pctx_->InternalSendStart(pctx_->user_jid_.domain());
+        state_ = LOGINSTATE_STREAMSTART_SENT;
+        break;
+      }
+
+      case LOGINSTATE_STREAMSTART_SENT: {
+        if (NULL == (element = NextStanza()))
+          return true;
+
+        if (!isStart_ || !HandleStartStream(element))
+          return Failure(XmppEngine::ERROR_VERSION);
+
+        state_ = LOGINSTATE_STARTED_XMPP;
+        return true;
+      }
+
+      case LOGINSTATE_STARTED_XMPP: {
+        if (NULL == (element = NextStanza()))
+          return true;
+
+        if (!HandleFeatures(element))
+          return Failure(XmppEngine::ERROR_VERSION);
+
+        // Use TLS if forced, or if available
+        if (pctx_->tls_needed_ || GetFeature(QN_TLS_STARTTLS) != NULL) {
+          state_ = LOGINSTATE_TLS_INIT;
+          continue;
+        }
+
+        if (authNeeded_) {
+          state_ = LOGINSTATE_AUTH_INIT;
+          continue;
+        }
+
+        state_ = LOGINSTATE_BIND_INIT;
+        continue;
+      }
+
+      case LOGINSTATE_TLS_INIT: {
+        const XmlElement * pelTls = GetFeature(QN_TLS_STARTTLS);
+        if (!pelTls)
+          return Failure(XmppEngine::ERROR_TLS);
+
+        XmlElement el(QN_TLS_STARTTLS, true);
+        pctx_->InternalSendStanza(&el);
+        state_ = LOGINSTATE_TLS_REQUESTED;
+        continue;
+      }
+
+      case LOGINSTATE_TLS_REQUESTED: {
+        if (NULL == (element = NextStanza()))
+          return true;
+        if (element->Name() != QN_TLS_PROCEED)
+          return Failure(XmppEngine::ERROR_TLS);
+
+        // The proper domain to verify against is the real underlying
+        // domain - i.e., the domain that owns the JID.  Our XmppEngineImpl
+        // also allows matching against a proxy domain instead, if it is told
+        // to do so - see the implementation of XmppEngineImpl::StartTls and
+        // XmppEngine::SetTlsServerDomain to see how you can use that feature
+        pctx_->StartTls(pctx_->user_jid_.domain());
+        pctx_->tls_needed_ = false;
+        state_ = LOGINSTATE_INIT;
+        continue;
+      }
+
+      case LOGINSTATE_AUTH_INIT: {
+        const XmlElement * pelSaslAuth = GetFeature(QN_SASL_MECHANISMS);
+        if (!pelSaslAuth) {
+          return Failure(XmppEngine::ERROR_AUTH);
+        }
+
+        // Collect together the SASL auth mechanisms presented by the server
+        std::vector<std::string> mechanisms;
+        for (const XmlElement * pelMech =
+             pelSaslAuth->FirstNamed(QN_SASL_MECHANISM);
+             pelMech;
+             pelMech = pelMech->NextNamed(QN_SASL_MECHANISM)) {
+
+          mechanisms.push_back(pelMech->BodyText());
+        }
+
+        // Given all the mechanisms, choose the best
+        std::string choice(pctx_->ChooseBestSaslMechanism(mechanisms, pctx_->IsEncrypted()));
+        if (choice.empty()) {
+          return Failure(XmppEngine::ERROR_AUTH);
+        }
+
+        // No recognized auth mechanism - that's an error
+        sasl_mech_.reset(pctx_->GetSaslMechanism(choice));
+        if (sasl_mech_.get() == NULL) {
+          return Failure(XmppEngine::ERROR_AUTH);
+        }
+
+        // OK, let's start it.
+        XmlElement * auth = sasl_mech_->StartSaslAuth();
+        if (auth == NULL) {
+          return Failure(XmppEngine::ERROR_AUTH);
+        }
+
+        pctx_->InternalSendStanza(auth);
+        delete auth;
+        state_ = LOGINSTATE_SASL_RUNNING;
+        continue;
+      }
+        
+      case LOGINSTATE_SASL_RUNNING: {
+        if (NULL == (element = NextStanza()))
+          return true;
+        if (element->Name().Namespace() != NS_SASL)
+          return Failure(XmppEngine::ERROR_AUTH);
+        if (element->Name() == QN_SASL_CHALLENGE) {
+          XmlElement * response = sasl_mech_->HandleSaslChallenge(element);
+          if (response == NULL) {
+            return Failure(XmppEngine::ERROR_AUTH);
+          }
+          pctx_->InternalSendStanza(response);
+          delete response;
+          state_ = LOGINSTATE_SASL_RUNNING;
+          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);
+        }
+
+        // Authenticated!
+        authNeeded_ = false;
+        state_ = LOGINSTATE_INIT;
+        continue;
+      }
+
+      case LOGINSTATE_BIND_INIT: {
+        const XmlElement * pelBindFeature = GetFeature(QN_BIND_BIND);
+        const XmlElement * pelSessionFeature = GetFeature(QN_SESSION_SESSION);
+        if (!pelBindFeature || !pelSessionFeature)
+          return Failure(XmppEngine::ERROR_BIND);
+
+        XmlElement iq(QN_IQ);
+        iq.AddAttr(QN_TYPE, "set");
+
+        iqId_ = pctx_->NextId();
+        iq.AddAttr(QN_ID, iqId_);
+        iq.AddElement(new XmlElement(QN_BIND_BIND, true));
+
+        if (pctx_->requested_resource_ != STR_EMPTY) {
+          iq.AddElement(new XmlElement(QN_BIND_RESOURCE), 1);
+          iq.AddText(pctx_->requested_resource_, 2);
+        }
+        pctx_->InternalSendStanza(&iq);
+        state_ = LOGINSTATE_BIND_REQUESTED;
+        continue;
+      }
+
+      case LOGINSTATE_BIND_REQUESTED: {
+        if (NULL == (element = NextStanza()))
+          return true;
+
+        if (element->Name() != QN_IQ || element->Attr(QN_ID) != iqId_ ||
+            element->Attr(QN_TYPE) == "get" || element->Attr(QN_TYPE) == "set")
+          return true;
+
+        if (element->Attr(QN_TYPE) != "result" || element->FirstElement() == NULL ||
+            element->FirstElement()->Name() != QN_BIND_BIND)
+          return Failure(XmppEngine::ERROR_BIND);
+
+        fullJid_ = Jid(element->FirstElement()->TextNamed(QN_BIND_JID));
+        if (!fullJid_.IsFull()) {
+          return Failure(XmppEngine::ERROR_BIND);
+        }
+
+        // now request session
+        XmlElement iq(QN_IQ);
+        iq.AddAttr(QN_TYPE, "set");
+
+        iqId_ = pctx_->NextId();
+        iq.AddAttr(QN_ID, iqId_);
+        iq.AddElement(new XmlElement(QN_SESSION_SESSION, true));
+        pctx_->InternalSendStanza(&iq);
+
+        state_ = LOGINSTATE_SESSION_REQUESTED;
+        continue;
+      }
+
+      case LOGINSTATE_SESSION_REQUESTED: {
+        if (NULL == (element = NextStanza()))
+          return true;
+        if (element->Name() != QN_IQ || element->Attr(QN_ID) != iqId_ ||
+            element->Attr(QN_TYPE) == "get" || element->Attr(QN_TYPE) == "set")
+          return false;
+
+        if (element->Attr(QN_TYPE) != "result")
+          return Failure(XmppEngine::ERROR_BIND);
+
+        pctx_->SignalBound(fullJid_);
+        FlushQueuedStanzas();
+        state_ = LOGINSTATE_DONE;
+        return true;
+      }
+
+      case LOGINSTATE_DONE:
+        return false;
+    }
+  }
+}
+
+bool
+XmppLoginTask::HandleStartStream(const XmlElement *element) {
+
+  if (element->Name() != QN_STREAM_STREAM)
+    return false;
+
+  if (element->Attr(QN_XMLNS) != "jabber:client")
+    return false;
+
+  if (element->Attr(QN_VERSION) != "1.0")
+    return false;
+
+  if (!element->HasAttr(QN_ID))
+    return false;
+  
+  streamId_ = element->Attr(QN_ID);
+
+  return true;
+}
+
+bool
+XmppLoginTask::HandleFeatures(const XmlElement *element) {
+  if (element->Name() != QN_STREAM_FEATURES)
+    return false;
+
+  pelFeatures_.reset(new XmlElement(*element));
+  return true;
+}
+
+const XmlElement *
+XmppLoginTask::GetFeature(const QName & name) {
+  return pelFeatures_->FirstNamed(name);
+}
+
+bool
+XmppLoginTask::Failure(XmppEngine::Error reason) {
+  state_ = LOGINSTATE_DONE;
+  pctx_->SignalError(reason, 0);
+  return false;
+}
+
+void
+XmppLoginTask::OutgoingStanza(const XmlElement * element) {
+  XmlElement * pelCopy = new XmlElement(*element);
+  pvecQueuedStanzas_->push_back(pelCopy);
+}
+
+void
+XmppLoginTask::FlushQueuedStanzas() {
+  for (size_t i = 0; i < pvecQueuedStanzas_->size(); i += 1) {
+    pctx_->InternalSendStanza((*pvecQueuedStanzas_)[i]);
+    delete (*pvecQueuedStanzas_)[i];
+  }
+  pvecQueuedStanzas_->clear();
+}
+
+}
diff --git a/talk/xmpp/xmpplogintask.h b/talk/xmpp/xmpplogintask.h
new file mode 100755
index 0000000..993a6bf
--- /dev/null
+++ b/talk/xmpp/xmpplogintask.h
@@ -0,0 +1,100 @@
+/*
+ * 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 _logintask_h_
+#define _logintask_h_
+
+#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"
+
+namespace buzz {
+
+class XmlElement;
+class XmppEngineImpl;
+class SaslMechanism;
+
+
+class XmppLoginTask {
+
+public:
+  XmppLoginTask(XmppEngineImpl *pctx);
+  ~XmppLoginTask();
+
+  bool IsDone()
+    { return state_ == LOGINSTATE_DONE; }
+  void IncomingStanza(const XmlElement * element, bool isStart);
+  void OutgoingStanza(const XmlElement *element);
+
+private:
+  enum LoginTaskState {
+    LOGINSTATE_INIT = 0,
+    LOGINSTATE_STREAMSTART_SENT,
+    LOGINSTATE_STARTED_XMPP,
+    LOGINSTATE_TLS_INIT,
+    LOGINSTATE_AUTH_INIT,
+    LOGINSTATE_BIND_INIT,
+    LOGINSTATE_TLS_REQUESTED,
+    LOGINSTATE_SASL_RUNNING,
+    LOGINSTATE_BIND_REQUESTED,
+    LOGINSTATE_SESSION_REQUESTED,
+    LOGINSTATE_DONE,
+  };
+
+  const XmlElement * NextStanza();
+  bool Advance();
+  bool HandleStartStream(const XmlElement * element);
+  bool HandleFeatures(const XmlElement * element);
+  const XmlElement * GetFeature(const QName & name);
+  bool Failure(XmppEngine::Error reason);
+  void FlushQueuedStanzas();
+
+  XmppEngineImpl * pctx_;
+  bool authNeeded_;
+  LoginTaskState state_;
+  const XmlElement * pelStanza_;
+  bool isStart_;
+  std::string iqId_;
+  scoped_ptr<XmlElement> pelFeatures_;
+  Jid fullJid_;
+  std::string streamId_;
+  scoped_ptr<std::vector<XmlElement *,
+          std::allocator<XmlElement *> > > pvecQueuedStanzas_;
+  
+  scoped_ptr<SaslMechanism> sasl_mech_;
+
+#ifdef _DEBUG
+  static const talk_base::ConstantLabel LOGINTASK_STATES[];
+#endif  // _DEBUG
+};
+
+}
+
+#endif
diff --git a/talk/xmpp/xmppstanzaparser.cc b/talk/xmpp/xmppstanzaparser.cc
new file mode 100755
index 0000000..66ed44f
--- /dev/null
+++ b/talk/xmpp/xmppstanzaparser.cc
@@ -0,0 +1,104 @@
+/*
+ * 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 <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
+
+namespace buzz {
+
+XmppStanzaParser::XmppStanzaParser(XmppStanzaParseHandler *psph) :
+  psph_(psph),
+  innerHandler_(this),
+  parser_(&innerHandler_),
+  depth_(0),
+  builder_() {
+}
+
+void
+XmppStanzaParser::Reset() {
+  parser_.Reset();
+  depth_ = 0;
+  builder_.Reset();
+}
+
+void
+XmppStanzaParser::IncomingStartElement(
+    XmlParseContext * pctx, const char * name, const char ** atts) {
+  if (depth_++ == 0) {
+    XmlElement * pelStream = XmlBuilder::BuildElement(pctx, name, atts);
+    if (pelStream == NULL) {
+      pctx->RaiseError(XML_ERROR_SYNTAX);
+      return;
+    }
+    psph_->StartStream(pelStream);
+    delete pelStream;
+    return;
+  }
+
+  builder_.StartElement(pctx, name, atts);
+}
+
+void
+XmppStanzaParser::IncomingCharacterData(
+    XmlParseContext * pctx, const char * text, int len) {
+  if (depth_ > 1) {
+    builder_.CharacterData(pctx, text, len);
+  }
+}
+
+void
+XmppStanzaParser::IncomingEndElement(
+    XmlParseContext * pctx, const char * name) {
+  if (--depth_ == 0) {
+    psph_->EndStream();
+    return;
+  }
+
+  builder_.EndElement(pctx, name);
+
+  if (depth_ == 1) {
+    XmlElement *element = builder_.CreateElement();
+    psph_->Stanza(element);
+    delete element;
+  }
+}
+
+void
+XmppStanzaParser::IncomingError(
+    XmlParseContext * pctx, XML_Error errCode) {
+  UNUSED(pctx);
+  UNUSED(errCode);
+  psph_->XmlError();
+}
+
+}
+
diff --git a/talk/xmpp/xmppstanzaparser.h b/talk/xmpp/xmppstanzaparser.h
new file mode 100755
index 0000000..1e109a3
--- /dev/null
+++ b/talk/xmpp/xmppstanzaparser.h
@@ -0,0 +1,96 @@
+/*
+ * 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 _xmppstanzaparser_h_
+#define _xmppstanzaparser_h_
+
+#include "talk/xmllite/xmlparser.h"
+#include "talk/xmllite/xmlbuilder.h"
+
+
+namespace buzz {
+
+class XmlElement;
+
+class XmppStanzaParseHandler {
+public:
+  virtual void StartStream(const XmlElement * pelStream) = 0;
+  virtual void Stanza(const XmlElement * pelStanza) = 0;
+  virtual void EndStream() = 0;
+  virtual void XmlError() = 0;
+};
+
+class XmppStanzaParser {
+public:
+  XmppStanzaParser(XmppStanzaParseHandler *psph);
+  bool Parse(const char * data, size_t len, bool isFinal)
+    { return parser_.Parse(data, len, isFinal); }
+  void Reset();
+
+private:
+  class ParseHandler : public XmlParseHandler {
+  public:
+    ParseHandler(XmppStanzaParser * outer) : outer_(outer) {}
+    virtual void StartElement(XmlParseContext * pctx,
+               const char * name, const char ** atts)
+      { outer_->IncomingStartElement(pctx, name, atts); }
+    virtual void EndElement(XmlParseContext * pctx,
+               const char * name)
+      { outer_->IncomingEndElement(pctx, name); }
+    virtual void CharacterData(XmlParseContext * pctx,
+               const char * text, int len)
+      { outer_->IncomingCharacterData(pctx, text, len); }
+    virtual void Error(XmlParseContext * pctx,
+               XML_Error errCode)
+      { outer_->IncomingError(pctx, errCode); }
+  private:
+    XmppStanzaParser * const outer_;
+  };
+
+  friend class ParseHandler;
+
+  void IncomingStartElement(XmlParseContext * pctx,
+               const char * name, const char ** atts);
+  void IncomingEndElement(XmlParseContext * pctx,
+               const char * name);
+  void IncomingCharacterData(XmlParseContext * pctx,
+               const char * text, int len);
+  void IncomingError(XmlParseContext * pctx,
+               XML_Error errCode);
+
+  XmppStanzaParseHandler * psph_;
+  ParseHandler innerHandler_;
+  XmlParser parser_;
+  int depth_;
+  XmlBuilder builder_;
+
+ };
+
+
+}
+
+#endif
diff --git a/talk/xmpp/xmpptask.cc b/talk/xmpp/xmpptask.cc
new file mode 100755
index 0000000..4756bbe
--- /dev/null
+++ b/talk/xmpp/xmpptask.cc
@@ -0,0 +1,174 @@
+/*
+ * 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/xmpp/xmpptask.h"
+#include "talk/xmpp/xmppclient.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/ratelimitmanager.h"
+
+namespace buzz {
+
+RateLimitManager task_rate_manager;
+
+XmppTask::XmppTask(Task* parent, XmppEngine::HandlerLevel level)
+    : Task(parent), client_(NULL) {
+#ifdef _DEBUG
+  debug_force_timeout_ = false;
+#endif
+
+  XmppClient* client = (XmppClient*)parent->GetParent(XMPP_CLIENT_TASK_CODE);
+  client_ = client;
+  id_ = client->NextId();
+  client->AddXmppTask(this, level);
+  client->SignalDisconnected.connect(this, &XmppTask::OnDisconnect);
+}
+
+XmppTask::~XmppTask() {
+  StopImpl();
+}
+
+void XmppTask::StopImpl() {
+  while (NextStanza() != NULL) {}
+  if (client_) {
+    client_->RemoveXmppTask(this);
+    client_->SignalDisconnected.disconnect(this);
+    client_ = NULL;
+  }
+}
+
+XmppReturnStatus XmppTask::SendStanza(const XmlElement* stanza) {
+  if (client_ == NULL)
+    return XMPP_RETURN_BADSTATE;
+  return client_->SendStanza(stanza);
+}
+
+XmppReturnStatus XmppTask::SendStanzaError(const XmlElement* element_original,
+                                           XmppStanzaError code,
+                                           const std::string& text) {
+  if (client_ == NULL)
+    return XMPP_RETURN_BADSTATE;
+  return client_->SendStanzaError(element_original, code, text);
+}
+
+void XmppTask::Stop() {
+  StopImpl();
+  Task::Stop();
+}
+
+void XmppTask::OnDisconnect() {
+  Error();
+}
+
+void XmppTask::QueueStanza(const XmlElement* stanza) {
+#ifdef _DEBUG
+  if (debug_force_timeout_)
+    return;
+#endif
+
+  stanza_queue_.push_back(new XmlElement(*stanza));
+  Wake();
+}
+
+const XmlElement* XmppTask::NextStanza() {
+  XmlElement* result = NULL;
+  if (!stanza_queue_.empty()) {
+    result = stanza_queue_.front();
+    stanza_queue_.pop_front();
+  }
+  next_stanza_.reset(result);
+  return result;
+}
+
+XmlElement* XmppTask::MakeIq(const std::string& type,
+                             const buzz::Jid& to,
+                             const std::string id) {
+  XmlElement* result = new XmlElement(QN_IQ);
+  if (!type.empty())
+    result->AddAttr(QN_TYPE, type);
+  if (to != JID_EMPTY)
+    result->AddAttr(QN_TO, to.Str());
+  if (!id.empty())
+    result->AddAttr(QN_ID, id);
+  return result;
+}
+
+XmlElement* XmppTask::MakeIqResult(const XmlElement * query) {
+  XmlElement* result = new XmlElement(QN_IQ);
+  result->AddAttr(QN_TYPE, STR_RESULT);
+  if (query->HasAttr(QN_FROM)) {
+    result->AddAttr(QN_TO, query->Attr(QN_FROM));
+  }
+  result->AddAttr(QN_ID, query->Attr(QN_ID));
+  return result;
+}
+
+bool XmppTask::MatchResponseIq(const XmlElement* stanza,
+                               const Jid& to,
+                               const std::string& id) {
+  if (stanza->Name() != QN_IQ)
+    return false;
+
+  if (stanza->Attr(QN_ID) != id)
+    return false;
+
+  Jid from(stanza->Attr(QN_FROM));
+  if (from == to)
+    return true;
+
+  // We address the server as "", check if we are doing so here.
+  if (to != JID_EMPTY)
+    return false;
+
+  // It is legal for the server to identify itself with "domain" or
+  // "myself@domain"
+  Jid me = client_->jid();
+  return (from == Jid(me.domain())) || (from == me.BareJid());
+}
+
+bool XmppTask::MatchRequestIq(const XmlElement* stanza,
+                              const std::string& type,
+                              const QName& qn) {
+  if (stanza->Name() != QN_IQ)
+    return false;
+
+  if (stanza->Attr(QN_TYPE) != type)
+    return false;
+
+  if (stanza->FirstNamed(qn) == NULL)
+    return false;
+
+  return true;
+} 
+
+bool XmppTask::VerifyTaskRateLimit(const std::string task_name, int max_count, 
+                                   int per_x_seconds) {
+  return task_rate_manager.VerifyRateLimit(task_name, max_count, 
+                                           per_x_seconds);
+}
+
+}
\ No newline at end of file
diff --git a/talk/xmpp/xmpptask.h b/talk/xmpp/xmpptask.h
new file mode 100755
index 0000000..156c9a5
--- /dev/null
+++ b/talk/xmpp/xmpptask.h
@@ -0,0 +1,130 @@
+/*
+ * 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 _XMPPTASK_H_
+#define _XMPPTASK_H_
+
+#include <string>
+#include <deque>
+#include "talk/base/sigslot.h"
+#include "talk/xmpp/xmppengine.h"
+#include "talk/base/task.h"
+
+namespace buzz {
+
+/////////////////////////////////////////////////////////////////////
+//
+// XMPPTASK
+//
+/////////////////////////////////////////////////////////////////////
+//
+// See Task and XmppClient first.
+//
+// XmppTask is a task that is designed to go underneath XmppClient and be
+// useful there.  It has a way of finding its XmppClient parent so you
+// can have it nested arbitrarily deep under an XmppClient and it can
+// still find the XMPP services.
+//
+// Tasks register themselves to listen to particular kinds of stanzas
+// that are sent out by the client.  Rather than processing stanzas
+// right away, they should decide if they own the sent stanza,
+// and if so, queue it and Wake() the task, or if a stanza does not belong
+// to you, return false right away so the next XmppTask can take a crack.
+// This technique (synchronous recognize, but asynchronous processing)
+// allows you to have arbitrary logic for recognizing stanzas yet still,
+// for example, disconnect a client while processing a stanza -
+// without reentrancy problems.
+//
+/////////////////////////////////////////////////////////////////////
+
+class XmppClient;
+
+class XmppTask :
+  public talk_base::Task,
+  public XmppStanzaHandler,
+  public sigslot::has_slots<>
+{
+ public:
+  XmppTask(talk_base::Task* parent, 
+           XmppEngine::HandlerLevel level = XmppEngine::HL_NONE);
+  virtual ~XmppTask();
+
+  virtual XmppClient* GetClient() const { return client_; }
+  std::string task_id() const { return id_; }
+  void set_task_id(std::string id) { id_ = id; }
+
+#ifdef _DEBUG
+  void set_debug_force_timeout(const bool f) { debug_force_timeout_ = f; }
+#endif
+
+ protected:
+  friend class XmppClient;
+
+  XmppReturnStatus SendStanza(const XmlElement* stanza);
+  XmppReturnStatus SetResult(const std::string& code);
+  XmppReturnStatus SendStanzaError(const XmlElement* element_original,
+                                   XmppStanzaError code,
+                                   const std::string& text);
+
+  virtual void Stop();
+  virtual bool HandleStanza(const XmlElement* stanza) { return false; }
+  virtual void OnDisconnect();
+  virtual int ProcessReponse() { return STATE_DONE; }
+
+  virtual void QueueStanza(const XmlElement* stanza);
+  const XmlElement* NextStanza();
+
+  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);
+
+  // 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, 
+                           int per_x_seconds);
+
+private:
+  void StopImpl();
+
+  XmppClient* client_;
+  std::deque<XmlElement*> stanza_queue_;
+  scoped_ptr<XmlElement> next_stanza_;
+  std::string id_;
+
+#ifdef _DEBUG
+  bool debug_force_timeout_;
+#endif                         
+};
+
+}
+
+#endif