google.golang.org/grpc@v1.72.2/channelz/internal/protoconv/socket.go (about) 1 /* 2 * 3 * Copyright 2024 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package protoconv 20 21 import ( 22 "net" 23 "time" 24 25 "google.golang.org/grpc/codes" 26 "google.golang.org/grpc/credentials" 27 "google.golang.org/grpc/internal/channelz" 28 "google.golang.org/grpc/status" 29 "google.golang.org/protobuf/types/known/anypb" 30 "google.golang.org/protobuf/types/known/timestamppb" 31 "google.golang.org/protobuf/types/known/wrapperspb" 32 33 channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1" 34 ) 35 36 func securityToProto(se credentials.ChannelzSecurityValue) *channelzpb.Security { 37 switch v := se.(type) { 38 case *credentials.TLSChannelzSecurityValue: 39 return &channelzpb.Security{Model: &channelzpb.Security_Tls_{Tls: &channelzpb.Security_Tls{ 40 CipherSuite: &channelzpb.Security_Tls_StandardName{StandardName: v.StandardName}, 41 LocalCertificate: v.LocalCertificate, 42 RemoteCertificate: v.RemoteCertificate, 43 }}} 44 case *credentials.OtherChannelzSecurityValue: 45 otherSecurity := &channelzpb.Security_OtherSecurity{ 46 Name: v.Name, 47 } 48 if anyval, err := anypb.New(v.Value); err == nil { 49 otherSecurity.Value = anyval 50 } 51 return &channelzpb.Security{Model: &channelzpb.Security_Other{Other: otherSecurity}} 52 } 53 return nil 54 } 55 56 func addrToProto(a net.Addr) *channelzpb.Address { 57 if a == nil { 58 return nil 59 } 60 switch a.Network() { 61 case "udp": 62 // TODO: Address_OtherAddress{}. Need proto def for Value. 63 case "ip": 64 // Note zone info is discarded through the conversion. 65 return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPAddr).IP}}} 66 case "ip+net": 67 // Note mask info is discarded through the conversion. 68 return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPNet).IP}}} 69 case "tcp": 70 // Note zone info is discarded through the conversion. 71 return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.TCPAddr).IP, Port: int32(a.(*net.TCPAddr).Port)}}} 72 case "unix", "unixgram", "unixpacket": 73 return &channelzpb.Address{Address: &channelzpb.Address_UdsAddress_{UdsAddress: &channelzpb.Address_UdsAddress{Filename: a.String()}}} 74 default: 75 } 76 return &channelzpb.Address{} 77 } 78 79 func socketToProto(skt *channelz.Socket) *channelzpb.Socket { 80 s := &channelzpb.Socket{} 81 s.Ref = &channelzpb.SocketRef{SocketId: skt.ID, Name: skt.RefName} 82 83 s.Data = &channelzpb.SocketData{ 84 StreamsStarted: skt.SocketMetrics.StreamsStarted.Load(), 85 StreamsSucceeded: skt.SocketMetrics.StreamsSucceeded.Load(), 86 StreamsFailed: skt.SocketMetrics.StreamsFailed.Load(), 87 MessagesSent: skt.SocketMetrics.MessagesSent.Load(), 88 MessagesReceived: skt.SocketMetrics.MessagesReceived.Load(), 89 KeepAlivesSent: skt.SocketMetrics.KeepAlivesSent.Load(), 90 } 91 if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastLocalStreamCreatedTimestamp.Load())); ts.IsValid() { 92 s.Data.LastLocalStreamCreatedTimestamp = ts 93 } 94 if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastRemoteStreamCreatedTimestamp.Load())); ts.IsValid() { 95 s.Data.LastRemoteStreamCreatedTimestamp = ts 96 } 97 if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastMessageSentTimestamp.Load())); ts.IsValid() { 98 s.Data.LastMessageSentTimestamp = ts 99 } 100 if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastMessageReceivedTimestamp.Load())); ts.IsValid() { 101 s.Data.LastMessageReceivedTimestamp = ts 102 } 103 if skt.EphemeralMetrics != nil { 104 e := skt.EphemeralMetrics() 105 s.Data.LocalFlowControlWindow = wrapperspb.Int64(e.LocalFlowControlWindow) 106 s.Data.RemoteFlowControlWindow = wrapperspb.Int64(e.RemoteFlowControlWindow) 107 } 108 109 s.Data.Option = sockoptToProto(skt.SocketOptions) 110 s.Security = securityToProto(skt.Security) 111 s.Local = addrToProto(skt.LocalAddr) 112 s.Remote = addrToProto(skt.RemoteAddr) 113 s.RemoteName = skt.RemoteName 114 return s 115 } 116 117 // GetServerSockets returns the protobuf representation of the server (listen) 118 // sockets starting at startID (max of len), and returns end=true if no server 119 // sockets exist with higher IDs. 120 func GetServerSockets(serverID, startID int64, len int) (sockets []*channelzpb.SocketRef, end bool) { 121 skts, end := channelz.GetServerSockets(serverID, startID, len) 122 for _, m := range skts { 123 sockets = append(sockets, &channelzpb.SocketRef{SocketId: m.ID, Name: m.RefName}) 124 } 125 return sockets, end 126 } 127 128 // GetSocket returns the protobuf representation of the socket with the given 129 // ID. 130 func GetSocket(id int64) (*channelzpb.Socket, error) { 131 skt := channelz.GetSocket(id) 132 if skt == nil { 133 return nil, status.Errorf(codes.NotFound, "requested socket %d not found", id) 134 } 135 return socketToProto(skt), nil 136 }