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/common/Configuration.cpp b/aos/common/Configuration.cpp
deleted file mode 100644
index edf5212..0000000
--- a/aos/common/Configuration.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-#include "Configuration.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#ifdef __VXWORKS__
-#include <ifLib.h>
-#include <inetLib.h>
-#else
-#include <ifaddrs.h>
-#endif
-#include <unistd.h>
-
-#ifndef __VXWORKS__
-#include "aos/common/logging/logging.h"
-#include "aos/common/unique_malloc_ptr.h"
-#else
-#include <taskLib.h>
-#undef ERROR
-enum LogLevel {
- DEBUG,
- INFO,
- WARNING,
- ERROR = -1,
- FATAL = 4,
-};
-#define LOG(level, format, args...) do { \
- fprintf(stderr, #level ": " format, ##args); \
- if (level == FATAL) { \
- printf("I am 0x%x suspending for debugging purposes.\n", taskIdSelf()); \
- printf("\t`tt 0x%x` will give you a stack trace.\n", taskIdSelf()); \
- fputs("\t`lkAddr` will reverse lookup a symbol for you.\n", stdout); \
- fputs("\t`dbgHelp` and `help` have some useful commands in them.\n", stdout); \
- taskSuspend(0); \
- printf("You weren't supposed to resume 0x%x!!. Going to really die now.\n", \
- taskIdSelf()); \
- abort(); \
- } \
-} while (0)
-#endif
-#include "aos/common/once.h"
-
-namespace aos {
-namespace configuration {
-
-namespace {
-
-#ifdef __VXWORKS__
-const size_t kMaxAddrLength = INET_ADDR_LEN;
-#else
-// Including the terminating '\0'.
-const size_t kMaxAddrLength = 18;
-#endif
-// Returns whether or not the current IP address is in ownIPAddress.
-bool GetOwnIPAddress();
-
-#ifdef __VXWORKS__
-// vxworks doesn't have real asprintf.......
-static inline int aos_asprintf(size_t max_len, char **strp, const char *fmt, ...) {
- *strp = static_cast<char *>(malloc(max_len));
- if (*strp == NULL) {
- return -1;
- }
- va_list argp;
- va_start(argp, fmt);
- const int r = vsnprintf(*strp, max_len, fmt, argp);
- va_end(argp);
- if (static_cast<uintmax_t>(r) >= max_len) {
- errno = EOVERFLOW;
- free(*strp);
- return -1;
- }
- return r;
-}
-
-// 4-slot cRIO: motfec0
-// 8-slot cRIO port 1: fec0
-// ifShow will show you all of the ones on a cRIO
-const char *const kCrioNetInterfaces[] = {"fec0", "motfec0"};
-bool GetOwnIPAddress(char *buffer, size_t bufferSize) {
- if (bufferSize < INET_ADDR_LEN) {
- LOG(ERROR, "bufferSize(%jd) isn't >= INET_ADDR_LEN(%jd)\n",
- static_cast<intmax_t>(bufferSize),
- static_cast<intmax_t>(INET_ADDR_LEN));
- return false;
- }
- for (size_t i = 0;
- i < sizeof(kCrioNetInterfaces) / sizeof(kCrioNetInterfaces[0]); ++i) {
- if (ifAddrGet(const_cast<char *>(kCrioNetInterfaces[i]), buffer) != OK) {
- LOG(DEBUG, "ifAddrGet(\"%s\", %p) failed with %d: %s\n",
- kCrioNetInterfaces[i], buffer, errno, strerror(errno));
- } else {
- return true;
- }
- }
- LOG(ERROR, "couldn't get the cRIO's IP address\n");
- return false;
-}
-#else
-static inline int aos_asprintf(size_t, char **strp, const char *fmt, ...) {
- va_list argp;
- va_start(argp, fmt);
- const int r = vasprintf(strp, fmt, argp);
- va_end(argp);
- return r;
-}
-
-const char *const kAtomNetInterface = "eth0";
-bool GetOwnIPAddress(char *buffer, size_t bufferSize) {
- ifaddrs *addrs;
- if (getifaddrs(&addrs) != 0) {
- LOG(ERROR, "getifaddrs(%p) failed with %d: %s\n", &addrs,
- errno, strerror(errno));
- return false;
- }
- // 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) {
- const char *ipAddress = inet_ntoa(
- reinterpret_cast<sockaddr_in *>(addrs->ifa_addr)->sin_addr);
- strncpy(buffer, ipAddress, bufferSize);
- return true;
- }
- }
- }
- LOG(ERROR, "couldn't find an AF_INET interface named \"%s\"\n",
- kAtomNetInterface);
- return false;
-}
-#endif
-
-const char *RawIPAddress(uint8_t last_part) {
- char ownIPAddress[kMaxAddrLength];
- if (!GetOwnIPAddress(ownIPAddress, sizeof(ownIPAddress))) {
- return NULL;
- }
- char *last_dot = strrchr(ownIPAddress, '.');
- if (last_dot == NULL) {
- LOG(ERROR, "can't find any '.'s in \"%s\"\n", ownIPAddress);
- return NULL;
- }
- *last_dot = '\0';
-
- char *r;
- if (aos_asprintf(kMaxAddrLength, &r, "%s.%hhu",
- ownIPAddress, last_part) == -1) {
- return NULL;
- }
- return r;
-}
-
-} // namespace
-
-const char *GetIPAddress(NetworkDevice device) {
- switch (device) {
- case NetworkDevice::kAtom:
- return RawIPAddress(179);
- case NetworkDevice::kCRIO:
- return RawIPAddress(2);
- case NetworkDevice::kSelf:
- char *ret = static_cast<char *>(malloc(kMaxAddrLength));
- if (!GetOwnIPAddress(ret, kMaxAddrLength)) return NULL;
- return ret;
- }
- LOG(FATAL, "Unknown network device.");
- return NULL;
-}
-
-namespace {
-const char *DoGetRootDirectory() {
-#ifdef __VXWORKS__
- return "/";
-#else
- 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;
- }
- }
-#endif
-}
-
-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();
-}
-
-} // namespace configuration
-} // namespace aos
diff --git a/aos/common/Configuration.h b/aos/common/Configuration.h
deleted file mode 100644
index e1b7ef5..0000000
--- a/aos/common/Configuration.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef AOS_COMMON_CONFIGURATION_H_
-#define AOS_COMMON_CONFIGURATION_H_
-
-#include "aos/aos_stdint.h"
-
-namespace aos {
-
-// Constants representing the various ports used for communications and some
-// documentation about what each is used for.
-enum class NetworkPort : uint16_t {
- // UDP socket sending motor values from the atom to the crio.
- kMotors = 9710,
- // UDP socket forwarding drivers station packets from the crio to the atom.
- kDS = 9711,
- // UDP socket sending sensor values from the crio to the atom.
- kSensors = 9712,
- // TCP socket(s) (automatically reconnects) sending logs from the crio to the
- // atom.
- kLogs = 9713,
- // HTTP server that sends out camera feeds in mjpg format.
- // Should not be changed because this number shows up elsewhere too.
- kCameraStreamer = 9714,
-};
-
-// Holds global configuration data. All of the functions are safe to call
-// from wherever (the ones that need to create locks on the cRIO).
-namespace configuration {
-
-// Constants indentifying various devices on the network.
-enum class NetworkDevice {
- // The computer that the cRIO talks to.
- kAtom,
- kCRIO,
- // Whatever device this is being run on.
- kSelf,
-};
-// Returns the IP address to get to the specified machine.
-// The return value should be passed to free(3) if it is no longer needed.
-const char *GetIPAddress(NetworkDevice device);
-
-// Returns the "root directory" for this run. Under linux, this is the
-// directory where the executable is located (from /proc/self/exe) and under
-// vxworks it is just "/".
-// 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
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index 09dc4a5..442e4ac 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -41,30 +41,6 @@
],
},
{
- 'target_name': 'common',
- 'type': 'static_library',
- 'sources': [
- 'Configuration.cpp',
- ],
- 'dependencies': [
- 'once',
- ],
- 'export_dependent_settings': [
- 'once',
- ],
- 'conditions': [
- ['OS=="crio"', {
- 'dependencies': [
- '<(EXTERNALS):WPILib',
- ],
- }, {
- 'dependencies': [
- '<(AOS)/build/aos.gyp:logging',
- ],
- }],
- ],
- },
- {
'target_name': 'queues',
'type': 'static_library',
'sources': [
@@ -86,11 +62,9 @@
}]
],
'dependencies': [
- '<(AOS)/common/common.gyp:common',
'time',
],
'export_dependent_settings': [
- '<(AOS)/common/common.gyp:common',
'time',
],
},
@@ -290,5 +264,12 @@
'die',
],
},
+ {
+ 'target_name': 'util',
+ 'type': 'static_library',
+ 'sources': [
+ 'util.cc',
+ ],
+ },
],
}
diff --git a/aos/common/network/SendSocket.h b/aos/common/network/SendSocket.h
index fca904a..9323da8 100644
--- a/aos/common/network/SendSocket.h
+++ b/aos/common/network/SendSocket.h
@@ -3,6 +3,10 @@
#include "Socket.h"
+#include "aos/atom_code/configuration.h"
+#include "aos/common/network_port.h"
+#include "aos/common/util.h"
+
namespace aos {
class SendSocket : public Socket {
@@ -10,8 +14,10 @@
// Connect must be called before use.
SendSocket() {}
// Calls Connect automatically.
- SendSocket(NetworkPort port, const char *robot_ip) {
- Connect(port, robot_ip);
+ SendSocket(NetworkPort port, ::aos::NetworkAddress address) {
+ Connect(port,
+ ::aos::util::MakeIPAddress(::aos::configuration::GetOwnIPAddress(),
+ address));
}
int Connect(NetworkPort port, const char *robot_ip, int type = SOCK_DGRAM);
};
diff --git a/aos/common/network/Socket.h b/aos/common/network/Socket.h
index 68fd32c..7a20d3e 100644
--- a/aos/common/network/Socket.h
+++ b/aos/common/network/Socket.h
@@ -9,8 +9,8 @@
#include <unistd.h>
#include <stdio.h>
-#include "aos/common/Configuration.h"
#include "aos/common/time.h"
+#include "aos/common/network_port.h"
namespace aos {
diff --git a/aos/common/network/network.gyp b/aos/common/network/network.gyp
index 4fc3a09..279bb53 100644
--- a/aos/common/network/network.gyp
+++ b/aos/common/network/network.gyp
@@ -37,16 +37,11 @@
'SendSocket.cpp',
'Socket.cpp',
],
- 'conditions': [
- ['OS=="crio"', {
- 'dependencies': [
- '<(EXTERNALS):WPILib',
- ]}
- ],
- ],
'dependencies': [
'<(AOS)/build/aos.gyp:logging',
'<(AOS)/common/common.gyp:time',
+ '<(AOS)/common/common.gyp:util',
+ '<(AOS)/atom_code/atom_code.gyp:configuration',
],
'export_dependent_settings': [
'<(AOS)/build/aos.gyp:logging',
diff --git a/aos/common/network_port.h b/aos/common/network_port.h
new file mode 100644
index 0000000..a8f2d1d
--- /dev/null
+++ b/aos/common/network_port.h
@@ -0,0 +1,35 @@
+#ifndef AOS_COMMON_NETWORK_PORT_H_
+#define AOS_COMMON_NETWORK_PORT_H_
+
+#include "aos/aos_stdint.h"
+
+namespace aos {
+
+// Constants representing the various ports used for communications and some
+// documentation about what each is used for.
+enum class NetworkPort : uint16_t {
+ // UDP socket sending motor values from the atom to the crio.
+ kMotors = 9710,
+ // UDP socket forwarding drivers station packets from the crio to the atom.
+ kDS = 9711,
+ // UDP socket sending sensor values from the crio to the atom.
+ kSensors = 9712,
+ // TCP socket(s) (automatically reconnects) sending logs from the crio to the
+ // atom.
+ kLogs = 9713,
+ // HTTP server that sends out camera feeds in mjpg format.
+ // Should not be changed because this number shows up elsewhere too.
+ kCameraStreamer = 9714,
+};
+
+// Constants representing the various devices that talk on the network and the
+// last segment of their IP addresses.
+enum class NetworkAddress : uint8_t {
+ // The computer that the cRIO talks to.
+ kAtom = 179,
+ kCRIO = 2,
+};
+
+} // namespace aos
+
+#endif // AOS_COMMON_NETWORK_PORT_H_
diff --git a/aos/common/sensors/sensor_receiver-tmpl.h b/aos/common/sensors/sensor_receiver-tmpl.h
index 8ebef22..8fb6cb4 100644
--- a/aos/common/sensors/sensor_receiver-tmpl.h
+++ b/aos/common/sensors/sensor_receiver-tmpl.h
@@ -1,5 +1,5 @@
-#include "aos/common/Configuration.h"
#include "aos/common/inttypes.h"
+#include "aos/common/network_port.h"
namespace aos {
namespace sensors {
diff --git a/aos/common/sensors/sensors.gyp b/aos/common/sensors/sensors.gyp
index b73e02b..b8a2092 100644
--- a/aos/common/sensors/sensors.gyp
+++ b/aos/common/sensors/sensors.gyp
@@ -47,14 +47,12 @@
],
'dependencies': [
'<(AOS)/common/network/network.gyp:socket',
- '<(AOS)/common/common.gyp:common',
'sensors',
'<(AOS)/common/common.gyp:time',
'<(AOS)/common/common.gyp:gtest_prod',
],
'export_dependent_settings': [
'<(AOS)/common/network/network.gyp:socket',
- '<(AOS)/common/common.gyp:common',
'sensors',
'<(AOS)/common/common.gyp:time',
'<(AOS)/common/common.gyp:gtest_prod',
diff --git a/aos/common/util.cc b/aos/common/util.cc
new file mode 100644
index 0000000..1b7ca93
--- /dev/null
+++ b/aos/common/util.cc
@@ -0,0 +1,31 @@
+#include "aos/common/util.h"
+
+#include <stdlib.h>
+#ifndef __VXWORKS__
+#include <string.h>
+#endif
+
+namespace aos {
+namespace util {
+
+const char *MakeIPAddress(const in_addr &base_address,
+ ::aos::NetworkAddress last_segment) {
+ in_addr address = base_address;
+ SetLastSegment(&address, last_segment);
+
+#ifdef __VXWORKS__
+ char *r = static_cast<char *>(malloc(INET_ADDR_LEN));
+ inet_ntoa_b(address, r);
+ return r;
+#else
+ return strdup(inet_ntoa(address));
+#endif
+}
+
+void SetLastSegment(in_addr *address, ::aos::NetworkAddress last_segment) {
+ address->s_addr &= ~0xFF;
+ address->s_addr |= static_cast<uint8_t>(last_segment);
+}
+
+} // namespace util
+} // namespace aos
diff --git a/aos/common/util.h b/aos/common/util.h
new file mode 100644
index 0000000..f41b86e
--- /dev/null
+++ b/aos/common/util.h
@@ -0,0 +1,29 @@
+#ifndef AOS_COMMON_UTIL_H_
+#define AOS_COMMON_UTIL_H_
+
+#ifdef __VXWORKS__
+#include <inetLib.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "aos/common/network_port.h"
+
+namespace aos {
+namespace util {
+
+// Makes an IP address string from base_address with the last byte set to
+// last_segment.
+// Returns a malloc(3)ed string.
+const char *MakeIPAddress(const in_addr &base_address,
+ ::aos::NetworkAddress last_segment);
+
+// Sets the last byte of *address to last_segment.
+void SetLastSegment(in_addr *address, ::aos::NetworkAddress last_segment);
+
+} // namespace util
+} // namespace aos
+
+#endif // AOS_COMMON_UTIL_H_