zero-trust-application-channel 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -2
- package/dist/audit/index.d.ts +2 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/interface.d.ts +29 -0
- package/dist/audit/interface.d.ts.map +1 -0
- package/dist/channel/index.d.ts +3 -0
- package/dist/channel/index.d.ts.map +1 -0
- package/dist/channel/interface.d.ts +63 -0
- package/dist/channel/interface.d.ts.map +1 -0
- package/dist/channel/ws-socket-client.d.ts +36 -0
- package/dist/channel/ws-socket-client.d.ts.map +1 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/tunnel-client.d.ts +99 -0
- package/dist/client/tunnel-client.d.ts.map +1 -0
- package/dist/codec/frame-codec.d.ts +26 -0
- package/dist/codec/frame-codec.d.ts.map +1 -0
- package/dist/codec/index.d.ts +4 -0
- package/dist/codec/index.d.ts.map +1 -0
- package/dist/codec/types.d.ts +51 -0
- package/dist/codec/types.d.ts.map +1 -0
- package/dist/connector/index.d.ts +5 -0
- package/dist/connector/index.d.ts.map +1 -0
- package/dist/connector/reconnect-delay.d.ts +32 -0
- package/dist/connector/reconnect-delay.d.ts.map +1 -0
- package/dist/connector/tunnel-connector.d.ts +128 -0
- package/dist/connector/tunnel-connector.d.ts.map +1 -0
- package/dist/demo/hub-harness.d.ts +31 -0
- package/dist/demo/hub-harness.d.ts.map +1 -0
- package/dist/hub/index.d.ts +3 -0
- package/dist/hub/index.d.ts.map +1 -0
- package/dist/hub/registry.d.ts +45 -0
- package/dist/hub/registry.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1922 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/interface.d.ts +19 -0
- package/dist/logger/interface.d.ts.map +1 -0
- package/dist/protocol/index.d.ts +2 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/messages.d.ts +226 -0
- package/dist/protocol/messages.d.ts.map +1 -0
- package/dist/proxy/hub-session-store.d.ts +55 -0
- package/dist/proxy/hub-session-store.d.ts.map +1 -0
- package/dist/proxy/index.d.ts +8 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/session-gateway.d.ts +85 -0
- package/dist/proxy/session-gateway.d.ts.map +1 -0
- package/dist/proxy/stream-sink.d.ts +18 -0
- package/dist/proxy/stream-sink.d.ts.map +1 -0
- package/dist/proxy/tunnel-proxy.d.ts +126 -0
- package/dist/proxy/tunnel-proxy.d.ts.map +1 -0
- package/dist/result/domain-error.d.ts +50 -0
- package/dist/result/domain-error.d.ts.map +1 -0
- package/dist/result/index.d.ts +4 -0
- package/dist/result/index.d.ts.map +1 -0
- package/dist/result/result.d.ts +24 -0
- package/dist/result/result.d.ts.map +1 -0
- package/dist/session/__test-helpers__/jose-signer.d.ts +13 -0
- package/dist/session/__test-helpers__/jose-signer.d.ts.map +1 -0
- package/dist/session/__test-helpers__/jose-signer.js +30 -0
- package/dist/session/client-session-server.d.ts +23 -0
- package/dist/session/client-session-server.d.ts.map +1 -0
- package/dist/session/client-session-store.d.ts +59 -0
- package/dist/session/client-session-store.d.ts.map +1 -0
- package/dist/session/index.d.ts +4 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/token/index.d.ts +2 -0
- package/dist/token/index.d.ts.map +1 -0
- package/dist/token/interface.d.ts +18 -0
- package/dist/token/interface.d.ts.map +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +61 -4
package/README.md
CHANGED
|
@@ -1,3 +1,68 @@
|
|
|
1
|
-
#
|
|
1
|
+
# zero-trust-application-channel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Jenerik, çoklanmış WebSocket tüneli — tek outbound bağlantı üzerinden HTTP/WS
|
|
4
|
+
reverse proxy + oturum yönetimi. GD-PMS monorepo'sundan **bağımsız bir
|
|
5
|
+
kütüphanedir** (tamper-logger deseni; ayrıntı:
|
|
6
|
+
`../docs/LIB-MIMARISI.md`). Domain adapter'leri
|
|
7
|
+
(Fastify/PG/ContainerProxy) tüketici projede yaşar.
|
|
8
|
+
|
|
9
|
+
**İki deployment, tek paket (v2):** aynı jenerik paket hem
|
|
10
|
+
**field→container** hem **field→boss** topolojisinde çalışır — register şeması
|
|
11
|
+
nötr `peerId`+`peerType`, oturum/cookie/allowlist config'le enjekte edilir
|
|
12
|
+
(ayrıntı: `../docs/CONTRACTS.md`).
|
|
13
|
+
|
|
14
|
+
## İçerik
|
|
15
|
+
|
|
16
|
+
| Modül | Görev |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `codec` | Binary frame codec — 9 bayt başlık (streamId u32 BE + seq u32 BE + flags FIN/RST/WS_OP); `decode` asla throw etmez (`Result`) |
|
|
19
|
+
| `protocol` | Kontrol mesaj tipleri + zod şemaları (register/ack — v2 `peerId`+`peerType`, heartbeat, telemetry, stream-*, open-session/*); `TUNNEL_PROTOCOL_VERSION = 2` |
|
|
20
|
+
| `connector` | `TunnelConnector` — outbound WS istemcisi + durum makinesi + üstel backoff (`ReconnectDelay`) |
|
|
21
|
+
| `channel` | `ISocketClient`/`WsSocketClient` (ws adapter), `ITunnelChannel` (client ucu), `IHubChannel` (hub ucu — peerId'li) |
|
|
22
|
+
| `client` | `TunnelClient` — stream multiplex, kredi bazlı backpressure, çift upstream yönlendirme, WS köprüsü |
|
|
23
|
+
| `session` | `ClientSessionStore` + `ClientSessionServer` — geçici oturum JWT'si (`ITokenSigner` enjeksiyonu) |
|
|
24
|
+
| `proxy` | `SessionGateway` + `HubSessionStore` + `TunnelProxy` — hub tarafı oturum + HTTP/WS proxy (`IHubChannel`/`IStreamSink`/`IAuditSink` enjeksiyonu; cookieName + PathAllowlist config'i) |
|
|
25
|
+
| `logger` / `token` / `audit` / `snapshot` / `types` | Bağımsızlık sözleşmeleri — minimal `ILogger`, `ITokenSigner`, `IAuditSink`, `ISnapshotSource`, jenerik `TunnelRole`/`TunnelUser`/`TunnelTelemetryPoint` |
|
|
26
|
+
|
|
27
|
+
## Bağımlılıklar
|
|
28
|
+
|
|
29
|
+
`ws`, `zod`, `@gd-monorepo/result` — başka bir şey yok. (`jose` yalnızca
|
|
30
|
+
devDependency — test yardımcısı; üretim kodu `ITokenSigner` enjeksiyonuyla
|
|
31
|
+
çalışır.)
|
|
32
|
+
|
|
33
|
+
## Örnek — loopback uçtan uca (monorepo'suz)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bun lib/examples/loopback-demo.mjs
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Paket içi demo: `HubHarness` (hub ucu) ↔ `TunnelConnector` + `TunnelClient`
|
|
40
|
+
(client ucu) ↔ `SessionGateway` + `TunnelProxy` — tek gerçek WS kanalında
|
|
41
|
+
register → oturum → tünel HTTP → WS köprüsü. Aynı akış test olarak da çalışır:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bun nx run lib:test # loopback.spec.ts dahil
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Test & kalite kapıları
|
|
48
|
+
|
|
49
|
+
- `nx run lib:test` — unit + spec + loopback uçtan uca
|
|
50
|
+
- `nx run lib:typecheck` — `tsc --noEmit` (test dosyaları hariç)
|
|
51
|
+
- Güvenlik-kritik modüller (codec, connector, client, proxy) branch kapsamı ≥ %90 hedeflenir
|
|
52
|
+
|
|
53
|
+
## Sözleşme özeti
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// Client ucu: TunnelConnector zaten ITunnelChannel'dır
|
|
57
|
+
const client = TunnelClient.create({ webServiceUrl, staticUrl });
|
|
58
|
+
client.attach(connector);
|
|
59
|
+
|
|
60
|
+
// Hub ucu: IHubChannel adapter'i (ör. paket içi HubHarness veya
|
|
61
|
+
// tüketicinin ContainerProxy sarmalayıcısı) + IStreamSink (tüketicinin
|
|
62
|
+
// HTTP framework adapter'i) + IAuditSink + ITokenSigner enjekte edilir
|
|
63
|
+
const gateway = new SessionGateway(channel, store, audit, logger);
|
|
64
|
+
const proxy = new TunnelProxy(channel, store, logger);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Tünel rolü YORUMLAMAZ: `TunnelRole` serbest string'dir — eşleme ve RBAC
|
|
68
|
+
tüketiciye aittir. Detaylı protokol: `../docs/deprecated/KONTEYNER-UZAKTAN-ERISIM-MIMARISI.md`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TunnelRole } from "../types";
|
|
2
|
+
/** Oturum açılış kaydı — audit sink'ine verilir. */
|
|
3
|
+
export interface SessionAuditOpenRecord {
|
|
4
|
+
hubId: string;
|
|
5
|
+
peerId: string;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
username: string;
|
|
8
|
+
callerRole: TunnelRole;
|
|
9
|
+
peerRole: TunnelRole;
|
|
10
|
+
remoteIp?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Oturum kapanış kaydı. */
|
|
13
|
+
export interface SessionAuditCloseRecord {
|
|
14
|
+
sessionId: string;
|
|
15
|
+
endReason: string;
|
|
16
|
+
bytesIn: number;
|
|
17
|
+
bytesOut: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* IAuditSink — oturum denetim kaydı sözleşmesi (fail-closed):
|
|
21
|
+
* `open` hata fırlatırsa oturum AÇILMAZ; `close` kapanışta çağrılır
|
|
22
|
+
* (hata yutulur + logger'a bildirilir).
|
|
23
|
+
* Monorepo implementasyonu: `SessionAudit` (web-service, PG + TamperLogger).
|
|
24
|
+
*/
|
|
25
|
+
export interface IAuditSink {
|
|
26
|
+
open(record: SessionAuditOpenRecord): Promise<void>;
|
|
27
|
+
close(record: SessionAuditCloseRecord): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/audit/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,oDAAoD;AACpD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4BAA4B;AAC5B,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,KAAK,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/channel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ISocketClient — tünelin kullandığı soket görünümü (jenerik).
|
|
3
|
+
* `ws` paketi `WsSocketClient` adapter'iyle gerçeklenir; testlerde fake soket
|
|
4
|
+
* enjekte edilir (Strategy).
|
|
5
|
+
*/
|
|
6
|
+
export interface ISocketClient {
|
|
7
|
+
/** Text frame gönderir (kontrol mesajı JSON). */
|
|
8
|
+
send(data: string): void;
|
|
9
|
+
/** Binary frame gönderir (tünel akış verisi — 9 bayt başlık + payload). */
|
|
10
|
+
sendBinary(data: Uint8Array): void;
|
|
11
|
+
/** WS protokol seviyesi ping — liveness tespiti için (pong beklenir). */
|
|
12
|
+
ping(): void;
|
|
13
|
+
/** Soketi kapatır. */
|
|
14
|
+
close(): void;
|
|
15
|
+
/** Bağlantı açıldı (upgrade tamam). */
|
|
16
|
+
onOpen(callback: () => void): void;
|
|
17
|
+
/** Text mesajı alındı. */
|
|
18
|
+
onMessage(callback: (raw: string) => void): void;
|
|
19
|
+
/** Binary mesajı alındı (tünel akış frame'leri). */
|
|
20
|
+
onBinaryMessage(callback: (data: Buffer) => void): void;
|
|
21
|
+
/** Bağlantı kapandı (her koşulda — hata sonrası dahil). */
|
|
22
|
+
onClose(callback: () => void): void;
|
|
23
|
+
/** Soket hatası — ardından onClose da tetiklenir. */
|
|
24
|
+
onError(callback: (error: Error) => void): void;
|
|
25
|
+
/** Pong alındı — liveness saati sıfırlanır. */
|
|
26
|
+
onPong(callback: () => void): void;
|
|
27
|
+
/**
|
|
28
|
+
* Pre-upgrade ret — sunucu upgrade'i reddetti (örn. 401 service token).
|
|
29
|
+
* `statusCode` HTTP yanıt kodudur.
|
|
30
|
+
*/
|
|
31
|
+
onRejected(callback: (statusCode: number) => void): void;
|
|
32
|
+
/** Güncel hazırlık durumu. */
|
|
33
|
+
readyState(): "connecting" | "open" | "closing" | "closed";
|
|
34
|
+
}
|
|
35
|
+
/** Soket üretici sözleşmesi — URL + auth header'ları ile client oluşturur. */
|
|
36
|
+
export interface ISocketClientFactory {
|
|
37
|
+
create(url: string, headers: Record<string, string>, protocols?: string[]): ISocketClient;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* ITunnelChannel — client tarafı kanal (TEK outbound bağlantı).
|
|
41
|
+
* TunnelConnector bu sözleşmeyi uygular; TunnelClient `attach(channel)` ile
|
|
42
|
+
* tünel akışlarını aynı WS üzerinden çoklar.
|
|
43
|
+
*/
|
|
44
|
+
export interface ITunnelChannel {
|
|
45
|
+
onMessage(subscriber: (message: unknown) => void): () => void;
|
|
46
|
+
onBinaryFrame(subscriber: (data: Buffer) => void): () => void;
|
|
47
|
+
sendControl(message: unknown): void;
|
|
48
|
+
sendBinary(data: Buffer): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* IHubChannel — hub tarafı kanal (peer başına peerId).
|
|
52
|
+
* Monorepo implementasyonu: `ContainerProxyFieldChannel` (ContainerProxy
|
|
53
|
+
* adapter'i — sendControl/sendBinary/observer + bağlantı durumu).
|
|
54
|
+
* İkinci deployment (boss uplink) aynı sözleşmeyi field kayıtları için uygular.
|
|
55
|
+
*/
|
|
56
|
+
export interface IHubChannel {
|
|
57
|
+
sendControl(peerId: string, message: unknown): void;
|
|
58
|
+
sendBinary(peerId: string, data: Buffer): void;
|
|
59
|
+
onControlMessage(subscriber: (peerId: string, message: unknown) => void): () => void;
|
|
60
|
+
onBinaryFrame(subscriber: (peerId: string, data: Buffer) => void): () => void;
|
|
61
|
+
isConnected(peerId: string): boolean;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/channel/interface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,2EAA2E;IAC3E,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACnC,yEAAyE;IACzE,IAAI,IAAI,IAAI,CAAC;IACb,sBAAsB;IACtB,KAAK,IAAI,IAAI,CAAC;IACd,uCAAuC;IACvC,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACnC,0BAA0B;IAC1B,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACjD,oDAAoD;IACpD,eAAe,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACxD,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACpC,qDAAqD;IACrD,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAChD,+CAA+C;IAC/C,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACnC;;;OAGG;IACH,UAAU,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACzD,8BAA8B;IAC9B,UAAU,IAAI,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;CAC5D;AAED,8EAA8E;AAC9E,MAAM,WAAW,oBAAoB;IACnC,MAAM,CACJ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,aAAa,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC9D,aAAa,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC9D,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACpD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACrF,aAAa,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC9E,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CACtC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { WebSocket } from "ws";
|
|
2
|
+
import type { ISocketClient, ISocketClientFactory } from "./interface";
|
|
3
|
+
/**
|
|
4
|
+
* WsSocketClient — `ws` paketi istemcisini `ISocketClient`'a uyarlar (Adapter).
|
|
5
|
+
* TunnelConnector bu sözleşme üzerinden çalışır; testlerde fake soket enjekte
|
|
6
|
+
* edilir. `unexpected-response` (pre-upgrade ret — 401/403) `onRejected`'a
|
|
7
|
+
* çevrilir; statusCode yoksa 0 iletilir.
|
|
8
|
+
*/
|
|
9
|
+
export declare class WsSocketClient implements ISocketClient {
|
|
10
|
+
private readonly raw;
|
|
11
|
+
constructor(raw: WebSocket);
|
|
12
|
+
send(data: string): void;
|
|
13
|
+
sendBinary(data: Uint8Array): void;
|
|
14
|
+
ping(): void;
|
|
15
|
+
close(): void;
|
|
16
|
+
onOpen(callback: () => void): void;
|
|
17
|
+
onMessage(callback: (raw: string) => void): void;
|
|
18
|
+
onBinaryMessage(callback: (data: Buffer) => void): void;
|
|
19
|
+
onClose(callback: () => void): void;
|
|
20
|
+
onError(callback: (error: Error) => void): void;
|
|
21
|
+
onPong(callback: () => void): void;
|
|
22
|
+
onRejected(callback: (statusCode: number) => void): void;
|
|
23
|
+
readyState(): "connecting" | "open" | "closing" | "closed";
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* WsSocketClientFactory — `ws` WebSocket üreticisi. Creator testlerde fake
|
|
27
|
+
* enjekte edilir; üretimde varsayılan creator gerçek `ws` istemcisini kurar.
|
|
28
|
+
*/
|
|
29
|
+
export declare class WsSocketClientFactory implements ISocketClientFactory {
|
|
30
|
+
private readonly creator;
|
|
31
|
+
constructor(creator?: (url: string, protocols: string[], options: {
|
|
32
|
+
headers: Record<string, string>;
|
|
33
|
+
}) => WebSocket);
|
|
34
|
+
create(url: string, headers: Record<string, string>, protocols?: string[]): ISocketClient;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=ws-socket-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-socket-client.d.ts","sourceRoot":"","sources":["../../src/channel/ws-socket-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AASvE;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,aAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,SAAS;IAE3C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAIlC,IAAI,IAAI,IAAI;IAIZ,KAAK,IAAI,IAAI;IAIb,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAOhD,eAAe,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAOvD,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAInC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI/C,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,UAAU,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAMxD,UAAU,IAAI,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ;CAM3D;AAED;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,oBAAoB;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAIT;gBAKb,OAAO,CAAC,EAAE,CACR,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,KACzC,SAAS;IAOhB,MAAM,CACJ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,GAAE,MAAM,EAAO,GACvB,aAAa;CAGjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { ISocketClientFactory, ITunnelChannel } from "../channel";
|
|
2
|
+
/** TunnelClient yapılandırması — opsiyonel alanlar testlerde enjekte edilir. */
|
|
3
|
+
export interface TunnelClientConfig {
|
|
4
|
+
/** API upstream taban URL'i (varsayılan kural: `/api/*`, `/ws/*`). */
|
|
5
|
+
webServiceUrl: string;
|
|
6
|
+
/** Statik/SPA upstream taban URL'i (varsayılan kural: diğer yollar). */
|
|
7
|
+
staticUrl: string;
|
|
8
|
+
/**
|
|
9
|
+
* Upstream yönlendirici — opsiyonel. Verilmezse varsayılan kural uygulanır
|
|
10
|
+
* (`/api/*`,`/ws/*` → webServiceUrl, diğer → staticUrl). Tüketici kendi
|
|
11
|
+
* yönlendirme politikasını enjekte edebilir.
|
|
12
|
+
*/
|
|
13
|
+
routeUpstream?: (path: string) => string;
|
|
14
|
+
/** Akış kredisi pencere boyutu (tasarım §5.2: 256 KiB). */
|
|
15
|
+
windowSize?: number;
|
|
16
|
+
/** Eşzamanlı akış tavanı (tasarım §5.6: 16). */
|
|
17
|
+
maxStreams?: number;
|
|
18
|
+
/** Frame parça boyutu (tasarım §5.2: ≤64 KiB). */
|
|
19
|
+
chunkSize?: number;
|
|
20
|
+
/** İstek gövdesi tavanı (POST/PUT) — aşımı RST + kapatma. */
|
|
21
|
+
maxRequestBody?: number;
|
|
22
|
+
/** Akış boşta kalma süresi (ms) — §12.4 her stream için idle timeout. */
|
|
23
|
+
idleTimeoutMs?: number;
|
|
24
|
+
/** Akış azami yaşı (ms) — §12.4 max yaş. */
|
|
25
|
+
maxAgeMs?: number;
|
|
26
|
+
/** Sweep aralığı (ms). */
|
|
27
|
+
sweepIntervalMs?: number;
|
|
28
|
+
/** Loopback WS üretici — testlerde fake; üretimde `ws`. */
|
|
29
|
+
socketFactory?: ISocketClientFactory;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* TunnelClient — client/peer tarafı akış multiplexer'ı.
|
|
33
|
+
*
|
|
34
|
+
* - `stream-open` frame'lerini alır, stream'leri upstream'e dağıtır:
|
|
35
|
+
* varsayılan kural `/api/*`, `/ws/*` → API upstream; diğer her şey → statik
|
|
36
|
+
* upstream. `routeUpstream` ile değiştirilebilir.
|
|
37
|
+
* - Undici fetch stream'lerini ≤64 KiB binary frame'lere böler; `stream-window`
|
|
38
|
+
* kredisiyle backpressure uygular (kredi yoksa gövde DURUR — §5.2).
|
|
39
|
+
* - `upgrade:"websocket"` → loopback WS köprüsü; mesaj sınırları ve opcode'lar
|
|
40
|
+
* WS_OP bayrağıyla korunur (§5.3).
|
|
41
|
+
* - Limitler: eşzamanlı akış tavanı → 503; boşta kalma/max yaş sweep'i;
|
|
42
|
+
* `stream-close` → iptal.
|
|
43
|
+
*/
|
|
44
|
+
export declare class TunnelClient {
|
|
45
|
+
private readonly config;
|
|
46
|
+
private readonly codec;
|
|
47
|
+
private readonly socketFactory;
|
|
48
|
+
private readonly routeUpstream;
|
|
49
|
+
private readonly streams;
|
|
50
|
+
private sweepTimer?;
|
|
51
|
+
private channel?;
|
|
52
|
+
private constructor();
|
|
53
|
+
static create(config: TunnelClientConfig): TunnelClient;
|
|
54
|
+
/** TunnelConnector kanalına abone olur (kontrol + binary). */
|
|
55
|
+
attach(channel: ITunnelChannel): void;
|
|
56
|
+
/** Tüm akışları kapatır ve sweep'i durdurur (komut). */
|
|
57
|
+
stop(): void;
|
|
58
|
+
private handleControl;
|
|
59
|
+
private onStreamOpen;
|
|
60
|
+
private handleBinaryFrame;
|
|
61
|
+
private onWsDataFrame;
|
|
62
|
+
private onBodyFrame;
|
|
63
|
+
/** HTTP akışı: loopback fetch → ack → kredi kontrollü gövde frame'leri. */
|
|
64
|
+
private fetchStream;
|
|
65
|
+
/** Gövde parçasını kredi kontrollü gönderir — kredi yoksa bekler. */
|
|
66
|
+
private sendPayload;
|
|
67
|
+
private sendFin;
|
|
68
|
+
private openWsBridge;
|
|
69
|
+
private awaitCredit;
|
|
70
|
+
private drainWaiting;
|
|
71
|
+
private sendRst;
|
|
72
|
+
private closeStream;
|
|
73
|
+
private sweep;
|
|
74
|
+
private now;
|
|
75
|
+
}
|
|
76
|
+
/** Varsayılan yönlendirme kuralı: `/api|/ws` → API upstream, diğer → statik. */
|
|
77
|
+
export declare function upstreamUrl(path: string, webServiceUrl: string, staticUrl: string): string;
|
|
78
|
+
/** Yanıt başlıklarını hop-by-hop başlıklardan arındırır. */
|
|
79
|
+
export declare function filterHeaders(headers: Headers): Record<string, string>;
|
|
80
|
+
/**
|
|
81
|
+
* Upstream WS URL'inden tarayıcı-origin'i üretir (sorgu — saf):
|
|
82
|
+
* `wss://` → `https://`, `ws://` → `http://` (WHATWG origin ws için
|
|
83
|
+
* http-eşdeğerini bekler; tarayıcı da wss bağlantısında `https://` yollar).
|
|
84
|
+
* Upstream handshake'inde `Origin` olarak kullanılır — Host ile eşleşir.
|
|
85
|
+
*/
|
|
86
|
+
export declare function wsOrigin(url: string): string;
|
|
87
|
+
/**
|
|
88
|
+
* Tarayıcının önerdiği subprotocol listesini ayrıştırır (RFC 6455):
|
|
89
|
+
* `Sec-WebSocket-Protocol: a, b` → `["a","b"]`. Upstream handshake'ine
|
|
90
|
+
* `protocols` olarak verilir (app-bağımsız — cockpit1, graphql-ws, mqtt...).
|
|
91
|
+
*/
|
|
92
|
+
export declare function requestedSubprotocols(header: string | undefined): string[];
|
|
93
|
+
/**
|
|
94
|
+
* Upstream WS handshake'ine taşınacak başlıkları süzer: hop-by-hop ve el
|
|
95
|
+
* sıkışmasına özgü başlıklar çıkarılır (yeni handshake kendi anahtarını
|
|
96
|
+
* üretir); `cookie`/`authorization` gibi uygulama başlıkları geçer.
|
|
97
|
+
*/
|
|
98
|
+
export declare function wsHandshakeHeaders(headers: Record<string, string> | undefined): Record<string, string>;
|
|
99
|
+
//# sourceMappingURL=tunnel-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel-client.d.ts","sourceRoot":"","sources":["../../src/client/tunnel-client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAiB,cAAc,EAAE,MAAM,YAAY,CAAC;AAEtF,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAuCD;;;;;;;;;;;;GAYG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAarB;IACF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuB;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2B;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,UAAU,CAAC,CAAiC;IACpD,OAAO,CAAC,OAAO,CAAC,CAAiB;IAIjC,OAAO;IAkBP,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY;IAIvD,8DAA8D;IAC9D,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAOrC,wDAAwD;IACxD,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,YAAY;IA0CpB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,WAAW;IAenB,2EAA2E;YAC7D,WAAW;IA8DzB,qEAAqE;YACvD,WAAW;IAyBzB,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,YAAY;YAmEN,WAAW;IASzB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,KAAK;IAYb,OAAO,CAAC,GAAG;CAGZ;AAMD,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAI1F;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOtE;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,EAAE,CAMV;AAaD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAC1C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ValidationError, Result } from "../result";
|
|
2
|
+
import type { TunnelFrame } from "./types";
|
|
3
|
+
/** Frame çözümleme hatası — beklenen (güvenilmez WS girdisi), Result ile taşınır. */
|
|
4
|
+
export declare class FrameDecodeError extends ValidationError {
|
|
5
|
+
constructor(reason: string);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* FrameCodec — tünel binary frame codec'i (tasarım §4.2).
|
|
9
|
+
*
|
|
10
|
+
* - `encode(frame)`: programcı hatası (aralık dışı streamId/seq, hatalı
|
|
11
|
+
* opcode-flag birleşimi) throw eder — bunlar protokol verisi değildir.
|
|
12
|
+
* - `decode(buffer, maxPayload?)`: girdi güvenilmezdir; HİÇBİR durumda throw
|
|
13
|
+
* etmez — kısa/çok-büyük frame `Result.err(FrameDecodeError)` döner.
|
|
14
|
+
* İkisi birden (throw ve Result) bilinçli hibrittir (bkz. Faz 0 ek 2).
|
|
15
|
+
*/
|
|
16
|
+
export declare class FrameCodec {
|
|
17
|
+
/** Frame'i 9 bayt başlık + payload olarak serileştirir. */
|
|
18
|
+
encode(frame: TunnelFrame): Buffer;
|
|
19
|
+
/**
|
|
20
|
+
* Ham baytları frame'e çözer. Kısa girdi veya `maxPayload` aşımı → Err;
|
|
21
|
+
* aksi halde Ok. WS_OP yokken `opcode` undefined döner; bilinmeyen opcode
|
|
22
|
+
* değerleri korunur (ileri uyumluluk).
|
|
23
|
+
*/
|
|
24
|
+
decode(buffer: Uint8Array, maxPayload?: number): Result<TunnelFrame, FrameDecodeError>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=frame-codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-codec.d.ts","sourceRoot":"","sources":["../../src/codec/frame-codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAMpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,qFAAqF;AACrF,qBAAa,gBAAiB,SAAQ,eAAe;gBACvC,MAAM,EAAE,MAAM;CAG3B;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAU;IACrB,2DAA2D;IAC3D,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM;IA6BlC;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,GAAE,MAA0B,GAAG,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC;CA+B1G"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/codec/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tünel akış frame'i tipleri — tasarım §4.2.
|
|
3
|
+
*
|
|
4
|
+
* Binary frame düzeni (9 bayt başlık + payload):
|
|
5
|
+
* ```
|
|
6
|
+
* 0 4 8 9
|
|
7
|
+
* ┌────────┬────────┬───┬────────────────────────┐
|
|
8
|
+
* │ streamId (u32 BE) │ seq (u32 BE) │flags│ payload (ham bayt)
|
|
9
|
+
* └────────┴────────┴───┴────────────────────────┘
|
|
10
|
+
* flags: 0x01 FIN · 0x02 RST · 0x04 WS_OP
|
|
11
|
+
* WS_OP varken sonraki 4 bit opcode: 0x0 veri, 0x1 text, 0x2 binary,
|
|
12
|
+
* 0x8 close, 0x9 ping, 0xA pong
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* - `streamId`: oturum açan taraf (field) atar, monoton artan.
|
|
16
|
+
* - `seq`: akış içi sıra (güvenilir WS üzerinde kayıp olmaz; teşhis amaçlı).
|
|
17
|
+
* - `WS_OP`: tünel WS akışlarında mesaj sınırları ve opcode'lar korunur.
|
|
18
|
+
*/
|
|
19
|
+
/** Başlık boyutu: streamId (4) + seq (4) + flags (1). */
|
|
20
|
+
export declare const FRAME_HEADER_SIZE = 9;
|
|
21
|
+
/** Frame başına azami payload — 64 KiB parçalar (tasarım §5.2). */
|
|
22
|
+
export declare const MAX_CHUNK_SIZE: number;
|
|
23
|
+
/** decode() güvenlik sınırı — 1 MiB üstü frame reddedilir. */
|
|
24
|
+
export declare const MAX_FRAME_PAYLOAD: number;
|
|
25
|
+
/** flags bitleri. */
|
|
26
|
+
export declare const FLAG_FIN = 1;
|
|
27
|
+
export declare const FLAG_RST = 2;
|
|
28
|
+
export declare const FLAG_WS_OP = 4;
|
|
29
|
+
/** WS_OP varken taşınan WS opcode değerleri (RFC 6455 alt kümesi). */
|
|
30
|
+
export declare const WS_OPCODE: {
|
|
31
|
+
readonly Data: 0;
|
|
32
|
+
readonly Text: 1;
|
|
33
|
+
readonly Binary: 2;
|
|
34
|
+
readonly Close: 8;
|
|
35
|
+
readonly Ping: 9;
|
|
36
|
+
readonly Pong: 10;
|
|
37
|
+
};
|
|
38
|
+
/** Bir tünel akış frame'i. `opcode` yalnızca WS_OP flag'i set iken anlamlıdır. */
|
|
39
|
+
export interface TunnelFrame {
|
|
40
|
+
/** Akış kimliği — 0..2^32-1. */
|
|
41
|
+
streamId: number;
|
|
42
|
+
/** Akış içi sıra numarası — 0..2^32-1. */
|
|
43
|
+
seq: number;
|
|
44
|
+
/** FIN|RST|WS_OP bitlerinin birleşimi (WS_OP varken yüksek 4 bit opcode taşır). */
|
|
45
|
+
flags: number;
|
|
46
|
+
/** WS_OP set iken WS opcode (0-15); diğer durumda undefined. */
|
|
47
|
+
opcode?: number;
|
|
48
|
+
/** Ham payload baytları. */
|
|
49
|
+
payload: Uint8Array;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/codec/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,yDAAyD;AACzD,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,mEAAmE;AACnE,eAAO,MAAM,cAAc,QAAY,CAAC;AAExC,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAE7C,qBAAqB;AACrB,eAAO,MAAM,QAAQ,IAAO,CAAC;AAC7B,eAAO,MAAM,QAAQ,IAAO,CAAC;AAC7B,eAAO,MAAM,UAAU,IAAO,CAAC;AAE/B,sEAAsE;AACtE,eAAO,MAAM,SAAS;;;;;;;CAOZ,CAAC;AAEX,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,OAAO,EAAE,UAAU,CAAC;CACrB"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { TunnelConnector } from "./tunnel-connector";
|
|
2
|
+
export type { TunnelConnectorConfig } from "./tunnel-connector";
|
|
3
|
+
export { ReconnectDelay } from "./reconnect-delay";
|
|
4
|
+
export type { ReconnectDelayConfig } from "./reconnect-delay";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/connector/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** ReconnectDelay yapılandırması — tüm alanlar zorunlu (birincil constructor). */
|
|
2
|
+
export interface ReconnectDelayConfig {
|
|
3
|
+
/** Taban gecikme (ms) — attempt 1'deki değer. */
|
|
4
|
+
baseMs: number;
|
|
5
|
+
/** Maksimum gecikme (ms) — üstel büyüme bu değeri aşamaz. */
|
|
6
|
+
maxMs: number;
|
|
7
|
+
/** Jitter açıklığı (ms) — [0, jitterSpanMs) aralığında ekleme. */
|
|
8
|
+
jitterSpanMs: number;
|
|
9
|
+
/** [0, 1) aralığında rastgele değer üretici — testlerde deterministik enjekte edilir. */
|
|
10
|
+
jitter: () => number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* ReconnectDelay — üstel backoff hesaplayıcı (tasarım §6):
|
|
14
|
+
*
|
|
15
|
+
* `delayFor(attempt)` = `min(maxMs, baseMs · 2^(attempt-1) + jitter() · jitterSpanMs)`.
|
|
16
|
+
* `reset()` başarılı bağlantıda çağrılır — bir sonraki kopuş yeniden tabandan başlar
|
|
17
|
+
* (reconnect fırtınası önlenir, tasarım §12.4).
|
|
18
|
+
*
|
|
19
|
+
* Immutable — durum yalnızca `reset()` komutuyla değişir (Elegant Object kural 3).
|
|
20
|
+
*/
|
|
21
|
+
export declare class ReconnectDelay {
|
|
22
|
+
private readonly baseMs;
|
|
23
|
+
private readonly maxMs;
|
|
24
|
+
private readonly jitterSpanMs;
|
|
25
|
+
private readonly jitter;
|
|
26
|
+
constructor(config: ReconnectDelayConfig);
|
|
27
|
+
/** `attempt` (1 tabanlı) için beklenmesi gereken gecikmeyi döndürür (ms). */
|
|
28
|
+
delayFor(attempt: number): number;
|
|
29
|
+
/** Başarılı bağlantıda çağrılır — bir sonraki kopuş tabandan başlar. */
|
|
30
|
+
reset(): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=reconnect-delay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnect-delay.d.ts","sourceRoot":"","sources":["../../src/connector/reconnect-delay.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAC;IACrB,yFAAyF;IACzF,MAAM,EAAE,MAAM,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,oBAAoB;IA4BxC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAoBjC,wEAAwE;IACxE,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { TunnelConnectorState, ServiceAnnouncement, TunnelPeerType } from "../protocol";
|
|
2
|
+
import type { ILogger } from "../logger";
|
|
3
|
+
import type { ISocketClientFactory, ITunnelChannel } from "../channel";
|
|
4
|
+
import type { ReconnectDelay } from "./reconnect-delay";
|
|
5
|
+
/** TunnelConnector yapılandırması — bootstrap env'den türetilir (tasarım §6.1). */
|
|
6
|
+
export interface TunnelConnectorConfig {
|
|
7
|
+
/** Hub WS URL listesi — sırayla denenir (ana + yedek). */
|
|
8
|
+
wsUrls: readonly string[];
|
|
9
|
+
/** Service token — upgrade'de `Authorization: Bearer` header'ı olarak taşınır. */
|
|
10
|
+
token: string;
|
|
11
|
+
/** Peer kimliği — register mesajının `peerId` alanı. */
|
|
12
|
+
peerId: string;
|
|
13
|
+
/** Peer türü — hub kayıt/doğrulama tarafını seçer. Varsayılan: "container". */
|
|
14
|
+
peerType?: TunnelPeerType;
|
|
15
|
+
/**
|
|
16
|
+
* Peer'ın sunduğu OPAK servisler (opsiyonel). Register mesajına yalnızca
|
|
17
|
+
* doluysa eklenir; hub hedef adresi bilmez (bkz. ServiceAnnouncement).
|
|
18
|
+
*/
|
|
19
|
+
services?: readonly ServiceAnnouncement[];
|
|
20
|
+
/** Heartbeat gönderim aralığı (ms) — operational config ile değişebilir. */
|
|
21
|
+
heartbeatIntervalMs: number;
|
|
22
|
+
/**
|
|
23
|
+
* Log olay kodları — nötr varsayılanlar; tüketici kendi (domain) kodlarını
|
|
24
|
+
* enjekte eder. Paket domain sözlüğü bilmez.
|
|
25
|
+
*/
|
|
26
|
+
eventCodes?: Partial<TunnelConnectorEventCodes>;
|
|
27
|
+
/** Register sonrası ack bekleme süresi (ms) — aşarsa backoff. */
|
|
28
|
+
registerTimeoutMs: number;
|
|
29
|
+
/** Pong alınmazsa bağlantı yarı-ölü sayılır (ms). */
|
|
30
|
+
livenessTimeoutMs: number;
|
|
31
|
+
}
|
|
32
|
+
/** Connector log olay kodları — nötr varsayılanlar. */
|
|
33
|
+
export interface TunnelConnectorEventCodes {
|
|
34
|
+
connected: string;
|
|
35
|
+
connectionLost: string;
|
|
36
|
+
registerRejected: string;
|
|
37
|
+
configRejected: string;
|
|
38
|
+
}
|
|
39
|
+
/** Varsayılan olay kodları — transport-nötr. */
|
|
40
|
+
export declare const DEFAULT_TUNNEL_EVENT_CODES: Readonly<TunnelConnectorEventCodes>;
|
|
41
|
+
/**
|
|
42
|
+
* TunnelConnector — client→hub outbound WS istemcisi (tasarım §6).
|
|
43
|
+
*
|
|
44
|
+
* Sorumluluklar: register + heartbeat + PPC durumu (`state()`) + operational
|
|
45
|
+
* config alımı (register-ack.config / config-update — restart'sız). Tünel
|
|
46
|
+
* stream'leri aynı kanala eklenir.
|
|
47
|
+
*
|
|
48
|
+
* Domain mesajları (telemetri/operasyon/olay) TAŞIMAZ; bilinmeyen tipler
|
|
49
|
+
* `onMessage` abonelerine akar.
|
|
50
|
+
*
|
|
51
|
+
* Durum makinesi (tasarım §6 diyagramı):
|
|
52
|
+
* ```
|
|
53
|
+
* offline → connecting: start() veya backoff bitti
|
|
54
|
+
* connecting → registered: register-ack ok
|
|
55
|
+
* connecting → backoff: hata / 401 / register timeout
|
|
56
|
+
* registered → connected: ilk heartbeat gönderildi
|
|
57
|
+
* connected → backoff: WS kapandı / liveness timeout
|
|
58
|
+
* backoff → connecting: exp(2^n·1s)+jitter (ReconnectDelay)
|
|
59
|
+
* connected → offline: stop()
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* Yan etkiler: `ws` soketi (enjekte fabrikadan), ILogger (geçiş-odaklı loglar —
|
|
63
|
+
* kodlar `eventCodes` ile enjekte edilir; varsayılanlar nötrdür).
|
|
64
|
+
*/
|
|
65
|
+
export declare class TunnelConnector implements ITunnelChannel {
|
|
66
|
+
private readonly config;
|
|
67
|
+
private readonly socketFactory;
|
|
68
|
+
private readonly reconnectDelay;
|
|
69
|
+
private readonly logger?;
|
|
70
|
+
private readonly now;
|
|
71
|
+
private stateValue;
|
|
72
|
+
private socket?;
|
|
73
|
+
private generation;
|
|
74
|
+
private attempt;
|
|
75
|
+
private urlIndex;
|
|
76
|
+
private stopped;
|
|
77
|
+
private heartbeatTimer?;
|
|
78
|
+
private registerTimer?;
|
|
79
|
+
private reconnectTimer?;
|
|
80
|
+
private lastHeartbeatSentAt?;
|
|
81
|
+
private lastPongAt;
|
|
82
|
+
private operational;
|
|
83
|
+
private readonly eventCodes;
|
|
84
|
+
private readonly messageSubscribers;
|
|
85
|
+
private readonly binarySubscribers;
|
|
86
|
+
constructor(config: TunnelConnectorConfig, socketFactory: ISocketClientFactory, reconnectDelay: ReconnectDelay, logger?: ILogger | undefined, now?: () => number);
|
|
87
|
+
/** Bağlantı döngüsünü başlatır (komut). Çalışıyorsa no-op. */
|
|
88
|
+
start(): Promise<void>;
|
|
89
|
+
/** Bağlantıyı kapatır, yeniden bağlanmaz (komut). */
|
|
90
|
+
stop(): Promise<void>;
|
|
91
|
+
/** Güncel durum makinesi durumu (sorgu). */
|
|
92
|
+
state(): TunnelConnectorState;
|
|
93
|
+
/** Hub'a bağlı mı — PPC kaynağı (sorgu). */
|
|
94
|
+
connected(): boolean;
|
|
95
|
+
/** Son heartbeat'in gönderildiği zaman (ms epoch) — hiç gönderilmediyse undefined. */
|
|
96
|
+
lastHeartbeatAt(): number | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Faz 3: tünel katmanının kullandığı kontrol mesajı gönderici (komut).
|
|
99
|
+
* stream-open-ack / stream-window / stream-close / open-session-ack.
|
|
100
|
+
* WS açık değilse no-op.
|
|
101
|
+
*/
|
|
102
|
+
sendControl(message: unknown): void;
|
|
103
|
+
/** Faz 3: ham binary frame gönderici (9 bayt başlık + payload). WS açıksa. */
|
|
104
|
+
sendBinary(data: Buffer): void;
|
|
105
|
+
/**
|
|
106
|
+
* Faz 3: tünel kontrol mesajı aboneliği — TunnelConnector'ın bilmediği tipler
|
|
107
|
+
* (open-session, stream-*, session-end) abonelere iletilir. Unsubscribe
|
|
108
|
+
* fonksiyonu döner (sorgu + yan etki — abonelik kurulumu).
|
|
109
|
+
*/
|
|
110
|
+
onMessage(subscriber: (message: unknown) => void): () => void;
|
|
111
|
+
/** Faz 3: binary frame aboneliği — tünel akış verisi abonelere iletilir. */
|
|
112
|
+
onBinaryFrame(subscriber: (data: Buffer) => void): () => void;
|
|
113
|
+
private connect;
|
|
114
|
+
private tryUrl;
|
|
115
|
+
private handleMessage;
|
|
116
|
+
private sendHeartbeat;
|
|
117
|
+
private applyOperationalConfig;
|
|
118
|
+
private scheduleHeartbeat;
|
|
119
|
+
private closeAndBackoff;
|
|
120
|
+
private enterBackoff;
|
|
121
|
+
private clearTimers;
|
|
122
|
+
private registerFrame;
|
|
123
|
+
/** Peer türü — varsayılan "container" (geriye uyumluluk). */
|
|
124
|
+
private peerType;
|
|
125
|
+
private send;
|
|
126
|
+
private log;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=tunnel-connector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel-connector.d.ts","sourceRoot":"","sources":["../../src/connector/tunnel-connector.ts"],"names":[],"mappings":"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"}
|