1/* ==================================================================== 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 * ==================================================================== 19 */ 20 21#include <apr_pools.h> 22#include <apr_mmap.h> 23 24#include "serf.h" 25#include "serf_bucket_util.h" 26 27#if APR_HAS_MMAP 28 29typedef struct { 30 apr_mmap_t *mmap; 31 void *current; 32 apr_off_t offset; 33 apr_off_t remaining; 34} mmap_context_t; 35 36 37serf_bucket_t *serf_bucket_mmap_create( 38 apr_mmap_t *file_mmap, 39 serf_bucket_alloc_t *allocator) 40{ 41 mmap_context_t *ctx; 42 43 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 44 ctx->mmap = file_mmap; 45 ctx->current = NULL; 46 ctx->offset = 0; 47 ctx->remaining = ctx->mmap->size; 48 49 return serf_bucket_create(&serf_bucket_type_mmap, allocator, ctx); 50} 51 52static apr_status_t serf_mmap_read(serf_bucket_t *bucket, 53 apr_size_t requested, 54 const char **data, apr_size_t *len) 55{ 56 mmap_context_t *ctx = bucket->data; 57 58 if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining) { 59 *len = ctx->remaining; 60 } 61 else { 62 *len = requested; 63 } 64 65 /* ### Would it be faster to call this once and do the offset ourselves? */ 66 apr_mmap_offset((void**)data, ctx->mmap, ctx->offset); 67 68 /* For the next read... */ 69 ctx->offset += *len; 70 ctx->remaining -= *len; 71 72 if (ctx->remaining == 0) { 73 return APR_EOF; 74 } 75 return APR_SUCCESS; 76} 77 78static apr_status_t serf_mmap_readline(serf_bucket_t *bucket, 79 int acceptable, int *found, 80 const char **data, apr_size_t *len) 81{ 82 mmap_context_t *ctx = bucket->data; 83 const char *end; 84 85 /* ### Would it be faster to call this once and do the offset ourselves? */ 86 apr_mmap_offset((void**)data, ctx->mmap, ctx->offset); 87 end = *data; 88 89 /* XXX An overflow is generated if we pass &ctx->remaining to readline. 90 * Not real clear why. 91 */ 92 *len = ctx->remaining; 93 94 serf_util_readline(&end, len, acceptable, found); 95 96 *len = end - *data; 97 98 ctx->offset += *len; 99 ctx->remaining -= *len; 100 101 if (ctx->remaining == 0) { 102 return APR_EOF; 103 } 104 return APR_SUCCESS; 105} 106 107static apr_status_t serf_mmap_peek(serf_bucket_t *bucket, 108 const char **data, 109 apr_size_t *len) 110{ 111 /* Oh, bah. */ 112 return APR_ENOTIMPL; 113} 114 115const serf_bucket_type_t serf_bucket_type_mmap = { 116 "MMAP", 117 serf_mmap_read, 118 serf_mmap_readline, 119 serf_default_read_iovec, 120 serf_default_read_for_sendfile, 121 serf_default_read_bucket, 122 serf_mmap_peek, 123 serf_default_destroy_and_data, 124}; 125 126#else /* !APR_HAS_MMAP */ 127 128serf_bucket_t *serf_bucket_mmap_create(apr_mmap_t *file_mmap, 129 serf_bucket_alloc_t *allocator) 130{ 131 return NULL; 132} 133 134const serf_bucket_type_t serf_bucket_type_mmap = { 135 "MMAP", 136 NULL, 137 NULL, 138 NULL, 139 NULL, 140 NULL, 141 NULL, 142 NULL, 143}; 144 145#endif 146