]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/client.c
Merge changes from CUPS 1.4svn-r7626.
[thirdparty/cups.git] / scheduler / client.c
index 94ddc900a9b5a22793f031f50d77ad24f3b52c0a..f56ed64a267339a8de31393cd3135958319b75e0 100644 (file)
@@ -28,6 +28,7 @@
  *   cupsdUpdateCGI()        - Read status messages from CGI scripts and programs.
  *   cupsdWriteClient()      - Write data to a client as needed.
  *   check_if_modified()     - Decode an "If-Modified-Since" line.
+ *   compare_clients()       - Compare two client connections.
  *   encrypt_client()        - Enable encryption for the client...
  *   get_cdsa_certificate()  - Convert a keychain name into the CFArrayRef
  *                            required by SSLSetCertificate.
@@ -82,6 +83,8 @@ extern const char *cssmErrorString(int error);
 
 static int             check_if_modified(cupsd_client_t *con,
                                          struct stat *filestats);
+static int             compare_clients(cupsd_client_t *a, cupsd_client_t *b,
+                                       void *data);
 #ifdef HAVE_SSL
 static int             encrypt_client(cupsd_client_t *con);
 #endif /* HAVE_SSL */
@@ -145,7 +148,18 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
   if (!Clients)
   {
     cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to allocate memory for client array!");
+                    "Unable to allocate memory for clients array!");
+    cupsdPauseListening();
+    return;
+  }
+
+  if (!ActiveClients)
+    ActiveClients = cupsArrayNew((cups_array_func_t)compare_clients, NULL);
+
+  if (!ActiveClients)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to allocate memory for active clients array!");
     cupsdPauseListening();
     return;
   }
@@ -522,15 +536,15 @@ cupsdCloseClient(cupsd_client_t *con)     /* I - Client to close */
     switch (SSL_shutdown(conn))
     {
       case 1 :
-          cupsdLogMessage(CUPSD_LOG_INFO,
-                         "cupsdCloseClient: SSL shutdown successful!");
+          cupsdLogMessage(CUPSD_LOG_DEBUG,
+                         "SSL shutdown successful!");
          break;
       case -1 :
           cupsdLogMessage(CUPSD_LOG_ERROR,
-                         "cupsdCloseClient: Fatal error during SSL shutdown!");
+                         "Fatal error during SSL shutdown!");
       default :
          while ((error = ERR_get_error()) != 0)
-           cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdCloseClient: %s",
+           cupsdLogMessage(CUPSD_LOG_ERROR, "SSL shutdown failed: %s",
                            ERR_error_string(error, NULL));
           break;
     }
@@ -546,12 +560,12 @@ cupsdCloseClient(cupsd_client_t *con)     /* I - Client to close */
     switch (error)
     {
       case GNUTLS_E_SUCCESS:
-       cupsdLogMessage(CUPSD_LOG_INFO,
-                       "cupsdCloseClient: SSL shutdown successful!");
+       cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "SSL shutdown successful!");
        break;
       default:
        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "cupsdCloseClient: %s", gnutls_strerror(error));
+                       "SSL shutdown failed: %s", gnutls_strerror(error));
        break;
     }
 
@@ -607,8 +621,11 @@ cupsdCloseClient(cupsd_client_t *con)      /* I - Client to close */
   * Close the socket and clear the file from the input set for select()...
   */
 
-  if (con->http.fd > 0)
+  if (con->http.fd >= 0)
   {
+    cupsArrayRemove(ActiveClients, con);
+    cupsdSetBusyState();
+
     if (partial)
     {
      /*
@@ -849,11 +866,14 @@ cupsdReadClient(cupsd_client_t *con)      /* I - Client to read from */
         switch (sscanf(line, "%63s%1023s%63s", operation, con->uri, version))
        {
          case 1 :
-             cupsdLogMessage(CUPSD_LOG_ERROR,
-                             "Bad request line \"%s\" from %s!", line,
-                             con->http.hostname);
-             cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE);
-             cupsdCloseClient(con);
+             if (line[0])
+             {
+               cupsdLogMessage(CUPSD_LOG_ERROR,
+                               "Bad request line \"%s\" from %s!", line,
+                               con->http.hostname);
+               cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE);
+               cupsdCloseClient(con);
+              }
              return;
          case 2 :
              con->http.version = HTTP_0_9;
@@ -973,6 +993,9 @@ cupsdReadClient(cupsd_client_t *con)        /* I - Client to read from */
 
        con->http.status = HTTP_OK;
 
+        cupsArrayAdd(ActiveClients, con);
+       cupsdSetBusyState();
+
     case HTTP_OPTIONS :
     case HTTP_DELETE :
     case HTTP_GET :
@@ -2144,8 +2167,16 @@ cupsdReadClient(cupsd_client_t *con)     /* I - Client to read from */
         break; /* Anti-compiler-warning-code */
   }
 
-  if (!con->http.keep_alive && con->http.state == HTTP_WAITING)
-    cupsdCloseClient(con);
+  if (con->http.state == HTTP_WAITING)
+  {
+    if (!con->http.keep_alive)
+      cupsdCloseClient(con);
+    else
+    {
+      cupsArrayRemove(ActiveClients, con);
+      cupsdSetBusyState();
+    }
+  }
 }
 
 
@@ -2606,7 +2637,8 @@ cupsdWriteClient(cupsd_client_t *con)     /* I - Client connection */
   cupsdLogMessage(CUPSD_LOG_DEBUG2,
                   "cupsdWriteClient(con=%p) %d response=%p(%d), file=%d "
                  "pipe_pid=%d state=%d",
-                  con, con->http.fd, con->response, con->response->state,
+                  con, con->http.fd, con->response,
+                 con->response ? con->response->state : -1,
                  con->file, con->pipe_pid, con->http.state);
 #endif /* DEBUG */
 
@@ -2753,7 +2785,10 @@ cupsdWriteClient(cupsd_client_t *con)    /* I - Client connection */
         return;
       }
       else if (bytes == 0)
+      {
         con->http.activity = time(NULL);
+        return;
+      }
     }
 
     if (bytes > 0)
@@ -2768,6 +2803,9 @@ cupsdWriteClient(cupsd_client_t *con)     /* I - Client connection */
        return;
       }
 
+      if (con->http.data_encoding == HTTP_ENCODE_CHUNKED)
+        httpFlushWrite(HTTP(con));
+
       con->bytes += bytes;
 
       if (con->http.state == HTTP_WAITING)
@@ -2910,6 +2948,26 @@ check_if_modified(
 }
 
 
+/*
+ * 'compare_clients()' - Compare two client connections.
+ */
+
+static int                             /* O - Result of comparison */
+compare_clients(cupsd_client_t *a,     /* I - First client */
+                cupsd_client_t *b,     /* I - Second client */
+                void           *data)  /* I - User data (not used) */
+{
+  (void)data;
+
+  if (a == b)
+    return (0);
+  else if (a < b)
+    return (-1);
+  else
+    return (1);
+}
+
+
 #ifdef HAVE_SSL
 /*
  * 'encrypt_client()' - Enable encryption for the client...
@@ -3648,9 +3706,7 @@ is_cgi(cupsd_client_t *con,               /* I - Client connection */
   if ((options = strchr(con->uri, '?')) != NULL)
   {
     options ++;
-
-    if (strchr(options, '='))
-      cupsdSetStringf(&(con->query_string), "QUERY_STRING=%s", options);
+    cupsdSetStringf(&(con->query_string), "QUERY_STRING=%s", options);
   }
 
  /*
@@ -3674,7 +3730,8 @@ is_cgi(cupsd_client_t *con,               /* I - Client connection */
 
     filename = strrchr(filename, '/') + 1; /* Filename always absolute */
 
-    cupsdSetString(&con->options, options);
+    if (options)
+      cupsdSetStringf(&con->options, " %s", options);
 
     cupsdLogMessage(CUPSD_LOG_DEBUG2,
                     "is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"",
@@ -4675,6 +4732,8 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */
 
       envp[envc ++] = con->query_string;
     }
+    else
+      envp[envc ++] = "QUERY_STRING=";
   }
   else
   {