summaryrefslogtreecommitdiff
path: root/header-value-parser.c
blob: aeab7d3f2d38f91e701cc61a91ce2e1e81e9be01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "internal.h"

//
// header value parser
//

fhp_err_t
fhp_header_value_parser_init(fhp_t * const fhp) {
  uint32_t hash = fhp->header_name_hash;
  fhp_header_value_parser_t parser = FHP_HEADER_VALUE_PARSER_NONE;
  fhp_err_t err;

  /* fprintf(
    stderr,
    "hashes: header = %u, env = %u, str = %u, str(lc) = %u\n",
    hash,
    fhp->env->hashes[FHP_STR_TRANSFER_ENCODING],
    fhp_hash_string("Transfer-Encoding"),
    fhp_lc_hash_string("Transfer-Encoding")
  ); */

  if (hash == fhp->env->hashes[FHP_STR_TRANSFER_ENCODING]) {
    // set parser type
    parser = FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING;

    // init parser
    if ((err = fhp_te_parser_init(&(fhp->parsers.te))) != FHP_OK)
      return err;
  } else if (hash == fhp->env->hashes[FHP_STR_CONTENT_LENGTH]) {
    // set parser type
    parser = FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH;

    // init parser
    if ((err = fhp_cl_parser_init(&(fhp->parsers.cl))) != FHP_OK)
      return err;
  } else {
    // set default parser type
    parser = FHP_HEADER_VALUE_PARSER_NONE;
  }

  // set value parser
  fhp->header_value_parser = parser;

  // return success
  return FHP_OK;
}

fhp_err_t
fhp_header_value_parser_push(
  fhp_t * const fhp,
  uint8_t * const buf,
  size_t len
) {
  fhp_err_t r = FHP_OK;

  switch (fhp->header_value_parser) {
  case FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING:
    r = fhp_te_parser_push(&(fhp->parsers.te), buf, len);
    break;
  case FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH:
    r = fhp_cl_parser_push(&(fhp->parsers.cl), buf, len);
    break;
  default:
    // do nothing
    r = FHP_OK;
    break;
  }

  // return result
  return r;
}

fhp_err_t
fhp_header_value_parser_done(fhp_t * const fhp) {
  fhp_err_t r = FHP_OK;

  switch (fhp->header_value_parser) {
  case FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING:
    // finish parsing tes
    if ((r = fhp_te_parser_done(&(fhp->parsers.te), &(fhp->num_tes))) != FHP_OK)
      return r;

    // check number of tes
    if (fhp->num_tes > FHP_MAX_TRANSFER_ENCODINGS)
      return FHP_ERR_TOO_MANY_TES;

    // copy tes to context
    if ((r = fhp_te_parser_get_tes(&(fhp->parsers.te), fhp->tes, FHP_MAX_TRANSFER_ENCODINGS)) != FHP_OK)
      return r;

    // notify callback
    if (!fhp->cb(fhp, FHP_TOKEN_HEADER_TRANSFER_ENCODING, 0, 0))
      return FHP_ERR_CB;

    break;
  case FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH:
    // finish parsing content-length and copy to context
    if ((r = fhp_cl_parser_done(&(fhp->parsers.cl), &(fhp->content_length))) != FHP_OK)
      return r;

    // notify callback
    if (!fhp->cb(fhp, FHP_TOKEN_HEADER_CONTENT_LENGTH, 0, 0))
      return FHP_ERR_CB;

    break;
  default:
    // do nothing
    r = FHP_OK;

    break;
  }

  // clear header value parser
  fhp->header_value_parser = FHP_HEADER_VALUE_PARSER_NONE;

  // return result
  return r;
}