How webMAN MOD Implements the NETISO Protocol for Streaming PS3 Games Over Network
webMAN MOD streams PS3, PS1, DVD, and Blu-ray ISOs over a LAN using a custom binary NETISO protocol that pairs a PS3 client with the PC-side ps3netsrv daemon on TCP port 38008, intercepting SCSI commands and forwarding them as network packets to simulate a locally attached disc drive.
The aldostools/webman-mod repository contains the complete implementation of this protocol, enabling users to mount and play games stored on a remote PC without copying them to the console's local storage. The architecture splits functionality between a lightweight NETISO client embedded in the webMAN MOD plugin and the ps3netsrv server application that handles file-system operations on the host machine.
NETISO Protocol Architecture
The NETISO system relies on two cooperating components that communicate via raw binary packets over TCP port 38008. When a user selects a network game in the webMAN MOD interface, the plugin constructs a net:// URL (for example, net://192.168.1.10/ISO/Game.iso) and initiates a mount sequence.
The PS3-side NETISO client, defined in include/mount/netclient.h, opens a persistent TCP socket to the server and translates Cobra driver SCSI requests into protocol commands. The PC-side NETISO server, implemented in _Projects_/ps3netsrv/src/main.cpp, listens for these commands, performs the corresponding file I/O, and streams raw bytes back to the client. From the PS3's perspective, the data appears to originate from a local BD-ROM drive.
Protocol Command Reference
The NETISO protocol defines a fixed set of opcodes in cobra/netiso.h for file and directory operations. All multi-byte integers use big-endian encoding, with the PS3 client automatically converting host byte order using inline helpers BE16, BE32, and BE64.
| Opcode | Command | Client Sends | Server Returns |
|---|---|---|---|
NETISO_CMD_OPEN_FILE (0x1224) |
Open a read-only file | _netiso_open_cmd with path length |
_netiso_open_result containing file size and mtime |
NETISO_CMD_READ_FILE |
Standard read request | _netiso_read_file_cmd with offset and byte count |
_netiso_read_file_result followed by raw data |
NETISO_CMD_READ_FILE_CRITICAL |
Fast read without error recovery | _netiso_read_file_critical_cmd |
Raw data (client aborts on failure) |
NETISO_CMD_READ_CD_2048_CRITICAL |
Read 2048-byte sectors for DVD/BD | _netiso_read_cd_2048_critical_cmd |
Raw sector data |
NETISO_CMD_STAT_FILE |
Retrieve file metadata | _netiso_stat_cmd |
_netiso_stat_result with size and timestamps |
NETISO_CMD_OPEN_DIR |
Open directory for listing | _netiso_open_dir_cmd |
_netiso_open_dir_result |
NETISO_CMD_READ_DIR |
Fetch directory entries | _netiso_read_dir_cmd |
_netiso_read_dir_result with entry list |
NETISO_CMD_CUSTOM_0 (0x2412) |
Extension point for future use | — | — |
Client-Side Implementation in webMAN MOD
The PS3 implementation integrates directly with the Cobra driver to intercept disc access requests.
Mounting Network ISOs
When a user triggers a mount via the webMAN MOD UI, the code in _Projects_/netiso/main.c and netiso.c creates a netiso_args structure containing the server IP, remote path, and emulation mode. The mount_iso() function parses the net:// URL and invokes the NETISO client API, which registers itself with Cobra using SYS_MODULE_INFO(NETISO, …). Once registered, all subsequent SCSI read commands route through the NETISO client rather than the physical drive.
Building Binary Command Packets
The client constructs packets by populating C structs and converting fields to big-endian. Below is a simplified version of the file-opening logic found in the client implementation:
// Simplified from netclient.c
int netiso_open(const char *server, const char *path)
{
int s = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(NETISO_PORT) };
inet_pton(AF_INET, server, &addr.sin_addr);
connect(s, (struct sockaddr *)&addr, sizeof(addr));
// Build open command with proper byte order
netiso_open_cmd cmd = {
.opcode = BE16(NETISO_CMD_OPEN_FILE),
.fp_len = BE16(strlen(path))
};
send(s, &cmd, sizeof(cmd), 0);
send(s, path, strlen(path), 0);
netiso_open_result res;
recv(s, &res, sizeof(res), 0);
res.file_size = (s64)BE64(res.file_size);
return s; // Socket handle for subsequent reads
}
For reading data, the client sends a _netiso_read_file_cmd structure specifying the byte offset and length, then receives the payload in two stages: first the result header containing the actual bytes read, then the raw ISO data.
// Read request construction
netiso_read_file_cmd rcmd = {
.opcode = BE16(NETISO_CMD_READ_FILE),
.pad = 0,
.num_bytes = BE32(0x10000), // 64 KB chunks
.offset = BE64(file_offset)
};
send(s, &rcmd, sizeof(rcmd), 0);
netiso_read_file_result rres;
recv(s, &rres, sizeof(rres), 0);
int bytes = BE32(rres.bytes_read);
recv(s, buffer, bytes, 0); // Raw ISO sector data
Server-Side Implementation (ps3netsrv)
The PC-side daemon ps3netsrv handles the actual file-system operations. The source in _Projects_/ps3netsrv/src/main.cpp implements a blocking TCP server that maintains per-connection state, including open file pointers.
Command Dispatch Loop
The server enters a loop receiving 16-bit opcodes, switching on the command type, and executing the corresponding handler. For NETISO_CMD_OPEN_FILE, it reconstructs the filename, opens the file in binary mode, and returns the size:
// Excerpt from _Projects_/ps3netsrv/src/main.cpp
case NETISO_CMD_OPEN_FILE:
{
netiso_open_cmd cmd;
recv(sock, &cmd, sizeof(cmd), 0);
cmd.opcode = BE16(cmd.opcode);
char filename[0x420];
recv(sock, filename, BE16(cmd.fp_len), 0);
FILE *fp = fopen(filename, "rb");
netiso_open_result res = { .file_size = -1, .mtime = 0 };
if (fp) {
fseek(fp, 0, SEEK_END);
res.file_size = ftell(fp);
rewind(fp);
}
res.file_size = BE64(res.file_size);
send(sock, &res, sizeof(res), 0);
// File pointer stored in connection state for reads
}
break;
Streaming File Data
For read operations, the server seeks to the requested offset, allocates a temporary buffer, and transmits the data immediately:
case NETISO_CMD_READ_FILE:
{
netiso_read_file_cmd cmd;
recv(sock, &cmd, sizeof(cmd), 0);
uint64_t off = BE64(cmd.offset);
uint32_t nbytes = BE32(cmd.num_bytes);
fseek(state->fp, off, SEEK_SET);
char *buf = new char[nbytes];
size_t got = fread(buf, 1, nbytes, state->fp);
netiso_read_file_result res = { .bytes_read = BE32((uint32_t)got) };
send(sock, &res, sizeof(res), 0);
send(sock, buf, got, 0);
delete[] buf;
}
break;
This zero-copy-like approach ensures minimal latency for streaming high-bandwidth Blu-ray ISOs over gigabit Ethernet.
Summary
- webMAN MOD implements the NETISO protocol to stream disc images over TCP port 38008, enabling network gameplay without local storage.
- The client in
include/mount/netclient.hconverts Cobra SCSI requests into binary commands using big-endian byte order helpers (BE16,BE32,BE64). - The server in
_Projects_/ps3netsrv/src/main.cppdispatches opcodes such asNETISO_CMD_OPEN_FILEandNETISO_CMD_READ_FILEto serve file data in 64 KB chunks or 2048-byte sectors. - Integration occurs through
net://URL parsing in_Projects_/netiso/main.c, which registers the NETISO module with the Cobra driver to intercept disc reads.
Frequently Asked Questions
What network port does the NETISO protocol use?
The NETISO protocol uses TCP port 38008 for all client-server communication. The ps3netsrv daemon binds to this port by default, and the webMAN MOD client connects to it when mounting net:// URLs.
Can NETISO stream folder-based games or only ISO files?
NETISO supports both ISO files and folder-based games. While ISOs use NETISO_CMD_READ_FILE for byte-offset reads, folder-based content (JBOD format) uses NETISO_CMD_OPEN_DIR and NETISO_CMD_READ_DIR to browse directory structures, with individual files accessed via the standard file commands.
How does webMAN MOD handle byte order in NETISO packets?
All NETISO packets use big-endian encoding to match the PS3's PowerPC architecture. The client and server use inline conversion macros BE16, BE32, and BE64 defined in cobra/netiso.h to swap byte order when packing or unpacking command structures on little-endian PC hosts.
Is the NETISO server compatible with other PS3 homebrew besides webMAN MOD?
The ps3netsrv implementation is specific to the NETISO protocol used by webMAN MOD and Cobra firmware. While the protocol is open-source, compatibility with other tools depends on whether they implement the same command set found in include/mount/netclient.h and _Projects_/ps3netsrv/include/netiso.h.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →