TCP/IP support
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <86box/plat.h>
|
||||
#include <86box/network.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/plat_netsocket.h>
|
||||
|
||||
/* From RFC 1055. */
|
||||
#define END 0300 /* indicates end of packet */
|
||||
@@ -93,9 +94,17 @@ typedef struct modem_t
|
||||
|
||||
bool connected, ringing;
|
||||
bool echo, numericresponse;
|
||||
bool tcpIpMode, tcpIpConnInProgress;
|
||||
uint32_t tcpIpConnCounter;
|
||||
|
||||
int doresponse;
|
||||
int cmdpause;
|
||||
int listen_port;
|
||||
int ringtimer;
|
||||
|
||||
SOCKET serversocket;
|
||||
SOCKET clientsocket;
|
||||
SOCKET waitingclientsocket;
|
||||
|
||||
struct {
|
||||
bool binary[2];
|
||||
@@ -309,7 +318,7 @@ modem_data_mode_process_byte(modem_t* modem, uint8_t data)
|
||||
|
||||
if (modem->tx_count < 0x10000 && modem->connected) {
|
||||
modem->tx_pkt_ser_line[modem->tx_count++] = data;
|
||||
if (data == END) {
|
||||
if (data == END && !modem->tcpIpMode) {
|
||||
process_tx_packet(modem, modem->tx_pkt_ser_line, (uint32_t)modem->tx_count);
|
||||
modem->tx_count = 0;
|
||||
}
|
||||
@@ -321,6 +330,9 @@ host_to_modem_cb(void *priv)
|
||||
{
|
||||
modem_t* modem = (modem_t*)priv;
|
||||
|
||||
if (modem->in_warmup)
|
||||
goto no_write_to_machine;
|
||||
|
||||
if ((modem->serial->type >= SERIAL_16550) && modem->serial->fifo_enabled) {
|
||||
if (fifo_get_full(modem->serial->rcvr_fifo)) {
|
||||
goto no_write_to_machine;
|
||||
@@ -441,6 +453,37 @@ modem_enter_idle_state(modem_t* modem)
|
||||
modem->ringing = false;
|
||||
modem->mode = MODEM_MODE_COMMAND;
|
||||
modem->in_warmup = 0;
|
||||
modem->tcpIpConnInProgress = 0;
|
||||
modem->tcpIpConnCounter = 0;
|
||||
|
||||
if (modem->waitingclientsocket != -1)
|
||||
plat_netsocket_close(modem->waitingclientsocket);
|
||||
|
||||
if (modem->clientsocket != -1)
|
||||
plat_netsocket_close(modem->clientsocket);
|
||||
|
||||
modem->clientsocket = modem->waitingclientsocket = -1;
|
||||
if (modem->serversocket != -1) {
|
||||
modem->waitingclientsocket = plat_netsocket_accept(modem->serversocket);
|
||||
while (modem->waitingclientsocket != -1) {
|
||||
plat_netsocket_close(modem->waitingclientsocket);
|
||||
modem->waitingclientsocket = plat_netsocket_accept(modem->serversocket);
|
||||
}
|
||||
plat_netsocket_close(modem->serversocket);
|
||||
modem->serversocket = -1;
|
||||
}
|
||||
|
||||
if (modem->waitingclientsocket != -1)
|
||||
plat_netsocket_close(modem->waitingclientsocket);
|
||||
|
||||
modem->waitingclientsocket = -1;
|
||||
modem->tcpIpMode = false;
|
||||
modem->tcpIpConnInProgress = false;
|
||||
|
||||
if (modem->listen_port) {
|
||||
modem->serversocket = plat_netsocket_create_server(NET_SOCKET_TCP, modem->listen_port);
|
||||
}
|
||||
|
||||
serial_set_cts(modem->serial, 1);
|
||||
serial_set_dsr(modem->serial, 1);
|
||||
serial_set_dcd(modem->serial, 0);
|
||||
@@ -454,6 +497,9 @@ modem_enter_connected_state(modem_t* modem)
|
||||
modem->mode = MODEM_MODE_DATA;
|
||||
modem->ringing = false;
|
||||
modem->connected = true;
|
||||
modem->tcpIpMode = true;
|
||||
plat_netsocket_close(modem->serversocket);
|
||||
modem->serversocket = -1;
|
||||
memset(&modem->telClient, 0, sizeof(modem->telClient));
|
||||
serial_set_dcd(modem->serial, 1);
|
||||
serial_set_ri(modem->serial, 0);
|
||||
@@ -488,15 +534,40 @@ void
|
||||
modem_dial(modem_t* modem, const char* str)
|
||||
{
|
||||
/* TODO: Port TCP/IP support from DOSBox. */
|
||||
modem->tcpIpConnCounter = 0;
|
||||
modem->tcpIpMode = false;
|
||||
if (!strncmp(str, "0.0.0.0", sizeof("0.0.0.0") - 1))
|
||||
{
|
||||
pclog("Turning on SLIP\n");
|
||||
modem_enter_connected_state(modem);
|
||||
modem->tcpIpMode = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
modem_send_res(modem, ResNOCARRIER);
|
||||
modem_enter_idle_state(modem);
|
||||
char buf[128] = "";
|
||||
const char *destination = buf;
|
||||
strcpy(buf, str);
|
||||
// Scan host for port
|
||||
uint16_t port;
|
||||
char * hasport = strrchr(buf,':');
|
||||
if (hasport) {
|
||||
*hasport++ = 0;
|
||||
port = (uint16_t)atoi(hasport);
|
||||
}
|
||||
else {
|
||||
port = 23;
|
||||
}
|
||||
|
||||
modem->clientsocket = plat_netsocket_create(NET_SOCKET_TCP);
|
||||
if (modem->clientsocket == -1) {
|
||||
modem_send_res(modem, ResNOCARRIER);
|
||||
modem_enter_idle_state(modem);
|
||||
return;
|
||||
}
|
||||
|
||||
plat_netsocket_connect(modem->clientsocket, buf, port);
|
||||
modem->tcpIpConnInProgress = 1;
|
||||
modem->tcpIpConnCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,6 +622,16 @@ char *trim(char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
static const char *modem_get_address_from_phonebook(modem_t* modem, const char *input) {
|
||||
int i = 0;
|
||||
for (i = 0; i < modem->entries_num; i++) {
|
||||
if (strcmp(input, modem->entries[i].phone) == 0)
|
||||
return modem->entries[i].address;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
modem_do_command(modem_t* modem)
|
||||
{
|
||||
@@ -583,7 +664,9 @@ modem_do_command(modem_t* modem)
|
||||
char buffer[128];
|
||||
char obuffer[128];
|
||||
char * foundstr = &scanbuf[0];
|
||||
const char *mappedaddr = NULL;
|
||||
size_t i = 0;
|
||||
|
||||
if (*foundstr == 'T' || *foundstr == 'P')
|
||||
foundstr++;
|
||||
|
||||
@@ -593,6 +676,13 @@ modem_do_command(modem_t* modem)
|
||||
}
|
||||
|
||||
foundstr = trim(foundstr);
|
||||
|
||||
mappedaddr = modem_get_address_from_phonebook(modem, foundstr);
|
||||
if (mappedaddr) {
|
||||
modem_dial(modem, mappedaddr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(foundstr) >= 12) {
|
||||
// Check if supplied parameter only consists of digits
|
||||
bool isNum = true;
|
||||
@@ -860,6 +950,9 @@ modem_rx(void *priv, uint8_t *buf, int io_len)
|
||||
uint8_t c = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (modem->tcpIpMode)
|
||||
return 0;
|
||||
|
||||
if (!modem->connected) {
|
||||
/* Drop packet. */
|
||||
pclog("Dropping %d bytes\n", io_len - 14);
|
||||
@@ -914,12 +1007,127 @@ modem_rcr_cb(UNUSED(struct serial_s *serial), void *priv)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
modem_accept_incoming_call(modem_t* modem)
|
||||
{
|
||||
if (modem->waitingclientsocket != -1) {
|
||||
modem->clientsocket = modem->waitingclientsocket;
|
||||
modem->waitingclientsocket = -1;
|
||||
modem_enter_connected_state(modem);
|
||||
modem->in_warmup = 250;
|
||||
} else {
|
||||
modem_enter_idle_state(modem);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
modem_cmdpause_timer_callback(void *priv)
|
||||
{
|
||||
modem_t *dev = (modem_t *) priv;
|
||||
uint32_t guard_threashold = 0;
|
||||
|
||||
if (dev->tcpIpConnInProgress) {
|
||||
int status = plat_netsocket_connected(dev->clientsocket);
|
||||
|
||||
if (status == -1) {
|
||||
plat_netsocket_close(dev->clientsocket);
|
||||
dev->clientsocket = -1;
|
||||
modem_enter_idle_state(dev);
|
||||
modem_send_res(dev, ResNOCARRIER);
|
||||
dev->tcpIpConnInProgress = 0;
|
||||
} else if (status == 1) {
|
||||
modem_enter_connected_state(dev);
|
||||
dev->tcpIpConnInProgress = 0;
|
||||
}
|
||||
|
||||
dev->tcpIpConnCounter++;
|
||||
|
||||
if (status <= 0 && dev->tcpIpConnCounter >= 5000) {
|
||||
plat_netsocket_close(dev->clientsocket);
|
||||
dev->clientsocket = -1;
|
||||
modem_enter_idle_state(dev);
|
||||
modem_send_res(dev, ResNOANSWER);
|
||||
dev->tcpIpConnInProgress = 0;
|
||||
dev->tcpIpMode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->connected && dev->waitingclientsocket == -1 && dev->serversocket != -1) {
|
||||
dev->waitingclientsocket = plat_netsocket_accept(dev->serversocket);
|
||||
if (dev->waitingclientsocket != -1) {
|
||||
if (!(dev->serial->mctrl & 1) && dev->dtrmode != 0) {
|
||||
modem_enter_idle_state(dev);
|
||||
} else {
|
||||
dev->ringing = true;
|
||||
modem_send_res(dev, ResRING);
|
||||
serial_set_ri(dev->serial, !serial_get_ri(dev->serial));
|
||||
dev->ringtimer = 3000;
|
||||
dev->reg[MREG_RING_COUNT] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dev->ringing) {
|
||||
if (dev->ringtimer <= 0) {
|
||||
dev->reg[MREG_RING_COUNT]++;
|
||||
if ((dev->reg[MREG_AUTOANSWER_COUNT] > 0) &&
|
||||
(dev->reg[MREG_RING_COUNT] >= dev->reg[MREG_AUTOANSWER_COUNT])) {
|
||||
modem_accept_incoming_call(dev);
|
||||
return;
|
||||
}
|
||||
modem_send_res(dev, ResRING);
|
||||
serial_set_ri(dev->serial, !serial_get_ri(dev->serial));
|
||||
|
||||
//MIXER_Enable(mhd.chan,true);
|
||||
dev->ringtimer = 3000;
|
||||
}
|
||||
--dev->ringtimer;
|
||||
}
|
||||
|
||||
if (dev->in_warmup) {
|
||||
dev->in_warmup--;
|
||||
if (dev->in_warmup == 0) {
|
||||
dev->tx_count = 0;
|
||||
fifo8_reset(&dev->rx_data);
|
||||
}
|
||||
}
|
||||
else if (dev->connected && dev->tcpIpMode) {
|
||||
if (dev->tx_count) {
|
||||
int wouldblock = 0;
|
||||
int res = plat_netsocket_send(dev->clientsocket, dev->tx_pkt_ser_line, dev->tx_count, &wouldblock);
|
||||
|
||||
if (res <= 0 && !wouldblock) {
|
||||
/* No bytes sent or error. */
|
||||
dev->tx_count = 0;
|
||||
modem_enter_idle_state(dev);
|
||||
modem_send_res(dev, ResNOCARRIER);
|
||||
} else if (res > 0) {
|
||||
if (res == dev->tx_count) {
|
||||
dev->tx_count = 0;
|
||||
} else {
|
||||
memmove(dev->tx_pkt_ser_line, &dev->tx_pkt_ser_line[res], dev->tx_count - res);
|
||||
dev->tx_count -= res;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dev->connected) {
|
||||
uint8_t buffer[16];
|
||||
int wouldblock = 0;
|
||||
int res = plat_netsocket_receive(dev->clientsocket, buffer, sizeof(buffer), &wouldblock);
|
||||
|
||||
if (res > 0) {
|
||||
fifo8_push_all(&dev->rx_data, buffer, res);
|
||||
} else if (res == 0) {
|
||||
dev->tx_count = 0;
|
||||
modem_enter_idle_state(dev);
|
||||
modem_send_res(dev, ResNOCARRIER);
|
||||
} else if (!wouldblock) {
|
||||
dev->tx_count = 0;
|
||||
modem_enter_idle_state(dev);
|
||||
modem_send_res(dev, ResNOCARRIER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev->cmdpause++;
|
||||
guard_threashold = (uint32_t)(dev->reg[MREG_GUARD_TIME] * 20);
|
||||
if (dev->cmdpause > guard_threashold) {
|
||||
@@ -938,11 +1146,13 @@ static void *
|
||||
modem_init(const device_t *info)
|
||||
{
|
||||
modem_t* modem = (modem_t*)calloc(1, sizeof(modem_t));
|
||||
const char* phonebook_file = NULL;
|
||||
memset(modem->mac, 0xfc, 6);
|
||||
|
||||
|
||||
modem->port = device_get_config_int("port");
|
||||
modem->baudrate = device_get_config_int("baudrate");
|
||||
modem->listen_port = device_get_config_int("listen_port");
|
||||
|
||||
fifo8_create(&modem->data_pending, 0x10000);
|
||||
fifo8_create(&modem->rx_data, 0x10000);
|
||||
@@ -955,12 +1165,20 @@ modem_init(const device_t *info)
|
||||
|
||||
modem_reset(modem);
|
||||
modem->card = network_attach(modem, modem->mac, modem_rx, NULL);
|
||||
|
||||
phonebook_file = device_get_config_string("phonebook_file");
|
||||
if (phonebook_file && phonebook_file[0] != 0) {
|
||||
modem_read_phonebook_file(modem, phonebook_file);
|
||||
}
|
||||
|
||||
return modem;
|
||||
}
|
||||
|
||||
void modem_close(void *priv)
|
||||
{
|
||||
modem_t* modem = (modem_t*)priv;
|
||||
modem->listen_port = 0;
|
||||
modem_reset(modem);
|
||||
fifo8_destroy(&modem->data_pending);
|
||||
fifo8_destroy(&modem->rx_data);
|
||||
netcard_close(modem->card);
|
||||
@@ -1009,6 +1227,23 @@ static const device_config_t modem_config[] = {
|
||||
{ .description = "300", .value = 300 },
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "listen_port",
|
||||
.description = "TCP/IP listening port",
|
||||
.type = CONFIG_INT,
|
||||
.default_string = "",
|
||||
.default_int = 5000,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {}
|
||||
},
|
||||
{
|
||||
.name = "phonebook_file",
|
||||
.description = "Phonebook File",
|
||||
.type = CONFIG_FNAME,
|
||||
.default_string = "",
|
||||
.file_filter = "Text files (*.txt)|*.txt"
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user