refactored the IP address handling code
It is now split up much more cleanly, has less stuff running on the
cRIO, and doesn't do as much of the stuff with string manipulation.
Before, it was kind of ridicilous how many times the code converted IP
addresses back and forth between 32-bit ints and strings to do various
manipulations and pass them around. Also, there was various junk that
the cRIO code did that it did not need to be doing.
diff --git a/aos/atom_code/atom_code.gyp b/aos/atom_code/atom_code.gyp
index 8253588..37caccd 100644
--- a/aos/atom_code/atom_code.gyp
+++ b/aos/atom_code/atom_code.gyp
@@ -12,5 +12,16 @@
'<(AOS)/build/aos.gyp:logging',
],
},
+ {
+ 'target_name': 'configuration',
+ 'type': 'static_library',
+ 'sources': [
+ 'configuration.cc',
+ ],
+ 'dependencies': [
+ '<(AOS)/common/common.gyp:once',
+ '<(AOS)/build/aos.gyp:logging',
+ ],
+ },
],
}
diff --git a/aos/atom_code/camera/HTTPStreamer.cpp b/aos/atom_code/camera/HTTPStreamer.cpp
index 8a896c5..5a9a405 100644
--- a/aos/atom_code/camera/HTTPStreamer.cpp
+++ b/aos/atom_code/camera/HTTPStreamer.cpp
@@ -15,7 +15,7 @@
#include <vector>
-#include "aos/common/Configuration.h"
+#include "aos/common/network_port.h"
#include "aos/atom_code/init.h"
#include "aos/atom_code/camera/Buffers.h"
#include "aos/common/logging/logging.h"
diff --git a/aos/atom_code/configuration.cc b/aos/atom_code/configuration.cc
new file mode 100644
index 0000000..a5dd4ee
--- /dev/null
+++ b/aos/atom_code/configuration.cc
@@ -0,0 +1,103 @@
+#include "aos/atom_code/configuration.h"
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <unistd.h>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/unique_malloc_ptr.h"
+#include "aos/common/once.h"
+
+namespace aos {
+namespace configuration {
+namespace {
+
+// Including the terminating '\0'.
+const size_t kMaxAddrLength = 18;
+
+const char *const kAtomNetInterface = "eth0";
+const in_addr *DoGetOwnIPAddress() {
+ ifaddrs *addrs;
+ if (getifaddrs(&addrs) != 0) {
+ LOG(FATAL, "getifaddrs(%p) failed with %d: %s\n", &addrs,
+ errno, strerror(errno));
+ }
+ // Smart pointers don't work very well for iterating through a linked list,
+ // but it does do a very nice job of making sure that addrs gets freed.
+ unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);
+
+ for (; addrs != NULL; addrs = addrs->ifa_next) {
+ if (addrs->ifa_addr->sa_family == AF_INET) {
+ if (strcmp(kAtomNetInterface, addrs->ifa_name) == 0) {
+ static const in_addr r =
+ reinterpret_cast<sockaddr_in *>(addrs->ifa_addr)->sin_addr;
+ return &r;
+ }
+ }
+ }
+ LOG(FATAL, "couldn't find an AF_INET interface named \"%s\"\n",
+ kAtomNetInterface);
+}
+
+const char *DoGetRootDirectory() {
+ ssize_t size = 0;
+ char *r = NULL;
+ while (true) {
+ if (r != NULL) delete r;
+ size += 256;
+ r = new char[size];
+
+ ssize_t ret = readlink("/proc/self/exe", r, size);
+ if (ret < 0) {
+ if (ret != -1) {
+ LOG(WARNING, "it returned %zd, not -1\n", ret);
+ }
+ LOG(FATAL, "readlink(\"/proc/self/exe\", %p, %zu) failed with %d: %s\n",
+ r, size, errno, strerror(errno));
+ }
+ if (ret < size) {
+ void *last_slash = memrchr(r, '/', size);
+ if (last_slash == NULL) {
+ r[ret] = '\0';
+ LOG(FATAL, "couldn't find a '/' in \"%s\"\n", r);
+ }
+ *static_cast<char *>(last_slash) = '\0';
+ LOG(INFO, "got a root dir of \"%s\"\n", r);
+ return r;
+ }
+ }
+}
+
+const char *DoGetLoggingDirectory() {
+ static const char kSuffix[] = "/../../tmp/robot_logs";
+ const char *root = GetRootDirectory();
+ char *r = new char[strlen(root) + sizeof(kSuffix)];
+ strcpy(r, root);
+ strcat(r, kSuffix);
+ return r;
+}
+
+} // namespace
+
+const char *GetRootDirectory() {
+ static aos::Once<const char> once(DoGetRootDirectory);
+ return once.Get();
+}
+
+const char *GetLoggingDirectory() {
+ static aos::Once<const char> once(DoGetLoggingDirectory);
+ return once.Get();
+}
+
+const in_addr &GetOwnIPAddress() {
+ static aos::Once<const in_addr> once(DoGetOwnIPAddress);
+ return *once.Get();
+}
+
+} // namespace configuration
+} // namespace aos
diff --git a/aos/atom_code/configuration.h b/aos/atom_code/configuration.h
new file mode 100644
index 0000000..a3917cc
--- /dev/null
+++ b/aos/atom_code/configuration.h
@@ -0,0 +1,31 @@
+#ifndef AOS_ATOM_CODE_CONFIGURATION_H_
+#define AOS_ATOM_CODE_CONFIGURATION_H_
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+namespace aos {
+
+// Holds global configuration data. All of the functions are safe to call
+// from wherever.
+namespace configuration {
+
+// Returns "our" IP address.
+const in_addr &GetOwnIPAddress();
+
+// Returns the "root directory" for this run. Under linux, this is the
+// directory where the executable is located (from /proc/self/exe)
+// The return value will always be to a static string, so no freeing is
+// necessary.
+const char *GetRootDirectory();
+// Returns the directory where logs get written. Relative to GetRootDirectory().
+// The return value will always be to a static string, so no freeing is
+// necessary.
+const char *GetLoggingDirectory();
+
+} // namespace configuration
+} // namespace aos
+
+#endif // AOS_ATOM_CODE_CONFIGURATION_H_
diff --git a/aos/atom_code/core/BinaryLogReader.cpp b/aos/atom_code/core/BinaryLogReader.cpp
index e266f24..9451fd1 100644
--- a/aos/atom_code/core/BinaryLogReader.cpp
+++ b/aos/atom_code/core/BinaryLogReader.cpp
@@ -13,8 +13,8 @@
#include "aos/atom_code/logging/atom_logging.h"
#include "aos/atom_code/core/LogFileCommon.h"
-#include "aos/common/Configuration.h"
#include "aos/atom_code/init.h"
+#include "aos/atom_code/configuration.h"
namespace aos {
namespace logging {
diff --git a/aos/atom_code/core/CRIOLogReader.cpp b/aos/atom_code/core/CRIOLogReader.cpp
index 73a5350..9c4dbd4 100644
--- a/aos/atom_code/core/CRIOLogReader.cpp
+++ b/aos/atom_code/core/CRIOLogReader.cpp
@@ -14,9 +14,9 @@
#include "aos/common/logging/logging_impl.h"
#include "aos/atom_code/logging/atom_logging.h"
-#include "aos/common/Configuration.h"
#include "aos/common/byteorder.h"
#include "aos/atom_code/init.h"
+#include "aos/common/network_port.h"
namespace aos {
namespace logging {
diff --git a/aos/atom_code/core/core.gyp b/aos/atom_code/core/core.gyp
index 3b327da..74b3232 100644
--- a/aos/atom_code/core/core.gyp
+++ b/aos/atom_code/core/core.gyp
@@ -19,7 +19,7 @@
'dependencies': [
'<(AOS)/build/aos.gyp:logging',
'<(AOS)/atom_code/atom_code.gyp:init',
- '<(AOS)/common/common.gyp:common',
+ '<(AOS)/atom_code/atom_code.gyp:configuration',
],
},
{
diff --git a/aos/atom_code/input/input.gyp b/aos/atom_code/input/input.gyp
index 19d0d2f..8aba065 100644
--- a/aos/atom_code/input/input.gyp
+++ b/aos/atom_code/input/input.gyp
@@ -10,7 +10,6 @@
'<(AOS)/common/input/input.gyp:driver_station_data',
'<(AOS)/common/messages/messages.gyp:aos_queues',
'<(AOS)/common/network/network.gyp:socket',
- '<(AOS)/common/common.gyp:common',
'<(EXTERNALS):WPILib-NetworkRobotValues',
'<(AOS)/build/aos.gyp:logging',
],
diff --git a/aos/atom_code/input/joystick_input.cc b/aos/atom_code/input/joystick_input.cc
index c2b4d9c..28618ed 100644
--- a/aos/atom_code/input/joystick_input.cc
+++ b/aos/atom_code/input/joystick_input.cc
@@ -4,7 +4,7 @@
#include "aos/externals/WPILib/WPILib/NetworkRobot/NetworkRobotValues.h"
-#include "aos/common/Configuration.h"
+#include "aos/common/network_port.h"
#include "aos/common/network/ReceiveSocket.h"
#include "aos/common/messages/RobotState.q.h"
#include "aos/common/logging/logging.h"
diff --git a/aos/atom_code/output/ctemplate_cache.cc b/aos/atom_code/output/ctemplate_cache.cc
index a73e4ad..02c7b2f 100644
--- a/aos/atom_code/output/ctemplate_cache.cc
+++ b/aos/atom_code/output/ctemplate_cache.cc
@@ -1,6 +1,6 @@
#include "aos/atom_code/output/ctemplate_cache.h"
-#include "aos/common/Configuration.h"
+#include "aos/atom_code/configuration.h"
#include "aos/common/once.h"
namespace aos {
diff --git a/aos/atom_code/output/motor_output.cc b/aos/atom_code/output/motor_output.cc
index d324da1..b68dcad 100644
--- a/aos/atom_code/output/motor_output.cc
+++ b/aos/atom_code/output/motor_output.cc
@@ -2,9 +2,9 @@
#include <math.h>
-#include "aos/common/Configuration.h"
#include "aos/common/control_loop/Timing.h"
#include "aos/common/logging/logging.h"
+#include "aos/common/network_port.h"
namespace aos {
@@ -26,8 +26,9 @@
}
}
-MotorOutput::MotorOutput() : socket_(NetworkPort::kMotors,
- configuration::GetIPAddress(configuration::NetworkDevice::kCRIO)) {}
+MotorOutput::MotorOutput()
+ : socket_(NetworkPort::kMotors, ::aos::NetworkAddress::kCRIO) {
+}
void MotorOutput::Run() {
while (true) {
diff --git a/aos/atom_code/output/output.gyp b/aos/atom_code/output/output.gyp
index 6fb5956..8f0e47d 100644
--- a/aos/atom_code/output/output.gyp
+++ b/aos/atom_code/output/output.gyp
@@ -12,7 +12,6 @@
'<(EXTERNALS):libevent',
'<(EXTERNALS):ctemplate',
'<(AOS)/common/common.gyp:once',
- '<(AOS)/common/common.gyp:common',
'<(AOS)/common/common.gyp:scoped_fd',
'<(AOS)/build/aos.gyp:logging',
],
@@ -29,7 +28,6 @@
],
'dependencies': [
'<(AOS)/common/network/network.gyp:socket',
- '<(AOS)/common/common.gyp:common',
'<(AOS)/common/common.gyp:timing',
'<(EXTERNALS):WPILib-NetworkRobotValues',
'<(AOS)/build/aos.gyp:logging',
diff --git a/aos/atom_code/starter/netconsole.cc b/aos/atom_code/starter/netconsole.cc
index e2ba2b4..258afd8 100644
--- a/aos/atom_code/starter/netconsole.cc
+++ b/aos/atom_code/starter/netconsole.cc
@@ -10,7 +10,8 @@
#include <assert.h>
#include "aos/common/logging/logging_impl.h"
-#include "aos/common/Configuration.h"
+#include "aos/common/util.h"
+#include "aos/atom_code/configuration.h"
namespace aos {
namespace {
@@ -158,6 +159,11 @@
pthread_t input_thread, output_thread;
+ address.in.sin_addr = ::aos::configuration::GetOwnIPAddress();
+ ::aos::util::SetLastSegment(&address.in.sin_addr, NetworkAddress::kCRIO);
+ fprintf(stderr, "Using cRIO IP %s.\n",
+ inet_ntoa(address.in.sin_addr));
+
if (input != -1) {
int to_crio = socket(AF_INET, SOCK_DGRAM, 0);
if (to_crio == -1) {
@@ -169,13 +175,6 @@
on, to_crio, errno, strerror(errno));
}
address.in.sin_port = htons(6668);
- if (inet_aton(
- configuration::GetIPAddress(configuration::NetworkDevice::kCRIO),
- &address.in.sin_addr) == 0) {
- LOG(FATAL, "inet_aton(%s, %p) failed with %d: %s\n",
- configuration::GetIPAddress(configuration::NetworkDevice::kCRIO),
- &address.in.sin_addr, errno, strerror(errno));
- }
if (connect(to_crio, &address.addr, sizeof(address)) == -1) {
LOG(FATAL, "connect(%d, %p, %zu) failed with %d: %s\n",
to_crio, &address.addr, sizeof(address), errno, strerror(errno));
@@ -187,16 +186,7 @@
}
}
- fprintf(stderr, "Using cRIO IP %s.\n",
- configuration::GetIPAddress(configuration::NetworkDevice::kCRIO));
-
- if (inet_aton(
- configuration::GetIPAddress(configuration::NetworkDevice::kSelf),
- &address.in.sin_addr) == 0) {
- LOG(FATAL, "inet_aton(%s, %p) failed with %d: %s\n",
- configuration::GetIPAddress(configuration::NetworkDevice::kSelf),
- &address.in.sin_addr, errno, strerror(errno));
- }
+ address.in.sin_addr = ::aos::configuration::GetOwnIPAddress();
FDsToCopy output_fds{from_crio, output, &address.in};
if (pthread_create(&output_thread, NULL, FDCopyThread, &output_fds) == -1) {
LOG(FATAL, "pthread_create(%p, NULL, %p, %p) failed with %d: %s\n",
diff --git a/aos/atom_code/starter/starter.gyp b/aos/atom_code/starter/starter.gyp
index 183ec9e..f494993 100644
--- a/aos/atom_code/starter/starter.gyp
+++ b/aos/atom_code/starter/starter.gyp
@@ -8,7 +8,8 @@
],
'dependencies': [
'<(AOS)/build/aos.gyp:logging',
- '<(AOS)/common/common.gyp:common',
+ '<(AOS)/atom_code/atom_code.gyp:configuration',
+ '<(AOS)/common/common.gyp:util',
],
},
{