-
-
Notifications
You must be signed in to change notification settings - Fork 879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Host/domain name, dns servers and default gateways information for Win/Linux #294
Conversation
Looks like you missed committing one of the changed files:
|
int maxNameServer = 3; | ||
List<String> servers = new ArrayList<>(); | ||
for(String line: resolv){ | ||
if(!line.startsWith(key)) continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style: avoid the continue
and break
in the same loop. Just test for a true startsWith()
here and put the rest of the method inside the if()
.
value.charAt(0) == '#' || value.charAt(0) == ';') continue; | ||
String val = value.split("[ \t#;]", 2)[0]; | ||
servers.add(val); | ||
if(servers.size() >= maxNameServer) break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use brackets and separate lines. If you're using Eclipse IDE, use its code style for "Sun Java Conventions". Also change your "cleanup" style to remove unused imports that I see the codacy-bot has flagged.
if(fields.length > 3 && fields[0].equals("::/0")) { | ||
try{ | ||
boolean isGateway = fields[2].indexOf('G') != -1; | ||
int metric = Integer.parseInt(fields[3]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ParseUtil.parseIntOrDefault()
which already handles the exception and will simplify your code.
*/ | ||
@Override | ||
public String getIpv4DefaultGateway() { | ||
String dest = "0.0.0.0/0"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put this (and other similar throughout the PR) string as a constant at the top of the file.
Map<String, List<Object>> vals = WmiUtil.selectObjectsFrom("ROOT\\StandardCimv2", "MSFT_NetRoute", | ||
"NextHop,RouteMetric", "WHERE DestinationPrefix=\"" + dest + "\"", GATEWAY_TYPES); | ||
List<Object> metrics = vals.get("RouteMetric"); | ||
if (vals.get("RouteMetric").size() == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style/readability: use !isEmpty()
and go straight to what's currently under else
. Then just put the return "";
after the if.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good. You're missing one file needed for compiling (no doubt you made a local change and missed committing it).
See style comments by codacy-bot and this review; use a code formatting IDE if you can (if not I'll just do a pass after merging the PR).
*/ | ||
@Override | ||
public String getHostName() { | ||
String hn = FileUtil.getStringFromFile("/proc/sys/kernel/hostname"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer native calls to reading files or parsing command lines. In this case, there is a gethostname()
function in libc
.
*/ | ||
@Override | ||
public String getDomainName() { | ||
return ExecutingCommand.getFirstAnswer("dnsdomainname"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer native calls to reading files or parsing command lines. In this case, dnsdomainname
is the result of calling getaddrinfo()
on the result of gethostname()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more comments. Note the code for getaddrinfo()
and hostname()
will be portable to Unix (Solaris and FreeBSD) as well.
See comments on #269 for code which works on other OS's. |
Some more thoughts: Why aren't we using built-in Java methods that already do all the cross-platform heavy lifting (probably using the same system calls I already suggested we use)? For example:
(As an aside, my initial objection to adding these to OSHI was because they were already available to users in core java. It makes sense to add them as part of an overall implementation including other things, though.) For the gateway, There is a non-API cross-platform Sun way of getting the nameservers:
But we shouldn't use non-API methods. Still, digging into the source code of their implementations may be instructive although the |
That sun package would not likely work with ibm jdk
Get Outlook for Android<https://aka.ms/ghei36>
…________________________________
From: dbwiddis <[email protected]>
Sent: Tuesday, January 3, 2017 6:23:31 PM
To: oshi/oshi
Cc: Subscribed
Subject: Re: [oshi/oshi] Host/domain name, dns servers and default gateways information for Win/Linux (#294)
Some more thoughts:
Why aren't we using built-in Java methods that already do all the cross-platform heavy lifting (probably using the same system calls I already suggested we use)? For example:
* Host Name: just use InetAddress.getHostName()
* Domain Name: just use InetAddress.getCanonicalHostName()
(As an aside, my initial objection to adding these to OSHI was because they were already available to users in core java. It makes sense to add them as part of an overall implementation including other things, though.)
For the gateway, netstat -nr is cross-platform (OSX, Linux, Unix, and even Windows, although the Windows output format is different) so you could implement that in a parent class, and override on Windows only with the WMI implementation, although the route command alternatives also work.
There is a non-API cross-platform Sun way of getting the nameservers:
List<String> nameservers = (List<String>) sun.net.dns.ResolverConfiguration.open().nameservers();
But we shouldn't use non-API methods. Still, digging into the source code of their implementations may be instructive although the resolv.conf approach for *nix, WMI for WIndows, and scutil --dns for OSX are probably sufficient.
-
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub<#294 (comment)>, or mute the thread<https://github.com/notifications/unsubscribe-auth/AA7ho0jxSD63dOrvcKuRTDcJI17buWvCks5rOthzgaJpZM4LZz93>.
|
import oshi.json.software.os.OSFileStore; | ||
import oshi.json.util.PropertiesUtil; | ||
|
||
public class NetworkPramsImpl extends AbstractOshiJsonObject implements NetworkParams{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Class name typo.
@Override | ||
public JsonObject toJSON(Properties properties) { | ||
JsonObjectBuilder json = NullAwareJsonObjectBuilder.wrap(this.jsonFactory.createObjectBuilder()); | ||
if (PropertiesUtil.getBoolean(properties, "operatingSystem.networkParams.hostName")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to add all these property strings to the sample oshi.json.properties file in src/test/resources.
Agreed we should not use the sun package. I was only suggesting it from a 'look at the source' standpoint. Which may be overkill. I did find a |
I was also hesitated on add host/dns domain name at beginning, it was then added because it's kind of weird having a network parameter but couldn't provide these two things. But like you said, maybe I should make getHostName as a As for the resolving code, actually it was following how the sun |
* using `InetAddress.getLocalHost().getHostName()` for getHostName * put resolv.conf parsing code to its getDnsServers
Glad to hear you dug into the Sun class. As for the host/dns names, I'd default to the
|
My suggestion based on everything discussed so far:
|
This StackOverflow post discusses why |
Current coverage is 84.62% (diff: 100%)@@ master #294 diff @@
==========================================
Files 23 23
Lines 1080 1080
Methods 0 0
Messages 0 0
Branches 195 195
==========================================
Hits 914 914
Misses 72 72
Partials 94 94
|
@dbwiddis PTAL Changes:
|
I'll take a look at this later this week. I see you've written a junit test. We'll also probably want one in SystemInfoTest as an example, but I'll probably work on that as I'm testing this so no need for you to do that. Thanks for your work on this! |
A few quick comments... codacy found an unused |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. Just a few more changes needed. See comments.
} | ||
|
||
private String getNextHop(String dest) { | ||
Map<String, List<Object>> vals = WmiUtil.selectObjectsFrom("ROOT\\StandardCimv2", "MSFT_NetRoute", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ROOT\\StandardCimv2
requires Windows 8+. This call produces errors on Windows 7.
We need to provide a fallback method for finding the default gateway on Win7. My suggestion would be to parse the output of netstat -nr
and return the gateway for 0.0.0.0
(IPv4) and ::/0
(IPv6).
LOG.error("Failed to get dns domain name. Error code: {}", Kernel32.INSTANCE.GetLastError()); | ||
return ""; | ||
} | ||
return new String(buffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On my test VM, buffer is filled with null characters, so the String
results in "\u0000\u0000\u0000\ ... 256 times ... \u0000"
. You should return new String(buffer).trim();
.
*/ | ||
@Override | ||
public String getDomainName() { | ||
LibC.Addrinfo hint = new LibC.Addrinfo(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These LibC
calls here are specific to Unix, and this code will only work on FreeBSD and Solaris. Either this Unix-specific should be implemented in a Unix class that accept the unix lass you imported, or you should do an OS check and import the appropriate LibC to use (the Linux LibC is a different class, and SystemB is the equivalent for the OS X case).
LibC.Addrinfo hint = new LibC.Addrinfo(); | ||
hint.ai_flags = LibC.AI_CANONNAME; | ||
String hostname = null; | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just call this class's own getHostName()
here, where you've implemented this code?
*/ | ||
@Override | ||
public String getDomainName() { | ||
return ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This overrides the default methods we put in the abstract class. If you get the correct LibC
/SystemB
class to create an instance of in that class, you can just leave this blank and OS X will use the C functions.
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public String[] getDnsServers() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're overriding the default method of reading /etc/resolv.conf
. Remove this override.
boolean v6Table = false; | ||
for(String line: lines){ | ||
if(v6Table && line.startsWith(DEFAULT_GATEWAY)){ | ||
String[] fields = line.split("[ \t#;]"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need a +
after the regex here to split on the multiple whitespace. You could also just use "\\s+"
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also if you do decide to use the \t
you would need a second backslash to escape the escape.
Hi,
here is interface for OS networking parameters and implementation for Linux/Win (sorry I don't have machine for other OS :().
Now it contains host name/dns domain name/dns servers/default gateway of IPv4/6.
Domain suffix search list is also considered but I think I'll wait JNA release
VT_ARRAY
support for this.