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