File:  [Isaki's NoNo m68k/m88k emulator] / nono / host / netdriver_slirp.h
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:02 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2025 nono project
// Licensed under nono-license.txt
//

//
// ホストネットワークの usermode (SLIRP) ドライバ
//

#pragma once

#include "netdriver.h"
#include "autofd.h"
#include "config.h"
#include "hostnet.h"
#include <poll.h>
#include <netinet/in.h>
#include <list>
#include <mutex>

typedef struct Slirp Slirp;
class SlirpThread;
class SlirpTimer;

struct FwdInfo
{
	int is_udp;
	struct sockaddr_in host;
	struct sockaddr_in guest;
};

class NetDriverSlirp : public NetDriver
{
	using inherited = NetDriver;
 public:
	explicit NetDriverSlirp(HostDevice *hostdev_);
	~NetDriverSlirp() override;

	void SetLogLevel(int) override;
	bool InitDriver(bool startup) override;

	int Read(NetPacket *p) override;
	void Write(const void *buf, int buflen) override;

	void MonitorScreenMD(TextScreen&, int y) override;

	// Slirp ドライバが稼働中かどうか (高々1つなのでグローバル)
	static bool IsOccupied() noexcept { return slirp_occupied; }

 private:
	void Close();

	int txd {};			// 裏スレッドへの送信ディスクリプタ
	int rxd {};			// 裏スレッドからの受信ディスクリプタ

	std::unique_ptr<SlirpThread> backend /*{}*/;

	// usermode を使えるのは同時に1人だけに限定する。
	static bool slirp_occupied;
};

// 裏スレッド
class SlirpThread : public ThreadDevice
{
	using inherited = ThreadDevice;

	// major.minor.patch のバージョン番号を適当に整数にマッピングする。
	static uint32 VER(uint major_, uint minor_, uint patch_) {
		return (major_ << 16) + (minor_ << 8) + patch_;
	}

 public:
	explicit SlirpThread(NetDriverSlirp *parent_);
	~SlirpThread() override;

	// 初期化
	bool InitBackend(const std::string& key, int *rfd, int *tfd);

	void Close();
	void Terminate() override;

	void MonitorScreen(Monitor *, TextScreen&);

	// コールバック (C のコールバックから呼ばれるので public)
	int AddPollCB(int fd, int slevents);
	int GetReventsCB(int idx);
	ssize_t SendPacketCB(const void *src, size_t srclen);
	int64 ClockGetNsCB() const;
	void *TimerNewCB(void (*)(void *), void *);
	void TimerFreeCB(SlirpTimer *);
	void TimerModCB(SlirpTimer *, int64);
	void GuestErrorCB(const char *);

	// エラーメッセージ。表スレッドへの連絡用。
	std::string errmsg {};

 private:
	void ThreadRun() override;

	bool ParseConfigNet(const ConfigItem&,
		struct in_addr *addr, struct in_addr *mask);
	bool ParseConfigNet6(const ConfigItem&, struct in6_addr *addr6, uint *len);
	bool ParseConfigHostFwdEntry(const ConfigItem&, const std::string& entry,
		const std::string& where);
	int  ParseAddrPort(const ConfigItem&, const std::string& hostport,
		struct sockaddr_in *, const char *which, const std::string& where);

	void Write();
	// 一部のパケットをこちらで処理する。
	bool WriteHook(const std::vector<uint8>&) const;

	void UpdateInfo();

	// スレッド終了フラグ
	bool exit_requested {};

	// デバッグ用。
	void DumpHex(const void *, size_t) const;
	void DumpFrame(const void *, size_t) const;

	// Slirp ハンドル
	Slirp *sl {};

	std::vector<struct pollfd> pollfds {};

	std::list<SlirpTimer *> timerlist {};

	std::vector<FwdInfo> fwdinfo {};

	struct in6_addr gw6 {};
	struct in6_addr dns6 {};

	// 表スレッドとの送信側/受信側パイプ。
	autofd txd_r {};
	autofd txd_w {};
	autofd rxd_r {};
	autofd rxd_w {};

	// モニタ表示用の内部テーブル文字列。
	char *conninfo {};
	char *nbrinfo {};
	std::mutex info_mtx {};

	// タイマーを区別するためのデバッグ用の番号用。
	int latest_timer_num {};

	// libslirp のバージョン
	uint32 ver {};

	Monitor *monitor {};

	HostNetDevice *hostnet {};
	NetDriverSlirp *parent {};
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.