1 /* 2 * Copyright 2018 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.Preconditions.checkNotNull; 20 import static com.google.common.base.Preconditions.checkState; 21 22 import com.google.common.annotations.VisibleForTesting; 23 import com.google.common.base.MoreObjects; 24 import com.google.common.base.Objects; 25 import java.net.SocketAddress; 26 import java.security.cert.Certificate; 27 import java.util.ArrayList; 28 import java.util.Collections; 29 import java.util.HashMap; 30 import java.util.Iterator; 31 import java.util.List; 32 import java.util.Map; 33 import java.util.concurrent.ConcurrentHashMap; 34 import java.util.concurrent.ConcurrentMap; 35 import java.util.concurrent.ConcurrentNavigableMap; 36 import java.util.concurrent.ConcurrentSkipListMap; 37 import java.util.logging.Level; 38 import java.util.logging.Logger; 39 import javax.annotation.Nullable; 40 import javax.annotation.concurrent.Immutable; 41 import javax.net.ssl.SSLPeerUnverifiedException; 42 import javax.net.ssl.SSLSession; 43 44 /** 45 * This is an internal API. Do NOT use. 46 */ 47 @Internal 48 public final class InternalChannelz { 49 private static final Logger log = Logger.getLogger(InternalChannelz.class.getName()); 50 private static final InternalChannelz INSTANCE = new InternalChannelz(); 51 52 private final ConcurrentNavigableMap<Long, InternalInstrumented<ServerStats>> servers 53 = new ConcurrentSkipListMap<Long, InternalInstrumented<ServerStats>>(); 54 private final ConcurrentNavigableMap<Long, InternalInstrumented<ChannelStats>> rootChannels 55 = new ConcurrentSkipListMap<Long, InternalInstrumented<ChannelStats>>(); 56 private final ConcurrentMap<Long, InternalInstrumented<ChannelStats>> subchannels 57 = new ConcurrentHashMap<Long, InternalInstrumented<ChannelStats>>(); 58 // An InProcessTransport can appear in both otherSockets and perServerSockets simultaneously 59 private final ConcurrentMap<Long, InternalInstrumented<SocketStats>> otherSockets 60 = new ConcurrentHashMap<Long, InternalInstrumented<SocketStats>>(); 61 private final ConcurrentMap<Long, ServerSocketMap> perServerSockets 62 = new ConcurrentHashMap<Long, ServerSocketMap>(); 63 64 // A convenience class to avoid deeply nested types. 65 private static final class ServerSocketMap 66 extends ConcurrentSkipListMap<Long, InternalInstrumented<SocketStats>> { 67 private static final long serialVersionUID = -7883772124944661414L; 68 } 69 70 @VisibleForTesting InternalChannelz()71 public InternalChannelz() { 72 } 73 instance()74 public static InternalChannelz instance() { 75 return INSTANCE; 76 } 77 78 /** Adds a server. */ addServer(InternalInstrumented<ServerStats> server)79 public void addServer(InternalInstrumented<ServerStats> server) { 80 ServerSocketMap prev = perServerSockets.put(id(server), new ServerSocketMap()); 81 assert prev == null; 82 add(servers, server); 83 } 84 85 /** Adds a subchannel. */ addSubchannel(InternalInstrumented<ChannelStats> subchannel)86 public void addSubchannel(InternalInstrumented<ChannelStats> subchannel) { 87 add(subchannels, subchannel); 88 } 89 90 /** Adds a root channel. */ addRootChannel(InternalInstrumented<ChannelStats> rootChannel)91 public void addRootChannel(InternalInstrumented<ChannelStats> rootChannel) { 92 add(rootChannels, rootChannel); 93 } 94 95 /** Adds a socket. */ addClientSocket(InternalInstrumented<SocketStats> socket)96 public void addClientSocket(InternalInstrumented<SocketStats> socket) { 97 add(otherSockets, socket); 98 } 99 addListenSocket(InternalInstrumented<SocketStats> socket)100 public void addListenSocket(InternalInstrumented<SocketStats> socket) { 101 add(otherSockets, socket); 102 } 103 104 /** Adds a server socket. */ addServerSocket( InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket)105 public void addServerSocket( 106 InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket) { 107 ServerSocketMap serverSockets = perServerSockets.get(id(server)); 108 assert serverSockets != null; 109 add(serverSockets, socket); 110 } 111 112 /** Removes a server. */ removeServer(InternalInstrumented<ServerStats> server)113 public void removeServer(InternalInstrumented<ServerStats> server) { 114 remove(servers, server); 115 ServerSocketMap prev = perServerSockets.remove(id(server)); 116 assert prev != null; 117 assert prev.isEmpty(); 118 } 119 removeSubchannel(InternalInstrumented<ChannelStats> subchannel)120 public void removeSubchannel(InternalInstrumented<ChannelStats> subchannel) { 121 remove(subchannels, subchannel); 122 } 123 removeRootChannel(InternalInstrumented<ChannelStats> channel)124 public void removeRootChannel(InternalInstrumented<ChannelStats> channel) { 125 remove(rootChannels, channel); 126 } 127 removeClientSocket(InternalInstrumented<SocketStats> socket)128 public void removeClientSocket(InternalInstrumented<SocketStats> socket) { 129 remove(otherSockets, socket); 130 } 131 removeListenSocket(InternalInstrumented<SocketStats> socket)132 public void removeListenSocket(InternalInstrumented<SocketStats> socket) { 133 remove(otherSockets, socket); 134 } 135 136 /** Removes a server socket. */ removeServerSocket( InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket)137 public void removeServerSocket( 138 InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket) { 139 ServerSocketMap socketsOfServer = perServerSockets.get(id(server)); 140 assert socketsOfServer != null; 141 remove(socketsOfServer, socket); 142 } 143 144 /** Returns a {@link RootChannelList}. */ getRootChannels(long fromId, int maxPageSize)145 public RootChannelList getRootChannels(long fromId, int maxPageSize) { 146 List<InternalInstrumented<ChannelStats>> channelList 147 = new ArrayList<InternalInstrumented<ChannelStats>>(); 148 Iterator<InternalInstrumented<ChannelStats>> iterator 149 = rootChannels.tailMap(fromId).values().iterator(); 150 151 while (iterator.hasNext() && channelList.size() < maxPageSize) { 152 channelList.add(iterator.next()); 153 } 154 return new RootChannelList(channelList, !iterator.hasNext()); 155 } 156 157 /** Returns a channel. */ 158 @Nullable getChannel(long id)159 public InternalInstrumented<ChannelStats> getChannel(long id) { 160 return rootChannels.get(id); 161 } 162 163 /** Returns a subchannel. */ 164 @Nullable getSubchannel(long id)165 public InternalInstrumented<ChannelStats> getSubchannel(long id) { 166 return subchannels.get(id); 167 } 168 169 /** Returns a server list. */ getServers(long fromId, int maxPageSize)170 public ServerList getServers(long fromId, int maxPageSize) { 171 List<InternalInstrumented<ServerStats>> serverList 172 = new ArrayList<InternalInstrumented<ServerStats>>(maxPageSize); 173 Iterator<InternalInstrumented<ServerStats>> iterator 174 = servers.tailMap(fromId).values().iterator(); 175 176 while (iterator.hasNext() && serverList.size() < maxPageSize) { 177 serverList.add(iterator.next()); 178 } 179 return new ServerList(serverList, !iterator.hasNext()); 180 } 181 182 /** Returns socket refs for a server. */ 183 @Nullable getServerSockets(long serverId, long fromId, int maxPageSize)184 public ServerSocketsList getServerSockets(long serverId, long fromId, int maxPageSize) { 185 ServerSocketMap serverSockets = perServerSockets.get(serverId); 186 if (serverSockets == null) { 187 return null; 188 } 189 List<InternalWithLogId> socketList = new ArrayList<>(maxPageSize); 190 Iterator<InternalInstrumented<SocketStats>> iterator 191 = serverSockets.tailMap(fromId).values().iterator(); 192 while (socketList.size() < maxPageSize && iterator.hasNext()) { 193 socketList.add(iterator.next()); 194 } 195 return new ServerSocketsList(socketList, !iterator.hasNext()); 196 } 197 198 /** Returns a socket. */ 199 @Nullable getSocket(long id)200 public InternalInstrumented<SocketStats> getSocket(long id) { 201 InternalInstrumented<SocketStats> clientSocket = otherSockets.get(id); 202 if (clientSocket != null) { 203 return clientSocket; 204 } 205 return getServerSocket(id); 206 } 207 getServerSocket(long id)208 private InternalInstrumented<SocketStats> getServerSocket(long id) { 209 for (ServerSocketMap perServerSockets : perServerSockets.values()) { 210 InternalInstrumented<SocketStats> serverSocket = perServerSockets.get(id); 211 if (serverSocket != null) { 212 return serverSocket; 213 } 214 } 215 return null; 216 } 217 218 @VisibleForTesting containsServer(InternalLogId serverRef)219 public boolean containsServer(InternalLogId serverRef) { 220 return contains(servers, serverRef); 221 } 222 223 @VisibleForTesting containsSubchannel(InternalLogId subchannelRef)224 public boolean containsSubchannel(InternalLogId subchannelRef) { 225 return contains(subchannels, subchannelRef); 226 } 227 getRootChannel(long id)228 public InternalInstrumented<ChannelStats> getRootChannel(long id) { 229 return rootChannels.get(id); 230 } 231 232 @VisibleForTesting containsClientSocket(InternalLogId transportRef)233 public boolean containsClientSocket(InternalLogId transportRef) { 234 return contains(otherSockets, transportRef); 235 } 236 add(Map<Long, T> map, T object)237 private static <T extends InternalInstrumented<?>> void add(Map<Long, T> map, T object) { 238 T prev = map.put(object.getLogId().getId(), object); 239 assert prev == null; 240 } 241 remove(Map<Long, T> map, T object)242 private static <T extends InternalInstrumented<?>> void remove(Map<Long, T> map, T object) { 243 T prev = map.remove(id(object)); 244 assert prev != null; 245 } 246 contains( Map<Long, T> map, InternalLogId id)247 private static <T extends InternalInstrumented<?>> boolean contains( 248 Map<Long, T> map, InternalLogId id) { 249 return map.containsKey(id.getId()); 250 } 251 252 public static final class RootChannelList { 253 public final List<InternalInstrumented<ChannelStats>> channels; 254 public final boolean end; 255 256 /** Creates an instance. */ RootChannelList(List<InternalInstrumented<ChannelStats>> channels, boolean end)257 public RootChannelList(List<InternalInstrumented<ChannelStats>> channels, boolean end) { 258 this.channels = checkNotNull(channels); 259 this.end = end; 260 } 261 } 262 263 public static final class ServerList { 264 public final List<InternalInstrumented<ServerStats>> servers; 265 public final boolean end; 266 267 /** Creates an instance. */ ServerList(List<InternalInstrumented<ServerStats>> servers, boolean end)268 public ServerList(List<InternalInstrumented<ServerStats>> servers, boolean end) { 269 this.servers = checkNotNull(servers); 270 this.end = end; 271 } 272 } 273 274 public static final class ServerSocketsList { 275 public final List<InternalWithLogId> sockets; 276 public final boolean end; 277 278 /** Creates an instance. */ ServerSocketsList(List<InternalWithLogId> sockets, boolean end)279 public ServerSocketsList(List<InternalWithLogId> sockets, boolean end) { 280 this.sockets = sockets; 281 this.end = end; 282 } 283 } 284 285 @Immutable 286 public static final class ServerStats { 287 public final long callsStarted; 288 public final long callsSucceeded; 289 public final long callsFailed; 290 public final long lastCallStartedNanos; 291 public final List<InternalInstrumented<SocketStats>> listenSockets; 292 293 /** 294 * Creates an instance. 295 */ ServerStats( long callsStarted, long callsSucceeded, long callsFailed, long lastCallStartedNanos, List<InternalInstrumented<SocketStats>> listenSockets)296 public ServerStats( 297 long callsStarted, 298 long callsSucceeded, 299 long callsFailed, 300 long lastCallStartedNanos, 301 List<InternalInstrumented<SocketStats>> listenSockets) { 302 this.callsStarted = callsStarted; 303 this.callsSucceeded = callsSucceeded; 304 this.callsFailed = callsFailed; 305 this.lastCallStartedNanos = lastCallStartedNanos; 306 this.listenSockets = checkNotNull(listenSockets); 307 } 308 309 public static final class Builder { 310 private long callsStarted; 311 private long callsSucceeded; 312 private long callsFailed; 313 private long lastCallStartedNanos; 314 public List<InternalInstrumented<SocketStats>> listenSockets = Collections.emptyList(); 315 setCallsStarted(long callsStarted)316 public Builder setCallsStarted(long callsStarted) { 317 this.callsStarted = callsStarted; 318 return this; 319 } 320 setCallsSucceeded(long callsSucceeded)321 public Builder setCallsSucceeded(long callsSucceeded) { 322 this.callsSucceeded = callsSucceeded; 323 return this; 324 } 325 setCallsFailed(long callsFailed)326 public Builder setCallsFailed(long callsFailed) { 327 this.callsFailed = callsFailed; 328 return this; 329 } 330 setLastCallStartedNanos(long lastCallStartedNanos)331 public Builder setLastCallStartedNanos(long lastCallStartedNanos) { 332 this.lastCallStartedNanos = lastCallStartedNanos; 333 return this; 334 } 335 336 /** Sets the listen sockets. */ setListenSockets(List<InternalInstrumented<SocketStats>> listenSockets)337 public Builder setListenSockets(List<InternalInstrumented<SocketStats>> listenSockets) { 338 checkNotNull(listenSockets); 339 this.listenSockets = Collections.unmodifiableList( 340 new ArrayList<InternalInstrumented<SocketStats>>(listenSockets)); 341 return this; 342 } 343 344 /** 345 * Builds an instance. 346 */ build()347 public ServerStats build() { 348 return new ServerStats( 349 callsStarted, 350 callsSucceeded, 351 callsFailed, 352 lastCallStartedNanos, 353 listenSockets); 354 } 355 } 356 } 357 358 /** 359 * A data class to represent a channel's stats. 360 */ 361 @Immutable 362 public static final class ChannelStats { 363 public final String target; 364 public final ConnectivityState state; 365 @Nullable public final ChannelTrace channelTrace; 366 public final long callsStarted; 367 public final long callsSucceeded; 368 public final long callsFailed; 369 public final long lastCallStartedNanos; 370 public final List<InternalWithLogId> subchannels; 371 public final List<InternalWithLogId> sockets; 372 373 /** 374 * Creates an instance. 375 */ ChannelStats( String target, ConnectivityState state, @Nullable ChannelTrace channelTrace, long callsStarted, long callsSucceeded, long callsFailed, long lastCallStartedNanos, List<InternalWithLogId> subchannels, List<InternalWithLogId> sockets)376 private ChannelStats( 377 String target, 378 ConnectivityState state, 379 @Nullable ChannelTrace channelTrace, 380 long callsStarted, 381 long callsSucceeded, 382 long callsFailed, 383 long lastCallStartedNanos, 384 List<InternalWithLogId> subchannels, 385 List<InternalWithLogId> sockets) { 386 checkState( 387 subchannels.isEmpty() || sockets.isEmpty(), 388 "channels can have subchannels only, subchannels can have either sockets OR subchannels, " 389 + "neither can have both"); 390 this.target = target; 391 this.state = state; 392 this.channelTrace = channelTrace; 393 this.callsStarted = callsStarted; 394 this.callsSucceeded = callsSucceeded; 395 this.callsFailed = callsFailed; 396 this.lastCallStartedNanos = lastCallStartedNanos; 397 this.subchannels = checkNotNull(subchannels); 398 this.sockets = checkNotNull(sockets); 399 } 400 401 public static final class Builder { 402 private String target; 403 private ConnectivityState state; 404 private ChannelTrace channelTrace; 405 private long callsStarted; 406 private long callsSucceeded; 407 private long callsFailed; 408 private long lastCallStartedNanos; 409 private List<InternalWithLogId> subchannels = Collections.emptyList(); 410 private List<InternalWithLogId> sockets = Collections.emptyList(); 411 setTarget(String target)412 public Builder setTarget(String target) { 413 this.target = target; 414 return this; 415 } 416 setState(ConnectivityState state)417 public Builder setState(ConnectivityState state) { 418 this.state = state; 419 return this; 420 } 421 setChannelTrace(ChannelTrace channelTrace)422 public Builder setChannelTrace(ChannelTrace channelTrace) { 423 this.channelTrace = channelTrace; 424 return this; 425 } 426 setCallsStarted(long callsStarted)427 public Builder setCallsStarted(long callsStarted) { 428 this.callsStarted = callsStarted; 429 return this; 430 } 431 setCallsSucceeded(long callsSucceeded)432 public Builder setCallsSucceeded(long callsSucceeded) { 433 this.callsSucceeded = callsSucceeded; 434 return this; 435 } 436 setCallsFailed(long callsFailed)437 public Builder setCallsFailed(long callsFailed) { 438 this.callsFailed = callsFailed; 439 return this; 440 } 441 setLastCallStartedNanos(long lastCallStartedNanos)442 public Builder setLastCallStartedNanos(long lastCallStartedNanos) { 443 this.lastCallStartedNanos = lastCallStartedNanos; 444 return this; 445 } 446 447 /** Sets the subchannels. */ setSubchannels(List<InternalWithLogId> subchannels)448 public Builder setSubchannels(List<InternalWithLogId> subchannels) { 449 checkState(sockets.isEmpty()); 450 this.subchannels = Collections.unmodifiableList(checkNotNull(subchannels)); 451 return this; 452 } 453 454 /** Sets the sockets. */ setSockets(List<InternalWithLogId> sockets)455 public Builder setSockets(List<InternalWithLogId> sockets) { 456 checkState(subchannels.isEmpty()); 457 this.sockets = Collections.unmodifiableList(checkNotNull(sockets)); 458 return this; 459 } 460 461 /** 462 * Builds an instance. 463 */ build()464 public ChannelStats build() { 465 return new ChannelStats( 466 target, 467 state, 468 channelTrace, 469 callsStarted, 470 callsSucceeded, 471 callsFailed, 472 lastCallStartedNanos, 473 subchannels, 474 sockets); 475 } 476 } 477 } 478 479 @Immutable 480 public static final class ChannelTrace { 481 public final long numEventsLogged; 482 public final long creationTimeNanos; 483 public final List<Event> events; 484 ChannelTrace(long numEventsLogged, long creationTimeNanos, List<Event> events)485 private ChannelTrace(long numEventsLogged, long creationTimeNanos, List<Event> events) { 486 this.numEventsLogged = numEventsLogged; 487 this.creationTimeNanos = creationTimeNanos; 488 this.events = events; 489 } 490 491 public static final class Builder { 492 private Long numEventsLogged; 493 private Long creationTimeNanos; 494 private List<Event> events = Collections.emptyList(); 495 setNumEventsLogged(long numEventsLogged)496 public Builder setNumEventsLogged(long numEventsLogged) { 497 this.numEventsLogged = numEventsLogged; 498 return this; 499 } 500 setCreationTimeNanos(long creationTimeNanos)501 public Builder setCreationTimeNanos(long creationTimeNanos) { 502 this.creationTimeNanos = creationTimeNanos; 503 return this; 504 } 505 setEvents(List<Event> events)506 public Builder setEvents(List<Event> events) { 507 this.events = Collections.unmodifiableList(new ArrayList<>(events)); 508 return this; 509 } 510 511 /** Builds a new ChannelTrace instance. */ build()512 public ChannelTrace build() { 513 checkNotNull(numEventsLogged, "numEventsLogged"); 514 checkNotNull(creationTimeNanos, "creationTimeNanos"); 515 return new ChannelTrace(numEventsLogged, creationTimeNanos, events); 516 } 517 } 518 519 @Immutable 520 public static final class Event { 521 public final String description; 522 public final Severity severity; 523 public final long timestampNanos; 524 525 // the oneof child_ref field in proto: one of channelRef and channelRef 526 @Nullable public final InternalWithLogId channelRef; 527 @Nullable public final InternalWithLogId subchannelRef; 528 529 public enum Severity { 530 CT_UNKNOWN, CT_INFO, CT_WARNING, CT_ERROR 531 } 532 Event( String description, Severity severity, long timestampNanos, @Nullable InternalWithLogId channelRef, @Nullable InternalWithLogId subchannelRef)533 private Event( 534 String description, Severity severity, long timestampNanos, 535 @Nullable InternalWithLogId channelRef, @Nullable InternalWithLogId subchannelRef) { 536 this.description = description; 537 this.severity = checkNotNull(severity, "severity"); 538 this.timestampNanos = timestampNanos; 539 this.channelRef = channelRef; 540 this.subchannelRef = subchannelRef; 541 } 542 543 @Override hashCode()544 public int hashCode() { 545 return Objects.hashCode(description, severity, timestampNanos, channelRef, subchannelRef); 546 } 547 548 @Override equals(Object o)549 public boolean equals(Object o) { 550 if (o instanceof Event) { 551 Event that = (Event) o; 552 return Objects.equal(description, that.description) 553 && Objects.equal(severity, that.severity) 554 && timestampNanos == that.timestampNanos 555 && Objects.equal(channelRef, that.channelRef) 556 && Objects.equal(subchannelRef, that.subchannelRef); 557 } 558 return false; 559 } 560 561 @Override toString()562 public String toString() { 563 return MoreObjects.toStringHelper(this) 564 .add("description", description) 565 .add("severity", severity) 566 .add("timestampNanos", timestampNanos) 567 .add("channelRef", channelRef) 568 .add("subchannelRef", subchannelRef) 569 .toString(); 570 } 571 572 public static final class Builder { 573 private String description; 574 private Severity severity; 575 private Long timestampNanos; 576 private InternalWithLogId channelRef; 577 private InternalWithLogId subchannelRef; 578 setDescription(String description)579 public Builder setDescription(String description) { 580 this.description = description; 581 return this; 582 } 583 setTimestampNanos(long timestampNanos)584 public Builder setTimestampNanos(long timestampNanos) { 585 this.timestampNanos = timestampNanos; 586 return this; 587 } 588 setSeverity(Severity severity)589 public Builder setSeverity(Severity severity) { 590 this.severity = severity; 591 return this; 592 } 593 setChannelRef(InternalWithLogId channelRef)594 public Builder setChannelRef(InternalWithLogId channelRef) { 595 this.channelRef = channelRef; 596 return this; 597 } 598 setSubchannelRef(InternalWithLogId subchannelRef)599 public Builder setSubchannelRef(InternalWithLogId subchannelRef) { 600 this.subchannelRef = subchannelRef; 601 return this; 602 } 603 604 /** Builds a new Event instance. */ build()605 public Event build() { 606 checkNotNull(description, "description"); 607 checkNotNull(severity, "severity"); 608 checkNotNull(timestampNanos, "timestampNanos"); 609 checkState( 610 channelRef == null || subchannelRef == null, 611 "at least one of channelRef and subchannelRef must be null"); 612 return new Event(description, severity, timestampNanos, channelRef, subchannelRef); 613 } 614 } 615 } 616 } 617 618 public static final class Security { 619 @Nullable 620 public final Tls tls; 621 @Nullable 622 public final OtherSecurity other; 623 Security(Tls tls)624 public Security(Tls tls) { 625 this.tls = checkNotNull(tls); 626 this.other = null; 627 } 628 Security(OtherSecurity other)629 public Security(OtherSecurity other) { 630 this.tls = null; 631 this.other = checkNotNull(other); 632 } 633 } 634 635 public static final class OtherSecurity { 636 public final String name; 637 @Nullable 638 public final Object any; 639 640 /** 641 * Creates an instance. 642 * @param name the name. 643 * @param any a com.google.protobuf.Any object 644 */ OtherSecurity(String name, @Nullable Object any)645 public OtherSecurity(String name, @Nullable Object any) { 646 this.name = checkNotNull(name); 647 checkState( 648 any == null || any.getClass().getName().endsWith("com.google.protobuf.Any"), 649 "the 'any' object must be of type com.google.protobuf.Any"); 650 this.any = any; 651 } 652 } 653 654 @Immutable 655 public static final class Tls { 656 public final String cipherSuiteStandardName; 657 @Nullable public final Certificate localCert; 658 @Nullable public final Certificate remoteCert; 659 660 /** 661 * A constructor only for testing. 662 */ Tls(String cipherSuiteName, Certificate localCert, Certificate remoteCert)663 public Tls(String cipherSuiteName, Certificate localCert, Certificate remoteCert) { 664 this.cipherSuiteStandardName = cipherSuiteName; 665 this.localCert = localCert; 666 this.remoteCert = remoteCert; 667 } 668 669 /** 670 * Creates an instance. 671 */ Tls(SSLSession session)672 public Tls(SSLSession session) { 673 String cipherSuiteStandardName = session.getCipherSuite(); 674 Certificate localCert = null; 675 Certificate remoteCert = null; 676 Certificate[] localCerts = session.getLocalCertificates(); 677 if (localCerts != null) { 678 localCert = localCerts[0]; 679 } 680 try { 681 Certificate[] peerCerts = session.getPeerCertificates(); 682 if (peerCerts != null) { 683 // The javadoc of getPeerCertificate states that the peer's own certificate is the first 684 // element of the list. 685 remoteCert = peerCerts[0]; 686 } 687 } catch (SSLPeerUnverifiedException e) { 688 // peer cert is not available 689 log.log( 690 Level.FINE, 691 String.format("Peer cert not available for peerHost=%s", session.getPeerHost()), 692 e); 693 } 694 this.cipherSuiteStandardName = cipherSuiteStandardName; 695 this.localCert = localCert; 696 this.remoteCert = remoteCert; 697 } 698 } 699 700 public static final class SocketStats { 701 @Nullable public final TransportStats data; 702 @Nullable public final SocketAddress local; 703 @Nullable public final SocketAddress remote; 704 public final SocketOptions socketOptions; 705 // Can be null if plaintext 706 @Nullable public final Security security; 707 708 /** Creates an instance. */ SocketStats( TransportStats data, @Nullable SocketAddress local, @Nullable SocketAddress remote, SocketOptions socketOptions, Security security)709 public SocketStats( 710 TransportStats data, 711 @Nullable SocketAddress local, 712 @Nullable SocketAddress remote, 713 SocketOptions socketOptions, 714 Security security) { 715 this.data = data; 716 this.local = checkNotNull(local, "local socket"); 717 this.remote = remote; 718 this.socketOptions = checkNotNull(socketOptions); 719 this.security = security; 720 } 721 } 722 723 public static final class TcpInfo { 724 public final int state; 725 public final int caState; 726 public final int retransmits; 727 public final int probes; 728 public final int backoff; 729 public final int options; 730 public final int sndWscale; 731 public final int rcvWscale; 732 public final int rto; 733 public final int ato; 734 public final int sndMss; 735 public final int rcvMss; 736 public final int unacked; 737 public final int sacked; 738 public final int lost; 739 public final int retrans; 740 public final int fackets; 741 public final int lastDataSent; 742 public final int lastAckSent; 743 public final int lastDataRecv; 744 public final int lastAckRecv; 745 public final int pmtu; 746 public final int rcvSsthresh; 747 public final int rtt; 748 public final int rttvar; 749 public final int sndSsthresh; 750 public final int sndCwnd; 751 public final int advmss; 752 public final int reordering; 753 TcpInfo(int state, int caState, int retransmits, int probes, int backoff, int options, int sndWscale, int rcvWscale, int rto, int ato, int sndMss, int rcvMss, int unacked, int sacked, int lost, int retrans, int fackets, int lastDataSent, int lastAckSent, int lastDataRecv, int lastAckRecv, int pmtu, int rcvSsthresh, int rtt, int rttvar, int sndSsthresh, int sndCwnd, int advmss, int reordering)754 TcpInfo(int state, int caState, int retransmits, int probes, int backoff, int options, 755 int sndWscale, int rcvWscale, int rto, int ato, int sndMss, int rcvMss, int unacked, 756 int sacked, int lost, int retrans, int fackets, int lastDataSent, int lastAckSent, 757 int lastDataRecv, int lastAckRecv, int pmtu, int rcvSsthresh, int rtt, int rttvar, 758 int sndSsthresh, int sndCwnd, int advmss, int reordering) { 759 this.state = state; 760 this.caState = caState; 761 this.retransmits = retransmits; 762 this.probes = probes; 763 this.backoff = backoff; 764 this.options = options; 765 this.sndWscale = sndWscale; 766 this.rcvWscale = rcvWscale; 767 this.rto = rto; 768 this.ato = ato; 769 this.sndMss = sndMss; 770 this.rcvMss = rcvMss; 771 this.unacked = unacked; 772 this.sacked = sacked; 773 this.lost = lost; 774 this.retrans = retrans; 775 this.fackets = fackets; 776 this.lastDataSent = lastDataSent; 777 this.lastAckSent = lastAckSent; 778 this.lastDataRecv = lastDataRecv; 779 this.lastAckRecv = lastAckRecv; 780 this.pmtu = pmtu; 781 this.rcvSsthresh = rcvSsthresh; 782 this.rtt = rtt; 783 this.rttvar = rttvar; 784 this.sndSsthresh = sndSsthresh; 785 this.sndCwnd = sndCwnd; 786 this.advmss = advmss; 787 this.reordering = reordering; 788 } 789 790 public static final class Builder { 791 private int state; 792 private int caState; 793 private int retransmits; 794 private int probes; 795 private int backoff; 796 private int options; 797 private int sndWscale; 798 private int rcvWscale; 799 private int rto; 800 private int ato; 801 private int sndMss; 802 private int rcvMss; 803 private int unacked; 804 private int sacked; 805 private int lost; 806 private int retrans; 807 private int fackets; 808 private int lastDataSent; 809 private int lastAckSent; 810 private int lastDataRecv; 811 private int lastAckRecv; 812 private int pmtu; 813 private int rcvSsthresh; 814 private int rtt; 815 private int rttvar; 816 private int sndSsthresh; 817 private int sndCwnd; 818 private int advmss; 819 private int reordering; 820 setState(int state)821 public Builder setState(int state) { 822 this.state = state; 823 return this; 824 } 825 setCaState(int caState)826 public Builder setCaState(int caState) { 827 this.caState = caState; 828 return this; 829 } 830 setRetransmits(int retransmits)831 public Builder setRetransmits(int retransmits) { 832 this.retransmits = retransmits; 833 return this; 834 } 835 setProbes(int probes)836 public Builder setProbes(int probes) { 837 this.probes = probes; 838 return this; 839 } 840 setBackoff(int backoff)841 public Builder setBackoff(int backoff) { 842 this.backoff = backoff; 843 return this; 844 } 845 setOptions(int options)846 public Builder setOptions(int options) { 847 this.options = options; 848 return this; 849 } 850 setSndWscale(int sndWscale)851 public Builder setSndWscale(int sndWscale) { 852 this.sndWscale = sndWscale; 853 return this; 854 } 855 setRcvWscale(int rcvWscale)856 public Builder setRcvWscale(int rcvWscale) { 857 this.rcvWscale = rcvWscale; 858 return this; 859 } 860 setRto(int rto)861 public Builder setRto(int rto) { 862 this.rto = rto; 863 return this; 864 } 865 setAto(int ato)866 public Builder setAto(int ato) { 867 this.ato = ato; 868 return this; 869 } 870 setSndMss(int sndMss)871 public Builder setSndMss(int sndMss) { 872 this.sndMss = sndMss; 873 return this; 874 } 875 setRcvMss(int rcvMss)876 public Builder setRcvMss(int rcvMss) { 877 this.rcvMss = rcvMss; 878 return this; 879 } 880 setUnacked(int unacked)881 public Builder setUnacked(int unacked) { 882 this.unacked = unacked; 883 return this; 884 } 885 setSacked(int sacked)886 public Builder setSacked(int sacked) { 887 this.sacked = sacked; 888 return this; 889 } 890 setLost(int lost)891 public Builder setLost(int lost) { 892 this.lost = lost; 893 return this; 894 } 895 setRetrans(int retrans)896 public Builder setRetrans(int retrans) { 897 this.retrans = retrans; 898 return this; 899 } 900 setFackets(int fackets)901 public Builder setFackets(int fackets) { 902 this.fackets = fackets; 903 return this; 904 } 905 setLastDataSent(int lastDataSent)906 public Builder setLastDataSent(int lastDataSent) { 907 this.lastDataSent = lastDataSent; 908 return this; 909 } 910 setLastAckSent(int lastAckSent)911 public Builder setLastAckSent(int lastAckSent) { 912 this.lastAckSent = lastAckSent; 913 return this; 914 } 915 setLastDataRecv(int lastDataRecv)916 public Builder setLastDataRecv(int lastDataRecv) { 917 this.lastDataRecv = lastDataRecv; 918 return this; 919 } 920 setLastAckRecv(int lastAckRecv)921 public Builder setLastAckRecv(int lastAckRecv) { 922 this.lastAckRecv = lastAckRecv; 923 return this; 924 } 925 setPmtu(int pmtu)926 public Builder setPmtu(int pmtu) { 927 this.pmtu = pmtu; 928 return this; 929 } 930 setRcvSsthresh(int rcvSsthresh)931 public Builder setRcvSsthresh(int rcvSsthresh) { 932 this.rcvSsthresh = rcvSsthresh; 933 return this; 934 } 935 setRtt(int rtt)936 public Builder setRtt(int rtt) { 937 this.rtt = rtt; 938 return this; 939 } 940 setRttvar(int rttvar)941 public Builder setRttvar(int rttvar) { 942 this.rttvar = rttvar; 943 return this; 944 } 945 setSndSsthresh(int sndSsthresh)946 public Builder setSndSsthresh(int sndSsthresh) { 947 this.sndSsthresh = sndSsthresh; 948 return this; 949 } 950 setSndCwnd(int sndCwnd)951 public Builder setSndCwnd(int sndCwnd) { 952 this.sndCwnd = sndCwnd; 953 return this; 954 } 955 setAdvmss(int advmss)956 public Builder setAdvmss(int advmss) { 957 this.advmss = advmss; 958 return this; 959 } 960 setReordering(int reordering)961 public Builder setReordering(int reordering) { 962 this.reordering = reordering; 963 return this; 964 } 965 966 /** Builds an instance. */ build()967 public TcpInfo build() { 968 return new TcpInfo( 969 state, caState, retransmits, probes, backoff, options, sndWscale, rcvWscale, 970 rto, ato, sndMss, rcvMss, unacked, sacked, lost, retrans, fackets, lastDataSent, 971 lastAckSent, lastDataRecv, lastAckRecv, pmtu, rcvSsthresh, rtt, rttvar, sndSsthresh, 972 sndCwnd, advmss, reordering); 973 } 974 } 975 } 976 977 public static final class SocketOptions { 978 public final Map<String, String> others; 979 // In netty, the value of a channel option may be null. 980 @Nullable public final Integer soTimeoutMillis; 981 @Nullable public final Integer lingerSeconds; 982 @Nullable public final TcpInfo tcpInfo; 983 984 /** Creates an instance. */ SocketOptions( @ullable Integer timeoutMillis, @Nullable Integer lingerSeconds, @Nullable TcpInfo tcpInfo, Map<String, String> others)985 public SocketOptions( 986 @Nullable Integer timeoutMillis, 987 @Nullable Integer lingerSeconds, 988 @Nullable TcpInfo tcpInfo, 989 Map<String, String> others) { 990 checkNotNull(others); 991 this.soTimeoutMillis = timeoutMillis; 992 this.lingerSeconds = lingerSeconds; 993 this.tcpInfo = tcpInfo; 994 this.others = Collections.unmodifiableMap(new HashMap<String, String>(others)); 995 } 996 997 public static final class Builder { 998 private final Map<String, String> others = new HashMap<String, String>(); 999 1000 private TcpInfo tcpInfo; 1001 private Integer timeoutMillis; 1002 private Integer lingerSeconds; 1003 1004 /** The value of {@link java.net.Socket#getSoTimeout()}. */ setSocketOptionTimeoutMillis(Integer timeoutMillis)1005 public Builder setSocketOptionTimeoutMillis(Integer timeoutMillis) { 1006 this.timeoutMillis = timeoutMillis; 1007 return this; 1008 } 1009 1010 /** The value of {@link java.net.Socket#getSoLinger()}. 1011 * Note: SO_LINGER is typically expressed in seconds. 1012 */ setSocketOptionLingerSeconds(Integer lingerSeconds)1013 public Builder setSocketOptionLingerSeconds(Integer lingerSeconds) { 1014 this.lingerSeconds = lingerSeconds; 1015 return this; 1016 } 1017 setTcpInfo(TcpInfo tcpInfo)1018 public Builder setTcpInfo(TcpInfo tcpInfo) { 1019 this.tcpInfo = tcpInfo; 1020 return this; 1021 } 1022 addOption(String name, String value)1023 public Builder addOption(String name, String value) { 1024 others.put(name, checkNotNull(value)); 1025 return this; 1026 } 1027 addOption(String name, int value)1028 public Builder addOption(String name, int value) { 1029 others.put(name, Integer.toString(value)); 1030 return this; 1031 } 1032 addOption(String name, boolean value)1033 public Builder addOption(String name, boolean value) { 1034 others.put(name, Boolean.toString(value)); 1035 return this; 1036 } 1037 build()1038 public SocketOptions build() { 1039 return new SocketOptions(timeoutMillis, lingerSeconds, tcpInfo, others); 1040 } 1041 } 1042 } 1043 1044 /** 1045 * A data class to represent transport stats. 1046 */ 1047 @Immutable 1048 public static final class TransportStats { 1049 public final long streamsStarted; 1050 public final long lastLocalStreamCreatedTimeNanos; 1051 public final long lastRemoteStreamCreatedTimeNanos; 1052 public final long streamsSucceeded; 1053 public final long streamsFailed; 1054 public final long messagesSent; 1055 public final long messagesReceived; 1056 public final long keepAlivesSent; 1057 public final long lastMessageSentTimeNanos; 1058 public final long lastMessageReceivedTimeNanos; 1059 public final long localFlowControlWindow; 1060 public final long remoteFlowControlWindow; 1061 // TODO(zpencer): report socket flags and other info 1062 1063 /** 1064 * Creates an instance. 1065 */ TransportStats( long streamsStarted, long lastLocalStreamCreatedTimeNanos, long lastRemoteStreamCreatedTimeNanos, long streamsSucceeded, long streamsFailed, long messagesSent, long messagesReceived, long keepAlivesSent, long lastMessageSentTimeNanos, long lastMessageReceivedTimeNanos, long localFlowControlWindow, long remoteFlowControlWindow)1066 public TransportStats( 1067 long streamsStarted, 1068 long lastLocalStreamCreatedTimeNanos, 1069 long lastRemoteStreamCreatedTimeNanos, 1070 long streamsSucceeded, 1071 long streamsFailed, 1072 long messagesSent, 1073 long messagesReceived, 1074 long keepAlivesSent, 1075 long lastMessageSentTimeNanos, 1076 long lastMessageReceivedTimeNanos, 1077 long localFlowControlWindow, 1078 long remoteFlowControlWindow) { 1079 this.streamsStarted = streamsStarted; 1080 this.lastLocalStreamCreatedTimeNanos = lastLocalStreamCreatedTimeNanos; 1081 this.lastRemoteStreamCreatedTimeNanos = lastRemoteStreamCreatedTimeNanos; 1082 this.streamsSucceeded = streamsSucceeded; 1083 this.streamsFailed = streamsFailed; 1084 this.messagesSent = messagesSent; 1085 this.messagesReceived = messagesReceived; 1086 this.keepAlivesSent = keepAlivesSent; 1087 this.lastMessageSentTimeNanos = lastMessageSentTimeNanos; 1088 this.lastMessageReceivedTimeNanos = lastMessageReceivedTimeNanos; 1089 this.localFlowControlWindow = localFlowControlWindow; 1090 this.remoteFlowControlWindow = remoteFlowControlWindow; 1091 } 1092 } 1093 1094 /** Unwraps a {@link InternalLogId} to return a {@code long}. */ id(InternalWithLogId withLogId)1095 public static long id(InternalWithLogId withLogId) { 1096 return withLogId.getLogId().getId(); 1097 } 1098 } 1099