Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include "src/core/transport/chttp2/incoming_metadata.h"
35 :
36 : #include <string.h>
37 :
38 : #include "src/core/transport/chttp2/internal.h"
39 :
40 : #include <grpc/support/alloc.h>
41 : #include <grpc/support/log.h>
42 :
43 5400327 : void grpc_chttp2_incoming_metadata_buffer_init(
44 : grpc_chttp2_incoming_metadata_buffer *buffer) {
45 5400327 : buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
46 5408465 : }
47 :
48 5403750 : void grpc_chttp2_incoming_metadata_buffer_destroy(
49 : grpc_chttp2_incoming_metadata_buffer *buffer) {
50 : size_t i;
51 5673065 : for (i = 0; i < buffer->count; i++) {
52 269292 : GRPC_MDELEM_UNREF(buffer->elems[i].md);
53 : }
54 5403773 : gpr_free(buffer->elems);
55 5403863 : }
56 :
57 19113636 : void grpc_chttp2_incoming_metadata_buffer_add(
58 : grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) {
59 19113636 : if (buffer->capacity == buffer->count) {
60 4294677 : buffer->capacity = GPR_MAX(8, 2 * buffer->capacity);
61 4294986 : buffer->elems =
62 4294677 : gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity);
63 : }
64 19113945 : buffer->elems[buffer->count++].md = elem;
65 19113945 : }
66 :
67 5187 : void grpc_chttp2_incoming_metadata_buffer_set_deadline(
68 : grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) {
69 5187 : buffer->deadline = deadline;
70 5187 : }
71 :
72 8040000 : void grpc_chttp2_incoming_metadata_live_op_buffer_end(
73 : grpc_chttp2_incoming_metadata_live_op_buffer *buffer) {
74 8040000 : gpr_free(buffer->elems);
75 8042993 : buffer->elems = NULL;
76 8042993 : }
77 :
78 4387043 : void grpc_chttp2_incoming_metadata_buffer_place_metadata_batch_into(
79 : grpc_chttp2_incoming_metadata_buffer *buffer, grpc_stream_op_buffer *sopb) {
80 : grpc_metadata_batch b;
81 :
82 4387043 : b.list.head = NULL;
83 : /* Store away the last element of the list, so that in patch_metadata_ops
84 : we can reconstitute the list.
85 : We can't do list building here as later incoming metadata may reallocate
86 : the underlying array. */
87 4387043 : b.list.tail = (void *)(gpr_intptr)buffer->count;
88 4387043 : b.garbage.head = b.garbage.tail = NULL;
89 4387043 : b.deadline = buffer->deadline;
90 4387043 : buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
91 :
92 4391233 : grpc_sopb_add_metadata(sopb, b);
93 4390951 : }
94 :
95 2714973 : void grpc_chttp2_incoming_metadata_buffer_swap(
96 : grpc_chttp2_incoming_metadata_buffer *a,
97 : grpc_chttp2_incoming_metadata_buffer *b) {
98 2714973 : GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, *a, *b);
99 2714973 : }
100 :
101 4040994 : void grpc_incoming_metadata_buffer_move_to_referencing_sopb(
102 : grpc_chttp2_incoming_metadata_buffer *src,
103 : grpc_chttp2_incoming_metadata_buffer *dst, grpc_stream_op_buffer *sopb) {
104 : size_t delta;
105 : size_t i;
106 4040994 : dst->deadline = gpr_time_min(src->deadline, dst->deadline);
107 :
108 4041783 : if (src->count == 0) {
109 1326799 : return;
110 : }
111 2714984 : if (dst->count == 0) {
112 2714977 : grpc_chttp2_incoming_metadata_buffer_swap(src, dst);
113 2712179 : return;
114 : }
115 7 : delta = dst->count;
116 7 : if (dst->capacity < src->count + dst->count) {
117 7 : dst->capacity = GPR_MAX(dst->capacity * 2, src->count + dst->count);
118 7 : dst->elems = gpr_realloc(dst->elems, dst->capacity * sizeof(*dst->elems));
119 : }
120 7 : memcpy(dst->elems + dst->count, src->elems, src->count * sizeof(*src->elems));
121 7 : dst->count += src->count;
122 14 : for (i = 0; i < sopb->nops; i++) {
123 7 : if (sopb->ops[i].type != GRPC_OP_METADATA) continue;
124 14 : sopb->ops[i].data.metadata.list.tail =
125 7 : (void *)(delta + (gpr_uintptr)sopb->ops[i].data.metadata.list.tail);
126 : }
127 7 : src->count = 0;
128 : }
129 :
130 5337698 : void grpc_chttp2_incoming_metadata_buffer_postprocess_sopb_and_begin_live_op(
131 : grpc_chttp2_incoming_metadata_buffer *buffer, grpc_stream_op_buffer *sopb,
132 : grpc_chttp2_incoming_metadata_live_op_buffer *live_op_buffer) {
133 5337698 : grpc_stream_op *ops = sopb->ops;
134 5337698 : size_t nops = sopb->nops;
135 : size_t i;
136 : size_t j;
137 5337698 : size_t mdidx = 0;
138 : size_t last_mdidx;
139 5337698 : int found_metadata = 0;
140 :
141 : /* rework the array of metadata into a linked list, making use
142 : of the breadcrumbs we left in metadata batches during
143 : add_metadata_batch */
144 19498483 : for (i = 0; i < nops; i++) {
145 14154547 : grpc_stream_op *op = &ops[i];
146 14154547 : if (op->type != GRPC_OP_METADATA) continue;
147 4113577 : found_metadata = 1;
148 : /* we left a breadcrumb indicating where the end of this list is,
149 : and since we add sequentially, we know from the end of the last
150 : segment where this segment begins */
151 4113577 : last_mdidx = (size_t)(gpr_intptr)(op->data.metadata.list.tail);
152 4113577 : GPR_ASSERT(last_mdidx > mdidx);
153 4119815 : GPR_ASSERT(last_mdidx <= buffer->count);
154 : /* turn the array into a doubly linked list */
155 4119815 : op->data.metadata.list.head = &buffer->elems[mdidx];
156 4119815 : op->data.metadata.list.tail = &buffer->elems[last_mdidx - 1];
157 18831544 : for (j = mdidx + 1; j < last_mdidx; j++) {
158 14711729 : buffer->elems[j].prev = &buffer->elems[j - 1];
159 14711729 : buffer->elems[j - 1].next = &buffer->elems[j];
160 : }
161 4119815 : buffer->elems[mdidx].prev = NULL;
162 4119815 : buffer->elems[last_mdidx - 1].next = NULL;
163 : /* track where we're up to */
164 4119815 : mdidx = last_mdidx;
165 : }
166 5343936 : if (found_metadata) {
167 2724701 : live_op_buffer->elems = buffer->elems;
168 2724701 : if (mdidx != buffer->count) {
169 : /* we have a partially read metadata batch still in incoming_metadata */
170 7 : size_t new_count = buffer->count - mdidx;
171 7 : size_t copy_bytes = sizeof(*buffer->elems) * new_count;
172 7 : GPR_ASSERT(mdidx < buffer->count);
173 7 : buffer->elems = gpr_malloc(copy_bytes);
174 7 : memcpy(buffer->elems, live_op_buffer->elems + mdidx, copy_bytes);
175 7 : buffer->count = buffer->capacity = new_count;
176 : } else {
177 2724694 : buffer->elems = NULL;
178 2724694 : buffer->count = 0;
179 2724694 : buffer->capacity = 0;
180 : }
181 : }
182 5343936 : }
|