docs: expand NCP provider/process redesign notes

This commit is contained in:
Mario Fetka
2026-06-02 06:13:07 +00:00
parent 4c586f99e2
commit 83ce6de11a

View File

@@ -294,6 +294,185 @@ This is a design target, not a demand to move files immediately. The important
part is that future code should avoid making `nwbind` a catch-all sink for
unrelated NCPs just because it already has an IPC path.
## Provider boundary versus process boundary
A provider boundary is not the same thing as a Unix process boundary. This is
an important distinction because splitting every NCP family into a separate
process would make the server harder to debug and could introduce new ordering,
locking, and reply-ownership bugs.
The preferred rule is:
```text
first define logical providers;
only later promote the few large stateful providers to separate processes.
```
A logical provider can start as an ordinary C module called from the existing
process path. It becomes valuable as soon as the dispatch table can say "this
endpoint belongs to the queue provider" or "this endpoint belongs to the
connection-local provider", even if no new process exists yet. A process split
should be treated as an implementation detail that is only justified when the
provider has enough independent state and lifecycle to benefit from isolation.
This keeps the redesign incremental:
```text
now:
nwconn switch -> existing local code or nwbind handoff
first cleanup:
nwconn switch -> provider-named helper/module
later, only where useful:
nwconn/dispatcher -> IPC -> provider process
```
### Good process candidates
#### Bindery
Bindery is already a natural service boundary. It owns long-lived server state:
objects, properties, sets, security, password/login/key handling, and object
lookup. Keeping bindery behind a clear provider boundary is appropriate, and the
existing `nwbind` process can remain that boundary while the dispatch layer is
cleaned up.
The main cleanup is not to remove `nwbind`, but to stop treating it as a generic
catch-all for unrelated forwarded requests. A future endpoint table should mark
true bindery calls as `bindery`, and queue or management calls should not be
classified as bindery merely because their current implementation lives in
`nwbind.c`.
#### Queue / possible `nwqueue`
Queue management is the strongest candidate for a future separate process after
bindery. Queue handling has its own domain state:
- queue objects and queue metadata;
- queue job lifecycle;
- queue server attach/detach state;
- service, finish, and abort state;
- job position and priority;
- client-rights transitions during job servicing;
- queue directories and spool/job files.
That is large enough to deserve a logical `queue` provider even before any
runtime split. A future `nwqueue` process can be considered once request/reply
ownership and bindery access are explicit.
The first step should only be a provider split:
```text
0x2222/23 queue subfunctions -> queue provider
queue provider -> bindery provider/library for object/security/property checks
queue provider -> file/path helpers for queue job files
```
A real `nwqueue` process should not be created by simply moving the current queue
cases out of `nwbind.c`. It needs an explicit contract for:
- which process owns the final NCP reply;
- how queue calls read bindery objects and properties;
- how queue job files are opened and handed back to the connection process;
- how connection cleanup affects attached queue servers and in-service jobs;
- how old 16-bit job-number calls and newer 32-bit job-number calls are kept
compatible.
Until those contracts are clear, `nwqueue` should remain a design target, not an
immediate functional change.
### Possible but risky process candidates
#### File and volume subsystem
The file/volume/name-space area is large and stateful, so it can look like a
candidate for a separate process. It owns or touches directory handles, file
handles, locks, trustee evaluation, volume information, name spaces, salvage and
purge operations, and Unix filesystem mapping.
However, this area is also tightly coupled to connection state and existing file
descriptor ownership. Moving it behind IPC too early could create more problems
than it solves. The safer path is:
```text
first: file/volume/name-space provider modules inside the current process model
later: consider a process split only after handle ownership is explicit
```
A file provider boundary is useful for documentation and dispatch cleanup. A
separate file process is optional and should be considered high-risk.
#### Accounting
Accounting is a maybe. It has a separate protocol domain, but in many setups it
may be small enough to stay as an in-process provider. A process boundary only
makes sense if accounting grows into a real persistent service with charges,
holds, notes, audit records, and recovery behavior that should be isolated from
connection handlers.
### Poor process candidates
#### Semaphore
Semaphore calls should have a clean provider boundary, but a dedicated process is
probably overkill. The old semaphore group is small: open, examine, wait,
signal, and close. It needs shared state, but not necessarily a standalone
process. A `sema` provider module with clear request/reply ownership should be
enough unless later testing shows that cross-connection semaphore state cannot be
managed safely in the existing process model.
#### Connection lifecycle and session-local calls
Connection lifecycle operations should stay with `nwconn` or a connection-local
provider. Calls such as Logout, End Of Job, watchdog handling, buffer
negotiation, and connection-state cleanup are fundamentally tied to the session
that received the packet. Moving them into another process would make cleanup
ordering and error handling harder.
#### Simple server-management calls
Simple management and information calls should not become their own process.
Examples include login-status queries, server description strings, server time,
console-privilege checks, and small broadcast/control helpers. These can be
represented as a `servermgmt` provider for dispatch clarity, but they should stay
in-process unless a specific call requires an existing backend service.
### Suggested provider map
The endpoint audit table should be able to use provider names like these:
```text
local packet/session-local handling in nwconn
bindery object/property/security/login backend
queue queue objects, jobs, queue servers, spool/job lifecycle
filesystem file, directory, volume, namespace, trustee, salvage helpers
semaphore semaphore state and old 0x2222/32 calls
message station messaging and broadcast helpers
servermgmt small server-management and information calls
accounting account status, charges, holds, notes
AFP AFP namespace and metadata helpers
unknown documented but not yet mapped
```
Only some providers should ever become processes:
```text
already process-like: bindery / nwbind
likely future process: queue / possible nwqueue
maybe, high risk: filesystem
usually in-process: semaphore, message, servermgmt, accounting, AFP helpers
```
The practical design rule is:
```text
Use provider names everywhere in documentation and endpoint tables.
Use new processes only where shared state, isolation, and lifecycle justify the
extra IPC complexity.
```
## Logging connection
The dispatch redesign also supports the desired log cleanup. If every request