Update to libjingle 0.5.6.

git-svn-id: http://libjingle.googlecode.com/svn/trunk@65 dd674b97-3498-5ee5-1854-bdd07cd0ff33
diff --git a/CHANGELOG b/CHANGELOG
index 7dbfbe8..88c5d23 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
 Libjingle
 
+0.5.6 - Jun 2, 2011
+  - Add IqTask
+  - Flush output in examples/call
+  - Bug fixes
+
 0.5.5 - May 26, 2011
   - Refactor async sockets
   - Improve MUC joining
diff --git a/talk/base/openssladapter.cc b/talk/base/openssladapter.cc
index 2aacecc..4208b79 100644
--- a/talk/base/openssladapter.cc
+++ b/talk/base/openssladapter.cc
@@ -1,3 +1,30 @@
+/*
+ * libjingle
+ * Copyright 2008, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif  // HAVE_CONFIG_H
@@ -15,8 +42,8 @@
 #include "talk/base/common.h"
 #include "talk/base/logging.h"
 #include "talk/base/openssladapter.h"
+#include "talk/base/sslroots.h"
 #include "talk/base/stringutils.h"
-#include "talk/base/Equifax_Secure_Global_eBusiness_CA-1.h"
 
 // TODO: Use a nicer abstraction for mutex.
 
@@ -56,94 +83,94 @@
 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_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) {
+  BIO* ret = BIO_new(BIO_s_socket2());
+  if (ret == NULL) {
           return NULL;
-	}
-	ret->ptr = socket;
-	return ret;
+  }
+  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;
+  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;
+  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);
+  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;
+    b->num = 1;
   } else if (socket->IsBlocking()) {
-		BIO_set_retry_read(b);
-	}
-	return -1;
+    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);
+  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;
+    BIO_set_retry_write(b);
+  }
+  return -1;
 }
 
 static int socket_puts(BIO* b, const char* str) {
-	return socket_write(b, str, strlen(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;
-	}
+  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;
+  }
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -194,7 +221,7 @@
 
 bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
   if (!InitializeSSLThread() || !SSL_library_init())
-  	  return false;
+      return false;
   SSL_load_error_strings();
   ERR_load_BIO_strings();
   OpenSSL_add_all_algorithms();
@@ -372,7 +399,7 @@
 
 void
 OpenSSLAdapter::Error(const char* context, int err, bool signal) {
-  LOG(LS_WARNING) << "SChannelAdapter::Error("
+  LOG(LS_WARNING) << "OpenSSLAdapter::Error("
                   << context << ", " << err << ")";
   state_ = SSL_ERROR;
   SetError(err);
@@ -822,15 +849,15 @@
 }
 
 bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
-  // Add the root cert to the SSL context
-  // TODO: this cert appears to be the wrong one.
+  // Add the root cert that we care about 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);
+    = Equifax_Secure_Certificate_Authority_certificate;
+  size_t cert_buffer_len =
+      sizeof(Equifax_Secure_Certificate_Authority_certificate);
   X509* cert = d2i_X509(NULL, &cert_buffer, cert_buffer_len);
   if (cert == NULL)
     return false;
diff --git a/talk/base/sslroots.h b/talk/base/sslroots.h
new file mode 100644
index 0000000..e59eba3
--- /dev/null
+++ b/talk/base/sslroots.h
@@ -0,0 +1,83 @@
+// This file is the Equifax root certificate in C form.
+
+// It was generated with the following command line:
+// > openssl x509 -in Equifax_Secure_Certificate_Authority.cer -noout -C
+
+// The certificate was retrieved from:
+// http://www.geotrust.com/resources/root_certificates/certificates/Equifax_Secure_Certificate_Authority.cer
+
+/* subject:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority */
+/* issuer :/C=US/O=Equifax/OU=Equifax Secure Certificate Authority */
+unsigned char Equifax_Secure_Certificate_Authority_subject_name[80]={
+0x30,0x4E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,
+0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0A,0x13,0x07,0x45,0x71,0x75,0x69,0x66,0x61,
+0x78,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x0B,0x13,0x24,0x45,0x71,0x75,0x69,
+0x66,0x61,0x78,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x43,0x65,0x72,0x74,0x69,
+0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,
+};
+unsigned char Equifax_Secure_Certificate_Authority_public_key[162]={
+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,0xC1,0x5D,0xB1,
+0x58,0x67,0x08,0x62,0xEE,0xA0,0x9A,0x2D,0x1F,0x08,0x6D,0x91,0x14,0x68,0x98,0x0A,
+0x1E,0xFE,0xDA,0x04,0x6F,0x13,0x84,0x62,0x21,0xC3,0xD1,0x7C,0xCE,0x9F,0x05,0xE0,
+0xB8,0x01,0xF0,0x4E,0x34,0xEC,0xE2,0x8A,0x95,0x04,0x64,0xAC,0xF1,0x6B,0x53,0x5F,
+0x05,0xB3,0xCB,0x67,0x80,0xBF,0x42,0x02,0x8E,0xFE,0xDD,0x01,0x09,0xEC,0xE1,0x00,
+0x14,0x4F,0xFC,0xFB,0xF0,0x0C,0xDD,0x43,0xBA,0x5B,0x2B,0xE1,0x1F,0x80,0x70,0x99,
+0x15,0x57,0x93,0x16,0xF1,0x0F,0x97,0x6A,0xB7,0xC2,0x68,0x23,0x1C,0xCC,0x4D,0x59,
+0x30,0xAC,0x51,0x1E,0x3B,0xAF,0x2B,0xD6,0xEE,0x63,0x45,0x7B,0xC5,0xD9,0x5F,0x50,
+0xD2,0xE3,0x50,0x0F,0x3A,0x88,0xE7,0xBF,0x14,0xFD,0xE0,0xC7,0xB9,0x02,0x03,0x01,
+0x00,0x01,
+};
+unsigned char Equifax_Secure_Certificate_Authority_certificate[804]={
+0x30,0x82,0x03,0x20,0x30,0x82,0x02,0x89,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x35,
+0xDE,0xF4,0xCF,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,
+0x05,0x00,0x30,0x4E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
+0x53,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0A,0x13,0x07,0x45,0x71,0x75,0x69,
+0x66,0x61,0x78,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x0B,0x13,0x24,0x45,0x71,
+0x75,0x69,0x66,0x61,0x78,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x43,0x65,0x72,
+0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,
+0x74,0x79,0x30,0x1E,0x17,0x0D,0x39,0x38,0x30,0x38,0x32,0x32,0x31,0x36,0x34,0x31,
+0x35,0x31,0x5A,0x17,0x0D,0x31,0x38,0x30,0x38,0x32,0x32,0x31,0x36,0x34,0x31,0x35,
+0x31,0x5A,0x30,0x4E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
+0x53,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0A,0x13,0x07,0x45,0x71,0x75,0x69,
+0x66,0x61,0x78,0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x0B,0x13,0x24,0x45,0x71,
+0x75,0x69,0x66,0x61,0x78,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x43,0x65,0x72,
+0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,
+0x74,0x79,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,0xC1,
+0x5D,0xB1,0x58,0x67,0x08,0x62,0xEE,0xA0,0x9A,0x2D,0x1F,0x08,0x6D,0x91,0x14,0x68,
+0x98,0x0A,0x1E,0xFE,0xDA,0x04,0x6F,0x13,0x84,0x62,0x21,0xC3,0xD1,0x7C,0xCE,0x9F,
+0x05,0xE0,0xB8,0x01,0xF0,0x4E,0x34,0xEC,0xE2,0x8A,0x95,0x04,0x64,0xAC,0xF1,0x6B,
+0x53,0x5F,0x05,0xB3,0xCB,0x67,0x80,0xBF,0x42,0x02,0x8E,0xFE,0xDD,0x01,0x09,0xEC,
+0xE1,0x00,0x14,0x4F,0xFC,0xFB,0xF0,0x0C,0xDD,0x43,0xBA,0x5B,0x2B,0xE1,0x1F,0x80,
+0x70,0x99,0x15,0x57,0x93,0x16,0xF1,0x0F,0x97,0x6A,0xB7,0xC2,0x68,0x23,0x1C,0xCC,
+0x4D,0x59,0x30,0xAC,0x51,0x1E,0x3B,0xAF,0x2B,0xD6,0xEE,0x63,0x45,0x7B,0xC5,0xD9,
+0x5F,0x50,0xD2,0xE3,0x50,0x0F,0x3A,0x88,0xE7,0xBF,0x14,0xFD,0xE0,0xC7,0xB9,0x02,
+0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x09,0x30,0x82,0x01,0x05,0x30,0x70,0x06,0x03,
+0x55,0x1D,0x1F,0x04,0x69,0x30,0x67,0x30,0x65,0xA0,0x63,0xA0,0x61,0xA4,0x5F,0x30,
+0x5D,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x10,
+0x30,0x0E,0x06,0x03,0x55,0x04,0x0A,0x13,0x07,0x45,0x71,0x75,0x69,0x66,0x61,0x78,
+0x31,0x2D,0x30,0x2B,0x06,0x03,0x55,0x04,0x0B,0x13,0x24,0x45,0x71,0x75,0x69,0x66,
+0x61,0x78,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,
+0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,
+0x0D,0x30,0x0B,0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x43,0x52,0x4C,0x31,0x30,0x1A,
+0x06,0x03,0x55,0x1D,0x10,0x04,0x13,0x30,0x11,0x81,0x0F,0x32,0x30,0x31,0x38,0x30,
+0x38,0x32,0x32,0x31,0x36,0x34,0x31,0x35,0x31,0x5A,0x30,0x0B,0x06,0x03,0x55,0x1D,
+0x0F,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,
+0x30,0x16,0x80,0x14,0x48,0xE6,0x68,0xF9,0x2B,0xD2,0xB2,0x95,0xD7,0x47,0xD8,0x23,
+0x20,0x10,0x4F,0x33,0x98,0x90,0x9F,0xD4,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,
+0x16,0x04,0x14,0x48,0xE6,0x68,0xF9,0x2B,0xD2,0xB2,0x95,0xD7,0x47,0xD8,0x23,0x20,
+0x10,0x4F,0x33,0x98,0x90,0x9F,0xD4,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x04,0x05,
+0x30,0x03,0x01,0x01,0xFF,0x30,0x1A,0x06,0x09,0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,
+0x41,0x00,0x04,0x0D,0x30,0x0B,0x1B,0x05,0x56,0x33,0x2E,0x30,0x63,0x03,0x02,0x06,
+0xC0,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,
+0x03,0x81,0x81,0x00,0x58,0xCE,0x29,0xEA,0xFC,0xF7,0xDE,0xB5,0xCE,0x02,0xB9,0x17,
+0xB5,0x85,0xD1,0xB9,0xE3,0xE0,0x95,0xCC,0x25,0x31,0x0D,0x00,0xA6,0x92,0x6E,0x7F,
+0xB6,0x92,0x63,0x9E,0x50,0x95,0xD1,0x9A,0x6F,0xE4,0x11,0xDE,0x63,0x85,0x6E,0x98,
+0xEE,0xA8,0xFF,0x5A,0xC8,0xD3,0x55,0xB2,0x66,0x71,0x57,0xDE,0xC0,0x21,0xEB,0x3D,
+0x2A,0xA7,0x23,0x49,0x01,0x04,0x86,0x42,0x7B,0xFC,0xEE,0x7F,0xA2,0x16,0x52,0xB5,
+0x67,0x67,0xD3,0x40,0xDB,0x3B,0x26,0x58,0xB2,0x28,0x77,0x3D,0xAE,0x14,0x77,0x61,
+0xD6,0xFA,0x2A,0x66,0x27,0xA0,0x0D,0xFA,0xA7,0x73,0x5C,0xEA,0x70,0xF1,0x94,0x21,
+0x65,0x44,0x5F,0xFA,0xFC,0xEF,0x29,0x68,0xA9,0xA2,0x87,0x79,0xEF,0x79,0xEF,0x4F,
+0xAC,0x07,0x77,0x38,
+};
diff --git a/talk/examples/call/call_main.cc b/talk/examples/call/call_main.cc
index 69d66f8..9735cfc 100644
--- a/talk/examples/call/call_main.cc
+++ b/talk/examples/call/call_main.cc
@@ -32,6 +32,9 @@
 #include <vector>
 #include "talk/base/logging.h"
 #include "talk/base/flags.h"
+#ifdef OSX
+#include "talk/base/macsocketserver.h"
+#endif
 #include "talk/base/pathutils.h"
 #include "talk/base/stream.h"
 #include "talk/base/ssladapter.h"
@@ -206,6 +209,12 @@
   return file_media_engine;
 }
 
+// TODO: Move this into Console.
+void Print(const char* chars) {
+  printf("%s", chars);
+  fflush(stdout);
+}
+
 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
@@ -259,7 +268,7 @@
   } else if (protocol == "hybrid") {
     initial_protocol = cricket::PROTOCOL_HYBRID;
   } else {
-    printf("Invalid protocol.  Must be jingle, gingle, or hybrid.\n");
+    Print("Invalid protocol.  Must be jingle, gingle, or hybrid.\n");
     return 1;
   }
 
@@ -271,7 +280,7 @@
   } else if (secure == "require") {
     secure_policy = cricket::SEC_REQUIRED;
   } else {
-    printf("Invalid encryption.  Must be enable, disable, or require.\n");
+    Print("Invalid encryption.  Must be enable, disable, or require.\n");
     return 1;
   }
 
@@ -290,7 +299,7 @@
     talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
 
   if (username.empty()) {
-    std::cout << "JID: ";
+    Print("JID: ");
     std::cin >> username;
   }
   if (username.find('@') == std::string::npos) {
@@ -298,15 +307,15 @@
   }
   jid = buzz::Jid(username);
   if (!jid.IsValid() || jid.node() == "") {
-    printf("Invalid JID. JIDs should be in the form user@domain\n");
+    Print("Invalid JID. JIDs should be in the form user@domain\n");
     return 1;
   }
   if (pass.password().empty() && !test_server) {
     Console::SetEcho(false);
-    std::cout << "Password: ";
+    Print("Password: ");
     std::cin >> pass.password();
     Console::SetEcho(true);
-    std::cout << std::endl;
+    Print("\n");
   }
 
   buzz::XmppClientSettings xcs;
@@ -338,7 +347,7 @@
   }
 
   xcs.set_server(talk_base::SocketAddress(host, port));
-  printf("Logging in to %s as %s\n", server.c_str(), jid.Str().c_str());
+  Print(("Logging in to " + server + " as " + jid.Str() + "\n").c_str());
 
   talk_base::InitializeSSL();
 
@@ -349,6 +358,10 @@
   talk_base::ThreadManager::SetCurrent(&w32_thread);
 #endif
   talk_base::Thread* main_thread = talk_base::Thread::Current();
+#ifdef OSX
+  talk_base::MacCarbonAppSocketServer ss;
+  talk_base::SocketServerScope ss_scope(&ss);
+#endif
 
   XmppPump pump;
   CallClient *client = new CallClient(pump.client());
diff --git a/talk/examples/call/callclient.cc b/talk/examples/call/callclient.cc
index f18c123..3192daf 100644
--- a/talk/examples/call/callclient.cc
+++ b/talk/examples/call/callclient.cc
@@ -158,7 +158,7 @@
     } else if (command == "reject") {
       Reject();
     } else {
-      console_->Print(RECEIVE_COMMANDS);
+      console_->PrintLine(RECEIVE_COMMANDS);
     }
   } else if (call_) {
     if (command == "hangup") {
@@ -171,7 +171,7 @@
       int ev = std::string("0123456789*#").find(words[1][0]);
       call_->PressDTMF(ev);
     } else {
-      console_->Print(CALL_COMMANDS);
+      console_->PrintLine(CALL_COMMANDS);
     }
   } else {
     if (command == "roster") {
@@ -184,8 +184,8 @@
       } else if (!last_sent_to_.empty()) {
         SendChat(last_sent_to_, words[1]);
       } else {
-        console_->Printf(
-            "Invalid JID. JIDs should be in the form user@domain\n");
+        console_->PrintLine(
+            "Invalid JID. JIDs should be in the form user@domain");
       }
     } else if ((words.size() == 2) && (command == "friend")) {
       InviteFriend(words[1]);
@@ -214,7 +214,7 @@
     } else if (command == "voicemail") {
       CallVoicemail((words.size() >= 2) ? words[1] : "");
     } else {
-      console_->Print(CONSOLE_COMMANDS);
+      console_->PrintLine(CONSOLE_COMMANDS);
     }
   }
 }
@@ -283,8 +283,7 @@
       local_renderer_ = NULL;
     }
     RemoveAllStaticRenderedViews();
-    console_->SetPrompt(NULL);
-    console_->Print("call destroyed");
+    console_->PrintLine("call destroyed");
     call_ = NULL;
     session_ = NULL;
   }
@@ -293,27 +292,27 @@
 void CallClient::OnStateChange(buzz::XmppEngine::State state) {
   switch (state) {
   case buzz::XmppEngine::STATE_START:
-    console_->Print("connecting...");
+    console_->PrintLine("connecting...");
     break;
 
   case buzz::XmppEngine::STATE_OPENING:
-    console_->Print("logging in...");
+    console_->PrintLine("logging in...");
     break;
 
   case buzz::XmppEngine::STATE_OPEN:
-    console_->Print("logged in...");
-    InitPhone();
+    console_->PrintLine("logged in...");
+    InitMedia();
     InitPresence();
     break;
 
   case buzz::XmppEngine::STATE_CLOSED:
     buzz::XmppEngine::Error error = xmpp_client_->GetError(NULL);
-    console_->Print("logged out..." + strerror(error));
+    console_->PrintLine("logged out... %s", strerror(error).c_str());
     Quit();
   }
 }
 
-void CallClient::InitPhone() {
+void CallClient::InitMedia() {
   std::string client_unique = xmpp_client_->jid().Str();
   talk_base::InitRandom(client_unique.c_str(), client_unique.size());
 
@@ -386,7 +385,7 @@
                                 cricket::BaseSession::State state) {
   if (state == cricket::Session::STATE_RECEIVEDINITIATE) {
     buzz::Jid jid(session->remote_name());
-    console_->Printf("Incoming call from '%s'", jid.Str().c_str());
+    console_->PrintLine("Incoming call from '%s'", jid.Str().c_str());
     call_ = call;
     session_ = session;
     incoming_call_ = true;
@@ -407,15 +406,15 @@
       remote_renderer_ =
           cricket::VideoRendererFactory::CreateGuiVideoRenderer(160, 100);
     }
-    console_->Print("calling...");
+    console_->PrintLine("calling...");
   } else if (state == cricket::Session::STATE_RECEIVEDACCEPT) {
-    console_->Print("call answered");
+    console_->PrintLine("call answered");
   } else if (state == cricket::Session::STATE_RECEIVEDREJECT) {
-    console_->Print("call not answered");
+    console_->PrintLine("call not answered");
   } else if (state == cricket::Session::STATE_INPROGRESS) {
-    console_->Print("call in progress");
+    console_->PrintLine("call in progress");
   } else if (state == cricket::Session::STATE_RECEIVEDTERMINATE) {
-    console_->Print("other side hung up");
+    console_->PrintLine("other side hung up");
   }
 }
 
@@ -453,7 +452,7 @@
   my_status_.set_priority(0);
   my_status_.set_know_capabilities(true);
   my_status_.set_pmuc_capability(true);
-  my_status_.set_phone_capability(
+  my_status_.set_voice_capability(
       (media_caps & cricket::MediaEngine::AUDIO_RECV) != 0);
   my_status_.set_video_capability(
       (media_caps & cricket::MediaEngine::VIDEO_RECV) != 0);
@@ -472,11 +471,11 @@
 
   std::string key = item.jid.Str();
 
-  if (status.available() && status.phone_capability()) {
-     console_->Printf("Adding to roster: %s", key.c_str());
+  if (status.available() && status.voice_capability()) {
+     console_->PrintLine("Adding to roster: %s", key.c_str());
     (*roster_)[key] = item;
   } else {
-    console_->Printf("Removing from roster: %s", key.c_str());
+    console_->PrintLine("Removing from roster: %s", key.c_str());
     RosterMap::iterator iter = roster_->find(key);
     if (iter != roster_->end())
       roster_->erase(iter);
@@ -484,16 +483,14 @@
 }
 
 void CallClient::PrintRoster() {
-  console_->SetPrompting(false);
-  console_->Printf("Roster contains %d callable", roster_->size());
+  console_->PrintLine("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));
+    console_->PrintLine("%s - %s",
+                        iter->second.jid.BareJid().Str().c_str(),
+                        DescribeStatus(iter->second.show, iter->second.status));
     iter++;
   }
-  console_->SetPrompting(true);
 }
 
 void CallClient::SendChat(const std::string& to, const std::string msg) {
@@ -512,7 +509,7 @@
 void CallClient::InviteFriend(const std::string& name) {
   buzz::Jid jid(name);
   if (!jid.IsValid() || jid.node() == "") {
-    console_->Printf("Invalid JID. JIDs should be in the form user@domain\n");
+    console_->PrintLine("Invalid JID. JIDs should be in the form user@domain.");
     return;
   }
   // Note: for some reason the Buzz backend does not forward our presence
@@ -521,7 +518,7 @@
   // run the friend command as the other user too to create the linkage
   // (and you won't be notified to do so).
   friend_invite_send_->Send(jid);
-  console_->Printf("Requesting to befriend %s.\n", name.c_str());
+  console_->PrintLine("Requesting to befriend %s.", name.c_str());
 }
 
 void CallClient::MakeCallTo(const std::string& name,
@@ -568,11 +565,12 @@
   }
 
   if (found) {
-    console_->Printf("Found %s '%s'", options.is_muc ? "room" : "online friend",
-        found_jid.Str().c_str());
+    console_->PrintLine("Found %s '%s'",
+                        options.is_muc ? "room" : "online friend",
+                        found_jid.Str().c_str());
     PlaceCall(found_jid, options);
   } else {
-    console_->Printf("Could not find online friend '%s'", name.c_str());
+    console_->PrintLine("Could not find online friend '%s'", name.c_str());
   }
 }
 
@@ -580,7 +578,6 @@
                            const cricket::CallOptions& options) {
   if (!call_) {
     call_ = media_client_->CreateCall();
-    console_->SetPrompt(jid.Str().c_str());
     session_ = call_->InitiateSession(jid, options);
   }
   media_client_->SetFocus(call_);
@@ -595,7 +592,7 @@
 void CallClient::CallVoicemail(const std::string& name) {
   buzz::Jid jid(name);
   if (!jid.IsValid() || jid.node() == "") {
-    console_->Printf("Invalid JID. JIDs should be in the form user@domain\n");
+    console_->PrintLine("Invalid JID. JIDs should be in the form user@domain.");
     return;
   }
   buzz::VoicemailJidRequester *request =
@@ -609,12 +606,12 @@
 
 void CallClient::OnFoundVoicemailJid(const buzz::Jid& to,
                                      const buzz::Jid& voicemail) {
-  console_->Printf("Calling %s's voicemail.\n", to.Str().c_str());
+  console_->PrintLine("Calling %s's voicemail.", to.Str().c_str());
   PlaceCall(voicemail, cricket::CallOptions());
 }
 
 void CallClient::OnVoicemailJidError(const buzz::Jid& to) {
-  console_->Printf("Unable to voicemail %s.\n", to.Str().c_str());
+  console_->PrintLine("Unable to voicemail %s.", to.Str().c_str());
 }
 
 void CallClient::Accept(const cricket::CallOptions& options) {
@@ -644,7 +641,7 @@
 void CallClient::LookupAndJoinMuc(const std::string& room_name) {
   // The room_name can't be empty for lookup task.
   if (room_name.empty()) {
-    console_->Print("Please provide a room name or room jid.");
+    console_->PrintLine("Please provide a room name or room jid.");
     return;
   }
 
@@ -659,9 +656,9 @@
 
   buzz::MucRoomLookupTask* lookup_query_task =
       new buzz::MucRoomLookupTask(xmpp_client_, room, domain);
-  lookup_query_task->SignalRoomLookupResponse.connect(this,
+  lookup_query_task->SignalResult.connect(this,
       &CallClient::OnRoomLookupResponse);
-  lookup_query_task->SignalRoomLookupError.connect(this,
+  lookup_query_task->SignalError.connect(this,
       &CallClient::OnRoomLookupError);
   lookup_query_task->Start();
 }
@@ -669,8 +666,8 @@
 void CallClient::JoinMuc(const std::string& room_jid_str) {
   if (room_jid_str.empty()) {
     buzz::Jid room_jid = GenerateRandomMucJid();
-    console_->Printf("Generated a random room jid: %s",
-                     room_jid.Str().c_str());
+    console_->PrintLine("Generated a random room jid: %s",
+                        room_jid.Str().c_str());
     JoinMuc(room_jid);
   } else {
     JoinMuc(buzz::Jid(room_jid_str));
@@ -679,8 +676,8 @@
 
 void CallClient::JoinMuc(const buzz::Jid& room_jid) {
   if (!room_jid.IsValid()) {
-    console_->Printf("Unable to make valid muc endpoint for %s",
-                     room_jid.Str().c_str());
+    console_->PrintLine("Unable to make valid muc endpoint for %s",
+                        room_jid.Str().c_str());
     return;
   }
 
@@ -692,7 +689,7 @@
 
   MucMap::iterator elem = mucs_.find(room_jid);
   if (elem != mucs_.end()) {
-    console_->Printf("This MUC already exists.");
+    console_->PrintLine("This MUC already exists.");
     return;
   }
 
@@ -706,28 +703,28 @@
 }
 
 void CallClient::OnRoomLookupError(const buzz::XmlElement* stanza) {
-  console_->Printf("%s\n", "Failed to look up the room_jid.",
-      stanza->Str().c_str());
+  console_->PrintLine("Failed to look up the room_jid. %s",
+                    stanza->Str().c_str());
 }
 
 void CallClient::OnMucInviteReceived(const buzz::Jid& inviter,
     const buzz::Jid& room,
     const std::vector<buzz::AvailableMediaEntry>& avail) {
 
-  console_->Printf("Invited to join %s by %s.\n", room.Str().c_str(),
+  console_->PrintLine("Invited to join %s by %s.", room.Str().c_str(),
       inviter.Str().c_str());
-  console_->Printf("Available media:\n");
+  console_->PrintLine("Available media:");
   if (avail.size() > 0) {
     for (std::vector<buzz::AvailableMediaEntry>::const_iterator i =
             avail.begin();
         i != avail.end();
         ++i) {
-      console_->Printf("  %s, %s\n",
-          buzz::AvailableMediaEntry::TypeAsString(i->type),
-          buzz::AvailableMediaEntry::StatusAsString(i->status));
+      console_->PrintLine("  %s, %s",
+                          buzz::AvailableMediaEntry::TypeAsString(i->type),
+                          buzz::AvailableMediaEntry::StatusAsString(i->status));
     }
   } else {
-    console_->Printf("  None\n");
+    console_->PrintLine("  None");
   }
   // We automatically join the room.
   JoinMuc(room);
@@ -740,7 +737,7 @@
 
   buzz::Muc* muc = elem->second;
   muc->set_state(buzz::Muc::MUC_JOINED);
-  console_->Printf("Joined \"%s\"", muc->jid().Str().c_str());
+  console_->PrintLine("Joined \"%s\"", muc->jid().Str().c_str());
 }
 
 void CallClient::OnMucStatusUpdate(const buzz::Jid& jid,
@@ -773,13 +770,13 @@
   }
 
   if (!room_jid.IsValid()) {
-    console_->Printf("Invalid MUC JID.");
+    console_->PrintLine("Invalid MUC JID.");
     return;
   }
 
   MucMap::iterator elem = mucs_.find(room_jid);
   if (elem == mucs_.end()) {
-    console_->Printf("No such MUC.");
+    console_->PrintLine("No such MUC.");
     return;
   }
 
@@ -802,11 +799,11 @@
 
   buzz::Muc* muc = elem->second;
   if (muc->state() == buzz::Muc::MUC_JOINING) {
-    console_->Printf("Failed to join \"%s\", code=%d",
-                     muc->jid().Str().c_str(), error);
+    console_->PrintLine("Failed to join \"%s\", code=%d",
+                        muc->jid().Str().c_str(), error);
   } else if (muc->state() == buzz::Muc::MUC_JOINED) {
-    console_->Printf("Kicked from \"%s\"",
-                     muc->jid().Str().c_str());
+    console_->PrintLine("Kicked from \"%s\"",
+                        muc->jid().Str().c_str());
   }
 
   delete muc;
@@ -818,7 +815,7 @@
   const buzz::Muc* found_muc;
   if (room.length() == 0) {
     if (mucs_.size() == 0) {
-      console_->Printf("Not in a room yet; can't invite.\n");
+      console_->PrintLine("Not in a room yet; can't invite.");
       return;
     }
     // Invite to the first muc
@@ -826,7 +823,7 @@
   } else {
     MucMap::iterator elem = mucs_.find(buzz::Jid(room));
     if (elem == mucs_.end()) {
-      console_->Printf("Not in room %s.\n", room.c_str());
+      console_->PrintLine("Not in room %s.", room.c_str());
       return;
     }
     found_muc = elem->second;
@@ -842,7 +839,7 @@
     }
   }
   if (!found_user) {
-    console_->Printf("No such friend as %s.\n", user.c_str());
+    console_->PrintLine("No such friend as %s.", user.c_str());
     return;
   }
 }
@@ -850,24 +847,24 @@
 void CallClient::GetDevices() {
   std::vector<std::string> names;
   media_client_->GetAudioInputDevices(&names);
-  printf("Audio input devices:\n");
+  console_->PrintLine("Audio input devices:");
   PrintDevices(names);
   media_client_->GetAudioOutputDevices(&names);
-  printf("Audio output devices:\n");
+  console_->PrintLine("Audio output devices:");
   PrintDevices(names);
   media_client_->GetVideoCaptureDevices(&names);
-  printf("Video capture devices:\n");
+  console_->PrintLine("Video capture devices:");
   PrintDevices(names);
 }
 
 void CallClient::PrintDevices(const std::vector<std::string>& names) {
   for (size_t i = 0; i < names.size(); ++i) {
-    printf("%d: %s\n", static_cast<int>(i), names[i].c_str());
+    console_->PrintLine("%d: %s", static_cast<int>(i), names[i].c_str());
   }
 }
 
 void CallClient::OnDevicesChange() {
-  printf("Devices changed.\n");
+  console_->PrintLine("Devices changed.");
   RefreshStatus();
 }
 
@@ -907,7 +904,7 @@
   call_->SetVideoRenderer(session, ssrc, rendered_view.renderer);
   static_rendered_views_.push_back(rendered_view);
   ++static_views_accumulated_count_;
-  console_->Printf("Added renderer for ssrc %d", ssrc);
+  console_->PrintLine("Added renderer for ssrc %d", ssrc);
 }
 
 bool CallClient::RemoveStaticRenderedView(uint32 ssrc) {
@@ -916,7 +913,7 @@
     if (it->view.ssrc == ssrc) {
       delete it->renderer;
       static_rendered_views_.erase(it);
-      console_->Printf("Removed renderer for ssrc %d", ssrc);
+      console_->PrintLine("Removed renderer for ssrc %d", ssrc);
       return true;
     }
   }
diff --git a/talk/examples/call/callclient.h b/talk/examples/call/callclient.h
index 82fc472..72a9ca9 100644
--- a/talk/examples/call/callclient.h
+++ b/talk/examples/call/callclient.h
@@ -143,7 +143,7 @@
   void RemoveStream(uint32 audio_src_id, uint32 video_src_id);
   void OnStateChange(buzz::XmppEngine::State state);
 
-  void InitPhone();
+  void InitMedia();
   void InitPresence();
   void RefreshStatus();
   void OnRequestSignaling();
diff --git a/talk/examples/call/console.cc b/talk/examples/call/console.cc
index 0aa7a4f..7949c15 100644
--- a/talk/examples/call/console.cc
+++ b/talk/examples/call/console.cc
@@ -28,6 +28,8 @@
 #define _CRT_SECURE_NO_DEPRECATE 1
 
 #ifdef POSIX
+#include <signal.h>
+#include <termios.h>
 #include <unistd.h>
 #endif  // POSIX
 #include <cassert>
@@ -38,16 +40,13 @@
 #include "talk/examples/call/callclient.h"
 
 #ifdef POSIX
-#include <signal.h>
-
 static void DoNothing(int unused) {}
 #endif
 
 Console::Console(talk_base::Thread *thread, CallClient *client) :
-  client_(client), client_thread_(thread),
-  console_thread_(new talk_base::Thread()), prompt_(std::string("call")),
-  prompting_(true) {
-}
+  client_(client),
+  client_thread_(thread),
+  console_thread_(new talk_base::Thread()) {}
 
 Console::~Console() {
   Stop();
@@ -100,27 +99,25 @@
 
   SetConsoleMode(hIn, mode);
 #else
-  int re;
-  if (on)
-    re = system("stty echo");
-  else
-    re = system("stty -echo");
-  if (-1 == re)
+  const int fd = fileno(stdin);
+  if (fd == -1)
+   return;
+
+  struct termios tcflags;
+  if (tcgetattr(fd, &tcflags) == -1)
     return;
+
+  if (on) {
+    tcflags.c_lflag |= ECHO;
+  } else {
+    tcflags.c_lflag &= ~ECHO;
+  }
+
+  tcsetattr(fd, TCSANOW, &tcflags);
 #endif
 }
 
-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, ...) {
+void Console::PrintLine(const char* format, ...) {
   va_list ap;
   va_start(ap, format);
 
@@ -129,7 +126,8 @@
   assert(size >= 0);
   assert(size < static_cast<int>(sizeof(buf)));
   buf[size] = '\0';
-  Print(buf);
+  printf("%s\n", buf);
+  fflush(stdout);
 
   va_end(ap);
 }
diff --git a/talk/examples/call/console.h b/talk/examples/call/console.h
index e2ba4f7..4a90a7f 100644
--- a/talk/examples/call/console.h
+++ b/talk/examples/call/console.h
@@ -48,21 +48,7 @@
 
   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, ...);
+  void PrintLine(const char* format, ...);
 
   static void SetEcho(bool on);
 
@@ -78,8 +64,6 @@
   CallClient *client_;
   talk_base::Thread *client_thread_;
   talk_base::scoped_ptr<talk_base::Thread> console_thread_;
-  std::string prompt_;
-  bool prompting_;
 };
 
 #endif // TALK_EXAMPLES_CALL_CONSOLE_H_
diff --git a/talk/examples/call/presenceouttask.cc b/talk/examples/call/presenceouttask.cc
index ff3d91b..b3e5f37 100644
--- a/talk/examples/call/presenceouttask.cc
+++ b/talk/examples/call/presenceouttask.cc
@@ -118,7 +118,7 @@
       result->AddAttr(QN_VER, s.version(), 1);
 
       std::string caps;
-      caps.append(s.phone_capability() ? "voice-v1" : "");
+      caps.append(s.voice_capability() ? "voice-v1" : "");
       caps.append(s.pmuc_capability() ? " pmuc-v1" : "");
       caps.append(s.video_capability() ? " video-v1" : "");
       caps.append(s.camera_capability() ? " camera-v1" : "");
diff --git a/talk/examples/call/presencepushtask.cc b/talk/examples/call/presencepushtask.cc
index ca7416d..1e2cc52 100644
--- a/talk/examples/call/presencepushtask.cc
+++ b/talk/examples/call/presencepushtask.cc
@@ -193,7 +193,7 @@
       }
 
       if (ListContainsToken(exts, "voice-v1")) {
-        s->set_phone_capability(true);
+        s->set_voice_capability(true);
       }
       if (ListContainsToken(exts, "video-v1")) {
         s->set_video_capability(true);
diff --git a/talk/examples/call/status.h b/talk/examples/call/status.h
index 92fe88c..68c333b 100644
--- a/talk/examples/call/status.h
+++ b/talk/examples/call/status.h
@@ -44,7 +44,7 @@
     e_code_(0),
     feedback_probation_(false),
     know_capabilities_(false),
-    phone_capability_(false),
+    voice_capability_(false),
     pmuc_capability_(false),
     video_capability_(false),
     camera_capability_(false),
@@ -74,7 +74,7 @@
   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 voice_capability() const { return voice_capability_; }
   bool pmuc_capability() const { return pmuc_capability_; }
   bool video_capability() const { return video_capability_; }
   bool camera_capability() const { return camera_capability_; }
@@ -91,7 +91,7 @@
   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_voice_capability(bool f) { voice_capability_ = f; }
   void set_pmuc_capability(bool f) { pmuc_capability_ = f; }
   void set_video_capability(bool f) { video_capability_ = f; }
   void set_camera_capability(bool f) { camera_capability_ = f; }
@@ -104,14 +104,14 @@
     if (!new_value.know_capabilities()) {
        bool k = know_capabilities();
        bool i = is_google_client();
-       bool p = phone_capability();
+       bool p = voice_capability();
        std::string v = version();
 
        *this = new_value;
 
        set_know_capabilities(k);
        set_is_google_client(i);
-       set_phone_capability(p);
+       set_voice_capability(p);
        set_version(v);
     }
     else {
@@ -213,7 +213,7 @@
 
   // capabilities (valid only if know_capabilities_
   bool know_capabilities_;
-  bool phone_capability_;
+  bool voice_capability_;
   bool pmuc_capability_;
   bool video_capability_;
   bool camera_capability_;
diff --git a/talk/examples/login/xmppsocket.cc b/talk/examples/login/xmppsocket.cc
index 89e8662..75325e4 100644
--- a/talk/examples/login/xmppsocket.cc
+++ b/talk/examples/login/xmppsocket.cc
@@ -231,13 +231,11 @@
 #ifndef USE_SSLSTREAM
   talk_base::SSLAdapter* ssl_adapter =
     static_cast<talk_base::SSLAdapter *>(cricket_socket_);
-  ssl_adapter->set_ignore_bad_cert(true);
   if (ssl_adapter->StartSSL(domainname.c_str(), false) != 0)
     return false;
 #else  // USE_SSLSTREAM
   talk_base::SSLStreamAdapter* ssl_stream =
     static_cast<talk_base::SSLStreamAdapter *>(stream_);
-  ssl_stream->set_ignore_bad_cert(true);
   if (ssl_stream->StartSSLWithServer(domainname.c_str()) != 0)
     return false;
 #endif  // USE_SSLSTREAM
diff --git a/talk/libjingle.scons b/talk/libjingle.scons
index be6a1c8..989ac70 100644
--- a/talk/libjingle.scons
+++ b/talk/libjingle.scons
@@ -11,7 +11,7 @@
                "third_party/expat-2.0.1/lib/xmltok.c",
              ],
              includedirs = [
-               "third_party/expat-2.0.1",
+               "third_party/expat-2.0.1/lib",
              ],
              win_cppdefines = [
                "COMPILED_FROM_DSP",
@@ -73,6 +73,7 @@
              mac_srcs = [
                "base/macconversion.cc",
                "base/macutils.cc",
+               "session/phone/carbonvideorenderer.cc",
                "session/phone/devicemanager_mac.mm",
              ],
              posix_srcs = [
@@ -198,6 +199,7 @@
                "xmllite/xmlparser.cc",
                "xmllite/xmlprinter.cc",
                "xmpp/constants.cc",
+               "xmpp/iqtask.cc",
                "xmpp/jid.cc",
                "xmpp/mucroomlookuptask.cc",
                "xmpp/ratelimitmanager.cc",
@@ -211,7 +213,7 @@
              ],
              includedirs = [
                "third_party/libudev",
-               "third_party/expat-2.0.1",
+               "third_party/expat-2.0.1/lib",
                "third_party/srtp/include",
                "third_party/srtp/crypto/include",
              ],
diff --git a/talk/main.scons b/talk/main.scons
index 349c317..f88d1a5 100644
--- a/talk/main.scons
+++ b/talk/main.scons
@@ -482,7 +482,7 @@
   p = vs_env.ComponentVSDirProject(
     'flute_source',
     ['$MAIN_DIR',
-     '$THIRD_PARTY'],
+    ],
     COMPONENT_VS_SOURCE_FOLDERS = [
       # Files are assigned to first matching folder. Folder names of None
       # are filters.
diff --git a/talk/p2p/base/session.cc b/talk/p2p/base/session.cc
index a1ec304..e9c5a03 100644
--- a/talk/p2p/base/session.cc
+++ b/talk/p2p/base/session.cc
@@ -680,11 +680,17 @@
   ASSERT(signaling_thread_->IsCurrent());
 
   if (msg.type == ACTION_SESSION_INITIATE) {
-    initiate_acked_ = true;
+    OnInitiateAcked();
+  }
+}
+
+void Session::OnInitiateAcked() {
     // TODO: This is to work around server re-ordering
     // messages.  We send the candidates once the session-initiate
     // is acked.  Once we have fixed the server to guarantee message
     // order, we can remove this case.
+  if (!initiate_acked_) {
+    initiate_acked_ = true;
     SessionError error;
     SendAllUnsentTransportInfoMessages(&error);
   }
@@ -720,7 +726,6 @@
 
   const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR);
   if (error) {
-    ASSERT(error->HasAttr(buzz::QN_TYPE));
     error_type = error->Attr(buzz::QN_TYPE);
 
     LOG(LS_ERROR) << "Session error:\n" << error->Str() << "\n"
@@ -792,8 +797,13 @@
   SessionAccept accept;
   if (!ParseSessionAccept(msg.protocol, msg.action_elem,
                           GetContentParsers(), GetTransportParsers(),
-                          &accept, error))
+                          &accept, error)) {
     return false;
+  }
+
+  // If we get an accept, we can assume the initiate has been
+  // received, even if we haven't gotten an IQ response.
+  OnInitiateAcked();
 
   set_remote_description(new SessionDescription(accept.ClearContents()));
   SetState(STATE_RECEIVEDACCEPT);
diff --git a/talk/p2p/base/session.h b/talk/p2p/base/session.h
index ba254ad..c299ac6 100644
--- a/talk/p2p/base/session.h
+++ b/talk/p2p/base/session.h
@@ -504,6 +504,7 @@
   void OnIncomingResponse(const buzz::XmlElement* orig_stanza,
                           const buzz::XmlElement* response_stanza,
                           const SessionMessage& msg);
+  void OnInitiateAcked();
   void OnFailedSend(const buzz::XmlElement* orig_stanza,
                     const buzz::XmlElement* error_stanza);
 
diff --git a/talk/p2p/base/sessionmanager.cc b/talk/p2p/base/sessionmanager.cc
index ba05bc7..89912b5 100644
--- a/talk/p2p/base/sessionmanager.cc
+++ b/talk/p2p/base/sessionmanager.cc
@@ -189,6 +189,10 @@
 
 void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
     const buzz::XmlElement* response_stanza) {
+  if (orig_stanza == NULL || response_stanza == NULL) {
+    return;
+  }
+
   SessionMessage msg;
   ParseError error;
   if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
diff --git a/talk/p2p/base/sessionmessages.cc b/talk/p2p/base/sessionmessages.cc
index a0b1aa7..7bc47b4 100644
--- a/talk/p2p/base/sessionmessages.cc
+++ b/talk/p2p/base/sessionmessages.cc
@@ -284,7 +284,7 @@
   bool has_video = FindContentInfoByName(contents, CN_VIDEO) != NULL;
 
   // If we don't have media, no need to separate the candidates.
-  if (!has_audio && !has_audio) {
+  if (!has_audio && !has_video) {
     tinfos->push_back(tinfo);
     return true;
   }
diff --git a/talk/p2p/base/transport.cc b/talk/p2p/base/transport.cc
index beb5d6d..fdd8520 100644
--- a/talk/p2p/base/transport.cc
+++ b/talk/p2p/base/transport.cc
@@ -62,7 +62,7 @@
   cricket::Candidate* candidate;
 };
 // TODO: Merge ChannelParams and ChannelMessage.
-typedef talk_base::TypedMessageData<ChannelParams*> ChannelMessage;
+typedef talk_base::ScopedMessageData<ChannelParams> ChannelMessage;
 
 enum {
   MSG_CREATECHANNEL = 1,
@@ -97,8 +97,7 @@
 
 TransportChannelImpl* Transport::CreateChannel(
     const std::string& name, const std::string& content_type) {
-  ChannelParams params(name, content_type);
-  ChannelMessage msg(&params);
+  ChannelMessage msg(new ChannelParams(name, content_type));
   worker_thread()->Send(this, MSG_CREATECHANNEL, &msg);
   return msg.data()->channel;
 }
@@ -142,8 +141,7 @@
 }
 
 void Transport::DestroyChannel(const std::string& name) {
-  ChannelParams params(name);
-  ChannelMessage msg(&params);
+  ChannelMessage msg(new ChannelParams(name));
   worker_thread()->Send(this, MSG_DESTROYCHANNEL, &msg);
 }
 
@@ -300,9 +298,8 @@
     return;
   }
 
-  // new candidate deleted when params is deleted
-  ChannelParams* params = new ChannelParams(new Candidate(candidate));
-  ChannelMessage* msg = new ChannelMessage(params);
+  ChannelMessage* msg = new ChannelMessage(
+      new ChannelParams(new Candidate(candidate)));
   worker_thread()->Post(this, MSG_ONREMOTECANDIDATE, msg);
 }
 
@@ -413,13 +410,15 @@
   switch (msg->message_id) {
   case MSG_CREATECHANNEL:
     {
-      ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data();
+      ChannelParams* params =
+          static_cast<ChannelMessage*>(msg->pdata)->data().get();
       params->channel = CreateChannel_w(params->name, params->content_type);
     }
     break;
   case MSG_DESTROYCHANNEL:
     {
-      ChannelParams* params = static_cast<ChannelMessage*>(msg->pdata)->data();
+      ChannelParams* params =
+          static_cast<ChannelMessage*>(msg->pdata)->data().get();
       DestroyChannel_w(params->name);
     }
     break;
@@ -438,9 +437,7 @@
   case MSG_ONREMOTECANDIDATE:
     {
       ChannelMessage* channel_msg = static_cast<ChannelMessage*>(msg->pdata);
-      ChannelParams* params = channel_msg->data();
-      OnRemoteCandidate_w(*(params->candidate));
-      delete params;
+      OnRemoteCandidate_w(*(channel_msg->data()->candidate));
       delete channel_msg;
     }
     break;
@@ -462,9 +459,8 @@
   case MSG_ROUTECHANGE:
     {
       ChannelMessage* channel_msg = static_cast<ChannelMessage*>(msg->pdata);
-      ChannelParams* params = channel_msg->data();
+      ChannelParams* params = channel_msg->data().get();
       OnChannelRouteChange_s(params->name, *params->candidate);
-      delete params;
       delete channel_msg;
     }
     break;
diff --git a/talk/session/phone/carbonvideorenderer.cc b/talk/session/phone/carbonvideorenderer.cc
new file mode 100644
index 0000000..9b9a01c
--- /dev/null
+++ b/talk/session/phone/carbonvideorenderer.cc
@@ -0,0 +1,181 @@
+// libjingle
+// Copyright 2011 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:
+//
+//  1. Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//  3. The name of the author may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Implementation of CarbonVideoRenderer
+
+#include "talk/session/phone/carbonvideorenderer.h"
+
+#include "talk/base/logging.h"
+#include "talk/session/phone/videocommon.h"
+
+namespace cricket {
+
+CarbonVideoRenderer::CarbonVideoRenderer(int x, int y)
+    : image_width_(0),
+      image_height_(0),
+      x_(x),
+      y_(y),
+      image_ref_(NULL),
+      window_ref_(NULL) {
+}
+
+CarbonVideoRenderer::~CarbonVideoRenderer() {
+  if (window_ref_) {
+    DisposeWindow(window_ref_);
+  }
+}
+
+// Called from the main event loop. All renderering needs to happen on
+// the main thread.
+OSStatus CarbonVideoRenderer::DrawEventHandler(EventHandlerCallRef handler,
+                                               EventRef event,
+                                               void* data) {
+  OSStatus status = noErr;
+  CarbonVideoRenderer* renderer = static_cast<CarbonVideoRenderer*>(data);
+  if (renderer != NULL) {
+    if (!renderer->DrawFrame()) {
+      LOG(LS_ERROR) << "Failed to draw frame.";
+    }
+  }
+  return status;
+}
+
+bool CarbonVideoRenderer::DrawFrame() {
+  // Grab the image lock to make sure it is not changed why we'll draw it.
+  talk_base::CritScope cs(&image_crit_);
+
+  if (image_.get() == NULL) {
+    // Nothing to draw, just return.
+    return true;
+  }
+  int width = image_width_;
+  int height = image_height_;
+  CGDataProviderRef provider =
+      CGDataProviderCreateWithData(NULL, image_.get(), width * height * 4,
+                                   NULL);
+  CGColorSpaceRef color_space_ref = CGColorSpaceCreateDeviceRGB();
+  CGBitmapInfo bitmap_info = kCGBitmapByteOrderDefault;
+  CGColorRenderingIntent rendering_intent = kCGRenderingIntentDefault;
+  CGImageRef image_ref = CGImageCreate(width, height, 8, 32, width * 4,
+                                       color_space_ref, bitmap_info, provider,
+                                       NULL, false, rendering_intent);
+  CGDataProviderRelease(provider);
+
+  if (image_ref == NULL) {
+    return false;
+  }
+  CGContextRef context;
+  SetPortWindowPort(window_ref_);
+  if (QDBeginCGContext(GetWindowPort(window_ref_), &context) != noErr) {
+    CGImageRelease(image_ref);
+    return false;
+  }
+  Rect window_bounds;
+  GetWindowPortBounds(window_ref_, &window_bounds);
+
+  // Anchor the image to the top left corner.
+  int x = 0;
+  int y = window_bounds.bottom - CGImageGetHeight(image_ref);
+  CGRect dst_rect = CGRectMake(x, y, CGImageGetWidth(image_ref),
+                               CGImageGetHeight(image_ref));
+  CGContextDrawImage(context, dst_rect, image_ref);
+  CGContextFlush(context);
+  QDEndCGContext(GetWindowPort(window_ref_), &context);
+  CGImageRelease(image_ref);
+  return true;
+}
+
+bool CarbonVideoRenderer::SetSize(int width, int height, int reserved) {
+  if (width != image_width_ || height != image_height_) {
+    // Grab the image lock while changing its size.
+    talk_base::CritScope cs(&image_crit_);
+    image_width_ = width;
+    image_height_ = height;
+    image_.reset(new uint8[width * height * 4]);
+    memset(image_.get(), 255, width * height * 4);
+  }
+  return true;
+}
+
+bool CarbonVideoRenderer::RenderFrame(const VideoFrame* frame) {
+  if (!frame) {
+    return false;
+  }
+  {
+    // Grab the image lock so we are not trashing up the image being drawn.
+    talk_base::CritScope cs(&image_crit_);
+    frame->ConvertToRgbBuffer(cricket::FOURCC_ABGR,
+                              image_.get(),
+                              frame->GetWidth() * frame->GetHeight() * 4,
+                              frame->GetWidth() * 4);
+  }
+
+  // Trigger a repaint event for the whole window.
+  Rect bounds;
+  InvalWindowRect(window_ref_, GetWindowPortBounds(window_ref_, &bounds));
+  return true;
+}
+
+bool CarbonVideoRenderer::Initialize() {
+  OSStatus err;
+  WindowAttributes attributes =
+      kWindowStandardDocumentAttributes |
+      kWindowLiveResizeAttribute |
+      kWindowFrameworkScaledAttribute |
+      kWindowStandardHandlerAttribute;
+
+  struct Rect bounds;
+  bounds.top = y_;
+  bounds.bottom = 480;
+  bounds.left = x_;
+  bounds.right = 640;
+  err = CreateNewWindow(kDocumentWindowClass, attributes,
+                        &bounds, &window_ref_);
+  if (!window_ref_ || err != noErr) {
+    LOG(LS_ERROR) << "CreateNewWindow failed, error code: " << err;
+    return false;
+  }
+  static const EventTypeSpec event_spec = {
+    kEventClassWindow,
+    kEventWindowDrawContent
+  };
+
+  err = InstallWindowEventHandler(
+      window_ref_,
+      NewEventHandlerUPP(CarbonVideoRenderer::DrawEventHandler),
+      GetEventTypeCount(event_spec),
+      &event_spec,
+      this,
+      NULL);
+  if (err != noErr) {
+    LOG(LS_ERROR) << "Failed to install event handler, error code: " << err;
+    return false;
+  }
+  SelectWindow(window_ref_);
+  ShowWindow(window_ref_);
+  return true;
+}
+
+}  // namespace cricket
diff --git a/talk/session/phone/carbonvideorenderer.h b/talk/session/phone/carbonvideorenderer.h
new file mode 100644
index 0000000..8865349
--- /dev/null
+++ b/talk/session/phone/carbonvideorenderer.h
@@ -0,0 +1,72 @@
+// libjingle
+// Copyright 2011 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:
+//
+//  1. Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//  3. The name of the author may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Definition of class CarbonVideoRenderer that implements the abstract class
+// cricket::VideoRenderer via Carbon.
+
+#ifndef TALK_SESSION_PHONE_CARBONVIDEORENDERER_H_
+#define TALK_SESSION_PHONE_CARBONVIDEORENDERER_H_
+
+#include <Carbon/Carbon.h>
+
+#include "talk/base/criticalsection.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/session/phone/mediachannel.h"
+
+namespace cricket {
+
+class CarbonVideoRenderer : public VideoRenderer {
+ public:
+  CarbonVideoRenderer(int x, int y);
+  virtual ~CarbonVideoRenderer();
+
+  // Implementation of pure virtual methods of VideoRenderer.
+  // These two methods may be executed in different threads.
+  // SetSize is called before RenderFrame.
+  virtual bool SetSize(int width, int height, int reserved);
+  virtual bool RenderFrame(const VideoFrame* frame);
+
+  // Needs to be called on the main thread.
+  bool Initialize();
+
+ private:
+  bool DrawFrame();
+
+  static OSStatus DrawEventHandler(EventHandlerCallRef handler,
+                                   EventRef event,
+                                   void* data);
+  talk_base::scoped_array<uint8> image_;
+  talk_base::CriticalSection image_crit_;
+  int image_width_;
+  int image_height_;
+  int x_;
+  int y_;
+  CGImageRef image_ref_;
+  WindowRef window_ref_;
+};
+
+}  // namespace cricket
+
+#endif  // TALK_SESSION_PHONE_CARBONVIDEORENDERER_H_
diff --git a/talk/session/phone/mediasessionclient.cc b/talk/session/phone/mediasessionclient.cc
index 6112db8..b4d440c 100644
--- a/talk/session/phone/mediasessionclient.cc
+++ b/talk/session/phone/mediasessionclient.cc
@@ -71,7 +71,7 @@
 
 
 void MediaSessionClient::Construct() {
-  // Register ourselves as the handler of phone and video sessions.
+  // Register ourselves as the handler of audio and video sessions.
   session_manager_->AddClient(NS_JINGLE_RTP, this);
   // Forward device notifications.
   SignalDevicesChange.repeat(channel_manager_->SignalDevicesChange);
diff --git a/talk/xmllite/xmlbuilder.cc b/talk/xmllite/xmlbuilder.cc
index b02dfe0..75daa57 100644
--- a/talk/xmllite/xmlbuilder.cc
+++ b/talk/xmllite/xmlbuilder.cc
@@ -25,16 +25,12 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "talk/xmllite/xmlbuilder.h"
+
 #include <vector>
 #include <set>
 #include "talk/base/common.h"
 #include "talk/xmllite/xmlelement.h"
-#include "talk/xmllite/xmlbuilder.h"
-#ifdef EXPAT_RELATIVE_PATH
-#include "lib/expat.h"
-#else
-#include "third_party/expat/v2_0_1/Source/lib/expat.h"
-#endif  // EXPAT_RELATIVE_PATH
 
 namespace buzz {
 
diff --git a/talk/xmllite/xmlbuilder.h b/talk/xmllite/xmlbuilder.h
index d375985..984eee2 100644
--- a/talk/xmllite/xmlbuilder.h
+++ b/talk/xmllite/xmlbuilder.h
@@ -34,7 +34,7 @@
 #include "talk/xmllite/xmlparser.h"
 
 #ifdef EXPAT_RELATIVE_PATH
-#include "lib/expat.h"
+#include "expat.h"
 #else
 #include "third_party/expat/v2_0_1/Source/lib/expat.h"
 #endif  // EXPAT_RELATIVE_PATH
diff --git a/talk/xmllite/xmlparser.cc b/talk/xmllite/xmlparser.cc
index 568bce1..5f6f7d5 100644
--- a/talk/xmllite/xmlparser.cc
+++ b/talk/xmllite/xmlparser.cc
@@ -31,15 +31,10 @@
 #include <vector>
 #include <iostream>
 #include "talk/base/common.h"
+#include "talk/xmllite/xmlconstants.h"
 #include "talk/xmllite/xmlelement.h"
 #include "talk/xmllite/xmlnsstack.h"
-#include "talk/xmllite/xmlconstants.h"
 #include "talk/xmllite/xmlnsstack.h"
-#ifdef EXPAT_RELATIVE_PATH
-#include "lib/expat.h"
-#else
-#include "third_party/expat/v2_0_1/Source/lib/expat.h"
-#endif  // EXPAT_RELATIVE_PATH
 
 namespace buzz {
 
diff --git a/talk/xmllite/xmlparser.h b/talk/xmllite/xmlparser.h
index 3e85e35..b461e7e 100644
--- a/talk/xmllite/xmlparser.h
+++ b/talk/xmllite/xmlparser.h
@@ -32,7 +32,7 @@
 
 #include "talk/xmllite/xmlnsstack.h"
 #ifdef EXPAT_RELATIVE_PATH
-#include "lib/expat.h"
+#include "expat.h"
 #else
 #include "third_party/expat/v2_0_1/Source/lib/expat.h"
 #endif  // EXPAT_RELATIVE_PATH
diff --git a/talk/xmpp/iqtask.cc b/talk/xmpp/iqtask.cc
new file mode 100644
index 0000000..d73aada
--- /dev/null
+++ b/talk/xmpp/iqtask.cc
@@ -0,0 +1,84 @@
+/*
+ * libjingle
+ * Copyright 2011, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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/iqtask.h"
+
+#include "talk/xmpp/xmppclient.h"
+#include "talk/xmpp/constants.h"
+
+namespace buzz {
+
+static const int kDefaultIqTimeoutSecs = 15;
+
+IqTask::IqTask(talk_base::Task* parent, const std::string& verb,
+               const buzz::Jid& to, buzz::XmlElement* el)
+    : buzz::XmppTask(parent, buzz::XmppEngine::HL_SINGLE),
+      to_(to),
+      stanza_(MakeIq(verb, to_, task_id())) {
+  stanza_->AddElement(el);
+  set_timeout_seconds(kDefaultIqTimeoutSecs);
+}
+
+int IqTask::ProcessStart() {
+  buzz::XmppReturnStatus ret = SendStanza(stanza_.get());
+  // TODO: HandleError(NULL) if SendStanza fails?
+  return (ret == buzz::XMPP_RETURN_OK) ? STATE_RESPONSE : STATE_ERROR;
+}
+
+bool IqTask::HandleStanza(const buzz::XmlElement* stanza) {
+  if (!MatchResponseIq(stanza, to_, task_id()))
+    return false;
+
+  if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_RESULT &&
+      stanza->Attr(buzz::QN_TYPE) != buzz::STR_ERROR) {
+    return false;
+  }
+
+  QueueStanza(stanza);
+  return true;
+}
+
+int IqTask::ProcessResponse() {
+  const buzz::XmlElement* stanza = NextStanza();
+  if (stanza == NULL)
+    return STATE_BLOCKED;
+
+  bool success = (stanza->Attr(buzz::QN_TYPE) == buzz::STR_RESULT);
+  if (success) {
+    HandleResult(stanza);
+  } else {
+    SignalError(stanza->FirstNamed(QN_ERROR));
+  }
+  return STATE_DONE;
+}
+
+int IqTask::OnTimeout() {
+  SignalError(NULL);
+  return XmppTask::OnTimeout();
+}
+
+}  // namespace buzz
diff --git a/talk/xmpp/iqtask.h b/talk/xmpp/iqtask.h
new file mode 100644
index 0000000..22e658d
--- /dev/null
+++ b/talk/xmpp/iqtask.h
@@ -0,0 +1,61 @@
+/*
+ * libjingle
+ * Copyright 2011, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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_XMPP_IQTASK_H_
+#define TALK_XMPP_IQTASK_H_
+
+#include <string>
+
+#include "talk/xmpp/xmpptask.h"
+#include "talk/xmpp/xmppengine.h"
+
+namespace buzz {
+
+class IqTask : public buzz::XmppTask {
+ public:
+  IqTask(talk_base::Task* parent, const std::string& verb, const buzz::Jid& to,
+         buzz::XmlElement* el);
+  virtual ~IqTask() {}
+
+  sigslot::signal1<const XmlElement*> SignalError;
+
+ protected:
+  virtual void HandleResult(const buzz::XmlElement* element) = 0;
+
+ private:
+  virtual int ProcessStart();
+  virtual bool HandleStanza(const buzz::XmlElement* stanza);
+  virtual int ProcessResponse();
+  virtual int OnTimeout();
+
+  buzz::Jid to_;
+  talk_base::scoped_ptr<buzz::XmlElement> stanza_;
+};
+
+}  // namespace buzz
+
+#endif  // TALK_XMPP_IQTASK_H_
diff --git a/talk/xmpp/mucroomlookuptask.cc b/talk/xmpp/mucroomlookuptask.cc
index 62b4b73..2cc5285 100644
--- a/talk/xmpp/mucroomlookuptask.cc
+++ b/talk/xmpp/mucroomlookuptask.cc
@@ -34,82 +34,17 @@
 
 namespace buzz {
 
-static const int kLookupTimeout = 15;
-
 MucRoomLookupTask::MucRoomLookupTask(Task* parent,
                                      const std::string& room_name,
                                      const std::string& organizer_domain)
-    : XmppTask(parent, XmppEngine::HL_SINGLE),
-      room_name_(room_name),
-      organizer_domain_(organizer_domain) {
-  set_timeout_seconds(kLookupTimeout);
+    : IqTask(parent, STR_SET, Jid(STR_MUC_LOOKUP_DOMAIN),
+             MakeRoomQuery(room_name, organizer_domain)) {
 }
 
 MucRoomLookupTask::MucRoomLookupTask(Task* parent,
                                      const Jid& room_jid)
-    : XmppTask(parent, XmppEngine::HL_SINGLE), room_jid_(room_jid) {
-  set_timeout_seconds(kLookupTimeout);
-}
-
-int MucRoomLookupTask::ProcessStart() {
-  talk_base::scoped_ptr<XmlElement> lookup(MakeIq(STR_SET,
-      Jid(STR_MUC_LOOKUP_DOMAIN), task_id()));
-  if (room_jid_ != JID_EMPTY) {
-    // TODO: need to test the jid query calling code below.
-    XmlElement* query_elem = MakeJidQuery(room_jid_.Str());
-    lookup->AddElement(query_elem);
-  } else {
-    // We do room query if room jid is unknown.
-    XmlElement* query_elem = MakeRoomQuery(room_name_, organizer_domain_);
-    lookup->AddElement(query_elem);
-  }
-
-  if (SendStanza(lookup.get()) != XMPP_RETURN_OK) {
-    SignalRoomLookupError(NULL);
-    return STATE_ERROR;
-  }
-  return STATE_RESPONSE;
-}
-
-int MucRoomLookupTask::ProcessResponse() {
-  const XmlElement* stanza = NextStanza();
-
-  if (stanza == NULL)
-    return STATE_BLOCKED;
-
-  if (stanza->Attr(QN_TYPE) == STR_ERROR) {
-    SignalRoomLookupError(stanza->FirstNamed(QN_ERROR));
-    return STATE_DONE;
-  }
-
-  const XmlElement* query_elem = stanza->FirstNamed(QN_SEARCH_QUERY);
-  if (query_elem != NULL) {
-    const XmlElement* item_elem =
-        query_elem->FirstNamed(QN_SEARCH_ITEM);
-    if (item_elem != NULL && item_elem->HasAttr(QN_JID)) {
-      MucRoomInfo room_info;
-      if (GetRoomInfoFromResponse(item_elem, &room_info)) {
-        SignalRoomLookupResponse(room_info);
-        return STATE_DONE;
-      }
-    }
-  }
-
-  SignalRoomLookupError(NULL);
-  return STATE_DONE;
-}
-
-int MucRoomLookupTask::OnTimeout() {
-  SignalRoomLookupError(NULL);
-  return XmppTask::OnTimeout();
-}
-
-bool MucRoomLookupTask::HandleStanza(const XmlElement* stanza) {
-  if (MatchResponseIq(stanza, Jid(STR_MUC_LOOKUP_DOMAIN), task_id())) {
-    QueueStanza(stanza);
-    return true;
-  }
-  return false;
+    : IqTask(parent, STR_SET, Jid(STR_MUC_LOOKUP_DOMAIN),
+             MakeJidQuery(room_jid)) {
 }
 
 XmlElement* MucRoomLookupTask::MakeRoomQuery(const std::string& room_name,
@@ -123,20 +58,35 @@
   XmlElement* query = new XmlElement(QN_SEARCH_QUERY, true);
   query->AddElement(room_elem);
   query->AddElement(domain_elem);
-
   return query;
 }
 
-XmlElement* MucRoomLookupTask::MakeJidQuery(const std::string& room_jid) {
+XmlElement* MucRoomLookupTask::MakeJidQuery(const Jid& room_jid) {
   XmlElement* jid_elem = new XmlElement(QN_SEARCH_ROOM_JID);
-  jid_elem->SetBodyText(room_jid);
+  jid_elem->SetBodyText(room_jid.Str());
 
   XmlElement* query = new XmlElement(QN_SEARCH_QUERY);
   query->AddElement(jid_elem);
-
   return query;
 }
 
+void MucRoomLookupTask::HandleResult(const XmlElement* stanza) {
+  const XmlElement* query_elem = stanza->FirstNamed(QN_SEARCH_QUERY);
+  if (query_elem != NULL) {
+    const XmlElement* item_elem =
+        query_elem->FirstNamed(QN_SEARCH_ITEM);
+    if (item_elem != NULL && item_elem->HasAttr(QN_JID)) {
+      MucRoomInfo room_info;
+      if (GetRoomInfoFromResponse(item_elem, &room_info)) {
+        SignalResult(room_info);
+        return;
+      }
+    }
+  }
+
+  SignalError(NULL);
+}
+
 bool MucRoomLookupTask::GetRoomInfoFromResponse(
     const XmlElement* stanza, MucRoomInfo* info) {
 
@@ -154,4 +104,5 @@
 
   return true;
 }
+
 }  // namespace buzz
diff --git a/talk/xmpp/mucroomlookuptask.h b/talk/xmpp/mucroomlookuptask.h
index ca56b3b..9ade9fa 100644
--- a/talk/xmpp/mucroomlookuptask.h
+++ b/talk/xmpp/mucroomlookuptask.h
@@ -29,39 +29,31 @@
 #define TALK_XMPP_MUCROOMLOOKUPTASK_H_
 
 #include <string>
-#include "talk/xmpp/xmpptask.h"
+#include "talk/xmpp/iqtask.h"
 
 namespace buzz {
 
 struct MucRoomInfo {
-  buzz::Jid room_jid;
+  Jid room_jid;
   std::string room_name;
   std::string organizer_domain;
 };
 
-class MucRoomLookupTask : public XmppTask {
+class MucRoomLookupTask : public IqTask {
  public:
   MucRoomLookupTask(Task* parent, const std::string& room_name,
       const std::string& organizer_domain);
   MucRoomLookupTask(Task* parent, const Jid& room_jid);
 
-  sigslot::signal1<const MucRoomInfo&> SignalRoomLookupResponse;
-  sigslot::signal1<const XmlElement*> SignalRoomLookupError;
-
- protected:
-  virtual bool HandleStanza(const XmlElement* stanza);
-  virtual int ProcessStart();
-  virtual int ProcessResponse();
-  virtual int OnTimeout();
+  sigslot::signal1<const MucRoomInfo&> SignalResult;
 
  private:
-  XmlElement* MakeRoomQuery(const std::string& room_name,
-      const std::string& org_domain);
-  XmlElement* MakeJidQuery(const std::string& room_jid);
-  bool GetRoomInfoFromResponse(const XmlElement* stanza, MucRoomInfo* info);
-  const std::string room_name_;
-  const std::string organizer_domain_;
-  const Jid room_jid_;
+  static XmlElement* MakeRoomQuery(const std::string& room_name,
+                                   const std::string& org_domain);
+  static XmlElement* MakeJidQuery(const Jid& room_jid);
+  virtual void HandleResult(const XmlElement* element);
+  static bool GetRoomInfoFromResponse(const XmlElement* stanza,
+                                      MucRoomInfo* info);
 };
 
 }  // namespace buzz
diff --git a/talk/xmpp/xmppclient.cc b/talk/xmpp/xmppclient.cc
index 1474e16..ba32908 100644
--- a/talk/xmpp/xmppclient.cc
+++ b/talk/xmpp/xmppclient.cc
@@ -111,21 +111,23 @@
   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"
+  // The talk.google.com server returns a certificate of "talk.google.com"
+  // for non-Gmail accounts, so we tweak this as needed:
+  // "foo@example.com" -> stream to="example.com"
+  // tls certificate for "talk.google.com"
+  // For Gmail accounts, and all other servers, we leave the strings empty,
+  // which causes the jid's domain to be used:
+  // "foo@gmail.com" -> stream to="gmail.com"
+  // tls certificate for "gmail.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
   std::string server_name = settings.server().IPAsString();
-  if ((server_name == buzz::STR_TALK_GOOGLE_COM ||
+  if (server_name == buzz::STR_TALK_GOOGLE_COM ||
       server_name == buzz::STR_TALKX_L_GOOGLE_COM ||
       server_name == buzz::STR_XMPP_GOOGLE_COM ||
-      server_name == buzz::STR_XMPPX_L_GOOGLE_COM) &&
-      pre_auth != NULL) {
-    d_->engine_->SetTlsServer(buzz::STR_GMAIL_COM, buzz::STR_GMAIL_COM);
+      server_name == buzz::STR_XMPPX_L_GOOGLE_COM) {
+    if (settings.host() != STR_GMAIL_COM) {
+      d_->engine_->SetTlsServer("", STR_TALK_GOOGLE_COM);
+    }
   }
 
   // Set language
diff --git a/talk/xmpp/xmppstanzaparser.cc b/talk/xmpp/xmppstanzaparser.cc
index 3aced15..6c3ef5f 100644
--- a/talk/xmpp/xmppstanzaparser.cc
+++ b/talk/xmpp/xmppstanzaparser.cc
@@ -25,12 +25,13 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "talk/xmpp/xmppstanzaparser.h"
+
 #include "talk/xmllite/xmlelement.h"
 #include "talk/base/common.h"
-#include "talk/xmpp/xmppstanzaparser.h"
 #include "talk/xmpp/constants.h"
 #ifdef EXPAT_RELATIVE_PATH
-#include "lib/expat.h"
+#include "expat.h"
 #else
 #include "third_party/expat/v2_0_1/Source/lib/expat.h"
 #endif