2021-04-30 20:10:30 +01:00
|
|
|
#include <StdAfx.h>
|
2021-05-17 19:26:11 +01:00
|
|
|
|
|
|
|
#include "linux/network/slirp2.h"
|
|
|
|
|
|
|
|
#ifdef U2_USE_SLIRP
|
|
|
|
|
2021-04-30 20:10:30 +01:00
|
|
|
#include <libslirp.h>
|
|
|
|
|
|
|
|
#include "Log.h"
|
|
|
|
#include "CPU.h"
|
|
|
|
#include "Core.h"
|
|
|
|
|
|
|
|
#define IP_PACK(a,b,c,d) htonl( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d))
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
short vdeslirp_slirp_to_poll(int events)
|
|
|
|
{
|
|
|
|
short ret = 0;
|
|
|
|
if (events & SLIRP_POLL_IN) ret |= POLLIN;
|
|
|
|
if (events & SLIRP_POLL_OUT) ret |= POLLOUT;
|
|
|
|
if (events & SLIRP_POLL_PRI) ret |= POLLPRI;
|
|
|
|
if (events & SLIRP_POLL_ERR) ret |= POLLERR;
|
|
|
|
if (events & SLIRP_POLL_HUP) ret |= POLLHUP;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int vdeslirp_poll_to_slirp(short events)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
if (events & POLLIN) ret |= SLIRP_POLL_IN;
|
|
|
|
if (events & POLLOUT) ret |= SLIRP_POLL_OUT;
|
|
|
|
if (events & POLLPRI) ret |= SLIRP_POLL_PRI;
|
|
|
|
if (events & POLLERR) ret |= SLIRP_POLL_ERR;
|
|
|
|
if (events & POLLHUP) ret |= SLIRP_POLL_HUP;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t net_slirp_send_packet(const void *buf, size_t len, void *opaque)
|
|
|
|
{
|
|
|
|
SlirpNet * slirp = reinterpret_cast<SlirpNet *>(opaque);
|
|
|
|
slirp->sendToGuest(reinterpret_cast<const uint8_t *>(buf), len);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
void net_slirp_guest_error(const char *msg, void *opaque)
|
|
|
|
{
|
|
|
|
LogOutput("SLIRP: %s\n", msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t net_slirp_clock_get_ns(void *opaque)
|
|
|
|
{
|
|
|
|
const int64_t ns = (10e9 * g_nCumulativeCycles) / g_fCurrentCLK6502;
|
|
|
|
return ns;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *net_slirp_timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque)
|
|
|
|
{
|
|
|
|
LogFileOutput("SLIRP: slirp_timer_new()\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void net_slirp_timer_free(void *timer, void *opaque)
|
|
|
|
{
|
|
|
|
LogFileOutput("SLIRP: slirp_timer_free()\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void net_slirp_timer_mod(void *timer, int64_t expire_timer, void *opaque)
|
|
|
|
{
|
|
|
|
LogFileOutput("SLIRP: slirp_timer_mod()\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void net_slirp_register_poll_fd(int /* fd */, void * /* opaque */)
|
|
|
|
{
|
|
|
|
// most existing implementations are a NOOP???
|
|
|
|
}
|
|
|
|
|
|
|
|
void net_slirp_unregister_poll_fd(int /* fd */, void * /* opaque */)
|
|
|
|
{
|
|
|
|
// most existing implementations are a NOOP???
|
|
|
|
}
|
|
|
|
|
|
|
|
void net_slirp_notify(void *opaque)
|
|
|
|
{
|
|
|
|
LogFileOutput("SLIRP: slirp_notify()\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
int net_slirp_add_poll(int fd, int events, void *opaque)
|
|
|
|
{
|
|
|
|
SlirpNet * slirp = reinterpret_cast<SlirpNet *>(opaque);
|
|
|
|
return slirp->addPoll(fd, events);
|
|
|
|
}
|
|
|
|
|
|
|
|
int net_slirp_get_revents(int idx, void *opaque)
|
|
|
|
{
|
|
|
|
const SlirpNet * slirp = reinterpret_cast<SlirpNet *>(opaque);
|
|
|
|
return slirp->getREvents(idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SlirpNet::SlirpNet()
|
|
|
|
{
|
|
|
|
const SlirpConfig cfg =
|
|
|
|
{
|
|
|
|
.version = SLIRP_CONFIG_VERSION_MAX,
|
|
|
|
.in_enabled = 1,
|
|
|
|
.vnetwork = { .s_addr = IP_PACK(10, 0, 0, 0) },
|
|
|
|
.vnetmask = { .s_addr = IP_PACK(255, 255, 255, 0) },
|
|
|
|
.vhost = { .s_addr = IP_PACK(10, 0, 0, 1) },
|
|
|
|
.vhostname = "applewin",
|
|
|
|
.vdhcp_start = { .s_addr = IP_PACK(10, 0, 0, 2) },
|
|
|
|
};
|
|
|
|
static const SlirpCb slirp_cb =
|
|
|
|
{
|
|
|
|
.send_packet = net_slirp_send_packet,
|
|
|
|
.guest_error = net_slirp_guest_error,
|
|
|
|
.clock_get_ns = net_slirp_clock_get_ns,
|
|
|
|
.timer_new = net_slirp_timer_new,
|
|
|
|
.timer_free = net_slirp_timer_free,
|
|
|
|
.timer_mod = net_slirp_timer_mod,
|
|
|
|
.register_poll_fd = net_slirp_register_poll_fd,
|
|
|
|
.unregister_poll_fd = net_slirp_unregister_poll_fd,
|
|
|
|
.notify = net_slirp_notify,
|
|
|
|
};
|
|
|
|
Slirp * slirp = slirp_new(&cfg, &slirp_cb, this);
|
|
|
|
mySlirp.reset(slirp, slirp_cleanup);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SlirpNet::sendFromGuest(const uint8_t *pkt, const int pkt_len)
|
|
|
|
{
|
|
|
|
slirp_input(mySlirp.get(), pkt, pkt_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SlirpNet::sendToGuest(const uint8_t *pkt, int pkt_len)
|
|
|
|
{
|
2021-05-09 19:49:18 +01:00
|
|
|
if (myQueue.size() < ourQueueSize)
|
|
|
|
{
|
|
|
|
myQueue.emplace(pkt, pkt + pkt_len);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// drop it
|
|
|
|
}
|
2021-04-30 20:10:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SlirpNet::process(uint32_t timeout)
|
|
|
|
{
|
|
|
|
myFDs.clear();
|
|
|
|
slirp_pollfds_fill(mySlirp.get(), &timeout, net_slirp_add_poll, this);
|
|
|
|
int pollout;
|
|
|
|
if (myFDs.empty())
|
|
|
|
{
|
|
|
|
pollout = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pollout = poll(myFDs.data(), myFDs.size(), timeout);
|
|
|
|
}
|
|
|
|
slirp_pollfds_poll(mySlirp.get(), (pollout <= 0), net_slirp_get_revents, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
int SlirpNet::addPoll(const int fd, const int events)
|
|
|
|
{
|
|
|
|
const pollfd ff = { .fd = fd, .events = vdeslirp_slirp_to_poll(events) };
|
|
|
|
myFDs.push_back(ff);
|
|
|
|
return myFDs.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SlirpNet::getREvents(const int idx) const
|
|
|
|
{
|
|
|
|
return vdeslirp_poll_to_slirp(myFDs[idx].revents);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::queue<std::vector<uint8_t>> & SlirpNet::getQueue()
|
|
|
|
{
|
|
|
|
return myQueue;
|
|
|
|
}
|
2021-05-05 15:02:42 +01:00
|
|
|
|
|
|
|
void SlirpNet::clearQueue()
|
|
|
|
{
|
|
|
|
std::queue<std::vector<uint8_t>>().swap(myQueue);
|
|
|
|
}
|
2021-05-17 19:26:11 +01:00
|
|
|
|
|
|
|
#endif
|