Bug 424207 – printing hangs on unreachable cups server
svn path=/trunk/; revision=20923
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user