Coverage Report

Created: 2026-06-13 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vinyl-cache/bin/vinyld/cache/cache.h
Line
Count
Source
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
#include <sys/uio.h>
46
47
#include "vdef.h"
48
#include "vrt.h"
49
50
#define CACHE_H_INCLUDED  // After vrt.h include.
51
52
#include "miniobj.h"
53
#include "vas.h"
54
#include "vqueue.h"
55
#include "vtree.h"
56
57
#include "vapi/vsl_int.h"
58
59
/*--------------------------------------------------------------------*/
60
61
struct vxids {
62
  uint64_t  vxid;
63
};
64
65
typedef struct vxids vxid_t;
66
67
#define NO_VXID ((struct vxids){0})
68
#define IS_NO_VXID(x) ((x).vxid == 0)
69
#define VXID_TAG(x) ((uintmax_t)((x).vxid & (VSL_CLIENTMARKER|VSL_BACKENDMARKER)))
70
#define VXID(u) ((uintmax_t)((u.vxid) & VSL_IDENTMASK))
71
#define IS_SAME_VXID(x, y) ((x).vxid == (y).vxid)
72
73
/*--------------------------------------------------------------------*/
74
75
struct body_status {
76
  const char    *name;
77
  int     nbr;
78
  int     avail;
79
  int     length_known;
80
};
81
82
#define BODYSTATUS(U, l, n, a, k) extern const struct body_status BS_##U[1];
83
#include "tbl/body_status.h"
84
85
typedef const struct body_status *body_status_t;
86
87
/*--------------------------------------------------------------------*/
88
89
struct stream_close {
90
  unsigned    magic;
91
#define STREAM_CLOSE_MAGIC  0xc879c93d
92
  int     idx;
93
  unsigned    is_err;
94
  const char    *name;
95
  const char    *desc;
96
};
97
    extern const struct stream_close SC_NULL[1];
98
#define SESS_CLOSE_C(nm, stat, err, desc) \
99
    extern const struct stream_close SC_##nm[1];
100
#include "tbl/sess_close.h"
101
102
103
/*--------------------------------------------------------------------
104
 * Indices into http->hd[]
105
 */
106
enum {
107
#define SLTH(tag, ind, req, resp, sdesc, ldesc) ind,
108
#include "tbl/vsl_tags_http.h"
109
};
110
111
/*--------------------------------------------------------------------*/
112
113
struct ban;
114
struct ban_proto;
115
struct cli;
116
struct http_conn;
117
struct listen_sock;
118
struct mempool;
119
struct objcore;
120
struct objhead;
121
struct pool;
122
struct req_step;
123
struct sess;
124
struct transport;
125
struct vcf;
126
struct VSC_lck;
127
struct VSC_main;
128
struct VSC_main_wrk;
129
struct worker;
130
struct worker_priv;
131
132
#define DIGEST_LEN    32
133
134
/*--------------------------------------------------------------------*/
135
136
struct lock { void *priv; };  // Opaque
137
138
/*--------------------------------------------------------------------
139
 * Workspace structure for quick memory allocation.
140
 */
141
142
0
#define WS_ID_SIZE 4
143
144
struct ws {
145
  unsigned    magic;
146
#define WS_MAGIC    0x35fac554
147
  char      id[WS_ID_SIZE]; /* identity */
148
  char      *s;   /* (S)tart of buffer */
149
  char      *f;   /* (F)ree/front pointer */
150
  char      *r;   /* (R)eserved length */
151
  char      *e;   /* (E)nd of buffer */
152
};
153
154
/*--------------------------------------------------------------------
155
 *
156
 */
157
158
enum well_known_method {
159
#define WKM(wk, bit) WKM_##wk = 1U << bit,
160
#include "tbl/well_known_methods.h"
161
#undef WKM
162
};
163
164
struct http {
165
  unsigned    magic;
166
#define HTTP_MAGIC    0x6428b5c9
167
168
  uint16_t    shd;    /* Size of hd space */
169
  txt     *hd;
170
  unsigned char   *hdf;
171
#define HDF_FILTER    (1 << 0)  /* Filtered by Connection */
172
173
  /* NB: ->nhd and below zeroed/initialized by http_Teardown */
174
  uint16_t    nhd;    /* Next free hd */
175
176
  enum VSL_tag_e    logtag;   /* Must be SLT_*Method */
177
  struct vsl_log    *vsl;
178
179
  struct ws   *ws;
180
  uint16_t    status;
181
  uint8_t     protover;
182
  enum well_known_method  wkm;
183
};
184
185
/*--------------------------------------------------------------------*/
186
187
struct acct_req {
188
#define ACCT(foo) uint64_t  foo;
189
#include "tbl/acct_fields_req.h"
190
};
191
192
/*--------------------------------------------------------------------*/
193
194
struct acct_bereq {
195
#define ACCT(foo) uint64_t  foo;
196
#include "tbl/acct_fields_bereq.h"
197
};
198
199
/*--------------------------------------------------------------------*/
200
201
struct vsl_log {
202
  uint16_t    magic;
203
#define VSL_LOG_MAGIC   0x9f34
204
  uint16_t    flags;
205
#define VSL_LOG_F_MALLOCED  1
206
  unsigned    wlr;
207
  uint32_t    *wlb, *wlp, *wle;
208
  vxid_t      wid;
209
};
210
211
/*--------------------------------------------------------------------*/
212
213
VRBT_HEAD(vrt_privs, vrt_priv);
214
215
/* Worker pool stuff -------------------------------------------------*/
216
217
typedef void task_func_t(struct worker *wrk, void *priv);
218
219
struct pool_task {
220
  VTAILQ_ENTRY(pool_task)   list;
221
  task_func_t     *func;
222
  void        *priv;
223
};
224
225
/*
226
 * tasks are taken off the queues in this order
227
 *
228
 * TASK_QUEUE_{REQ|STR} are new req's (H1/H2), and subject to queue limit.
229
 *
230
 * TASK_QUEUE_RUSH is req's returning from waiting list
231
 *
232
 * NOTE: When changing the number of classes, update places marked with
233
 * TASK_QUEUE_RESERVE in params.h
234
 */
235
enum task_prio {
236
  TASK_QUEUE_BO,
237
  TASK_QUEUE_RUSH,
238
  TASK_QUEUE_REQ,
239
  TASK_QUEUE_STR,
240
  TASK_QUEUE_VCA,
241
  TASK_QUEUE_BG,
242
  TASK_QUEUE__END
243
};
244
245
#define TASK_QUEUE_HIGHEST_PRIORITY TASK_QUEUE_BO
246
#define TASK_QUEUE_RESERVE TASK_QUEUE_BG
247
#define TASK_QUEUE_LIMITED(prio) \
248
  (prio == TASK_QUEUE_REQ || prio == TASK_QUEUE_STR)
249
250
/*--------------------------------------------------------------------*/
251
252
struct worker {
253
  unsigned    magic;
254
#define WORKER_MAGIC    0x6391adcf
255
  int     strangelove;
256
  struct worker_priv  *wpriv;
257
  struct pool   *pool;
258
  struct VSC_main_wrk *stats;
259
  struct vsl_log    *vsl;   // borrowed from req/bo
260
261
  struct pool_task  task[1];
262
263
  vtim_real   lastused;
264
265
  pthread_cond_t    cond;
266
267
  struct ws   aws[1];
268
269
  unsigned    cur_method;
270
  unsigned    seen_methods;
271
272
  struct wrk_vpi    *vpi;
273
};
274
275
/* Stored object -----------------------------------------------------
276
 * This is just to encapsulate the fields owned by the stevedore
277
 */
278
279
struct storeobj {
280
  const struct stevedore  *stevedore;
281
  void      *priv;
282
  uint64_t    priv2;
283
};
284
285
/* Busy Objcore structure --------------------------------------------
286
 *
287
 */
288
289
/*
290
 * The macro-states we expose outside the fetch code
291
 */
292
enum boc_state_e {
293
#define BOC_STATE(U, l)       BOS_##U,
294
#include "tbl/boc_state.h"
295
};
296
297
// cache_obj.h vai notify
298
struct vai_qe;
299
VSLIST_HEAD(vai_q_head, vai_qe);
300
301
struct boc {
302
  unsigned    magic;
303
#define BOC_MAGIC   0x70c98476
304
  unsigned    refcount;
305
  struct lock   mtx;
306
  pthread_cond_t    cond;
307
  void      *stevedore_priv;
308
  enum boc_state_e  state;
309
  uint8_t     *vary;
310
  uint64_t    fetched_so_far;
311
  uint64_t    delivered_so_far;
312
  uint64_t    transit_buffer;
313
  struct vai_q_head vai_q_head;
314
};
315
316
/* Object core structure ---------------------------------------------
317
 * Objects have sideways references in the binary heap and the LRU list
318
 * and we want to avoid paging in a lot of objects just to move them up
319
 * or down the binheap or to move a unrelated object on the LRU list.
320
 * To avoid this we use a proxy object, objcore, to hold the relevant
321
 * housekeeping fields parts of an object.
322
 */
323
324
enum obj_attr {
325
#define OBJ_FIXATTR(U, l, s)  OA_##U,
326
#define OBJ_VARATTR(U, l) OA_##U,
327
#define OBJ_AUXATTR(U, l) OA_##U,
328
#include "tbl/obj_attr.h"
329
        OA__MAX,
330
};
331
332
enum obj_flags {
333
#define OBJ_FLAG(U, l, v)       OF_##U = v,
334
#include "tbl/obj_attr.h"
335
};
336
337
enum oc_flags {
338
#define OC_FLAG(U, l, v)  OC_F_##U = v,
339
#include "tbl/oc_flags.h"
340
};
341
342
#define OC_F_TRANSIENT (OC_F_PRIVATE | OC_F_HFM | OC_F_HFP)
343
344
enum oc_exp_flags {
345
#define OC_EXP_FLAG(U, l, v)  OC_EF_##U = v,
346
#include "tbl/oc_exp_flags.h"
347
};
348
349
struct objcore {
350
  unsigned    magic;
351
#define OBJCORE_MAGIC   0x4d301302
352
  int     refcnt;
353
  struct storeobj   stobj[1];
354
  struct objhead    *objhead;
355
  struct boc    *boc;
356
  vtim_real   timer_when;
357
  VCL_INT     hits;
358
359
360
  vtim_real   t_origin;
361
  float     ttl;
362
  float     grace;
363
  float     keep;
364
365
  uint8_t     flags;
366
367
  uint8_t     exp_flags;
368
369
  uint16_t    oa_present;
370
371
  unsigned    timer_idx;  // XXX 4Gobj limit
372
  unsigned    waitinglist_gen;
373
  vtim_real   last_lru;
374
  VTAILQ_ENTRY(objcore) hsh_list;
375
  VTAILQ_ENTRY(objcore) lru_list;
376
  VTAILQ_ENTRY(objcore) ban_list;
377
  VSTAILQ_ENTRY(objcore)  exp_list;
378
  struct ban    *ban;
379
};
380
381
/* Busy Object structure ---------------------------------------------
382
 *
383
 * The busyobj structure captures the aspects of an object related to,
384
 * and while it is being fetched from the backend.
385
 *
386
 * One of these aspects will be how much has been fetched, which
387
 * streaming delivery will make use of.
388
 */
389
390
enum director_state_e {
391
  DIR_S_NULL = 0,
392
  DIR_S_HDRS = 1,
393
  DIR_S_BODY = 2,
394
};
395
396
struct busyobj {
397
  unsigned    magic;
398
#define BUSYOBJ_MAGIC   0x23b95567
399
400
  char      *end;
401
402
  unsigned    max_retries;
403
  unsigned    retries;
404
  struct req    *req;
405
  struct sess   *sp;
406
  struct worker   *wrk;
407
408
  /* beresp.body */
409
  struct vfp_ctx    *vfc;
410
  const char    *vfp_filter_list;
411
  /* bereq.body */
412
  const char    *vdp_filter_list;
413
414
  struct ws   ws[1];
415
  uintptr_t   ws_bo;
416
  struct http   *bereq0;
417
  struct http   *bereq;
418
  struct http   *beresp;
419
  struct objcore    *bereq_body;
420
  struct objcore    *stale_oc;
421
  struct objcore    *fetch_objcore;
422
423
  const char    *no_retry;
424
425
  struct http_conn  *htc;
426
427
  struct pool_task  fetch_task[1];
428
429
  const char    *err_reason;
430
  enum director_state_e director_state;
431
  uint16_t    err_code;
432
433
#define BERESP_FLAG(l, r, w, f, d) unsigned l:1;
434
#define BEREQ_FLAG(l, r, w, d) BERESP_FLAG(l, r, w, 0, d)
435
#include "tbl/bereq_flags.h"
436
#include "tbl/beresp_flags.h"
437
438
439
  /* Timeouts */
440
  vtim_dur    connect_timeout;
441
  vtim_dur    first_byte_timeout;
442
  vtim_dur    between_bytes_timeout;
443
  vtim_dur    task_deadline;
444
445
  /* Timers */
446
  vtim_real   t_first;  /* First timestamp logged */
447
  vtim_real   t_resp;   /* response received */
448
  vtim_real   t_prev;   /* Previous timestamp logged */
449
450
  /* Acct */
451
  struct acct_bereq acct;
452
453
  const struct stevedore  *storage;
454
  const struct director *director_req;
455
  const struct director *director_resp;
456
  struct vcl    *vcl;
457
458
  struct vsl_log    vsl[1];
459
460
  uint8_t     digest[DIGEST_LEN];
461
  struct vrt_privs  privs[1];
462
463
  const char    *client_identity;
464
};
465
466
#define BUSYOBJ_TMO(bo, pfx, tmo)         \
467
  (isnan((bo)->tmo) ? cache_param->pfx##tmo : (bo)->tmo)
468
469
extern const char *retry_disabled;
470
471
/*--------------------------------------------------------------------*/
472
473
struct reqtop {
474
  unsigned    magic;
475
#define REQTOP_MAGIC    0x57fbda52
476
  struct req    *topreq;
477
  struct vcl    *vcl0;
478
  struct vrt_privs  privs[1];
479
};
480
481
struct req {
482
  unsigned    magic;
483
#define REQ_MAGIC   0xfb4abf6d
484
485
  unsigned    esi_level;
486
  body_status_t   req_body_status;
487
  stream_close_t    doclose;
488
  unsigned    restarts;
489
  unsigned    max_restarts;
490
  unsigned    waitinglist_gen;
491
492
  const struct req_step *req_step;
493
  struct reqtop   *top; /* esi_level == 0 request */
494
495
  uint16_t    err_code;
496
#define REQ_FLAG(l, r, w, d) unsigned l:1;
497
#include "tbl/req_flags.h"
498
499
  const char    *err_reason;
500
501
  struct sess   *sp;
502
  struct worker   *wrk;
503
  struct pool_task  task[1];
504
505
  const struct transport  *transport;
506
  void      *transport_priv;
507
508
  VTAILQ_ENTRY(req) w_list;
509
510
  struct objcore    *body_oc;
511
512
  /* Built Vary string == workspace reservation */
513
  uint8_t     *vary_b;
514
  uint8_t     *vary_e;
515
516
  uint8_t     digest[DIGEST_LEN];
517
518
  vtim_dur    d_ttl;
519
  vtim_dur    d_grace;
520
521
  const struct stevedore  *storage;
522
523
  const struct director *director_hint;
524
  struct vcl    *vcl;
525
526
  uintptr_t   ws_req;   /* WS above request data */
527
528
  /* Timestamps */
529
  vtim_real   t_first;  /* First timestamp logged */
530
  vtim_real   t_prev;   /* Previous timestamp logged */
531
  vtim_real   t_req;    /* Headers complete */
532
  vtim_real   t_resp;   /* Entry to last deliver/synth */
533
534
  struct http_conn  *htc;
535
  struct vfp_ctx    *vfc;
536
  const char    *client_identity;
537
538
  /* HTTP request */
539
  struct http   *http;
540
  struct http   *http0;
541
542
  /* HTTP response */
543
  struct http   *resp;
544
  intmax_t    resp_len;
545
546
  struct ws   ws[1];
547
  struct objcore    *objcore;
548
  struct objcore    *stale_oc;
549
  struct boc    *boc;   /* valid during cnt_transmit */
550
551
  /* resp.body */
552
  struct vdp_ctx    *vdc;
553
  const char    *vdp_filter_list;
554
  /* req.body */
555
  const char    *vfp_filter_list;
556
557
  /* Transaction VSL buffer */
558
  struct vsl_log    vsl[1];
559
560
  /* Temporary accounting */
561
  struct acct_req   acct;
562
563
  struct vrt_privs  privs[1];
564
565
  struct vcf    *vcf;
566
567
  struct ocstash    *stash;
568
};
569
570
#define IS_TOPREQ(req) ((req)->top->topreq == (req))
571
572
/*--------------------------------------------------------------------
573
 * Struct sess is a high memory-load structure because sessions typically
574
 * hang around the waiter for relatively long time.
575
 *
576
 * The size goal for struct sess + struct memitem is <512 bytes
577
 *
578
 * Getting down to the next relevant size (<256 bytes because of how malloc
579
 * works, is not realistic without a lot of code changes.
580
 */
581
582
enum sess_attr {
583
#define SESS_ATTR(UP, low, typ, len)  SA_##UP,
584
#include "tbl/sess_attr.h"
585
  SA_LAST
586
};
587
588
struct sess {
589
  unsigned    magic;
590
#define SESS_MAGIC    0x2c2f9c5a
591
592
  uint16_t    sattr[SA_LAST];
593
  struct listen_sock  *listen_sock;
594
  int     refcnt;
595
  int     fd;
596
  vxid_t      vxid;
597
598
  struct lock   mtx;
599
600
  struct pool   *pool;
601
602
  struct ws   ws[1];
603
604
  vtim_real   t_open;   /* fd accepted */
605
  vtim_real   t_idle;   /* fd accepted or resp sent */
606
  vtim_dur    timeout_idle;
607
  vtim_dur    timeout_linger;
608
  vtim_dur    send_timeout;
609
  vtim_dur    idle_send_timeout;
610
};
611
612
#define SESS_TMO(sp, tmo)         \
613
  (isnan((sp)->tmo) ? cache_param->tmo : (sp)->tmo)
614
615
/* Prototypes etc ----------------------------------------------------*/
616
617
618
/* cache_ban.c */
619
620
/* for constructing bans */
621
struct ban_proto *BAN_Build(void);
622
const char *BAN_AddTest(struct ban_proto *,
623
    const char *, const char *, const char *);
624
const char *BAN_Commit(struct ban_proto *b);
625
void BAN_Abandon(struct ban_proto *b);
626
627
/* cache_cli.c [CLI] */
628
extern pthread_t cli_thread;
629
#define IS_CLI() (pthread_equal(pthread_self(), cli_thread))
630
#define ASSERT_CLI() do {assert(IS_CLI());} while (0)
631
632
/* cache_http.c */
633
unsigned HTTP_estimate(unsigned nhttp);
634
void HTTP_Clone(struct http *to, const struct http * const fm);
635
void HTTP_Dup(struct http *to, const struct http * const fm);
636
struct http *HTTP_create(void *p, uint16_t nhttp, unsigned);
637
const char *http_Status2Reason(unsigned, const char **);
638
int http_IsHdr(const txt *hh, hdr_t hdr);
639
unsigned http_EstimateWS(const struct http *fm, unsigned how);
640
void http_PutResponse(struct http *to, const char *proto, uint16_t status,
641
    const char *response);
642
void http_FilterReq(struct http *to, const struct http *fm, unsigned how);
643
void HTTP_Encode(const struct http *fm, uint8_t *, unsigned len, unsigned how);
644
int HTTP_Decode(struct http *to, const uint8_t *fm);
645
void http_ForceHeader(struct http *to, hdr_t, const char *val);
646
void http_AppendHeader(struct http *to, hdr_t, const char *val);
647
void http_PrintfHeader(struct http *to, const char *fmt, ...)
648
    v_printflike_(2, 3);
649
void http_TimeHeader(struct http *to, const char *fmt, vtim_real now);
650
const char * http_ViaHeader(void);
651
void http_Proto(struct http *to);
652
void http_SetHeader(struct http *to, const char *header);
653
void http_SetH(struct http *to, unsigned n, const char *header);
654
void http_ForceField(struct http *to, unsigned n, const char *t);
655
void HTTP_Setup(struct http *, struct ws *, struct vsl_log *, enum VSL_tag_e);
656
void http_Teardown(struct http *ht);
657
int http_GetHdr(const struct http *hp, hdr_t, const char **ptr);
658
int http_GetHdrToken(const struct http *hp, hdr_t,
659
    const char *token, const char **pb, const char **pe);
660
int http_GetHdrField(const struct http *hp, hdr_t,
661
    const char *field, const char **ptr);
662
double http_GetHdrQ(const struct http *hp, hdr_t, const char *field);
663
ssize_t http_GetContentLength(const struct http *hp);
664
ssize_t http_GetContentRange(const struct http *hp, ssize_t *lo, ssize_t *hi);
665
const char * http_GetRange(const struct http *hp, ssize_t *lo, ssize_t *hi,
666
    ssize_t len);
667
uint16_t http_GetStatus(const struct http *hp);
668
int http_IsStatus(const struct http *hp, int);
669
void http_SetStatus(struct http *to, uint16_t status, const char *reason);
670
const char *http_GetMethod(const struct http *hp);
671
int http_HdrIs(const struct http *hp, hdr_t, const char *val);
672
void http_CopyHome(const struct http *hp);
673
void http_Unset(struct http *hp, hdr_t);
674
unsigned http_CountHdr(const struct http *hp, hdr_t);
675
void http_CollectHdr(struct http *hp, hdr_t);
676
void http_CollectHdrSep(struct http *hp, hdr_t, const char *sep);
677
void http_VSL_log(const struct http *hp);
678
void HTTP_Merge(struct worker *, struct objcore *, struct http *to);
679
uint16_t HTTP_GetStatusPack(struct worker *, struct objcore *oc);
680
int HTTP_IterHdrPack(struct worker *, struct objcore *, const char **);
681
#define HTTP_FOREACH_PACK(wrk, oc, ptr) \
682
   for ((ptr) = NULL; HTTP_IterHdrPack(wrk, oc, &(ptr));)
683
const char *HTTP_GetHdrPack(struct worker *, struct objcore *, hdr_t);
684
stream_close_t http_DoConnection(struct http *hp, stream_close_t sc_close);
685
int http_IsFiltered(const struct http *hp, unsigned u, unsigned how);
686
void http_SetWellKnownMethod(struct http *hp);
687
688
#define HTTPH_R_PASS    (1 << 0)  /* Request (c->b) in pass mode */
689
#define HTTPH_R_FETCH   (1 << 1)  /* Request (c->b) for fetch */
690
#define HTTPH_A_INS   (1 << 2)  /* Response (b->o) for insert */
691
#define HTTPH_A_PASS    (1 << 3)  /* Response (b->o) for pass */
692
#define HTTPH_C_SPECIFIC  (1 << 4)  /* Connection-specific */
693
694
#define HTTPH(a, b, c) extern hdr_t b;
695
#include "tbl/http_headers.h"
696
697
extern hdr_t H__Status;
698
extern hdr_t H__Proto;
699
extern hdr_t H__Reason;
700
701
// rfc7233,l,1207,1208
702
#define http_tok_eq(s1, s2)   (!vct_casecmp(s1, s2))
703
#define http_tok_at(s1, s2, l)    (!vct_caselencmp(s1, s2, l))
704
#define http_ctok_at(s, cs)   (!vct_caselencmp(s, cs, sizeof(cs) - 1))
705
706
// rfc7230,l,1037,1038
707
#define http_scheme_at(str, tok)  http_ctok_at(str, #tok "://")
708
709
// rfc7230,l,1144,1144
710
// rfc7231,l,1156,1158
711
#define http_method_eq(check, wkm)  ((check & wkm) == wkm)
712
#define http_method_among(check, wkms)  ((check & (wkms)) != 0)
713
714
// rfc7230,l,1222,1222
715
// rfc7230,l,2848,2848
716
// rfc7231,l,3883,3885
717
// rfc7234,l,1339,1340
718
// rfc7234,l,1418,1419
719
#define http_hdr_eq(s1, s2)   http_tok_eq(s1, s2)
720
#define http_hdr_at(s1, s2, l)    http_tok_at(s1, s2, l)
721
722
// rfc7230,l,1952,1952
723
// rfc7231,l,604,604
724
#define http_coding_eq(str, tok)  http_tok_eq(str, #tok)
725
726
// rfc7231,l,1864,1864
727
#define http_expect_eq(str, tok)  http_tok_eq(str, #tok)
728
729
// rfc7233,l,1207,1208
730
#define http_range_at(str, tok, l)  http_tok_at(str, #tok, l)
731
732
/* cache_lck.c */
733
734
/* Internal functions, call only through macros below */
735
void Lck__Lock(struct lock *lck, const char *p,  int l);
736
void Lck__Unlock(struct lock *lck, const char *p,  int l);
737
int Lck__Trylock(struct lock *lck, const char *p,  int l);
738
void Lck__New(struct lock *lck, struct VSC_lck *, const char *);
739
int Lck__Held(const struct lock *lck);
740
int Lck__Owned(const struct lock *lck);
741
extern pthread_mutexattr_t mtxattr_errorcheck;
742
743
/* public interface: */
744
void Lck_Delete(struct lock *lck);
745
int Lck_CondWaitUntil(pthread_cond_t *, struct lock *, vtim_real when);
746
int Lck_CondWait(pthread_cond_t *, struct lock *);
747
int Lck_CondWaitTimeout(pthread_cond_t *, struct lock *, vtim_dur timeout);
748
749
#define Lck_New(a, b) Lck__New(a, b, #b)
750
#define Lck_Lock(a) Lck__Lock(a, __func__, __LINE__)
751
#define Lck_Unlock(a) Lck__Unlock(a, __func__, __LINE__)
752
#define Lck_Trylock(a) Lck__Trylock(a, __func__, __LINE__)
753
#define Lck_AssertHeld(a)   \
754
  do {        \
755
    assert(Lck__Held(a)); \
756
    assert(Lck__Owned(a));  \
757
  } while (0)
758
759
struct VSC_lck *Lck_CreateClass(struct vsc_seg **, const char *);
760
void Lck_DestroyClass(struct vsc_seg **);
761
762
#define LOCK(nam) extern struct VSC_lck *lck_##nam;
763
#include "tbl/locks.h"
764
765
/* cache_obj.c */
766
767
int ObjHasAttr(struct worker *, struct objcore *, enum obj_attr);
768
const void *ObjGetAttr(struct worker *, struct objcore *, enum obj_attr,
769
    ssize_t *len);
770
771
typedef int objiterate_f(void *priv, unsigned flush,
772
    const void *ptr, ssize_t len);
773
#define OBJ_ITER_FLUSH  0x01
774
#define OBJ_ITER_END  0x02
775
776
int ObjIterate(struct worker *, struct objcore *,
777
    void *priv, objiterate_f *func, int final);
778
779
vxid_t ObjGetXID(struct worker *, struct objcore *);
780
uint64_t ObjGetLen(struct worker *, struct objcore *);
781
int ObjGetDouble(struct worker *, struct objcore *, enum obj_attr, double *);
782
int ObjGetU64(struct worker *, struct objcore *, enum obj_attr, uint64_t *);
783
int ObjCheckFlag(struct worker *, struct objcore *, enum obj_flags of);
784
785
/*====================================================================
786
 * ObjVAI...(): Asynchronous Iteration
787
 *
788
 * see comments in cache_obj.c for usage
789
 */
790
791
typedef void *vai_hdl;
792
typedef void vai_notify_cb(vai_hdl, void *priv);
793
794
795
/*
796
 * VSCARAB: Vinyl SCatter ARAy of Buffers:
797
 *
798
 * an array of viovs, elsewhere also called an siov or sarray
799
 */
800
struct viov {
801
  uintptr_t lease;
802
  struct iovec  iov;
803
};
804
805
/*
806
 * special empty iovec to return a lease with no data once delivery has reached
807
 * this point. Allows AN(iov_base) to catch unintentional cases
808
 */
809
#define IOV_NIL ((struct iovec){.iov_base = TRUST_ME(0x42), .iov_len = 0})
810
811
/*
812
 * rules for vscarabs:
813
 * used marks the portion of the s array which is in use
814
 * used viovs must not have a NULL iov_base, use IOV_NIL
815
 * free viovs must be all zero (lease=0, iov_base=NULL, iov_len=0)
816
 */
817
struct vscarab {
818
  unsigned  magic;
819
#define VSCARAB_MAGIC 0x05ca7ab0
820
  unsigned  flags;
821
#define VSCARAB_F_END 1 // last viov is last overall
822
  unsigned  capacity;
823
  unsigned  used;
824
  struct viov s[] v_counted_by_(capacity);
825
};
826
827
// VFLA: starting generic container-with-flexible-array-member macros
828
// aka "struct hack"
829
//
830
// type : struct name
831
// name : a pointer to struct type
832
// mag  : the magic value for this VFLA
833
// cptr : pointer to container struct (aka "head")
834
// fam  : member name of the flexible array member
835
// cap  : capacity
836
//
837
// common properties of all VFLAs:
838
// - are a miniobj (have magic as the first element)
839
// - capacity member is the fam capacity
840
// - used member is the number of fam elements used
841
//
842
// VFLA_SIZE ignores the cap == 0 case, we assert in _INIT
843
// offsetoff ref: https://gustedt.wordpress.com/2011/03/14/flexible-array-member/
844
//lint -emacro(413, VFLA_SIZE)
845
//lint -emacro(545, VFLA_SIZE) bsd offsetof() seems to be using &
846
#define VFLA_SIZE(type, fam, cap) (offsetof(struct type, fam) + \
847
  (cap) * sizeof(((struct type *)0)->fam[0]))
848
#define VFLA_INIT_(type, cptr, mag, fam, cap, save) do {  \
849
  unsigned save = (cap);          \
850
  AN(save);           \
851
  memset((cptr), 0, VFLA_SIZE(type, fam, save));    \
852
  (cptr)->magic = (mag);          \
853
  (cptr)->capacity = (save);        \
854
} while (0)
855
#define VFLA_INIT(type, cptr, mag, fam, cap)      \
856
  VFLA_INIT_(type, cptr, mag, fam, cap, VUNIQ_NAME(save))
857
// declare, allocate and initialize a local VFLA
858
// the additional VLA buf declaration avoids
859
// "Variable-sized object may not be initialized"
860
//lint -emacro(413, VFLA_LOCAL_)
861
#define VFLA_LOCAL_(type, name, mag, fam, cap, bufname)       \
862
  uintptr_t bufname[(VFLA_SIZE(type, fam, cap) + sizeof(uintptr_t) -1) / sizeof(uintptr_t)]; \
863
  struct type *name = (void *)bufname;          \
864
  VFLA_INIT(type, name, mag, fam, cap)
865
#define VFLA_LOCAL(type, name, mag, fam, cap)         \
866
  VFLA_LOCAL_(type, name, mag, fam, cap, VUNIQ_NAME(buf))
867
// malloc and initialize a VFLA
868
#define VFLA_ALLOC(type, name, mag, fam, cap) do {      \
869
  (name) = malloc(VFLA_SIZE(type, fam, cap));     \
870
  if ((name) != NULL)           \
871
    VFLA_INIT(type, name, mag, fam, cap);     \
872
} while(0)
873
#define VFLA_FOREACH(var, cptr, fam)            \
874
  for (var = &(cptr)->fam[0];           \
875
       (var = (var < &(cptr)->fam[(cptr)->used] ? var : NULL)) != NULL; \
876
       var++)
877
// continue iterating after a break of a _FOREACH
878
#define VFLA_FOREACH_RESUME(var, cptr, fam)         \
879
  for (;                  \
880
       var != NULL &&             \
881
         (var = (var < &(cptr)->fam[(cptr)->used] ? var : NULL)) != NULL; \
882
       var++)
883
#define VFLA_GET(cptr, fam) ((cptr)->used < (cptr)->capacity ? &(cptr)->fam[(cptr)->used++] : NULL)
884
// asserts sufficient capacity
885
#define VFLA_ADD(cptr, fam, val) do {           \
886
  assert((cptr)->used < (cptr)->capacity);        \
887
  (cptr)->fam[(cptr)->used++] = (val);          \
888
} while(0)
889
890
#define VSCARAB_SIZE(cap) VFLA_SIZE(vscarab, s, cap)
891
#define VSCARAB_INIT(scarab, cap) VFLA_INIT(vscarab, scarab, VSCARAB_MAGIC, s, cap)
892
#define VSCARAB_LOCAL(scarab, cap) VFLA_LOCAL(vscarab, scarab, VSCARAB_MAGIC, s, cap)
893
#define VSCARAB_ALLOC(scarab, cap) VFLA_ALLOC(vscarab, scarab, VSCARAB_MAGIC, s, cap)
894
#define VSCARAB_FOREACH(var, scarab) VFLA_FOREACH(var, scarab, s)
895
#define VSCARAB_FOREACH_RESUME(var, scarab) VFLA_FOREACH_RESUME(var, scarab, s)
896
#define VSCARAB_GET(scarab) VFLA_GET(scarab, s)
897
#define VSCARAB_ADD(scarab, val) VFLA_ADD(scarab, s, val)
898
//lint -emacro(64, VSCARAB_ADD_IOV_NORET) weird flexelint bug?
899
#define VSCARAB_ADD_IOV_NORET(scarab, vec)          \
900
  VSCARAB_ADD(scarab, ((struct viov){.lease = VAI_LEASE_NORET, .iov = (vec)}))
901
#define VSCARAB_LAST(scarab) ((scarab)->used > 0 ?        \
902
  &(scarab)->s[(scarab)->used - 1] : NULL)
903
904
#define VSCARAB_CHECK(scarab) do {            \
905
  CHECK_OBJ(scarab, VSCARAB_MAGIC);         \
906
  assert((scarab)->used <= (scarab)->capacity);       \
907
} while(0)
908
909
#define VSCARAB_CHECK_NOTNULL(scarab) do {          \
910
  AN(scarab);               \
911
  VSCARAB_CHECK(scarab);              \
912
} while(0)
913
914
/*
915
 * VSCARET: Vinyl SCatter Array Return
916
 *
917
 * an array of leases obtained from a vscarab
918
 */
919
920
struct vscaret {
921
  unsigned  magic;
922
#define VSCARET_MAGIC 0x9c1f3d7b
923
  unsigned  capacity;
924
  unsigned  used;
925
  uintptr_t lease[] v_counted_by_(capacity);
926
};
927
928
#define VSCARET_SIZE(cap) VFLA_SIZE(vscaret, lease, cap)
929
#define VSCARET_INIT(scaret, cap) VFLA_INIT(vscaret, scaret, VSCARET_MAGIC, lease, cap)
930
#define VSCARET_LOCAL(scaret, cap) VFLA_LOCAL(vscaret, scaret, VSCARET_MAGIC, lease, cap)
931
#define VSCARET_ALLOC(scaret, cap) VFLA_ALLOC(vscaret, scaret, VSCARET_MAGIC, lease, cap)
932
#define VSCARET_FOREACH(var, scaret) VFLA_FOREACH(var, scaret, lease)
933
#define VSCARET_GET(scaret) VFLA_GET(scaret, lease)
934
#define VSCARET_ADD(scaret, val) VFLA_ADD(scaret, lease, val)
935
936
#define VSCARET_CHECK(scaret) do {            \
937
  CHECK_OBJ(scaret, VSCARET_MAGIC);         \
938
  assert(scaret->used <= scaret->capacity);       \
939
} while(0)
940
941
#define VSCARET_CHECK_NOTNULL(scaret) do {          \
942
  AN(scaret);               \
943
  VSCARET_CHECK(scaret);              \
944
} while(0)
945
946
/*
947
 * VSCARABs can contain leases which are not to be returned to storage, for
948
 * example static data or fragments of larger leases to be returned later. For
949
 * these cases, use this magic value as the lease. This is deliberately not 0 to
950
 * catch oversights.
951
 */
952
#define VAI_LEASE_NORET ((uint64_t)0x8)
953
954
vai_hdl ObjVAIinit(struct worker *, struct objcore *, struct ws *,
955
    vai_notify_cb *, void *);
956
int ObjVAIlease(struct worker *, vai_hdl, struct vscarab *);
957
int ObjVAIbuffer(struct worker *, vai_hdl, struct vscarab *);
958
void ObjVAIreturn(struct worker *, vai_hdl, struct vscaret *);
959
void ObjVAInotify(struct worker *, vai_hdl);
960
void ObjVAIfini(struct worker *, vai_hdl *);
961
962
/* cache_req_body.c */
963
ssize_t VRB_Iterate(struct worker *, struct vsl_log *, struct req *,
964
    objiterate_f *func, void *priv);
965
966
/* cache_session.c [SES] */
967
968
#define SESS_ATTR(UP, low, typ, len)          \
969
  int SES_Get_##low(const struct sess *sp, typ **dst);
970
#include "tbl/sess_attr.h"
971
const char *SES_Get_String_Attr(const struct sess *sp, enum sess_attr a);
972
973
/* cache_shmlog.c */
974
void VSLv(enum VSL_tag_e tag, vxid_t vxid, const char *fmt, va_list va);
975
void VSL(enum VSL_tag_e tag, vxid_t vxid, const char *fmt, ...)
976
    v_printflike_(3, 4);
977
void VSLs(enum VSL_tag_e tag, vxid_t vxid, const struct strands *s);
978
void VSLbv(struct vsl_log *, enum VSL_tag_e tag, const char *fmt, va_list va);
979
void VSLb(struct vsl_log *, enum VSL_tag_e tag, const char *fmt, ...)
980
    v_printflike_(3, 4);
981
void VSLbt(struct vsl_log *, enum VSL_tag_e tag, txt t);
982
void VSLbs(struct vsl_log *, enum VSL_tag_e tag, const struct strands *s);
983
void VSLb_ts(struct vsl_log *, const char *event, vtim_real first,
984
    vtim_real *pprev, vtim_real now);
985
void VSLb_bin(struct vsl_log *, enum VSL_tag_e, ssize_t, const void*);
986
int VSL_tag_is_masked(enum VSL_tag_e tag);
987
988
static inline void
989
VSLb_ts_req(struct req *req, const char *event, vtim_real now)
990
0
{
991
0
992
0
  if (isnan(req->t_first) || req->t_first == 0.)
993
0
    req->t_first = req->t_prev = now;
994
0
  VSLb_ts(req->vsl, event, req->t_first, &req->t_prev, now);
995
0
}
Unexecuted instantiation: cache_ws_emu.c:VSLb_ts_req
Unexecuted instantiation: cache_ws_common.c:VSLb_ts_req
Unexecuted instantiation: cache_esi_parse.c:VSLb_ts_req
Unexecuted instantiation: esi_parse_fuzzer.c:VSLb_ts_req
996
997
static inline void
998
VSLb_ts_busyobj(struct busyobj *bo, const char *event, vtim_real now)
999
0
{
1000
0
1001
0
  if (isnan(bo->t_first) || bo->t_first == 0.)
1002
0
    bo->t_first = bo->t_prev = now;
1003
0
  VSLb_ts(bo->vsl, event, bo->t_first, &bo->t_prev, now);
1004
0
}
Unexecuted instantiation: cache_ws_emu.c:VSLb_ts_busyobj
Unexecuted instantiation: cache_ws_common.c:VSLb_ts_busyobj
Unexecuted instantiation: cache_esi_parse.c:VSLb_ts_busyobj
Unexecuted instantiation: esi_parse_fuzzer.c:VSLb_ts_busyobj
1005
1006
/* cache_vcl.c */
1007
const char *VCL_Name(const struct vcl *);
1008
1009
/* cache_wrk.c */
1010
1011
typedef void *bgthread_t(struct worker *, void *priv);
1012
void WRK_BgThread(pthread_t *thr, const char *name, bgthread_t *func,
1013
    void *priv);
1014
1015
/* cache_ws.c */
1016
void WS_Init(struct ws *ws, const char *id, void *space, unsigned len);
1017
1018
unsigned WS_ReserveSize(struct ws *, unsigned);
1019
unsigned WS_ReserveAll(struct ws *);
1020
void WS_Release(struct ws *ws, unsigned bytes);
1021
void WS_ReleaseP(struct ws *ws, const char *ptr);
1022
void WS_Assert(const struct ws *ws);
1023
void WS_Reset(struct ws *ws, uintptr_t);
1024
void *WS_Alloc(struct ws *ws, unsigned bytes);
1025
void *WS_Copy(struct ws *ws, const void *str, int len);
1026
uintptr_t WS_Snapshot(struct ws *ws);
1027
int WS_Allocated(const struct ws *ws, const void *ptr, ssize_t len);
1028
unsigned WS_Dump(const struct ws *ws, char, size_t off, void *buf, size_t len);
1029
1030
static inline void *
1031
WS_Reservation(const struct ws *ws)
1032
0
{
1033
1034
0
  WS_Assert(ws);
1035
0
  AN(ws->r);
1036
0
  AN(ws->f);
1037
0
  return (ws->f);
1038
0
}
Unexecuted instantiation: cache_ws_emu.c:WS_Reservation
Unexecuted instantiation: cache_ws_common.c:WS_Reservation
Unexecuted instantiation: cache_esi_parse.c:WS_Reservation
Unexecuted instantiation: esi_parse_fuzzer.c:WS_Reservation
1039
1040
static inline unsigned
1041
WS_ReservationSize(const struct ws *ws)
1042
0
{
1043
0
1044
0
  AN(ws->r);
1045
0
  return (ws->r - ws->f);
1046
0
}
Unexecuted instantiation: cache_ws_emu.c:WS_ReservationSize
Unexecuted instantiation: cache_ws_common.c:WS_ReservationSize
Unexecuted instantiation: cache_esi_parse.c:WS_ReservationSize
Unexecuted instantiation: esi_parse_fuzzer.c:WS_ReservationSize
1047
1048
static inline unsigned
1049
WS_ReserveLumps(struct ws *ws, size_t sz)
1050
0
{
1051
0
1052
0
  AN(sz);
1053
0
  return (WS_ReserveAll(ws) / sz);
1054
0
}
Unexecuted instantiation: cache_ws_emu.c:WS_ReserveLumps
Unexecuted instantiation: cache_ws_common.c:WS_ReserveLumps
Unexecuted instantiation: cache_esi_parse.c:WS_ReserveLumps
Unexecuted instantiation: esi_parse_fuzzer.c:WS_ReserveLumps
1055
1056
/* cache_ws_common.c */
1057
void WS_MarkOverflow(struct ws *ws);
1058
int WS_Overflowed(const struct ws *ws);
1059
1060
const char *WS_Printf(struct ws *ws, const char *fmt, ...) v_printflike_(2, 3);
1061
1062
void WS_VSB_new(struct vsb *, struct ws *);
1063
char *WS_VSB_finish(struct vsb *, struct ws *, size_t *);
1064
1065
/* WS utility */
1066
#define WS_TASK_ALLOC_OBJ(ctx, ptr, magic) do {     \
1067
  ptr = WS_Alloc((ctx)->ws, sizeof *(ptr));   \
1068
  if ((ptr) == NULL)          \
1069
    VRT_fail(ctx, "Out of workspace for " #magic);  \
1070
  else              \
1071
    INIT_OBJ(ptr, magic);       \
1072
} while(0)
1073
1074
/* cache_rfc2616.c */
1075
void RFC2616_Ttl(struct busyobj *, vtim_real now, vtim_real *t_origin,
1076
    float *ttl, float *grace, float *keep);
1077
unsigned RFC2616_Req_Gzip(const struct http *);
1078
int RFC2616_Do_Cond(const struct req *sp);
1079
void RFC2616_Weaken_Etag(struct http *hp);
1080
void RFC2616_Vary_AE(struct http *hp);
1081
const char * RFC2616_Strong_LM(const struct http *hp, struct worker *wrk,
1082
    struct objcore *oc);
1083
1084
/*
1085
 * We want to cache the most recent timestamp in wrk->lastused to avoid
1086
 * extra timestamps in cache_pool.c.  Hide this detail with a macro
1087
 */
1088
#define W_TIM_real(w) ((w)->lastused = VTIM_real())