1 /*-
2  * Copyright (c) 2006 Verdens Gang AS
3  * Copyright (c) 2006-2015 Varnish Software AS
4  * All rights reserved.
5  *
6  * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7  *
8  * SPDX-License-Identifier: BSD-2-Clause
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  */
32 
33 #ifdef VRT_H_INCLUDED
34 #  error "vrt.h included before cache.h - they are exclusive"
35 #endif
36 
37 #ifdef CACHE_H_INCLUDED
38 #  error "cache.h included multiple times"
39 #endif
40 
41 #include <math.h>
42 #include <pthread.h>
43 #include <stdarg.h>
44 #include <sys/types.h>
45 
46 #include "vdef.h"
47 #include "vrt.h"
48 
49 #define CACHE_H_INCLUDED	// After vrt.h include.
50 
51 #include "miniobj.h"
52 #include "vas.h"
53 #include "vqueue.h"
54 #include "vtree.h"
55 
56 #include "vapi/vsl_int.h"
57 
58 /*--------------------------------------------------------------------*/
59 
60 struct body_status {
61 	const char		*name;
62 	int			nbr;
63 	int			avail;
64 	int			length_known;
65 };
66 
67 #define BODYSTATUS(U, l, n, a, k) extern const struct body_status BS_##U[1];
68 #include "tbl/body_status.h"
69 
70 typedef const struct body_status *body_status_t;
71 
72 /*--------------------------------------------------------------------*/
73 
74 enum sess_close {
75 	SC_NULL = 0,
76 #define SESS_CLOSE(nm, stat, err, desc)	SC_##nm,
77 #include "tbl/sess_close.h"
78 };
79 
80 /*--------------------------------------------------------------------
81  * Indices into http->hd[]
82  */
83 enum {
84 #define SLTH(tag, ind, req, resp, sdesc, ldesc)	ind,
85 #include "tbl/vsl_tags_http.h"
86 };
87 
88 /*--------------------------------------------------------------------*/
89 
90 struct VSC_lck;
91 struct VSC_main;
92 struct VSC_main_wrk;
93 struct ban;
94 struct ban_proto;
95 struct cli;
96 struct http_conn;
97 struct mempool;
98 struct objcore;
99 struct objhead;
100 struct pool;
101 struct sess;
102 struct transport;
103 struct worker;
104 struct listen_sock;
105 struct vcf;
106 struct req_step;
107 
108 #define DIGEST_LEN		32
109 
110 /*--------------------------------------------------------------------*/
111 
112 typedef struct {
113 	const char		*b;
114 	const char		*e;
115 } txt;
116 
117 /*--------------------------------------------------------------------*/
118 
119 struct lock { void *priv; };	// Opaque
120 
121 /*--------------------------------------------------------------------
122  * Workspace structure for quick memory allocation.
123  */
124 
125 #define WS_ID_SIZE 4
126 
127 struct ws {
128 	unsigned		magic;
129 #define WS_MAGIC		0x35fac554
130 	char			id[WS_ID_SIZE];	/* identity */
131 	char			*s;		/* (S)tart of buffer */
132 	char			*f;		/* (F)ree/front pointer */
133 	char			*r;		/* (R)eserved length */
134 	char			*e;		/* (E)nd of buffer */
135 };
136 
137 /*--------------------------------------------------------------------
138  *
139  */
140 
141 struct http {
142 	unsigned		magic;
143 #define HTTP_MAGIC		0x6428b5c9
144 
145 	uint16_t		shd;		/* Size of hd space */
146 	txt			*hd;
147 	unsigned char		*hdf;
148 #define HDF_FILTER		(1 << 0)	/* Filtered by Connection */
149 
150 	/* NB: ->nhd and below zeroed/initialized by http_Teardown */
151 	uint16_t		nhd;		/* Next free hd */
152 
153 	enum VSL_tag_e		logtag;		/* Must be SLT_*Method */
154 	struct vsl_log		*vsl;
155 
156 	struct ws		*ws;
157 	uint16_t		status;
158 	uint8_t			protover;
159 };
160 
161 /*--------------------------------------------------------------------*/
162 
163 struct acct_req {
164 #define ACCT(foo)	uint64_t	foo;
165 #include "tbl/acct_fields_req.h"
166 };
167 
168 /*--------------------------------------------------------------------*/
169 
170 struct acct_bereq {
171 #define ACCT(foo)	uint64_t	foo;
172 #include "tbl/acct_fields_bereq.h"
173 };
174 
175 /*--------------------------------------------------------------------*/
176 
177 struct vsl_log {
178 	uint32_t                *wlb, *wlp, *wle;
179 	unsigned                wlr;
180 	unsigned                wid;
181 };
182 
183 /*--------------------------------------------------------------------*/
184 
185 struct vxid_pool {
186 	uint32_t		next;
187 	uint32_t		count;
188 };
189 
190 /*--------------------------------------------------------------------*/
191 
192 VRBT_HEAD(vrt_privs, vrt_priv);
193 
194 /* Worker pool stuff -------------------------------------------------*/
195 
196 typedef void task_func_t(struct worker *wrk, void *priv);
197 
198 struct pool_task {
199 	VTAILQ_ENTRY(pool_task)		list;
200 	task_func_t			*func;
201 	void				*priv;
202 };
203 
204 /*
205  * tasks are taken off the queues in this order
206  *
207  * TASK_QUEUE_{REQ|STR} are new req's (H1/H2), and subject to queue limit.
208  *
209  * TASK_QUEUE_RUSH is req's returning from waiting list
210  *
211  * NOTE: When changing the number of classes, update places marked with
212  * TASK_QUEUE__END in mgt_pool.c
213  */
214 enum task_prio {
215 	TASK_QUEUE_BO,
216 	TASK_QUEUE_RUSH,
217 	TASK_QUEUE_REQ,
218 	TASK_QUEUE_STR,
219 	TASK_QUEUE_VCA,
220 	TASK_QUEUE__END
221 };
222 
223 #define TASK_QUEUE_HIGHEST_PRIORITY TASK_QUEUE_BO
224 #define TASK_QUEUE_CLIENT(prio) \
225 	(prio == TASK_QUEUE_REQ || prio == TASK_QUEUE_STR)
226 
227 /*--------------------------------------------------------------------*/
228 
229 struct worker {
230 	unsigned		magic;
231 #define WORKER_MAGIC		0x6391adcf
232 	struct pool		*pool;
233 	struct objhead		*nobjhead;
234 	struct objcore		*nobjcore;
235 	void			*nhashpriv;
236 	struct VSC_main_wrk	*stats;
237 	struct vsl_log		*vsl;		// borrowed from req/bo
238 
239 	struct pool_task	task[1];
240 
241 	vtim_real		lastused;
242 	int			strangelove;
243 
244 	struct v1l		*v1l;
245 
246 	pthread_cond_t		cond;
247 
248 	struct vcl		*vcl;
249 
250 	struct ws		aws[1];
251 
252 	struct vxid_pool	vxid_pool;
253 
254 	unsigned		cur_method;
255 	unsigned		seen_methods;
256 	unsigned		handling;
257 };
258 
259 /* Stored object -----------------------------------------------------
260  * This is just to encapsulate the fields owned by the stevedore
261  */
262 
263 struct storeobj {
264 	const struct stevedore	*stevedore;
265 	void			*priv;
266 	uintptr_t		priv2;
267 };
268 
269 /* Busy Objcore structure --------------------------------------------
270  *
271  */
272 
273 /*
274  * The macro-states we expose outside the fetch code
275  */
276 enum boc_state_e {
277 #define BOC_STATE(U, l)       BOS_##U,
278 #include "tbl/boc_state.h"
279 };
280 
281 struct boc {
282 	unsigned		magic;
283 #define BOC_MAGIC		0x70c98476
284 	unsigned		refcount;
285 	struct lock		mtx;
286 	pthread_cond_t		cond;
287 	void			*stevedore_priv;
288 	enum boc_state_e	state;
289 	uint8_t			*vary;
290 	uint64_t		len_so_far;
291 };
292 
293 /* Object core structure ---------------------------------------------
294  * Objects have sideways references in the binary heap and the LRU list
295  * and we want to avoid paging in a lot of objects just to move them up
296  * or down the binheap or to move a unrelated object on the LRU list.
297  * To avoid this we use a proxy object, objcore, to hold the relevant
298  * housekeeping fields parts of an object.
299  */
300 
301 enum obj_attr {
302 #define OBJ_FIXATTR(U, l, s)	OA_##U,
303 #define OBJ_VARATTR(U, l)	OA_##U,
304 #define OBJ_AUXATTR(U, l)	OA_##U,
305 #include "tbl/obj_attr.h"
306 				OA__MAX,
307 };
308 
309 enum obj_flags {
310 #define OBJ_FLAG(U, l, v)       OF_##U = v,
311 #include "tbl/obj_attr.h"
312 };
313 
314 enum oc_flags {
315 #define OC_FLAG(U, l, v)	OC_F_##U = v,
316 #include "tbl/oc_flags.h"
317 };
318 
319 enum oc_exp_flags {
320 #define OC_EXP_FLAG(U, l, v)	OC_EF_##U = v,
321 #include "tbl/oc_exp_flags.h"
322 };
323 
324 struct objcore {
325 	unsigned		magic;
326 #define OBJCORE_MAGIC		0x4d301302
327 	int			refcnt;
328 	struct storeobj		stobj[1];
329 	struct objhead		*objhead;
330 	struct boc		*boc;
331 	vtim_real		timer_when;
332 	VCL_INT			hits;
333 
334 
335 	vtim_real		t_origin;
336 	float			ttl;
337 	float			grace;
338 	float			keep;
339 
340 	uint8_t			flags;
341 
342 	uint8_t			exp_flags;
343 
344 	uint16_t		oa_present;
345 
346 	unsigned		timer_idx;	// XXX 4Gobj limit
347 	vtim_real		last_lru;
348 	VTAILQ_ENTRY(objcore)	hsh_list;
349 	VTAILQ_ENTRY(objcore)	lru_list;
350 	VTAILQ_ENTRY(objcore)	ban_list;
351 	VSTAILQ_ENTRY(objcore)	exp_list;
352 	struct ban		*ban;
353 };
354 
355 /* Busy Object structure ---------------------------------------------
356  *
357  * The busyobj structure captures the aspects of an object related to,
358  * and while it is being fetched from the backend.
359  *
360  * One of these aspects will be how much has been fetched, which
361  * streaming delivery will make use of.
362  */
363 
364 enum director_state_e {
365 	DIR_S_NULL = 0,
366 	DIR_S_HDRS = 1,
367 	DIR_S_BODY = 2,
368 };
369 
370 struct busyobj {
371 	unsigned		magic;
372 #define BUSYOBJ_MAGIC		0x23b95567
373 
374 	char			*end;
375 
376 	/*
377 	 * All fields from retries and down are zeroed when the busyobj
378 	 * is recycled.
379 	 */
380 	unsigned		retries;
381 	struct req		*req;
382 	struct sess		*sp;
383 	struct worker		*wrk;
384 
385 	struct vfp_ctx		*vfc;
386 	const char		*vfp_filter_list;
387 
388 	struct ws		ws[1];
389 	uintptr_t		ws_bo;
390 	struct http		*bereq0;
391 	struct http		*bereq;
392 	struct http		*beresp;
393 	struct objcore		*bereq_body;
394 	struct objcore		*stale_oc;
395 	struct objcore		*fetch_objcore;
396 
397 	const char		*no_retry;
398 
399 	struct http_conn	*htc;
400 
401 	struct pool_task	fetch_task[1];
402 
403 #define BO_FLAG(l, r, rr, rw, f, d) unsigned	l:1;
404 #include "tbl/bo_flags.h"
405 
406 	/* Timeouts */
407 	vtim_dur		connect_timeout;
408 	vtim_dur		first_byte_timeout;
409 	vtim_dur		between_bytes_timeout;
410 
411 	/* Timers */
412 	vtim_real		t_first;	/* First timestamp logged */
413 	vtim_real		t_prev;		/* Previous timestamp logged */
414 
415 	/* Acct */
416 	struct acct_bereq	acct;
417 
418 	const struct stevedore	*storage;
419 	const struct director	*director_req;
420 	const struct director	*director_resp;
421 	enum director_state_e	director_state;
422 	struct vcl		*vcl;
423 
424 	struct vsl_log		vsl[1];
425 
426 	uint8_t			digest[DIGEST_LEN];
427 	struct vrt_privs	privs[1];
428 
429 	uint16_t		err_code;
430 	const char		*err_reason;
431 
432 	const char		*client_identity;
433 };
434 
435 
436 /*--------------------------------------------------------------------*/
437 
438 struct reqtop {
439 	unsigned		magic;
440 #define REQTOP_MAGIC		0x57fbda52
441 	struct req		*topreq;
442 	struct vcl		*vcl0;
443 	struct vrt_privs	privs[1];
444 };
445 
446 struct req {
447 	unsigned		magic;
448 #define REQ_MAGIC		0xfb4abf6d
449 
450 	body_status_t		req_body_status;
451 	enum sess_close		doclose;
452 	unsigned		restarts;
453 	unsigned		esi_level;
454 
455 	/* Delivery mode */
456 	unsigned		res_mode;
457 #define RES_ESI			(1<<4)
458 #define RES_PIPE		(1<<7)
459 
460 	const struct req_step	*req_step;
461 	struct reqtop		*top;	/* esi_level == 0 request */
462 
463 #define REQ_FLAG(l, r, w, d) unsigned	l:1;
464 #include "tbl/req_flags.h"
465 
466 	uint16_t		err_code;
467 	const char		*err_reason;
468 
469 	struct sess		*sp;
470 	struct worker		*wrk;
471 	struct pool_task	task[1];
472 
473 	const struct transport	*transport;
474 	void			*transport_priv;
475 
476 	VTAILQ_ENTRY(req)	w_list;
477 
478 	struct objcore		*body_oc;
479 
480 	/* The busy objhead we sleep on */
481 	struct objhead		*hash_objhead;
482 
483 	/* Built Vary string */
484 	uint8_t			*vary_b;
485 	uint8_t			*vary_l;
486 	uint8_t			*vary_e;
487 
488 	uint8_t			digest[DIGEST_LEN];
489 
490 	vtim_dur		d_ttl;
491 	vtim_dur		d_grace;
492 
493 	const struct stevedore	*storage;
494 
495 	const struct director	*director_hint;
496 	struct vcl		*vcl;
497 
498 	uintptr_t		ws_req;		/* WS above request data */
499 
500 	/* Timestamps */
501 	vtim_real		t_first;	/* First timestamp logged */
502 	vtim_real		t_prev;		/* Previous timestamp logged */
503 	vtim_real		t_req;		/* Headers complete */
504 
505 	struct http_conn	*htc;
506 	struct vfp_ctx		*vfc;
507 	const char		*client_identity;
508 
509 	/* HTTP request */
510 	struct http		*http;
511 	struct http		*http0;
512 
513 	/* HTTP response */
514 	struct http		*resp;
515 	intmax_t		resp_len;
516 
517 	struct ws		ws[1];
518 	struct objcore		*objcore;
519 	struct objcore		*stale_oc;
520 
521 	/* Deliver pipeline */
522 	struct vdp_ctx		*vdc;
523 	const char		*filter_list;
524 
525 	/* Transaction VSL buffer */
526 	struct vsl_log		vsl[1];
527 
528 	/* Temporary accounting */
529 	struct acct_req		acct;
530 
531 	struct vrt_privs	privs[1];
532 
533 	struct vcf		*vcf;
534 };
535 
536 #define IS_TOPREQ(req) ((req)->top->topreq == (req))
537 
538 /*--------------------------------------------------------------------
539  * Struct sess is a high memory-load structure because sessions typically
540  * hang around the waiter for relatively long time.
541  *
542  * The size goal for struct sess + struct memitem is <512 bytes
543  *
544  * Getting down to the next relevant size (<256 bytes because of how malloc
545  * works, is not realistic without a lot of code changes.
546  */
547 
548 enum sess_attr {
549 #define SESS_ATTR(UP, low, typ, len)	SA_##UP,
550 #include "tbl/sess_attr.h"
551 	SA_LAST
552 };
553 
554 struct sess {
555 	unsigned		magic;
556 #define SESS_MAGIC		0x2c2f9c5a
557 
558 	uint16_t		sattr[SA_LAST];
559 	struct listen_sock	*listen_sock;
560 	int			refcnt;
561 	int			fd;
562 	uint32_t		vxid;
563 
564 	struct lock		mtx;
565 
566 	struct pool		*pool;
567 
568 	struct ws		ws[1];
569 
570 	vtim_real		t_open;		/* fd accepted */
571 	vtim_real		t_idle;		/* fd accepted or resp sent */
572 	vtim_dur		timeout_idle;
573 	vtim_dur		timeout_linger;
574 	vtim_dur		send_timeout;
575 	vtim_dur		idle_send_timeout;
576 };
577 
578 #define SESS_TMO(sp, tmo)					\
579 	(isnan((sp)->tmo) ? cache_param->tmo : (sp)->tmo)
580 
581 /* Prototypes etc ----------------------------------------------------*/
582 
583 
584 /* cache_ban.c */
585 
586 /* for constructing bans */
587 struct ban_proto *BAN_Build(void);
588 const char *BAN_AddTest(struct ban_proto *,
589     const char *, const char *, const char *);
590 const char *BAN_Commit(struct ban_proto *b);
591 void BAN_Abandon(struct ban_proto *b);
592 
593 /* cache_cli.c [CLI] */
594 extern pthread_t cli_thread;
595 #define ASSERT_CLI() do {assert(pthread_equal(pthread_self(), cli_thread));} while (0)
596 
597 /* cache_http.c */
598 unsigned HTTP_estimate(unsigned nhttp);
599 void HTTP_Clone(struct http *to, const struct http * const fm);
600 void HTTP_Dup(struct http *to, const struct http * const fm);
601 struct http *HTTP_create(void *p, uint16_t nhttp, unsigned);
602 const char *http_Status2Reason(unsigned, const char **);
603 unsigned http_EstimateWS(const struct http *fm, unsigned how);
604 void http_PutResponse(struct http *to, const char *proto, uint16_t status,
605     const char *response);
606 void http_FilterReq(struct http *to, const struct http *fm, unsigned how);
607 void HTTP_Encode(const struct http *fm, uint8_t *, unsigned len, unsigned how);
608 int HTTP_Decode(struct http *to, const uint8_t *fm);
609 void http_ForceHeader(struct http *to, const char *hdr, const char *val);
610 void http_PrintfHeader(struct http *to, const char *fmt, ...)
611     v_printflike_(2, 3);
612 void http_TimeHeader(struct http *to, const char *fmt, vtim_real now);
613 void http_Proto(struct http *to);
614 void http_SetHeader(struct http *to, const char *hdr);
615 void http_SetH(struct http *to, unsigned n, const char *fm);
616 void http_ForceField(struct http *to, unsigned n, const char *t);
617 void HTTP_Setup(struct http *, struct ws *, struct vsl_log *, enum VSL_tag_e);
618 void http_Teardown(struct http *ht);
619 int http_GetHdr(const struct http *hp, const char *hdr, const char **ptr);
620 int http_GetHdrToken(const struct http *hp, const char *hdr,
621     const char *token, const char **pb, const char **pe);
622 int http_GetHdrField(const struct http *hp, const char *hdr,
623     const char *field, const char **ptr);
624 double http_GetHdrQ(const struct http *hp, const char *hdr, const char *field);
625 ssize_t http_GetContentLength(const struct http *hp);
626 uint16_t http_GetStatus(const struct http *hp);
627 int http_IsStatus(const struct http *hp, int);
628 void http_SetStatus(struct http *to, uint16_t status, const char *reason);
629 const char *http_GetMethod(const struct http *hp);
630 int http_HdrIs(const struct http *hp, const char *hdr, const char *val);
631 void http_CopyHome(const struct http *hp);
632 void http_Unset(struct http *hp, const char *hdr);
633 unsigned http_CountHdr(const struct http *hp, const char *hdr);
634 void http_CollectHdr(struct http *hp, const char *hdr);
635 void http_CollectHdrSep(struct http *hp, const char *hdr, const char *sep);
636 void http_VSL_log(const struct http *hp);
637 void HTTP_Merge(struct worker *, struct objcore *, struct http *to);
638 uint16_t HTTP_GetStatusPack(struct worker *, struct objcore *oc);
639 int HTTP_IterHdrPack(struct worker *, struct objcore *, const char **);
640 #define HTTP_FOREACH_PACK(wrk, oc, ptr) \
641 	 for ((ptr) = NULL; HTTP_IterHdrPack(wrk, oc, &(ptr));)
642 const char *HTTP_GetHdrPack(struct worker *, struct objcore *, const char *hdr);
643 enum sess_close http_DoConnection(struct http *hp, enum sess_close sc_close);
644 int http_IsFiltered(const struct http *hp, unsigned u, unsigned how);
645 
646 #define HTTPH_R_PASS		(1 << 0)	/* Request (c->b) in pass mode */
647 #define HTTPH_R_FETCH		(1 << 1)	/* Request (c->b) for fetch */
648 #define HTTPH_A_INS		(1 << 2)	/* Response (b->o) for insert */
649 #define HTTPH_A_PASS		(1 << 3)	/* Response (b->o) for pass */
650 #define HTTPH_C_SPECIFIC	(1 << 4)	/* Connection-specific */
651 
652 #define HTTPH(a, b, c) extern char b[];
653 #include "tbl/http_headers.h"
654 
655 extern const char H__Status[];
656 extern const char H__Proto[];
657 extern const char H__Reason[];
658 
659 /* cache_main.c */
660 #define VXID(u) ((u) & VSL_IDENTMASK)
661 uint32_t VXID_Get(struct worker *, uint32_t marker);
662 extern pthread_key_t witness_key;
663 
664 /* cache_lck.c */
665 
666 /* Internal functions, call only through macros below */
667 void Lck__Lock(struct lock *lck, const char *p,  int l);
668 void Lck__Unlock(struct lock *lck, const char *p,  int l);
669 int Lck__Trylock(struct lock *lck, const char *p,  int l);
670 void Lck__New(struct lock *lck, struct VSC_lck *, const char *);
671 int Lck__Held(const struct lock *lck);
672 int Lck__Owned(const struct lock *lck);
673 
674 /* public interface: */
675 void Lck_Delete(struct lock *lck);
676 int Lck_CondWait(pthread_cond_t *cond, struct lock *lck, vtim_real);
677 
678 #define Lck_New(a, b) Lck__New(a, b, #b)
679 #define Lck_Lock(a) Lck__Lock(a, __func__, __LINE__)
680 #define Lck_Unlock(a) Lck__Unlock(a, __func__, __LINE__)
681 #define Lck_Trylock(a) Lck__Trylock(a, __func__, __LINE__)
682 #define Lck_AssertHeld(a)		\
683 	do {				\
684 		assert(Lck__Held(a));	\
685 		assert(Lck__Owned(a));	\
686 	} while (0)
687 
688 struct VSC_lck *Lck_CreateClass(struct vsc_seg **, const char *);
689 void Lck_DestroyClass(struct vsc_seg **);
690 
691 #define LOCK(nam) extern struct VSC_lck *lck_##nam;
692 #include "tbl/locks.h"
693 
694 /* cache_obj.c */
695 
696 int ObjHasAttr(struct worker *, struct objcore *, enum obj_attr);
697 const void *ObjGetAttr(struct worker *, struct objcore *, enum obj_attr,
698     ssize_t *len);
699 
700 typedef int objiterate_f(void *priv, unsigned flush,
701     const void *ptr, ssize_t len);
702 #define OBJ_ITER_FLUSH	0x01
703 #define OBJ_ITER_END	0x02
704 
705 int ObjIterate(struct worker *, struct objcore *,
706     void *priv, objiterate_f *func, int final);
707 
708 unsigned ObjGetXID(struct worker *, struct objcore *);
709 uint64_t ObjGetLen(struct worker *, struct objcore *);
710 int ObjGetDouble(struct worker *, struct objcore *, enum obj_attr, double *);
711 int ObjGetU32(struct worker *, struct objcore *, enum obj_attr, uint32_t *);
712 int ObjGetU64(struct worker *, struct objcore *, enum obj_attr, uint64_t *);
713 int ObjCheckFlag(struct worker *, struct objcore *, enum obj_flags of);
714 
715 /* cache_req_body.c */
716 ssize_t VRB_Iterate(struct worker *, struct vsl_log *, struct req *,
717     objiterate_f *func, void *priv);
718 
719 /* cache_session.c [SES] */
720 
721 #define SESS_ATTR(UP, low, typ, len)					\
722 	int SES_Get_##low(const struct sess *sp, typ **dst);
723 #include "tbl/sess_attr.h"
724 const char *SES_Get_String_Attr(const struct sess *sp, enum sess_attr a);
725 
726 /* cache_shmlog.c */
727 void VSLv(enum VSL_tag_e tag, uint32_t vxid, const char *fmt, va_list va);
728 void VSL(enum VSL_tag_e tag, uint32_t vxid, const char *fmt, ...)
729     v_printflike_(3, 4);
730 void VSLs(enum VSL_tag_e tag, uint32_t vxid, const struct strands *s);
731 void VSLbv(struct vsl_log *, enum VSL_tag_e tag, const char *fmt, va_list va);
732 void VSLb(struct vsl_log *, enum VSL_tag_e tag, const char *fmt, ...)
733     v_printflike_(3, 4);
734 void VSLbt(struct vsl_log *, enum VSL_tag_e tag, txt t);
735 void VSLbs(struct vsl_log *, enum VSL_tag_e tag, const struct strands *s);
736 void VSLb_ts(struct vsl_log *, const char *event, vtim_real first,
737     vtim_real *pprev, vtim_real now);
738 void VSLb_bin(struct vsl_log *, enum VSL_tag_e, ssize_t, const void*);
739 
740 static inline void
VSLb_ts_req(struct req * req,const char * event,vtim_real now)741 VSLb_ts_req(struct req *req, const char *event, vtim_real now)
742 {
743 
744 	if (isnan(req->t_first) || req->t_first == 0.)
745 		req->t_first = req->t_prev = now;
746 	VSLb_ts(req->vsl, event, req->t_first, &req->t_prev, now);
747 }
748 
749 static inline void
VSLb_ts_busyobj(struct busyobj * bo,const char * event,vtim_real now)750 VSLb_ts_busyobj(struct busyobj *bo, const char *event, vtim_real now)
751 {
752 
753 	if (isnan(bo->t_first) || bo->t_first == 0.)
754 		bo->t_first = bo->t_prev = now;
755 	VSLb_ts(bo->vsl, event, bo->t_first, &bo->t_prev, now);
756 }
757 
758 /* cache_vcl.c */
759 const char *VCL_Name(const struct vcl *);
760 
761 /* cache_vrt.c */
762 /*
763  * These prototypes go here, because we do not want to pollute vrt.h
764  * with va_list.  VCC never generates direct calls to them.
765  * XXX: We should deprecate these (ref: STRANDS)
766  */
767 const char *VRT_String(struct ws *ws, const char *h, const char *p, va_list ap);
768 char *VRT_StringList(char *d, unsigned dl, const char *p, va_list ap);
769 
770 /* cache_wrk.c */
771 
772 typedef void *bgthread_t(struct worker *, void *priv);
773 void WRK_BgThread(pthread_t *thr, const char *name, bgthread_t *func,
774     void *priv);
775 
776 /* cache_ws.c */
777 
778 void WS_Init(struct ws *ws, const char *id, void *space, unsigned len);
779 
780 unsigned WS_ReserveSize(struct ws *, unsigned);
781 unsigned WS_ReserveAll(struct ws *);
782 unsigned WS_ReserveLumps(struct ws *ws, size_t sz);
783 void WS_MarkOverflow(struct ws *ws);
784 void WS_Release(struct ws *ws, unsigned bytes);
785 void WS_ReleaseP(struct ws *ws, const char *ptr);
786 void WS_Assert(const struct ws *ws);
787 void WS_Reset(struct ws *ws, uintptr_t);
788 void *WS_Alloc(struct ws *ws, unsigned bytes);
789 void *WS_Copy(struct ws *ws, const void *str, int len);
790 uintptr_t WS_Snapshot(struct ws *ws);
791 int WS_Overflowed(const struct ws *ws);
792 const char *WS_Printf(struct ws *ws, const char *fmt, ...) v_printflike_(2, 3);
793 int WS_Inside(const struct ws *, const void *, const void *);
794 void WS_Assert_Allocated(const struct ws *ws, const void *ptr, ssize_t len);
795 
796 void WS_VSB_new(struct vsb *, struct ws *);
797 char *WS_VSB_finish(struct vsb *, struct ws *, size_t *);
798 
799 /* REL_20210315 remove */
800 static inline char*
WS_Front(const struct ws * ws)801 WS_Front(const struct ws *ws)
802 {
803 	AN(ws->r);
804 	return ws->f;
805 }
806 
807 static inline void *
WS_Reservation(const struct ws * ws)808 WS_Reservation(const struct ws *ws)
809 {
810 
811 	WS_Assert(ws);
812 	AN(ws->r);
813 	AN(ws->f);
814 	return (ws->f);
815 }
816 
817 static inline unsigned
WS_ReservationSize(const struct ws * ws)818 WS_ReservationSize(const struct ws *ws)
819 {
820 
821 	AN(ws->r);
822 	return (ws->r - ws->f);
823 }
824 
825 /* cache_rfc2616.c */
826 void RFC2616_Ttl(struct busyobj *, vtim_real now, vtim_real *t_origin,
827     float *ttl, float *grace, float *keep);
828 unsigned RFC2616_Req_Gzip(const struct http *);
829 int RFC2616_Do_Cond(const struct req *sp);
830 void RFC2616_Weaken_Etag(struct http *hp);
831 void RFC2616_Vary_AE(struct http *hp);
832 
833 #define Tcheck(t) do {						\
834 		AN((t).b);					\
835 		AN((t).e);					\
836 		assert((t).b <= (t).e);				\
837 	} while(0)
838 
839 /*
840  * unsigned length of a txt
841  */
842 
843 static inline unsigned
Tlen(const txt t)844 Tlen(const txt t)
845 {
846 
847 	Tcheck(t);
848 	return ((unsigned)(t.e - t.b));
849 }
850 
851 /*
852  * We want to cache the most recent timestamp in wrk->lastused to avoid
853  * extra timestamps in cache_pool.c.  Hide this detail with a macro
854  */
855 #define W_TIM_real(w) ((w)->lastused = VTIM_real())
856 
857 int PAN_dump_struct2(struct vsb *vsb, int block, const void *ptr,
858     const char *smagic, unsigned magic, const char *fmt, ...)
859     v_printflike_(6,7);
860 
861 #define PAN_dump_struct(vsb, ptr, magic, ...)		\
862     PAN_dump_struct2(vsb, 1, ptr, #magic, magic, __VA_ARGS__)
863 
864 #define PAN_dump_oneline(vsb, ptr, magic, ...)		\
865     PAN_dump_struct2(vsb, 0, ptr, #magic, magic, __VA_ARGS__)
866