Exemplo n.º 1
0
term_t bif_read0_2(term_t Port, term_t Len, process_t *ctx)
{
	apr_status_t rs;
	apr_size_t size;
	apr_byte_t *buf;
	term_t bin;
	port_t *p;
	if (!is_port(Port) || !is_int(Len))
		return A_BADARG;
	p = port_lookup(prp_serial(Port));
	if (p == 0)
		return A_BADARG;
	size = (apr_size_t)int_value(Len);
	buf = xalloc(proc_gc_pool(ctx), size);
	rs = p->read(p, buf, &size);
	if (size == 0 && APR_STATUS_IS_EOF(rs))
		result(A_EOF);
	else if (size == 0 && rs != 0)
		return decipher_status(rs);
	else
	{
		bin = make_binary(intnum(size), buf, proc_gc_pool(ctx));
		result(bin);
	}
	return AI_OK;
}
Exemplo n.º 2
0
// Called by parent process.
static std::string read_pipe(apr_file_t* in, bool timeout_ok = false)
{
	char buf[256];
	unsigned char bytes_to_read;
	apr_size_t bytes_read;
	apr_status_t status = apr_file_read_full(in, &bytes_to_read, 1, &bytes_read);
	if (status != APR_SUCCESS)
	{
		if (APR_STATUS_IS_TIMEUP(status) && timeout_ok)
		{
			return "TIMEOUT";
		}
		llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl;
		assert(APR_STATUS_IS_EOF(status));
		return "END OF FILE";
	}
	assert(bytes_read == 1);
	status = apr_file_read_full(in, buf, bytes_to_read, &bytes_read);
	if (status != APR_SUCCESS)
	{
		llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl;
		assert(status == APR_SUCCESS);	// Fail
	}
	assert(bytes_read == bytes_to_read);

	std::string received(buf, bytes_read);
	llinfos << "Received: \"" << received << "\" (bytes read: " << bytes_read << ")" << llendl;
	return received;
}
Exemplo n.º 3
0
apr_status_t h2_conn_run(struct h2_ctx *ctx, conn_rec *c)
{
    apr_status_t status;
    int mpm_state = 0;
    
    do {
        if (c->cs) {
            c->cs->sense = CONN_SENSE_DEFAULT;
        }
        status = h2_session_process(h2_ctx_session_get(ctx), async_mpm);
        
        if (c->cs) {
            c->cs->state = CONN_STATE_WRITE_COMPLETION;
        }
        if (APR_STATUS_IS_EOF(status)) {
            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c,
                          "h2_session(%ld): process, closing conn", c->id);
            c->keepalive = AP_CONN_CLOSE;
        }
        else {
            c->keepalive = AP_CONN_KEEPALIVE;
        }
        
        if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state)) {
            break;
        }
    } while (!async_mpm
             && c->keepalive == AP_CONN_KEEPALIVE 
             && mpm_state != AP_MPMQ_STOPPING);
    
    return DONE;
}
Exemplo n.º 4
0
/* Ensure the buffer is prepared for reading. Will return APR_SUCCESS,
 * APR_EOF, or some failure code. *len is only set for EOF. */
static apr_status_t common_databuf_prep(serf_databuf_t *databuf,
                                        apr_size_t *len)
{
    apr_size_t readlen;
    apr_status_t status;

    /* if there is data in the buffer, then we're happy. */
    if (databuf->remaining > 0)
        return APR_SUCCESS;

    /* if we already hit EOF, then keep returning that. */
    if (APR_STATUS_IS_EOF(databuf->status)) {
        /* *data = NULL;   ?? */
        *len = 0;
        return APR_EOF;
    }

    /* refill the buffer */
    status = (*databuf->read)(databuf->read_baton, sizeof(databuf->buf),
                              databuf->buf, &readlen);
    if (SERF_BUCKET_READ_ERROR(status)) {
        return status;
    }

    databuf->current = databuf->buf;
    databuf->remaining = readlen;
    databuf->status = status;

    return APR_SUCCESS;
}
Exemplo n.º 5
0
static apr_status_t serf_chunk_read_iovec(serf_bucket_t *bucket,
                                          apr_size_t requested,
                                          int vecs_size,
                                          struct iovec *vecs,
                                          int *vecs_used)
{
    chunk_context_t *ctx = bucket->data;
    apr_status_t status;

    /* Before proceeding, we need to fetch some data from the stream. */
    if (ctx->state == STATE_FETCH) {
        status = create_chunk(bucket);
        if (status) {
            return status;
        }
    }

    status = serf_bucket_read_iovec(ctx->chunk, requested, vecs_size, vecs,
                                    vecs_used);

    /* Mask EOF from aggregate bucket. */
    if (APR_STATUS_IS_EOF(status) && ctx->state == STATE_CHUNK) {
        status = ctx->last_status;
        ctx->state = STATE_FETCH;
    }

    return status;
}
Exemplo n.º 6
0
static apr_status_t talkTalk(apr_socket_t *socket, apr_pool_t *parent)
{
    apr_pool_t *pool;
    apr_size_t len;
    char *buf;
    apr_status_t rv;

    if (apr_pool_create(&pool, parent) != APR_SUCCESS)
        return APR_ENOPOOL;


    buf = apr_palloc(pool, BUF_SIZE);
    if (!buf)
        return ENOMEM;

    do {
        len = BUF_SIZE;
        rv = apr_socket_recv(socket, buf, &len);
        if (APR_STATUS_IS_EOF(rv) || len == 0 || rv != APR_SUCCESS)
            break;
        rv = apr_socket_send(socket, buf, &len);
        if (len == 0 || rv != APR_SUCCESS)
            break;
    } while (rv == APR_SUCCESS);

    apr_pool_clear(pool);
    return APR_SUCCESS;
}
Exemplo n.º 7
0
/* Implements svn_read_fn_t */
static svn_error_t *
sock_read_cb(void *baton, char *buffer, apr_size_t *len)
{
  sock_baton_t *b = baton;
  apr_status_t status;
  apr_interval_time_t interval;

  status = apr_socket_timeout_get(b->sock, &interval);
  if (status)
    return svn_error_wrap_apr(status, _("Can't get socket timeout"));

  /* Always block on read.
   * During pipelining, we set the timeout to 0 for some write
   * operations so that we can try them without blocking. If APR had
   * separate timeouts for read and write, we would only set the
   * write timeout, but it doesn't. So here, we revert back to blocking.
   */
  apr_socket_timeout_set(b->sock, -1);
  status = apr_socket_recv(b->sock, buffer, len);
  apr_socket_timeout_set(b->sock, interval);

  if (status && !APR_STATUS_IS_EOF(status))
    return svn_error_wrap_apr(status, _("Can't read from connection"));
  if (*len == 0)
    return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL);
  return SVN_NO_ERROR;
}
Exemplo n.º 8
0
static apr_status_t serf_chunk_read(serf_bucket_t *bucket,
                                    apr_size_t requested,
                                    const char **data, apr_size_t *len)
{
    chunk_context_t *ctx = bucket->data;
    apr_status_t status;

    /* Before proceeding, we need to fetch some data from the stream. */
    if (ctx->state == STATE_FETCH) {
        status = create_chunk(bucket);
        if (status) {
            return status;
        }
    }

    status = serf_bucket_read(ctx->chunk, requested, data, len);

    /* Mask EOF from aggregate bucket. */
    if (APR_STATUS_IS_EOF(status) && ctx->state == STATE_CHUNK) {
        status = ctx->last_status;
        ctx->state = STATE_FETCH;
    }

    return status;
}
Exemplo n.º 9
0
static svn_error_t *
read_handler_apr(void *baton, char *buffer, apr_size_t *len)
{
  struct baton_apr *btn = baton;
  svn_error_t *err;
  svn_boolean_t eof;

  if (*len == 1)
    {
      err = svn_io_file_getc(buffer, btn->file, btn->pool);
      if (err)
        {
          *len = 0;
          if (APR_STATUS_IS_EOF(err->apr_err))
            {
              svn_error_clear(err);
              err = SVN_NO_ERROR;
            }
        }
    }
  else
    err = svn_io_file_read_full2(btn->file, buffer, *len, len,
                                 &eof, btn->pool);

  return svn_error_trace(err);
}
Exemplo n.º 10
0
static apr_status_t
read_complete_body(request_rec *r, apr_bucket_brigade *kept_body)
{
    apr_bucket_brigade *tmp_bb;
    apr_bucket *t_bucket1, *t_bucket2;
    unsigned short eos_seen = 0;
    apr_status_t status;

    tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);

    while (!eos_seen) {
        status = ap_get_brigade(
                        r->input_filters,
                        tmp_bb,
                        AP_MODE_READBYTES,
                        APR_BLOCK_READ,
                        HUGE_STRING_LEN);

        /* This means the filter discovered an error.
         * Furthermore input-filter already handeld the error and sends
         * something to the output chain.
         * For example ap_http_filter does this if LimitRequestBody is reached
         */
        if (status == AP_FILTER_ERROR) {
            apr_brigade_destroy(tmp_bb);
            return AP_FILTER_ERROR;
        }

        /* Cool no need to search for the eos bucket */
        if (APR_STATUS_IS_EOF(status)) {
            apr_brigade_destroy(tmp_bb);
            return APR_SUCCESS;
        }

        if (status != APR_SUCCESS) {
            apr_brigade_destroy(tmp_bb);
            return status;
        }

        ITER_BRIGADE(t_bucket1, tmp_bb) {

            apr_bucket_copy(t_bucket1, &t_bucket2);

            /* If SSL is used TRANSIENT buckets are returned.
             * However we need this bucket for a longer period than
             * this function call, hence 'setaside' the bucket.
             */
            if APR_BUCKET_IS_TRANSIENT(t_bucket2) {
                apr_bucket_setaside(t_bucket2, r->pool);
            }

            APR_BRIGADE_INSERT_TAIL(kept_body, t_bucket2);

            if (!eos_seen && APR_BUCKET_IS_EOS(t_bucket1)) {
                eos_seen = 1;
            }
        }
        apr_brigade_cleanup(tmp_bb);
    }
Exemplo n.º 11
0
static void im_exec_fill_buffer(nx_module_input_t *input)
{
    apr_status_t rv;
    apr_size_t len;

    ASSERT(input != NULL);
    ASSERT(input->buf != NULL);
    ASSERT(input->module != NULL);
    ASSERT(input->desc_type == APR_POLL_FILE);
    ASSERT(input->desc.f != NULL);

    if ( input->bufstart == input->bufsize )
    {
	input->bufstart = 0;
	input->buflen = 0;
    }
    if ( input->buflen == 0 )
    {
	input->bufstart = 0;
    }

    ASSERT(input->bufstart + input->buflen <= input->bufsize);
    len = (apr_size_t) (input->bufsize - (input->buflen + input->bufstart));

    rv = apr_file_read(input->desc.f, input->buf + input->bufstart + input->buflen, &len);

    if ( rv != APR_SUCCESS )
    {
	if ( APR_STATUS_IS_EOF(rv) )
	{
	    throw_msg("Module %s got EOF, process exited? ", input->module->name);
	}
	else if ( APR_STATUS_IS_EAGAIN(rv) )
	{ 
#ifdef WIN32
	    // on windows EAGAIN is normal because we are using NON-BLOCKING reads
	    // so we try again after 500 ms
	    im_exec_add_read_event(input->module, 500);
	    log_debug("got EAGAIN");
#else
	    log_error("got EAGAIN for blocking read in module %s", input->module->name);
#endif
	    ASSERT(len == 0);
	    return;
	}
	else
	{
	    throw(rv, "Module %s couldn't read from pipe", input->module->name);
	}
    }
    else
    {
	log_debug("im_exec read %d bytes", (int) len);
    }
    input->buflen += (int) len;
    ASSERT(input->buflen <= input->bufsize);
}
Exemplo n.º 12
0
static apr_status_t fortune_process(conn_rec *c,
                                    apr_procattr_t *pattr,
                                    apr_bucket_brigade *bb)
{
    apr_status_t rv;
    int argc = 0;
    const char *argv[APP_MAX_ARGC];
    apr_proc_t proc;
    apr_bucket *b;
    apr_pool_t *p = c->pool;

    fortune_conf_t *fconf = ap_get_module_config(c->base_server->module_config,
						 &fortune_module);

    argv[argc++] = fconf->progname;
    argv[argc++] = NULL;	/* @argvs should be null-terminated */

    if ((rv = apr_proc_create(&proc, fconf->progname,
                              (const char *const *) argv,
                              NULL, (apr_procattr_t *) pattr,
                              p)) != APR_SUCCESS) {
        return rv;
    }

    while (TRUE) {
        char buf[BUFSIZE] = { 0, };

        /* read the command's output through the pipe */
        rv = apr_file_gets(buf, sizeof(buf), proc.out);
        if (APR_STATUS_IS_EOF(rv)) {
            break;
        }
        b = apr_bucket_pool_create(apr_pstrdup(p, buf),
                                   strlen(buf), p, c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(bb, b);
    }
    apr_file_close(proc.out);

    {
        int st;
        apr_exit_why_e why;

        rv = apr_proc_wait(&proc, &st, &why, APR_WAIT);
        if (APR_STATUS_IS_CHILD_DONE(rv)) {
            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,
                          "child done: why = %d, exit status = %d", why, st);
        }
        else {
            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, "child notdone");
            return APR_EGENERAL;
        }
    }

    return APR_SUCCESS;
}
Exemplo n.º 13
0
/* Implements svn_read_fn_t */
static svn_error_t *
file_read_cb(void *baton, char *buffer, apr_size_t *len)
{
  file_baton_t *b = baton;
  apr_status_t status = apr_file_read(b->in_file, buffer, len);

  if (status && !APR_STATUS_IS_EOF(status))
    return svn_error_wrap_apr(status, _("Can't read from connection"));
  if (*len == 0)
    return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL);
  return SVN_NO_ERROR;
}
Exemplo n.º 14
0
static int h2_session_status_from_apr_status(apr_status_t rv)
{
    if (rv == APR_SUCCESS) {
        return NGHTTP2_NO_ERROR;
    }
    else if (APR_STATUS_IS_EAGAIN(rv)) {
        return NGHTTP2_ERR_WOULDBLOCK;
    }
    else if (APR_STATUS_IS_EOF(rv)) {
            return NGHTTP2_ERR_EOF;
    }
    return NGHTTP2_ERR_PROTO;
}
Exemplo n.º 15
0
apr_status_t h2_conn_run(conn_rec *c)
{
    apr_status_t status;
    int mpm_state = 0;
    h2_session *session = h2_ctx_get_session(c);
    
    ap_assert(session);
    do {
        if (c->cs) {
            c->cs->sense = CONN_SENSE_DEFAULT;
            c->cs->state = CONN_STATE_HANDLER;
        }
    
        status = h2_session_process(session, async_mpm);
        
        if (APR_STATUS_IS_EOF(status)) {
            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c, 
                          H2_SSSN_LOG(APLOGNO(03045), session, 
                          "process, closing conn"));
            c->keepalive = AP_CONN_CLOSE;
        }
        else {
            c->keepalive = AP_CONN_KEEPALIVE;
        }
        
        if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state)) {
            break;
        }
    } while (!async_mpm
             && c->keepalive == AP_CONN_KEEPALIVE 
             && mpm_state != AP_MPMQ_STOPPING);

    if (c->cs) {
        switch (session->state) {
            case H2_SESSION_ST_INIT:
            case H2_SESSION_ST_IDLE:
            case H2_SESSION_ST_BUSY:
            case H2_SESSION_ST_WAIT:
                c->cs->state = CONN_STATE_WRITE_COMPLETION;
                break;
            case H2_SESSION_ST_CLEANUP:
            case H2_SESSION_ST_DONE:
            default:
                c->cs->state = CONN_STATE_LINGER;
            break;
        }
    }

    return APR_SUCCESS;
}
Exemplo n.º 16
0
static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o,
                                     apr_bucket_brigade *bb, char *name)
{
    int rv;
#ifdef DEBUGGING
    apr_off_t len;
#endif

    do {
        apr_brigade_cleanup(bb);
        rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES,
                            APR_NONBLOCK_READ, AP_IOBUFSIZE);
        if (rv == APR_SUCCESS) {
            if (c_o->aborted) {
                return APR_EPIPE;
            }
            if (APR_BRIGADE_EMPTY(bb)) {
                break;
            }
#ifdef DEBUGGING
            len = -1;
            apr_brigade_length(bb, 0, &len);
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02440)
                          "read %" APR_OFF_T_FMT
                          " bytes from %s", len, name);
#endif
            rv = ap_pass_brigade(c_o->output_filters, bb);
            if (rv == APR_SUCCESS) {
                ap_fflush(c_o->output_filters, bb);
            }
            else {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02441)
                              "error on %s - ap_pass_brigade",
                              name);
            }
        } else if (!APR_STATUS_IS_EAGAIN(rv) && !APR_STATUS_IS_EOF(rv)) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(02442)
                          "error on %s - ap_get_brigade",
                          name);
        }
    } while (rv == APR_SUCCESS);

    ap_log_rerror(APLOG_MARK, APLOG_TRACE2, rv, r, "wstunnel_transfer complete");

    if (APR_STATUS_IS_EAGAIN(rv)) {
        rv = APR_SUCCESS;
    }
   
    return rv;
}
Exemplo n.º 17
0
static apr_status_t serf_chunk_peek(serf_bucket_t *bucket,
                                     const char **data,
                                     apr_size_t *len)
{
    chunk_context_t *ctx = bucket->data;
    apr_status_t status;

    status = serf_bucket_peek(ctx->chunk, data, len);

    /* Mask EOF from aggregate bucket. */
    if (APR_STATUS_IS_EOF(status) && ctx->state == STATE_CHUNK) {
        status = APR_EAGAIN;
    }

    return status;
}
Exemplo n.º 18
0
/* Read method of CGI bucket: polls on stderr and stdout of the child,
 * sending any stderr output immediately away to the error log. */
static apr_status_t aikido_bucket_read(apr_bucket *b, const char **str,
                                    apr_size_t *len, apr_read_type_e block)
{
    struct aikido_bucket_data *data = b->data;
    apr_interval_time_t timeout;
    apr_status_t rv;
    int gotdata = 0;

    timeout = block == APR_NONBLOCK_READ ? 0 : data->r->server->timeout;

    do {
        const apr_pollfd_t *results;
        apr_int32_t num;

        rv = apr_pollset_poll(data->pollset, timeout, &num, &results);
        if (APR_STATUS_IS_TIMEUP(rv)) {
            if (timeout) {
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, data->r, 
                              "Timeout waiting for output from CGI script %s",
                              data->r->filename);
                return rv;
            }
            else {
                return APR_EAGAIN;
            }
        }
        else if (APR_STATUS_IS_EINTR(rv)) {
            continue;
        }
        else if (rv != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r, 
                          "poll failed waiting for CGI child");
            return rv;
        }

        for (; num; num--, results++) {
            rv = aikido_read_stdout(b, results[0].desc.f, str, len);
            if (APR_STATUS_IS_EOF(rv)) {
                rv = APR_SUCCESS;
            }
            gotdata = 1;
        }

    } while (!gotdata);

    return rv;
}
Exemplo n.º 19
0
static apr_status_t serf_chunk_readline(serf_bucket_t *bucket,
                                         int acceptable, int *found,
                                         const char **data, apr_size_t *len)
{
    chunk_context_t *ctx = bucket->data;
    apr_status_t status;

    status = serf_bucket_readline(ctx->chunk, acceptable, found, data, len);

    /* Mask EOF from aggregate bucket. */
    if (APR_STATUS_IS_EOF(status) && ctx->state == STATE_CHUNK) {
        status = APR_EAGAIN;
        ctx->state = STATE_FETCH;
    }

    return status;
}
Exemplo n.º 20
0
static ssize_t ra_neon_body_provider(void *userdata,
                                     char *buffer,
                                     size_t buflen)
{
  body_provider_baton_t *b = userdata;
  svn_ra_neon__request_t *req = b->req;
  apr_file_t *body_file = b->body_file;

  if (req->sess->callbacks &&
      req->sess->callbacks->cancel_func)
    SVN_RA_NEON__REQ_ERR
      (req, (req->sess->callbacks->cancel_func)(req->sess->callback_baton));

  if (req->err)
    return -1;

  svn_pool_clear(req->iterpool);
  if (buflen == 0)
    {
      /* This is the beginning of a new body pull. Rewind the file. */
      apr_off_t offset = 0;
      SVN_RA_NEON__REQ_ERR
        (b->req,
         svn_io_file_seek(body_file, APR_SET, &offset, req->iterpool));
      return (req->err ? -1 : 0);
    }
  else
    {
      apr_size_t nbytes = buflen;
      svn_error_t *err = svn_io_file_read(body_file, buffer, &nbytes,
                                          req->iterpool);
      if (err)
        {
          if (APR_STATUS_IS_EOF(err->apr_err))
            {
              svn_error_clear(err);
              return 0;
            }

          SVN_RA_NEON__REQ_ERR(req, err);
          return -1;
        }
      else
        return nbytes;
    }
}
Exemplo n.º 21
0
/* Returns the amount read. */
static int bio_bucket_read(BIO *bio, char *in, int inlen)
{
    serf_ssl_context_t *ctx = bio->ptr;
    const char *data;
    apr_status_t status;
    apr_size_t len;

#ifdef SSL_VERBOSE
    printf("bio_bucket_read called for %d bytes\n", inlen);
#endif

    if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
        && BIO_should_read(ctx->bio)) {
#ifdef SSL_VERBOSE
        printf("bio_bucket_read waiting: (%d %d %d)\n",
           BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
           BIO_get_retry_flags(ctx->bio));
#endif
        /* Falling back... */
        ctx->encrypt.exhausted_reset = 1;
        BIO_clear_retry_flags(bio);
    }

    status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len);

    ctx->decrypt.status = status;
#ifdef SSL_VERBOSE
    printf("bio_bucket_read received %d bytes (%d)\n", len, status);
#endif

    if (!SERF_BUCKET_READ_ERROR(status)) {
        /* Oh suck. */
        if (len) {
            memcpy(in, data, len);
            return len;
        }
        if (APR_STATUS_IS_EOF(status)) {
            BIO_set_retry_read(bio);
            return -1;
        }
    }

    return -1;
}
Exemplo n.º 22
0
apr_status_t serf_databuf_peek(
    serf_databuf_t *databuf,
    const char **data,
    apr_size_t *len)
{
    apr_status_t status = common_databuf_prep(databuf, len);
    if (status)
        return status;

    /* return everything we have */
    *data = databuf->current;
    *len = databuf->remaining;

    /* If the last read returned EOF, then the peek should return the same.
     * The other possibility in databuf->status is APR_EAGAIN, which we
     * should never return. Thus, just return APR_SUCCESS for non-EOF cases.
     */
    if (APR_STATUS_IS_EOF(databuf->status))
        return APR_EOF;
    return APR_SUCCESS;
}
Exemplo n.º 23
0
// get next place takes the request, a file pointing to the file named in the request
// and a buffer which is used to pass back the place's name
static int get_next_place(request_rec *r, apr_file_t *fd, char * buf) {
	// initialization
	int counter=0;
	apr_status_t rv;
	
	// loop and get characters from file until the
	// end of the file is reached or a newline is reached
	// increment the counter based on the character
	// and if the buffer capacity is reached then
	// return an error
	while(1) {
		rv = apr_file_getc(buf+counter,fd);
		if(APR_STATUS_IS_EOF(rv)) {
			return DONE;
		}
		if(buf[counter]=='\n') {
			buf[counter]='\0';
			return OK;
		}
		// escapes spaces for URI
		if(buf[counter]==' ') {
			if(counter+3 < MAX_BUF_LENGTH) {
				buf[counter]='%';
				buf[counter+1]='2';
				buf[counter+2]='0';
			}
			counter+=3;
		}
		else {
			counter++;
		}
		// check for exceeding the buffer length
		if(counter>=MAX_BUF_LENGTH) {
			ap_log_rerror(APLOG_MARK, APLOG_ERR, 0 , r, "Name in file:%s is longer than %d!", 
								r->filename, MAX_BUF_LENGTH);
			return HTTP_INTERNAL_SERVER_ERROR;
		}		
	}
}
Exemplo n.º 24
0
/* Returns the amount read. */
static int bio_file_read(BIO *bio, char *in, int inlen)
{
    apr_file_t *file = bio->ptr;
    apr_status_t status;
    apr_size_t len;

    BIO_clear_retry_flags(bio);

    len = inlen;
    status = apr_file_read(file, in, &len);

    if (!SERF_BUCKET_READ_ERROR(status)) {
        /* Oh suck. */
        if (APR_STATUS_IS_EOF(status)) {
            BIO_set_retry_read(bio);
            return -1;
        } else {
            return len;
        }
    }

    return -1;
}
Exemplo n.º 25
0
static int connection_rx_cb(serv_ctx_t *serv_ctx, apr_pollset_t *pollset, apr_socket_t *sock)
{
    //printf("connection_rx_cb()\n");


    apr_size_t len = BUFSIZE - serv_ctx->down_buf_level;

    apr_status_t rv = apr_socket_recv(sock, (char*)&serv_ctx->down_buf[serv_ctx->down_buf_level], &len); //Daten empfangen
    if (APR_STATUS_IS_EAGAIN(rv))
    {
        /* we have no data to read. we should keep polling the socket */
        return TRUE;
    }
    else if (APR_STATUS_IS_EOF(rv) || len == 0)
    {
        /* we lost TCP session.
         * XXX On Windows, rv would equal to APR_SUCCESS and len==0 in this case. So, we should check @len in addition to APR_EOF check */
        return FALSE;
    }
    else
    {
        /* we got data */
//        printf("rx(%d): ", serv_ctx->channel_number);
//        for(size_t i = 0; i < len ;++i)
//            printf("0x%02x ", (int)serv_ctx->down_buf[serv_ctx->down_buf_level+i]);
//        printf("\n");

        serv_ctx->down_buf_level += len;

        //ipdbgJtagWrite(serv_ctx->chain, (uint8_t*)buf, len, serv_ctx->valid_mask);

    }


    return TRUE;
}
Exemplo n.º 26
0
/**
 * @internal
 *
 * "Sniffs" the input (request) data from the connection stream and tries
 * to determine who closed a connection and why.
 */
static int ironbee_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
                                ap_input_mode_t mode, apr_read_type_e block,
                                apr_off_t readbytes)
{
    conn_rec *c = f->c;
    ironbee_conn_context *ctx = f->ctx;
    ib_conn_t *iconn = ctx->iconn;
    ib_core_cfg_t *corecfg;
    ib_stream_t *istream;
    apr_bucket *b;
    apr_status_t rc;
    int buffering = 0;

    /* Any mode not handled just gets passed through. */
    if ((mode != AP_MODE_GETLINE) && (mode != AP_MODE_READBYTES)) {
        return ap_get_brigade(f->next, bb, mode, block, readbytes);
    }

    /* Configure. */
    ib_context_module_config(iconn->ctx, ib_core_module(), (void *)&corecfg);
    if (corecfg != NULL) {
        buffering = (int)corecfg->buffer_req;
    }

    /* When buffering, data is removed from the brigade and handed
     * to IronBee. The filter must not return an empty brigade in this
     * case and keeps reading until there is processed data that comes
     * back from IronBee.
     */
    do {
        ib_tx_t *itx = iconn->tx;

        /* If there is any processed data, then send it now. */
        if (buffering && (itx != NULL)) {
            ib_sdata_t *sdata;

            /* Take any data from the drain (processed data) and
             * inject it back into the filter brigade.
             */
            ib_fctl_drain(itx->fctl, &istream);
            if ((istream != NULL) && (istream->nelts > 0)) {
                int done = 0;

                while (!done) {
                    apr_bucket *ibucket = NULL;

                    /// @todo Handle multi-bucket lines
                    if (mode == AP_MODE_GETLINE) {
                        done = 1;
                    }

                    ib_stream_pull(istream, &sdata);
                    if (sdata == NULL) {
                        /* No more data left. */
                        break;
                    }

                    switch (sdata->type) {
                        case IB_STREAM_DATA:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": DATA[%d]: %.*s", (int)sdata->dlen, (int)sdata->dlen, (char *)sdata->data);
#endif
                            
                            /// @todo Is this creating a copy?  Just need a reference.
                            ibucket = apr_bucket_heap_create(sdata->data,
                                                             sdata->dlen,
                                                             NULL,
                                                             bb->bucket_alloc);
                            break;
                        case IB_STREAM_FLUSH:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": FLUSH");
#endif
                            ibucket = apr_bucket_flush_create(bb->bucket_alloc);
                            break;
                        case IB_STREAM_EOH:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": EOH");
#endif
                            /// @todo Do something here???
                            break;
                        case IB_STREAM_EOB:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": EOB");
#endif
                            /// @todo Do something here???
                            break;
                        case IB_STREAM_EOS:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": EOS");
#endif
                            ibucket = apr_bucket_eos_create(bb->bucket_alloc);
                            break;
                        default:
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": UNKNOWN stream data type %d", sdata->type);
                    }

                    if (ibucket != NULL) {
                        APR_BRIGADE_INSERT_TAIL(bb, ibucket);
                    }
                }

                /* Need to send any processed data to avoid deadlock. */
                if (!APR_BRIGADE_EMPTY(bb)) {
                    return APR_SUCCESS;
                }
            }
        }

        /* Fetch data from the next filter. */
        if (buffering) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         "FETCH BRIGADE (buffering)");

            /* Normally Apache will request the headers line-by-line, but
             * IronBee does not require this.  So, here the request is
             * fetched with READBYTES and IronBee will then break
             * it back up into lines when it is injected back into
             * the brigade after the data is processed.
             */
            rc = ap_get_brigade(f->next,
                                bb,
                                AP_MODE_READBYTES,
                                block,
                                HUGE_STRING_LEN);
        }
        else {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         "FETCH BRIGADE (non-buffering)");
            rc = ap_get_brigade(f->next, bb, mode, block, readbytes);
        }

        /* Check for any timeouts/disconnects/errors. */
        if (APR_STATUS_IS_TIMEUP(rc)) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         IB_PRODUCT_NAME ": %s server closed connection (%d)",
                         f->frec->name, rc);

            ap_remove_input_filter(f);
            return rc;
        }
        else if (APR_STATUS_IS_EOF(rc) || apr_get_os_error() == ECONNRESET) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         IB_PRODUCT_NAME ": %s client closed connection (%d)",
                         f->frec->name, rc);

            ap_remove_input_filter(f);
            return rc;
        }
        else if (rc != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         IB_PRODUCT_NAME ": %s returned %d (0x%08x) - %s",
                         f->frec->name, rc, rc, strerror(apr_get_os_error()));

            return rc;
        }

        /* Process data. */
        for (b = APR_BRIGADE_FIRST(bb);
             b != APR_BRIGADE_SENTINEL(bb);
             b = APR_BUCKET_NEXT(b))
        {
            if (buffering) {
                /// @todo setaside into our own pool to destroy later???
                apr_bucket_setaside(b, c->pool);
                process_bucket(f, b);
                APR_BUCKET_REMOVE(b);
            }
            else {
                process_bucket(f, b);
            }
        }
    } while (buffering);

    return APR_SUCCESS;
}
Exemplo n.º 27
0
/* If a 200 OK was received for the CONNECT request, consider the connection
   as ready for use. */
static apr_status_t handle_response(serf_request_t *request,
                                    serf_bucket_t *response,
                                    void *handler_baton,
                                    apr_pool_t *pool)
{
    apr_status_t status;
    serf_status_line sl;
    req_ctx_t *ctx = handler_baton;
    serf_connection_t *conn = request->conn;

    /* CONNECT request was cancelled. Assuming that this is during connection
       reset, we can safely discard the request as a new one will be created
       when setting up the next connection. */
    if (!response)
        return APR_SUCCESS;

    status = serf_bucket_response_status(response, &sl);
    if (SERF_BUCKET_READ_ERROR(status)) {
        return status;
    }
    if (!sl.version && (APR_STATUS_IS_EOF(status) ||
                      APR_STATUS_IS_EAGAIN(status)))
    {
        return status;
    }

    status = serf_bucket_response_wait_for_headers(response);
    if (status && !APR_STATUS_IS_EOF(status)) {
        return status;
    }

    /* RFC 2817:  Any successful (2xx) response to a CONNECT request indicates
       that the proxy has established a connection to the requested host and
       port, and has switched to tunneling the current connection to that server
       connection.
    */
    if (sl.code >= 200 && sl.code < 300) {
        serf_bucket_t *hdrs;
        const char *val;

        conn->state = SERF_CONN_CONNECTED;

        /* Body is supposed to be empty. */
        apr_pool_destroy(ctx->pool);
        serf_bucket_destroy(conn->ssltunnel_ostream);
        serf_bucket_destroy(conn->stream);
        conn->stream = NULL;
        ctx = NULL;

        serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
                      "successfully set up ssl tunnel.\n");

        /* Fix for issue #123: ignore the "Connection: close" header here,
           leaving the header in place would make the serf's main context
           loop close this connection immediately after reading the 200 OK
           response. */

        hdrs = serf_bucket_response_get_headers(response);
        val = serf_bucket_headers_get(hdrs, "Connection");
        if (val && strcasecmp("close", val) == 0) {
            serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
                      "Ignore Connection: close header on this reponse, don't "
                      "close the connection now that the tunnel is set up.\n");
            serf__bucket_headers_remove(hdrs, "Connection");
        }

        return APR_EOF;
    }

    /* Authentication failure and 2xx Ok are handled at this point,
       the rest are errors. */
    return SERF_ERROR_SSLTUNNEL_SETUP_FAILED;
}
Exemplo n.º 28
0
// virtual
LLIOPipe::EStatus LLIOSocketReader::process_impl(
	const LLChannelDescriptors& channels,
	buffer_ptr_t& buffer,
	bool& eos,
	LLSD& context,
	LLPumpIO* pump)
{
	LL_RECORD_BLOCK_TIME(FTM_PROCESS_SOCKET_READER);
	PUMP_DEBUG;
	if(!mSource) return STATUS_PRECONDITION_NOT_MET;
	if(!mInitialized)
	{
		PUMP_DEBUG;
		// Since the read will not block, it's ok to initialize and
		// attempt to read off the descriptor immediately.
		mInitialized = true;
		if(pump)
		{
			PUMP_DEBUG;
			LL_DEBUGS() << "Initializing poll descriptor for LLIOSocketReader."
					 << LL_ENDL;
			apr_pollfd_t poll_fd;
			poll_fd.p = NULL;
			poll_fd.desc_type = APR_POLL_SOCKET;
			poll_fd.reqevents = APR_POLLIN;
			poll_fd.rtnevents = 0x0;
			poll_fd.desc.s = mSource->getSocket();
			poll_fd.client_data = NULL;
			pump->setConditional(this, &poll_fd);
		}
	}
	//if(!buffer)
	//{
	//	buffer = new LLBufferArray;
	//}
	PUMP_DEBUG;
	const apr_size_t READ_BUFFER_SIZE = 1024;
	char read_buf[READ_BUFFER_SIZE]; /*Flawfinder: ignore*/
	apr_size_t len;
	apr_status_t status = APR_SUCCESS;
	do
	{
		PUMP_DEBUG;
		len = READ_BUFFER_SIZE;
		status = apr_socket_recv(mSource->getSocket(), read_buf, &len);
		buffer->append(channels.out(), (U8*)read_buf, len);
	} while((APR_SUCCESS == status) && (READ_BUFFER_SIZE == len));
	LL_DEBUGS() << "socket read status: " << status << LL_ENDL;
	LLIOPipe::EStatus rv = STATUS_OK;

	PUMP_DEBUG;
	// *FIX: Also need to check for broken pipe
	if(APR_STATUS_IS_EOF(status))
	{
		// *FIX: Should we shut down the socket read?
		if(pump)
		{
			pump->setConditional(this, NULL);
		}
		rv = STATUS_DONE;
		eos = true;
	}
	else if(APR_STATUS_IS_EAGAIN(status))
	{
/*Commented out by Aura 9-9-8 for DEV-19961.
		// everything is fine, but we can terminate this process pump.
	
		rv = STATUS_BREAK;
*/
	}
	else
	{
		if(ll_apr_warn_status(status))
		{
			rv = STATUS_ERROR;
		}
	}
	PUMP_DEBUG;
	return rv;
}
Exemplo n.º 29
0
void* thread_socket_pipe_receiver(apr_thread_t* thd, void* data)
{
	frl_socket_pipe* pipe = (frl_socket_pipe*)data;

	apr_status_t state;

	apr_socket_t* listen_sock;
	apr_socket_create(&listen_sock, pipe->sock_addr->family, SOCK_STREAM, APR_PROTO_TCP, pipe->sockpool);
	apr_socket_opt_set(listen_sock, APR_SO_NONBLOCK, 1);
	apr_socket_timeout_set(listen_sock, 0);
	apr_socket_opt_set(listen_sock, APR_SO_REUSEADDR, 1);
	pipe->recv_state = apr_socket_bind(listen_sock, pipe->sock_addr);
	F_ERROR_IF_RUN(APR_SUCCESS != pipe->recv_state, return NULL, "[frl_socket_pipe::thread_socket_pipe_receiver]: Socket Binding Error: %d\n", pipe->recv_state);
	pipe->recv_state = apr_socket_listen(listen_sock, SOMAXCONN);
	F_ERROR_IF_RUN(APR_SUCCESS != pipe->recv_state, return NULL, "[frl_socket_pipe::thread_socket_pipe_receiver]: Socket Listen Error: %d\n", pipe->recv_state);
	apr_uint32_t hash;
	apr_pollset_t* pollset;
	apr_pollset_create(&pollset, pipe->replicate+2, pipe->sockpool, 0);
	apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, NULL };
	pfd.desc.s = listen_sock;
	apr_pollset_add(pollset, &pfd);
	do {
		// the fun loop
		apr_int32_t total;
		const apr_pollfd_t* ret_pfd;
		pipe->recv_state = apr_pollset_poll(pollset, SOCKET_PIPE_POLL_TIMEOUT, &total, &ret_pfd);
		if (APR_SUCCESS == pipe->recv_state)
		{
			for (int i = 0; i < total; i++)
			{
				if (ret_pfd[i].desc.s == listen_sock)
				{
					apr_socket_t* accept_sock;
					state = apr_socket_accept(&accept_sock, listen_sock, pipe->sockpool);
					F_ERROR_IF_RUN(APR_SUCCESS != state, continue, "[frl_socket_pipe::thread_socket_pipe_receiver]: Socket Accept Error: %d\n", state);
					// accept connection, initiate recv
					frl_pipe_state_t* pipestate = (frl_pipe_state_t*)frl_slab_palloc(pipe->statepool);
					apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, pipestate };
					pipestate->state = FRL_PIPE_READ_HEADER_START;
					pipestate->reader = (char*)&pipestate->header;
					pipestate->offset = 0;
					pipestate->size = SIZEOF_FRL_PIPE_HEADER_T;
					pfd.desc.s = accept_sock;
					apr_socket_opt_set(accept_sock, APR_SO_NONBLOCK, 1);
					apr_socket_timeout_set(accept_sock, 0);
					apr_pollset_add(pollset, &pfd);
				} else {
					if (ret_pfd[i].rtnevents & APR_POLLIN)
					{
						frl_pipe_state_t* pipestate = (frl_pipe_state_t*)ret_pfd[i].client_data;
						apr_size_t len_a = pipestate->size-pipestate->offset;
						state = apr_socket_recv(ret_pfd[i].desc.s, pipestate->reader, &len_a);
						pipestate->offset += len_a;
						pipestate->reader += len_a;
						// read buffer to reader
						if ((pipestate->offset >= pipestate->size)||(APR_STATUS_IS_EAGAIN(state)))
						{
							pipestate->offset = pipestate->size;
							PIPE_STATE_TO_COMPLETE(pipestate->state);
							// read complete, move state to complete
						} else if ((APR_STATUS_IS_EOF(state))||(len_a == 0)) {
							apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, pipestate };
							pfd.desc.s = ret_pfd[i].desc.s;
							apr_pollset_remove(pollset, &pfd);
							frl_slab_pfree(pipestate);
							apr_socket_close(ret_pfd[i].desc.s);
							// remote error, close connection
							continue;
						}
						switch (pipestate->state)
						{
							case FRL_PIPE_READ_HEADER_COMPLETE:
							{
								// recv header (hash & size)
								pipestate->data.offset = 0;
								pipestate->data.size = pipestate->header.size;
								state = pipe->recv_before(&pipestate->data.buf, &pipestate->data.size);
								if (FRL_PROGRESS_IS_INTERRUPT(state))
								{
									apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, pipestate };
									pfd.desc.s = ret_pfd[i].desc.s;
									apr_pollset_remove(pollset, &pfd);
									frl_slab_pfree(pipestate);
									apr_socket_close(ret_pfd[i].desc.s);
									continue;
								}
								pipestate->state = FRL_PIPE_READ_BLOCK_START;
								// start to read block (<= 4092 bytes each)
								pipestate->reader = pipestate->buffer;
								pipestate->offset = 0;
								if (pipestate->data.size < SIZEOF_FRL_PIPE_BLOCK_BUFFER)
									pipestate->size = pipestate->data.size+SIZEOF_FRL_PIPE_HEADER_T;
								else
									pipestate->size = SOCKET_PACKAGE_SIZE;
								break;
							}
							case FRL_PIPE_READ_BLOCK_COMPLETE:
							{
								// a block complete, move to data
								memcpy(pipestate->data.buf+pipestate->data.offset, &pipestate->block.start, pipestate->block.header.size);
								hash = hashlittle(&pipestate->block.start, pipestate->size-SIZEOF_FRL_PIPE_HEADER_T);
								if (hash != pipestate->block.header.hash)
								{
									// check the hash fingerprint of the block
									apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, pipestate };
									pfd.desc.s = ret_pfd[i].desc.s;
									apr_pollset_remove(pollset, &pfd);
									frl_slab_pfree(pipestate);
									apr_socket_close(ret_pfd[i].desc.s);
									continue;
								}
								pipestate->data.offset += pipestate->block.header.size;
								if (pipestate->data.offset >= pipestate->data.size)
								{
									// finish read, report state to remote
									apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, pipestate };
									pfd.desc.s = ret_pfd[i].desc.s;
									apr_pollset_remove(pollset, &pfd);
									hash = hashlittle(pipestate->data.buf, pipestate->data.size);
									if (hash != pipestate->header.hash)
									{
										// check hash fingerprint of all data
										frl_slab_pfree(pipestate);
										apr_socket_close(ret_pfd[i].desc.s);
									} else {
										pfd.reqevents = APR_POLLOUT;
										state = pipe->recv_after(pipestate->data.buf, pipestate->data.size);
										if (FRL_PROGRESS_IS_INTERRUPT(state))
										{
											frl_slab_pfree(pipestate);
											apr_socket_close(ret_pfd[i].desc.s);
										} else {
											pipestate->state = FRL_PIPE_SEND_HEADER_START;
											pipestate->reader = (char*)&pipestate->header;
											pipestate->offset = 0;
											pipestate->size = SIZEOF_FRL_PIPE_HEADER_T;
											apr_pollset_add(pollset, &pfd);
										}
									}
									continue;
								}
								// to start read successor block
								pipestate->state = FRL_PIPE_READ_BLOCK_START;
								pipestate->reader = pipestate->buffer;
								pipestate->offset = 0;
								if (pipestate->data.size-pipestate->data.offset < SIZEOF_FRL_PIPE_BLOCK_BUFFER)
									pipestate->size = pipestate->data.size-pipestate->data.offset+SIZEOF_FRL_PIPE_HEADER_T;
								else
									pipestate->size = SOCKET_PACKAGE_SIZE;
								break;
							}
							default:
								break;
						}
					} else if (ret_pfd[i].rtnevents & APR_POLLOUT) {
						// send report information, basic header
						frl_pipe_state_t* pipestate = (frl_pipe_state_t*)ret_pfd[i].client_data;
						apr_size_t len_a = pipestate->size-pipestate->offset;
						state = apr_socket_send(ret_pfd[i].desc.s, pipestate->reader, &len_a);
						pipestate->offset += len_a;
						pipestate->reader += len_a;
						if ((pipestate->offset >= pipestate->size)||(APR_STATUS_IS_EAGAIN(state)))
						{
							pipestate->offset = pipestate->size;
							PIPE_STATE_TO_COMPLETE(pipestate->state);
						} else if ((APR_STATUS_IS_EOF(state))||(len_a == 0)) {
							apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLOUT, 0, { NULL }, pipestate };
							pfd.desc.s = ret_pfd[i].desc.s;
							apr_pollset_remove(pollset, &pfd);
							frl_slab_pfree(pipestate);
							apr_socket_close(ret_pfd[i].desc.s);
							continue;
						}
						switch (pipestate->state)
						{
							case FRL_PIPE_SEND_HEADER_COMPLETE:
							{
								// complete, return to listen state
								apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLOUT, 0, { NULL }, pipestate };
								pfd.desc.s = ret_pfd[i].desc.s;
								apr_pollset_remove(pollset, &pfd);
								pfd.reqevents = APR_POLLIN;
								pipestate->state = FRL_PIPE_DISABLED;
								pipestate->reader = 0;
								pipestate->offset = 0;
								pipestate->size = 0;
								apr_pollset_add(pollset, &pfd);
								break;
							}
							default:
								break;
						}
					} else {
						// other errors, close connection
						frl_pipe_state_t* pipestate = (frl_pipe_state_t*)ret_pfd[i].client_data;
						apr_pollfd_t pfd = { pipe->sockpool, APR_POLL_SOCKET, APR_POLLIN | APR_POLLOUT, 0, { NULL }, pipestate };
						pfd.desc.s = ret_pfd[i].desc.s;
						apr_pollset_remove(pollset, &pfd);
						frl_slab_pfree(pipestate);
						apr_socket_close(ret_pfd[i].desc.s);
					}
				}
			}
		} else if (!APR_STATUS_IS_TIMEUP(pipe->recv_state)) {
Exemplo n.º 30
0
static apr_status_t handle_response(serf_request_t *request,
                                    serf_bucket_t *response,
                                    void *handler_baton,
                                    apr_pool_t *pool)
{
    const char *data;
    apr_size_t len;
    serf_status_line sl;
    apr_status_t status;
    handler_baton_t *ctx = handler_baton;

    if (!response) {
        /* Oh no!  We've been cancelled! */
        abort();
    }

    status = serf_bucket_response_status(response, &sl);
    if (status) {
        if (APR_STATUS_IS_EAGAIN(status)) {
            return APR_SUCCESS;
        }
        abort();
    }

    while (1) {
        status = serf_bucket_read(response, 2048, &data, &len);

        if (SERF_BUCKET_READ_ERROR(status))
            return status;

        /*fwrite(data, 1, len, stdout);*/

        if (!ctx->hdr_read) {
            serf_bucket_t *hdrs;
            const char *val;

            printf("Processing %s\n", ctx->path);

            hdrs = serf_bucket_response_get_headers(response);
            val = serf_bucket_headers_get(hdrs, "Content-Type");
            /* FIXME: This check isn't quite right because Content-Type could
             * be decorated; ideally strcasestr would be correct.
             */
            if (val && strcasecmp(val, "text/html") == 0) {
                ctx->is_html = 1;
                apr_pool_create(&ctx->parser_pool, NULL);
                ctx->parser = apr_xml_parser_create(ctx->parser_pool);
            }
            else {
                ctx->is_html = 0;
            }
            ctx->hdr_read = 1;
        }
        if (ctx->is_html) {
            apr_status_t xs;

            xs = apr_xml_parser_feed(ctx->parser, data, len);
            /* Uh-oh. */
            if (xs) {
#ifdef SERF_VERBOSE
                printf("XML parser error (feed): %d\n", xs);
#endif
                ctx->is_html = 0;
            }
        }

        /* are we done yet? */
        if (APR_STATUS_IS_EOF(status)) {

            if (ctx->is_html) {
                apr_xml_doc *xmld;
                apr_status_t xs;
                doc_path_t *dup;

                xs = apr_xml_parser_done(ctx->parser, &xmld);
                if (xs) {
#ifdef SERF_VERBOSE
                    printf("XML parser error (done): %d\n", xs);
#endif
                    return xs;
                }
                dup = (doc_path_t*)
                    serf_bucket_mem_alloc(ctx->doc_queue_alloc,
                                          sizeof(doc_path_t));
                dup->doc = xmld;
                dup->path = (char*)serf_bucket_mem_alloc(ctx->doc_queue_alloc,
                                                         ctx->path_len);
                memcpy(dup->path, ctx->path, ctx->path_len);
                dup->pool = ctx->parser_pool;

                *(doc_path_t **)apr_array_push(ctx->doc_queue) = dup;

                apr_thread_cond_signal(ctx->doc_queue_condvar);
            }

            apr_atomic_dec32(ctx->requests_outstanding);
            serf_bucket_mem_free(ctx->allocator, ctx->path);
            if (ctx->query) {
                serf_bucket_mem_free(ctx->allocator, ctx->query);
                serf_bucket_mem_free(ctx->allocator, ctx->full_path);
            }
            if (ctx->fragment) {
                serf_bucket_mem_free(ctx->allocator, ctx->fragment);
            }
            serf_bucket_mem_free(ctx->allocator, ctx);
            return APR_EOF;
        }

        /* have we drained the response so far? */
        if (APR_STATUS_IS_EAGAIN(status))
            return APR_SUCCESS;

        /* loop to read some more. */
    }
    /* NOTREACHED */
}