#include "osm/bind.h" #include #include #include #include #include #define MAX_ID 0xFFFF /** * The required characters to represent an id as a file name * id - the id to get translated to a file name */ int _need_chars(int id) { int i = 1; while (id > 15) { id /= 16; i++; } return i; } /** * Write the integer file name after the folder path. * id - the id to get translated to a file name * start - a pointer to just after the end of the folder path string */ void _write_name(int id, char *start) { int i = _need_chars(id); while (i > 0) { // Get current character char c = '0'; if (id % 16 < 10) c += id % 16; else c = 'a' + (id % 16) - 10; // Put character *(start + i - 1) = c; // divide id, sub from i id /= 16; i -= 1; } } /** * Bind to the next available onboard socket in the given directory * sock_dir - The directory containing osm sockets (or null for the default) */ int osm_bind_local(int sockfd, const char *sock_dir) { struct sockaddr_un name; name.sun_family = AF_LOCAL; strncpy(name.sun_path, sock_dir, sizeof(name.sun_path)); name.sun_path[sizeof(name.sun_path) - 1] = 0; // Check for slash at end of path int len = strlen(name.sun_path); if (name.sun_path[len - 1] != '/') { name.sun_path[len] = '/'; len++; } // check that we won't overflow the buffer if (len > sizeof(name.sun_path) - 2) { return -1; } // sequentially try to bind uint id = 0; uint offset = offsetof(struct sockaddr_un, sun_path); while(_need_chars(id) + len < sizeof(name.sun_path) - 1) { if (id > MAX_ID) return -1; // write file name _write_name(id, name.sun_path + len); // try to bind errno = 0; int err = bind(sockfd, (struct sockaddr *) &name, offset + strlen(name.sun_path)); if (err == 0) { printf("Bound!\n"); return 0; } else if (errno != EADDRINUSE) { // If not bound and it's not due to an address in use error // then we have an actual problem return -1; } // inc id id++; } return -1; } /** * Bind a new onboard socket * sock_dir - The directory containing osm sockets (or null for the default) * return - a negitve number on error, or the socket fd on success */ int osm_open_onboard(char *sock_dir) { int sockfd = socket(AF_LOCAL, SOCK_SEQPACKET, 0); if (sockfd < 0) { perror("socket"); return sockfd; } int bound = -1; if (sock_dir == NULL) { bound = osm_bind_local(sockfd, "/run/osm/onboard/"); } else { bound = osm_bind_local(sockfd, sock_dir); } if (bound != 0) { perror("bind"); close(sockfd); return bound; } return sockfd; } /** * Bind a new network socket * Should only be called by one process on the machine. * * If more than one device needs to be exposed through this system, use a * master process to handle internet traffic and export each device as a * sub-device. * * return - a negative number on error, or the */ int osm_open_network() { int sockfd = socket(AF_INET6, SOCK_STREAM, 0); return sockfd; }