1 /* 2 * Copyright 2014 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; 18 19 import static com.google.common.base.Charsets.US_ASCII; 20 import static com.google.common.base.Preconditions.checkArgument; 21 import static com.google.common.base.Preconditions.checkNotNull; 22 23 import com.google.common.annotations.VisibleForTesting; 24 import com.google.common.base.Preconditions; 25 import com.google.common.io.BaseEncoding; 26 import com.google.common.io.ByteStreams; 27 import java.io.ByteArrayInputStream; 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.nio.ByteBuffer; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.BitSet; 34 import java.util.Collections; 35 import java.util.HashMap; 36 import java.util.HashSet; 37 import java.util.Iterator; 38 import java.util.List; 39 import java.util.Locale; 40 import java.util.Map; 41 import java.util.NoSuchElementException; 42 import java.util.Set; 43 import java.util.logging.Level; 44 import java.util.logging.Logger; 45 import javax.annotation.Nullable; 46 import javax.annotation.concurrent.Immutable; 47 import javax.annotation.concurrent.NotThreadSafe; 48 49 /** 50 * Provides access to read and write metadata values to be exchanged during a call. 51 * 52 * <p>Keys are allowed to be associated with more than one value. 53 * 54 * <p>This class is not thread safe, implementations should ensure that header reads and writes do 55 * not occur in multiple threads concurrently. 56 */ 57 @NotThreadSafe 58 public final class Metadata { 59 private static final Logger logger = Logger.getLogger(Metadata.class.getName()); 60 61 /** 62 * All binary headers should have this suffix in their names. Vice versa. 63 * 64 * <p>Its value is {@code "-bin"}. An ASCII header's name must not end with this. 65 */ 66 public static final String BINARY_HEADER_SUFFIX = "-bin"; 67 68 /** 69 * Simple metadata marshaller that encodes bytes as is. 70 * 71 * <p>This should be used when raw bytes are favored over un-serialized version of object. Can be 72 * helpful in situations where more processing to bytes is needed on application side, avoids 73 * double encoding/decoding. 74 * 75 * <p>Both {@link BinaryMarshaller#toBytes} and {@link BinaryMarshaller#parseBytes} methods do not 76 * return a copy of the byte array. Do _not_ modify the byte arrays of either the arguments or 77 * return values. 78 */ 79 public static final BinaryMarshaller<byte[]> BINARY_BYTE_MARSHALLER = 80 new BinaryMarshaller<byte[]>() { 81 82 @Override 83 public byte[] toBytes(byte[] value) { 84 return value; 85 } 86 87 @Override 88 public byte[] parseBytes(byte[] serialized) { 89 return serialized; 90 } 91 }; 92 93 /** 94 * Simple metadata marshaller that encodes strings as is. 95 * 96 * <p>This should be used with ASCII strings that only contain the characters listed in the class 97 * comment of {@link AsciiMarshaller}. Otherwise the output may be considered invalid and 98 * discarded by the transport, or the call may fail. 99 */ 100 public static final AsciiMarshaller<String> ASCII_STRING_MARSHALLER = 101 new AsciiMarshaller<String>() { 102 103 @Override 104 public String toAsciiString(String value) { 105 return value; 106 } 107 108 @Override 109 public String parseAsciiString(String serialized) { 110 return serialized; 111 } 112 }; 113 114 static final BaseEncoding BASE64_ENCODING_OMIT_PADDING = BaseEncoding.base64().omitPadding(); 115 116 /** 117 * Constructor called by the transport layer when it receives binary metadata. Metadata will 118 * mutate the passed in array. 119 */ Metadata(byte[]... binaryValues)120 Metadata(byte[]... binaryValues) { 121 this(binaryValues.length / 2, binaryValues); 122 } 123 124 /** 125 * Constructor called by the transport layer when it receives binary metadata. Metadata will 126 * mutate the passed in array. 127 * 128 * @param usedNames the number of names 129 */ Metadata(int usedNames, byte[]... binaryValues)130 Metadata(int usedNames, byte[]... binaryValues) { 131 this(usedNames, (Object[]) binaryValues); 132 } 133 134 /** 135 * Constructor called by the transport layer when it receives partially-parsed metadata. 136 * Metadata will mutate the passed in array. 137 * 138 * @param usedNames the number of names 139 * @param namesAndValues an array of interleaved names and values, with each name 140 * (at even indices) represented by a byte array, and values (at odd indices) as 141 * described by {@link InternalMetadata#newMetadataWithParsedValues}. 142 */ Metadata(int usedNames, Object[] namesAndValues)143 Metadata(int usedNames, Object[] namesAndValues) { 144 assert (namesAndValues.length & 1) == 0 145 : "Odd number of key-value pairs " + namesAndValues.length; 146 size = usedNames; 147 this.namesAndValues = namesAndValues; 148 } 149 150 private Object[] namesAndValues; 151 // The unscaled number of headers present. 152 private int size; 153 name(int i)154 private byte[] name(int i) { 155 return (byte[]) namesAndValues[i * 2]; 156 } 157 name(int i, byte[] name)158 private void name(int i, byte[] name) { 159 namesAndValues[i * 2] = name; 160 } 161 value(int i)162 private Object value(int i) { 163 return namesAndValues[i * 2 + 1]; 164 } 165 value(int i, byte[] value)166 private void value(int i, byte[] value) { 167 namesAndValues[i * 2 + 1] = value; 168 } 169 value(int i, Object value)170 private void value(int i, Object value) { 171 if (namesAndValues instanceof byte[][]) { 172 // Reallocate an array of Object. 173 expand(cap()); 174 } 175 namesAndValues[i * 2 + 1] = value; 176 } 177 valueAsBytes(int i)178 private byte[] valueAsBytes(int i) { 179 Object value = value(i); 180 if (value instanceof byte[]) { 181 return (byte[]) value; 182 } else { 183 return ((LazyValue<?>) value).toBytes(); 184 } 185 } 186 valueAsBytesOrStream(int i)187 private Object valueAsBytesOrStream(int i) { 188 Object value = value(i); 189 if (value instanceof byte[]) { 190 return value; 191 } else { 192 return ((LazyValue<?>) value).toStream(); 193 } 194 } 195 valueAsT(int i, Key<T> key)196 private <T> T valueAsT(int i, Key<T> key) { 197 Object value = value(i); 198 if (value instanceof byte[]) { 199 return key.parseBytes((byte[]) value); 200 } else { 201 return ((LazyValue<?>) value).toObject(key); 202 } 203 } 204 cap()205 private int cap() { 206 return namesAndValues != null ? namesAndValues.length : 0; 207 } 208 209 // The scaled version of size. len()210 private int len() { 211 return size * 2; 212 } 213 214 /** checks when {@link #namesAndValues} is null or has no elements. */ isEmpty()215 private boolean isEmpty() { 216 return size == 0; 217 } 218 219 /** Constructor called by the application layer when it wants to send metadata. */ Metadata()220 public Metadata() {} 221 222 /** Returns the total number of key-value headers in this metadata, including duplicates. */ headerCount()223 int headerCount() { 224 return size; 225 } 226 227 /** 228 * Returns true if a value is defined for the given key. 229 * 230 * <p>This is done by linear search, so if it is followed by {@link #get} or {@link #getAll}, 231 * prefer calling them directly and checking the return value against {@code null}. 232 */ containsKey(Key<?> key)233 public boolean containsKey(Key<?> key) { 234 for (int i = 0; i < size; i++) { 235 if (bytesEqual(key.asciiName(), name(i))) { 236 return true; 237 } 238 } 239 return false; 240 } 241 242 /** 243 * Returns the last metadata entry added with the name 'name' parsed as T. 244 * 245 * @return the parsed metadata entry or null if there are none. 246 */ 247 @Nullable get(Key<T> key)248 public <T> T get(Key<T> key) { 249 for (int i = size - 1; i >= 0; i--) { 250 if (bytesEqual(key.asciiName(), name(i))) { 251 return valueAsT(i, key); 252 } 253 } 254 return null; 255 } 256 257 private final class IterableAt<T> implements Iterable<T> { 258 private final Key<T> key; 259 private int startIdx; 260 IterableAt(Key<T> key, int startIdx)261 private IterableAt(Key<T> key, int startIdx) { 262 this.key = key; 263 this.startIdx = startIdx; 264 } 265 266 @Override iterator()267 public Iterator<T> iterator() { 268 return new Iterator<T>() { 269 private boolean hasNext = true; 270 private int idx = startIdx; 271 272 @Override 273 public boolean hasNext() { 274 if (hasNext) { 275 return true; 276 } 277 for (; idx < size; idx++) { 278 if (bytesEqual(key.asciiName(), name(idx))) { 279 hasNext = true; 280 return hasNext; 281 } 282 } 283 return false; 284 } 285 286 @Override 287 public T next() { 288 if (hasNext()) { 289 hasNext = false; 290 return valueAsT(idx++, key); 291 } 292 throw new NoSuchElementException(); 293 } 294 295 @Override 296 public void remove() { 297 throw new UnsupportedOperationException(); 298 } 299 }; 300 } 301 } 302 303 /** 304 * Returns all the metadata entries named 'name', in the order they were received, parsed as T, or 305 * null if there are none. The iterator is not guaranteed to be "live." It may or may not be 306 * accurate if Metadata is mutated. 307 */ 308 @Nullable getAll(final Key<T> key)309 public <T> Iterable<T> getAll(final Key<T> key) { 310 for (int i = 0; i < size; i++) { 311 if (bytesEqual(key.asciiName(), name(i))) { 312 return new IterableAt<>(key, i); 313 } 314 } 315 return null; 316 } 317 318 /** 319 * Returns set of all keys in store. 320 * 321 * @return unmodifiable Set of keys 322 */ 323 @SuppressWarnings("deprecation") // The String ctor is deprecated, but fast. keys()324 public Set<String> keys() { 325 if (isEmpty()) { 326 return Collections.emptySet(); 327 } 328 Set<String> ks = new HashSet<>(size); 329 for (int i = 0; i < size; i++) { 330 ks.add(new String(name(i), 0 /* hibyte */)); 331 } 332 // immutable in case we decide to change the implementation later. 333 return Collections.unmodifiableSet(ks); 334 } 335 336 /** 337 * Adds the {@code key, value} pair. If {@code key} already has values, {@code value} is added to 338 * the end. Duplicate values for the same key are permitted. 339 * 340 * @throws NullPointerException if key or value is null 341 */ put(Key<T> key, T value)342 public <T> void put(Key<T> key, T value) { 343 Preconditions.checkNotNull(key, "key"); 344 Preconditions.checkNotNull(value, "value"); 345 maybeExpand(); 346 name(size, key.asciiName()); 347 if (key.serializesToStreams()) { 348 value(size, LazyValue.create(key, value)); 349 } else { 350 value(size, key.toBytes(value)); 351 } 352 size++; 353 } 354 maybeExpand()355 private void maybeExpand() { 356 if (len() == 0 || len() == cap()) { 357 expand(Math.max(len() * 2, 8)); 358 } 359 } 360 361 // Expands to exactly the desired capacity. expand(int newCapacity)362 private void expand(int newCapacity) { 363 Object[] newNamesAndValues = new Object[newCapacity]; 364 if (!isEmpty()) { 365 System.arraycopy(namesAndValues, 0, newNamesAndValues, 0, len()); 366 } 367 namesAndValues = newNamesAndValues; 368 } 369 370 /** 371 * Removes the first occurrence of {@code value} for {@code key}. 372 * 373 * @param key key for value 374 * @param value value 375 * @return {@code true} if {@code value} removed; {@code false} if {@code value} was not present 376 * @throws NullPointerException if {@code key} or {@code value} is null 377 */ remove(Key<T> key, T value)378 public <T> boolean remove(Key<T> key, T value) { 379 Preconditions.checkNotNull(key, "key"); 380 Preconditions.checkNotNull(value, "value"); 381 for (int i = 0; i < size; i++) { 382 if (!bytesEqual(key.asciiName(), name(i))) { 383 continue; 384 } 385 T stored = valueAsT(i, key); 386 if (!value.equals(stored)) { 387 continue; 388 } 389 int writeIdx = i * 2; 390 int readIdx = (i + 1) * 2; 391 int readLen = len() - readIdx; 392 System.arraycopy(namesAndValues, readIdx, namesAndValues, writeIdx, readLen); 393 size -= 1; 394 name(size, null); 395 value(size, (byte[]) null); 396 return true; 397 } 398 return false; 399 } 400 401 /** Remove all values for the given key. If there were no values, {@code null} is returned. */ removeAll(Key<T> key)402 public <T> Iterable<T> removeAll(Key<T> key) { 403 if (isEmpty()) { 404 return null; 405 } 406 int writeIdx = 0; 407 int readIdx = 0; 408 List<T> ret = null; 409 for (; readIdx < size; readIdx++) { 410 if (bytesEqual(key.asciiName(), name(readIdx))) { 411 ret = ret != null ? ret : new ArrayList<T>(); 412 ret.add(valueAsT(readIdx, key)); 413 continue; 414 } 415 name(writeIdx, name(readIdx)); 416 value(writeIdx, value(readIdx)); 417 writeIdx++; 418 } 419 int newSize = writeIdx; 420 // Multiply by two since namesAndValues is interleaved. 421 Arrays.fill(namesAndValues, writeIdx * 2, len(), null); 422 size = newSize; 423 return ret; 424 } 425 426 /** 427 * Remove all values for the given key without returning them. This is a minor performance 428 * optimization if you do not need the previous values. 429 */ 430 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4691") discardAll(Key<T> key)431 public <T> void discardAll(Key<T> key) { 432 if (isEmpty()) { 433 return; 434 } 435 int writeIdx = 0; 436 int readIdx = 0; 437 for (; readIdx < size; readIdx++) { 438 if (bytesEqual(key.asciiName(), name(readIdx))) { 439 continue; 440 } 441 name(writeIdx, name(readIdx)); 442 value(writeIdx, value(readIdx)); 443 writeIdx++; 444 } 445 int newSize = writeIdx; 446 // Multiply by two since namesAndValues is interleaved. 447 Arrays.fill(namesAndValues, writeIdx * 2, len(), null); 448 size = newSize; 449 } 450 451 /** 452 * Serialize all the metadata entries. 453 * 454 * <p>It produces serialized names and values interleaved. result[i*2] are names, while 455 * result[i*2+1] are values. 456 * 457 * <p>Names are ASCII string bytes that contains only the characters listed in the class comment 458 * of {@link Key}. If the name ends with {@code "-bin"}, the value can be raw binary. Otherwise, 459 * the value must contain only characters listed in the class comments of {@link AsciiMarshaller} 460 * 461 * <p>The returned individual byte arrays <em>must not</em> be modified. However, the top level 462 * array may be modified. 463 * 464 * <p>This method is intended for transport use only. 465 */ 466 @Nullable serialize()467 byte[][] serialize() { 468 byte[][] serialized = new byte[len()][]; 469 if (namesAndValues instanceof byte[][]) { 470 System.arraycopy(namesAndValues, 0, serialized, 0, len()); 471 } else { 472 for (int i = 0; i < size; i++) { 473 serialized[i * 2] = name(i); 474 serialized[i * 2 + 1] = valueAsBytes(i); 475 } 476 } 477 return serialized; 478 } 479 480 /** 481 * Serializes all metadata entries, leaving some values as {@link InputStream}s. 482 * 483 * <p>Produces serialized names and values interleaved. result[i*2] are names, while 484 * result[i*2+1] are values. 485 * 486 * <p>Names are byte arrays as described according to the {@link #serialize} 487 * method. Values are either byte arrays or {@link InputStream}s. 488 * 489 * <p>This method is intended for transport use only. 490 */ 491 @Nullable serializePartial()492 Object[] serializePartial() { 493 Object[] serialized = new Object[len()]; 494 for (int i = 0; i < size; i++) { 495 serialized[i * 2] = name(i); 496 serialized[i * 2 + 1] = valueAsBytesOrStream(i); 497 } 498 return serialized; 499 } 500 501 /** 502 * Perform a simple merge of two sets of metadata. 503 * 504 * <p>This is a purely additive operation, because a single key can be associated with multiple 505 * values. 506 */ merge(Metadata other)507 public void merge(Metadata other) { 508 if (other.isEmpty()) { 509 return; 510 } 511 int remaining = cap() - len(); 512 if (isEmpty() || remaining < other.len()) { 513 expand(len() + other.len()); 514 } 515 System.arraycopy(other.namesAndValues, 0, namesAndValues, len(), other.len()); 516 size += other.size; 517 } 518 519 /** 520 * Merge values from the given set of keys into this set of metadata. If a key is present in keys, 521 * then all of the associated values will be copied over. 522 * 523 * @param other The source of the new key values. 524 * @param keys The subset of matching key we want to copy, if they exist in the source. 525 */ merge(Metadata other, Set<Key<?>> keys)526 public void merge(Metadata other, Set<Key<?>> keys) { 527 Preconditions.checkNotNull(other, "other"); 528 // Use ByteBuffer for equals and hashCode. 529 Map<ByteBuffer, Key<?>> asciiKeys = new HashMap<>(keys.size()); 530 for (Key<?> key : keys) { 531 asciiKeys.put(ByteBuffer.wrap(key.asciiName()), key); 532 } 533 for (int i = 0; i < other.size; i++) { 534 ByteBuffer wrappedNamed = ByteBuffer.wrap(other.name(i)); 535 if (asciiKeys.containsKey(wrappedNamed)) { 536 maybeExpand(); 537 name(size, other.name(i)); 538 value(size, other.value(i)); 539 size++; 540 } 541 } 542 } 543 544 @Override toString()545 public String toString() { 546 StringBuilder sb = new StringBuilder("Metadata("); 547 for (int i = 0; i < size; i++) { 548 if (i != 0) { 549 sb.append(','); 550 } 551 String headerName = new String(name(i), US_ASCII); 552 sb.append(headerName).append('='); 553 if (headerName.endsWith(BINARY_HEADER_SUFFIX)) { 554 sb.append(BASE64_ENCODING_OMIT_PADDING.encode(valueAsBytes(i))); 555 } else { 556 String headerValue = new String(valueAsBytes(i), US_ASCII); 557 sb.append(headerValue); 558 } 559 } 560 return sb.append(')').toString(); 561 } 562 bytesEqual(byte[] left, byte[] right)563 private boolean bytesEqual(byte[] left, byte[] right) { 564 return Arrays.equals(left, right); 565 } 566 567 /** Marshaller for metadata values that are serialized into raw binary. */ 568 public interface BinaryMarshaller<T> { 569 /** 570 * Serialize a metadata value to bytes. 571 * 572 * @param value to serialize 573 * @return serialized version of value 574 */ toBytes(T value)575 byte[] toBytes(T value); 576 577 /** 578 * Parse a serialized metadata value from bytes. 579 * 580 * @param serialized value of metadata to parse 581 * @return a parsed instance of type T 582 */ parseBytes(byte[] serialized)583 T parseBytes(byte[] serialized); 584 } 585 586 /** 587 * Marshaller for metadata values that are serialized into ASCII strings. The strings contain only 588 * following characters: 589 * 590 * <ul> 591 * <li>Space: {@code 0x20}, but must not be at the beginning or at the end of the value. Leading 592 * or trailing whitespace may not be preserved. 593 * <li>ASCII visible characters ({@code 0x21-0x7E}). 594 * </ul> 595 * 596 * <p>Note this has to be the subset of valid characters in {@code field-content} from RFC 7230 597 * Section 3.2. 598 */ 599 public interface AsciiMarshaller<T> { 600 /** 601 * Serialize a metadata value to a ASCII string that contains only the characters listed in the 602 * class comment of {@link AsciiMarshaller}. Otherwise the output may be considered invalid and 603 * discarded by the transport, or the call may fail. 604 * 605 * @param value to serialize 606 * @return serialized version of value, or null if value cannot be transmitted. 607 */ toAsciiString(T value)608 String toAsciiString(T value); 609 610 /** 611 * Parse a serialized metadata value from an ASCII string. 612 * 613 * @param serialized value of metadata to parse 614 * @return a parsed instance of type T 615 */ parseAsciiString(String serialized)616 T parseAsciiString(String serialized); 617 } 618 619 /** Marshaller for metadata values that are serialized to an InputStream. */ 620 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/6575") 621 public interface BinaryStreamMarshaller<T> { 622 /** 623 * Serializes a metadata value to an {@link InputStream}. 624 * 625 * @param value to serialize 626 * @return serialized version of value 627 */ toStream(T value)628 InputStream toStream(T value); 629 630 /** 631 * Parses a serialized metadata value from an {@link InputStream}. 632 * 633 * @param stream of metadata to parse 634 * @return a parsed instance of type T 635 */ parseStream(InputStream stream)636 T parseStream(InputStream stream); 637 } 638 639 /** 640 * Key for metadata entries. Allows for parsing and serialization of metadata. 641 * 642 * <h3>Valid characters in key names</h3> 643 * 644 * <p>Only the following ASCII characters are allowed in the names of keys: 645 * 646 * <ul> 647 * <li>digits: {@code 0-9} 648 * <li>uppercase letters: {@code A-Z} (normalized to lower) 649 * <li>lowercase letters: {@code a-z} 650 * <li>special characters: {@code -_.} 651 * </ul> 652 * 653 * <p>This is a strict subset of the HTTP field-name rules. Applications may not send or receive 654 * metadata with invalid key names. However, the gRPC library may preserve any metadata received 655 * even if it does not conform to the above limitations. Additionally, if metadata contains non 656 * conforming field names, they will still be sent. In this way, unknown metadata fields are 657 * parsed, serialized and preserved, but never interpreted. They are similar to protobuf unknown 658 * fields. 659 * 660 * <p>Note this has to be the subset of valid HTTP/2 token characters as defined in RFC7230 661 * Section 3.2.6 and RFC5234 Section B.1 662 * 663 * <p>Note that a key is immutable but it may not be deeply immutable, because the key depends on 664 * its marshaller, and the marshaller can be mutable though not recommended. 665 * 666 * @see <a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">Wire Spec</a> 667 * @see <a href="https://tools.ietf.org/html/rfc7230#section-3.2.6">RFC7230</a> 668 * @see <a href="https://tools.ietf.org/html/rfc5234#appendix-B.1">RFC5234</a> 669 */ 670 @Immutable 671 public abstract static class Key<T> { 672 673 /** Valid characters for field names as defined in RFC7230 and RFC5234. */ 674 private static final BitSet VALID_T_CHARS = generateValidTChars(); 675 676 /** 677 * Creates a key for a binary header. 678 * 679 * @param name Must contain only the valid key characters as defined in the class comment. Must 680 * end with {@link #BINARY_HEADER_SUFFIX}. 681 */ of(String name, BinaryMarshaller<T> marshaller)682 public static <T> Key<T> of(String name, BinaryMarshaller<T> marshaller) { 683 return new BinaryKey<>(name, marshaller); 684 } 685 686 /** 687 * Creates a key for a binary header, serializing to input streams. 688 * 689 * @param name Must contain only the valid key characters as defined in the class comment. Must 690 * end with {@link #BINARY_HEADER_SUFFIX}. 691 */ 692 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/6575") of(String name, BinaryStreamMarshaller<T> marshaller)693 public static <T> Key<T> of(String name, BinaryStreamMarshaller<T> marshaller) { 694 return new LazyStreamBinaryKey<>(name, marshaller); 695 } 696 697 /** 698 * Creates a key for an ASCII header. 699 * 700 * @param name Must contain only the valid key characters as defined in the class comment. Must 701 * <b>not</b> end with {@link #BINARY_HEADER_SUFFIX} 702 */ of(String name, AsciiMarshaller<T> marshaller)703 public static <T> Key<T> of(String name, AsciiMarshaller<T> marshaller) { 704 return of(name, false, marshaller); 705 } 706 of(String name, boolean pseudo, AsciiMarshaller<T> marshaller)707 static <T> Key<T> of(String name, boolean pseudo, AsciiMarshaller<T> marshaller) { 708 return new AsciiKey<>(name, pseudo, marshaller); 709 } 710 of(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller)711 static <T> Key<T> of(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller) { 712 return new TrustedAsciiKey<>(name, pseudo, marshaller); 713 } 714 715 private final String originalName; 716 717 private final String name; 718 private final byte[] nameBytes; 719 private final Object marshaller; 720 generateValidTChars()721 private static BitSet generateValidTChars() { 722 BitSet valid = new BitSet(0x7f); 723 valid.set('-'); 724 valid.set('_'); 725 valid.set('.'); 726 for (char c = '0'; c <= '9'; c++) { 727 valid.set(c); 728 } 729 // Only validates after normalization, so we exclude uppercase. 730 for (char c = 'a'; c <= 'z'; c++) { 731 valid.set(c); 732 } 733 return valid; 734 } 735 validateName(String n, boolean pseudo)736 private static String validateName(String n, boolean pseudo) { 737 checkNotNull(n, "name"); 738 checkArgument(!n.isEmpty(), "token must have at least 1 tchar"); 739 if (n.equals("connection")) { 740 logger.log( 741 Level.WARNING, 742 "Metadata key is 'Connection', which should not be used. That is used by HTTP/1 for " 743 + "connection-specific headers which are not to be forwarded. There is probably an " 744 + "HTTP/1 conversion bug. Simply removing the Connection header is not enough; you " 745 + "should remove all headers it references as well. See RFC 7230 section 6.1", 746 new RuntimeException("exception to show backtrace")); 747 } 748 for (int i = 0; i < n.length(); i++) { 749 char tChar = n.charAt(i); 750 if (pseudo && tChar == ':' && i == 0) { 751 continue; 752 } 753 754 checkArgument( 755 VALID_T_CHARS.get(tChar), "Invalid character '%s' in key name '%s'", tChar, n); 756 } 757 return n; 758 } 759 Key(String name, boolean pseudo, Object marshaller)760 private Key(String name, boolean pseudo, Object marshaller) { 761 this.originalName = checkNotNull(name, "name"); 762 this.name = validateName(this.originalName.toLowerCase(Locale.ROOT), pseudo); 763 this.nameBytes = this.name.getBytes(US_ASCII); 764 this.marshaller = marshaller; 765 } 766 767 /** 768 * Returns the original name used to create this key. 769 */ originalName()770 public final String originalName() { 771 return originalName; 772 } 773 774 /** 775 * Returns the normalized name for this key. 776 */ name()777 public final String name() { 778 return name; 779 } 780 781 /** 782 * Get the name as bytes using ASCII-encoding. 783 * 784 * <p>The returned byte arrays <em>must not</em> be modified. 785 * 786 * <p>This method is intended for transport use only. 787 */ 788 // TODO (louiscryan): Migrate to ByteString 789 @VisibleForTesting asciiName()790 byte[] asciiName() { 791 return nameBytes; 792 } 793 794 /** 795 * Returns true if the two objects are both Keys, and their names match (case insensitive). 796 */ 797 @SuppressWarnings("EqualsGetClass") 798 @Override equals(Object o)799 public final boolean equals(Object o) { 800 if (this == o) { 801 return true; 802 } 803 if (o == null || getClass() != o.getClass()) { 804 return false; 805 } 806 Key<?> key = (Key<?>) o; 807 return name.equals(key.name); 808 } 809 810 @Override hashCode()811 public final int hashCode() { 812 return name.hashCode(); 813 } 814 815 @Override toString()816 public String toString() { 817 return "Key{name='" + name + "'}"; 818 } 819 820 /** 821 * Serialize a metadata value to bytes. 822 * 823 * @param value to serialize 824 * @return serialized version of value 825 */ toBytes(T value)826 abstract byte[] toBytes(T value); 827 828 /** 829 * Parse a serialized metadata value from bytes. 830 * 831 * @param serialized value of metadata to parse 832 * @return a parsed instance of type T 833 */ parseBytes(byte[] serialized)834 abstract T parseBytes(byte[] serialized); 835 836 /** 837 * Returns whether this key will be serialized to bytes lazily. 838 */ serializesToStreams()839 boolean serializesToStreams() { 840 return false; 841 } 842 843 /** 844 * Gets this keys (implementation-specific) marshaller, or null if the 845 * marshaller is not of the given type. 846 * 847 * @param marshallerClass The type we expect the marshaller to be. 848 * @return the marshaller object for this key, or null. 849 */ 850 @Nullable getMarshaller(Class<M> marshallerClass)851 final <M> M getMarshaller(Class<M> marshallerClass) { 852 if (marshallerClass.isInstance(marshaller)) { 853 return marshallerClass.cast(marshaller); 854 } 855 return null; 856 } 857 } 858 859 private static class BinaryKey<T> extends Key<T> { 860 private final BinaryMarshaller<T> marshaller; 861 862 /** Keys have a name and a binary marshaller used for serialization. */ BinaryKey(String name, BinaryMarshaller<T> marshaller)863 private BinaryKey(String name, BinaryMarshaller<T> marshaller) { 864 super(name, false /* not pseudo */, marshaller); 865 checkArgument( 866 name.endsWith(BINARY_HEADER_SUFFIX), 867 "Binary header is named %s. It must end with %s", 868 name, 869 BINARY_HEADER_SUFFIX); 870 checkArgument(name.length() > BINARY_HEADER_SUFFIX.length(), "empty key name"); 871 this.marshaller = checkNotNull(marshaller, "marshaller is null"); 872 } 873 874 @Override toBytes(T value)875 byte[] toBytes(T value) { 876 return Preconditions.checkNotNull(marshaller.toBytes(value), "null marshaller.toBytes()"); 877 } 878 879 @Override parseBytes(byte[] serialized)880 T parseBytes(byte[] serialized) { 881 return marshaller.parseBytes(serialized); 882 } 883 } 884 885 /** A binary key for values which should be serialized lazily to {@link InputStream}s. */ 886 private static class LazyStreamBinaryKey<T> extends Key<T> { 887 888 private final BinaryStreamMarshaller<T> marshaller; 889 890 /** Keys have a name and a stream marshaller used for serialization. */ LazyStreamBinaryKey(String name, BinaryStreamMarshaller<T> marshaller)891 private LazyStreamBinaryKey(String name, BinaryStreamMarshaller<T> marshaller) { 892 super(name, false /* not pseudo */, marshaller); 893 checkArgument( 894 name.endsWith(BINARY_HEADER_SUFFIX), 895 "Binary header is named %s. It must end with %s", 896 name, 897 BINARY_HEADER_SUFFIX); 898 checkArgument(name.length() > BINARY_HEADER_SUFFIX.length(), "empty key name"); 899 this.marshaller = checkNotNull(marshaller, "marshaller is null"); 900 } 901 902 @Override toBytes(T value)903 byte[] toBytes(T value) { 904 return streamToBytes(checkNotNull(marshaller.toStream(value), "null marshaller.toStream()")); 905 } 906 907 @Override parseBytes(byte[] serialized)908 T parseBytes(byte[] serialized) { 909 return marshaller.parseStream(new ByteArrayInputStream(serialized)); 910 } 911 912 @Override serializesToStreams()913 boolean serializesToStreams() { 914 return true; 915 } 916 } 917 918 /** Internal holder for values which are serialized/de-serialized lazily. */ 919 static final class LazyValue<T> { 920 private final BinaryStreamMarshaller<T> marshaller; 921 private final T value; 922 private volatile byte[] serialized; 923 create(Key<T> key, T value)924 static <T> LazyValue<T> create(Key<T> key, T value) { 925 return new LazyValue<>(checkNotNull(getBinaryStreamMarshaller(key)), value); 926 } 927 928 /** A value set by the application. */ LazyValue(BinaryStreamMarshaller<T> marshaller, T value)929 LazyValue(BinaryStreamMarshaller<T> marshaller, T value) { 930 this.marshaller = marshaller; 931 this.value = value; 932 } 933 toStream()934 InputStream toStream() { 935 return checkNotNull(marshaller.toStream(value), "null marshaller.toStream()"); 936 } 937 toBytes()938 byte[] toBytes() { 939 if (serialized == null) { 940 synchronized (this) { 941 if (serialized == null) { 942 serialized = streamToBytes(toStream()); 943 } 944 } 945 } 946 return serialized; 947 } 948 toObject(Key<T2> key)949 <T2> T2 toObject(Key<T2> key) { 950 if (key.serializesToStreams()) { 951 BinaryStreamMarshaller<T2> marshaller = getBinaryStreamMarshaller(key); 952 if (marshaller != null) { 953 return marshaller.parseStream(toStream()); 954 } 955 } 956 return key.parseBytes(toBytes()); 957 } 958 959 @Nullable 960 @SuppressWarnings("unchecked") getBinaryStreamMarshaller(Key<T> key)961 private static <T> BinaryStreamMarshaller<T> getBinaryStreamMarshaller(Key<T> key) { 962 return (BinaryStreamMarshaller<T>) key.getMarshaller(BinaryStreamMarshaller.class); 963 } 964 } 965 966 private static class AsciiKey<T> extends Key<T> { 967 private final AsciiMarshaller<T> marshaller; 968 969 /** Keys have a name and an ASCII marshaller used for serialization. */ AsciiKey(String name, boolean pseudo, AsciiMarshaller<T> marshaller)970 private AsciiKey(String name, boolean pseudo, AsciiMarshaller<T> marshaller) { 971 super(name, pseudo, marshaller); 972 Preconditions.checkArgument( 973 !name.endsWith(BINARY_HEADER_SUFFIX), 974 "ASCII header is named %s. Only binary headers may end with %s", 975 name, 976 BINARY_HEADER_SUFFIX); 977 this.marshaller = Preconditions.checkNotNull(marshaller, "marshaller"); 978 } 979 980 @Override toBytes(T value)981 byte[] toBytes(T value) { 982 String encoded = Preconditions.checkNotNull( 983 marshaller.toAsciiString(value), "null marshaller.toAsciiString()"); 984 return encoded.getBytes(US_ASCII); 985 } 986 987 @Override parseBytes(byte[] serialized)988 T parseBytes(byte[] serialized) { 989 return marshaller.parseAsciiString(new String(serialized, US_ASCII)); 990 } 991 } 992 993 private static final class TrustedAsciiKey<T> extends Key<T> { 994 private final TrustedAsciiMarshaller<T> marshaller; 995 996 /** Keys have a name and an ASCII marshaller used for serialization. */ TrustedAsciiKey(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller)997 private TrustedAsciiKey(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller) { 998 super(name, pseudo, marshaller); 999 Preconditions.checkArgument( 1000 !name.endsWith(BINARY_HEADER_SUFFIX), 1001 "ASCII header is named %s. Only binary headers may end with %s", 1002 name, 1003 BINARY_HEADER_SUFFIX); 1004 this.marshaller = Preconditions.checkNotNull(marshaller, "marshaller"); 1005 } 1006 1007 @Override toBytes(T value)1008 byte[] toBytes(T value) { 1009 return Preconditions.checkNotNull( 1010 marshaller.toAsciiString(value), "null marshaller.toAsciiString()"); 1011 } 1012 1013 @Override parseBytes(byte[] serialized)1014 T parseBytes(byte[] serialized) { 1015 return marshaller.parseAsciiString(serialized); 1016 } 1017 } 1018 1019 /** 1020 * A specialized plain ASCII marshaller. Both input and output are assumed to be valid header 1021 * ASCII. 1022 */ 1023 @Immutable 1024 interface TrustedAsciiMarshaller<T> { 1025 /** 1026 * Serialize a metadata value to a ASCII string that contains only the characters listed in the 1027 * class comment of {@link io.grpc.Metadata.AsciiMarshaller}. Otherwise the output may be 1028 * considered invalid and discarded by the transport, or the call may fail. 1029 * 1030 * @param value to serialize 1031 * @return serialized version of value, or null if value cannot be transmitted. 1032 */ toAsciiString(T value)1033 byte[] toAsciiString(T value); 1034 1035 /** 1036 * Parse a serialized metadata value from an ASCII string. 1037 * 1038 * @param serialized value of metadata to parse 1039 * @return a parsed instance of type T 1040 */ parseAsciiString(byte[] serialized)1041 T parseAsciiString(byte[] serialized); 1042 } 1043 streamToBytes(InputStream stream)1044 private static byte[] streamToBytes(InputStream stream) { 1045 try { 1046 return ByteStreams.toByteArray(stream); 1047 } catch (IOException ioe) { 1048 throw new RuntimeException("failure reading serialized stream", ioe); 1049 } 1050 } 1051 } 1052