2 * streams.c : stream encapsulation routines for the ra_svn protocol
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
26 #include <apr_general.h>
27 #include <apr_network_io.h>
30 #include "svn_types.h"
31 #include "svn_error.h"
32 #include "svn_pools.h"
34 #include "svn_private_config.h"
38 struct svn_ra_svn__stream_st {
41 ra_svn_pending_fn_t pending_fn;
42 ra_svn_timeout_fn_t timeout_fn;
45 typedef struct sock_baton_t {
50 typedef struct file_baton_t {
56 /* Returns TRUE if PFD has pending data, FALSE otherwise. */
57 static svn_boolean_t pending(apr_pollfd_t *pfd, apr_pool_t *pool)
63 pfd->reqevents = APR_POLLIN;
64 status = apr_poll(pfd, 1, &n, 0);
65 return (status == APR_SUCCESS && n);
68 /* Functions to implement a file backed svn_ra_svn__stream_t. */
70 /* Implements svn_read_fn_t */
72 file_read_cb(void *baton, char *buffer, apr_size_t *len)
74 file_baton_t *b = baton;
75 apr_status_t status = apr_file_read(b->in_file, buffer, len);
77 if (status && !APR_STATUS_IS_EOF(status))
78 return svn_error_wrap_apr(status, _("Can't read from connection"));
80 return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL);
84 /* Implements svn_write_fn_t */
86 file_write_cb(void *baton, const char *buffer, apr_size_t *len)
88 file_baton_t *b = baton;
89 apr_status_t status = apr_file_write(b->out_file, buffer, len);
91 return svn_error_wrap_apr(status, _("Can't write to connection"));
95 /* Implements ra_svn_timeout_fn_t */
97 file_timeout_cb(void *baton, apr_interval_time_t interval)
99 file_baton_t *b = baton;
100 apr_file_pipe_timeout_set(b->out_file, interval);
103 /* Implements ra_svn_pending_fn_t */
105 file_pending_cb(void *baton)
107 file_baton_t *b = baton;
110 pfd.desc_type = APR_POLL_FILE;
111 pfd.desc.f = b->in_file;
113 return pending(&pfd, b->pool);
116 svn_ra_svn__stream_t *
117 svn_ra_svn__stream_from_files(apr_file_t *in_file,
118 apr_file_t *out_file,
121 file_baton_t *b = apr_palloc(pool, sizeof(*b));
123 b->in_file = in_file;
124 b->out_file = out_file;
127 return svn_ra_svn__stream_create(b, file_read_cb, file_write_cb,
128 file_timeout_cb, file_pending_cb,
132 /* Functions to implement a socket backed svn_ra_svn__stream_t. */
134 /* Implements svn_read_fn_t */
136 sock_read_cb(void *baton, char *buffer, apr_size_t *len)
138 sock_baton_t *b = baton;
140 apr_interval_time_t interval;
142 status = apr_socket_timeout_get(b->sock, &interval);
144 return svn_error_wrap_apr(status, _("Can't get socket timeout"));
146 /* Always block on read.
147 * During pipelining, we set the timeout to 0 for some write
148 * operations so that we can try them without blocking. If APR had
149 * separate timeouts for read and write, we would only set the
150 * write timeout, but it doesn't. So here, we revert back to blocking.
152 apr_socket_timeout_set(b->sock, -1);
153 status = apr_socket_recv(b->sock, buffer, len);
154 apr_socket_timeout_set(b->sock, interval);
156 if (status && !APR_STATUS_IS_EOF(status))
157 return svn_error_wrap_apr(status, _("Can't read from connection"));
159 return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL);
163 /* Implements svn_write_fn_t */
165 sock_write_cb(void *baton, const char *buffer, apr_size_t *len)
167 sock_baton_t *b = baton;
168 apr_status_t status = apr_socket_send(b->sock, buffer, len);
170 return svn_error_wrap_apr(status, _("Can't write to connection"));
174 /* Implements ra_svn_timeout_fn_t */
176 sock_timeout_cb(void *baton, apr_interval_time_t interval)
178 sock_baton_t *b = baton;
179 apr_socket_timeout_set(b->sock, interval);
182 /* Implements ra_svn_pending_fn_t */
184 sock_pending_cb(void *baton)
186 sock_baton_t *b = baton;
189 pfd.desc_type = APR_POLL_SOCKET;
190 pfd.desc.s = b->sock;
192 return pending(&pfd, b->pool);
195 svn_ra_svn__stream_t *
196 svn_ra_svn__stream_from_sock(apr_socket_t *sock,
199 sock_baton_t *b = apr_palloc(pool, sizeof(*b));
204 return svn_ra_svn__stream_create(b, sock_read_cb, sock_write_cb,
205 sock_timeout_cb, sock_pending_cb,
209 svn_ra_svn__stream_t *
210 svn_ra_svn__stream_create(void *baton,
211 svn_read_fn_t read_cb,
212 svn_write_fn_t write_cb,
213 ra_svn_timeout_fn_t timeout_cb,
214 ra_svn_pending_fn_t pending_cb,
217 svn_ra_svn__stream_t *s = apr_palloc(pool, sizeof(*s));
218 s->stream = svn_stream_empty(pool);
219 svn_stream_set_baton(s->stream, baton);
221 svn_stream_set_read(s->stream, read_cb);
223 svn_stream_set_write(s->stream, write_cb);
225 s->timeout_fn = timeout_cb;
226 s->pending_fn = pending_cb;
231 svn_ra_svn__stream_write(svn_ra_svn__stream_t *stream,
232 const char *data, apr_size_t *len)
234 return svn_stream_write(stream->stream, data, len);
238 svn_ra_svn__stream_read(svn_ra_svn__stream_t *stream, char *data,
241 return svn_stream_read(stream->stream, data, len);
245 svn_ra_svn__stream_timeout(svn_ra_svn__stream_t *stream,
246 apr_interval_time_t interval)
248 stream->timeout_fn(stream->baton, interval);
252 svn_ra_svn__stream_pending(svn_ra_svn__stream_t *stream)
254 return stream->pending_fn(stream->baton);