"Fossies" - the Fresh Open Source Software Archive

Member "mod_ftp-0.9.6/modules/ftp/ftp_data_filters.c" (28 May 2009, 10707 Bytes) of package /linux/www/apache_httpd_modules/old/mod_ftp-0.9.6-beta.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ftp_data_filters.c" see the Fossies "Dox" file reference documentation.

    1 /* Licensed to the Apache Software Foundation (ASF) under one or more
    2  * contributor license agreements.  See the NOTICE file distributed with
    3  * this work for additional information regarding copyright ownership.
    4  * The ASF licenses this file to You under the Apache License, Version 2.0
    5  * (the "License"); you may not use this file except in compliance with
    6  * the License.  You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 /*
   18  * Original Copyright (c) 2005 Covalent Technologies
   19  *
   20  * FTP Protocol module for Apache 2.0
   21  */
   22 
   23 #include "mod_ftp.h"
   24 #include "ftp_internal.h"
   25 
   26 /* Reimplement the core i/o filters to insert two-channel
   27  * data socket buckets for send or retrieve, monitoring
   28  * the control channel for sideband ABOR-like commands.
   29  *
   30  * These filters sit below
   31  */
   32 
   33 static apr_status_t datasock_bucket_read(apr_bucket * a, const char **str,
   34                                     apr_size_t * len, apr_read_type_e block)
   35 {
   36     ftp_connection *fc = a->data;
   37     apr_socket_t *sd = fc->datasock;
   38     char *buf;
   39     apr_status_t rv;
   40     apr_interval_time_t timeout;
   41     apr_interval_time_t polltimeout;
   42     apr_pollfd_t pollset[2];
   43     int n;
   44 
   45     /* command socket heard already?  (e.g. already polled) */
   46     rv = ftp_read_ahead_request(fc);
   47 
   48     if ((rv != APR_SUCCESS) &&
   49         !(APR_STATUS_IS_EINTR(rv) || (APR_STATUS_IS_EAGAIN(rv)) ||
   50           APR_STATUS_IS_EOF(rv))) {
   51         return rv;
   52     }
   53 
   54     apr_socket_timeout_get(sd, &timeout);
   55 
   56     if (block == APR_NONBLOCK_READ) {
   57         apr_socket_timeout_set(sd, 0);
   58         polltimeout = 0;
   59     }
   60     else {
   61         polltimeout = timeout;
   62     }
   63 
   64     *str = NULL;
   65     /* buf allocation must mirror *len initalization below */
   66     buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, a->list);
   67 
   68     pollset[0].desc_type = APR_POLL_SOCKET;
   69     pollset[0].desc.s = fc->datasock;
   70     pollset[0].reqevents = APR_POLLIN;  /* APR_POLLOUT for write */
   71     pollset[1].desc_type = APR_POLL_SOCKET;
   72     pollset[1].desc.s = fc->cntlsock;
   73     pollset[1].reqevents = (APR_POLLIN | APR_POLLPRI);
   74     pollset[1].rtnevents = 0;   /* For poll(1), pretend poll answered this */
   75 
   76     /* XXX: evil, no apr_socket_pool_get accessor available, though */
   77     pollset[1].p = pollset[0].p = *((apr_pool_t **) fc->datasock);
   78 
   79     do {
   80         /* Unset so we don't trip over the len when we don't call recv */
   81         *len = 0;
   82 
   83         /*
   84          * If we have already assembled our next_request, don't bother
   85          * polling the control connection - we won't read ahead two commands
   86          */
   87         rv = apr_poll(pollset, fc->next_request ? 1 : 2,
   88                       &n, polltimeout);
   89         /* pedantic sanity check, this should never happen */
   90         if ((rv == APR_SUCCESS) && (n < 0)) {
   91             rv = APR_EGENERAL;
   92         }
   93 
   94         if (rv != APR_SUCCESS) {
   95             /*
   96              * The loss of either socket here means the death of the data
   97              * connection. Unset the length to avoid looping
   98              */
   99             break;
  100         }
  101         if (pollset[1].rtnevents & (APR_POLLIN | APR_POLLPRI)) {
  102             /* command socket heard - but with a full line yet? */
  103             rv = ftp_read_ahead_request(fc);
  104 
  105             if ((rv != APR_SUCCESS) &&
  106                 !(APR_STATUS_IS_EINTR(rv) || (APR_STATUS_IS_EAGAIN(rv)) ||
  107                   APR_STATUS_IS_EOF(rv))) {
  108                 apr_bucket_free(buf);
  109                 return rv;
  110             }
  111         }
  112 
  113         if (pollset[0].rtnevents & APR_POLLIN) {
  114             /* *len must mirror the apr_bucket_alloc above. */
  115             *len = APR_BUCKET_BUFF_SIZE;
  116             rv = apr_socket_recv(sd, buf, len);
  117         }
  118     } while (APR_STATUS_IS_EINTR(rv)
  119              || (APR_STATUS_IS_EAGAIN(rv) && (block == APR_BLOCK_READ)));
  120     /*
  121      * EINTR, above, is obvious, EAGAIN is less so - win32 (perhaps others)
  122      * can trigger POLLIN a little too early, before the recieved packet has
  123      * actually been disassembled - so loop again.
  124      */
  125 
  126     if (block == APR_NONBLOCK_READ) {
  127         apr_socket_timeout_set(sd, timeout);
  128     }
  129 
  130     if (rv != APR_SUCCESS && !APR_STATUS_IS_EOF(rv)) {
  131         apr_bucket_free(buf);
  132         return rv;
  133     }
  134     /*
  135      * If there's more to read we have to keep the rest of the socket
  136      * for later. XXX: Note that more complicated bucket types that
  137      * refer to data not in memory and must therefore have a read()
  138      * function similar to this one should be wary of copying this
  139      * code because if they have a destroy function they probably
  140      * want to migrate the bucket's subordinate structure from the
  141      * old bucket to a raw new one and adjust it as appropriate,
  142      * rather than destroying the old one and creating a completely
  143      * new bucket.
  144      *
  145      * Even if there is nothing more to read, don't close the socket here
  146      * as we have to use it to send any response :)  We could shut it
  147      * down for reading, but there is no benefit to doing so.
  148      */
  149     if (*len > 0) {
  150         apr_bucket_heap *h;
  151         /* Change the current bucket to refer to what we read */
  152         a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
  153         h = a->data;
  154         h->alloc_len = APR_BUCKET_BUFF_SIZE;    /* note the real buffer size */
  155         *str = buf;
  156         APR_BUCKET_INSERT_AFTER(a, ftp_bucket_datasock_create(fc, a->list));
  157     }
  158     else {
  159         apr_bucket_free(buf);
  160         a = apr_bucket_immortal_make(a, "", 0);
  161         *str = a->data;
  162     }
  163     return APR_SUCCESS;
  164 }
  165 
  166 static apr_bucket *ftp_bucket_datasock_make(apr_bucket * b, ftp_connection *fc)
  167 {
  168     /*
  169      * Note that typically the socket is allocated from the connection pool
  170      * so it will disappear when the connection is finished.
  171      */
  172     b->type = &ftp_bucket_type_datasock;
  173     b->length = (apr_size_t) (-1);
  174     b->start = -1;
  175     b->data = fc;
  176 
  177     return b;
  178 }
  179 
  180 apr_bucket *ftp_bucket_datasock_create(ftp_connection *fc,
  181                                                   apr_bucket_alloc_t * list)
  182 {
  183     apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
  184 
  185     APR_BUCKET_INIT(b);
  186     b->free = apr_bucket_free;
  187     b->list = list;
  188     return ftp_bucket_datasock_make(b, fc);
  189 }
  190 
  191 const apr_bucket_type_t ftp_bucket_type_datasock = {
  192     "DATASOCK",
  193     5,
  194     APR_BUCKET_DATA,
  195     apr_bucket_destroy_noop,
  196     datasock_bucket_read,
  197     apr_bucket_setaside_notimpl,
  198     apr_bucket_split_notimpl,
  199     apr_bucket_copy_notimpl
  200 };
  201 
  202 
  203 apr_status_t ftp_data_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
  204 {
  205     ftp_connection *fc = f->ctx;
  206     ftp_server_config *fsc;
  207     conn_rec *c = fc->connection;
  208     apr_status_t rv;
  209     apr_interval_time_t polltimeout;
  210     apr_pollfd_t pollset[2];
  211     apr_bucket_brigade *next_bb;
  212     apr_bucket *e;
  213     int n;
  214 
  215     /* command socket heard already?  (e.g. already polled) */
  216     rv = ftp_read_ahead_request(fc);
  217 
  218     if ((rv != APR_SUCCESS) &&
  219         !(APR_STATUS_IS_EINTR(rv) || (APR_STATUS_IS_EAGAIN(rv)) ||
  220           APR_STATUS_IS_EOF(rv))) {
  221         f->c->aborted = 1;
  222         return rv;
  223     }
  224 
  225     fsc = ftp_get_module_config(fc->orig_server->module_config);
  226 
  227     while (!APR_BRIGADE_EMPTY(bb)) {
  228 
  229         /*
  230          * The brigade can be far to 'chunky' to respect the ABOR tests we
  231          * perform below.  Dice up the raw response stream into chuncks
  232          * (48000 bytes by default) and and check between each chunk for a
  233          * control channel command.  At 48000 this is at least 1/minute on a
  234          * very slow 9600 baud line.
  235          */
  236         rv = apr_brigade_partition(bb, fsc->data_block_size, &e);
  237         if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
  238             return rv;
  239         }
  240         next_bb = apr_brigade_split(bb, e);
  241 
  242         /*
  243          * Poll to see if we are are prepared to pass on the brigade and the
  244          * client hasn't ABORted us yet.
  245          */
  246         apr_socket_timeout_get(fc->datasock, &polltimeout);
  247 
  248         pollset[0].desc_type = APR_POLL_SOCKET;
  249         pollset[0].desc.s = fc->datasock;
  250         pollset[0].reqevents = APR_POLLOUT;
  251         pollset[1].desc_type = APR_POLL_SOCKET;
  252         pollset[1].desc.s = fc->cntlsock;
  253         pollset[1].reqevents = (APR_POLLIN | APR_POLLPRI);
  254         pollset[1].rtnevents = 0;       /* For poll(1), pretend poll answered
  255                                          * this */
  256 
  257         /* XXX: evil, no apr_socket_pool_get accessor available, though */
  258         pollset[1].p = pollset[0].p = *((apr_pool_t **) fc->datasock);
  259 
  260         do {
  261             /*
  262              * If we have already assembled our next_request, don't bother
  263              * polling the control connection - we won't read ahead two
  264              * commands
  265              */
  266             rv = apr_poll(pollset, fc->next_request ? 1 : 2,
  267                           &n, polltimeout);
  268             /* pedantic sanity check, this should never happen */
  269             if ((rv == APR_SUCCESS) && (n < 0)) {
  270                 rv = APR_EGENERAL;
  271             }
  272 
  273             if (rv != APR_SUCCESS) {
  274                 /*
  275                  * The loss of either socket here means the death of the data
  276                  * connection.
  277                  */
  278                 break;
  279             }
  280 
  281             if (pollset[1].rtnevents & (APR_POLLIN | APR_POLLPRI)) {
  282                 /* command socket heard - but with a full line yet? */
  283                 rv = ftp_read_ahead_request(fc);
  284 
  285                 if ((rv != APR_SUCCESS) &&
  286                   !(APR_STATUS_IS_EINTR(rv) || (APR_STATUS_IS_EAGAIN(rv)) ||
  287                     APR_STATUS_IS_EOF(rv))) {
  288                     f->c->aborted = 1;
  289                     return rv;
  290                 }
  291             }
  292 
  293             if ((rv == APR_SUCCESS) && (pollset[0].rtnevents & APR_POLLOUT)) {
  294                 break;
  295             }
  296         } while (APR_STATUS_IS_EINTR(rv) || APR_STATUS_IS_EAGAIN(rv));
  297         /*
  298          * EINTR, above, is obvious, EAGAIN is less so - win32 (perhaps
  299          * others) can trigger POLLIN a little too early, before the recieved
  300          * packet has actually been disassembled - so loop again.
  301          */
  302 
  303         if (c->aborted || f->c->aborted) {
  304             return AP_FILTER_ERROR;
  305         }
  306 
  307         rv = ap_pass_brigade(f->next, bb);
  308         if (rv != APR_SUCCESS) {
  309             f->c->aborted = 1;
  310             return rv;
  311         }
  312         bb = next_bb;
  313     }
  314 
  315     return APR_SUCCESS;
  316 }