[pan2] * memory leak at void GUI :: do_save_articles_to_nzb () fixed. * check for executable bit in folders
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2] * memory leak at void GUI :: do_save_articles_to_nzb () fixed. * check for executable bit in folders
- Date: Sat, 3 Dec 2011 21:02:37 +0000 (UTC)
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]