mturk       2002/06/25 00:08:03

  Modified:    jk/native/common jk_ajp_common.c
  Log:
  Introduced socket and cache timeout.
  By Jan Singer, Henri Gomez and Mladen Turk.
  
  Revision  Changes    Path
  1.26      +376 -334  jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.c
  
  Index: jk_ajp_common.c
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_ajp_common.c,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- jk_ajp_common.c   10 May 2002 23:58:40 -0000      1.25
  +++ jk_ajp_common.c   25 Jun 2002 07:08:03 -0000      1.26
  @@ -115,23 +115,23 @@
       } else if(0 == strcmp(method, "TRACE")) {
           *sc = SC_M_TRACE;
       } else if(0 == strcmp(method, "PROPFIND")) {
  -     *sc = SC_M_PROPFIND;
  +    *sc = SC_M_PROPFIND;
       } else if(0 == strcmp(method, "PROPPATCH")) {
  -     *sc = SC_M_PROPPATCH;
  +    *sc = SC_M_PROPPATCH;
       } else if(0 == strcmp(method, "MKCOL")) {
  -     *sc = SC_M_MKCOL;
  +    *sc = SC_M_MKCOL;
       } else if(0 == strcmp(method, "COPY")) {
  -     *sc = SC_M_COPY;
  +    *sc = SC_M_COPY;
       } else if(0 == strcmp(method, "MOVE")) {
  -     *sc = SC_M_MOVE;
  +    *sc = SC_M_MOVE;
       } else if(0 == strcmp(method, "LOCK")) {
  -     *sc = SC_M_LOCK;
  +    *sc = SC_M_LOCK;
       } else if(0 == strcmp(method, "UNLOCK")) {
  -     *sc = SC_M_UNLOCK;
  +    *sc = SC_M_UNLOCK;
       } else if(0 == strcmp(method, "ACL")) {
  -     *sc = SC_M_ACL;
  +    *sc = SC_M_ACL;
       } else if(0 == strcmp(method, "REPORT")) {
  -     *sc = SC_M_REPORT;
  +    *sc = SC_M_REPORT;
       } else if(0 == strcmp(method, "VERSION-CONTROL")) {
           *sc = SC_M_VERSION_CONTROL;
       } else if(0 == strcmp(method, "CHECKIN")) {
  @@ -263,7 +263,7 @@
       ?ssl_cert      (byte)(string)
       ?ssl_cipher    (byte)(string)
       ?ssl_session   (byte)(string)
  -    ?ssl_key_size  (byte)(int)               via JkOptions +ForwardKeySize
  +    ?ssl_key_size  (byte)(int)      via JkOptions +ForwardKeySize
       request_terminator (byte)
       ?body          content_length*(var binary)
   
  @@ -442,10 +442,10 @@
   
   static int ajp_unmarshal_response(jk_msg_buf_t   *msg,
                                     jk_res_data_t  *d,
  -                                                       ajp_endpoint_t *ae,
  +                                  ajp_endpoint_t *ae,
                                     jk_logger_t    *l)
   {
  -     jk_pool_t * p = &ae->pool;
  +    jk_pool_t * p = &ae->pool;
   
       d->status = jk_b_get_int(msg);
   
  @@ -533,16 +533,16 @@
   void ajp_close_endpoint(ajp_endpoint_t *ae,
                           jk_logger_t    *l)
   {
  -     jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_close_endpoint\n");
  +    jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_close_endpoint\n");
   
       ajp_reset_endpoint(ae);
       jk_close_pool(&(ae->pool));
   
       if (ae->sd > 0) { 
           jk_close_socket(ae->sd);
  -             jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_close_endpoint, closed 
sd = %d\n", ae->sd);
  -             ae->sd = -1; /* just to avoid twice close */
  -     }
  +        jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_close_endpoint, closed sd = 
%d\n", ae->sd);
  +        ae->sd = -1; /* just to avoid twice close */
  +    }
   
       free(ae);
   }
  @@ -584,20 +584,22 @@
       unsigned attempt;
   
       for(attempt = 0 ; attempt < ae->worker->connect_retry_attempts ; attempt++) {
  -        ae->sd = jk_open_socket(&ae->worker->worker_inet_addr, JK_TRUE, l);
  +        ae->sd = jk_open_socket(&ae->worker->worker_inet_addr, JK_TRUE, 
ae->worker->keepalive, l);
           if(ae->sd >= 0) {
               jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::ajp_connect_to_endpoint, 
connected sd = %d\n", ae->sd);
   
  -                     /* Check if we must execute a logon after the physical connect 
*/
  -                     if (ae->worker->logon != NULL)
  -                             return (ae->worker->logon(ae, l));
  +             /* set last_access */
  +             ae->last_access = time(NULL);
  +            /* Check if we must execute a logon after the physical connect */
  +            if (ae->worker->logon != NULL)
  +                return (ae->worker->logon(ae, l));
   
  -                     return JK_TRUE;
  +            return JK_TRUE;
           }
       }
   
       jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::ajp_connect_to_endpoint, failed 
errno = %d\n", errno);
  -     return JK_FALSE;
  +    return JK_FALSE;
   }
   
   /*
  @@ -608,18 +610,18 @@
                                       jk_msg_buf_t   *msg,
                                       jk_logger_t    *l)
   {
  -     if (ae->proto == AJP13_PROTO) {
  -     jk_b_end(msg, AJP13_WS_HEADER);
  -             jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp13", msg);
  -     }
  -     else if (ae->proto == AJP14_PROTO) {
  -             jk_b_end(msg, AJP14_WS_HEADER);
  -             jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp14", msg);
  -     }
  -     else {
  -             jk_log(l, JK_LOG_ERROR, "In 
jk_endpoint_t::ajp_connection_tcp_send_message, unknown protocol %d, supported are 
AJP13/AJP14\n", ae->proto);
  -             return JK_FALSE;
  -     }
  +    if (ae->proto == AJP13_PROTO) {
  +        jk_b_end(msg, AJP13_WS_HEADER);
  +        jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp13", msg);
  +    }
  +    else if (ae->proto == AJP14_PROTO) {
  +        jk_b_end(msg, AJP14_WS_HEADER);
  +        jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp14", msg);
  +    }
  +    else {
  +        jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::ajp_connection_tcp_send_message, 
unknown protocol %d, supported are AJP13/AJP14\n", ae->proto);
  +        return JK_FALSE;
  +    }
   
       if(0 > jk_tcp_socket_sendfull(ae->sd, jk_b_get_buff(msg), jk_b_get_len(msg))) {
           return JK_FALSE;
  @@ -639,12 +641,12 @@
       unsigned char head[AJP_HEADER_LEN];
       int           rc;
       int           msglen;
  -     unsigned int  header;
  +    unsigned int  header;
   
  -     if ((ae->proto != AJP13_PROTO) && (ae->proto != AJP14_PROTO)) {
  -             jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Can't handle 
unknown protocol %d\n", ae->proto);
  -             return JK_FALSE;
  -     }
  +    if ((ae->proto != AJP13_PROTO) && (ae->proto != AJP14_PROTO)) {
  +        jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Can't handle 
unknown protocol %d\n", ae->proto);
  +        return JK_FALSE;
  +    }
   
       rc = jk_tcp_socket_recvfull(ae->sd, head, AJP_HEADER_LEN);
   
  @@ -653,30 +655,30 @@
           return JK_FALSE;
       }
   
  -     header = ((unsigned int)head[0] << 8) | head[1];
  +    header = ((unsigned int)head[0] << 8) | head[1];
     
  -     if (ae->proto == AJP13_PROTO) {
  -     if (header != AJP13_SW_HEADER) {
  +    if (ae->proto == AJP13_PROTO) {
  +        if (header != AJP13_SW_HEADER) {
  +
  +            if (header == AJP14_SW_HEADER)
  +                jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error - 
received AJP14 reply on an AJP13 connection\n");
  +            else
  +                jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error - 
Wrong message format 0x%04x\n", header);
  +
  +            return JK_FALSE;
  +        }
  +    }
  +    else if (ae->proto == AJP14_PROTO) {
  +        if (header != AJP14_SW_HEADER) {
   
  -                     if (header == AJP14_SW_HEADER)
  -                             jk_log(l, JK_LOG_ERROR, 
"ajp_connection_tcp_get_message: Error - received AJP14 reply on an AJP13 
connection\n");
  -                     else
  -                     jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error 
- Wrong message format 0x%04x\n", header);
  -
  -             return JK_FALSE;
  -     }
  -     }
  -     else if (ae->proto == AJP14_PROTO) {
  -             if (header != AJP14_SW_HEADER) {
  -
  -                     if (header == AJP13_SW_HEADER)
  -                             jk_log(l, JK_LOG_ERROR, 
"ajp_connection_tcp_get_message: Error - received AJP13 reply on an AJP14 
connection\n");
  -                     else
  -                             jk_log(l, JK_LOG_ERROR, 
"ajp_connection_tcp_get_message: Error - Wrong message format 0x%04x\n", header);
  -
  -                     return JK_FALSE;
  -             }
  -     }       
  +            if (header == AJP13_SW_HEADER)
  +                jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error - 
received AJP13 reply on an AJP14 connection\n");
  +            else
  +                jk_log(l, JK_LOG_ERROR, "ajp_connection_tcp_get_message: Error - 
Wrong message format 0x%04x\n", header);
  +
  +            return JK_FALSE;
  +        }
  +    }   
   
       msglen  = ((head[2]&0xff)<<8);
       msglen += (head[3] & 0xFF);
  @@ -695,11 +697,11 @@
           return JK_FALSE;
       }
   
  -     if (ae->proto == AJP13_PROTO) 
  -     jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp13", msg);
  -     else if (ae->proto == AJP14_PROTO)
  -             jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp14", msg);
  -     
  +    if (ae->proto == AJP13_PROTO) 
  +        jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp13", msg);
  +    else if (ae->proto == AJP14_PROTO)
  +        jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp14", msg);
  +    
       return JK_TRUE;
   }
   
  @@ -718,7 +720,7 @@
       unsigned padded_len = len;
   
       if (s->is_chunked && s->no_more_chunks) {
  -     return 0;
  +    return 0;
       }
       if (s->is_chunked) {
           /* Corner case: buf must be large enough to hold next
  @@ -737,9 +739,9 @@
           }
   
           if(0 == this_time) {
  -         if (s->is_chunked) {
  -             s->no_more_chunks = 1; /* read no more */
  -         }
  +        if (s->is_chunked) {
  +        s->no_more_chunks = 1; /* read no more */
  +        }
               break;
           }
           rdlen += this_time;
  @@ -769,7 +771,7 @@
   
       /* Pick the max size since we don't know the content_length */
       if (r->is_chunked && len == 0) {
  -     len = AJP13_MAX_SEND_BODY_SZ;
  +    len = AJP13_MAX_SEND_BODY_SZ;
       }
   
       if ((len = ajp_read_fully_from_server(r, read_buf, len)) < 0) {
  @@ -778,17 +780,17 @@
       }
   
       if (!r->is_chunked) {
  -     ae->left_bytes_to_send -= len;
  +    ae->left_bytes_to_send -= len;
       }
   
       if (len > 0) {
  -     /* Recipient recognizes empty packet as end of stream, not
  -        an empty body packet */
  +    /* Recipient recognizes empty packet as end of stream, not
  +       an empty body packet */
           if(0 != jk_b_append_int(msg, (unsigned short)len)) {
               jk_log(l, JK_LOG_ERROR, 
                      "read_into_msg_buff: Error - jk_b_append_int failed\n");
               return -1;
  -     }
  +    }
       }
   
       jk_b_set_len(msg, jk_b_get_len(msg) + len);
  @@ -809,89 +811,89 @@
    *     repmsg is the reply msg buffer which could be scratched
    */
   static int ajp_send_request(jk_endpoint_t *e,
  -                                             jk_ws_service_t *s,
  -                                                 jk_logger_t *l,
  -                                                 ajp_endpoint_t *ae,
  -                                                 ajp_operation_t *op)
  +                            jk_ws_service_t *s,
  +                            jk_logger_t *l,
  +                            ajp_endpoint_t *ae,
  +                            ajp_operation_t *op)
   {
  -     /* Up to now, we can recover */
  -     op->recoverable = JK_TRUE;
  +    /* Up to now, we can recover */
  +    op->recoverable = JK_TRUE;
  +
  +    /*
  +     * First try to reuse open connections...
  +    */
  +    while ((ae->sd > 0) && ! ajp_connection_tcp_send_message(ae, op->request, l)) {
  +        jk_log(l, JK_LOG_ERROR, "Error sending request try another pooled 
connection\n");
  +        jk_close_socket(ae->sd);
  +        ae->sd = -1;
  +        ajp_reuse_connection(ae, l);
  +    }
  +
  +    /*
  +     * If we failed to reuse a connection, try to reconnect.
  +     */
  +    if (ae->sd < 0) {
  +        if (ajp_connect_to_endpoint(ae, l) == JK_TRUE) {
  +        /*
  +         * After we are connected, each error that we are going to
  +         * have is probably unrecoverable
  +         */
  +        if (!ajp_connection_tcp_send_message(ae, op->request, l)) {
  +            jk_log(l, JK_LOG_ERROR, "Error sending request on a fresh 
connection\n");
  +            return JK_FALSE;
  +        }
  +        } else {
  +            jk_log(l, JK_LOG_ERROR, "Error connecting to the Tomcat process.\n");
  +            return JK_FALSE;
  +        }
  +    }
   
  -     /*
  -      * First try to reuse open connections...
  -     */
  -     while ((ae->sd > 0) && ! ajp_connection_tcp_send_message(ae, op->request, l)) {
  -             jk_log(l, JK_LOG_ERROR, "Error sending request try another pooled 
connection\n");
  -             jk_close_socket(ae->sd);
  -             ae->sd = -1;
  -             ajp_reuse_connection(ae, l);
  -     }
  -
  -     /*
  -      * If we failed to reuse a connection, try to reconnect.
  -      */
  -     if (ae->sd < 0) {
  -             if (ajp_connect_to_endpoint(ae, l) == JK_TRUE) {
  -             /*
  -              * After we are connected, each error that we are going to
  -              * have is probably unrecoverable
  -              */
  -             if (!ajp_connection_tcp_send_message(ae, op->request, l)) {
  -                     jk_log(l, JK_LOG_ERROR, "Error sending request on a fresh 
connection\n");
  -                     return JK_FALSE;
  -             }
  -             } else {
  -                     jk_log(l, JK_LOG_ERROR, "Error connecting to the Tomcat 
process.\n");
  -                     return JK_FALSE;
  -             }
  -     }
  -
  -     /*
  -      * From now on an error means that we have an internal server error
  -      * or Tomcat crashed. In any case we cannot recover this.
  -      */
  -
  -     jk_log(l, JK_LOG_DEBUG, "ajp_send_request 2: request body to send %d - request 
body to resend %d\n", 
  -             ae->left_bytes_to_send, jk_b_get_len(op->reply) - AJP_HEADER_LEN);
  -
  -     /*
  -      * POST recovery job is done here.
  -      * It's not very fine to have posted data in reply but that's the only easy
  -      * way to do that for now. Sharing the reply is really a bad solution but
  -      * it will works for POST DATA less than 8k.
  -      * We send here the first part of data which was sent previously to the
  -      * remote Tomcat
  -      */
  -     if (jk_b_get_len(op->post) > AJP_HEADER_LEN) {
  -             if(!ajp_connection_tcp_send_message(ae, op->post, l)) {
  -                     jk_log(l, JK_LOG_ERROR, "Error resending request body\n");
  -                     return JK_FALSE;
  -             }
  -     }
  -     else
  -     {
  -             /* We never sent any POST data and we check it we have to send at
  -              * least of block of data (max 8k). These data will be kept in reply
  -              * for resend if the remote Tomcat is down, a fact we will learn only
  -              * doing a read (not yet) 
  -              */
  -             if (s->is_chunked || ae->left_bytes_to_send > 0) {
  -                     int len = ae->left_bytes_to_send;
  -                     if (len > AJP13_MAX_SEND_BODY_SZ) 
  -                             len = AJP13_MAX_SEND_BODY_SZ;
  -                     if ((len = ajp_read_into_msg_buff(ae, s, op->post, len, l)) < 
0) {
  -                             /* the browser stop sending data, no need to recover */
  -                             op->recoverable = JK_FALSE;
  -                             return JK_FALSE;
  -                     }
  -                     s->content_read = len;
  -                     if (!ajp_connection_tcp_send_message(ae, op->post, l)) {
  -                             jk_log(l, JK_LOG_ERROR, "Error sending request 
body\n");
  -                             return JK_FALSE;
  -                     }  
  -             }
  -     }
  -     return (JK_TRUE);
  +    /*
  +     * From now on an error means that we have an internal server error
  +     * or Tomcat crashed. In any case we cannot recover this.
  +     */
  +
  +    jk_log(l, JK_LOG_DEBUG, "ajp_send_request 2: request body to send %d - request 
body to resend %d\n", 
  +        ae->left_bytes_to_send, jk_b_get_len(op->reply) - AJP_HEADER_LEN);
  +
  +    /*
  +     * POST recovery job is done here.
  +     * It's not very fine to have posted data in reply but that's the only easy
  +     * way to do that for now. Sharing the reply is really a bad solution but
  +     * it will works for POST DATA less than 8k.
  +     * We send here the first part of data which was sent previously to the
  +     * remote Tomcat
  +     */
  +    if (jk_b_get_len(op->post) > AJP_HEADER_LEN) {
  +        if(!ajp_connection_tcp_send_message(ae, op->post, l)) {
  +            jk_log(l, JK_LOG_ERROR, "Error resending request body\n");
  +            return JK_FALSE;
  +        }
  +    }
  +    else
  +    {
  +        /* We never sent any POST data and we check it we have to send at
  +         * least of block of data (max 8k). These data will be kept in reply
  +         * for resend if the remote Tomcat is down, a fact we will learn only
  +         * doing a read (not yet) 
  +         */
  +        if (s->is_chunked || ae->left_bytes_to_send > 0) {
  +            int len = ae->left_bytes_to_send;
  +            if (len > AJP13_MAX_SEND_BODY_SZ) 
  +                len = AJP13_MAX_SEND_BODY_SZ;
  +                    if ((len = ajp_read_into_msg_buff(ae, s, op->post, len, l)) < 
0) {
  +                /* the browser stop sending data, no need to recover */
  +                op->recoverable = JK_FALSE;
  +                return JK_FALSE;
  +            }
  +            s->content_read = len;
  +            if (!ajp_connection_tcp_send_message(ae, op->post, l)) {
  +                jk_log(l, JK_LOG_ERROR, "Error sending request body\n");
  +                return JK_FALSE;
  +            }  
  +        }
  +    }
  +    return (JK_TRUE);
   }
   
   /*
  @@ -924,21 +926,21 @@
                       return JK_CLIENT_ERROR;
                   }
               }
  -         break;
  +        break;
   
           case JK_AJP13_SEND_BODY_CHUNK:
               {
  -                 unsigned len = (unsigned)jk_b_get_int(msg);
  +                unsigned len = (unsigned)jk_b_get_int(msg);
                   if(!r->write(r, jk_b_get_buff(msg) + jk_b_get_pos(msg), len)) {
                       jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - write 
failed\n");
                       return JK_CLIENT_ERROR;
                   }
               }
  -         break;
  +        break;
   
           case JK_AJP13_GET_BODY_CHUNK:
               {
  -             int len = (int)jk_b_get_int(msg);
  +        int len = (int)jk_b_get_int(msg);
   
                   if(len > AJP13_MAX_SEND_BODY_SZ) {
                       len = AJP13_MAX_SEND_BODY_SZ;
  @@ -946,20 +948,20 @@
                   if(len > ae->left_bytes_to_send) {
                       len = ae->left_bytes_to_send;
                   }
  -             if(len < 0) {
  -                 len = 0;
  -             }
  -
  -             /* the right place to add file storage for upload */
  -             if ((len = ajp_read_into_msg_buff(ae, r, pmsg, len, l)) >= 0) {
  -                 r->content_read += len;
  -                 return JK_AJP13_HAS_RESPONSE;
  -             }                  
  +        if(len < 0) {
  +            len = 0;
  +        }
  +
  +        /* the right place to add file storage for upload */
  +        if ((len = ajp_read_into_msg_buff(ae, r, pmsg, len, l)) >= 0) {
  +            r->content_read += len;
  +            return JK_AJP13_HAS_RESPONSE;
  +        }                  
   
  -             jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - 
ajp_read_into_msg_buff failed\n");
  -             return JK_INTERNAL_ERROR;           
  +        jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - 
ajp_read_into_msg_buff failed\n");
  +        return JK_INTERNAL_ERROR;       
               }
  -         break;
  +        break;
   
           case JK_AJP13_END_RESPONSE:
               {
  @@ -976,11 +978,11 @@
                   ae->reuse = JK_TRUE;
               }
               return JK_AJP13_END_RESPONSE;
  -         break;
  +        break;
   
           default:
  -             jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - Invalid code: 
%d\n", code);
  -             return JK_AJP13_ERROR;
  +            jk_log(l, JK_LOG_ERROR, "Error ajp_process_callback - Invalid code: 
%d\n", code);
  +            return JK_AJP13_ERROR;
       }
       
       return JK_AJP13_NO_RESPONSE;
  @@ -1002,40 +1004,40 @@
   static int ajp_get_reply(jk_endpoint_t *e,
                            jk_ws_service_t *s,
                            jk_logger_t *l,
  -                                  ajp_endpoint_t *p,
  -                                  ajp_operation_t *op)
  +                         ajp_endpoint_t *p,
  +                         ajp_operation_t *op)
   {
  -     /* Start read all reply message */
  -     while(1) {
  -             int rc = 0;
  -
  -             if(!ajp_connection_tcp_get_message(p, op->reply, l)) {
  -                     jk_log(l, JK_LOG_ERROR, "Error reading reply\n");
  -                     /* we just can't recover, unset recover flag */
  -                     return JK_FALSE;
  -             }
  -
  -             rc = ajp_process_callback(op->reply, op->post, p, s, l);
  -
  -             /* no more data to be sent, fine we have finish here */
  -                     if(JK_AJP13_END_RESPONSE == rc)
  -                     return JK_TRUE;
  -             else if(JK_AJP13_HAS_RESPONSE == rc) {
  -             /* 
  -              * in upload-mode there is no second chance since
  -              * we may have allready send part of uploaded data 
  -              * to Tomcat.
  -              * In this case if Tomcat connection is broken we must 
  -              * abort request and indicate error.
  -              * A possible work-around could be to store the uploaded
  -              * data to file and replay for it
  -              */
  -                     op->recoverable = JK_FALSE; 
  -                     rc = ajp_connection_tcp_send_message(p, op->post, l);
  -                     if (rc < 0) {
  -                             jk_log(l, JK_LOG_ERROR, "Error sending request data 
%d\n", rc);
  -                                     return JK_FALSE;
  -                     }
  +    /* Start read all reply message */
  +    while(1) {
  +        int rc = 0;
  +
  +        if(!ajp_connection_tcp_get_message(p, op->reply, l)) {
  +            jk_log(l, JK_LOG_ERROR, "Error reading reply\n");
  +            /* we just can't recover, unset recover flag */
  +            return JK_FALSE;
  +        }
  +
  +        rc = ajp_process_callback(op->reply, op->post, p, s, l);
  +
  +        /* no more data to be sent, fine we have finish here */
  +            if(JK_AJP13_END_RESPONSE == rc)
  +                return JK_TRUE;
  +            else if(JK_AJP13_HAS_RESPONSE == rc) {
  +            /* 
  +             * in upload-mode there is no second chance since
  +             * we may have allready send part of uploaded data 
  +             * to Tomcat.
  +             * In this case if Tomcat connection is broken we must 
  +             * abort request and indicate error.
  +             * A possible work-around could be to store the uploaded
  +             * data to file and replay for it
  +             */
  +            op->recoverable = JK_FALSE; 
  +            rc = ajp_connection_tcp_send_message(p, op->post, l);
  +                if (rc < 0) {
  +                jk_log(l, JK_LOG_ERROR, "Error sending request data %d\n", rc);
  +                        return JK_FALSE;
  +            }
           } else if(JK_FATAL_ERROR == rc) {
             /*
              * we won't be able to gracefully recover from this so
  @@ -1052,13 +1054,13 @@
                      * un-recoverable error.  We just won't log it as such.
                      */
                   return JK_TRUE;
  -             } else if(rc < 0) {
  -                     return (JK_FALSE); /* XXX error */
  -             }
  -     }
  +        } else if(rc < 0) {
  +            return (JK_FALSE); /* XXX error */
  +        }
  +    }
   }
   
  -#define      JK_RETRIES 3
  +#define JK_RETRIES 3
   
   /*
    * service is now splitted in ajp_send_request and ajp_get_reply
  @@ -1072,95 +1074,95 @@
                   jk_logger_t     *l,
                   int             *is_recoverable_error)
   {
  -     int i;
  -     ajp_operation_t oper;
  -     ajp_operation_t *op = &oper;
  -
  -     jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::service\n");
  -
  -     if(e && e->endpoint_private && s && is_recoverable_error) {
  -             ajp_endpoint_t *p = e->endpoint_private;
  -                     op->request = jk_b_new(&(p->pool));
  -             jk_b_set_buffer_size(op->request, DEF_BUFFER_SZ); 
  -             jk_b_reset(op->request);
  +    int i;
  +    ajp_operation_t oper;
  +    ajp_operation_t *op = &oper;
  +
  +    jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::service\n");
  +
  +    if(e && e->endpoint_private && s && is_recoverable_error) {
  +        ajp_endpoint_t *p = e->endpoint_private;
  +            op->request = jk_b_new(&(p->pool));
  +        jk_b_set_buffer_size(op->request, DEF_BUFFER_SZ); 
  +        jk_b_reset(op->request);
          
  -             op->reply = jk_b_new(&(p->pool));
  -             jk_b_set_buffer_size(op->reply, DEF_BUFFER_SZ);
  -             jk_b_reset(op->reply); 
  -             
  -             op->post = jk_b_new(&(p->pool));
  -             jk_b_set_buffer_size(op->post, DEF_BUFFER_SZ);
  -             jk_b_reset(op->post); 
  -             
  -             op->recoverable = JK_TRUE;
  -             op->uploadfd     = -1;          /* not yet used, later ;) */
  -
  -             p->left_bytes_to_send = s->content_length;
  -             p->reuse = JK_FALSE;
  -             *is_recoverable_error = JK_TRUE;
  +        op->reply = jk_b_new(&(p->pool));
  +        jk_b_set_buffer_size(op->reply, DEF_BUFFER_SZ);
  +        jk_b_reset(op->reply); 
  +        
  +        op->post = jk_b_new(&(p->pool));
  +        jk_b_set_buffer_size(op->post, DEF_BUFFER_SZ);
  +        jk_b_reset(op->post); 
  +        
  +        op->recoverable = JK_TRUE;
  +        op->uploadfd     = -1;      /* not yet used, later ;) */
  +
  +        p->left_bytes_to_send = s->content_length;
  +        p->reuse = JK_FALSE;
  +        *is_recoverable_error = JK_TRUE;
   
                   s->secret = p->worker->secret;
  -             /* 
  -              * We get here initial request (in reqmsg)
  -              */
  -             if (!ajp_marshal_into_msgb(op->request, s, l, p)) {
  -                     *is_recoverable_error = JK_FALSE;                
  -                     return JK_FALSE;
  -             }
  -
  -             /* 
  -              * JK_RETRIES could be replaced by the number of workers in
  -              * a load-balancing configuration 
  -              */
  -             for (i = 0; i < JK_RETRIES; i++)
  -             {
  -                     /*
  -                      * We're using reqmsg which hold initial request
  -                      * if Tomcat is stopped or restarted, we will pass reqmsg
  -                      * to next valid tomcat. 
  -                      */
  -                     if (ajp_send_request(e, s, l, p, op)) {
  -
  -                             /* If we have the no recoverable error, it's probably 
because the sender (browser)
  -                              * stop sending data before the end (certainly in a 
big post)
  -                              */
  -                             if (! op->recoverable) {
  -                                     *is_recoverable_error = JK_FALSE;
  -                                     jk_log(l, JK_LOG_ERROR, "In 
jk_endpoint_t::service, ajp_send_request failed without recovery in send loop %d\n", 
i);
  -                                     return JK_FALSE;
  -                             }
  -
  -                             /* Up to there we can recover */
  -                             *is_recoverable_error = JK_TRUE;
  -                             op->recoverable = JK_TRUE;
  -
  -                             if (ajp_get_reply(e, s, l, p, op))
  -                                     return (JK_TRUE);
  -
  -                             /* if we can't get reply, check if no recover flag was 
set 
  -                              * if is_recoverable_error is cleared, we have started 
received 
  -                              * upload data and we must consider that operation is 
no more recoverable
  -                              */
  -                             if (! op->recoverable) {
  -                                     *is_recoverable_error = JK_FALSE;
  -                                     jk_log(l, JK_LOG_ERROR, "In 
jk_endpoint_t::service, ajp_get_reply failed without recovery in send loop %d\n", i);
  -                                     return JK_FALSE;
  -                             }
  -                             
  -                             jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, 
ajp_get_reply failed in send loop %d\n", i);
  -                     }
  -                     else
  -                             jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, 
ajp_send_request failed in send loop %d\n", i);
  -             
  -                     jk_close_socket(p->sd);
  -                     p->sd = -1;
  -                     ajp_reuse_connection(p, l);
  -             }
  -     } else {
  -             jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, NULL 
parameters\n");
  -     }
  +        /* 
  +         * We get here initial request (in reqmsg)
  +         */
  +        if (!ajp_marshal_into_msgb(op->request, s, l, p)) {
  +            *is_recoverable_error = JK_FALSE;                
  +            return JK_FALSE;
  +        }
  +
  +        /* 
  +         * JK_RETRIES could be replaced by the number of workers in
  +         * a load-balancing configuration 
  +         */
  +        for (i = 0; i < JK_RETRIES; i++)
  +        {
  +            /*
  +             * We're using reqmsg which hold initial request
  +             * if Tomcat is stopped or restarted, we will pass reqmsg
  +             * to next valid tomcat. 
  +             */
  +            if (ajp_send_request(e, s, l, p, op)) {
  +
  +                /* If we have the no recoverable error, it's probably because the 
sender (browser)
  +                 * stop sending data before the end (certainly in a big post)
  +                 */
  +                if (! op->recoverable) {
  +                    *is_recoverable_error = JK_FALSE;
  +                    jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, 
ajp_send_request failed without recovery in send loop %d\n", i);
  +                    return JK_FALSE;
  +                }
  +
  +                /* Up to there we can recover */
  +                *is_recoverable_error = JK_TRUE;
  +                op->recoverable = JK_TRUE;
  +
  +                if (ajp_get_reply(e, s, l, p, op))
  +                    return (JK_TRUE);
  +
  +                /* if we can't get reply, check if no recover flag was set 
  +                 * if is_recoverable_error is cleared, we have started received 
  +                 * upload data and we must consider that operation is no more 
recoverable
  +                 */
  +                if (! op->recoverable) {
  +                    *is_recoverable_error = JK_FALSE;
  +                    jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, 
ajp_get_reply failed without recovery in send loop %d\n", i);
  +                    return JK_FALSE;
  +                }
  +                
  +                jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, ajp_get_reply 
failed in send loop %d\n", i);
  +            }
  +            else
  +                jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, 
ajp_send_request failed in send loop %d\n", i);
  +        
  +            jk_close_socket(p->sd);
  +            p->sd = -1;
  +            ajp_reuse_connection(p, l);
  +        }
  +    } else {
  +            jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, NULL parameters\n");
  +    }
   
  -     return JK_FALSE;
  +    return JK_FALSE;
   }
   /*
    * Validate the worker (ajp13/ajp14)
  @@ -1170,25 +1172,25 @@
                    jk_map_t    *props,
                    jk_worker_env_t *we,
                    jk_logger_t *l,
  -                              int          proto)
  +                 int          proto)
   {
  -     int    port;
  -     char * host;
  +    int    port;
  +    char * host;
   
       jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::validate\n");
   
  -     if (proto == AJP13_PROTO) {
  -             port = AJP13_DEF_PORT;
  -             host = AJP13_DEF_HOST;
  -     }
  -     else if (proto == AJP14_PROTO) {
  -             port = AJP14_DEF_PORT;
  -             host = AJP14_DEF_HOST;
  -     }
  -     else {
  -             jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::validate unknown protocol 
%d\n", proto);
  -             return JK_FALSE;
  -     } 
  +    if (proto == AJP13_PROTO) {
  +        port = AJP13_DEF_PORT;
  +        host = AJP13_DEF_HOST;
  +    }
  +    else if (proto == AJP14_PROTO) {
  +        port = AJP14_DEF_PORT;
  +        host = AJP14_DEF_HOST;
  +    }
  +    else {
  +        jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::validate unknown protocol %d\n", 
proto);
  +        return JK_FALSE;
  +    } 
   
       if (pThis && pThis->worker_private) {
           ajp_worker_t *p = pThis->worker_private;
  @@ -1216,10 +1218,10 @@
                jk_map_t    *props,
                jk_worker_env_t *we,
                jk_logger_t *l,
  -                      int          proto)
  +             int          proto)
   {
  -     int cache;
  -     
  +    int cache;
  +    
       /*
        * start the connection cache
        */
  @@ -1232,21 +1234,29 @@
           cache = AJP13_DEF_CACHE_SZ;
       }
       else {
  -        jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::validate unknown protocol %d\n", 
proto);
  +        jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::init, unknown protocol %d\n", 
proto);
           return JK_FALSE;
       }
   
       if (pThis && pThis->worker_private) {
           ajp_worker_t *p = pThis->worker_private;
           int cache_sz = jk_get_worker_cache_size(props, p->name, cache);
  -        
  +        int socket_timeout = jk_get_worker_socket_timeout(props, p->name, 
AJP13_DEF_TIMEOUT);
  +        int socket_keepalive = jk_get_worker_socket_keepalive(props, p->name, 
JK_FALSE);
  +        int cache_timeout = jk_get_worker_cache_timeout(props, p->name, 
AJP_DEF_CACHE_TIMEOUT);
  +
  +        jk_log(l, JK_LOG_DEBUG, "In jk_worker_t::init, setting socket timeout to 
%d\n", socket_timeout);
  +        p->socket_timeout = socket_timeout;
  +        p->keepalive = socket_keepalive;
  +        p->cache_timeout = cache_timeout;
           /* 
            *  Need to initialize secret here since we could return from inside
            *  of the following loop
            */
              
           p->secret = jk_get_worker_secret(props, p->name );
  -
  +        p->ep_cache_sz = 0;
  +        p->ep_mincache_sz = 0;
           if (cache_sz > 0) {
               p->ep_cache = (ajp_endpoint_t **)malloc(sizeof(ajp_endpoint_t *) * 
cache_sz);
               if(p->ep_cache) {
  @@ -1270,16 +1280,16 @@
   
   int ajp_destroy(jk_worker_t **pThis,
                   jk_logger_t *l,
  -                             int          proto)
  +                int          proto)
   {
       jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::destroy\n");
   
       if (pThis && *pThis && (*pThis)->worker_private) {
           ajp_worker_t *aw = (*pThis)->worker_private;
   
  -             free(aw->name);
  +        free(aw->name);
   
  -             jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::destroy up to %d endpoint 
to close\n", aw->ep_cache_sz);
  +        jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::destroy up to %d endpoint to 
close\n", aw->ep_cache_sz);
   
           if(aw->ep_cache_sz) {
               unsigned i;
  @@ -1292,10 +1302,10 @@
               JK_DELETE_CS(&(aw->cs), i);
           }
   
  -             if (aw->login) {
  -                     free(aw->login);
  -                     aw->login = NULL;
  -             }
  +        if (aw->login) {
  +            free(aw->login);
  +            aw->login = NULL;
  +        }
   
           free(aw);
           return JK_TRUE;
  @@ -1330,8 +1340,8 @@
                       }
                       JK_LEAVE_CS(&w->cs, rc);
                       if(i < w->ep_cache_sz) {
  -                            jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::done, 
recycling connection\n");
  -                            return JK_TRUE;
  +                        jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::done, 
recycling connection\n");
  +                        return JK_TRUE;
                       }
                   }
               }
  @@ -1350,7 +1360,7 @@
   int ajp_get_endpoint(jk_worker_t    *pThis,
                        jk_endpoint_t **je,
                        jk_logger_t    *l,
  -                                      int                     proto)
  +                     int             proto)
   {
       jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::get_endpoint\n");
   
  @@ -1363,7 +1373,10 @@
               JK_ENTER_CS(&aw->cs, rc);
               if (rc) {
                   unsigned i;
  -    
  +                time_t now;
  +                if (aw->socket_timeout > 0 || aw->cache_timeout) {
  +                    now = time(NULL);
  +                }
                   for (i = 0 ; i < aw->ep_cache_sz ; i++) {
                       if (aw->ep_cache[i]) {
                           ae = aw->ep_cache[i];
  @@ -1371,8 +1384,36 @@
                           break;
                       }
                   }
  +                /* Handle enpoint cache timeouts */
  +                if (aw->cache_timeout) {
  +                    for ( ; i < aw->ep_cache_sz ; i++) {
  +                        if (aw->ep_cache[i]) {
  +                            unsigned elapsed = (unsigned)(now - ae->last_access);
  +                            if (elapsed > aw->cache_timeout) {
  +                                jk_log(l, JK_LOG_DEBUG, 
  +                                    "In jk_endpoint_t::ajp_get_endpoint," \
  +                                    " cleaning cache slot = %d elapsed %d\n",
  +                                     i, elapsed);
  +                                ajp_close_endpoint(aw->ep_cache[i], l);
  +                                aw->ep_cache[i] = NULL;
  +                            }
  +                        }
  +                    }
  +                }
                   JK_LEAVE_CS(&aw->cs, rc);
                   if (ae) {
  +                    if (ae->sd > 0) {
  +                        /* Handle timeouts for open sockets */
  +                        unsigned elapsed = (unsigned)(now - ae->last_access);
  +                        ae->last_access = now;
  +                        jk_log(l, JK_LOG_DEBUG, "In 
jk_endpoint_t::ajp_get_endpoint, time elapsed since last request = %d seconds\n", 
elapsed);
  +                        if (aw->socket_timeout > 0 && elapsed > aw->socket_timeout) 
{
  +                            jk_close_socket(ae->sd);
  +                            jk_log(l, JK_LOG_DEBUG, 
  +                                   "In jk_endpoint_t::ajp_get_endpoint, reached 
socket timeout, closed sd = %d\n", ae->sd);
  +                            ae->sd = -1; /* just to avoid twice close */
  +                        }
  +                    }
                       *je = &ae->endpoint;
                       return JK_TRUE;
                   }
  @@ -1383,10 +1424,11 @@
           if (ae) {
               ae->sd = -1;
               ae->reuse = JK_FALSE;
  +            ae->last_access = time(NULL);
               jk_open_pool(&ae->pool, ae->buf, sizeof(ae->buf));
               ae->worker = pThis->worker_private;
               ae->endpoint.endpoint_private = ae;
  -                     ae->proto = proto;
  +            ae->proto = proto;
               ae->endpoint.service = ajp_service;
               ae->endpoint.done = ajp_done;
               *je = &ae->endpoint;
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to