1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26
27 /*
28 * RFC7233 examples
29 *
30 * o The first 500 bytes (byte offsets 0-499, inclusive):
31 *
32 * bytes=0-499
33 *
34 * o The second 500 bytes (byte offsets 500-999, inclusive):
35 *
36 * bytes=500-999
37 *
38 * o The final 500 bytes (byte offsets 9500-9999, inclusive):
39 *
40 * bytes=-500
41 *
42 * Or:
43 *
44 * bytes=9500-
45 *
46 * o The first and last bytes only (bytes 0 and 9999):
47 *
48 * bytes=0-0,-1
49 *
50 * o Other valid (but not canonical) specifications of the second 500
51 * bytes (byte offsets 500-999, inclusive):
52 *
53 * bytes=500-600,601-999
54 * bytes=500-700,601-999
55 */
56
57 /*
58 * returns 1 if the range struct represents a usable range
59 * if no ranges header, you get one of these for the whole
60 * file. Otherwise you get one for each valid range in the
61 * header.
62 *
63 * returns 0 if no further valid range forthcoming; rp->state
64 * may be LWSRS_SYNTAX or LWSRS_COMPLETED
65 */
66
67 int
lws_ranges_next(struct lws_range_parsing * rp)68 lws_ranges_next(struct lws_range_parsing *rp)
69 {
70 static const char * const beq = "bytes=";
71
72 while (1) {
73
74 char c = rp->buf[rp->pos];
75
76 switch (rp->state) {
77 case LWSRS_SYNTAX:
78 case LWSRS_COMPLETED:
79 return 0;
80
81 case LWSRS_NO_ACTIVE_RANGE:
82 rp->state = LWSRS_COMPLETED;
83 return 0;
84
85 case LWSRS_BYTES_EQ: // looking for "bytes="
86 if (c != beq[rp->pos]) {
87 rp->state = LWSRS_SYNTAX;
88 return -1;
89 }
90 if (rp->pos == 5)
91 rp->state = LWSRS_FIRST;
92 break;
93
94 case LWSRS_FIRST:
95 rp->start = 0;
96 rp->end = 0;
97 rp->start_valid = 0;
98 rp->end_valid = 0;
99
100 rp->state = LWSRS_STARTING;
101
102 // fallthru
103
104 case LWSRS_STARTING:
105 if (c == '-') {
106 rp->state = LWSRS_ENDING;
107 break;
108 }
109
110 if (!(c >= '0' && c <= '9')) {
111 rp->state = LWSRS_SYNTAX;
112 return 0;
113 }
114 rp->start = (unsigned long long)(((unsigned long long)rp->start * 10) + (unsigned long long)(c - '0'));
115 rp->start_valid = 1;
116 break;
117
118 case LWSRS_ENDING:
119 if (c == ',' || c == '\0') {
120 rp->state = LWSRS_FIRST;
121 if (c == ',')
122 rp->pos++;
123
124 /*
125 * By the end of this, start and end are
126 * always valid if the range still is
127 */
128
129 if (!rp->start_valid) { /* eg, -500 */
130 if (rp->end > rp->extent)
131 rp->end = rp->extent;
132
133 rp->start = rp->extent - rp->end;
134 rp->end = rp->extent - 1;
135 } else
136 if (!rp->end_valid)
137 rp->end = rp->extent - 1;
138
139 rp->did_try = 1;
140
141 /* end must be >= start or ignore it */
142 if (rp->end < rp->start) {
143 if (c == ',')
144 break;
145 rp->state = LWSRS_COMPLETED;
146 return 0;
147 }
148
149 return 1; /* issue range */
150 }
151
152 if (!(c >= '0' && c <= '9')) {
153 rp->state = LWSRS_SYNTAX;
154 return 0;
155 }
156 rp->end = (unsigned long long)(((unsigned long long)rp->end * 10) + (unsigned long long)(c - '0'));
157 rp->end_valid = 1;
158 break;
159 }
160
161 rp->pos++;
162 }
163 }
164
165 void
lws_ranges_reset(struct lws_range_parsing * rp)166 lws_ranges_reset(struct lws_range_parsing *rp)
167 {
168 rp->pos = 0;
169 rp->ctr = 0;
170 rp->start = 0;
171 rp->end = 0;
172 rp->start_valid = 0;
173 rp->end_valid = 0;
174 rp->state = LWSRS_BYTES_EQ;
175 }
176
177 /*
178 * returns count of valid ranges
179 */
180 int
lws_ranges_init(struct lws * wsi,struct lws_range_parsing * rp,unsigned long long extent)181 lws_ranges_init(struct lws *wsi, struct lws_range_parsing *rp,
182 unsigned long long extent)
183 {
184 rp->agg = 0;
185 rp->send_ctr = 0;
186 rp->inside = 0;
187 rp->count_ranges = 0;
188 rp->did_try = 0;
189 lws_ranges_reset(rp);
190 rp->state = LWSRS_COMPLETED;
191
192 rp->extent = extent;
193
194 if (lws_hdr_copy(wsi, (char *)rp->buf, sizeof(rp->buf),
195 WSI_TOKEN_HTTP_RANGE) <= 0)
196 return 0;
197
198 rp->state = LWSRS_BYTES_EQ;
199
200 while (lws_ranges_next(rp)) {
201 rp->count_ranges++;
202 rp->agg += rp->end - rp->start + 1;
203 }
204
205 lwsl_debug("%s: count %d\n", __func__, rp->count_ranges);
206 lws_ranges_reset(rp);
207
208 if (rp->did_try && !rp->count_ranges)
209 return -1; /* "not satisfiable */
210
211 lws_ranges_next(rp);
212
213 return rp->count_ranges;
214 }
215