1362181Sdim/* ====================================================================
2362181Sdim *    Licensed to the Apache Software Foundation (ASF) under one
3362181Sdim *    or more contributor license agreements.  See the NOTICE file
4362181Sdim *    distributed with this work for additional information
5362181Sdim *    regarding copyright ownership.  The ASF licenses this file
6362181Sdim *    to you under the Apache License, Version 2.0 (the
7362181Sdim *    "License"); you may not use this file except in compliance
8362181Sdim *    with the License.  You may obtain a copy of the License at
9251877Speter *
10362181Sdim *      http://www.apache.org/licenses/LICENSE-2.0
11251877Speter *
12362181Sdim *    Unless required by applicable law or agreed to in writing,
13362181Sdim *    software distributed under the License is distributed on an
14362181Sdim *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15362181Sdim *    KIND, either express or implied.  See the License for the
16362181Sdim *    specific language governing permissions and limitations
17362181Sdim *    under the License.
18362181Sdim * ====================================================================
19251877Speter */
20251877Speter
21251877Speter#include <apr_pools.h>
22251877Speter#include <apr_network_io.h>
23251877Speter
24251877Speter#include "serf.h"
25251877Speter#include "serf_private.h"
26251877Speter#include "serf_bucket_util.h"
27251877Speter
28251877Speter
29251877Spetertypedef struct {
30251877Speter    apr_socket_t *skt;
31251877Speter
32251877Speter    serf_databuf_t databuf;
33251877Speter
34251877Speter    /* Progress callback */
35251877Speter    serf_progress_t progress_func;
36251877Speter    void *progress_baton;
37251877Speter} socket_context_t;
38251877Speter
39251877Speter
40251877Speterstatic apr_status_t socket_reader(void *baton, apr_size_t bufsize,
41251877Speter                                  char *buf, apr_size_t *len)
42251877Speter{
43251877Speter    socket_context_t *ctx = baton;
44251877Speter    apr_status_t status;
45251877Speter
46251877Speter    *len = bufsize;
47251877Speter    status = apr_socket_recv(ctx->skt, buf, len);
48251877Speter
49251877Speter    if (status && !APR_STATUS_IS_EAGAIN(status))
50251877Speter        serf__log_skt(SOCK_VERBOSE, __FILE__, ctx->skt,
51251877Speter                      "socket_recv error %d\n", status);
52251877Speter
53251877Speter    if (*len)
54251877Speter        serf__log_skt(SOCK_MSG_VERBOSE, __FILE__, ctx->skt,
55251877Speter                      "--- socket_recv:\n%.*s\n-(%d)-\n",
56251877Speter                      *len, buf, *len);
57251877Speter
58262324Speter    if (ctx->progress_func && *len)
59251877Speter        ctx->progress_func(ctx->progress_baton, *len, 0);
60251877Speter
61251877Speter    return status;
62251877Speter}
63251877Speter
64251877Speterserf_bucket_t *serf_bucket_socket_create(
65251877Speter    apr_socket_t *skt,
66251877Speter    serf_bucket_alloc_t *allocator)
67251877Speter{
68251877Speter    socket_context_t *ctx;
69251877Speter
70251877Speter    /* Oh, well. */
71251877Speter    ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
72251877Speter    ctx->skt = skt;
73251877Speter
74251877Speter    serf_databuf_init(&ctx->databuf);
75251877Speter    ctx->databuf.read = socket_reader;
76251877Speter    ctx->databuf.read_baton = ctx;
77251877Speter
78251877Speter    ctx->progress_func = NULL;
79251877Speter    ctx->progress_baton = NULL;
80251877Speter    return serf_bucket_create(&serf_bucket_type_socket, allocator, ctx);
81251877Speter}
82251877Speter
83251877Spetervoid serf_bucket_socket_set_read_progress_cb(
84251877Speter    serf_bucket_t *bucket,
85251877Speter    const serf_progress_t progress_func,
86251877Speter    void *progress_baton)
87251877Speter{
88251877Speter    socket_context_t *ctx = bucket->data;
89251877Speter
90251877Speter    ctx->progress_func = progress_func;
91251877Speter    ctx->progress_baton = progress_baton;
92251877Speter}
93251877Speter
94251877Speterstatic apr_status_t serf_socket_read(serf_bucket_t *bucket,
95251877Speter                                     apr_size_t requested,
96251877Speter                                     const char **data, apr_size_t *len)
97251877Speter{
98251877Speter    socket_context_t *ctx = bucket->data;
99251877Speter
100251877Speter    return serf_databuf_read(&ctx->databuf, requested, data, len);
101251877Speter}
102251877Speter
103251877Speterstatic apr_status_t serf_socket_readline(serf_bucket_t *bucket,
104251877Speter                                         int acceptable, int *found,
105251877Speter                                         const char **data, apr_size_t *len)
106251877Speter{
107251877Speter    socket_context_t *ctx = bucket->data;
108251877Speter
109251877Speter    return serf_databuf_readline(&ctx->databuf, acceptable, found, data, len);
110251877Speter}
111251877Speter
112251877Speterstatic apr_status_t serf_socket_peek(serf_bucket_t *bucket,
113251877Speter                                     const char **data,
114251877Speter                                     apr_size_t *len)
115251877Speter{
116251877Speter    socket_context_t *ctx = bucket->data;
117251877Speter
118251877Speter    return serf_databuf_peek(&ctx->databuf, data, len);
119251877Speter}
120251877Speter
121251877Speterconst serf_bucket_type_t serf_bucket_type_socket = {
122251877Speter    "SOCKET",
123251877Speter    serf_socket_read,
124251877Speter    serf_socket_readline,
125251877Speter    serf_default_read_iovec,
126251877Speter    serf_default_read_for_sendfile,
127251877Speter    serf_default_read_bucket,
128251877Speter    serf_socket_peek,
129251877Speter    serf_default_destroy_and_data,
130251877Speter};
131