• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.netty;
18 
19 import io.netty.handler.codec.http2.Http2Headers;
20 import io.netty.util.AsciiString;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.NoSuchElementException;
24 
25 /**
26  * A custom implementation of Http2Headers that only includes methods used by gRPC.
27  */
28 final class GrpcHttp2OutboundHeaders extends AbstractHttp2Headers {
29 
30   private final AsciiString[] normalHeaders;
31   private final AsciiString[] preHeaders;
32   private static final AsciiString[] EMPTY = new AsciiString[]{};
33 
clientRequestHeaders(byte[][] serializedMetadata, AsciiString authority, AsciiString path, AsciiString method, AsciiString scheme, AsciiString userAgent)34   static GrpcHttp2OutboundHeaders clientRequestHeaders(byte[][] serializedMetadata,
35       AsciiString authority, AsciiString path, AsciiString method, AsciiString scheme,
36       AsciiString userAgent) {
37     AsciiString[] preHeaders = new AsciiString[] {
38         Http2Headers.PseudoHeaderName.AUTHORITY.value(), authority,
39         Http2Headers.PseudoHeaderName.PATH.value(), path,
40         Http2Headers.PseudoHeaderName.METHOD.value(), method,
41         Http2Headers.PseudoHeaderName.SCHEME.value(), scheme,
42         Utils.CONTENT_TYPE_HEADER, Utils.CONTENT_TYPE_GRPC,
43         Utils.TE_HEADER, Utils.TE_TRAILERS,
44         Utils.USER_AGENT, userAgent,
45     };
46     return new GrpcHttp2OutboundHeaders(preHeaders, serializedMetadata);
47   }
48 
serverResponseHeaders(byte[][] serializedMetadata)49   static GrpcHttp2OutboundHeaders serverResponseHeaders(byte[][] serializedMetadata) {
50     AsciiString[] preHeaders = new AsciiString[] {
51         Http2Headers.PseudoHeaderName.STATUS.value(), Utils.STATUS_OK,
52         Utils.CONTENT_TYPE_HEADER, Utils.CONTENT_TYPE_GRPC,
53     };
54     return new GrpcHttp2OutboundHeaders(preHeaders, serializedMetadata);
55   }
56 
serverResponseTrailers(byte[][] serializedMetadata)57   static GrpcHttp2OutboundHeaders serverResponseTrailers(byte[][] serializedMetadata) {
58     return new GrpcHttp2OutboundHeaders(EMPTY, serializedMetadata);
59   }
60 
GrpcHttp2OutboundHeaders(AsciiString[] preHeaders, byte[][] serializedMetadata)61   private GrpcHttp2OutboundHeaders(AsciiString[] preHeaders, byte[][] serializedMetadata) {
62     normalHeaders = new AsciiString[serializedMetadata.length];
63     for (int i = 0; i < normalHeaders.length; i++) {
64       normalHeaders[i] = new AsciiString(serializedMetadata[i], false);
65     }
66     this.preHeaders = preHeaders;
67   }
68 
69   @Override
70   @SuppressWarnings("ReferenceEquality") // STATUS.value() never changes.
status()71   public CharSequence status() {
72     // preHeaders is never null.  It has status as the first element or not at all.
73     if (preHeaders.length >= 2 && preHeaders[0] == Http2Headers.PseudoHeaderName.STATUS.value()) {
74       return preHeaders[1];
75     }
76     return null;
77   }
78 
79   @Override
iterator()80   public Iterator<Map.Entry<CharSequence, CharSequence>> iterator() {
81     return new Itr();
82   }
83 
84   @Override
size()85   public int size() {
86     return (normalHeaders.length + preHeaders.length) / 2;
87   }
88 
89   private class Itr implements Map.Entry<CharSequence, CharSequence>,
90       Iterator<Map.Entry<CharSequence, CharSequence>> {
91     private int idx;
92     private AsciiString[] current = preHeaders.length != 0 ? preHeaders : normalHeaders;
93     private AsciiString key;
94     private AsciiString value;
95 
96     @Override
hasNext()97     public boolean hasNext() {
98       return idx < current.length;
99     }
100 
101     /**
102      * This function is ordered specifically to get ideal performance on OpenJDK.  If you decide to
103      * change it, even in ways that don't seem possible to affect performance, please benchmark
104      * speeds before and after.
105      */
106     @Override
next()107     public Map.Entry<CharSequence, CharSequence> next() {
108       if (hasNext()) {
109         key = current[idx];
110         value = current[idx + 1];
111         idx += 2;
112         if (idx >= current.length && current == preHeaders) {
113           current = normalHeaders;
114           idx = 0;
115         }
116         return this;
117       } else {
118         throw new NoSuchElementException();
119       }
120     }
121 
122     @Override
getKey()123     public CharSequence getKey() {
124       return key;
125     }
126 
127     @Override
getValue()128     public CharSequence getValue() {
129       return value;
130     }
131 
132     @Override
setValue(CharSequence value)133     public CharSequence setValue(CharSequence value) {
134       throw new UnsupportedOperationException();
135     }
136 
137     @Override
remove()138     public void remove() {
139       throw new UnsupportedOperationException();
140     }
141   }
142 
143   @Override
toString()144   public String toString() {
145     StringBuilder builder = new StringBuilder(getClass().getSimpleName()).append('[');
146     String separator = "";
147     for (Map.Entry<CharSequence, CharSequence> e : this) {
148       CharSequence name = e.getKey();
149       CharSequence value = e.getValue();
150       builder.append(separator);
151       builder.append(name).append(": ").append(value);
152       separator = ", ";
153     }
154     builder.append(']');
155     return builder.toString();
156   }
157 }
158