diff -u -r -x *~ pan-0.111/pan/gui/pan.cc panasync/pan/gui/pan.cc
--- pan-0.111/pan/gui/pan.cc	Tue Aug 29 17:20:44 2006
+++ panasync/pan/gui/pan.cc	Tue Sep  5 22:33:33 2006
@@ -160,6 +160,7 @@
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
   textdomain (GETTEXT_PACKAGE);
 
+  g_thread_init(NULL);
   gtk_init (&argc, &argv);
   g_mime_init (GMIME_INIT_FLAG_UTF8);
 
diff -u -r -x *~ pan-0.111/pan/tasks/nntp-pool.cc panasync/pan/tasks/nntp-pool.cc
--- pan-0.111/pan/tasks/nntp-pool.cc	Wed Aug 30 15:28:57 2006
+++ panasync/pan/tasks/nntp-pool.cc	Tue Sep  5 21:47:29 2006
@@ -108,12 +108,35 @@
 /***
 ****
 ***/
+
 void
 NNTP_Pool :: on_server_limits_changed (const Quark& server, int max_connections)
 {
   assert (server == _server);
   _max_connections = max_connections;
-std::cerr << LINE_ID << " pool for " << server << " knows that it has a max of " << max_connections << " connections" << std::endl;
+}
+
+/***
+****
+***/
+
+void
+NNTP_Pool :: on_socket_created (const StringView& host, int port, bool ok, Socket* socket)
+{
+  if (!ok)
+  {
+    delete socket;
+    _connection_pending = false;
+  }
+  else
+  {
+    // okay, we at least we established a connection.
+    // now try to handshake and pass the buck to on_nntp_done().
+    std::string user, pass;
+    _server_info.get_server_auth (_server, user, pass);
+    NNTP * nntp = new NNTP (_server, user, pass, socket);
+    nntp->handshake (this); // 
+  }
 }
 
 void
@@ -169,34 +192,27 @@
 void
 NNTP_Pool :: request_nntp ()
 {
-   int active, idle, pending, max;
-   get_counts (active, idle, pending, max);
+  int active, idle, pending, max;
+  get_counts (active, idle, pending, max);
 
 #if 0
-std::cerr << LINE_ID << "server " << _server << ", "
-          << "active: " << active << ' '
-          << "idle: " << idle << ' '
-          << "pending: " << pending << ' '
-          << "max: " << max << ' ' << std::endl;
+  std::cerr << LINE_ID << "server " << _server << ", "
+            << "active: " << active << ' '
+            << "idle: " << idle << ' '
+            << "pending: " << pending << ' '
+            << "max: " << max << ' ' << std::endl;
 #endif
 
-   if (!idle && !pending && active<max)
-   {
-      debug ("trying to create a socket");
-
-      std::string address;
-      int port;
-      _server_info.get_server_addr (_server, address, port);
-      Socket * sock (_socket_creator->create_socket (address, port));
-      if (sock != 0)
-      {
-         _connection_pending = true;
-         std::string user, pass;
-         _server_info.get_server_auth (_server, user, pass);
-         NNTP * nntp = new NNTP (_server, user, pass, sock);
-         nntp->handshake (this);
-      }
-   }
+  if (!idle && !pending && active<max)
+  {
+    debug ("trying to create a socket");
+
+    _connection_pending = true;
+    std::string address;
+    int port;
+    _server_info.get_server_addr (_server, address, port);
+    _socket_creator->create_socket (address, port, this);
+  }
 }
 
 /**
diff -u -r -x *~ pan-0.111/pan/tasks/nntp-pool.h panasync/pan/tasks/nntp-pool.h
--- pan-0.111/pan/tasks/nntp-pool.h	Mon Aug 21 17:43:03 2006
+++ panasync/pan/tasks/nntp-pool.h	Tue Sep  5 21:47:29 2006
@@ -37,7 +37,8 @@
   class NNTP_Pool:
     public NNTP::Source,
     private NNTP::Listener,
-    private ServerInfo::Listener
+    private ServerInfo::Listener,
+    private Socket::Creator::Listener
   {
     public:
 
@@ -76,6 +77,9 @@
 
     private: // ServerInfo::Listener
       virtual void on_server_limits_changed (const Quark& server, int max_connections);
+
+    private: // Socket::Creator::Listener
+      virtual void on_socket_created (const StringView& host, int port, bool ok, Socket*);
 
     private:
 
diff -u -r -x *~ pan-0.111/pan/tasks/nntp.cc panasync/pan/tasks/nntp.cc
--- pan-0.111/pan/tasks/nntp.cc	Thu Aug 17 15:25:19 2006
+++ panasync/pan/tasks/nntp.cc	Tue Sep  5 21:47:29 2006
@@ -112,13 +112,8 @@
 ****  WRITING
 ***/
 
-void
-NNTP :: onSocketOpen (Socket * sock)
-{
-}
-
 bool
-NNTP :: onSocketResponse (Socket * sock, const StringView& line_in)
+NNTP :: on_socket_response (Socket * sock, const StringView& line_in)
 {
    enum State { CMD_FAIL, CMD_DONE, CMD_MORE, CMD_NEXT, CMD_RETRY };
    State state;
@@ -264,13 +259,13 @@
 }
 
 void
-NNTP :: onSocketAbort (Socket * sock)
+NNTP :: on_socket_abort (Socket * sock)
 {
    fire_done_func (FAIL);
 }
 
 void
-NNTP :: onSocketError (Socket * sock)
+NNTP :: on_socket_error (Socket * sock)
 {
    _socket_error = true;
    fire_done_func (RETRY);
diff -u -r -x *~ pan-0.111/pan/tasks/nntp.h panasync/pan/tasks/nntp.h
--- pan-0.111/pan/tasks/nntp.h	Wed Jul 12 14:33:44 2006
+++ panasync/pan/tasks/nntp.h	Tue Sep  5 21:47:29 2006
@@ -257,10 +257,9 @@
 
     private: // private socket listener funcs, for socket handshake
 
-      virtual void onSocketOpen (Socket*);
-      virtual bool onSocketResponse (Socket*, const StringView& line);
-      virtual void onSocketError (Socket*);
-      virtual void onSocketAbort (Socket*);
+      virtual bool on_socket_response (Socket*, const StringView& line);
+      virtual void on_socket_error (Socket*);
+      virtual void on_socket_abort (Socket*);
 
     public:
 
diff -u -r -x *~ pan-0.111/pan/tasks/socket-impl-gio.cc panasync/pan/tasks/socket-impl-gio.cc
--- pan-0.111/pan/tasks/socket-impl-gio.cc	Wed Jul 19 09:51:23 2006
+++ panasync/pan/tasks/socket-impl-gio.cc	Tue Sep  5 22:09:14 2006
@@ -38,7 +38,7 @@
 
 #ifdef G_OS_WIN32
   // this #define is necessary for mingw
-  #define _WIN32_WINNT 0x0500
+  #define _WIN32_WINNT 0x0501
   #include <ws2tcpip.h>
   #undef gai_strerror
   #define gai_strerror(i) gai_strerror_does_not_link (i)
@@ -78,6 +78,8 @@
   #include <netinet/in.h>
   #include <netdb.h>
   #include <arpa/inet.h>
+  
+#define closesocket(xxx) close(xxx)
 #endif
 
 #include <pan/general/debug.h>
@@ -109,7 +111,6 @@
   {
     int err;
     int sockfd;
-    Log::add_info_va (_("Making a new connection to %*.*s"), host.len, host.len, host.str);
     ensure_module_inited ();
 
 #ifndef G_OS_WIN32
@@ -165,6 +166,8 @@
     if (!err)
       OutputDebugString ("Connection seems to be opened");
     else {
+      //windows only codepath
+      closesocket(sockfd);
       PrintLastError(err);
       return NULL;
     }
@@ -173,6 +176,7 @@
 
     struct addrinfo hints, *ans;
     GList * l=NULL, *list=NULL, *ipv4_list=NULL, *ipv6_list=NULL;
+    bool cnct(false),gotsock(false);
 
     memset (&hints, 0, sizeof(struct addrinfo));
     hints.ai_flags = 0;
@@ -206,32 +210,65 @@
     sockfd = -1;
     for (l=list; l!=NULL; l=l->next)
     {
+      char hostbuf[128];
       struct addrinfo * ainfo = (struct addrinfo*) l->data;
       sockfd = ::socket (ainfo->ai_family,
                          ainfo->ai_socktype,
                          ainfo->ai_protocol);
       if (sockfd >= 0)
-        break;
+      {
+        gotsock=true;
+        if(ainfo->ai_family==AF_INET)
+        {
+          struct sockaddr_in *sin=reinterpret_cast<sockaddr_in*>(ainfo->ai_addr);
+          unsigned char *addr=reinterpret_cast<unsigned char *>(&(sin->sin_addr));
+          g_snprintf (hostbuf, sizeof(hostbuf),
+                  "Trying host %u.%u.%u.%u, port %d\n",
+                  addr[0], addr[1], addr[2], addr[3], sin->sin_port);
+        }else if(ainfo->ai_family==AF_INET6)
+        {
+          struct sockaddr_in6 *sin=reinterpret_cast<sockaddr_in6*>(ainfo->ai_addr);
+          //is the addr in host or network order?
+          unsigned short *addr=reinterpret_cast<unsigned short *>(&(sin->sin6_addr));
+          g_snprintf (hostbuf, sizeof(hostbuf),
+                  "Trying host %x:%x:%x:%x:%x:%x:%x:%x, port %d\n",
+                  addr[0], addr[1],addr[2],addr[3],
+                  addr[4], addr[5],addr[6],addr[7],
+                  sin->sin6_port);
+        }else
+          g_snprintf (hostbuf, sizeof(hostbuf),"Trying host (unknown family).\n");
+        OutputDebugString (hostbuf);
+        // try to connect to the host
+        if (connect (sockfd, ainfo->ai_addr, ainfo->ai_addrlen) == 0)
+        {
+          cnct=true;
+          break;
+        }
+        //be nice and close the socket if it doesn't connect
+        closesocket(sockfd);
+        sockfd=-1;
+      }
     }
 
     g_list_free (list);
-    if (sockfd < 0) {
-      g_message ("couldn't create a socket.");
+    if (!gotsock) {
       ::freeaddrinfo (ans);
+      g_message ("couldn't create a socket.");
       return NULL;
     }
-
-    // try to connect to the host
-    if (connect (sockfd, ans->ai_addr, ans->ai_addrlen) < 0) {
-      g_message ("Connect failed: %s", g_strerror(errno));
+    if(!cnct)
+    {
       ::freeaddrinfo (ans);
+      g_message ("Connect failed");
       return NULL;
     }
 #endif
 
-    GIOChannel * channel = g_io_channel_unix_new (sockfd);
 #ifndef G_OS_WIN32
+    GIOChannel * channel = g_io_channel_unix_new (sockfd);
     g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
+#else
+    GIOChannel * channel = g_io_channel_win32_new_socket (sockfd);
 #endif
     if (g_io_channel_get_encoding (channel) != NULL)
       g_io_channel_set_encoding (channel, NULL, NULL);
@@ -285,18 +322,11 @@
   _in_buf = 0;
 }
 
-void
-GIOChannelSocket :: open (const StringView& address, int port, Listener * l)
+bool
+GIOChannelSocket :: open (const StringView& address, int port)
 {
-  _listener = l;
   _channel = create_channel (address, port);
-
-  if (_listener) {
-    if (_channel)
-      _listener->onSocketOpen (this);
-    else
-      _listener->onSocketError (this);
-  }
+  return _channel != 0;
 }
 
 void
@@ -335,7 +365,7 @@
          // strip off \r\n
          if (g->len>=2 && g->str[g->len-2]=='\r' && g->str[g->len-1]=='\n')
             g_string_truncate (g, g->len-2);
-         more = _listener->onSocketResponse (this, StringView (g->str, g->len));
+         more = _listener->on_socket_response (this, StringView (g->str, g->len));
       }
       else if (status == G_IO_STATUS_AGAIN)
       {
@@ -348,7 +378,7 @@
          Log::add_err_va (_("Error reading from socket: %s"), msg);
          if (err != NULL)
             g_clear_error (&err);
-         _listener->onSocketError (this);
+         _listener->on_socket_error (this);
          more = false;
       }
    }
@@ -356,7 +386,7 @@
    // if more is false, 'this' may have been deleted by the listeners...
    // so don't touch _abort_flag or _listener unless we're clean here.
    if (more && _abort_flag)
-      _listener->onSocketAbort (this);
+      _listener->on_socket_abort (this);
 
    return false;
 }
@@ -370,7 +400,7 @@
    if (_abort_flag)
    {
       finished = true;
-      _listener->onSocketAbort (this);
+      _listener->on_socket_abort (this);
    }
    else
    {
@@ -393,7 +423,7 @@
       if (err) {
          Log::add_err (err->message);
          g_clear_error (&err);
-         _listener->onSocketError (this);
+         _listener->on_socket_error (this);
          return false;
       }
 
@@ -423,14 +453,14 @@
    if (self->_abort_flag)
    {
       self->set_watch_mode (IGNORE_NOW);
-      self->_listener->onSocketAbort (self);
+      self->_listener->on_socket_abort (self);
       gimmie_more = false;
    }
    else if (!(cond & (G_IO_IN | G_IO_OUT)))
    {
       debug ("socket " << self << " got err or hup; ignoring");
       self->set_watch_mode (IGNORE_NOW);
-      self->_listener->onSocketError (self);
+      self->_listener->on_socket_error (self);
       gimmie_more = false;
    }
    else if (cond & G_IO_IN)
@@ -502,4 +532,53 @@
    }
 
    debug ("set_watch_mode " << mode << ": _tag_watch is now " << _tag_watch);
+}
+
+/***
+****  GIOChannel::SocketCreator -- create a socket in a worker thread
+***/
+
+namespace
+{
+  struct ThreadInfo
+  {
+    std::string host;
+    int port;
+    Socket::Creator::Listener * listener;
+
+    bool ok;
+    Socket * socket;
+
+    ThreadInfo (const StringView& h, int p, Socket::Creator::Listener *l):
+      host(h), port(p), listener(l), ok(false), socket(0) {}
+  };
+
+  gboolean socket_created_idle (gpointer info_gpointer)
+  {
+    ThreadInfo * info (static_cast<ThreadInfo*>(info_gpointer));
+    info->listener->on_socket_created (info->host, info->port, info->ok, info->socket);
+    delete info;
+    return false;
+  }
+
+  gpointer create_socket_thread_func (gpointer info_gpointer)
+  {
+    ThreadInfo * info (static_cast<ThreadInfo*>(info_gpointer));
+    info->socket = new GIOChannelSocket ();
+    info->ok = info->socket->open (info->host, info->port);
+    g_idle_add (socket_created_idle, info); // pass the results back to the main thread...
+    return 0;
+  }
+}
+  
+void
+GIOChannelSocket :: Creator :: create_socket (const StringView & host,
+                                              int                port,
+                                              Listener         * listener)
+{
+  // farm this out to a worker thread so that the main thread
+  // doesn't block while we open the socket.
+  g_thread_create (create_socket_thread_func,
+                   new ThreadInfo (host, port, listener),
+                   true, 0);
 }
diff -u -r -x *~ pan-0.111/pan/tasks/socket-impl-gio.h panasync/pan/tasks/socket-impl-gio.h
--- pan-0.111/pan/tasks/socket-impl-gio.h	Sun Mar 26 13:35:47 2006
+++ panasync/pan/tasks/socket-impl-gio.h	Tue Sep  5 21:47:29 2006
@@ -25,49 +25,45 @@
 
 namespace pan
 {
-   /**
-    * glib implementation of Socket
-    * 
-    * @ingroup tasks
-    */
-   class GIOChannelSocket: public Socket
-   {
-      public:
-
-         GIOChannelSocket ();
-         virtual ~GIOChannelSocket ();
-         virtual void open (const StringView& address, int port, Listener *);
-         virtual void write_command (const StringView& chars, Listener *);
-
-      private:
-
-         GIOChannel * _channel;
-         unsigned int _tag_watch;
-         Listener * _listener;
-         GString * _out_buf;
-         GString * _in_buf;
-
-         enum WatchMode { READ_NOW, READ_LATER, WRITE_NOW, IGNORE_NOW };
-         void set_watch_mode (WatchMode mode);
-         static gboolean gio_func (GIOChannel*, GIOCondition, gpointer);
-         static gboolean read_later (gpointer);
-         bool do_read ();
-         bool do_write ();
-
-      public:
-
-         /**
-          * Socket::Creator that instantiates GIOSocket objects.
-          */
-         struct Creator: public Socket::Creator {
-            virtual ~Creator () { }
-            virtual Socket* create_socket (const StringView& host, int port) {
-               GIOChannelSocket * sock = new GIOChannelSocket ();
-               sock->open (host, port, NULL);
-               return sock;
-            }
-         };
-   };
+  /**
+   * glib implementation of Socket
+   * 
+   * @ingroup tasks
+   */
+  class GIOChannelSocket: public Socket
+  {
+    public:
+      GIOChannelSocket ();
+      virtual ~GIOChannelSocket ();
+      virtual bool open (const StringView& address, int port);
+      virtual void write_command (const StringView& chars, Listener *);
+
+    private:
+      GIOChannel * _channel;
+      unsigned int _tag_watch;
+      Listener * _listener;
+      GString * _out_buf;
+      GString * _in_buf;
+
+    private:
+      enum WatchMode { READ_NOW, READ_LATER, WRITE_NOW, IGNORE_NOW };
+      void set_watch_mode (WatchMode mode);
+      static gboolean gio_func (GIOChannel*, GIOCondition, gpointer);
+      static gboolean read_later (gpointer);
+      bool do_read ();
+      bool do_write ();
+
+    public:
+
+      /**
+       * Socket::Creator that instantiates GIOSocket objects.
+       */
+      class Creator: public Socket::Creator {
+        public:
+          virtual ~Creator () { }
+          virtual void create_socket (const StringView& host, int port, Listener *l);
+      };
+  };
 }
 
 #endif
diff -u -r -x *~ pan-0.111/pan/tasks/socket-impl-scripted.cc panasync/pan/tasks/socket-impl-scripted.cc
--- pan-0.111/pan/tasks/socket-impl-scripted.cc	Wed Jun 14 15:19:41 2006
+++ panasync/pan/tasks/socket-impl-scripted.cc	Tue Sep  5 21:47:29 2006
@@ -37,11 +37,11 @@
 {
 }
 
-void
-ScriptedSocket :: open (const StringView& address, int port, Listener * l)
+bool
+ScriptedSocket :: open (const StringView& address, int port)
 {
-   // FIXME: always succeeds right now; should have an ar in ctor to make it fail
-   l->onSocketOpen (this);
+  // FIXME: always succeeds right now; should have an ar in ctor to make it fail
+  return true;
 }
 
 void
@@ -69,14 +69,14 @@
       responses.pop_front ();
       if (s == NETWORK_ERROR) {
          listener_wants_more = false;
-         l->onSocketError (this);
+         l->on_socket_error (this);
       } else if (s == ABORT) {
          listener_wants_more = false;
-         l->onSocketAbort (this);
+         l->on_socket_abort (this);
       }
       else {
          debug ("got [" << cat.first << "], writing [" << s << ']');
-         listener_wants_more = l->onSocketResponse (this, s);
+         listener_wants_more = l->on_socket_response (this, s);
       }
    }
 
diff -u -r -x *~ pan-0.111/pan/tasks/socket-impl-scripted.h panasync/pan/tasks/socket-impl-scripted.h
--- pan-0.111/pan/tasks/socket-impl-scripted.h	Sat Feb 25 13:36:11 2006
+++ panasync/pan/tasks/socket-impl-scripted.h	Tue Sep  5 21:47:29 2006
@@ -38,7 +38,7 @@
 
          ScriptedSocket ();
          virtual ~ScriptedSocket ();
-         virtual void open (const StringView& address, int port, Listener *);
+         virtual bool open (const StringView& address, int port);
          virtual void write_command (const StringView& chars, Listener *);
 
          typedef std::deque<std::string> strings_t;
diff -u -r -x *~ pan-0.111/pan/tasks/socket.h panasync/pan/tasks/socket.h
--- pan-0.111/pan/tasks/socket.h	Fri May  5 01:05:48 2006
+++ panasync/pan/tasks/socket.h	Tue Sep  5 21:47:29 2006
@@ -42,14 +42,13 @@
       /** Interface class for objects that listen to a Socket's events */
       struct Listener {
         virtual ~Listener () {}
-        virtual void onSocketOpen (Socket*) = 0;
-        virtual bool onSocketResponse (Socket*, const StringView& line) = 0;
-        virtual void onSocketError (Socket*) = 0;
-        virtual void onSocketAbort (Socket*) = 0;
+        virtual bool on_socket_response (Socket*, const StringView& line) = 0;
+        virtual void on_socket_error (Socket*) = 0;
+        virtual void on_socket_abort (Socket*) = 0;
       };
 
     public:
-      virtual void open (const StringView& address, int port, Listener *) = 0;
+      virtual bool open (const StringView& address, int port) = 0;
       virtual void write_command (const StringView& chars, Listener *) = 0;
 
     public:
@@ -76,9 +75,15 @@
        * 
        * @ingroup tasks
        */
-      struct Creator {
+      struct Creator
+      {
+        struct Listener {
+          virtual ~Listener () {}
+          virtual void on_socket_created (const StringView& host, int port, bool ok, Socket*) = 0;
+        };
+
         virtual ~Creator () { }
-        virtual Socket* create_socket (const StringView& host, int port) = 0;
+        virtual void create_socket (const StringView& host, int port, Listener*) = 0;
       };
   };
 }
