Merge pull request #4247 from Cacodemon345/modem_emu
Modem emulation (includinng SLIP connectivity)
This commit is contained in:
@@ -1170,13 +1170,14 @@ pc_reset_hard_init(void)
|
|||||||
/* note: PLIP LPT side has to be initialized before the network side */
|
/* note: PLIP LPT side has to be initialized before the network side */
|
||||||
lpt_devices_init();
|
lpt_devices_init();
|
||||||
|
|
||||||
/* Reset and reconfigure the Network Card layer. */
|
|
||||||
network_reset();
|
|
||||||
|
|
||||||
/* Reset and reconfigure the serial ports. */
|
/* Reset and reconfigure the serial ports. */
|
||||||
|
/* note: SLIP COM side has to be initialized before the network side */
|
||||||
serial_standalone_init();
|
serial_standalone_init();
|
||||||
serial_passthrough_init();
|
serial_passthrough_init();
|
||||||
|
|
||||||
|
/* Reset and reconfigure the Network Card layer. */
|
||||||
|
network_reset();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset the mouse, this will attach it to any port needed.
|
* Reset the mouse, this will attach it to any port needed.
|
||||||
*/
|
*/
|
||||||
|
@@ -432,6 +432,25 @@ serial_set_dcd(serial_t *dev, uint8_t enabled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_set_ri(serial_t *dev, uint8_t enabled)
|
||||||
|
{
|
||||||
|
uint8_t prev_state = !!(dev->msr & 0x40);
|
||||||
|
if (dev->mctrl & 0x10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev->msr &= ~0x40;
|
||||||
|
dev->msr |= (!!enabled) << 6;
|
||||||
|
dev->msr_set &= ~0x40;
|
||||||
|
dev->msr_set |= (!!enabled) << 6;
|
||||||
|
|
||||||
|
if (prev_state == 0 && (!!enabled) == 1) {
|
||||||
|
dev->msr |= 0x4;
|
||||||
|
dev->int_status |= SERIAL_INT_MSR;
|
||||||
|
serial_update_ints(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
serial_set_clock_src(serial_t *dev, double clock_src)
|
serial_set_clock_src(serial_t *dev, double clock_src)
|
||||||
{
|
{
|
||||||
@@ -570,6 +589,8 @@ serial_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
serial_do_irq(dev, 0);
|
serial_do_irq(dev, 0);
|
||||||
if ((val ^ dev->mctrl) & 0x10)
|
if ((val ^ dev->mctrl) & 0x10)
|
||||||
serial_reset_fifo(dev);
|
serial_reset_fifo(dev);
|
||||||
|
if (dev->sd && dev->sd->dtr_callback && (val ^ dev->mctrl) & 1)
|
||||||
|
dev->sd->dtr_callback(dev, val & 1, dev->sd->priv);
|
||||||
dev->mctrl = val;
|
dev->mctrl = val;
|
||||||
if (val & 0x10) {
|
if (val & 0x10) {
|
||||||
new_msr = (val & 0x0c) << 4;
|
new_msr = (val & 0x0c) << 4;
|
||||||
@@ -797,6 +818,25 @@ serial_attach_ex(int port,
|
|||||||
return sd->serial;
|
return sd->serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serial_t *
|
||||||
|
serial_attach_ex_2(int port,
|
||||||
|
void (*rcr_callback)(struct serial_s *serial, void *priv),
|
||||||
|
void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data),
|
||||||
|
void (*dtr_callback)(struct serial_s *serial, int status, void *priv),
|
||||||
|
void *priv)
|
||||||
|
{
|
||||||
|
serial_device_t *sd = &serial_devices[port];
|
||||||
|
|
||||||
|
sd->rcr_callback = rcr_callback;
|
||||||
|
sd->dtr_callback = dtr_callback;
|
||||||
|
sd->dev_write = dev_write;
|
||||||
|
sd->transmit_period_callback = NULL;
|
||||||
|
sd->lcr_callback = NULL;
|
||||||
|
sd->priv = priv;
|
||||||
|
|
||||||
|
return sd->serial;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_speed_changed(void *priv)
|
serial_speed_changed(void *priv)
|
||||||
{
|
{
|
||||||
|
@@ -225,6 +225,9 @@ extern const device_t pcnet_am79c970a_device;
|
|||||||
extern const device_t pcnet_am79c973_device;
|
extern const device_t pcnet_am79c973_device;
|
||||||
extern const device_t pcnet_am79c973_onboard_device;
|
extern const device_t pcnet_am79c973_onboard_device;
|
||||||
|
|
||||||
|
/* Modem */
|
||||||
|
extern const device_t modem_device;
|
||||||
|
|
||||||
/* PLIP */
|
/* PLIP */
|
||||||
#ifdef EMU_LPT_H
|
#ifdef EMU_LPT_H
|
||||||
extern const lpt_device_t lpt_plip_device;
|
extern const lpt_device_t lpt_plip_device;
|
||||||
|
24
src/include/86box/plat_netsocket.h
Normal file
24
src/include/86box/plat_netsocket.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _WIN32
|
||||||
|
#define SOCKET int
|
||||||
|
#else
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum net_socket_types
|
||||||
|
{
|
||||||
|
/* Only TCP is supported for now. */
|
||||||
|
NET_SOCKET_TCP
|
||||||
|
};
|
||||||
|
|
||||||
|
SOCKET plat_netsocket_create(int type);
|
||||||
|
SOCKET plat_netsocket_create_server(int type, unsigned short port);
|
||||||
|
void plat_netsocket_close(SOCKET socket);
|
||||||
|
|
||||||
|
SOCKET plat_netsocket_accept(SOCKET socket);
|
||||||
|
int plat_netsocket_connected(SOCKET socket); /* Returns -1 on trouble. */
|
||||||
|
int plat_netsocket_connect(SOCKET socket, const char* hostname, unsigned short port);
|
||||||
|
|
||||||
|
/* Returns 0 in case of inability to send. -1 in case of errors. */
|
||||||
|
int plat_netsocket_send(SOCKET socket, const unsigned char* data, unsigned int size, int *wouldblock);
|
||||||
|
int plat_netsocket_receive(SOCKET socket, unsigned char* data, unsigned int size, int *wouldblock);
|
@@ -92,6 +92,7 @@ typedef struct serial_s {
|
|||||||
|
|
||||||
typedef struct serial_device_s {
|
typedef struct serial_device_s {
|
||||||
void (*rcr_callback)(struct serial_s *serial, void *priv);
|
void (*rcr_callback)(struct serial_s *serial, void *priv);
|
||||||
|
void (*dtr_callback)(struct serial_s *serial, int status, void *priv);
|
||||||
void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data);
|
void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data);
|
||||||
void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t lcr);
|
void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t lcr);
|
||||||
void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period);
|
void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period);
|
||||||
@@ -112,6 +113,12 @@ extern serial_t *serial_attach_ex(int port,
|
|||||||
void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t data_bits),
|
void (*lcr_callback)(struct serial_s *serial, void *priv, uint8_t data_bits),
|
||||||
void *priv);
|
void *priv);
|
||||||
|
|
||||||
|
extern serial_t *serial_attach_ex_2(int port,
|
||||||
|
void (*rcr_callback)(struct serial_s *serial, void *priv),
|
||||||
|
void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data),
|
||||||
|
void (*dtr_callback)(struct serial_s *serial, int status, void *priv),
|
||||||
|
void *priv);
|
||||||
|
|
||||||
#define serial_attach(port, rcr_callback, dev_write, priv) \
|
#define serial_attach(port, rcr_callback, dev_write, priv) \
|
||||||
serial_attach_ex(port, rcr_callback, dev_write, NULL, NULL, priv);
|
serial_attach_ex(port, rcr_callback, dev_write, NULL, NULL, priv);
|
||||||
|
|
||||||
@@ -129,6 +136,7 @@ extern void serial_device_timeout(void *priv);
|
|||||||
extern void serial_set_cts(serial_t *dev, uint8_t enabled);
|
extern void serial_set_cts(serial_t *dev, uint8_t enabled);
|
||||||
extern void serial_set_dsr(serial_t *dev, uint8_t enabled);
|
extern void serial_set_dsr(serial_t *dev, uint8_t enabled);
|
||||||
extern void serial_set_dcd(serial_t *dev, uint8_t enabled);
|
extern void serial_set_dcd(serial_t *dev, uint8_t enabled);
|
||||||
|
extern void serial_set_ri(serial_t *dev, uint8_t enabled);
|
||||||
|
|
||||||
extern const device_t ns8250_device;
|
extern const device_t ns8250_device;
|
||||||
extern const device_t ns8250_pcjr_device;
|
extern const device_t ns8250_pcjr_device;
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
set(net_sources)
|
set(net_sources)
|
||||||
list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c
|
list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c
|
||||||
net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c
|
net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c
|
||||||
net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c net_l80225.c)
|
net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c net_l80225.c net_modem.c utils/getline.c)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp)
|
pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp)
|
||||||
|
1027
src/network/net_modem.c
Normal file
1027
src/network/net_modem.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@
|
|||||||
#include <86box/ini.h>
|
#include <86box/ini.h>
|
||||||
#include <86box/config.h>
|
#include <86box/config.h>
|
||||||
#include <86box/video.h>
|
#include <86box/video.h>
|
||||||
|
#include <86box/bswap.h>
|
||||||
|
|
||||||
#define _SSIZE_T_DEFINED
|
#define _SSIZE_T_DEFINED
|
||||||
#include <slirp/libslirp.h>
|
#include <slirp/libslirp.h>
|
||||||
@@ -76,6 +77,29 @@ typedef struct net_slirp_t {
|
|||||||
#endif
|
#endif
|
||||||
} net_slirp_t;
|
} net_slirp_t;
|
||||||
|
|
||||||
|
/* Pulled off from libslirp code. This is only needed for modem. */
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct arphdr_local {
|
||||||
|
unsigned char h_dest[6]; /* destination eth addr */
|
||||||
|
unsigned char h_source[6]; /* source ether addr */
|
||||||
|
unsigned short h_proto; /* packet type ID field */
|
||||||
|
|
||||||
|
unsigned short ar_hrd; /* format of hardware address */
|
||||||
|
unsigned short ar_pro; /* format of protocol address */
|
||||||
|
unsigned char ar_hln; /* length of hardware address */
|
||||||
|
unsigned char ar_pln; /* length of protocol address */
|
||||||
|
unsigned short ar_op; /* ARP opcode (command) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ethernet looks like this : This bit is variable sized however...
|
||||||
|
*/
|
||||||
|
uint8_t ar_sha[6]; /* sender hardware address */
|
||||||
|
uint32_t ar_sip; /* sender IP address */
|
||||||
|
uint8_t ar_tha[6]; /* target hardware address */
|
||||||
|
uint32_t ar_tip; /* target IP address */
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#ifdef ENABLE_SLIRP_LOG
|
#ifdef ENABLE_SLIRP_LOG
|
||||||
int slirp_do_log = ENABLE_SLIRP_LOG;
|
int slirp_do_log = ENABLE_SLIRP_LOG;
|
||||||
|
|
||||||
@@ -455,6 +479,32 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
slirp->sock_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
slirp->sock_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!strcmp(network_card_get_internal_name(net_cards_conf[net_card_current].device_num), "modem")) {
|
||||||
|
/* Send a gratuitous ARP here to make SLiRP work properly with SLIP connections. */
|
||||||
|
struct arphdr_local arphdr;
|
||||||
|
/* ARP part. */
|
||||||
|
arphdr.ar_hrd = bswap16(1);
|
||||||
|
arphdr.ar_pro = bswap16(0x0800);
|
||||||
|
arphdr.ar_hln = 6;
|
||||||
|
arphdr.ar_pln = 4;
|
||||||
|
arphdr.ar_op = bswap16(1);
|
||||||
|
memcpy(&arphdr.ar_sha, mac_addr, 6);
|
||||||
|
memcpy(&arphdr.ar_tha, mac_addr, 6);
|
||||||
|
arphdr.ar_sip = dhcp.s_addr;
|
||||||
|
arphdr.ar_tip = dhcp.s_addr;
|
||||||
|
|
||||||
|
/* Ethernet header part. */
|
||||||
|
arphdr.h_proto = bswap16(0x0806);
|
||||||
|
memset(arphdr.h_dest, 0xff, 6);
|
||||||
|
memset(arphdr.h_source, 0x52, 6);
|
||||||
|
arphdr.h_source[2] = 0x0a;
|
||||||
|
arphdr.h_source[3] = 0x00;
|
||||||
|
arphdr.h_source[4] = slirp_card_num;
|
||||||
|
arphdr.h_source[5] = 2;
|
||||||
|
slirp_input(slirp->slirp, (const uint8_t *)&arphdr, sizeof(struct arphdr_local));
|
||||||
|
}
|
||||||
|
|
||||||
slirp_log("SLiRP: creating thread...\n");
|
slirp_log("SLiRP: creating thread...\n");
|
||||||
slirp->poll_tid = thread_create(net_slirp_thread, slirp);
|
slirp->poll_tid = thread_create(net_slirp_thread, slirp);
|
||||||
|
|
||||||
|
@@ -136,6 +136,7 @@ static const device_t *net_cards[] = {
|
|||||||
&dec_tulip_21140_vpc_device,
|
&dec_tulip_21140_vpc_device,
|
||||||
&dec_tulip_21040_device,
|
&dec_tulip_21040_device,
|
||||||
&pcnet_am79c960_vlb_device,
|
&pcnet_am79c960_vlb_device,
|
||||||
|
&modem_device,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -453,6 +454,7 @@ netcard_t *
|
|||||||
network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state)
|
network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state)
|
||||||
{
|
{
|
||||||
netcard_t *card = calloc(1, sizeof(netcard_t));
|
netcard_t *card = calloc(1, sizeof(netcard_t));
|
||||||
|
int net_type = net_cards_conf[net_card_current].net_type;
|
||||||
card->queued_pkt.data = calloc(1, NET_MAX_FRAME);
|
card->queued_pkt.data = calloc(1, NET_MAX_FRAME);
|
||||||
card->card_drv = card_drv;
|
card->card_drv = card_drv;
|
||||||
card->rx = rx;
|
card->rx = rx;
|
||||||
@@ -469,7 +471,12 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin
|
|||||||
network_queue_init(&card->queues[i]);
|
network_queue_init(&card->queues[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (net_cards_conf[net_card_current].net_type) {
|
if (!strcmp(network_card_get_internal_name(net_cards_conf[net_card_current].device_num), "modem") && net_type >= NET_TYPE_PCAP) {
|
||||||
|
/* Force SLiRP here. Modem only operates on non-Ethernet frames. */
|
||||||
|
net_type = NET_TYPE_SLIRP;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (net_type) {
|
||||||
case NET_TYPE_SLIRP:
|
case NET_TYPE_SLIRP:
|
||||||
card->host_drv = net_slirp_drv;
|
card->host_drv = net_slirp_drv;
|
||||||
card->host_drv.priv = card->host_drv.init(card, mac, NULL, net_drv_error);
|
card->host_drv.priv = card->host_drv.init(card, mac, NULL, net_drv_error);
|
||||||
|
81
src/network/utils/getline.c
Normal file
81
src/network/utils/getline.c
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
local_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
|
||||||
|
{
|
||||||
|
char *ptr, *eptr;
|
||||||
|
|
||||||
|
|
||||||
|
if (*buf == NULL || *bufsiz == 0) {
|
||||||
|
*bufsiz = BUFSIZ;
|
||||||
|
if ((*buf = malloc(*bufsiz)) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
|
||||||
|
int c = fgetc(fp);
|
||||||
|
if (c == -1) {
|
||||||
|
if (feof(fp)) {
|
||||||
|
ssize_t diff = (ssize_t)(ptr - *buf);
|
||||||
|
if (diff != 0) {
|
||||||
|
*ptr = '\0';
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ptr++ = c;
|
||||||
|
if (c == delimiter) {
|
||||||
|
*ptr = '\0';
|
||||||
|
return ptr - *buf;
|
||||||
|
}
|
||||||
|
if (ptr + 2 >= eptr) {
|
||||||
|
char *nbuf;
|
||||||
|
size_t nbufsiz = *bufsiz * 2;
|
||||||
|
ssize_t d = ptr - *buf;
|
||||||
|
if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
|
||||||
|
return -1;
|
||||||
|
*buf = nbuf;
|
||||||
|
*bufsiz = nbufsiz;
|
||||||
|
eptr = nbuf + nbufsiz;
|
||||||
|
ptr = nbuf + d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
local_getline(char **buf, size_t *bufsiz, FILE *fp)
|
||||||
|
{
|
||||||
|
return local_getdelim(buf, bufsiz, '\n', fp);
|
||||||
|
}
|
@@ -221,7 +221,7 @@ if(WIN32 AND NOT MINGW)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_sources(plat PRIVATE ../win/win_serial_passthrough.c)
|
target_sources(plat PRIVATE ../win/win_serial_passthrough.c ../win/win_netsocket.c)
|
||||||
else()
|
else()
|
||||||
target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c)
|
target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c)
|
||||||
endif()
|
endif()
|
||||||
|
153
src/win/win_netsocket.c
Normal file
153
src/win/win_netsocket.c
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
#define _XOPEN_SOURCE 500
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/log.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/plat.h>
|
||||||
|
#include <86box/device.h>
|
||||||
|
#include <86box/plat_netsocket.h>
|
||||||
|
#include <86box/ui.h>
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
|
||||||
|
SOCKET plat_netsocket_create(int type)
|
||||||
|
{
|
||||||
|
SOCKET socket = -1;
|
||||||
|
u_long yes = 1;
|
||||||
|
|
||||||
|
if (type != NET_SOCKET_TCP)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
socket = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
|
||||||
|
if (socket == INVALID_SOCKET)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ioctlsocket(socket, FIONBIO, &yes);
|
||||||
|
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET plat_netsocket_create_server(int type, unsigned short port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in sock_addr;
|
||||||
|
SOCKET socket = plat_netsocket_create(type);
|
||||||
|
if (socket == INVALID_SOCKET)
|
||||||
|
return (SOCKET)-1;
|
||||||
|
|
||||||
|
memset(&sock_addr, 0, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
sock_addr.sin_family = AF_INET;
|
||||||
|
sock_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
sock_addr.sin_port = port;
|
||||||
|
|
||||||
|
if (bind(socket, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
|
||||||
|
plat_netsocket_close(socket);
|
||||||
|
return (SOCKET)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(socket, 5) == SOCKET_ERROR) {
|
||||||
|
plat_netsocket_close(socket);
|
||||||
|
return (SOCKET)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plat_netsocket_close(SOCKET socket)
|
||||||
|
{
|
||||||
|
closesocket((SOCKET)socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET plat_netsocket_accept(SOCKET socket)
|
||||||
|
{
|
||||||
|
SOCKET clientsocket = accept(socket, NULL, NULL);
|
||||||
|
|
||||||
|
if (clientsocket == INVALID_SOCKET)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return clientsocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plat_netsocket_connected(SOCKET socket)
|
||||||
|
{
|
||||||
|
struct sockaddr addr;
|
||||||
|
socklen_t len = sizeof(struct sockaddr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (getpeername(socket, &addr, &len) == SOCKET_ERROR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plat_netsocket_connect(SOCKET socket, const char* hostname, unsigned short port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in sock_addr;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
sock_addr.sin_family = AF_INET;
|
||||||
|
sock_addr.sin_addr.s_addr = inet_addr(hostname);
|
||||||
|
sock_addr.sin_port = htons(port);
|
||||||
|
|
||||||
|
if (sock_addr.sin_addr.s_addr == -1 || sock_addr.sin_addr.s_addr == 0) {
|
||||||
|
struct hostent *hp;
|
||||||
|
|
||||||
|
hp = gethostbyname(hostname);
|
||||||
|
|
||||||
|
if (hp)
|
||||||
|
memcpy(&sock_addr.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = connect(socket, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_in));
|
||||||
|
|
||||||
|
if (res == SOCKET_ERROR) {
|
||||||
|
int error = WSAGetLastError();
|
||||||
|
|
||||||
|
if (error == WSAEISCONN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plat_netsocket_send(SOCKET socket, const unsigned char* data, unsigned int size, int *wouldblock)
|
||||||
|
{
|
||||||
|
int res = send(socket, (const char*)data, size, 0);
|
||||||
|
|
||||||
|
if (res == SOCKET_ERROR) {
|
||||||
|
int error = WSAGetLastError();
|
||||||
|
|
||||||
|
if (wouldblock)
|
||||||
|
*wouldblock = !!(error == WSAEWOULDBLOCK);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plat_netsocket_receive(SOCKET socket, unsigned char* data, unsigned int size, int *wouldblock)
|
||||||
|
{
|
||||||
|
int res = recv(socket, (char*)data, size, 0);
|
||||||
|
|
||||||
|
if (res == SOCKET_ERROR) {
|
||||||
|
int error = WSAGetLastError();
|
||||||
|
|
||||||
|
if (wouldblock)
|
||||||
|
*wouldblock = !!(error == WSAEWOULDBLOCK);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
Reference in New Issue
Block a user