/* 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);