1251881Speter/* 2251881Speter * sb_bucket.c : a serf bucket that wraps a spillbuf 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter#include <serf.h> 25251881Speter#include <serf_bucket_util.h> 26251881Speter 27251881Speter#include "svn_private_config.h" 28251881Speter#include "private/svn_subr_private.h" 29251881Speter 30251881Speter#include "ra_serf.h" 31251881Speter 32251881Speter#define SB_BLOCKSIZE 1024 33251881Speter#define SB_MAXSIZE 32768 34251881Speter 35251881Speter 36251881Speterstruct sbb_baton 37251881Speter{ 38251881Speter svn_spillbuf_t *spillbuf; 39251881Speter 40251881Speter const char *holding; 41251881Speter apr_size_t hold_len; 42251881Speter 43251881Speter apr_pool_t *scratch_pool; 44251881Speter}; 45251881Speter 46251881Speter 47251881Spetersvn_error_t * 48251881Spetersvn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf, 49251881Speter serf_bucket_t *bkt, 50251881Speter apr_pool_t *result_pool, 51251881Speter apr_pool_t *scratch_pool) 52251881Speter{ 53251881Speter *spillbuf = svn_spillbuf__create(SB_BLOCKSIZE, SB_MAXSIZE, result_pool); 54251881Speter 55251881Speter /* Copy all data from the bucket into the spillbuf. */ 56251881Speter while (TRUE) 57251881Speter { 58251881Speter apr_status_t status; 59251881Speter const char *data; 60251881Speter apr_size_t len; 61251881Speter 62251881Speter status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); 63251881Speter 64251881Speter if (status != APR_SUCCESS && status != APR_EOF) 65251881Speter return svn_ra_serf__wrap_err(status, _("Failed to read the request")); 66251881Speter 67251881Speter SVN_ERR(svn_spillbuf__write(*spillbuf, data, len, scratch_pool)); 68251881Speter 69251881Speter if (status == APR_EOF) 70251881Speter break; 71251881Speter } 72251881Speter 73251881Speter return SVN_NO_ERROR; 74251881Speter} 75251881Speter 76251881Speter 77251881Speterstatic apr_status_t 78251881Spetersb_bucket_read(serf_bucket_t *bucket, apr_size_t requested, 79251881Speter const char **data, apr_size_t *len) 80251881Speter{ 81251881Speter struct sbb_baton *sbb = bucket->data; 82251881Speter svn_error_t *err; 83251881Speter 84251881Speter if (sbb->holding) 85251881Speter { 86251881Speter *data = sbb->holding; 87251881Speter 88251881Speter if (requested < sbb->hold_len) 89251881Speter { 90251881Speter *len = requested; 91251881Speter sbb->holding += requested; 92251881Speter sbb->hold_len -= requested; 93251881Speter return APR_SUCCESS; 94251881Speter } 95251881Speter 96251881Speter /* Return whatever we're holding, and then forget (consume) it. */ 97251881Speter *len = sbb->hold_len; 98251881Speter sbb->holding = NULL; 99251881Speter return APR_SUCCESS; 100251881Speter } 101251881Speter 102251881Speter err = svn_spillbuf__read(data, len, sbb->spillbuf, sbb->scratch_pool); 103251881Speter svn_pool_clear(sbb->scratch_pool); 104251881Speter 105251881Speter /* ### do something with this */ 106251881Speter svn_error_clear(err); 107251881Speter 108251881Speter /* The spillbuf may have returned more than requested. Stash any extra 109251881Speter into our holding area. */ 110251881Speter if (requested < *len) 111251881Speter { 112251881Speter sbb->holding = *data + requested; 113251881Speter sbb->hold_len = *len - requested; 114251881Speter *len = requested; 115251881Speter } 116251881Speter 117251881Speter return *data == NULL ? APR_EOF : APR_SUCCESS; 118251881Speter} 119251881Speter 120251881Speter 121251881Speterstatic apr_status_t 122251881Spetersb_bucket_readline(serf_bucket_t *bucket, int acceptable, 123251881Speter int *found, 124251881Speter const char **data, apr_size_t *len) 125251881Speter{ 126251881Speter /* ### for now, we know callers won't use this function. */ 127251881Speter svn_error_clear(svn_error__malfunction(TRUE, __FILE__, __LINE__, 128251881Speter "Not implemented.")); 129251881Speter return APR_ENOTIMPL; 130251881Speter} 131251881Speter 132251881Speter 133251881Speterstatic apr_status_t 134251881Spetersb_bucket_peek(serf_bucket_t *bucket, 135251881Speter const char **data, apr_size_t *len) 136251881Speter{ 137251881Speter struct sbb_baton *sbb = bucket->data; 138251881Speter svn_error_t *err; 139251881Speter 140251881Speter /* If we're not holding any data, then fill it. */ 141251881Speter if (sbb->holding == NULL) 142251881Speter { 143251881Speter err = svn_spillbuf__read(&sbb->holding, &sbb->hold_len, sbb->spillbuf, 144251881Speter sbb->scratch_pool); 145251881Speter svn_pool_clear(sbb->scratch_pool); 146251881Speter 147251881Speter /* ### do something with this */ 148251881Speter svn_error_clear(err); 149251881Speter } 150251881Speter 151251881Speter /* Return the data we are (now) holding. */ 152251881Speter *data = sbb->holding; 153251881Speter *len = sbb->hold_len; 154251881Speter 155251881Speter return *data == NULL ? APR_EOF : APR_SUCCESS; 156251881Speter} 157251881Speter 158251881Speter 159251881Speterstatic const serf_bucket_type_t sb_bucket_vtable = { 160251881Speter "SPILLBUF", 161251881Speter sb_bucket_read, 162251881Speter sb_bucket_readline, 163251881Speter serf_default_read_iovec, 164251881Speter serf_default_read_for_sendfile, 165251881Speter serf_default_read_bucket, 166251881Speter sb_bucket_peek, 167251881Speter serf_default_destroy_and_data, 168251881Speter}; 169251881Speter 170251881Speter 171251881Speterserf_bucket_t * 172251881Spetersvn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf, 173251881Speter serf_bucket_alloc_t *allocator, 174251881Speter apr_pool_t *result_pool, 175251881Speter apr_pool_t *scratch_pool) 176251881Speter{ 177251881Speter struct sbb_baton *sbb; 178251881Speter 179251881Speter sbb = serf_bucket_mem_alloc(allocator, sizeof(*sbb)); 180251881Speter sbb->spillbuf = spillbuf; 181251881Speter sbb->holding = NULL; 182251881Speter sbb->scratch_pool = svn_pool_create(result_pool); 183251881Speter 184251881Speter return serf_bucket_create(&sb_bucket_vtable, allocator, sbb); 185251881Speter} 186