Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f971cbd
Refactor SCTP constants and improve data handling in RTCDtlsTransport…
shinyoshiaki May 24, 2025
2199a4b
Add SCTPTimerManager for improved timer management in SCTP
shinyoshiaki May 24, 2025
450bf04
Refactor SCTPTimerManager to use constants for max retransmissions an…
shinyoshiaki May 24, 2025
5cbabbc
wip Implement SCTPTransmitter for improved chunk sending and connecti…
shinyoshiaki May 24, 2025
0a6270f
Enhance SCTP connection management by integrating EventDisposer and u…
shinyoshiaki May 24, 2025
e5e1a69
Refactor SCTP and SCTPTransmitter for improved state management and t…
shinyoshiaki May 24, 2025
91eeff8
Fix SCTPTransmitter event handling by specifying state type in onStat…
shinyoshiaki May 24, 2025
48649d5
Refactor SCTPTransmitter to delegate RTT calculations to SCTPTimerMan…
shinyoshiaki May 24, 2025
49caece
Refactor SCTPTransmitter and SCTPTimerManager to use event subscripti…
shinyoshiaki May 24, 2025
ee82339
Implement SctpReconfig class for managing reconfiguration requests an…
shinyoshiaki May 24, 2025
3daf5cd
wip: Enhance SctpReconfig for improved reconfiguration handling and i…
shinyoshiaki May 24, 2025
2c10346
wip Refactor SCTP to delegate reconfiguration response handling to Sc…
shinyoshiaki May 24, 2025
74d5a9e
wip: Refactor SCTP to delegate stream addition handling to SctpReconf…
shinyoshiaki May 24, 2025
025d044
refactor: Simplify stream handling in SctpReconfig and update SCTP to…
shinyoshiaki May 24, 2025
b15a5ad
refactor: Update SctpReconfig and SCTP to use localTsn from SCTPTrans…
shinyoshiaki May 24, 2025
89ed1f1
refactor: Remove unused SCTP RTO constants from transmitter for clean…
shinyoshiaki May 24, 2025
0fcf281
refactor: Update SCTP class to improve property access and organizati…
shinyoshiaki May 24, 2025
4c7a2b0
refactor: Update SCTP and UdpTransport classes for improved clarity a…
shinyoshiaki May 24, 2025
cefd167
refactor: Enhance StreamManager and SCTP classes for improved stream …
shinyoshiaki May 24, 2025
4760db1
refactor: Improve Chunk and SCTPTimerManager classes with enhanced er…
shinyoshiaki May 24, 2025
32783c7
Enhance SCTP, SctpReconfig, StreamManager, and SCTPTimerManager clas…
shinyoshiaki May 24, 2025
dd58db4
wip
shinyoshiaki May 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@
"pranswer",
"prflx",
"protoo",
"PRSCTP",
"psfb",
"raddr",
"reconfig",
"recvonly",
"remb",
"reset",
"RETRANS",
"rport",
"rtc",
"rtpfb",
Expand Down Expand Up @@ -81,5 +83,5 @@
],
"typescript.tsdk": "node_modules/typescript/lib",
"biome.lsp.bin": "node_modules/@biomejs/biome/bin/biome",
"prettier.enable": false
"prettier.enable": false,
}
47 changes: 46 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 83 additions & 0 deletions packages/sctp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,89 @@ await Promise.all([
client.send(0, WEBRTC_PPID.STRING, Buffer.from("ping"));
```

## Session Migration

werift-sctp supports session state serialization and restoration, allowing you to migrate SCTP sessions between different processes or network endpoints while preserving connection state.

### Usage

```typescript
import { SCTP } from "werift-sctp";

// Export session state
const stateBuffer = sctpSession.exportState();

// Restore session with new transport
const newSession = SCTP.restoreState(stateBuffer, newTransport);
```

### Example

```typescript
import { createSocket } from "dgram";
import { SCTP, WEBRTC_PPID, createUdpTransport } from "werift-sctp";
import { randomPort } from "werift-common";

async function sessionMigrationExample() {
const clientPort = await randomPort();
const serverPort = await randomPort();

// Create initial session
const sctpA = SCTP.client(
createUdpTransport(createSocket("udp4").bind(clientPort), {
port: serverPort,
address: "127.0.0.1",
}),
);

const sctpB = SCTP.server(
createUdpTransport(createSocket("udp4").bind(serverPort), {
port: clientPort,
address: "127.0.0.1",
}),
);

// Establish connection
await Promise.all([sctpA.start(), sctpB.start()]);

// Send data
await sctpA.send(0, WEBRTC_PPID.STRING, Buffer.from("Hello"));

// Export session state
const stateBuffer = sctpA.exportState();

// Create new transport for migration
const newClientPort = await randomPort();
const newTransport = createUdpTransport(createSocket("udp4").bind(newClientPort), {
port: serverPort,
address: "127.0.0.1",
});

// Restore session
const sctpA2 = SCTP.restoreState(stateBuffer, newTransport);

// Update server's remote port
sctpB.setRemotePort(newClientPort);

// Stop old session
await sctpA.stop();

// Continue communication with migrated session
await sctpA2.send(0, WEBRTC_PPID.STRING, Buffer.from("Migrated Hello"));

// Cleanup
await sctpA2.stop();
await sctpB.stop();
}
```

### Features

- **Complete state preservation**: All session state including streams, sequence numbers, and connection parameters are preserved
- **MessagePack serialization**: Efficient binary serialization using MessagePack
- **Multiple stream support**: Stream state is maintained across migration
- **Transport flexibility**: Works with any transport implementation

# reference

-
Expand Down
116 changes: 116 additions & 0 deletions packages/sctp/examples/session-migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { randomPort } from "../../common/src";
import { SCTP, WEBRTC_PPID } from "../src";
import { createUdpTransport } from "../src/transport";
import { createSocket } from "node:dgram";

async function main() {
console.log("SCTP Session Migration Example with UDP Transport");

// Get random ports for UDP communication
const clientPort = await randomPort();
const serverPort = await randomPort();

console.log(`Client port: ${clientPort}, Server port: ${serverPort}`);

// Create SCTP sessions with UDP transport
const sctpA = SCTP.client(
createUdpTransport(createSocket("udp4").bind(clientPort), {
port: serverPort,
address: "127.0.0.1",
}),
);
const sctpB = SCTP.server(
createUdpTransport(createSocket("udp4").bind(serverPort), {
port: clientPort,
address: "127.0.0.1",
}),
);

// Set up event listeners
sctpB.onReceive.subscribe((streamId, ppId, data) => {
console.log(`Received from stream ${streamId}: ${data.toString()}`);
});

// Start sessions and wait for connection
console.log("Starting SCTP sessions...");
await Promise.all([sctpA.start(), sctpB.start()]);

// Wait for connection to be established
await new Promise<void>((resolve, reject) => {
const timeout = setTimeout(() => reject(new Error("Connection timeout")), 5000);
const checkConnection = () => {
if (sctpA.state === "connected" && sctpB.state === "connected") {
clearTimeout(timeout);
resolve();
} else {
setTimeout(checkConnection, 10);
}
};
checkConnection();
});

console.log("Connection established");

// Send some data from session A
await sctpA.send(0, WEBRTC_PPID.STRING, Buffer.from("Hello from session A"));
console.log("Sent data from session A");

// Send data on multiple streams
await sctpA.send(1, WEBRTC_PPID.STRING, Buffer.from("Stream 1 data"));
console.log("Sent data on stream 1");

// Wait a bit for data to be processed
await new Promise(resolve => setTimeout(resolve, 200));

// Export session A state
console.log("Exporting session A state...");
const stateBuffer = sctpA.exportState();
console.log(`Exported state size: ${stateBuffer.length} bytes`);

// Create new transport for restored session with a new port
const newClientPort = await randomPort();
console.log(`New client port for migration: ${newClientPort}`);

const transportA2 = createUdpTransport(createSocket("udp4").bind(newClientPort), {
port: serverPort,
address: "127.0.0.1",
});

// Restore session from exported state
console.log("Restoring session from exported state...");
const sctpA2 = SCTP.restoreState(stateBuffer, transportA2);

// Update server's remote port to communicate with the new client
sctpB.setRemotePort(newClientPort);

console.log("Session migrated successfully");
console.log(`Original session state: ${sctpA.state}`);
console.log(`Restored session state: ${sctpA2.state}`);
console.log(`Restored session is server: ${sctpA2.isServer}`);
console.log(`Restored session port: ${sctpA2.port}`);
console.log(`Restored session max channels: ${sctpA2.maxChannels}`);

// Stop original session
await sctpA.stop();
console.log("Original session stopped");

// Send data from restored session
await sctpA2.send(0, WEBRTC_PPID.STRING, Buffer.from("Hello from migrated session A"));
console.log("Sent data from migrated session on stream 0");

await sctpA2.send(1, WEBRTC_PPID.STRING, Buffer.from("Migrated stream 1 data"));
console.log("Sent data from migrated session on stream 1");

// Wait for messages to be received
await new Promise(resolve => setTimeout(resolve, 200));

// Clean up
await sctpA2.stop();
await sctpB.stop();

console.log("Session migration example completed successfully");
}

if (require.main === module) {
main().catch(console.error);
}
4 changes: 3 additions & 1 deletion packages/sctp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
"dependencies": {
"@shinyoshiaki/jspack": "^0.0.6",
"lodash": "^4.17.21",
"msgpack-lite": "^0.1.26",
"turbo-crc32": "^1.0.1"
},
"devDependencies": {
"@types/lodash": "^4.17.15"
"@types/lodash": "^4.17.15",
"@types/msgpack-lite": "^0.1.11"
},
"engines": {
"node": ">=10"
Expand Down
Loading