Deep Dive: Simulating DATAPAC, Canada's Forgotten Internet
Building a historically accurate X.25 packet-switching network simulator—PAD commands, NUA addressing, and the five virtual hosts that defined Canadian computing in the 1980s.
Deep Dive: Simulating DATAPAC, Canada’s Forgotten Internet
Building a historically accurate X.25 packet-switching network simulator
Before the internet, there was DATAPAC.
If you’re Canadian and old enough to remember the 1980s, you might have dialed into it. If you’re not, you probably haven’t heard of it at all—which is a shame, because DATAPAC was genuinely ahead of its time. Canada had nationwide packet-switching in 1977, a full decade before most people knew what a modem was.
So naturally, when building a retro terminal emulator, I had to include it.
What Was DATAPAC?
DATAPAC was Canada’s public X.25 packet-switching network, operated by the Trans-Canada Telephone System (later Telecom Canada, eventually absorbed into what became Bell). It ran from 1977 to 1998, which means it predates the commercial internet by about 15 years.
The key insight of packet-switching (versus circuit-switching like phone calls) was that you didn’t need a dedicated line between two points. Your data got chopped into packets, each packet found its own route through the network, and they reassembled at the destination. Revolutionary stuff in 1977.
To access DATAPAC, you’d dial a local access number with your modem. After connecting, you’d see:
DATAPAC: 3101
That cryptic “3101” was the PAD (Packet Assembler/Disassembler) port identifier. From there, you could connect to any host on the network by entering its NUA—Network User Address.
(Think of NUAs like phone numbers, but for computers. Businesses would advertise their NUA in trade magazines: “Connect to our BBS at NUA 92001234!”)
The PAD Interface
The PAD was your gateway. It handled the translation between your dumb terminal (or terminal emulator) and the X.25 network. The command set was terse but functional:
| Command | Description |
|---|---|
C or CALL | Connect to an NUA |
CLR | Clear (disconnect) current call |
STAT | Show connection status |
SET | Set PAD parameters |
PAR | Display PAD parameters |
PROF | Load predefined parameter profile |
DIR | Directory of known hosts |
HELP | Help text |
BYE | Disconnect from DATAPAC entirely |
When connected to a host, pressing Escape would “recall” the PAD, letting you check status or clear the connection without losing your session. It was like an early version of Ctrl+Z for backgrounding a process.
X.3 PAD Parameters
Here’s where it gets interesting. The PAD wasn’t just a dumb relay—it had 22 configurable parameters (X.3 standard) that controlled how it handled your data:
Parameter 1: Data forwarding character (CR)
Parameter 2: Echo mode (local/remote)
Parameter 3: Forward on character count
Parameter 4: Idle timer (tenths of seconds)
Parameter 5: Flow control (XON/XOFF)
Parameter 6: PAD service signals
Parameter 7: Break handling
...
Different hosts needed different settings. A full-screen application might want local echo off and different line-ending handling than an interactive command system. Profiles let you switch between common configurations:
PROF 0- Interactive (transparent, host echo)PROF 1- Simple terminal (local echo, CR forwarding)PROF 7- Block mode (for file transfers)
Implementing the Simulator
For the emulator, I needed to recreate this experience authentically. That meant:
- PAD state machine — Track whether user is at PAD prompt or connected to a host
- NUA routing — Map addresses to virtual backends
- Parameter storage — All 22 X.3 parameters, with profile presets
- Escape handling — PAD recall while connected
- Authentic prompts — The exact text DATAPAC displayed
The structure ended up looking like this:
interface DatapacState {
mode: 'pad' | 'connected';
connectedNua: string | null;
parameters: X3Parameters;
callStartTime: number | null;
}
class DatapacBackend implements Backend {
private state: DatapacState;
private virtualHosts: Map<string, VirtualHost>;
constructor() {
this.state = {
mode: 'pad',
connectedNua: null,
parameters: defaultX3Parameters(),
callStartTime: null,
};
// Register our five virtual hosts
this.virtualHosts = new Map([
['92001001', new Envoy100Host()],
['92001002', new INet2000Host()],
['92001003', new InfoGlobeHost()],
['92001004', new QLSystemsHost()],
['92001005', new DatapacBBSHost()],
]);
}
handleInput(data: string): string {
if (this.state.mode === 'pad') {
return this.handlePadCommand(data.trim().toUpperCase());
} else {
// Check for PAD recall (Escape key)
if (data === '\x1b') {
return this.padRecall();
}
// Forward to connected host
return this.forwardToHost(data);
}
}
private handlePadCommand(cmd: string): string {
if (cmd.startsWith('C ') || cmd.startsWith('CALL ')) {
const nua = cmd.split(' ')[1];
return this.connectToNua(nua);
}
if (cmd === 'CLR') {
return this.clearCall();
}
if (cmd === 'STAT') {
return this.showStatus();
}
if (cmd === 'DIR') {
return this.showDirectory();
}
// ... other commands
return 'DATAPAC: INVALID COMMAND\r\n';
}
}
The Five Virtual Hosts
I wanted hosts that felt authentic to the era. After researching what services actually existed on DATAPAC, I settled on five:
1. Envoy 100 (NUA 92001001)
Telecom Canada’s own email and messaging service. Launched 1984, it was remarkably sophisticated—email, telex gateway, fax gateway, and an early attempt at “social networking” with public message boards.
*** ENVOY 100 ***
Electronic Messaging Service
Telecom Canada (1984)
MAIL - Electronic Mail
TELEX - Telex Gateway
FAX - Facsimile Gateway
MSG - Public Messages
HELP - System Help
(Envoy 100 was eventually killed by the internet, but in 1984 it was the future.)
2. iNet 2000 (NUA 92001002)
Infomart’s online database service. If you needed stock quotes, news, or business information before the web existed, this was where you got it.
WELCOME TO iNET 2000
Infomart Online (1985)
NEWS - Canadian Press Wire
BIZ - Business Database
QUOTE - Stock Quotations
REF - Reference Library
3. Info Globe (NUA 92001003)
The Globe and Mail’s online archive. Full-text newspaper search, years before Google existed.
INFO-GLOBE
The Globe and Mail Online
Full Text Since 1977
Commands:
SEARCH - Search articles
BROWSE - Browse by date
HELP - Search syntax
4. QL Systems (NUA 92001004)
Legal research database. Canadian case law, statutes, and regulations. Lawyers paid handsomely for access.
QUICKLAW
QL Systems Ltd.
Canadian Legal Database
CASES - Case Law Search
STAT - Statutes
REG - Regulations
NEWS - Legal News
5. DATAPAC BBS (NUA 92001005)
A fictional but era-appropriate bulletin board system. Because every network needs a BBS.
DATAPAC BBS
Public Bulletin Board
BOARDS - Message Boards
FILES - File Library
CHAT - User Chat
WHO - Online Users
The Connection Sequence
Getting the timing right mattered for authenticity. Real DATAPAC connections had noticeable delays—packet networks in the ’80s weren’t instant:
private async connectToNua(nua: string): Promise<string> {
const host = this.virtualHosts.get(nua);
if (!host) {
// Simulate network timeout for invalid NUAs
await delay(2000);
return `DATAPAC: ${nua} NOT RESPONDING\r\n`;
}
// Simulate call setup delay (varied by "distance")
const setupTime = 500 + Math.random() * 1000;
await delay(setupTime);
this.state.mode = 'connected';
this.state.connectedNua = nua;
this.state.callStartTime = Date.now();
// Return call confirmation plus host banner
return `DATAPAC: CALL CONNECTED ${nua}\r\n\r\n` + host.getBanner();
}
The PAD recall had its own distinct feedback:
private padRecall(): string {
return '\r\n*** PAD ***\r\n';
}
That *** PAD *** prompt was distinctive. Anyone who used DATAPAC in the ’80s would recognize it instantly.
STAT Command: Where Authenticity Gets Nerdy
The STAT command showed connection details in a format that looked exactly like the real thing:
DATAPAC: STATUS
CALL TO 92001003 INFO-GLOBE
CONNECTED 00:03:47
PACKETS: TX 127 RX 2,104
BYTES: TX 1,143 RX 84,160
I tracked actual packet counts (roughly) based on input/output sizes. The numbers didn’t need to be perfectly accurate, but they needed to feel right—to increment plausibly as you used the system.
PAD Parameters
The X.3 parameter handling was more complex than I initially expected. Each parameter had valid ranges, interactions with other parameters, and behavioral implications:
interface X3Parameters {
dataForwarding: number; // Param 1: 0-127 (CR, LF, etc.)
echo: number; // Param 2: 0=off, 1=on
forwardCharCount: number; // Param 3: 0-255
idleTimer: number; // Param 4: 0-255 (tenths)
flowControl: number; // Param 5: 0=none, 1=XON/XOFF
padSignals: number; // Param 6: 0-5
breakHandling: number; // Param 7: 0-21
discardOutput: number; // Param 8: 0-1
padding: number; // Param 9: 0-255
lineFolding: number; // Param 10: 0-255
// ... parameters 11-22
}
const PROFILES: Record<number, Partial<X3Parameters>> = {
0: { // Transparent
echo: 0,
dataForwarding: 0,
idleTimer: 0,
},
1: { // Simple terminal
echo: 1,
dataForwarding: 13, // CR
idleTimer: 20,
},
7: { // Block mode
echo: 0,
dataForwarding: 0,
forwardCharCount: 128,
idleTimer: 0,
},
};
I didn’t implement all 22 parameters fully—some were only relevant to actual X.25 hardware—but enough to make the SET and PAR commands feel authentic.
Testing at 300 Baud
Here’s a fun challenge: DATAPAC was typically accessed at 300 baud in its early years. My emulator simulates period-accurate baud rates, which meant testing the DATAPAC backend required patience.
At 300 baud, a single character takes about 33 milliseconds. A full screen of text takes over 5 seconds. The Playwright E2E tests needed 4-minute timeouts to handle realistic data flow.
test('can connect to Envoy 100 and see banner', async () => {
// At 300 baud, this takes a while
await terminal.type('ATD5550325\r'); // Dial DATAPAC
// Wait for DATAPAC banner
await expect(terminal).toContainText('DATAPAC:', { timeout: 60000 });
// Connect to Envoy 100
await terminal.type('C 92001001\r');
// Wait for connection + banner (slow at 300 baud)
await expect(terminal).toContainText('ENVOY 100', { timeout: 90000 });
});
Painful to run, but necessary for authenticity.
Why This Matters
DATAPAC isn’t just computing history—it’s Canadian computing history. We had nationwide packet switching when most Americans were still using acoustic couplers. Telecom Canada was genuinely innovative.
But DATAPAC is almost forgotten now. If you Google it, you’ll find a few Wikipedia articles and some nostalgic forum posts. The actual experience of using it? Mostly lost.
Building this simulator means someone in 2026 (or 2046) can dial 555-0325 on a virtual modem and experience what it was like to query QL Systems for case law, or send a message on Envoy 100, or browse Info Globe’s archives.
That’s worth preserving.
Phone: 555-0325
See also: Deep Dive: Bell 103 FSK Modem — how the audio modem gets you connected.
See also: Deep Dive: The Microservices Migration — for when virtual hosts need real backends.