tcpser/src/ip232.c
ksherlock c48aeb7188 use NULL ip address for ip232 server
inet_addr("") is treated as 0xffffffff (INADDR_BROADCAST) which probably isn't what you want.
2017-05-08 22:09:20 -04:00

266 lines
6.1 KiB
C

#include <sys/socket.h> // for recv...
#include <stdlib.h> // for exit...
#include <sys/file.h>
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include "util.h"
#include "debug.h"
#include "modem_core.h"
#include "ip.h"
#include "ip232.h"
void *ip232_thread(void *arg)
{
modem_config *cfg = (modem_config *) arg;
int accept_pending = FALSE;
int rc;
int res = 0;
char buf[256];
fd_set readfs;
int max_fd = 0;
int cSocket;
LOG_ENTER();
for (;;) {
FD_ZERO(&readfs);
FD_SET(cfg->dce_data.dp[1][0], &readfs);
max_fd = cfg->dce_data.dp[1][0];
if (accept_pending == FALSE) {
FD_SET(cfg->dce_data.sSocket, &readfs);
max_fd = MAX(max_fd, cfg->dce_data.sSocket);
}
LOG(LOG_ALL, "Waiting for incoming ip232 connections");
rc = select(max_fd + 1, &readfs, NULL, NULL, NULL);
if (rc < 0) {
// handle error
}
else {
if (FD_ISSET(cfg->dce_data.dp[1][0], &readfs)) { // pipe
res = read(cfg->dce_data.dp[1][0], buf, sizeof(buf) - 1);
LOG(LOG_DEBUG, "ip232 thread notified");
accept_pending = FALSE;
}
if (FD_ISSET(cfg->dce_data.sSocket, &readfs)) { // ip connection
if (cfg->dce_data.ip232_is_connected) {
LOG(LOG_DEBUG, "Already have ip232 connection, rejecting new");
// already have a connection... accept and close
cSocket = ip_accept(cfg->dce_data.sSocket);
if (cSocket > -1) {
close(cSocket);
}
}
else {
LOG(LOG_DEBUG, "Incoming ip232 connection");
writePipe(cfg->dce_data.dp[0][1], MSG_ACCEPT);
accept_pending = TRUE;
}
}
}
}
LOG_EXIT();
}
int spawn_ip232_thread(modem_config *cfg)
{
int rc;
pthread_t thread_id;
rc = pthread_create(&thread_id, NULL, ip232_thread, (void *) cfg);
LOG(LOG_ALL, "ip232 thread ID=%d", (int) thread_id);
if (rc < 0) {
ELOG(LOG_FATAL, "ip232 thread could not be started");
exit(-1);
}
return 0;
}
int ip232_init_conn(modem_config *cfg)
{
int rc = -1;
int port;
LOG_ENTER();
LOG(LOG_INFO, "Opening ip232 device");
port = atoi(cfg->dce_data.tty);
rc = ip_init_server_conn(NULL, port);
if (rc < 0) {
ELOG(LOG_FATAL, "Could not initialize ip232 server socket");
exit(-1);
}
if (-1 == pipe(cfg->dce_data.dp[0])) {
ELOG(LOG_FATAL, "ip232 thread incoming IPC pipe could not be created");
exit(-1);
}
if (-1 == pipe(cfg->dce_data.dp[1])) {
ELOG(LOG_FATAL, "ip232 thread outgoing IPC pipe could not be created");
exit(-1);
}
cfg->dce_data.sSocket = rc;
cfg->dce_data.ip232_is_connected = FALSE;
cfg->dce_data.fd = cfg->dce_data.dp[0][0];
spawn_ip232_thread(cfg);
LOG(LOG_INFO, "ip232 device configured");
LOG_EXIT();
return rc;
}
int ip232_set_flow_control(modem_config *cfg, int status)
{
return 0;
}
int ip232_get_control_lines(modem_config *cfg)
{
int status = 0;
if (cfg->dce_data.ip232_is_connected && cfg->dce_data.ip232_dtr) {
status |= TIOCM_DSR;
}
return status;
}
int ip232_set_control_lines(modem_config *cfg, int state)
{
int dcd;
char cmd[2];
if (cfg->dce_data.ip232_is_connected) {
dcd = (state & TIOCM_DTR) ? TRUE : FALSE;
if (dcd != cfg->dce_data.ip232_dcd) {
cfg->dce_data.ip232_dcd = dcd;
cmd[0] = 255;
cmd[1] = dcd ? 1 : 0;
ip_write(cfg->dce_data.fd, cmd, sizeof(cmd));
}
}
return 0;
}
int ip232_write(modem_config *cfg, char *data, int len)
{
int retval;
int i = 0;
int double_iac = FALSE;
char text[1024];
int text_len = 0;
log_trace(TRACE_MODEM_OUT, data, len);
retval = len;
if (cfg->dce_data.ip232_is_connected) {
while (i < len) {
if (double_iac) {
text[text_len++] = 255;
double_iac = FALSE;
i++;
}
else {
if (255 == data[i]) {
text[text_len++] = 255;
double_iac = TRUE;
}
else {
text[text_len++] = data[i++];
}
}
if (text_len == sizeof(text)) {
retval = ip_write(cfg->dce_data.fd, text, text_len);
text_len = 0;
}
}
if (text_len) {
retval = ip_write(cfg->dce_data.fd, text, text_len);
}
}
return retval;
}
int ip232_read(modem_config *cfg, char *data, int len)
{
int res;
int rc;
char buf[256];
int i = 0;
int ch;
int text_len = 0;
LOG_ENTER();
if (len > sizeof(buf)) {
LOG(LOG_FATAL, "ip232_read: len > sizeof(buf)");
exit(-1);
}
if (cfg->dce_data.ip232_is_connected) {
res = recv(cfg->dce_data.fd, buf, len, 0);
if (0 >= res) {
LOG(LOG_INFO, "No ip232 socket data read, assume closed peer");
ip_disconnect(cfg->dce_data.fd);
cfg->dce_data.fd = cfg->dce_data.dp[0][0];
cfg->dce_data.ip232_is_connected = FALSE;
}
else {
LOG(LOG_DEBUG, "Read %d bytes from ip232 socket", res);
log_trace(TRACE_MODEM_IN, buf, res);
while (i < res) {
ch = buf[i];
if (cfg->dce_data.ip232_iac) {
cfg->dce_data.ip232_iac = FALSE;
switch (ch) {
case 0:
cfg->dce_data.ip232_dtr = FALSE;
break;
case 1:
cfg->dce_data.ip232_dtr = TRUE;
break;
case 255:
data[text_len++] = 255;
break;
}
}
else {
if (255 == ch) {
cfg->dce_data.ip232_iac = TRUE;
}
else {
data[text_len++] = ch;
}
}
i++;
}
}
}
else {
// not connected
res = read(cfg->dce_data.dp[0][0], buf, sizeof(buf));
switch (buf[0]) {
case MSG_ACCEPT: // accept connection.
LOG(LOG_INFO, "Accepting ip232 connection...");
rc = ip_accept(cfg->dce_data.sSocket);
if (res > -1) {
cfg->dce_data.fd = rc;
cfg->dce_data.ip232_is_connected = TRUE;
cfg->dce_data.ip232_dtr = FALSE;
cfg->dce_data.ip232_dcd = FALSE;
writePipe(cfg->dce_data.dp[1][1], MSG_ACCEPTED);
}
break;
}
}
LOG_EXIT();
return text_len;
}