xref: /aosp_15_r20/external/libwebsockets/lib/roles/http/server/ranges.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
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