View Javadoc
1   /*
2    * Copyright 2020-2023 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.software.os;
6   
7   import java.net.InetAddress;
8   import java.net.UnknownHostException;
9   import java.util.Arrays;
10  import java.util.List;
11  
12  import oshi.annotation.concurrent.Immutable;
13  import oshi.annotation.concurrent.ThreadSafe;
14  
15  /**
16   * Includes key statistics of TCP and UDP protocols
17   */
18  @ThreadSafe
19  public interface InternetProtocolStats {
20  
21      /**
22       * Get the TCP stats for IPv4 connections.
23       * <p>
24       * On macOS connection information requires elevated permissions. Without elevatd permissions, segment data is
25       * estimated.
26       *
27       * @return a {@link TcpStats} object encapsulating the stats.
28       */
29      TcpStats getTCPv4Stats();
30  
31      /**
32       * Get the TCP stats for IPv6 connections, if available. If not available separately, these may be 0 and included in
33       * IPv4 connections.
34       *
35       * @return a {@link TcpStats} object encapsulating the stats.
36       */
37      TcpStats getTCPv6Stats();
38  
39      /**
40       * Get the UDP stats for IPv4 datagrams.
41       *
42       * @return a {@link UdpStats} object encapsulating the stats.
43       */
44      UdpStats getUDPv4Stats();
45  
46      /**
47       * Get the UDP stats for IPv6 datagrams, if available. If not available separately, these may be 0 and included in
48       * IPv4 datagrams.
49       *
50       * @return a {@link UdpStats} object encapsulating the stats.
51       */
52      UdpStats getUDPv6Stats();
53  
54      /**
55       * Gets a list of TCP and UDP connections.
56       *
57       * @return A list of {@link IPConnection} objects for TCP and UDP connections.
58       */
59      List<IPConnection> getConnections();
60  
61      /**
62       * Encapsulates statistics associated with a TCP connection.
63       */
64      @Immutable
65      final class TcpStats {
66          private final long connectionsEstablished;
67          private final long connectionsActive;
68          private final long connectionsPassive;
69          private final long connectionFailures;
70          private final long connectionsReset;
71          private final long segmentsSent;
72          private final long segmentsReceived;
73          private final long segmentsRetransmitted;
74          private final long inErrors;
75          private final long outResets;
76  
77          public TcpStats(long connectionsEstablished, long connectionsActive, long connectionsPassive,
78                  long connectionFailures, long connectionsReset, long segmentsSent, long segmentsReceived,
79                  long segmentsRetransmitted, long inErrors, long outResets) {
80              this.connectionsEstablished = connectionsEstablished;
81              this.connectionsActive = connectionsActive;
82              this.connectionsPassive = connectionsPassive;
83              this.connectionFailures = connectionFailures;
84              this.connectionsReset = connectionsReset;
85              this.segmentsSent = segmentsSent;
86              this.segmentsReceived = segmentsReceived;
87              this.segmentsRetransmitted = segmentsRetransmitted;
88              this.inErrors = inErrors;
89              this.outResets = outResets;
90          }
91  
92          /**
93           * Connections Established is the number of TCP connections for which the current state is either ESTABLISHED or
94           * CLOSE-WAIT
95           *
96           * @return the connectionsEstablished
97           */
98          public long getConnectionsEstablished() {
99              return connectionsEstablished;
100         }
101 
102         /**
103          * Connections Active is the number of times TCP connections have made a direct transition to the SYN-SENT state
104          * from the CLOSED state. In other words, it shows a number of connections which are initiated by the local
105          * computer. The value is a cumulative total.
106          *
107          * @return the connectionsActive
108          */
109         public long getConnectionsActive() {
110             return connectionsActive;
111         }
112 
113         /**
114          * Connections Passive is the number of times TCP connections have made a direct transition to the SYN-RCVD
115          * state from the LISTEN state. In other words, it shows a number of connections to the local computer, which
116          * are initiated by remote computers. The value is a cumulative total.
117          *
118          * @return the connectionsPassive
119          */
120         public long getConnectionsPassive() {
121             return connectionsPassive;
122         }
123 
124         /**
125          * Connection Failures is the number of times TCP connections have made a direct transition to the CLOSED state
126          * from the SYN-SENT state or the SYN-RCVD state, plus the number of times TCP connections have made a direct
127          * transition to the LISTEN state from the SYN-RCVD state.
128          *
129          * @return the connectionFailures
130          */
131         public long getConnectionFailures() {
132             return connectionFailures;
133         }
134 
135         /**
136          * Connections Reset is the number of times TCP connections have made a direct transition to the CLOSED state
137          * from either the ESTABLISHED state or the CLOSE-WAIT state.
138          *
139          * @return the connectionsReset
140          */
141         public long getConnectionsReset() {
142             return connectionsReset;
143         }
144 
145         /**
146          * Segments Sent is the number of segments sent, including those on current connections, but excluding those
147          * containing only retransmitted bytes.
148          *
149          * @return the segmentsSent
150          */
151         public long getSegmentsSent() {
152             return segmentsSent;
153         }
154 
155         /**
156          * Segments Received is the number of segments received, including those received in error. This count includes
157          * segments received on currently established connections.
158          *
159          * @return the segmentsReceived
160          */
161         public long getSegmentsReceived() {
162             return segmentsReceived;
163         }
164 
165         /**
166          * Segments Retransmitted is the number of segments retransmitted, that is, segments transmitted containing one
167          * or more previously transmitted bytes.
168          *
169          * @return the segmentsRetransmitted
170          */
171         public long getSegmentsRetransmitted() {
172             return segmentsRetransmitted;
173         }
174 
175         /**
176          * The number of errors received.
177          *
178          * @return the inErrors
179          */
180         public long getInErrors() {
181             return inErrors;
182         }
183 
184         /**
185          * The number of segments transmitted with the reset flag set.
186          *
187          * @return the outResets
188          */
189         public long getOutResets() {
190             return outResets;
191         }
192 
193         @Override
194         public String toString() {
195             return "TcpStats [connectionsEstablished=" + connectionsEstablished + ", connectionsActive="
196                     + connectionsActive + ", connectionsPassive=" + connectionsPassive + ", connectionFailures="
197                     + connectionFailures + ", connectionsReset=" + connectionsReset + ", segmentsSent=" + segmentsSent
198                     + ", segmentsReceived=" + segmentsReceived + ", segmentsRetransmitted=" + segmentsRetransmitted
199                     + ", inErrors=" + inErrors + ", outResets=" + outResets + "]";
200         }
201     }
202 
203     /**
204      * Encapsulates statistics associated with a UDP connection.
205      */
206     @Immutable
207     final class UdpStats {
208         private final long datagramsSent;
209         private final long datagramsReceived;
210         private final long datagramsNoPort;
211         private final long datagramsReceivedErrors;
212 
213         public UdpStats(long datagramsSent, long datagramsReceived, long datagramsNoPort,
214                 long datagramsReceivedErrors) {
215             this.datagramsSent = datagramsSent;
216             this.datagramsReceived = datagramsReceived;
217             this.datagramsNoPort = datagramsNoPort;
218             this.datagramsReceivedErrors = datagramsReceivedErrors;
219         }
220 
221         /**
222          * Datagrams Sent is the number of UDP datagrams sent from the entity.
223          *
224          * @return the datagramsSent
225          */
226         public long getDatagramsSent() {
227             return datagramsSent;
228         }
229 
230         /**
231          * Datagrams Received is the number of UDP datagrams delivered to UDP users.
232          *
233          * @return the datagramsReceived
234          */
235         public long getDatagramsReceived() {
236             return datagramsReceived;
237         }
238 
239         /**
240          * Datagrams No Port is the number of received UDP datagrams for which there was no application at the
241          * destination port.
242          *
243          * @return the datagramsNoPort
244          */
245         public long getDatagramsNoPort() {
246             return datagramsNoPort;
247         }
248 
249         /**
250          * Datagrams Received Errors is the number of received UDP datagrams that could not be delivered for reasons
251          * other than the lack of an application at the destination port.
252          *
253          * @return the datagramsReceivedErrors
254          */
255         public long getDatagramsReceivedErrors() {
256             return datagramsReceivedErrors;
257         }
258 
259         @Override
260         public String toString() {
261             return "UdpStats [datagramsSent=" + datagramsSent + ", datagramsReceived=" + datagramsReceived
262                     + ", datagramsNoPort=" + datagramsNoPort + ", datagramsReceivedErrors=" + datagramsReceivedErrors
263                     + "]";
264         }
265     }
266 
267     /**
268      * The TCP connection state as described in RFC 793.
269      */
270     enum TcpState {
271         UNKNOWN, CLOSED, LISTEN, SYN_SENT, SYN_RECV, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT, CLOSING, LAST_ACK,
272         TIME_WAIT, NONE;
273     }
274 
275     /**
276      * Encapsulates information associated with an IP connection.
277      */
278     @Immutable
279     final class IPConnection {
280         private final String type;
281         private final byte[] localAddress;
282         private final int localPort;
283         private final byte[] foreignAddress;
284         private final int foreignPort;
285         private final TcpState state;
286         private final int transmitQueue;
287         private final int receiveQueue;
288         private int owningProcessId;
289 
290         public IPConnection(String type, byte[] localAddress, int localPort, byte[] foreignAddress, int foreignPort,
291                 TcpState state, int transmitQueue, int receiveQueue, int owningProcessId) {
292             this.type = type;
293             this.localAddress = Arrays.copyOf(localAddress, localAddress.length);
294             this.localPort = localPort;
295             this.foreignAddress = Arrays.copyOf(foreignAddress, foreignAddress.length);
296             this.foreignPort = foreignPort;
297             this.state = state;
298             this.transmitQueue = transmitQueue;
299             this.receiveQueue = receiveQueue;
300             this.owningProcessId = owningProcessId;
301         }
302 
303         /**
304          * Returns the connection protocol type, e.g., tcp4, tcp6, tcp46, udp4, udp6, udp46
305          *
306          * @return The protocol type
307          */
308         public String getType() {
309             return type;
310         }
311 
312         /**
313          * Gets the local address. For IPv4 addresses this is a 4-byte array. For IPv6 addresses this is a 16-byte
314          * array.
315          * <p>
316          * On Unix operating systems, the 16-bit value may be truncated, giving only the high order bytes. IPv6
317          * addresses ending in zeroes should be considered suspect.
318          *
319          * @return The local address, or an empty array if the listener can accept a connection on any interface.
320          */
321         public byte[] getLocalAddress() {
322             return Arrays.copyOf(localAddress, localAddress.length);
323         }
324 
325         /**
326          * Gets the local port.
327          *
328          * @return The local port, or 0 if unknown, or any port.
329          */
330         public int getLocalPort() {
331             return localPort;
332         }
333 
334         /**
335          * Gets the foreign/remote address. For IPv4 addresses this is a 4-byte array. For IPv6 addresses this is a
336          * 16-byte array.
337          * <p>
338          * On Unix operating systems, this value may be truncated. IPv6 addresses ending in zeroes should be considered
339          * suspect.
340          *
341          * @return The foreign/remote address, or an empty array if unknown. An empty array will also result if
342          */
343         public byte[] getForeignAddress() {
344             return Arrays.copyOf(foreignAddress, foreignAddress.length);
345         }
346 
347         /**
348          * Gets the foreign/remote port.
349          *
350          * @return The foreign/remote port, or 0 if unknown.
351          */
352         public int getForeignPort() {
353             return foreignPort;
354         }
355 
356         /**
357          * Gets the connection state (TCP connections only).
358          *
359          * @return The connection state if known or relevant, null otherwise.
360          */
361         public TcpState getState() {
362             return state;
363         }
364 
365         /**
366          * Gets the size of the transmit queue. Not available on Windows.
367          *
368          * @return The size of the transmit queue, or 0 if unknown.
369          */
370         public int getTransmitQueue() {
371             return transmitQueue;
372         }
373 
374         /**
375          * Gets the size of the receive queue. Not available on Windows.
376          *
377          * @return The size of the receive queue, or 0 if unknown.
378          */
379         public int getReceiveQueue() {
380             return receiveQueue;
381         }
382 
383         /**
384          * Gets the id of the process which holds this connection.
385          *
386          * @return The process id of the process which holds this connection if known, -1 otherwise.
387          */
388         public int getowningProcessId() {
389             return owningProcessId;
390         }
391 
392         @Override
393         public String toString() {
394             String localIp = "*";
395             try {
396                 localIp = InetAddress.getByAddress(localAddress).toString();
397             } catch (UnknownHostException e) { // NOSONAR squid:S108
398             }
399             String foreignIp = "*";
400             try {
401                 foreignIp = InetAddress.getByAddress(foreignAddress).toString();
402             } catch (UnknownHostException e) { // NOSONAR squid:S108
403             }
404             return "IPConnection [type=" + type + ", localAddress=" + localIp + ", localPort=" + localPort
405                     + ", foreignAddress=" + foreignIp + ", foreignPort=" + foreignPort + ", state=" + state
406                     + ", transmitQueue=" + transmitQueue + ", receiveQueue=" + receiveQueue + ", owningProcessId="
407                     + owningProcessId + "]";
408         }
409     }
410 }