dist: ethos: add tcp socket support
Add ethos support to use a tcp socket instead of a TTY. Use 'tcp:host' as serial argument. Port can be given in place of the baudrate argument. Default port is 20000 which is used in on IoT-LAB.
This commit is contained in:
parent
6dfec48629
commit
a52c781339
159
dist/tools/ethos/ethos.c
vendored
159
dist/tools/ethos/ethos.c
vendored
@ -22,11 +22,14 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
#define MTU 9000
|
#define MTU 9000
|
||||||
|
|
||||||
#define TRACE(x)
|
#define TRACE(x)
|
||||||
|
#define TTY_TIMEOUT_MS (500)
|
||||||
|
|
||||||
#define case_baudrate(val) \
|
#define case_baudrate(val) \
|
||||||
case val: \
|
case val: \
|
||||||
@ -35,9 +38,13 @@
|
|||||||
|
|
||||||
#define BAUDRATE_DEFAULT B115200
|
#define BAUDRATE_DEFAULT B115200
|
||||||
|
|
||||||
|
#define TCP_DEV "tcp:"
|
||||||
|
#define IOTLAB_TCP_PORT "20000"
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: ethos <tap> <serial> [baudrate]\n");
|
fprintf(stderr, "Usage: ethos <tap> <serial> [baudrate]\n");
|
||||||
|
fprintf(stderr, " ethos <tap> tcp:<host> [port]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checked_write(int handle, void *buffer, int nbyte)
|
static void checked_write(int handle, void *buffer, int nbyte)
|
||||||
@ -69,7 +76,8 @@ int set_serial_attribs (int fd, int speed, int parity)
|
|||||||
/* no canonical processing*/
|
/* no canonical processing*/
|
||||||
tty.c_oflag = 0; /* no remapping, no delays*/
|
tty.c_oflag = 0; /* no remapping, no delays*/
|
||||||
tty.c_cc[VMIN] = 0; /* read doesn't block*/
|
tty.c_cc[VMIN] = 0; /* read doesn't block*/
|
||||||
tty.c_cc[VTIME] = 5; /* 0.5 seconds read timeout*/
|
tty.c_cc[VTIME] = TTY_TIMEOUT_MS / 100; /* 0.5 seconds read timeout*/
|
||||||
|
/* in tenths of a second*/
|
||||||
|
|
||||||
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* shut off xon/xoff ctrl*/
|
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* shut off xon/xoff ctrl*/
|
||||||
|
|
||||||
@ -100,7 +108,8 @@ void set_blocking (int fd, int should_block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tty.c_cc[VMIN] = should_block ? 1 : 0;
|
tty.c_cc[VMIN] = should_block ? 1 : 0;
|
||||||
tty.c_cc[VTIME] = 5; /* 0.5 seconds read timeout*/
|
tty.c_cc[VTIME] = TTY_TIMEOUT_MS / 100; /* 0.5 seconds read timeout*/
|
||||||
|
/* in tenths of a second*/
|
||||||
|
|
||||||
if (tcsetattr (fd, TCSANOW, &tty) != 0)
|
if (tcsetattr (fd, TCSANOW, &tty) != 0)
|
||||||
perror("error setting term attributes");
|
perror("error setting term attributes");
|
||||||
@ -276,6 +285,11 @@ static void _clear_neighbor_cache(const char *ifname)
|
|||||||
|
|
||||||
static int _parse_baudrate(const char *arg, unsigned *baudrate)
|
static int _parse_baudrate(const char *arg, unsigned *baudrate)
|
||||||
{
|
{
|
||||||
|
if (arg == NULL) {
|
||||||
|
*baudrate = BAUDRATE_DEFAULT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch(strtol(arg, (char**)NULL, 10)) {
|
switch(strtol(arg, (char**)NULL, 10)) {
|
||||||
case 9600:
|
case 9600:
|
||||||
*baudrate = B9600;
|
*baudrate = B9600;
|
||||||
@ -339,10 +353,137 @@ static int _parse_baudrate(const char *arg, unsigned *baudrate)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _parse_tcp_arg(char *name, char *port_arg, char **host, char **port)
|
||||||
|
{
|
||||||
|
/* Remove 'tcp:' */
|
||||||
|
name = &name[sizeof(TCP_DEV) - 1];
|
||||||
|
|
||||||
|
/* Set default if NULL */
|
||||||
|
if (!port_arg) {
|
||||||
|
port_arg = IOTLAB_TCP_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*host = name;
|
||||||
|
*port = port_arg;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adapted from 'getaddrinfo' manpage example */
|
||||||
|
int _tcp_connect(char *host, char *port)
|
||||||
|
{
|
||||||
|
int sfd = -1;
|
||||||
|
struct addrinfo hints, *result, *rp;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
int s = getaddrinfo(host, port, &hints, &result);
|
||||||
|
if (s) {
|
||||||
|
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* getaddrinfo() returns a list of address structures.
|
||||||
|
Try each address until we successfully connect(2).
|
||||||
|
If socket(2) (or connect(2)) fails, we (close the socket
|
||||||
|
and) try the next address. */
|
||||||
|
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||||
|
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
|
if (sfd == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
close(sfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
|
|
||||||
|
if (rp == NULL) {
|
||||||
|
fprintf(stderr, "Could not connect to '%s:%s'\n", host, port);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _set_socket_timeout(int sfd)
|
||||||
|
{
|
||||||
|
struct timeval timeout = {
|
||||||
|
.tv_sec = 0,
|
||||||
|
.tv_usec = TTY_TIMEOUT_MS * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO,
|
||||||
|
(char *)&timeout, sizeof(timeout)) == -1) {
|
||||||
|
perror("setsockopt failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO,
|
||||||
|
(char *)&timeout, sizeof(timeout)) == -1) {
|
||||||
|
perror("setsockopt failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _open_tcp_connection(char *name, char *port_arg)
|
||||||
|
{
|
||||||
|
char *host;
|
||||||
|
char *port;
|
||||||
|
|
||||||
|
int ret = _parse_tcp_arg(name, port_arg, &host, &port);
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "Error while parsing tcp arguments\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sfd = _tcp_connect(host, port);
|
||||||
|
if (_set_socket_timeout(sfd)) {
|
||||||
|
fprintf(stderr, "Error while setting socket options\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _open_serial_connection(char *name, char *baudrate_arg)
|
||||||
|
{
|
||||||
|
unsigned baudrate = 0;
|
||||||
|
if (_parse_baudrate(baudrate_arg, &baudrate) == -1) {
|
||||||
|
fprintf(stderr, "Invalid baudrate specified: %s\n", baudrate_arg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serial_fd = open(name, O_RDWR | O_NOCTTY | O_SYNC);
|
||||||
|
|
||||||
|
if (serial_fd < 0) {
|
||||||
|
fprintf(stderr, "Error opening serial device %s\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_serial_attribs(serial_fd, baudrate, 0);
|
||||||
|
set_blocking(serial_fd, 1);
|
||||||
|
|
||||||
|
return serial_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _open_connection(char *name, char* option)
|
||||||
|
{
|
||||||
|
if (strncmp(name, TCP_DEV, strlen(TCP_DEV)) == 0) {
|
||||||
|
return _open_tcp_connection(name, option);
|
||||||
|
} else {
|
||||||
|
return _open_serial_connection(name, option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char inbuf[MTU];
|
char inbuf[MTU];
|
||||||
unsigned baudrate = BAUDRATE_DEFAULT;
|
char *serial_option = NULL;
|
||||||
|
|
||||||
serial_t serial = {0};
|
serial_t serial = {0};
|
||||||
|
|
||||||
@ -351,9 +492,8 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc >= 4 && _parse_baudrate(argv[3], &baudrate) == -1) {
|
if (argc >= 4) {
|
||||||
fprintf(stderr, "Invalid baudrate specified: %s\n", argv[3]);
|
serial_option = argv[3];
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char ifname[IFNAMSIZ];
|
char ifname[IFNAMSIZ];
|
||||||
@ -364,16 +504,13 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int serial_fd = open(argv[2], O_RDWR | O_NOCTTY | O_SYNC);
|
|
||||||
|
|
||||||
|
int serial_fd = _open_connection(argv[2], serial_option);
|
||||||
if (serial_fd < 0) {
|
if (serial_fd < 0) {
|
||||||
fprintf(stderr, "Error opening serial device %s\n", argv[2]);
|
fprintf(stderr, "Error opening serial device %s\n", argv[2]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_serial_attribs(serial_fd, baudrate, 0);
|
|
||||||
set_blocking(serial_fd, 1);
|
|
||||||
|
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
int max_fd = (serial_fd > tap_fd) ? serial_fd : tap_fd;
|
int max_fd = (serial_fd > tap_fd) ? serial_fd : tap_fd;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user