SDK Script serial-udp-server.are

serial-udp-server.are
/* DESC: This script reads messages coming from the serial port and forwards them via UDP to a remote host (and vice versa).
 * Copyright (C) 2013 NetModule AG, Switzerland
 */
 
DEV = "SERIAL1";
 
REMOTE_HOST = argv[1];
REMOTE_PORT = (int) argv[2];
LOCAL_PORT = (int) argv[3];
MAX_PACKET_SIZE = (int) argv[4];        /* bytes */
POLL_TIMEOUT = (int) argv[5];           /* seconds */
LATENCY = (int) argv[6];                /* seconds */
 
void usage()
{
    printf("usage: serial-udp-server.are <remote-host> <remote-port> <local-port> <max-packet-size> <poll-timeout> <latency>\n");
    exit(1);
}
 
int jiffy()
{
    sys = sysinfo();
    u = struct_get(sys, "uptime");
 
    if (is_void(u) || u < 1) {
        return 0;
    } else {
        return u;
    }
}
 
/* check arguments */
if (strlen(argv[1]) == 0) {
    nb_syslog("ERROR: no remote host specified");
    usage();
}
if (strlen(argv[2]) == 0) {
    nb_syslog("ERROR: no remote port specified");
    usage();
}
if (strlen(argv[3]) == 0) {
    nb_syslog("ERROR: no local port specified");
    usage();
}
if (strlen(argv[4]) == 0) {
    MAX_PACKET_SIZE = 1380;
}
if (strlen(argv[5]) == 0 || POLL_TIMEOUT < 1) {
    POLL_TIMEOUT = 1;
}
if (strlen(argv[6]) == 0 || LATENCY < 1) {
    LATENCY = 2;
}
 
/* check serial port config */
status = nb_config_get("serial.0.status");
if (status != "2") {
    nb_syslog("serial port is not enabled for us");
    exit(1);
}
 
/* set attributes */
rc = nb_serial_setattr(DEV, 115200, 8, 1, 0, 0);
if (rc != 0) {
    nb_syslog("ERROR: unable to set serial attributes (rc %d)", rc);
    exit(1);
}
 
/* open serial port */
fd = nb_serial_open(DEV);
if (fd < 0) {
    nb_syslog("Unable to open serial device (%s)", DEV);
    exit(1);
}
 
/* open UDP socket */
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0) {
    nb_syslog("ERROR: unable to open socket");
    exit(1);
}
 
/* bind socket to 1st LAN interface */
addr = nb_ifc_address("LAN1");
rc = bind(sock, REMOTE_PORT, addr);
if (rc == -1) {
    nb_syslog("ERROR: unable to bind to port %d\n", REMOTE_PORT);
    exit(1);
}
 
nb_syslog("Listening for messages (local %d, remote %s:%d)", LOCAL_PORT, REMOTE_HOST, REMOTE_PORT);
 
fds = mkarray(sock, fd);
last = jiffy();
buffer = "";
 
while (1) {
    rc = select(fds, POLL_TIMEOUT);
    if (rc == -1) {
        nb_syslog("ERROR: select failed");
        close(fd);
        exit(1);
    } 
 
    if (rc == fd) {
        /* received something from serial device */
        data = read(fd, 4096);
        if (data) {
            buffer = strcat(buffer, data);
        }
    } else if (rc == sock) {
        /* received something from UDP */
        data = recvfrom(sock);
        if (data) {
            len = strlen(data);
            if (len > 0) {
                /* write to serial device */
                if (len > MAX_PACKET_SIZE) len = MAX_PACKET_SIZE;
                write(fd, data, len);
            }
        }
    }
 
    /* check serial buffer and send message */
    len = strlen(buffer);
    if (len == 0) continue;
 
    now = jiffy();
    elapsed = now - last;
 
    if (len < MAX_PACKET_SIZE && elapsed < LATENCY) continue;
 
    if (len <= MAX_PACKET_SIZE) {
        msg = buffer;
        msglen = len;
        buffer = "";
    } else {
        msg = substr(buffer, 0, MAX_PACKET_SIZE);
        msglen = MAX_PACKET_SIZE;
        buffer = substr(buffer, MAX_PACKET_SIZE);
    }
 
    /* send UDP packet */
    sendbufto(sock, msg, msglen, REMOTE_HOST, REMOTE_PORT);
    last = now;
}
 
close(sock);
close(fd);
 
exit(0);