-rw-r--r-- | rsync/stream.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/rsync/stream.c b/rsync/stream.c new file mode 100644 index 0000000..d20d866 --- a/dev/null +++ b/rsync/stream.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- dynamic caching and delta update in HTTP | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * Programming languages should be designed not | ||
25 | * by piling feature on top of feature, but by | ||
26 | * removing the weaknesses and restrictions that | ||
27 | * make additional features appear necessary. | ||
28 | * -- Revised^5 Report on Scheme | ||
29 | */ | ||
30 | |||
31 | |||
32 | /* | ||
33 | * OK, so I'll admit IO here is a little complex. The most important | ||
34 | * player here is the stream, which is an object for managing filter | ||
35 | * operations. It has both input and output sides, both of which is | ||
36 | * just a (pointer,len) pair into a buffer provided by the client. | ||
37 | * The code controlling the stream handles however much data it wants, | ||
38 | * and the client provides or accepts however much is convenient. | ||
39 | * | ||
40 | * At the same time as being friendly to the client, we also try to be | ||
41 | * very friendly to the internal code. It wants to be able to ask for | ||
42 | * arbitrary amounts of input or output and get it without having to | ||
43 | * keep track of partial completion. So there are functions which | ||
44 | * either complete, or queue whatever was not sent and return | ||
45 | * RS_BLOCKED. | ||
46 | * | ||
47 | * The output buffer is a little more clever than simply a data | ||
48 | * buffer. Instead it knows that we can send either literal data, or | ||
49 | * data copied through from the input of the stream. | ||
50 | * | ||
51 | * In buf.c you will find functions that then map buffers onto stdio | ||
52 | * files. | ||
53 | * | ||
54 | * So on return from an encoding function, either the input or the | ||
55 | * output or possibly both will have no more bytes available. | ||
56 | */ | ||
57 | |||
58 | /* | ||
59 | * Manage librsync streams of IO. See scoop.c and tube.c for related | ||
60 | * code for input and output respectively. | ||
61 | * | ||
62 | * librsync never does IO or memory allocation, but relies on the | ||
63 | * caller. This is very nice for integration, but means that we have | ||
64 | * to be fairly flexible as to when we can `read' or `write' stuff | ||
65 | * internally. | ||
66 | * | ||
67 | * librsync basically does two types of IO. It reads network integers | ||
68 | * of various lengths which encode command and control information | ||
69 | * such as versions and signatures. It also does bulk data transfer. | ||
70 | * | ||
71 | * IO of network integers is internally buffered, because higher | ||
72 | * levels of the code need to see them transmitted atomically: it's no | ||
73 | * good to read half of a uint32. So there is a small and fixed | ||
74 | * length internal buffer which accumulates these. Unlike previous | ||
75 | * versions of the library, we don't require that the caller hold the | ||
76 | * start until the whole thing has arrived, which guarantees that we | ||
77 | * can always make progress. | ||
78 | * | ||
79 | * On each call into a stream iterator, it should begin by trying to | ||
80 | * flush output. This may well use up all the remaining stream space, | ||
81 | * in which case nothing else can be done. | ||
82 | */ | ||
83 | |||
84 | /* TODO: Return errors rather than aborting if something goes wrong. */ | ||
85 | |||
86 | |||
87 | #include <config_rsync.h> | ||
88 | |||
89 | #include <assert.h> | ||
90 | #include <stdlib.h> | ||
91 | #include <string.h> | ||
92 | #include <stdio.h> | ||
93 | |||
94 | #include "rsync.h" | ||
95 | #include "stream.h" | ||
96 | #include "util.h" | ||
97 | #include "trace.h" | ||
98 | |||
99 | static const int RS_STREAM_DOGTAG = 2001125; | ||
100 | |||
101 | |||
102 | /** | ||
103 | * \brief Copy up to \p max_len bytes from input of \b stream to its output. | ||
104 | * | ||
105 | * Return the number of bytes actually copied, which may be less than | ||
106 | * LEN if there is not enough space in one or the other stream. | ||
107 | * | ||
108 | * This always does the copy immediately. Most functions should call | ||
109 | * rs_tube_copy() to cause the copy to happen gradually as space | ||
110 | * becomes available. | ||
111 | */ | ||
112 | int rs_buffers_copy(rs_buffers_t *stream, int max_len) | ||
113 | { | ||
114 | int len = max_len; | ||
115 | |||
116 | assert(len > 0); | ||
117 | |||
118 | if ((unsigned) len > stream->avail_in) { | ||
119 | rs_trace("copy limited to %d available input bytes", | ||
120 | stream->avail_in); | ||
121 | len = stream->avail_in; | ||
122 | } | ||
123 | |||
124 | |||
125 | if ((unsigned) len > stream->avail_out) { | ||
126 | rs_trace("copy limited to %d available output bytes", | ||
127 | stream->avail_out); | ||
128 | len = stream->avail_out; | ||
129 | } | ||
130 | |||
131 | if (!len) | ||
132 | return 0; | ||
133 | /* rs_trace("stream copied chunk of %d bytes", len); */ | ||
134 | |||
135 | memcpy(stream->next_out, stream->next_in, len); | ||
136 | |||
137 | stream->next_out += len; | ||
138 | stream->avail_out -= len; | ||
139 | |||
140 | stream->next_in += len; | ||
141 | stream->avail_in -= len; | ||
142 | |||
143 | return len; | ||
144 | } | ||
145 | |||
146 | |||
147 | /** | ||
148 | * Whenever a stream processing function exits, it should have done so | ||
149 | * because it has either consumed all the input or has filled the | ||
150 | * output buffer. This function checks that simple postcondition. | ||
151 | */ | ||
152 | void rs_buffers_check_exit(rs_buffers_t const *stream) | ||
153 | { | ||
154 | assert(stream->avail_in == 0 || stream->avail_out == 0); | ||
155 | } | ||