From 5fecc57e8a4d4a70bf3bf525e6f60e405d7e83f5 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 18 Nov 2016 11:44:25 -0800 Subject: [PATCH] Add methods to get the hostname and network interfaces. --- examples/usbstream/usbstream.cpp | 6 +++ include/cscore_c.h | 5 +++ include/cscore_cpp.h | 4 ++ java/lib/CameraServerJNI.cpp | 22 ++++++++++ java/src/edu/wpi/cscore/CameraServerJNI.java | 4 ++ src/cscore_c.cpp | 20 ++++++++++ src/cscore_cpp.cpp | 42 ++++++++++++++++++++ 7 files changed, 103 insertions(+) diff --git a/examples/usbstream/usbstream.cpp b/examples/usbstream/usbstream.cpp index 5191b5b4db..29f9e06fd6 100644 --- a/examples/usbstream/usbstream.cpp +++ b/examples/usbstream/usbstream.cpp @@ -2,7 +2,13 @@ #include +#include "llvm/raw_ostream.h" + int main() { + llvm::outs() << "hostname: " << cs::GetHostname() << '\n'; + llvm::outs() << "IPv4 network addresses:\n"; + for (const auto& addr : cs::GetNetworkInterfaces()) + llvm::outs() << " " << addr << '\n'; cs::USBCamera camera{"usbcam", 1}; camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30); cs::MJPEGServer mjpegServer{"httpserver", 8081}; diff --git a/include/cscore_c.h b/include/cscore_c.h index 5d8eb6de23..ab87d605b4 100644 --- a/include/cscore_c.h +++ b/include/cscore_c.h @@ -297,6 +297,11 @@ void CS_FreeEnumPropertyChoices(char** choices, int count); void CS_FreeEnumeratedProperties(CS_Property* properties, int count); void CS_FreeEnumeratedVideoModes(CS_VideoMode* modes, int count); +char* CS_GetHostname(); + +char** CS_GetNetworkInterfaces(int* count); +void CS_FreeNetworkInterfaces(char** interfaces, int count); + #ifdef __cplusplus } #endif diff --git a/include/cscore_cpp.h b/include/cscore_cpp.h index 7d552bc85d..fad70a6f9f 100644 --- a/include/cscore_cpp.h +++ b/include/cscore_cpp.h @@ -275,6 +275,10 @@ llvm::ArrayRef EnumerateSourceHandles( llvm::ArrayRef EnumerateSinkHandles( llvm::SmallVectorImpl& vec, CS_Status* status); +std::string GetHostname(); + +std::vector GetNetworkInterfaces(); + } // namespace cs #endif // CSCORE_CPP_H_ diff --git a/java/lib/CameraServerJNI.cpp b/java/lib/CameraServerJNI.cpp index 102cf31750..f54a48ea1d 100644 --- a/java/lib/CameraServerJNI.cpp +++ b/java/lib/CameraServerJNI.cpp @@ -1089,4 +1089,26 @@ JNIEXPORT jintArray JNICALL Java_edu_wpi_cscore_CameraServerJNI_enumerateSinks return MakeJIntArray(env, arr); } +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: getHostname + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_edu_wpi_cscore_CameraServerJNI_getHostname + (JNIEnv *env, jclass) +{ + return MakeJString(env, cs::GetHostname()); +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: getNetworkInterfaces + * Signature: ()[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_edu_wpi_cscore_CameraServerJNI_getNetworkInterfaces + (JNIEnv *env, jclass) +{ + return MakeJStringArray(env, cs::GetNetworkInterfaces()); +} + } // extern "C" diff --git a/java/src/edu/wpi/cscore/CameraServerJNI.java b/java/src/edu/wpi/cscore/CameraServerJNI.java index 4625e02b52..64f5c369d7 100644 --- a/java/src/edu/wpi/cscore/CameraServerJNI.java +++ b/java/src/edu/wpi/cscore/CameraServerJNI.java @@ -181,4 +181,8 @@ public class CameraServerJNI { public static native int[] enumerateSources(); public static native int[] enumerateSinks(); + + public static native String getHostname(); + + public static native String[] getNetworkInterfaces(); } diff --git a/src/cscore_c.cpp b/src/cscore_c.cpp index 981d951e0d..20803f4094 100644 --- a/src/cscore_c.cpp +++ b/src/cscore_c.cpp @@ -321,4 +321,24 @@ void CS_FreeEnumeratedVideoModes(CS_VideoMode* modes, int count) { std::free(modes); } +char* CS_GetHostname() { + return cs::ConvertToC(cs::GetHostname()); +} + +char** CS_GetNetworkInterfaces(int* count) { + auto interfaces = cs::GetNetworkInterfaces(); + char** out = + static_cast(std::malloc(interfaces.size() * sizeof(char*))); + *count = interfaces.size(); + for (std::size_t i = 0; i < interfaces.size(); ++i) + out[i] = cs::ConvertToC(interfaces[i]); + return out; +} + +void CS_FreeNetworkInterfaces(char** interfaces, int count) { + if (!interfaces) return; + for (int i = 0; i < count; ++i) std::free(interfaces[i]); + std::free(interfaces); +} + } // extern "C" diff --git a/src/cscore_cpp.cpp b/src/cscore_cpp.cpp index 4abbbdbf8f..30a8b273d7 100644 --- a/src/cscore_cpp.cpp +++ b/src/cscore_cpp.cpp @@ -7,6 +7,13 @@ #include "cscore_cpp.h" +#if defined(__linux__) +#include +#include +#include +#include +#endif + #include "llvm/SmallString.h" #include "Notifier.h" @@ -511,4 +518,39 @@ llvm::ArrayRef EnumerateSinkHandles( return Sinks::GetInstance().GetAll(vec); } +std::string GetHostname() { +#ifdef __linux__ + char name[256]; + if (::gethostname(name, sizeof(name)) != 0) return ""; + name[255] = '\0'; // Per POSIX, may not be null terminated if too long + return name; +#else + return ""; // TODO +#endif +} + +std::vector GetNetworkInterfaces() { +#ifdef __linux__ + struct ifaddrs* ifa; + if (::getifaddrs(&ifa) != 0) return std::vector{}; + + std::vector rv; + char buf[256]; + for (struct ifaddrs* i = ifa; i; i = i->ifa_next) { + if (!i->ifa_addr) continue; // no address + if (i->ifa_addr->sa_family != AF_INET) continue; // only return IPv4 + struct sockaddr_in* addr_in = reinterpret_cast(i->ifa_addr); + const char* addr = + ::inet_ntop(addr_in->sin_family, &addr_in->sin_addr, buf, sizeof(buf)); + if (!addr) continue; // error converting address + rv.emplace_back(addr); + } + + ::freeifaddrs(ifa); + return rv; +#else + return std::vector{}; // TODO +#endif +} + } // namespace cs