summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorMatthias Clasen <matthiasc@src.gnome.org>2008-07-31 23:56:17 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2008-07-31 23:56:17 +0000
commite9d978dff9f9b18eaac6c4920fb5abf7245d839d (patch)
tree11e1d6864cfc988203ba48ffad98851b1820e011 /modules
parentc04c884f3516ca7408fd737536a2721554dc7f71 (diff)
downloadgdk-pixbuf-e9d978dff9f9b18eaac6c4920fb5abf7245d839d.tar.gz
Bug 424207 – printing hangs on unreachable cups server
svn path=/trunk/; revision=20923
Diffstat (limited to 'modules')
-rw-r--r--modules/printbackends/cups/gtkcupsutils.c119
-rw-r--r--modules/printbackends/cups/gtkcupsutils.h82
-rw-r--r--modules/printbackends/cups/gtkprintbackendcups.c57
3 files changed, 217 insertions, 41 deletions
diff --git a/modules/printbackends/cups/gtkcupsutils.c b/modules/printbackends/cups/gtkcupsutils.c
index 06e8ca866..09cd6906c 100644
--- a/modules/printbackends/cups/gtkcupsutils.c
+++ b/modules/printbackends/cups/gtkcupsutils.c
@@ -29,6 +29,8 @@
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
+#include <fcntl.h>
+#include <sys/socket.h>
typedef void (*GtkCupsRequestStateFunc) (GtkCupsRequest *request);
@@ -1195,3 +1197,120 @@ gtk_cups_result_get_error_string (GtkCupsResult *result)
return result->error_msg;
}
+/* This function allocates new instance of GtkCupsConnectionTest() and creates
+ * a socket for communication with a CUPS server 'server'.
+ */
+GtkCupsConnectionTest *
+gtk_cups_connection_test_new (const char *server)
+{
+ GtkCupsConnectionTest *result = NULL;
+ gchar *port_str = NULL;
+
+ result = g_new (GtkCupsConnectionTest, 1);
+
+ port_str = g_strdup_printf ("%d", ippPort ());
+
+ if (server != NULL)
+ result->addrlist = httpAddrGetList (server, AF_UNSPEC, port_str);
+ else
+ result->addrlist = httpAddrGetList (cupsServer (), AF_UNSPEC, port_str);
+
+ g_free (port_str);
+
+ result->socket = -1;
+ result->current_addr = NULL;
+ result->success_at_init = FALSE;
+
+ result->success_at_init = gtk_cups_connection_test_is_server_available (result);
+
+ return result;
+}
+
+
+/* A non-blocking test whether it is possible to connect to a CUPS server specified
+ * inside of GtkCupsConnectionTest structure.
+ * - you need to check it more then once.
+ * The connection is closed after a successful connection.
+ */
+gboolean
+gtk_cups_connection_test_is_server_available (GtkCupsConnectionTest *test)
+{
+ http_addrlist_t *iter;
+ gboolean result = FALSE;
+ gint flags;
+ gint code;
+
+ if (test == NULL)
+ return FALSE;
+
+ if (test->success_at_init)
+ {
+ test->success_at_init = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ if (test->socket == -1)
+ {
+ iter = test->addrlist;
+ while (iter)
+ {
+ test->socket = socket (iter->addr.addr.sa_family,
+ SOCK_STREAM,
+ 0);
+
+ if (test->socket >= 0)
+ {
+ flags = fcntl (test->socket, F_GETFL);
+
+ if (flags != -1)
+ flags |= O_NONBLOCK;
+
+ fcntl (test->socket, F_SETFL, flags);
+
+ test->current_addr = iter;
+
+ break;
+ }
+ iter = iter->next;
+ }
+ }
+
+ if (test->socket >= 0)
+ {
+ code = connect (test->socket,
+ &test->current_addr->addr.addr,
+ httpAddrLength (&test->current_addr->addr));
+
+ if (code == 0)
+ {
+ close (test->socket);
+ test->socket = -1;
+ test->current_addr = NULL;
+ result = TRUE;
+ }
+ else
+ result = FALSE;
+ }
+
+ return result;
+ }
+}
+
+/* This function frees memory used by the GtkCupsConnectionTest structure.
+ */
+void
+gtk_cups_connection_test_free (GtkCupsConnectionTest *test)
+{
+ if (test == NULL)
+ return FALSE;
+
+ test->current_addr = NULL;
+ httpAddrFreeList (test->addrlist);
+ if (test->socket != -1)
+ {
+ close (test->socket);
+ test->socket = -1;
+ }
+ g_free (test);
+}
diff --git a/modules/printbackends/cups/gtkcupsutils.h b/modules/printbackends/cups/gtkcupsutils.h
index 6ea80e78d..7dfe387f9 100644
--- a/modules/printbackends/cups/gtkcupsutils.h
+++ b/modules/printbackends/cups/gtkcupsutils.h
@@ -28,8 +28,9 @@
G_BEGIN_DECLS
-typedef struct _GtkCupsRequest GtkCupsRequest;
-typedef struct _GtkCupsResult GtkCupsResult;
+typedef struct _GtkCupsRequest GtkCupsRequest;
+typedef struct _GtkCupsResult GtkCupsResult;
+typedef struct _GtkCupsConnectionTest GtkCupsConnectionTest;
typedef enum
{
@@ -80,6 +81,14 @@ struct _GtkCupsRequest
gint own_http : 1;
};
+struct _GtkCupsConnectionTest
+{
+ http_addrlist_t *addrlist;
+ http_addrlist_t *current_addr;
+ gboolean success_at_init;
+ gint socket;
+};
+
#define GTK_CUPS_REQUEST_START 0
#define GTK_CUPS_REQUEST_DONE 500
@@ -105,39 +114,42 @@ enum
GTK_CUPS_GET_DONE = GTK_CUPS_REQUEST_DONE
};
-GtkCupsRequest * gtk_cups_request_new (http_t *connection,
- GtkCupsRequestType req_type,
- gint operation_id,
- GIOChannel *data_io,
- const char *server,
- const char *resource);
-void gtk_cups_request_ipp_add_string (GtkCupsRequest *request,
- ipp_tag_t group,
- ipp_tag_t tag,
- const char *name,
- const char *charset,
- const char *value);
-void gtk_cups_request_ipp_add_strings (GtkCupsRequest *request,
- ipp_tag_t group,
- ipp_tag_t tag,
- const char *name,
- int num_values,
- const char *charset,
- const char * const *values);
-gboolean gtk_cups_request_read_write (GtkCupsRequest *request);
-GtkCupsPollState gtk_cups_request_get_poll_state (GtkCupsRequest *request);
-void gtk_cups_request_free (GtkCupsRequest *request);
-GtkCupsResult * gtk_cups_request_get_result (GtkCupsRequest *request);
-gboolean gtk_cups_request_is_done (GtkCupsRequest *request);
-void gtk_cups_request_encode_option (GtkCupsRequest *request,
- const gchar *option,
- const gchar *value);
-gboolean gtk_cups_result_is_error (GtkCupsResult *result);
-ipp_t * gtk_cups_result_get_response (GtkCupsResult *result);
-GtkCupsErrorType gtk_cups_result_get_error_type (GtkCupsResult *result);
-int gtk_cups_result_get_error_status (GtkCupsResult *result);
-int gtk_cups_result_get_error_code (GtkCupsResult *result);
-const char * gtk_cups_result_get_error_string (GtkCupsResult *result);
+GtkCupsRequest * gtk_cups_request_new (http_t *connection,
+ GtkCupsRequestType req_type,
+ gint operation_id,
+ GIOChannel *data_io,
+ const char *server,
+ const char *resource);
+void gtk_cups_request_ipp_add_string (GtkCupsRequest *request,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ const char *charset,
+ const char *value);
+void gtk_cups_request_ipp_add_strings (GtkCupsRequest *request,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int num_values,
+ const char *charset,
+ const char * const *values);
+gboolean gtk_cups_request_read_write (GtkCupsRequest *request);
+GtkCupsPollState gtk_cups_request_get_poll_state (GtkCupsRequest *request);
+void gtk_cups_request_free (GtkCupsRequest *request);
+GtkCupsResult * gtk_cups_request_get_result (GtkCupsRequest *request);
+gboolean gtk_cups_request_is_done (GtkCupsRequest *request);
+void gtk_cups_request_encode_option (GtkCupsRequest *request,
+ const gchar *option,
+ const gchar *value);
+gboolean gtk_cups_result_is_error (GtkCupsResult *result);
+ipp_t * gtk_cups_result_get_response (GtkCupsResult *result);
+GtkCupsErrorType gtk_cups_result_get_error_type (GtkCupsResult *result);
+int gtk_cups_result_get_error_status (GtkCupsResult *result);
+int gtk_cups_result_get_error_code (GtkCupsResult *result);
+const char * gtk_cups_result_get_error_string (GtkCupsResult *result);
+GtkCupsConnectionTest * gtk_cups_connection_test_new (const char *server);
+gboolean gtk_cups_connection_test_is_server_available (GtkCupsConnectionTest *test);
+void gtk_cups_connection_test_free (GtkCupsConnectionTest *test);
G_END_DECLS
#endif
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c
index f493063b7..1a3ebae8a 100644
--- a/modules/printbackends/cups/gtkprintbackendcups.c
+++ b/modules/printbackends/cups/gtkprintbackendcups.c
@@ -106,6 +106,8 @@ struct _GtkPrintBackendCups
guint list_printers_poll;
guint list_printers_pending : 1;
guint got_default_printer : 1;
+ guint default_printer_poll;
+ GtkCupsConnectionTest *default_printer_connection_test;
char **covers;
char *default_cover_before;
@@ -120,6 +122,7 @@ static void gtk_print_backend_cups_init (GtkPrintBack
static void gtk_print_backend_cups_finalize (GObject *object);
static void gtk_print_backend_cups_dispose (GObject *object);
static void cups_get_printer_list (GtkPrintBackend *print_backend);
+static void cups_get_default_printer (GtkPrintBackendCups *print_backend);
static void cups_request_execute (GtkPrintBackendCups *print_backend,
GtkCupsRequest *request,
GtkPrintCupsResponseCallbackFunc callback,
@@ -141,7 +144,7 @@ static void cups_printer_prepare_for_print (GtkPrinter
static GList * cups_printer_list_papers (GtkPrinter *printer);
static GtkPageSetup * cups_printer_get_default_page_size (GtkPrinter *printer);
static void cups_printer_request_details (GtkPrinter *printer);
-static void cups_request_default_printer (GtkPrintBackendCups *print_backend);
+static gboolean cups_request_default_printer (GtkPrintBackendCups *print_backend);
static void cups_request_ppd (GtkPrinter *printer);
static void cups_printer_get_hard_margins (GtkPrinter *printer,
double *top,
@@ -509,7 +512,10 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
backend_cups->default_cover_after = NULL;
backend_cups->number_of_covers = 0;
- cups_request_default_printer (backend_cups);
+ backend_cups->default_printer_poll = 0;
+ backend_cups->default_printer_connection_test = NULL;
+
+ cups_get_default_printer (backend_cups);
}
static void
@@ -530,6 +536,8 @@ gtk_print_backend_cups_finalize (GObject *object)
g_free (backend_cups->default_cover_before);
g_free (backend_cups->default_cover_after);
+
+ gtk_cups_connection_test_free (backend_cups->default_printer_connection_test);
backend_parent_class->finalize (object);
}
@@ -548,6 +556,10 @@ gtk_print_backend_cups_dispose (GObject *object)
g_source_remove (backend_cups->list_printers_poll);
backend_cups->list_printers_poll = 0;
+ if (backend_cups->default_printer_poll > 0)
+ g_source_remove (backend_cups->default_printer_poll);
+ backend_cups->default_printer_poll = 0;
+
backend_parent_class->dispose (object);
}
@@ -1812,6 +1824,27 @@ cups_get_user_options (const char *printer_name,
return num_options;
}
+/* This function requests default printer from a CUPS server in regular intervals.
+ * In the case of unreachable CUPS server the request is repeated later.
+ * The default printer is not requested in the case of previous success.
+ */
+static void
+cups_get_default_printer (GtkPrintBackendCups *backend)
+{
+ GtkPrintBackendCups *cups_backend;
+
+ cups_backend = backend;
+
+ cups_backend->default_printer_connection_test = gtk_cups_connection_test_new (NULL);
+ if (cups_backend->default_printer_poll == 0)
+ {
+ if (cups_request_default_printer (cups_backend))
+ cups_backend->default_printer_poll = gdk_threads_add_timeout_seconds (1,
+ (GSourceFunc) cups_request_default_printer,
+ backend);
+ }
+}
+
static void
cups_request_default_printer_cb (GtkPrintBackendCups *print_backend,
GtkCupsResult *result,
@@ -1820,6 +1853,8 @@ cups_request_default_printer_cb (GtkPrintBackendCups *print_backend,
ipp_t *response;
ipp_attribute_t *attr;
+ GDK_THREADS_ENTER ();
+
response = gtk_cups_result_get_response (result);
if ((attr = ippFindAttribute (response, "printer-name", IPP_TAG_NAME)) != NULL)
@@ -1832,27 +1867,35 @@ cups_request_default_printer_cb (GtkPrintBackendCups *print_backend,
*/
if (print_backend->list_printers_poll != 0)
cups_request_printer_list (print_backend);
+
+ GDK_THREADS_LEAVE ();
}
-static void
+static gboolean
cups_request_default_printer (GtkPrintBackendCups *print_backend)
{
GtkCupsRequest *request;
const char *str;
char *name = NULL;
+ if (!gtk_cups_connection_test_is_server_available (print_backend->default_printer_connection_test))
+ return TRUE;
+
+ gtk_cups_connection_test_free (print_backend->default_printer_connection_test);
+ print_backend->default_printer_connection_test = NULL;
+
if ((str = g_getenv ("LPDEST")) != NULL)
{
print_backend->default_printer = g_strdup (str);
print_backend->got_default_printer = TRUE;
- return;
+ return FALSE;
}
else if ((str = g_getenv ("PRINTER")) != NULL &&
strcmp (str, "lp") != 0)
{
print_backend->default_printer = g_strdup (str);
print_backend->got_default_printer = TRUE;
- return;
+ return FALSE;
}
/* Figure out user setting for default printer */
@@ -1861,7 +1904,7 @@ cups_request_default_printer (GtkPrintBackendCups *print_backend)
{
print_backend->default_printer = name;
print_backend->got_default_printer = TRUE;
- return;
+ return FALSE;
}
request = gtk_cups_request_new (NULL,
@@ -1876,6 +1919,8 @@ cups_request_default_printer (GtkPrintBackendCups *print_backend)
(GtkPrintCupsResponseCallbackFunc) cups_request_default_printer_cb,
g_object_ref (print_backend),
g_object_unref);
+
+ return FALSE;
}
static void