[pan2] * memory leak at void GUI :: do_save_articles_to_nzb () fixed. * check for executable bit in folders



commit c492965650b67f53e0deee67a1c7583f3ea90f9a
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Sat Dec 3 00:34:21 2011 +0100

    * memory leak at void GUI :: do_save_articles_to_nzb () fixed.
    * check for executable bit in folders (from judgefudge tree)
    * dbus support -> bugzilla 360809: queue enqueue while pan is working :D
    
    Used libgio-2.0 functions to create the sockets, much more portable

 pan/data-impl/Makefile.am    |   42 ++++----
 pan/data-impl/data-io.cc     |    6 +
 pan/data-impl/data-io.h      |    3 +-
 pan/general/file-util.cc     |   53 ++++++++-
 pan/gui/gui.cc               |   15 ++-
 pan/gui/pan.cc               |  245 ++++++++++++++++++++++++++++++++++++++++--
 pan/tasks/queue.h            |    5 +-
 pan/tasks/socket-impl-gio.cc |  230 +++------------------------------------
 pan/tasks/socket-impl-gio.h  |    2 +-
 9 files changed, 346 insertions(+), 255 deletions(-)
---
diff --git a/pan/data-impl/Makefile.am b/pan/data-impl/Makefile.am
index ed09bd2..92322c7 100644
--- a/pan/data-impl/Makefile.am
+++ b/pan/data-impl/Makefile.am
@@ -22,26 +22,26 @@ noinst_HEADERS = \
  profiles.h \
  memchunk.h
 
-noinst_PROGRAMS = \
- add-server \
- headers-test \
- speed-test-load-group
+#noinst_PROGRAMS = \
+# add-server \
+# headers-test \
+# speed-test-load-group
 
-TESTS = \
- add-server \
- headers-test 
+#TESTS = \
+# add-server \
+# headers-test
 
-TEST_LDADD = \
- ./libpandata.a \
- ../tasks/libtasks.a \
- ../data/libdata.a \
- ../usenet-utils/libusenetutils.a \
- ../general/libgeneralutils.a \
- ../../uulib/libuu.a \
- @GMIME_LIBS@ @GLIB_LIBS@
-add_server_SOURCES = add-server.cc
-add_server_LDADD = $(TEST_LDADD)
-headers_test_SOURCES = headers-test.cc
-headers_test_LDADD = $(TEST_LDADD)
-speed_test_load_group_SOURCES = speed-test-load-group.cc
-speed_test_load_group_LDADD = $(TEST_LDADD)
+#TEST_LDADD = \
+# ./libpandata.a \
+# ../tasks/libtasks.a \
+# ../data/libdata.a \
+# ../usenet-utils/libusenetutils.a \
+# ../general/libgeneralutils.a \
+# ../../uulib/libuu.a \
+# @GMIME_LIBS@ @GLIB_LIBS@
+#add_server_SOURCES = add-server.cc
+#add_server_LDADD = $(TEST_LDADD)
+#headers_test_SOURCES = headers-test.cc
+#headers_test_LDADD = $(TEST_LDADD)
+#speed_test_load_group_SOURCES = speed-test-load-group.cc
+#speed_test_load_group_LDADD = $(TEST_LDADD)
diff --git a/pan/data-impl/data-io.cc b/pan/data-impl/data-io.cc
index b8f4f2a..4146426 100644
--- a/pan/data-impl/data-io.cc
+++ b/pan/data-impl/data-io.cc
@@ -116,6 +116,12 @@ DataIO :: get_server_filename () const
   return get_pan_home_file ("servers.xml");
 }
 
+std::string
+DataIO :: get_lock_filename ()
+{
+  return get_pan_home_file ("pan.lock");
+}
+
 /****
 *****
 ****/
diff --git a/pan/data-impl/data-io.h b/pan/data-impl/data-io.h
index 207c1c2..0efe6e8 100644
--- a/pan/data-impl/data-io.h
+++ b/pan/data-impl/data-io.h
@@ -31,7 +31,7 @@ namespace pan
    * Specifies the datafiles used by DataImpl.
    * It's abstracted out so that unit tests can substitute in its own data.
    * This private class should only be used by code in the data-impl module.
-   * 
+   *
    * @ingroup data_impl
    */
   struct DataIO
@@ -42,6 +42,7 @@ namespace pan
     virtual std::string get_scorefile_name () const;
     virtual std::string get_posting_name () const;
     virtual std::string get_server_filename () const;
+    static std::string get_lock_filename () ;
 
     virtual void clear_group_headers (const Quark& group);
 
diff --git a/pan/general/file-util.cc b/pan/general/file-util.cc
index 4945d83..afe6e7c 100644
--- a/pan/general/file-util.cc
+++ b/pan/general/file-util.cc
@@ -18,7 +18,6 @@
  */
 
 #include <config.h>
-
 #include <cassert>
 #include <cerrno>
 #include <cctype>
@@ -28,9 +27,11 @@ extern "C"
   #include <unistd.h>
   #include <sys/stat.h>
   #include <sys/types.h>
-
   #include <glib.h>
   #include <glib/gi18n.h>
+  #ifndef G_OS_WIN32
+    #include <pwd.h>
+  #endif
 }
 
 #include "debug.h"
@@ -40,6 +41,8 @@ extern "C"
 #include "utf8-utils.h"
 #include <algorithm>
 
+
+
 using namespace pan;
 
 #define is_nonempty_string(a) ((a) && (*a))
@@ -63,7 +66,7 @@ file :: get_pan_home ()
       g_free (pch);
     }
   }
-                                                                                                                                
+
   file :: ensure_dir_exists (pan_home);
   return pan_home;
 }
@@ -75,6 +78,30 @@ file :: pan_strerror (int error_number)
   return pch && *pch ? pch : "";
 }
 
+namespace
+{
+
+  enum EX_ERRORS
+  {
+    EX_NOFILE, EX_BIT, EX_SUCCESS
+  };
+
+  EX_ERRORS check_executable_bit(const char* d)
+  {
+#ifndef G_OS_WIN32
+    struct stat sb;
+    if (stat (d, &sb) == -1) return EX_NOFILE;
+    const char* user(g_get_user_name());
+    struct passwd* pw(getpwnam(user));
+    if (sb.st_mode & S_IXUSR || ((sb.st_mode & S_IXGRP ) && pw->pw_gid == sb.st_gid))
+      return EX_SUCCESS;
+    return EX_BIT;
+#else
+    return EX_SUCCESS;
+#endif
+  }
+}
+
 bool
 file :: ensure_dir_exists (const StringView& dirname_sv)
 {
@@ -82,11 +109,27 @@ file :: ensure_dir_exists (const StringView& dirname_sv)
 
   pan_return_val_if_fail (!dirname_sv.empty(), true);
   bool retval (true);
-
   const std::string dirname (dirname_sv.to_string());
+  EX_ERRORS cmd (check_executable_bit(dirname.c_str()));
+  if (cmd == EX_BIT) goto _set_bit;
+
   if (!g_file_test (dirname.c_str(), G_FILE_TEST_IS_DIR))
-    retval = !g_mkdir_with_parents (dirname.c_str(), 0755);
+    retval = !g_mkdir_with_parents (dirname.c_str(), 0740); // changed from 755
 
+  if (!retval)
+  {
+    // check for executable bit
+    Log::add_err_va("Error creating directory '%s' : %s", dirname.c_str(),
+                    cmd == EX_NOFILE ? "error accessing file." : "executable bit not set.");
+    // set it manually
+    _set_bit:
+    if (cmd == EX_BIT)
+      if (chmod(dirname.c_str(), 0740))
+      {
+        Log::add_urgent_va("Error setting executable bit for directory '%s' : "
+                           "Please check your permissions.", dirname.c_str());
+      }
+  }
   return retval;
 }
 
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index 53ec36a..b614301 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -594,12 +594,15 @@ void GUI :: do_save_articles_to_nzb ()
       foreach_const (std::vector<Article>, copies, it)
         tasks.push_back (new TaskArticle (_data, _data, *it, _cache, _data, 0, TaskArticle::RAW,emptystring));
 
-          // write them to a file
-          std::ofstream tmp(file.c_str());
-          if (tmp.good()) {
-            NZB :: nzb_to_xml_file (tmp, tasks);
-            tmp.close();
-          }
+      // write them to a file
+      std::ofstream tmp(file.c_str());
+      if (tmp.good()) {
+        NZB :: nzb_to_xml_file (tmp, tasks);
+        tmp.close();
+      }
+      // cleanup the virtual queue
+      foreach(Queue::tasks_t, tasks, it)
+        delete *it;
     }
 }
 
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index 5f47aa0..6b1c5c7 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -24,11 +24,18 @@ extern "C" {
   #include <glib/gi18n.h>
   #include <gtk/gtk.h>
   #include <gmime/gmime.h>
+  #include <gio/gio.h>
+  #include <sys/types.h>
+  #include <sys/stat.h>
+  #include <unistd.h>
 }
+
 #ifdef G_OS_WIN32
-#define _WIN32_WINNT 0x0501
-#include <windows.h>
+  #undef _WIN32_WINNT
+  #define _WIN32_WINNT 0x0501
+  #include <windows.h>
 #endif
+
 #include <pan/general/debug.h>
 #include <pan/general/log.h>
 #include <pan/general/file-util.h>
@@ -38,6 +45,7 @@ extern "C" {
 #include <pan/tasks/task-xover.h>
 #include <pan/tasks/nzb.h>
 #include <pan/data-impl/data-impl.h>
+#include <pan/data-impl/data-io.h>
 #include <pan/icons/pan-pixbufs.h>
 #include "gui.h"
 #include "group-prefs.h"
@@ -50,6 +58,11 @@ using namespace pan;
 
 namespace
 {
+  typedef std::vector<std::string> strings_t;
+}
+
+namespace
+{
   GMainLoop * nongui_gmainloop (0);
 
   void mainloop ()
@@ -232,9 +245,13 @@ _("General Options\n"
 "  -h, --help               Show this usage page.\n"
 "\n"
 "URL Options\n"
-"  news:message-id          Show the specified article.\n"
+
+// Doesn't work yet.
+/*"  news:message-id          Show the specified article.\n"
 "  news:group.name          Show the specified newsgroup.\n"
 "  headers:group.name       Download new headers for the specified newsgroup.\n"
+*/
+
 "  --no-gui                 On news:message-id, dump the article to stdout.\n"
 "\n"
 "NZB Batch Options\n"
@@ -242,8 +259,184 @@ _("General Options\n"
 "  -o path, --output=path   Path to save attachments listed in the nzb files.\n"
 "  --no-gui                 Only show console output, not the download queue.\n") << std::endl;
   }
+
+  /***
+   ** DBUS STUFF
+   ***/
+
+  #define PAN_DBUS_SERVICE_NAME      "news.pan.NZB"
+  #define PAN_DBUS_SERVICE_PATH      "/news/pan/NZB"
+
+  /** Struct for dbus handling */
+  struct Pan
+  {
+    Data& data;
+    Queue& queue;
+    ArticleCache& cache;
+    Prefs& prefs;
+    GroupPrefs& group_prefs;
+    int dbus_id;
+    bool name_valid;
+    bool lost_name;
+
+    GDBusNodeInfo * busnodeinfo;
+    GDBusInterfaceVTable ifacetable;
+
+    Pan(Data& d, Queue& q, ArticleCache& c, Prefs& p, GroupPrefs& gp) :
+      dbus_id(-1), busnodeinfo(0),
+      data(d), queue(q), cache(c), prefs(p), group_prefs(gp),
+      lost_name(false), name_valid(false)
+      {}
+  };
+
+  static void
+  nzb_method_call  (GDBusConnection      *connection,
+                   const gchar           *sender,
+                   const gchar           *object_path,
+                   const gchar           *interface_name,
+                   const gchar           *method_name,
+                   GVariant              *parameters,
+                   GDBusMethodInvocation *invocation,
+                   gpointer               user_data)
+  {
+
+    Pan* pan(static_cast<Pan*>(user_data));
+    if (!pan) return;
+
+    gboolean gui(false), nzb(false);
+    gchar* groups;
+    gchar* nzb_output_path;
+    gchar* nzbs;
+    strings_t nzb_files;
+
+    if (g_strcmp0 (method_name, "NZBEnqueue") == 0)
+    {
+      g_variant_get (parameters, "(sssbb)", &groups, &nzb_output_path, &nzbs, &gui, &nzb);
+
+      if (groups)
+        if (strlen(groups)!=0)
+        {
+          StringView tok, v(groups);
+          while (v.pop_token(tok,','))
+            pan->queue.add_task (new TaskXOver (pan->data, tok, TaskXOver::NEW), Queue::BOTTOM);
+        }
+
+      if (nzb && nzbs)
+      {
+        //parse the files
+        StringView tok, nzb(nzbs);
+        while (nzb.pop_token(tok))
+          nzb_files.push_back(tok);
+
+        // load the nzb files...
+        std::vector<Task*> tasks;
+        foreach_const (strings_t, nzb_files, it)
+          NZB :: tasks_from_nzb_file (*it, nzb_output_path, pan->cache, pan->data, pan->data, pan->data, tasks);
+        pan->queue.add_tasks (tasks, Queue::BOTTOM);
+      }
+    }
+
+    g_dbus_method_invocation_return_value (invocation, NULL);
+  }
+
+  static GDBusConnection *dbus_connection(NULL);
+
+  static const gchar xml[]=
+  "<node>"
+  "  <interface name='news.pan.NZB'>"
+  "    <method name='NZBEnqueue'>"
+  "      <arg type='s' name='groups'    direction='in'/>"
+  "      <arg type='s' name='nzb_files' direction='in'/>"
+  "      <arg type='s' name='nzb_path'  direction='in'/>"
+  "      <arg type='b' name='gui'       direction='in'/>"
+  "      <arg type='b' name='nzb'       direction='in'/>"
+  "    </method>"
+  "  </interface>"
+  "</node>";
+
+
+  static void
+  on_bus_acquired (GDBusConnection *connection,
+                   const gchar     *name,
+                   gpointer         user_data)
+  {
+    Pan* pan (static_cast<Pan*>(user_data));
+    g_return_if_fail (pan);
+
+    pan->busnodeinfo = g_dbus_node_info_new_for_xml (xml, NULL);
+
+   /* init iface table */
+    GDBusInterfaceVTable tmp =
+    {
+      nzb_method_call ,
+      NULL, NULL
+    };
+    pan->ifacetable = tmp;
+
+    g_dbus_connection_register_object(
+      connection,
+      "/news/pan/NZB",
+      pan->busnodeinfo->interfaces[0],
+      &pan->ifacetable,
+      pan,
+      NULL,
+      NULL
+    );
+
+  }
+
+  static void
+  on_name_acquired (GDBusConnection *connection,
+                    const gchar     *name,
+                    gpointer         user_data)
+  {
+
+    Pan* pan(static_cast<Pan*>(user_data));
+    g_return_if_fail (pan);
+
+    if (connection)
+    {
+      dbus_connection = connection;
+      pan->name_valid = true;
+      pan->lost_name = false;
+    }
+  }
+
+  static void
+  on_name_lost (GDBusConnection *connection,
+                const gchar     *name,
+                gpointer         user_data)
+  {
+    Pan* pan(static_cast<Pan*>(user_data));
+    g_return_if_fail (pan);
+
+    pan->name_valid = false;
+    pan->lost_name = true;
+    pan->dbus_id= -1;
+
+  }
+
+
+  static void
+  pan_dbus_init (Pan* pan)
+  {
+    pan->dbus_id = g_bus_own_name(
+        G_BUS_TYPE_SESSION,
+        PAN_DBUS_SERVICE_NAME,
+        G_BUS_NAME_OWNER_FLAGS_NONE,
+        on_bus_acquired,
+        on_name_acquired,
+        on_name_lost,
+        pan,NULL);
+  }
+
+  /***
+   ***
+   ***/
+
 }
 
+
 int
 main (int argc, char *argv[])
 {
@@ -251,6 +444,7 @@ main (int argc, char *argv[])
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
   textdomain (GETTEXT_PACKAGE);
 
+  g_type_init();
   g_thread_init (0);
   g_mime_init (GMIME_ENABLE_RFC2047_WORKAROUNDS);
 
@@ -258,8 +452,8 @@ main (int argc, char *argv[])
   std::string url;
   std::string groups;
   std::string nzb_output_path;
-  typedef std::vector<std::string> strings_t;
   strings_t nzb_files;
+  std::string nzb_str;
 
   for (int i=1; i<argc; ++i)
   {
@@ -287,6 +481,8 @@ main (int argc, char *argv[])
     else {
       nzb = true;
       nzb_files.push_back (tok);
+      if (nzb_files.size() > 1) nzb_str +=" ";
+      nzb_str += tok;
     }
   }
 
@@ -322,9 +518,38 @@ main (int argc, char *argv[])
     // instantiate the queue...
     WorkerPool worker_pool (4, true);
     GIOChannelSocket::Creator socket_creator;
-    Queue queue (data, data, &socket_creator, worker_pool,
-                 prefs.get_flag ("work-online", true),
-                 prefs.get_int ("task-save-delay-secs", 10));
+    Queue queue (data, data, &socket_creator, worker_pool, false, 32768);
+
+
+    ///////////// DBUS
+
+    Pan pan(data, queue, cache, prefs, group_prefs);
+#ifndef G_OS_WIN32
+    pan_dbus_init(&pan);
+
+    GError* error(NULL);
+    GVariant* var = g_variant_new ("(sssbb)",
+                    groups.c_str(), nzb_output_path.c_str(), nzb_str.c_str(),  gui, nzb);
+    g_dbus_connection_call_sync (g_bus_get_sync  (G_BUS_TYPE_SESSION , NULL, NULL),
+                           PAN_DBUS_SERVICE_NAME,
+                           PAN_DBUS_SERVICE_PATH,
+                           "news.pan.NZB",
+                           "NZBEnqueue",
+                           var,
+                           NULL,
+                           G_DBUS_CALL_FLAGS_NONE,
+                           -1,
+                           NULL,
+                           &error);
+    if (!error)
+    {
+      std::cerr<<"Added "<<nzb_files.size()<<" files to the queue. Exiting.\n";
+      exit(EXIT_SUCCESS);
+    }
+#endif
+    queue.set_online(true);
+    queue.set_task_save_delay(prefs.get_int ("task-save-delay-secs", 10));
+
     g_timeout_add (5000, queue_upkeep_timer_cb, &queue);
 
     if (nzb || !groups.empty())
@@ -349,7 +574,7 @@ main (int argc, char *argv[])
         queue.add_tasks (tasks, Queue::BOTTOM);
       }
 
-      // iff non-gui mode, contains a PanKiller ptr to quit pan on queue empty
+      // if in non-gui mode, contains a PanKiller ptr to quit pan on queue empty
       std::auto_ptr<PanKiller> killer;
 
       // don't open the full-blown Pan, just act as a nzb client,
@@ -384,9 +609,13 @@ main (int argc, char *argv[])
       gtk_window_set_resizable (GTK_WINDOW(window), true);
       gtk_window_set_default_icon (pixbuf);
       g_object_unref (pixbuf);
+
       run_pan_in_window (cache, data, queue, prefs, group_prefs, GTK_WINDOW(window));
     }
 
+    if (pan.dbus_id != -1 ) g_bus_unown_name(pan.dbus_id);
+    if (dbus_connection) g_dbus_connection_close(dbus_connection,NULL,0,NULL);
+
     worker_pool.cancel_all_silently ();
 
     if (prefs.get_flag("clear-article-cache-on-shutdown", false))
diff --git a/pan/tasks/queue.h b/pan/tasks/queue.h
index 09b97ef..b2e0574 100644
--- a/pan/tasks/queue.h
+++ b/pan/tasks/queue.h
@@ -98,7 +98,7 @@ namespace pan
         ServerConnectionCounts(): active(0), idle(0), connecting(0), KiBps(0.0) {}
       };
       void get_full_connection_counts (std::vector<ServerConnectionCounts>& setme) const;
-                                         
+
 
     public:
       enum TaskState { QUEUED, RUNNING, DECODING, STOPPED, REMOVING,
@@ -219,6 +219,9 @@ namespace pan
       time_t _last_time_saved;
       quarks_t _mids;
 
+    public:
+      void set_task_save_delay(int value) { _save_delay_secs = value; }
+
     private:
       TaskArchive& _archive;
       void clean_n_save ();
diff --git a/pan/tasks/socket-impl-gio.cc b/pan/tasks/socket-impl-gio.cc
index a0e14eb..7930e73 100644
--- a/pan/tasks/socket-impl-gio.cc
+++ b/pan/tasks/socket-impl-gio.cc
@@ -32,6 +32,7 @@
 extern "C" {
   #include <unistd.h>
   #include <glib/gi18n.h>
+  #include <gio/gio.h>
 }
 
 #include <pan/general/file-util.h>
@@ -39,51 +40,6 @@ extern "C" {
 #include <pan/general/macros.h>
 #include <pan/general/worker-pool.h>
 
-#ifdef G_OS_WIN32
-  // this #define is necessary for mingw
-  #define _WIN32_WINNT 0x0501
-  #include <ws2tcpip.h>
-  #undef gai_strerror
-  /*
-  #define gai_strerror(i) gai_strerror_does_not_link (i)
-  static const char*
-  gai_strerror_does_not_link (int errval)
-  {
-    static char buf[32];
-    g_snprintf (buf, sizeof(buf), "Winsock error %d", errval);
-    return buf;
-  }
-  */
-  static const char*
-  get_last_error (int err)
-  {
-    const char * msg = 0;
-    switch(err) {
-      case WSANOTINITIALISED: msg = "No successful WSAStartup call yet."; break;
-      case WSAENETDOWN: msg = "The network subsystem has failed."; break;
-      case WSAEADDRINUSE: msg = "Fully qualified address already bound"; break;
-      case WSAEADDRNOTAVAIL: msg = "The specified address is not a valid address for this computer."; break;
-      case WSAEFAULT: msg = "Error in socket address"; break;
-      case WSAEINPROGRESS: msg = "A call is already in progress"; break;
-      case WSAEINVAL: msg = "The socket is already bound to an address."; break;
-      case WSAENOBUFS: msg = "Not enough buffers available, too many connections."; break;
-      case WSAENOTSOCK: msg = "The descriptor is not a socket."; break;
-      case 11001: msg = "Host not found"; break;
-      default: msg = "Connect failed";
-    }
-    return msg;
-  }
-
-#else
-  #include <signal.h>
-  #include <sys/types.h>
-  #include <sys/socket.h>
-  #include <netinet/in.h>
-  #include <netdb.h>
-  #include <arpa/inet.h>
-  #define closesocket(fd) close(fd)
-#endif
-
 #include <pan/general/debug.h>
 #include <pan/general/log.h>
 #include <pan/general/string-view.h>
@@ -94,184 +50,39 @@ using namespace pan;
 
 namespace
 {
-  typedef int (*t_getaddrinfo)(const char *,const char *, const struct addrinfo*, struct addrinfo **);
-  t_getaddrinfo p_getaddrinfo (0);
-
-  typedef void (*t_freeaddrinfo)(struct addrinfo*);
-  t_freeaddrinfo p_freeaddrinfo (0);
-
-  void ensure_module_inited (void)
-  {
-    static bool inited (false);
+  const unsigned int TIMEOUT_SECS (30);
+}
 
-    if (!inited)
-    {
-      p_freeaddrinfo=NULL;
-      p_getaddrinfo=NULL;
-
-#ifdef G_OS_WIN32
-      WSADATA wsaData;
-      WSAStartup(MAKEWORD(2,2), &wsaData);
-
-      char sysdir[MAX_PATH], path[MAX_PATH+8];
-
-      if(GetSystemDirectory(sysdir,MAX_PATH)!=0)
-      {
-        HMODULE lib=NULL;
-        FARPROC pfunc=NULL;
-        const char *libs[]={"ws2_32","wship6",NULL};
-
-        for(const char **p=libs;*p!=NULL;++p)
-        {
-          g_snprintf(path,MAX_PATH+8,"%s\\%s",sysdir,*p);
-          lib=LoadLibrary(path);
-          if(!lib)
-            continue;
-          pfunc=GetProcAddress(lib,"getaddrinfo");
-          if(!pfunc)
-          {
-            FreeLibrary(lib);
-            lib=NULL;
-            continue;
-          }
-          p_getaddrinfo=reinterpret_cast<t_getaddrinfo>(pfunc);
-          pfunc=GetProcAddress(lib,"freeaddrinfo");
-          if(!pfunc)
-          {
-            FreeLibrary(lib);
-            lib=NULL;
-            p_getaddrinfo=NULL;
-            continue;
-          }
-          p_freeaddrinfo=reinterpret_cast<t_freeaddrinfo>(pfunc);
-          break;
-        }
-      }
-#else
-      p_freeaddrinfo=::freeaddrinfo;
-      p_getaddrinfo=::getaddrinfo;
-#endif
-      inited = true;
-    }
-  }
+namespace
+{
 
   GIOChannel *
   create_channel (const StringView& host_in, int port, std::string& setme_err)
   {
-    int err;
-    int sockfd;
+
+    GIOChannel * channel (0);
 
 #ifndef G_OS_WIN32
     signal (SIGPIPE, SIG_IGN);
 #endif
 
-    // get an addrinfo for the host
     const std::string host (host_in.str, host_in.len);
     char portbuf[32], hpbuf[255];
     g_snprintf (portbuf, sizeof(portbuf), "%d", port);
-    g_snprintf (hpbuf,sizeof(hpbuf),"%s:%s",host_in.str,portbuf);
-    
-#ifdef G_OS_WIN32 // windows might not have getaddrinfo...
-    if (!p_getaddrinfo)
-    {
-      struct hostent * ans = isalpha (host[0])
-        ? gethostbyname (host.c_str())
-        : gethostbyaddr (host.c_str(), host.size(), AF_INET);
-
-      err = WSAGetLastError();
-      if (err || !ans) {
-        setme_err = get_last_error (err);
-        return 0;
-      }
-
-      // try opening the socket
-      sockfd = socket (AF_INET, SOCK_STREAM, 0 /*IPPROTO_TCP*/);
-      if (sockfd < 0)
-        return 0;
-
-      // Try connecting
-      int i = 0;
-      err = -1;
-      struct sockaddr_in server;
-      memset (&server, 0, sizeof(struct sockaddr_in));
-      while (err && ans->h_addr_list[i])
-      {
-        char *addr = ans->h_addr_list[i];
-        memcpy (&server.sin_addr, addr, ans->h_length);
-        server.sin_family = AF_INET;
-        server.sin_port = htons(port);
-        ++i;
-        err = connect (sockfd,(struct sockaddr*)&server, sizeof(server));
-      }
+    g_snprintf (hpbuf, sizeof(hpbuf), "%s:%s", host_in.str, portbuf);
 
-      if (err) {
-        closesocket (sockfd);
-        setme_err = get_last_error (err);
-        return 0;
-      }
-    }
-    else
-#endif // #ifdef G_OS_WIN32 ...
-    {
-      errno = 0;
-      struct addrinfo hints;
-      memset (&hints, 0, sizeof(struct addrinfo));
-      hints.ai_flags = 0;
-      hints.ai_family = 0;
-      hints.ai_socktype = SOCK_STREAM;
-      struct addrinfo * ans;
-      err = p_getaddrinfo (host.c_str(), portbuf, &hints, &ans);
-      if (err != 0) {
-        char buf[512];
-        snprintf (buf, sizeof(buf), _("Error connecting to \"%s\""), hpbuf);
-        setme_err = buf;
-        if (errno) {
-          setme_err += " (";
-          setme_err += file :: pan_strerror (errno);
-          setme_err += ")";
-        }
-        return 0;
-      }
+    GSocketClient * client = g_socket_client_new ();
+    g_return_val_if_fail(client, 0);
 
-      // try to open a socket on any ipv4 or ipv6 addresses we found
-      errno = 0;
-      sockfd = -1;
-      for (struct addrinfo * walk(ans); walk && sockfd<0; walk=walk->ai_next)
-      {
-        // only use ipv4 or ipv6 addresses
-        if ((walk->ai_family!=PF_INET) && (walk->ai_family!=PF_INET6))
-          continue;
-
-        // try to create a socket...
-        sockfd = ::socket (walk->ai_family, walk->ai_socktype, walk->ai_protocol);
-        if (sockfd < 0)
-          continue;
-
-        // and make a connection
-        if (::connect (sockfd, walk->ai_addr, walk->ai_addrlen) < 0) {
-          closesocket (sockfd);
-          sockfd = -1;
-        }
-      }
+    GSocketConnection * conn = g_socket_client_connect_to_host
+      (client, hpbuf, 119, 0, NULL);
+    g_return_val_if_fail(conn, 0);
 
-      // cleanup
-      p_freeaddrinfo (ans);
-    }
+    GSocket* g(g_socket_connection_get_socket(conn));
+    g_return_val_if_fail(g, 0);
 
-    // create the giochannel...
-    if (sockfd < 0) {
-      char buf[512];
-      snprintf (buf, sizeof(buf), _("Error connecting to \"%s\""), hpbuf);
-      setme_err = buf;
-      if (errno) {
-        setme_err += " (";
-        setme_err += file :: pan_strerror (errno);
-        setme_err += ")";
-      }
-      return 0;
-    }
+    int sockfd = g_socket_get_fd(g);
 
-    GIOChannel * channel (0);
 #ifndef G_OS_WIN32
     channel = g_io_channel_unix_new (sockfd);
     g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
@@ -282,6 +93,7 @@ namespace
       g_io_channel_set_encoding (channel, NULL, NULL);
     g_io_channel_set_buffered (channel, true);
     g_io_channel_set_line_term (channel, "\n", 1);
+
     return channel;
   }
 }
@@ -506,7 +318,7 @@ GIOChannelSocket :: gio_func (GIOChannel   * channel,
      * could be a bug in gcc 4.2.1.
      */
     /*if (_abort_flag)        _listener->on_socket_abort (this);
-    else*/ if (result == IO_ERR)   _listener->on_socket_error (this);
+    else*/ if (result == IO_ERR) _listener->on_socket_error (this);
     else if (result == IO_READ)  set_watch_mode (READ_NOW);
     else if (result == IO_WRITE) set_watch_mode (WRITE_NOW);
   }
@@ -514,10 +326,6 @@ GIOChannelSocket :: gio_func (GIOChannel   * channel,
   return false; // set_watch_now(IGNORE) cleared the tag that called this func
 }
 
-namespace
-{
-  const unsigned int TIMEOUT_SECS (30);
-}
 
 void
 GIOChannelSocket :: set_watch_mode (WatchMode mode)
@@ -596,8 +404,6 @@ GIOChannelSocket :: Creator :: create_socket (const StringView & host,
                                               WorkerPool       & threadpool,
                                               Listener         * listener)
 {
-  ensure_module_inited ();
-
   ThreadWorker * w = new ThreadWorker (host, port, listener);
   threadpool.push_work (w, w, true);
 }
diff --git a/pan/tasks/socket-impl-gio.h b/pan/tasks/socket-impl-gio.h
index da74acc..165ff53 100644
--- a/pan/tasks/socket-impl-gio.h
+++ b/pan/tasks/socket-impl-gio.h
@@ -38,7 +38,6 @@ namespace pan
       GIOChannelSocket ();
       virtual ~GIOChannelSocket ();
       virtual bool open (const StringView& address, int port, std::string& setme_err);
-      virtual void write_command (const StringView& chars, Listener *);
       virtual void get_host (std::string& setme) const;
 
     private:
@@ -55,6 +54,7 @@ namespace pan
     private:
       enum WatchMode { READ_NOW, WRITE_NOW, IGNORE_NOW };
       void set_watch_mode (WatchMode mode);
+      virtual void write_command (const StringView& chars, Listener *);
       static gboolean gio_func (GIOChannel*, GIOCondition, gpointer);
       gboolean gio_func (GIOChannel*, GIOCondition);
       static gboolean timeout_func (gpointer);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]