View Javadoc
1   /*
2    * Copyright 2020-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.mac;
6   
7   import java.net.NetworkInterface;
8   import java.util.ArrayList;
9   import java.util.List;
10  import java.util.Map;
11  
12  import org.slf4j.Logger;
13  import org.slf4j.LoggerFactory;
14  
15  import com.sun.jna.Pointer;
16  import com.sun.jna.platform.mac.CoreFoundation.CFArrayRef;
17  import com.sun.jna.platform.mac.CoreFoundation.CFStringRef;
18  
19  import oshi.annotation.concurrent.ThreadSafe;
20  import oshi.driver.mac.net.NetStat;
21  import oshi.driver.mac.net.NetStat.IFdata;
22  import oshi.hardware.NetworkIF;
23  import oshi.hardware.common.AbstractNetworkIF;
24  import oshi.jna.platform.mac.SystemConfiguration;
25  import oshi.jna.platform.mac.SystemConfiguration.SCNetworkInterfaceRef;
26  
27  /**
28   * MacNetworks class.
29   */
30  @ThreadSafe
31  public final class MacNetworkIF extends AbstractNetworkIF {
32  
33      private static final Logger LOG = LoggerFactory.getLogger(MacNetworkIF.class);
34  
35      private int ifType;
36      private long bytesRecv;
37      private long bytesSent;
38      private long packetsRecv;
39      private long packetsSent;
40      private long inErrors;
41      private long outErrors;
42      private long inDrops;
43      private long collisions;
44      private long speed;
45      private long timeStamp;
46  
47      public MacNetworkIF(NetworkInterface netint, Map<Integer, IFdata> data) throws InstantiationException {
48          super(netint, queryIfDisplayName(netint));
49          updateNetworkStats(data);
50      }
51  
52      private static String queryIfDisplayName(NetworkInterface netint) {
53          String name = netint.getName();
54          CFArrayRef ifArray = SystemConfiguration.INSTANCE.SCNetworkInterfaceCopyAll();
55          if (ifArray != null) {
56              try {
57                  int count = ifArray.getCount();
58                  for (int i = 0; i < count; i++) {
59                      Pointer pNetIf = ifArray.getValueAtIndex(i);
60                      SCNetworkInterfaceRef scNetIf = new SCNetworkInterfaceRef(pNetIf);
61                      CFStringRef cfName = SystemConfiguration.INSTANCE.SCNetworkInterfaceGetBSDName(scNetIf);
62                      if (cfName != null && name.equals(cfName.stringValue())) {
63                          CFStringRef cfDisplayName = SystemConfiguration.INSTANCE
64                                  .SCNetworkInterfaceGetLocalizedDisplayName(scNetIf);
65                          return cfDisplayName.stringValue();
66                      }
67                  }
68              } finally {
69                  ifArray.release();
70              }
71          }
72          return name;
73      }
74  
75      /**
76       * Gets all network interfaces on this machine
77       *
78       * @param includeLocalInterfaces include local interfaces in the result
79       * @return A list of {@link NetworkIF} objects representing the interfaces
80       */
81      public static List<NetworkIF> getNetworks(boolean includeLocalInterfaces) {
82          // One time fetch of stats
83          final Map<Integer, IFdata> data = NetStat.queryIFdata(-1);
84          List<NetworkIF> ifList = new ArrayList<>();
85          for (NetworkInterface ni : getNetworkInterfaces(includeLocalInterfaces)) {
86              try {
87                  ifList.add(new MacNetworkIF(ni, data));
88              } catch (InstantiationException e) {
89                  LOG.debug("Network Interface Instantiation failed: {}", e.getMessage());
90              }
91          }
92          return ifList;
93      }
94  
95      @Override
96      public int getIfType() {
97          return this.ifType;
98      }
99  
100     @Override
101     public long getBytesRecv() {
102         return this.bytesRecv;
103     }
104 
105     @Override
106     public long getBytesSent() {
107         return this.bytesSent;
108     }
109 
110     @Override
111     public long getPacketsRecv() {
112         return this.packetsRecv;
113     }
114 
115     @Override
116     public long getPacketsSent() {
117         return this.packetsSent;
118     }
119 
120     @Override
121     public long getInErrors() {
122         return this.inErrors;
123     }
124 
125     @Override
126     public long getOutErrors() {
127         return this.outErrors;
128     }
129 
130     @Override
131     public long getInDrops() {
132         return this.inDrops;
133     }
134 
135     @Override
136     public long getCollisions() {
137         return this.collisions;
138     }
139 
140     @Override
141     public long getSpeed() {
142         return this.speed;
143     }
144 
145     @Override
146     public long getTimeStamp() {
147         return this.timeStamp;
148     }
149 
150     @Override
151     public boolean updateAttributes() {
152         int index = queryNetworkInterface().getIndex();
153         return updateNetworkStats(NetStat.queryIFdata(index));
154     }
155 
156     /**
157      * Updates interface network statistics on the given interface. Statistics include packets and bytes sent and
158      * received, and interface speed.
159      *
160      * @param data A map of network interface statistics with the index as the key
161      * @return {@code true} if the update was successful, {@code false} otherwise.
162      */
163     private boolean updateNetworkStats(Map<Integer, IFdata> data) {
164         int index = queryNetworkInterface().getIndex();
165         if (data.containsKey(index)) {
166             IFdata ifData = data.get(index);
167             // Update data
168             this.ifType = ifData.getIfType();
169             this.bytesSent = ifData.getOBytes();
170             this.bytesRecv = ifData.getIBytes();
171             this.packetsSent = ifData.getOPackets();
172             this.packetsRecv = ifData.getIPackets();
173             this.outErrors = ifData.getOErrors();
174             this.inErrors = ifData.getIErrors();
175             this.collisions = ifData.getCollisions();
176             this.inDrops = ifData.getIDrops();
177             this.speed = ifData.getSpeed();
178             this.timeStamp = ifData.getTimeStamp();
179             return true;
180         }
181         return false;
182     }
183 
184 }