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 - 2021 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 * Implements a cache backing store compatible with netscape cookies.txt format
25*1c60b9acSAndroid Build Coastguard Worker * There is one entry per "line", and fields are tab-delimited
26*1c60b9acSAndroid Build Coastguard Worker *
27*1c60b9acSAndroid Build Coastguard Worker * We need to know the format here, because while the unique cookie tag consists
28*1c60b9acSAndroid Build Coastguard Worker * of "hostname|urlpath|cookiename", that does not appear like that in the file;
29*1c60b9acSAndroid Build Coastguard Worker * we have to go parse the fields and synthesize the corresponding tag.
30*1c60b9acSAndroid Build Coastguard Worker *
31*1c60b9acSAndroid Build Coastguard Worker * We rely on all the fields except the cookie value fitting in a 256 byte
32*1c60b9acSAndroid Build Coastguard Worker * buffer, and allow eating multiple buffers to get a huge cookie values.
33*1c60b9acSAndroid Build Coastguard Worker *
34*1c60b9acSAndroid Build Coastguard Worker * Because the cookie file is a device-wide asset, although lws will change it
35*1c60b9acSAndroid Build Coastguard Worker * from the lws thread without conflict, there may be other processes that will
36*1c60b9acSAndroid Build Coastguard Worker * change it by removal and regenerating the file asynchronously. For that
37*1c60b9acSAndroid Build Coastguard Worker * reason, file handles are opened fresh each time we want to use the file, so
38*1c60b9acSAndroid Build Coastguard Worker * we always get the latest version.
39*1c60b9acSAndroid Build Coastguard Worker *
40*1c60b9acSAndroid Build Coastguard Worker * When updating the file ourselves, we use a lockfile to ensure our process
41*1c60b9acSAndroid Build Coastguard Worker * has exclusive access.
42*1c60b9acSAndroid Build Coastguard Worker *
43*1c60b9acSAndroid Build Coastguard Worker *
44*1c60b9acSAndroid Build Coastguard Worker * Tag Matching rules
45*1c60b9acSAndroid Build Coastguard Worker *
46*1c60b9acSAndroid Build Coastguard Worker * There are three kinds of tag matching rules
47*1c60b9acSAndroid Build Coastguard Worker *
48*1c60b9acSAndroid Build Coastguard Worker * 1) specific - tag strigs must be the same
49*1c60b9acSAndroid Build Coastguard Worker * 2) wilcard - tags matched using optional wildcards
50*1c60b9acSAndroid Build Coastguard Worker * 3) wildcard + lookup - wildcard, but path part matches using cookie scope rules
51*1c60b9acSAndroid Build Coastguard Worker *
52*1c60b9acSAndroid Build Coastguard Worker */
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker #include <private-lib-core.h>
55*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-misc-cache-ttl.h"
56*1c60b9acSAndroid Build Coastguard Worker
57*1c60b9acSAndroid Build Coastguard Worker typedef enum nsc_iterator_ret {
58*1c60b9acSAndroid Build Coastguard Worker NIR_CONTINUE = 0,
59*1c60b9acSAndroid Build Coastguard Worker NIR_FINISH_OK = 1,
60*1c60b9acSAndroid Build Coastguard Worker NIR_FINISH_ERROR = -1
61*1c60b9acSAndroid Build Coastguard Worker } nsc_iterator_ret_t;
62*1c60b9acSAndroid Build Coastguard Worker
63*1c60b9acSAndroid Build Coastguard Worker typedef enum cbreason {
64*1c60b9acSAndroid Build Coastguard Worker LCN_SOL = (1 << 0),
65*1c60b9acSAndroid Build Coastguard Worker LCN_EOL = (1 << 1)
66*1c60b9acSAndroid Build Coastguard Worker } cbreason_t;
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker typedef int (*nsc_cb_t)(lws_cache_nscookiejar_t *cache, void *opaque, int flags,
69*1c60b9acSAndroid Build Coastguard Worker const char *buf, size_t size);
70*1c60b9acSAndroid Build Coastguard Worker
71*1c60b9acSAndroid Build Coastguard Worker static void
72*1c60b9acSAndroid Build Coastguard Worker expiry_cb(lws_sorted_usec_list_t *sul);
73*1c60b9acSAndroid Build Coastguard Worker
74*1c60b9acSAndroid Build Coastguard Worker static int
nsc_backing_open_lock(lws_cache_nscookiejar_t * cache,int mode,const char * par)75*1c60b9acSAndroid Build Coastguard Worker nsc_backing_open_lock(lws_cache_nscookiejar_t *cache, int mode, const char *par)
76*1c60b9acSAndroid Build Coastguard Worker {
77*1c60b9acSAndroid Build Coastguard Worker int sanity = 50;
78*1c60b9acSAndroid Build Coastguard Worker char lock[128];
79*1c60b9acSAndroid Build Coastguard Worker int fd_lock, fd;
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s\n", __func__, par);
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(lock, sizeof(lock), "%s.LCK",
84*1c60b9acSAndroid Build Coastguard Worker cache->cache.info.u.nscookiejar.filepath);
85*1c60b9acSAndroid Build Coastguard Worker
86*1c60b9acSAndroid Build Coastguard Worker do {
87*1c60b9acSAndroid Build Coastguard Worker fd_lock = open(lock, LWS_O_CREAT | O_EXCL, 0600);
88*1c60b9acSAndroid Build Coastguard Worker if (fd_lock >= 0) {
89*1c60b9acSAndroid Build Coastguard Worker close(fd_lock);
90*1c60b9acSAndroid Build Coastguard Worker break;
91*1c60b9acSAndroid Build Coastguard Worker }
92*1c60b9acSAndroid Build Coastguard Worker
93*1c60b9acSAndroid Build Coastguard Worker if (!sanity--) {
94*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: unable to lock %s: errno %d\n", __func__,
95*1c60b9acSAndroid Build Coastguard Worker lock, errno);
96*1c60b9acSAndroid Build Coastguard Worker return -1;
97*1c60b9acSAndroid Build Coastguard Worker }
98*1c60b9acSAndroid Build Coastguard Worker
99*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
100*1c60b9acSAndroid Build Coastguard Worker Sleep(100);
101*1c60b9acSAndroid Build Coastguard Worker #else
102*1c60b9acSAndroid Build Coastguard Worker usleep(100000);
103*1c60b9acSAndroid Build Coastguard Worker #endif
104*1c60b9acSAndroid Build Coastguard Worker } while (1);
105*1c60b9acSAndroid Build Coastguard Worker
106*1c60b9acSAndroid Build Coastguard Worker fd = open(cache->cache.info.u.nscookiejar.filepath,
107*1c60b9acSAndroid Build Coastguard Worker LWS_O_CREAT | mode, 0600);
108*1c60b9acSAndroid Build Coastguard Worker
109*1c60b9acSAndroid Build Coastguard Worker if (fd == -1) {
110*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: unable to open or create %s\n", __func__,
111*1c60b9acSAndroid Build Coastguard Worker cache->cache.info.u.nscookiejar.filepath);
112*1c60b9acSAndroid Build Coastguard Worker unlink(lock);
113*1c60b9acSAndroid Build Coastguard Worker }
114*1c60b9acSAndroid Build Coastguard Worker
115*1c60b9acSAndroid Build Coastguard Worker return fd;
116*1c60b9acSAndroid Build Coastguard Worker }
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker static void
nsc_backing_close_unlock(lws_cache_nscookiejar_t * cache,int fd)119*1c60b9acSAndroid Build Coastguard Worker nsc_backing_close_unlock(lws_cache_nscookiejar_t *cache, int fd)
120*1c60b9acSAndroid Build Coastguard Worker {
121*1c60b9acSAndroid Build Coastguard Worker char lock[128];
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s\n", __func__);
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(lock, sizeof(lock), "%s.LCK",
126*1c60b9acSAndroid Build Coastguard Worker cache->cache.info.u.nscookiejar.filepath);
127*1c60b9acSAndroid Build Coastguard Worker if (fd >= 0)
128*1c60b9acSAndroid Build Coastguard Worker close(fd);
129*1c60b9acSAndroid Build Coastguard Worker unlink(lock);
130*1c60b9acSAndroid Build Coastguard Worker }
131*1c60b9acSAndroid Build Coastguard Worker
132*1c60b9acSAndroid Build Coastguard Worker /*
133*1c60b9acSAndroid Build Coastguard Worker * We're going to call the callback with chunks of the file with flags
134*1c60b9acSAndroid Build Coastguard Worker * indicating we're giving it the start of a line and / or giving it the end
135*1c60b9acSAndroid Build Coastguard Worker * of a line.
136*1c60b9acSAndroid Build Coastguard Worker *
137*1c60b9acSAndroid Build Coastguard Worker * It's like this because the cookie value may be huge (and to a lesser extent
138*1c60b9acSAndroid Build Coastguard Worker * the path may also be big).
139*1c60b9acSAndroid Build Coastguard Worker *
140*1c60b9acSAndroid Build Coastguard Worker * If it's the start of a line (flags on the cb has LCN_SOL), then the buffer
141*1c60b9acSAndroid Build Coastguard Worker * contains up to the first 256 chars of the line, it's enough to match with.
142*1c60b9acSAndroid Build Coastguard Worker *
143*1c60b9acSAndroid Build Coastguard Worker * We cannot hold the file open inbetweentimes, since other processes may
144*1c60b9acSAndroid Build Coastguard Worker * regenerate it, so we need to bind to a new inode. We open it with an
145*1c60b9acSAndroid Build Coastguard Worker * exclusive flock() so other processes can't replace conflicting changes
146*1c60b9acSAndroid Build Coastguard Worker * while we also write changes, without having to wait and see our changes.
147*1c60b9acSAndroid Build Coastguard Worker */
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker static int
nscookiejar_iterate(lws_cache_nscookiejar_t * cache,int fd,nsc_cb_t cb,void * opaque)150*1c60b9acSAndroid Build Coastguard Worker nscookiejar_iterate(lws_cache_nscookiejar_t *cache, int fd,
151*1c60b9acSAndroid Build Coastguard Worker nsc_cb_t cb, void *opaque)
152*1c60b9acSAndroid Build Coastguard Worker {
153*1c60b9acSAndroid Build Coastguard Worker int m = 0, n = 0, e, r = LCN_SOL, ignore = 0, ret = 0;
154*1c60b9acSAndroid Build Coastguard Worker char temp[256], eof = 0;
155*1c60b9acSAndroid Build Coastguard Worker
156*1c60b9acSAndroid Build Coastguard Worker if (lseek(fd, 0, SEEK_SET) == (off_t)-1)
157*1c60b9acSAndroid Build Coastguard Worker return -1;
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker do { /* for as many buffers in the file */
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker int n1;
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: n %d, m %d\n", __func__, n, m);
164*1c60b9acSAndroid Build Coastguard Worker
165*1c60b9acSAndroid Build Coastguard Worker read:
166*1c60b9acSAndroid Build Coastguard Worker n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n);
167*1c60b9acSAndroid Build Coastguard Worker
168*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: n1 %d\n", __func__, n1);
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker if (n1 <= 0) {
171*1c60b9acSAndroid Build Coastguard Worker eof = 1;
172*1c60b9acSAndroid Build Coastguard Worker if (m == n)
173*1c60b9acSAndroid Build Coastguard Worker continue;
174*1c60b9acSAndroid Build Coastguard Worker } else
175*1c60b9acSAndroid Build Coastguard Worker n += n1;
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Worker while (m < n) {
178*1c60b9acSAndroid Build Coastguard Worker
179*1c60b9acSAndroid Build Coastguard Worker m++;
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker if (temp[m - 1] != '\n')
182*1c60b9acSAndroid Build Coastguard Worker continue;
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker /* ie, we hit EOL */
185*1c60b9acSAndroid Build Coastguard Worker
186*1c60b9acSAndroid Build Coastguard Worker if (temp[0] == '#')
187*1c60b9acSAndroid Build Coastguard Worker /* lines starting with # are comments */
188*1c60b9acSAndroid Build Coastguard Worker e = 0;
189*1c60b9acSAndroid Build Coastguard Worker else
190*1c60b9acSAndroid Build Coastguard Worker e = cb(cache, opaque, r | LCN_EOL, temp,
191*1c60b9acSAndroid Build Coastguard Worker (size_t)m - 1);
192*1c60b9acSAndroid Build Coastguard Worker r = LCN_SOL;
193*1c60b9acSAndroid Build Coastguard Worker ignore = 0;
194*1c60b9acSAndroid Build Coastguard Worker /*
195*1c60b9acSAndroid Build Coastguard Worker * Move back remainder and prefill the gap that opened
196*1c60b9acSAndroid Build Coastguard Worker * up: we want to pass enough in the start chunk so the
197*1c60b9acSAndroid Build Coastguard Worker * cb can classify it even if it can't get all the
198*1c60b9acSAndroid Build Coastguard Worker * value part in one go
199*1c60b9acSAndroid Build Coastguard Worker */
200*1c60b9acSAndroid Build Coastguard Worker memmove(temp, temp + m, (size_t)(n - m));
201*1c60b9acSAndroid Build Coastguard Worker n -= m;
202*1c60b9acSAndroid Build Coastguard Worker m = 0;
203*1c60b9acSAndroid Build Coastguard Worker
204*1c60b9acSAndroid Build Coastguard Worker if (e) {
205*1c60b9acSAndroid Build Coastguard Worker ret = e;
206*1c60b9acSAndroid Build Coastguard Worker goto bail;
207*1c60b9acSAndroid Build Coastguard Worker }
208*1c60b9acSAndroid Build Coastguard Worker
209*1c60b9acSAndroid Build Coastguard Worker goto read;
210*1c60b9acSAndroid Build Coastguard Worker }
211*1c60b9acSAndroid Build Coastguard Worker
212*1c60b9acSAndroid Build Coastguard Worker if (m) {
213*1c60b9acSAndroid Build Coastguard Worker /* we ran out of buffer */
214*1c60b9acSAndroid Build Coastguard Worker if (ignore || (r == LCN_SOL && n && temp[0] == '#')) {
215*1c60b9acSAndroid Build Coastguard Worker e = 0;
216*1c60b9acSAndroid Build Coastguard Worker ignore = 1;
217*1c60b9acSAndroid Build Coastguard Worker } else {
218*1c60b9acSAndroid Build Coastguard Worker e = cb(cache, opaque,
219*1c60b9acSAndroid Build Coastguard Worker r | (n == m && eof ? LCN_EOL : 0),
220*1c60b9acSAndroid Build Coastguard Worker temp, (size_t)m);
221*1c60b9acSAndroid Build Coastguard Worker
222*1c60b9acSAndroid Build Coastguard Worker m = 0;
223*1c60b9acSAndroid Build Coastguard Worker n = 0;
224*1c60b9acSAndroid Build Coastguard Worker }
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker if (e) {
227*1c60b9acSAndroid Build Coastguard Worker /*
228*1c60b9acSAndroid Build Coastguard Worker * We have to call off the whole thing if any
229*1c60b9acSAndroid Build Coastguard Worker * step, eg, OOMs
230*1c60b9acSAndroid Build Coastguard Worker */
231*1c60b9acSAndroid Build Coastguard Worker ret = e;
232*1c60b9acSAndroid Build Coastguard Worker goto bail;
233*1c60b9acSAndroid Build Coastguard Worker }
234*1c60b9acSAndroid Build Coastguard Worker r = 0;
235*1c60b9acSAndroid Build Coastguard Worker }
236*1c60b9acSAndroid Build Coastguard Worker
237*1c60b9acSAndroid Build Coastguard Worker } while (!eof || n != m);
238*1c60b9acSAndroid Build Coastguard Worker
239*1c60b9acSAndroid Build Coastguard Worker ret = 0;
240*1c60b9acSAndroid Build Coastguard Worker
241*1c60b9acSAndroid Build Coastguard Worker bail:
242*1c60b9acSAndroid Build Coastguard Worker
243*1c60b9acSAndroid Build Coastguard Worker return ret;
244*1c60b9acSAndroid Build Coastguard Worker }
245*1c60b9acSAndroid Build Coastguard Worker
246*1c60b9acSAndroid Build Coastguard Worker /*
247*1c60b9acSAndroid Build Coastguard Worker * lookup() just handles wildcard resolution, it doesn't deal with moving the
248*1c60b9acSAndroid Build Coastguard Worker * hits to L1. That has to be done individually by non-wildcard names.
249*1c60b9acSAndroid Build Coastguard Worker */
250*1c60b9acSAndroid Build Coastguard Worker
251*1c60b9acSAndroid Build Coastguard Worker enum {
252*1c60b9acSAndroid Build Coastguard Worker NSC_COL_HOST = 0, /* wc idx 0 */
253*1c60b9acSAndroid Build Coastguard Worker NSC_COL_PATH = 2, /* wc idx 1 */
254*1c60b9acSAndroid Build Coastguard Worker NSC_COL_EXPIRY = 4,
255*1c60b9acSAndroid Build Coastguard Worker NSC_COL_NAME = 5, /* wc idx 2 */
256*1c60b9acSAndroid Build Coastguard Worker
257*1c60b9acSAndroid Build Coastguard Worker NSC_COL_COUNT = 6
258*1c60b9acSAndroid Build Coastguard Worker };
259*1c60b9acSAndroid Build Coastguard Worker
260*1c60b9acSAndroid Build Coastguard Worker /*
261*1c60b9acSAndroid Build Coastguard Worker * This performs the specialized wildcard that knows about cookie path match
262*1c60b9acSAndroid Build Coastguard Worker * rules.
263*1c60b9acSAndroid Build Coastguard Worker *
264*1c60b9acSAndroid Build Coastguard Worker * To defeat the lookup path matching, lie to it about idx being NSC_COL_PATH
265*1c60b9acSAndroid Build Coastguard Worker */
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker static int
nsc_match(const char * wc,size_t wc_len,const char * col,size_t col_len,int idx)268*1c60b9acSAndroid Build Coastguard Worker nsc_match(const char *wc, size_t wc_len, const char *col, size_t col_len,
269*1c60b9acSAndroid Build Coastguard Worker int idx)
270*1c60b9acSAndroid Build Coastguard Worker {
271*1c60b9acSAndroid Build Coastguard Worker size_t n = 0;
272*1c60b9acSAndroid Build Coastguard Worker
273*1c60b9acSAndroid Build Coastguard Worker if (idx != NSC_COL_PATH)
274*1c60b9acSAndroid Build Coastguard Worker return lws_strcmp_wildcard(wc, wc_len, col, col_len);
275*1c60b9acSAndroid Build Coastguard Worker
276*1c60b9acSAndroid Build Coastguard Worker /*
277*1c60b9acSAndroid Build Coastguard Worker * Cookie path match is special, if we lookup on a path like /my/path,
278*1c60b9acSAndroid Build Coastguard Worker * we must match on cookie paths for every dir level including /, so
279*1c60b9acSAndroid Build Coastguard Worker * match on /, /my, and /my/path. But we must not match on /m or
280*1c60b9acSAndroid Build Coastguard Worker * /my/pa etc. If we lookup on /, we must not match /my/path
281*1c60b9acSAndroid Build Coastguard Worker *
282*1c60b9acSAndroid Build Coastguard Worker * Let's go through wc checking at / and for every complete subpath if
283*1c60b9acSAndroid Build Coastguard Worker * it is an explicit match
284*1c60b9acSAndroid Build Coastguard Worker */
285*1c60b9acSAndroid Build Coastguard Worker
286*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(col, wc))
287*1c60b9acSAndroid Build Coastguard Worker return 0; /* exact hit */
288*1c60b9acSAndroid Build Coastguard Worker
289*1c60b9acSAndroid Build Coastguard Worker while (n <= wc_len) {
290*1c60b9acSAndroid Build Coastguard Worker if (n == wc_len || wc[n] == '/') {
291*1c60b9acSAndroid Build Coastguard Worker if (n && col_len <= n && !strncmp(wc, col, n))
292*1c60b9acSAndroid Build Coastguard Worker return 0; /* hit */
293*1c60b9acSAndroid Build Coastguard Worker
294*1c60b9acSAndroid Build Coastguard Worker if (n != wc_len && col_len <= n + 1 &&
295*1c60b9acSAndroid Build Coastguard Worker !strncmp(wc, col, n + 1)) /* check for trailing / */
296*1c60b9acSAndroid Build Coastguard Worker return 0; /* hit */
297*1c60b9acSAndroid Build Coastguard Worker }
298*1c60b9acSAndroid Build Coastguard Worker n++;
299*1c60b9acSAndroid Build Coastguard Worker }
300*1c60b9acSAndroid Build Coastguard Worker
301*1c60b9acSAndroid Build Coastguard Worker return 1; /* fail */
302*1c60b9acSAndroid Build Coastguard Worker }
303*1c60b9acSAndroid Build Coastguard Worker
304*1c60b9acSAndroid Build Coastguard Worker static const uint8_t nsc_cols[] = { NSC_COL_HOST, NSC_COL_PATH, NSC_COL_NAME };
305*1c60b9acSAndroid Build Coastguard Worker
306*1c60b9acSAndroid Build Coastguard Worker static int
lws_cache_nscookiejar_tag_match(struct lws_cache_ttl_lru * cache,const char * wc,const char * tag,char lookup)307*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_tag_match(struct lws_cache_ttl_lru *cache,
308*1c60b9acSAndroid Build Coastguard Worker const char *wc, const char *tag, char lookup)
309*1c60b9acSAndroid Build Coastguard Worker {
310*1c60b9acSAndroid Build Coastguard Worker const char *wc_end = wc + strlen(wc), *tag_end = tag + strlen(tag),
311*1c60b9acSAndroid Build Coastguard Worker *start_wc, *start_tag;
312*1c60b9acSAndroid Build Coastguard Worker int n = 0;
313*1c60b9acSAndroid Build Coastguard Worker
314*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: '%s' vs '%s'\n", __func__, wc, tag);
315*1c60b9acSAndroid Build Coastguard Worker
316*1c60b9acSAndroid Build Coastguard Worker /*
317*1c60b9acSAndroid Build Coastguard Worker * Given a well-formed host|path|name tag and a wildcard term,
318*1c60b9acSAndroid Build Coastguard Worker * make the determination if the tag matches the wildcard or not,
319*1c60b9acSAndroid Build Coastguard Worker * using lookup rules that apply at this cache level.
320*1c60b9acSAndroid Build Coastguard Worker */
321*1c60b9acSAndroid Build Coastguard Worker
322*1c60b9acSAndroid Build Coastguard Worker while (n < 3) {
323*1c60b9acSAndroid Build Coastguard Worker start_wc = wc;
324*1c60b9acSAndroid Build Coastguard Worker while (wc < wc_end && *wc != LWSCTAG_SEP)
325*1c60b9acSAndroid Build Coastguard Worker wc++;
326*1c60b9acSAndroid Build Coastguard Worker
327*1c60b9acSAndroid Build Coastguard Worker start_tag = tag;
328*1c60b9acSAndroid Build Coastguard Worker while (tag < tag_end && *tag != LWSCTAG_SEP)
329*1c60b9acSAndroid Build Coastguard Worker tag++;
330*1c60b9acSAndroid Build Coastguard Worker
331*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: '%.*s' vs '%.*s'\n", __func__,
332*1c60b9acSAndroid Build Coastguard Worker lws_ptr_diff(wc, start_wc), start_wc,
333*1c60b9acSAndroid Build Coastguard Worker lws_ptr_diff(tag, start_tag), start_tag);
334*1c60b9acSAndroid Build Coastguard Worker if (nsc_match(start_wc, lws_ptr_diff_size_t(wc, start_wc),
335*1c60b9acSAndroid Build Coastguard Worker start_tag, lws_ptr_diff_size_t(tag, start_tag),
336*1c60b9acSAndroid Build Coastguard Worker lookup ? nsc_cols[n] : NSC_COL_HOST)) {
337*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: fail\n", __func__);
338*1c60b9acSAndroid Build Coastguard Worker return 1;
339*1c60b9acSAndroid Build Coastguard Worker }
340*1c60b9acSAndroid Build Coastguard Worker
341*1c60b9acSAndroid Build Coastguard Worker if (wc < wc_end)
342*1c60b9acSAndroid Build Coastguard Worker wc++;
343*1c60b9acSAndroid Build Coastguard Worker if (tag < tag_end)
344*1c60b9acSAndroid Build Coastguard Worker tag++;
345*1c60b9acSAndroid Build Coastguard Worker
346*1c60b9acSAndroid Build Coastguard Worker n++;
347*1c60b9acSAndroid Build Coastguard Worker }
348*1c60b9acSAndroid Build Coastguard Worker
349*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: hit\n", __func__);
350*1c60b9acSAndroid Build Coastguard Worker
351*1c60b9acSAndroid Build Coastguard Worker return 0; /* match */
352*1c60b9acSAndroid Build Coastguard Worker }
353*1c60b9acSAndroid Build Coastguard Worker
354*1c60b9acSAndroid Build Coastguard Worker /*
355*1c60b9acSAndroid Build Coastguard Worker * Converts the start of a cookie file line into a tag
356*1c60b9acSAndroid Build Coastguard Worker */
357*1c60b9acSAndroid Build Coastguard Worker
358*1c60b9acSAndroid Build Coastguard Worker static int
nsc_line_to_tag(const char * buf,size_t size,char * tag,size_t max_tag,lws_usec_t * pexpiry)359*1c60b9acSAndroid Build Coastguard Worker nsc_line_to_tag(const char *buf, size_t size, char *tag, size_t max_tag,
360*1c60b9acSAndroid Build Coastguard Worker lws_usec_t *pexpiry)
361*1c60b9acSAndroid Build Coastguard Worker {
362*1c60b9acSAndroid Build Coastguard Worker int n, idx = 0, tl = 0;
363*1c60b9acSAndroid Build Coastguard Worker lws_usec_t expiry = 0;
364*1c60b9acSAndroid Build Coastguard Worker size_t bn = 0;
365*1c60b9acSAndroid Build Coastguard Worker char col[64];
366*1c60b9acSAndroid Build Coastguard Worker
367*1c60b9acSAndroid Build Coastguard Worker if (size < 3)
368*1c60b9acSAndroid Build Coastguard Worker return 1;
369*1c60b9acSAndroid Build Coastguard Worker
370*1c60b9acSAndroid Build Coastguard Worker while (bn < size && idx <= NSC_COL_NAME) {
371*1c60b9acSAndroid Build Coastguard Worker
372*1c60b9acSAndroid Build Coastguard Worker n = 0;
373*1c60b9acSAndroid Build Coastguard Worker while (bn < size && n < (int)sizeof(col) - 1 &&
374*1c60b9acSAndroid Build Coastguard Worker buf[bn] != '\t')
375*1c60b9acSAndroid Build Coastguard Worker col[n++] = buf[bn++];
376*1c60b9acSAndroid Build Coastguard Worker col[n] = '\0';
377*1c60b9acSAndroid Build Coastguard Worker if (buf[bn] == '\t')
378*1c60b9acSAndroid Build Coastguard Worker bn++;
379*1c60b9acSAndroid Build Coastguard Worker
380*1c60b9acSAndroid Build Coastguard Worker switch (idx) {
381*1c60b9acSAndroid Build Coastguard Worker case NSC_COL_EXPIRY:
382*1c60b9acSAndroid Build Coastguard Worker expiry = (lws_usec_t)((unsigned long long)atoll(col) *
383*1c60b9acSAndroid Build Coastguard Worker (lws_usec_t)LWS_US_PER_SEC);
384*1c60b9acSAndroid Build Coastguard Worker break;
385*1c60b9acSAndroid Build Coastguard Worker
386*1c60b9acSAndroid Build Coastguard Worker case NSC_COL_HOST:
387*1c60b9acSAndroid Build Coastguard Worker case NSC_COL_PATH:
388*1c60b9acSAndroid Build Coastguard Worker case NSC_COL_NAME:
389*1c60b9acSAndroid Build Coastguard Worker
390*1c60b9acSAndroid Build Coastguard Worker /*
391*1c60b9acSAndroid Build Coastguard Worker * As we match the pieces of the wildcard,
392*1c60b9acSAndroid Build Coastguard Worker * compose the matches into a specific tag
393*1c60b9acSAndroid Build Coastguard Worker */
394*1c60b9acSAndroid Build Coastguard Worker
395*1c60b9acSAndroid Build Coastguard Worker if (tl + n + 2 > (int)max_tag)
396*1c60b9acSAndroid Build Coastguard Worker return 1;
397*1c60b9acSAndroid Build Coastguard Worker if (tl)
398*1c60b9acSAndroid Build Coastguard Worker tag[tl++] = LWSCTAG_SEP;
399*1c60b9acSAndroid Build Coastguard Worker memcpy(tag + tl, col, (size_t)n);
400*1c60b9acSAndroid Build Coastguard Worker tl += n;
401*1c60b9acSAndroid Build Coastguard Worker tag[tl] = '\0';
402*1c60b9acSAndroid Build Coastguard Worker break;
403*1c60b9acSAndroid Build Coastguard Worker default:
404*1c60b9acSAndroid Build Coastguard Worker break;
405*1c60b9acSAndroid Build Coastguard Worker }
406*1c60b9acSAndroid Build Coastguard Worker
407*1c60b9acSAndroid Build Coastguard Worker idx++;
408*1c60b9acSAndroid Build Coastguard Worker }
409*1c60b9acSAndroid Build Coastguard Worker
410*1c60b9acSAndroid Build Coastguard Worker if (pexpiry)
411*1c60b9acSAndroid Build Coastguard Worker *pexpiry = expiry;
412*1c60b9acSAndroid Build Coastguard Worker
413*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %.*s: tag '%s'\n", __func__, (int)size, buf, tag);
414*1c60b9acSAndroid Build Coastguard Worker
415*1c60b9acSAndroid Build Coastguard Worker return 0;
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker
418*1c60b9acSAndroid Build Coastguard Worker struct nsc_lookup_ctx {
419*1c60b9acSAndroid Build Coastguard Worker const char *wildcard_key;
420*1c60b9acSAndroid Build Coastguard Worker lws_dll2_owner_t *results_owner;
421*1c60b9acSAndroid Build Coastguard Worker lws_cache_match_t *match; /* current match if any */
422*1c60b9acSAndroid Build Coastguard Worker size_t wklen;
423*1c60b9acSAndroid Build Coastguard Worker };
424*1c60b9acSAndroid Build Coastguard Worker
425*1c60b9acSAndroid Build Coastguard Worker
426*1c60b9acSAndroid Build Coastguard Worker static int
nsc_lookup_cb(lws_cache_nscookiejar_t * cache,void * opaque,int flags,const char * buf,size_t size)427*1c60b9acSAndroid Build Coastguard Worker nsc_lookup_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags,
428*1c60b9acSAndroid Build Coastguard Worker const char *buf, size_t size)
429*1c60b9acSAndroid Build Coastguard Worker {
430*1c60b9acSAndroid Build Coastguard Worker struct nsc_lookup_ctx *ctx = (struct nsc_lookup_ctx *)opaque;
431*1c60b9acSAndroid Build Coastguard Worker lws_usec_t expiry;
432*1c60b9acSAndroid Build Coastguard Worker char tag[200];
433*1c60b9acSAndroid Build Coastguard Worker int tl;
434*1c60b9acSAndroid Build Coastguard Worker
435*1c60b9acSAndroid Build Coastguard Worker if (!(flags & LCN_SOL)) {
436*1c60b9acSAndroid Build Coastguard Worker if (ctx->match)
437*1c60b9acSAndroid Build Coastguard Worker ctx->match->payload_size += size;
438*1c60b9acSAndroid Build Coastguard Worker
439*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
440*1c60b9acSAndroid Build Coastguard Worker }
441*1c60b9acSAndroid Build Coastguard Worker
442*1c60b9acSAndroid Build Coastguard Worker /*
443*1c60b9acSAndroid Build Coastguard Worker * There should be enough in buf to match or reject it... let's
444*1c60b9acSAndroid Build Coastguard Worker * synthesize a tag from the text "line" and then check the tags for
445*1c60b9acSAndroid Build Coastguard Worker * a match
446*1c60b9acSAndroid Build Coastguard Worker */
447*1c60b9acSAndroid Build Coastguard Worker
448*1c60b9acSAndroid Build Coastguard Worker ctx->match = NULL; /* new SOL means stop tracking payload len */
449*1c60b9acSAndroid Build Coastguard Worker
450*1c60b9acSAndroid Build Coastguard Worker if (nsc_line_to_tag(buf, size, tag, sizeof(tag), &expiry))
451*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
452*1c60b9acSAndroid Build Coastguard Worker
453*1c60b9acSAndroid Build Coastguard Worker if (lws_cache_nscookiejar_tag_match(&cache->cache,
454*1c60b9acSAndroid Build Coastguard Worker ctx->wildcard_key, tag, 1))
455*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
456*1c60b9acSAndroid Build Coastguard Worker
457*1c60b9acSAndroid Build Coastguard Worker tl = (int)strlen(tag);
458*1c60b9acSAndroid Build Coastguard Worker
459*1c60b9acSAndroid Build Coastguard Worker /*
460*1c60b9acSAndroid Build Coastguard Worker * ... it looks like a match then... create new match
461*1c60b9acSAndroid Build Coastguard Worker * object with the specific tag, and add it to the owner list
462*1c60b9acSAndroid Build Coastguard Worker */
463*1c60b9acSAndroid Build Coastguard Worker
464*1c60b9acSAndroid Build Coastguard Worker ctx->match = lws_fi(&cache->cache.info.cx->fic, "cache_lookup_oom") ? NULL :
465*1c60b9acSAndroid Build Coastguard Worker lws_malloc(sizeof(*ctx->match) + (unsigned int)tl + 1u,
466*1c60b9acSAndroid Build Coastguard Worker __func__);
467*1c60b9acSAndroid Build Coastguard Worker if (!ctx->match)
468*1c60b9acSAndroid Build Coastguard Worker /* caller of lookup will clean results list on fail */
469*1c60b9acSAndroid Build Coastguard Worker return NIR_FINISH_ERROR;
470*1c60b9acSAndroid Build Coastguard Worker
471*1c60b9acSAndroid Build Coastguard Worker ctx->match->payload_size = size;
472*1c60b9acSAndroid Build Coastguard Worker ctx->match->tag_size = (size_t)tl;
473*1c60b9acSAndroid Build Coastguard Worker ctx->match->expiry = expiry;
474*1c60b9acSAndroid Build Coastguard Worker
475*1c60b9acSAndroid Build Coastguard Worker memset(&ctx->match->list, 0, sizeof(ctx->match->list));
476*1c60b9acSAndroid Build Coastguard Worker memcpy(&ctx->match[1], tag, (size_t)tl + 1u);
477*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&ctx->match->list, ctx->results_owner);
478*1c60b9acSAndroid Build Coastguard Worker
479*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
480*1c60b9acSAndroid Build Coastguard Worker }
481*1c60b9acSAndroid Build Coastguard Worker
482*1c60b9acSAndroid Build Coastguard Worker static int
lws_cache_nscookiejar_lookup(struct lws_cache_ttl_lru * _c,const char * wildcard_key,lws_dll2_owner_t * results_owner)483*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_lookup(struct lws_cache_ttl_lru *_c,
484*1c60b9acSAndroid Build Coastguard Worker const char *wildcard_key,
485*1c60b9acSAndroid Build Coastguard Worker lws_dll2_owner_t *results_owner)
486*1c60b9acSAndroid Build Coastguard Worker {
487*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c;
488*1c60b9acSAndroid Build Coastguard Worker struct nsc_lookup_ctx ctx;
489*1c60b9acSAndroid Build Coastguard Worker int ret, fd;
490*1c60b9acSAndroid Build Coastguard Worker
491*1c60b9acSAndroid Build Coastguard Worker fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__);
492*1c60b9acSAndroid Build Coastguard Worker if (fd < 0)
493*1c60b9acSAndroid Build Coastguard Worker return 1;
494*1c60b9acSAndroid Build Coastguard Worker
495*1c60b9acSAndroid Build Coastguard Worker ctx.wildcard_key = wildcard_key;
496*1c60b9acSAndroid Build Coastguard Worker ctx.results_owner = results_owner;
497*1c60b9acSAndroid Build Coastguard Worker ctx.wklen = strlen(wildcard_key);
498*1c60b9acSAndroid Build Coastguard Worker ctx.match = 0;
499*1c60b9acSAndroid Build Coastguard Worker
500*1c60b9acSAndroid Build Coastguard Worker ret = nscookiejar_iterate(cache, fd, nsc_lookup_cb, &ctx);
501*1c60b9acSAndroid Build Coastguard Worker /*
502*1c60b9acSAndroid Build Coastguard Worker * The cb can fail, eg, with OOM, making the whole lookup
503*1c60b9acSAndroid Build Coastguard Worker * invalid and returning fail. Caller will clean
504*1c60b9acSAndroid Build Coastguard Worker * results_owner on fail.
505*1c60b9acSAndroid Build Coastguard Worker */
506*1c60b9acSAndroid Build Coastguard Worker nsc_backing_close_unlock(cache, fd);
507*1c60b9acSAndroid Build Coastguard Worker
508*1c60b9acSAndroid Build Coastguard Worker return ret == NIR_FINISH_ERROR;
509*1c60b9acSAndroid Build Coastguard Worker }
510*1c60b9acSAndroid Build Coastguard Worker
511*1c60b9acSAndroid Build Coastguard Worker /*
512*1c60b9acSAndroid Build Coastguard Worker * It's pretty horrible having to implement add or remove individual items by
513*1c60b9acSAndroid Build Coastguard Worker * file regeneration, but if we don't want to keep it all in heap, and we want
514*1c60b9acSAndroid Build Coastguard Worker * this cookie jar format, that is what we are into.
515*1c60b9acSAndroid Build Coastguard Worker *
516*1c60b9acSAndroid Build Coastguard Worker * Allow to optionally add a "line", optionally wildcard delete tags, and always
517*1c60b9acSAndroid Build Coastguard Worker * delete expired entries.
518*1c60b9acSAndroid Build Coastguard Worker *
519*1c60b9acSAndroid Build Coastguard Worker * Although we can rely on the lws thread to be doing this, multiple processes
520*1c60b9acSAndroid Build Coastguard Worker * may be using the cookie jar and can tread on each other. So we use flock()
521*1c60b9acSAndroid Build Coastguard Worker * (linux only) to get exclusive access while we are processing this.
522*1c60b9acSAndroid Build Coastguard Worker *
523*1c60b9acSAndroid Build Coastguard Worker * We leave the existing file alone and generate a new one alongside it, with a
524*1c60b9acSAndroid Build Coastguard Worker * fixed name.tmp format so it can't leak, if that went OK then we unlink the
525*1c60b9acSAndroid Build Coastguard Worker * old and rename the new.
526*1c60b9acSAndroid Build Coastguard Worker */
527*1c60b9acSAndroid Build Coastguard Worker
528*1c60b9acSAndroid Build Coastguard Worker struct nsc_regen_ctx {
529*1c60b9acSAndroid Build Coastguard Worker const char *wildcard_key_delete;
530*1c60b9acSAndroid Build Coastguard Worker const void *add_data;
531*1c60b9acSAndroid Build Coastguard Worker lws_usec_t curr;
532*1c60b9acSAndroid Build Coastguard Worker size_t add_size;
533*1c60b9acSAndroid Build Coastguard Worker int fdt;
534*1c60b9acSAndroid Build Coastguard Worker char drop;
535*1c60b9acSAndroid Build Coastguard Worker };
536*1c60b9acSAndroid Build Coastguard Worker
537*1c60b9acSAndroid Build Coastguard Worker /* only used by nsc_regen() */
538*1c60b9acSAndroid Build Coastguard Worker
539*1c60b9acSAndroid Build Coastguard Worker static int
nsc_regen_cb(lws_cache_nscookiejar_t * cache,void * opaque,int flags,const char * buf,size_t size)540*1c60b9acSAndroid Build Coastguard Worker nsc_regen_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags,
541*1c60b9acSAndroid Build Coastguard Worker const char *buf, size_t size)
542*1c60b9acSAndroid Build Coastguard Worker {
543*1c60b9acSAndroid Build Coastguard Worker struct nsc_regen_ctx *ctx = (struct nsc_regen_ctx *)opaque;
544*1c60b9acSAndroid Build Coastguard Worker char tag[256];
545*1c60b9acSAndroid Build Coastguard Worker lws_usec_t expiry;
546*1c60b9acSAndroid Build Coastguard Worker
547*1c60b9acSAndroid Build Coastguard Worker if (flags & LCN_SOL) {
548*1c60b9acSAndroid Build Coastguard Worker
549*1c60b9acSAndroid Build Coastguard Worker ctx->drop = 0;
550*1c60b9acSAndroid Build Coastguard Worker
551*1c60b9acSAndroid Build Coastguard Worker if (nsc_line_to_tag(buf, size, tag, sizeof(tag), &expiry))
552*1c60b9acSAndroid Build Coastguard Worker /* filter it out if it is unparseable */
553*1c60b9acSAndroid Build Coastguard Worker goto drop;
554*1c60b9acSAndroid Build Coastguard Worker
555*1c60b9acSAndroid Build Coastguard Worker /* routinely track the earliest expiry */
556*1c60b9acSAndroid Build Coastguard Worker
557*1c60b9acSAndroid Build Coastguard Worker if (!cache->earliest_expiry ||
558*1c60b9acSAndroid Build Coastguard Worker (expiry && cache->earliest_expiry > expiry))
559*1c60b9acSAndroid Build Coastguard Worker cache->earliest_expiry = expiry;
560*1c60b9acSAndroid Build Coastguard Worker
561*1c60b9acSAndroid Build Coastguard Worker if (expiry && expiry < ctx->curr)
562*1c60b9acSAndroid Build Coastguard Worker /* routinely strip anything beyond its expiry */
563*1c60b9acSAndroid Build Coastguard Worker goto drop;
564*1c60b9acSAndroid Build Coastguard Worker
565*1c60b9acSAndroid Build Coastguard Worker if (ctx->wildcard_key_delete)
566*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: %s vs %s\n", __func__,
567*1c60b9acSAndroid Build Coastguard Worker tag, ctx->wildcard_key_delete);
568*1c60b9acSAndroid Build Coastguard Worker if (ctx->wildcard_key_delete &&
569*1c60b9acSAndroid Build Coastguard Worker !lws_cache_nscookiejar_tag_match(&cache->cache,
570*1c60b9acSAndroid Build Coastguard Worker ctx->wildcard_key_delete,
571*1c60b9acSAndroid Build Coastguard Worker tag, 0)) {
572*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: %s matches wc delete %s\n", __func__,
573*1c60b9acSAndroid Build Coastguard Worker tag, ctx->wildcard_key_delete);
574*1c60b9acSAndroid Build Coastguard Worker goto drop;
575*1c60b9acSAndroid Build Coastguard Worker }
576*1c60b9acSAndroid Build Coastguard Worker }
577*1c60b9acSAndroid Build Coastguard Worker
578*1c60b9acSAndroid Build Coastguard Worker if (ctx->drop)
579*1c60b9acSAndroid Build Coastguard Worker return 0;
580*1c60b9acSAndroid Build Coastguard Worker
581*1c60b9acSAndroid Build Coastguard Worker cache->cache.current_footprint += (uint64_t)size;
582*1c60b9acSAndroid Build Coastguard Worker
583*1c60b9acSAndroid Build Coastguard Worker if (write(ctx->fdt, buf, /*msvc*/(unsigned int)size) != (ssize_t)size)
584*1c60b9acSAndroid Build Coastguard Worker return NIR_FINISH_ERROR;
585*1c60b9acSAndroid Build Coastguard Worker
586*1c60b9acSAndroid Build Coastguard Worker if (flags & LCN_EOL)
587*1c60b9acSAndroid Build Coastguard Worker if ((size_t)write(ctx->fdt, "\n", 1) != 1)
588*1c60b9acSAndroid Build Coastguard Worker return NIR_FINISH_ERROR;
589*1c60b9acSAndroid Build Coastguard Worker
590*1c60b9acSAndroid Build Coastguard Worker return 0;
591*1c60b9acSAndroid Build Coastguard Worker
592*1c60b9acSAndroid Build Coastguard Worker drop:
593*1c60b9acSAndroid Build Coastguard Worker ctx->drop = 1;
594*1c60b9acSAndroid Build Coastguard Worker
595*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
596*1c60b9acSAndroid Build Coastguard Worker }
597*1c60b9acSAndroid Build Coastguard Worker
598*1c60b9acSAndroid Build Coastguard Worker static int
nsc_regen(lws_cache_nscookiejar_t * cache,const char * wc_delete,const void * pay,size_t pay_size)599*1c60b9acSAndroid Build Coastguard Worker nsc_regen(lws_cache_nscookiejar_t *cache, const char *wc_delete,
600*1c60b9acSAndroid Build Coastguard Worker const void *pay, size_t pay_size)
601*1c60b9acSAndroid Build Coastguard Worker {
602*1c60b9acSAndroid Build Coastguard Worker struct nsc_regen_ctx ctx;
603*1c60b9acSAndroid Build Coastguard Worker char filepath[128];
604*1c60b9acSAndroid Build Coastguard Worker int fd, ret = 1;
605*1c60b9acSAndroid Build Coastguard Worker
606*1c60b9acSAndroid Build Coastguard Worker fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__);
607*1c60b9acSAndroid Build Coastguard Worker if (fd < 0)
608*1c60b9acSAndroid Build Coastguard Worker return 1;
609*1c60b9acSAndroid Build Coastguard Worker
610*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(filepath, sizeof(filepath), "%s.tmp",
611*1c60b9acSAndroid Build Coastguard Worker cache->cache.info.u.nscookiejar.filepath);
612*1c60b9acSAndroid Build Coastguard Worker unlink(filepath);
613*1c60b9acSAndroid Build Coastguard Worker
614*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&cache->cache.info.cx->fic, "cache_regen_temp_open"))
615*1c60b9acSAndroid Build Coastguard Worker goto bail;
616*1c60b9acSAndroid Build Coastguard Worker
617*1c60b9acSAndroid Build Coastguard Worker ctx.fdt = open(filepath, LWS_O_CREAT | LWS_O_WRONLY, 0600);
618*1c60b9acSAndroid Build Coastguard Worker if (ctx.fdt < 0)
619*1c60b9acSAndroid Build Coastguard Worker goto bail;
620*1c60b9acSAndroid Build Coastguard Worker
621*1c60b9acSAndroid Build Coastguard Worker /* magic header */
622*1c60b9acSAndroid Build Coastguard Worker
623*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&cache->cache.info.cx->fic, "cache_regen_temp_write") ||
624*1c60b9acSAndroid Build Coastguard Worker /* other consumers insist to see this at start of cookie jar */
625*1c60b9acSAndroid Build Coastguard Worker write(ctx.fdt, "# Netscape HTTP Cookie File\n", 28) != 28)
626*1c60b9acSAndroid Build Coastguard Worker goto bail1;
627*1c60b9acSAndroid Build Coastguard Worker
628*1c60b9acSAndroid Build Coastguard Worker /* if we are adding something, put it first */
629*1c60b9acSAndroid Build Coastguard Worker
630*1c60b9acSAndroid Build Coastguard Worker if (pay &&
631*1c60b9acSAndroid Build Coastguard Worker write(ctx.fdt, pay, /*msvc*/(unsigned int)pay_size) !=
632*1c60b9acSAndroid Build Coastguard Worker (ssize_t)pay_size)
633*1c60b9acSAndroid Build Coastguard Worker goto bail1;
634*1c60b9acSAndroid Build Coastguard Worker if (pay && write(ctx.fdt, "\n", 1u) != (ssize_t)1)
635*1c60b9acSAndroid Build Coastguard Worker goto bail1;
636*1c60b9acSAndroid Build Coastguard Worker
637*1c60b9acSAndroid Build Coastguard Worker cache->cache.current_footprint = 0;
638*1c60b9acSAndroid Build Coastguard Worker
639*1c60b9acSAndroid Build Coastguard Worker ctx.wildcard_key_delete = wc_delete;
640*1c60b9acSAndroid Build Coastguard Worker ctx.add_data = pay;
641*1c60b9acSAndroid Build Coastguard Worker ctx.add_size = pay_size;
642*1c60b9acSAndroid Build Coastguard Worker ctx.curr = lws_now_usecs();
643*1c60b9acSAndroid Build Coastguard Worker ctx.drop = 0;
644*1c60b9acSAndroid Build Coastguard Worker
645*1c60b9acSAndroid Build Coastguard Worker cache->earliest_expiry = 0;
646*1c60b9acSAndroid Build Coastguard Worker
647*1c60b9acSAndroid Build Coastguard Worker if (lws_fi(&cache->cache.info.cx->fic, "cache_regen_iter_fail") ||
648*1c60b9acSAndroid Build Coastguard Worker nscookiejar_iterate(cache, fd, nsc_regen_cb, &ctx))
649*1c60b9acSAndroid Build Coastguard Worker goto bail1;
650*1c60b9acSAndroid Build Coastguard Worker
651*1c60b9acSAndroid Build Coastguard Worker close(ctx.fdt);
652*1c60b9acSAndroid Build Coastguard Worker ctx.fdt = -1;
653*1c60b9acSAndroid Build Coastguard Worker
654*1c60b9acSAndroid Build Coastguard Worker if (unlink(cache->cache.info.u.nscookiejar.filepath) == -1)
655*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: unlink %s failed\n", __func__,
656*1c60b9acSAndroid Build Coastguard Worker cache->cache.info.u.nscookiejar.filepath);
657*1c60b9acSAndroid Build Coastguard Worker if (rename(filepath, cache->cache.info.u.nscookiejar.filepath) == -1)
658*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: rename %s failed\n", __func__,
659*1c60b9acSAndroid Build Coastguard Worker cache->cache.info.u.nscookiejar.filepath);
660*1c60b9acSAndroid Build Coastguard Worker
661*1c60b9acSAndroid Build Coastguard Worker if (cache->earliest_expiry)
662*1c60b9acSAndroid Build Coastguard Worker lws_cache_schedule(&cache->cache, expiry_cb,
663*1c60b9acSAndroid Build Coastguard Worker cache->earliest_expiry);
664*1c60b9acSAndroid Build Coastguard Worker
665*1c60b9acSAndroid Build Coastguard Worker ret = 0;
666*1c60b9acSAndroid Build Coastguard Worker goto bail;
667*1c60b9acSAndroid Build Coastguard Worker
668*1c60b9acSAndroid Build Coastguard Worker bail1:
669*1c60b9acSAndroid Build Coastguard Worker if (ctx.fdt >= 0)
670*1c60b9acSAndroid Build Coastguard Worker close(ctx.fdt);
671*1c60b9acSAndroid Build Coastguard Worker bail:
672*1c60b9acSAndroid Build Coastguard Worker unlink(filepath);
673*1c60b9acSAndroid Build Coastguard Worker
674*1c60b9acSAndroid Build Coastguard Worker nsc_backing_close_unlock(cache, fd);
675*1c60b9acSAndroid Build Coastguard Worker
676*1c60b9acSAndroid Build Coastguard Worker return ret;
677*1c60b9acSAndroid Build Coastguard Worker }
678*1c60b9acSAndroid Build Coastguard Worker
679*1c60b9acSAndroid Build Coastguard Worker static void
expiry_cb(lws_sorted_usec_list_t * sul)680*1c60b9acSAndroid Build Coastguard Worker expiry_cb(lws_sorted_usec_list_t *sul)
681*1c60b9acSAndroid Build Coastguard Worker {
682*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = lws_container_of(sul,
683*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t, cache.sul);
684*1c60b9acSAndroid Build Coastguard Worker
685*1c60b9acSAndroid Build Coastguard Worker /*
686*1c60b9acSAndroid Build Coastguard Worker * regen the cookie jar without changes, so expired are removed and
687*1c60b9acSAndroid Build Coastguard Worker * new earliest expired computed
688*1c60b9acSAndroid Build Coastguard Worker */
689*1c60b9acSAndroid Build Coastguard Worker if (nsc_regen(cache, NULL, NULL, 0))
690*1c60b9acSAndroid Build Coastguard Worker return;
691*1c60b9acSAndroid Build Coastguard Worker
692*1c60b9acSAndroid Build Coastguard Worker if (cache->earliest_expiry)
693*1c60b9acSAndroid Build Coastguard Worker lws_cache_schedule(&cache->cache, expiry_cb,
694*1c60b9acSAndroid Build Coastguard Worker cache->earliest_expiry);
695*1c60b9acSAndroid Build Coastguard Worker }
696*1c60b9acSAndroid Build Coastguard Worker
697*1c60b9acSAndroid Build Coastguard Worker
698*1c60b9acSAndroid Build Coastguard Worker /* specific_key and expiry are ignored, since it must be encoded in payload */
699*1c60b9acSAndroid Build Coastguard Worker
700*1c60b9acSAndroid Build Coastguard Worker static int
lws_cache_nscookiejar_write(struct lws_cache_ttl_lru * _c,const char * specific_key,const uint8_t * source,size_t size,lws_usec_t expiry,void ** ppvoid)701*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_write(struct lws_cache_ttl_lru *_c,
702*1c60b9acSAndroid Build Coastguard Worker const char *specific_key, const uint8_t *source,
703*1c60b9acSAndroid Build Coastguard Worker size_t size, lws_usec_t expiry, void **ppvoid)
704*1c60b9acSAndroid Build Coastguard Worker {
705*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c;
706*1c60b9acSAndroid Build Coastguard Worker char tag[128];
707*1c60b9acSAndroid Build Coastguard Worker
708*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: %s: len %d\n", __func__, _c->info.name, (int)size);
709*1c60b9acSAndroid Build Coastguard Worker
710*1c60b9acSAndroid Build Coastguard Worker assert(source);
711*1c60b9acSAndroid Build Coastguard Worker
712*1c60b9acSAndroid Build Coastguard Worker if (nsc_line_to_tag((const char *)source, size, tag, sizeof(tag), NULL))
713*1c60b9acSAndroid Build Coastguard Worker return 1;
714*1c60b9acSAndroid Build Coastguard Worker
715*1c60b9acSAndroid Build Coastguard Worker if (ppvoid)
716*1c60b9acSAndroid Build Coastguard Worker *ppvoid = NULL;
717*1c60b9acSAndroid Build Coastguard Worker
718*1c60b9acSAndroid Build Coastguard Worker if (nsc_regen(cache, tag, source, size)) {
719*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: regen failed\n", __func__);
720*1c60b9acSAndroid Build Coastguard Worker
721*1c60b9acSAndroid Build Coastguard Worker return 1;
722*1c60b9acSAndroid Build Coastguard Worker }
723*1c60b9acSAndroid Build Coastguard Worker
724*1c60b9acSAndroid Build Coastguard Worker return 0;
725*1c60b9acSAndroid Build Coastguard Worker }
726*1c60b9acSAndroid Build Coastguard Worker
727*1c60b9acSAndroid Build Coastguard Worker struct nsc_get_ctx {
728*1c60b9acSAndroid Build Coastguard Worker struct lws_buflist *buflist;
729*1c60b9acSAndroid Build Coastguard Worker const char *specific_key;
730*1c60b9acSAndroid Build Coastguard Worker const void **pdata;
731*1c60b9acSAndroid Build Coastguard Worker size_t *psize;
732*1c60b9acSAndroid Build Coastguard Worker lws_cache_ttl_lru_t *l1;
733*1c60b9acSAndroid Build Coastguard Worker lws_usec_t expiry;
734*1c60b9acSAndroid Build Coastguard Worker };
735*1c60b9acSAndroid Build Coastguard Worker
736*1c60b9acSAndroid Build Coastguard Worker /*
737*1c60b9acSAndroid Build Coastguard Worker * We're looking for a specific key, if found, we want to make an entry for it
738*1c60b9acSAndroid Build Coastguard Worker * in L1 and return information about that
739*1c60b9acSAndroid Build Coastguard Worker */
740*1c60b9acSAndroid Build Coastguard Worker
741*1c60b9acSAndroid Build Coastguard Worker static int
nsc_get_cb(lws_cache_nscookiejar_t * cache,void * opaque,int flags,const char * buf,size_t size)742*1c60b9acSAndroid Build Coastguard Worker nsc_get_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags,
743*1c60b9acSAndroid Build Coastguard Worker const char *buf, size_t size)
744*1c60b9acSAndroid Build Coastguard Worker {
745*1c60b9acSAndroid Build Coastguard Worker struct nsc_get_ctx *ctx = (struct nsc_get_ctx *)opaque;
746*1c60b9acSAndroid Build Coastguard Worker char tag[200];
747*1c60b9acSAndroid Build Coastguard Worker uint8_t *q;
748*1c60b9acSAndroid Build Coastguard Worker
749*1c60b9acSAndroid Build Coastguard Worker if (ctx->buflist)
750*1c60b9acSAndroid Build Coastguard Worker goto collect;
751*1c60b9acSAndroid Build Coastguard Worker
752*1c60b9acSAndroid Build Coastguard Worker if (!(flags & LCN_SOL))
753*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
754*1c60b9acSAndroid Build Coastguard Worker
755*1c60b9acSAndroid Build Coastguard Worker if (nsc_line_to_tag(buf, size, tag, sizeof(tag), &ctx->expiry)) {
756*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: can't get tag\n", __func__);
757*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
758*1c60b9acSAndroid Build Coastguard Worker }
759*1c60b9acSAndroid Build Coastguard Worker
760*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: %s %s\n", __func__, ctx->specific_key, tag);
761*1c60b9acSAndroid Build Coastguard Worker
762*1c60b9acSAndroid Build Coastguard Worker if (strcmp(ctx->specific_key, tag)) {
763*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: no match\n", __func__);
764*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
765*1c60b9acSAndroid Build Coastguard Worker }
766*1c60b9acSAndroid Build Coastguard Worker
767*1c60b9acSAndroid Build Coastguard Worker /* it's a match */
768*1c60b9acSAndroid Build Coastguard Worker
769*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: IS match\n", __func__);
770*1c60b9acSAndroid Build Coastguard Worker
771*1c60b9acSAndroid Build Coastguard Worker if (!(flags & LCN_EOL))
772*1c60b9acSAndroid Build Coastguard Worker goto collect;
773*1c60b9acSAndroid Build Coastguard Worker
774*1c60b9acSAndroid Build Coastguard Worker /* it all fit in the buffer, let's create it in L1 now */
775*1c60b9acSAndroid Build Coastguard Worker
776*1c60b9acSAndroid Build Coastguard Worker *ctx->psize = size;
777*1c60b9acSAndroid Build Coastguard Worker if (ctx->l1->info.ops->write(ctx->l1,
778*1c60b9acSAndroid Build Coastguard Worker ctx->specific_key, (const uint8_t *)buf,
779*1c60b9acSAndroid Build Coastguard Worker size, ctx->expiry, (void **)ctx->pdata))
780*1c60b9acSAndroid Build Coastguard Worker return NIR_FINISH_ERROR;
781*1c60b9acSAndroid Build Coastguard Worker
782*1c60b9acSAndroid Build Coastguard Worker return NIR_FINISH_OK;
783*1c60b9acSAndroid Build Coastguard Worker
784*1c60b9acSAndroid Build Coastguard Worker collect:
785*1c60b9acSAndroid Build Coastguard Worker /*
786*1c60b9acSAndroid Build Coastguard Worker * it's bigger than one buffer-load, we have to stash what we're getting
787*1c60b9acSAndroid Build Coastguard Worker * on a buflist and create it when we have it all
788*1c60b9acSAndroid Build Coastguard Worker */
789*1c60b9acSAndroid Build Coastguard Worker
790*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_append_segment(&ctx->buflist, (const uint8_t *)buf,
791*1c60b9acSAndroid Build Coastguard Worker size))
792*1c60b9acSAndroid Build Coastguard Worker goto cleanup;
793*1c60b9acSAndroid Build Coastguard Worker
794*1c60b9acSAndroid Build Coastguard Worker if (!(flags & LCN_EOL))
795*1c60b9acSAndroid Build Coastguard Worker return NIR_CONTINUE;
796*1c60b9acSAndroid Build Coastguard Worker
797*1c60b9acSAndroid Build Coastguard Worker /* we have all the payload, create the L1 entry without payload yet */
798*1c60b9acSAndroid Build Coastguard Worker
799*1c60b9acSAndroid Build Coastguard Worker *ctx->psize = size;
800*1c60b9acSAndroid Build Coastguard Worker if (ctx->l1->info.ops->write(ctx->l1, ctx->specific_key, NULL,
801*1c60b9acSAndroid Build Coastguard Worker lws_buflist_total_len(&ctx->buflist),
802*1c60b9acSAndroid Build Coastguard Worker ctx->expiry, (void **)&q))
803*1c60b9acSAndroid Build Coastguard Worker goto cleanup;
804*1c60b9acSAndroid Build Coastguard Worker *ctx->pdata = q;
805*1c60b9acSAndroid Build Coastguard Worker
806*1c60b9acSAndroid Build Coastguard Worker /* dump the buflist into the L1 cache entry */
807*1c60b9acSAndroid Build Coastguard Worker
808*1c60b9acSAndroid Build Coastguard Worker do {
809*1c60b9acSAndroid Build Coastguard Worker uint8_t *p;
810*1c60b9acSAndroid Build Coastguard Worker size_t len = lws_buflist_next_segment_len(&ctx->buflist, &p);
811*1c60b9acSAndroid Build Coastguard Worker
812*1c60b9acSAndroid Build Coastguard Worker memcpy(q, p, len);
813*1c60b9acSAndroid Build Coastguard Worker q += len;
814*1c60b9acSAndroid Build Coastguard Worker
815*1c60b9acSAndroid Build Coastguard Worker lws_buflist_use_segment(&ctx->buflist, len);
816*1c60b9acSAndroid Build Coastguard Worker } while (ctx->buflist);
817*1c60b9acSAndroid Build Coastguard Worker
818*1c60b9acSAndroid Build Coastguard Worker return NIR_FINISH_OK;
819*1c60b9acSAndroid Build Coastguard Worker
820*1c60b9acSAndroid Build Coastguard Worker cleanup:
821*1c60b9acSAndroid Build Coastguard Worker lws_buflist_destroy_all_segments(&ctx->buflist);
822*1c60b9acSAndroid Build Coastguard Worker
823*1c60b9acSAndroid Build Coastguard Worker return NIR_FINISH_ERROR;
824*1c60b9acSAndroid Build Coastguard Worker }
825*1c60b9acSAndroid Build Coastguard Worker
826*1c60b9acSAndroid Build Coastguard Worker static int
lws_cache_nscookiejar_get(struct lws_cache_ttl_lru * _c,const char * specific_key,const void ** pdata,size_t * psize)827*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_get(struct lws_cache_ttl_lru *_c,
828*1c60b9acSAndroid Build Coastguard Worker const char *specific_key, const void **pdata,
829*1c60b9acSAndroid Build Coastguard Worker size_t *psize)
830*1c60b9acSAndroid Build Coastguard Worker {
831*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c;
832*1c60b9acSAndroid Build Coastguard Worker struct nsc_get_ctx ctx;
833*1c60b9acSAndroid Build Coastguard Worker int ret, fd;
834*1c60b9acSAndroid Build Coastguard Worker
835*1c60b9acSAndroid Build Coastguard Worker fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__);
836*1c60b9acSAndroid Build Coastguard Worker if (fd < 0)
837*1c60b9acSAndroid Build Coastguard Worker return 1;
838*1c60b9acSAndroid Build Coastguard Worker
839*1c60b9acSAndroid Build Coastguard Worker /* get a pointer to l1 */
840*1c60b9acSAndroid Build Coastguard Worker ctx.l1 = &cache->cache;
841*1c60b9acSAndroid Build Coastguard Worker while (ctx.l1->child)
842*1c60b9acSAndroid Build Coastguard Worker ctx.l1 = ctx.l1->child;
843*1c60b9acSAndroid Build Coastguard Worker
844*1c60b9acSAndroid Build Coastguard Worker ctx.pdata = pdata;
845*1c60b9acSAndroid Build Coastguard Worker ctx.psize = psize;
846*1c60b9acSAndroid Build Coastguard Worker ctx.specific_key = specific_key;
847*1c60b9acSAndroid Build Coastguard Worker ctx.buflist = NULL;
848*1c60b9acSAndroid Build Coastguard Worker ctx.expiry = 0;
849*1c60b9acSAndroid Build Coastguard Worker
850*1c60b9acSAndroid Build Coastguard Worker ret = nscookiejar_iterate(cache, fd, nsc_get_cb, &ctx);
851*1c60b9acSAndroid Build Coastguard Worker
852*1c60b9acSAndroid Build Coastguard Worker nsc_backing_close_unlock(cache, fd);
853*1c60b9acSAndroid Build Coastguard Worker
854*1c60b9acSAndroid Build Coastguard Worker return ret != NIR_FINISH_OK;
855*1c60b9acSAndroid Build Coastguard Worker }
856*1c60b9acSAndroid Build Coastguard Worker
857*1c60b9acSAndroid Build Coastguard Worker static int
lws_cache_nscookiejar_invalidate(struct lws_cache_ttl_lru * _c,const char * wc_key)858*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_invalidate(struct lws_cache_ttl_lru *_c,
859*1c60b9acSAndroid Build Coastguard Worker const char *wc_key)
860*1c60b9acSAndroid Build Coastguard Worker {
861*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c;
862*1c60b9acSAndroid Build Coastguard Worker
863*1c60b9acSAndroid Build Coastguard Worker return nsc_regen(cache, wc_key, NULL, 0);
864*1c60b9acSAndroid Build Coastguard Worker }
865*1c60b9acSAndroid Build Coastguard Worker
866*1c60b9acSAndroid Build Coastguard Worker static struct lws_cache_ttl_lru *
lws_cache_nscookiejar_create(const struct lws_cache_creation_info * info)867*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_create(const struct lws_cache_creation_info *info)
868*1c60b9acSAndroid Build Coastguard Worker {
869*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache;
870*1c60b9acSAndroid Build Coastguard Worker
871*1c60b9acSAndroid Build Coastguard Worker cache = lws_fi(&info->cx->fic, "cache_createfail") ? NULL :
872*1c60b9acSAndroid Build Coastguard Worker lws_zalloc(sizeof(*cache), __func__);
873*1c60b9acSAndroid Build Coastguard Worker if (!cache)
874*1c60b9acSAndroid Build Coastguard Worker return NULL;
875*1c60b9acSAndroid Build Coastguard Worker
876*1c60b9acSAndroid Build Coastguard Worker cache->cache.info = *info;
877*1c60b9acSAndroid Build Coastguard Worker
878*1c60b9acSAndroid Build Coastguard Worker /*
879*1c60b9acSAndroid Build Coastguard Worker * We need to scan the file, if it exists, and find the earliest
880*1c60b9acSAndroid Build Coastguard Worker * expiry while cleaning out any expired entries
881*1c60b9acSAndroid Build Coastguard Worker */
882*1c60b9acSAndroid Build Coastguard Worker expiry_cb(&cache->cache.sul);
883*1c60b9acSAndroid Build Coastguard Worker
884*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: create %s\n", __func__, info->name ? info->name : "?");
885*1c60b9acSAndroid Build Coastguard Worker
886*1c60b9acSAndroid Build Coastguard Worker return (struct lws_cache_ttl_lru *)cache;
887*1c60b9acSAndroid Build Coastguard Worker }
888*1c60b9acSAndroid Build Coastguard Worker
889*1c60b9acSAndroid Build Coastguard Worker static int
lws_cache_nscookiejar_expunge(struct lws_cache_ttl_lru * _c)890*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_expunge(struct lws_cache_ttl_lru *_c)
891*1c60b9acSAndroid Build Coastguard Worker {
892*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c;
893*1c60b9acSAndroid Build Coastguard Worker int r;
894*1c60b9acSAndroid Build Coastguard Worker
895*1c60b9acSAndroid Build Coastguard Worker if (!cache)
896*1c60b9acSAndroid Build Coastguard Worker return 0;
897*1c60b9acSAndroid Build Coastguard Worker
898*1c60b9acSAndroid Build Coastguard Worker r = unlink(cache->cache.info.u.nscookiejar.filepath);
899*1c60b9acSAndroid Build Coastguard Worker if (r)
900*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: failed to unlink %s\n", __func__,
901*1c60b9acSAndroid Build Coastguard Worker cache->cache.info.u.nscookiejar.filepath);
902*1c60b9acSAndroid Build Coastguard Worker
903*1c60b9acSAndroid Build Coastguard Worker return r;
904*1c60b9acSAndroid Build Coastguard Worker }
905*1c60b9acSAndroid Build Coastguard Worker
906*1c60b9acSAndroid Build Coastguard Worker static void
lws_cache_nscookiejar_destroy(struct lws_cache_ttl_lru ** _pc)907*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_destroy(struct lws_cache_ttl_lru **_pc)
908*1c60b9acSAndroid Build Coastguard Worker {
909*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)*_pc;
910*1c60b9acSAndroid Build Coastguard Worker
911*1c60b9acSAndroid Build Coastguard Worker if (!cache)
912*1c60b9acSAndroid Build Coastguard Worker return;
913*1c60b9acSAndroid Build Coastguard Worker
914*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&cache->cache.sul);
915*1c60b9acSAndroid Build Coastguard Worker
916*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(*_pc);
917*1c60b9acSAndroid Build Coastguard Worker }
918*1c60b9acSAndroid Build Coastguard Worker
919*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
920*1c60b9acSAndroid Build Coastguard Worker
921*1c60b9acSAndroid Build Coastguard Worker static int
nsc_dump_cb(lws_cache_nscookiejar_t * cache,void * opaque,int flags,const char * buf,size_t size)922*1c60b9acSAndroid Build Coastguard Worker nsc_dump_cb(lws_cache_nscookiejar_t *cache, void *opaque, int flags,
923*1c60b9acSAndroid Build Coastguard Worker const char *buf, size_t size)
924*1c60b9acSAndroid Build Coastguard Worker {
925*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_cache(buf, size);
926*1c60b9acSAndroid Build Coastguard Worker
927*1c60b9acSAndroid Build Coastguard Worker return 0;
928*1c60b9acSAndroid Build Coastguard Worker }
929*1c60b9acSAndroid Build Coastguard Worker
930*1c60b9acSAndroid Build Coastguard Worker static void
lws_cache_nscookiejar_debug_dump(struct lws_cache_ttl_lru * _c)931*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_debug_dump(struct lws_cache_ttl_lru *_c)
932*1c60b9acSAndroid Build Coastguard Worker {
933*1c60b9acSAndroid Build Coastguard Worker lws_cache_nscookiejar_t *cache = (lws_cache_nscookiejar_t *)_c;
934*1c60b9acSAndroid Build Coastguard Worker int fd = nsc_backing_open_lock(cache, LWS_O_RDONLY, __func__);
935*1c60b9acSAndroid Build Coastguard Worker
936*1c60b9acSAndroid Build Coastguard Worker if (fd < 0)
937*1c60b9acSAndroid Build Coastguard Worker return;
938*1c60b9acSAndroid Build Coastguard Worker
939*1c60b9acSAndroid Build Coastguard Worker lwsl_cache("%s: %s\n", __func__, _c->info.name);
940*1c60b9acSAndroid Build Coastguard Worker
941*1c60b9acSAndroid Build Coastguard Worker nscookiejar_iterate(cache, fd, nsc_dump_cb, NULL);
942*1c60b9acSAndroid Build Coastguard Worker
943*1c60b9acSAndroid Build Coastguard Worker nsc_backing_close_unlock(cache, fd);
944*1c60b9acSAndroid Build Coastguard Worker }
945*1c60b9acSAndroid Build Coastguard Worker #endif
946*1c60b9acSAndroid Build Coastguard Worker
947*1c60b9acSAndroid Build Coastguard Worker const struct lws_cache_ops lws_cache_ops_nscookiejar = {
948*1c60b9acSAndroid Build Coastguard Worker .create = lws_cache_nscookiejar_create,
949*1c60b9acSAndroid Build Coastguard Worker .destroy = lws_cache_nscookiejar_destroy,
950*1c60b9acSAndroid Build Coastguard Worker .expunge = lws_cache_nscookiejar_expunge,
951*1c60b9acSAndroid Build Coastguard Worker
952*1c60b9acSAndroid Build Coastguard Worker .write = lws_cache_nscookiejar_write,
953*1c60b9acSAndroid Build Coastguard Worker .tag_match = lws_cache_nscookiejar_tag_match,
954*1c60b9acSAndroid Build Coastguard Worker .lookup = lws_cache_nscookiejar_lookup,
955*1c60b9acSAndroid Build Coastguard Worker .invalidate = lws_cache_nscookiejar_invalidate,
956*1c60b9acSAndroid Build Coastguard Worker .get = lws_cache_nscookiejar_get,
957*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
958*1c60b9acSAndroid Build Coastguard Worker .debug_dump = lws_cache_nscookiejar_debug_dump,
959*1c60b9acSAndroid Build Coastguard Worker #endif
960*1c60b9acSAndroid Build Coastguard Worker };
961