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/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