1// +build !appengine
2
3/*
4 *
5 * Copyright 2018 gRPC authors.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21package service
22
23import (
24	"time"
25
26	"github.com/golang/protobuf/ptypes"
27	durpb "github.com/golang/protobuf/ptypes/duration"
28	channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
29	"google.golang.org/grpc/internal/channelz"
30)
31
32func convertToPtypesDuration(sec int64, usec int64) *durpb.Duration {
33	return ptypes.DurationProto(time.Duration(sec*1e9 + usec*1e3))
34}
35
36func sockoptToProto(skopts *channelz.SocketOptionData) []*channelzpb.SocketOption {
37	var opts []*channelzpb.SocketOption
38	if skopts.Linger != nil {
39		additional, err := ptypes.MarshalAny(&channelzpb.SocketOptionLinger{
40			Active:   skopts.Linger.Onoff != 0,
41			Duration: convertToPtypesDuration(int64(skopts.Linger.Linger), 0),
42		})
43		if err == nil {
44			opts = append(opts, &channelzpb.SocketOption{
45				Name:       "SO_LINGER",
46				Additional: additional,
47			})
48		}
49	}
50	if skopts.RecvTimeout != nil {
51		additional, err := ptypes.MarshalAny(&channelzpb.SocketOptionTimeout{
52			Duration: convertToPtypesDuration(int64(skopts.RecvTimeout.Sec), int64(skopts.RecvTimeout.Usec)),
53		})
54		if err == nil {
55			opts = append(opts, &channelzpb.SocketOption{
56				Name:       "SO_RCVTIMEO",
57				Additional: additional,
58			})
59		}
60	}
61	if skopts.SendTimeout != nil {
62		additional, err := ptypes.MarshalAny(&channelzpb.SocketOptionTimeout{
63			Duration: convertToPtypesDuration(int64(skopts.SendTimeout.Sec), int64(skopts.SendTimeout.Usec)),
64		})
65		if err == nil {
66			opts = append(opts, &channelzpb.SocketOption{
67				Name:       "SO_SNDTIMEO",
68				Additional: additional,
69			})
70		}
71	}
72	if skopts.TCPInfo != nil {
73		additional, err := ptypes.MarshalAny(&channelzpb.SocketOptionTcpInfo{
74			TcpiState:       uint32(skopts.TCPInfo.State),
75			TcpiCaState:     uint32(skopts.TCPInfo.Ca_state),
76			TcpiRetransmits: uint32(skopts.TCPInfo.Retransmits),
77			TcpiProbes:      uint32(skopts.TCPInfo.Probes),
78			TcpiBackoff:     uint32(skopts.TCPInfo.Backoff),
79			TcpiOptions:     uint32(skopts.TCPInfo.Options),
80			// https://golang.org/pkg/syscall/#TCPInfo
81			// TCPInfo struct does not contain info about TcpiSndWscale and TcpiRcvWscale.
82			TcpiRto:          skopts.TCPInfo.Rto,
83			TcpiAto:          skopts.TCPInfo.Ato,
84			TcpiSndMss:       skopts.TCPInfo.Snd_mss,
85			TcpiRcvMss:       skopts.TCPInfo.Rcv_mss,
86			TcpiUnacked:      skopts.TCPInfo.Unacked,
87			TcpiSacked:       skopts.TCPInfo.Sacked,
88			TcpiLost:         skopts.TCPInfo.Lost,
89			TcpiRetrans:      skopts.TCPInfo.Retrans,
90			TcpiFackets:      skopts.TCPInfo.Fackets,
91			TcpiLastDataSent: skopts.TCPInfo.Last_data_sent,
92			TcpiLastAckSent:  skopts.TCPInfo.Last_ack_sent,
93			TcpiLastDataRecv: skopts.TCPInfo.Last_data_recv,
94			TcpiLastAckRecv:  skopts.TCPInfo.Last_ack_recv,
95			TcpiPmtu:         skopts.TCPInfo.Pmtu,
96			TcpiRcvSsthresh:  skopts.TCPInfo.Rcv_ssthresh,
97			TcpiRtt:          skopts.TCPInfo.Rtt,
98			TcpiRttvar:       skopts.TCPInfo.Rttvar,
99			TcpiSndSsthresh:  skopts.TCPInfo.Snd_ssthresh,
100			TcpiSndCwnd:      skopts.TCPInfo.Snd_cwnd,
101			TcpiAdvmss:       skopts.TCPInfo.Advmss,
102			TcpiReordering:   skopts.TCPInfo.Reordering,
103		})
104		if err == nil {
105			opts = append(opts, &channelzpb.SocketOption{
106				Name:       "TCP_INFO",
107				Additional: additional,
108			})
109		}
110	}
111	return opts
112}
113