tcpip 0.3.4 → 0.3.5

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/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10;var _chunkDVPTIOIVcjs = require('./chunk-DVPTIOIV.cjs');var _browser_wasi_shim = require('@bjorn3/browser_wasi_shim');var _dns = require('@tcpip/dns');var _wire = require('@tcpip/wire');var l=class{#e=new WeakMap;#t=new WeakMap;setOuter(e,r){this.#e.set(e,r)}setInner(e,r){this.#t.set(e,r)}getOuter(e){let r=this.#e.get(e);if(!r)throw new Error(`outer hooks not set for ${e}`);return r}getInner(e){let r=this.#t.get(e);if(!r)throw new Error(`inner hooks not set for ${e}`);return r}},R=class extends Number{constructor(e,r){super(e),this.free=r}[_chunkDVPTIOIVcjs.c](){this.free(this.valueOf())}},T=class extends Map{#e=new Map;wait(e){return new Promise(r=>{let t=_nullishCoalesce(this.#e.get(e), () => (new Set));t.add(r),this.#e.set(e,t)})}set(e,r){super.set(e,r);let t=this.#e.get(e);if(t)for(let n of t)n(r),t.delete(n);return this}};function w(o,e){let r=o.getReader();return oe(r,e)}async function*oe(o,e){try{for(;;){let{done:r,value:t}=await o.read();if(r)return t;yield t}}finally{_optionalChain([e, 'optionalAccess', _2 => _2.preventCancel])||await o.cancel(),o.releaseLock()}}var P=class extends ReadableStream{#e;constructor({lock:e,...r},t){super(r,t),this.#e=e}getReader(){let e=super.getReader();return this.locked&&_optionalChain([this, 'access', _3 => _3.#e, 'optionalCall', _4 => _4()]),e}pipeThrough(e,r){let t=super.pipeThrough(e,r);return this.locked&&_optionalChain([this, 'access', _5 => _5.#e, 'optionalCall', _6 => _6()]),t}pipeTo(e,r){let t=super.pipeTo(e,r);return this.locked&&_optionalChain([this, 'access', _7 => _7.#e, 'optionalCall', _8 => _8()]),t}tee(){let[e,r]=super.tee();return this.locked&&_optionalChain([this, 'access', _9 => _9.#e, 'optionalCall', _10 => _10()]),[e,r]}};async function g(){return await new Promise(o=>queueMicrotask(o))}function ie(o,e,{transformAtoB:r,transformBtoA:t}={}){let n=r?o.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=r(c);a.enqueue(i)}catch(i){console.warn("Error transforming A to B",i)}}})):o.readable,s=t?e.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=t(c);a.enqueue(i)}catch(i){console.warn("Error transforming B to A",i)}}})):e.readable;n.pipeTo(e.writable),s.pipeTo(o.writable)}var f=class{#e;get exports(){if(!this.#e)throw new Error("exports were not registered");return this.#e}register(e){this.#e=e}smartMalloc(e){return new R(this.exports.malloc(e),this.exports.free)}copyToMemory(e){let r=e.length,t=this.smartMalloc(r);return new Uint8Array(this.exports.memory.buffer,t.valueOf(),r).set(e),t}copyFromMemory(e,r){let t=this.exports.memory.buffer.slice(Number(e),Number(e)+r);return new Uint8Array(t)}viewFromMemory(e,r){return new Uint8Array(this.exports.memory.buffer,Number(e),r)}};var A={ERR_OK:0,ERR_MEM:-1,ERR_BUF:-2,ERR_TIMEOUT:-3,ERR_RTE:-4,ERR_INPROGRESS:-5,ERR_VAL:-6,ERR_WOULDBLOCK:-7,ERR_USE:-8,ERR_ALREADY:-9,ERR_ISCONN:-10,ERR_CONN:-11,ERR_IF:-12,ERR_ABRT:-13,ERR_RST:-14,ERR_CLSD:-15,ERR_ARG:-16};var b=new l,O= (_class =class extends f{constructor(...args) { super(...args); _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }__init() {this.interfaces=new Map}__init2() {this.imports={register_tap_interface:e=>{let r=new W;b.setOuter(r,{handle:e,sendFrame:t=>{let n=this.copyToMemory(t),s=this.exports.send_tap_interface(e,n,t.length);if(s!==A.ERR_OK)throw new Error(`failed to send frame: ${s}`)},getMacAddress:()=>{let t=this.exports.get_interface_mac_address(e),n=this.viewFromMemory(t,6);return _wire.parseMacAddress.call(void 0, n)},getIPv4Address:()=>{let t=this.exports.get_interface_ip4_address(e);if(t===0)return;let n=this.viewFromMemory(t,4);return _wire.parseIPv4Address.call(void 0, n)},getIPv4Netmask:()=>{let t=this.exports.get_interface_ip4_netmask(e);if(t===0)return;let n=this.viewFromMemory(t,4);return _wire.parseIPv4Address.call(void 0, n)}}),this.interfaces.set(e,r)},receive_frame:async(e,r,t)=>{let n=this.copyFromMemory(r,t);await g();let s=this.interfaces.get(e);if(!s){console.error("received frame on unknown tap interface");return}b.getInner(s).receiveFrame(new Uint8Array(n))}}}async create(e){var d=[];try{let r=e.mac?_wire.serializeMacAddress.call(void 0, e.mac):_wire.generateMacAddress.call(void 0, );let{ipAddress:t,netmask:n}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let s=_chunkDVPTIOIVcjs.a.call(void 0, d,this.copyToMemory(r));let c=_chunkDVPTIOIVcjs.a.call(void 0, d,t?this.copyToMemory(t):void 0);let a=_chunkDVPTIOIVcjs.a.call(void 0, d,n?this.copyToMemory(n):void 0);let i=this.exports.create_tap_interface(s,_nullishCoalesce(c, () => (0)),_nullishCoalesce(a, () => (0)));let m=this.interfaces.get(i);if(!m)throw new Error("tap interface failed to register");return m}catch(y){var I=y,v=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, d,I,v)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_tap_interface(r),this.interfaces.delete(r);return}}}, _class),W= (_class2 =class{#e;#t=!1;__init3() {this.type="tap"}get mac(){return b.getOuter(this).getMacAddress()}get ip(){return b.getOuter(this).getIPv4Address()}get netmask(){return b.getOuter(this).getIPv4Netmask()}constructor(){;_class2.prototype.__init3.call(this);b.setInner(this,{receiveFrame:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");this.#e.enqueue(e)}}}),this.readable=new P({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{try{b.getOuter(this).sendFrame(e)}catch(r){console.error("tap interface send failed",r)}}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}[Symbol.asyncIterator](){return this.listen()}}, _class2);var E=new l,U= (_class3 =class extends f{constructor(...args2) { super(...args2); _class3.prototype.__init4.call(this);_class3.prototype.__init5.call(this); }__init4() {this.interfaces=new Map}__init5() {this.imports={}}async create(e){var I=[];try{let r=e.mac?_wire.serializeMacAddress.call(void 0, e.mac):_wire.generateMacAddress.call(void 0, );let{ipAddress:t,netmask:n}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let s=_chunkDVPTIOIVcjs.a.call(void 0, I,this.copyToMemory(r));let c=_chunkDVPTIOIVcjs.a.call(void 0, I,t?this.copyToMemory(t):void 0);let a=_chunkDVPTIOIVcjs.a.call(void 0, I,n?this.copyToMemory(n):void 0);let i=new Uint32Array(e.ports.map(k=>Number(b.getOuter(k).handle)));let m=_chunkDVPTIOIVcjs.a.call(void 0, I,this.copyToMemory(new Uint8Array(i.buffer)));let d=this.exports.create_bridge_interface(s,_nullishCoalesce(c, () => (0)),_nullishCoalesce(a, () => (0)),m,e.ports.length);let y=new j;E.setOuter(y,{handle:d,getMacAddress:()=>{let k=this.exports.get_interface_mac_address(d),S=this.viewFromMemory(k,6);return _wire.parseMacAddress.call(void 0, S)},getIPv4Address:()=>{let k=this.exports.get_interface_ip4_address(d);if(k===0)return;let S=this.viewFromMemory(k,4);return _wire.parseIPv4Address.call(void 0, S)},getIPv4Netmask:()=>{let k=this.exports.get_interface_ip4_netmask(d);if(k===0)return;let S=this.viewFromMemory(k,4);return _wire.parseIPv4Address.call(void 0, S)}});this.interfaces.set(d,y);return y}catch(v){var D=v,F=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, I,D,F)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_bridge_interface(r),this.interfaces.delete(r);return}}}, _class3),j= (_class4 =class{constructor() { _class4.prototype.__init6.call(this); }__init6() {this.type="bridge"}get mac(){return E.getOuter(this).getMacAddress()}get ip(){return E.getOuter(this).getIPv4Address()}get netmask(){return E.getOuter(this).getIPv4Netmask()}}, _class4);var z=new l,C= (_class5 =class extends f{constructor(...args3) { super(...args3); _class5.prototype.__init7.call(this);_class5.prototype.__init8.call(this); }__init7() {this.interfaces=new Map}__init8() {this.imports={register_loopback_interface:e=>{let r=new K;z.setOuter(r,{handle:e,getIPv4Address:()=>{let t=this.exports.get_interface_ip4_address(e);if(t===0)return;let n=this.viewFromMemory(t,4);return _wire.parseIPv4Address.call(void 0, n)},getIPv4Netmask:()=>{let t=this.exports.get_interface_ip4_netmask(e);if(t===0)return;let n=this.viewFromMemory(t,4);return _wire.parseIPv4Address.call(void 0, n)}}),this.interfaces.set(e,r)}}}async create(e){var i=[];try{let{ipAddress:r,netmask:t}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let n=_chunkDVPTIOIVcjs.a.call(void 0, i,r?this.copyToMemory(r):void 0);let s=_chunkDVPTIOIVcjs.a.call(void 0, i,t?this.copyToMemory(t):void 0);let c=this.exports.create_loopback_interface(_nullishCoalesce(n, () => (0)),_nullishCoalesce(s, () => (0)));let a=this.interfaces.get(c);if(!a)throw new Error("loopback interface failed to register");return a}catch(m){var d=m,y=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, i,d,y)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_loopback_interface(r),this.interfaces.delete(r);return}}}, _class5),K= (_class6 =class{constructor() { _class6.prototype.__init9.call(this); }__init9() {this.type="loopback"}get ip(){return z.getOuter(this).getIPv4Address()}get netmask(){return z.getOuter(this).getIPv4Netmask()}}, _class6);var q=new l,_=new l,G=1448,nt=G*4,st=G*4,ye=G,M= (_class7 =class extends f{#e=new Map;#t=new T;#r=new Map;#n;async#s(e){try{return _wire.serializeIPv4Address.call(void 0, e)}catch (e2){let t=await this.#n.lookup(e);return _wire.serializeIPv4Address.call(void 0, t)}}constructor(e){super();_class7.prototype.__init10.call(this);,this.#n=e}__init10() {this.imports={accept_tcp_connection:async(e,r)=>{let t=this.#e.get(e);if(!t){console.error("new tcp connection to unknown listener");return}await g();let n=new L;_.setOuter(n,{send:async s=>{let c=Number(this.copyToMemory(s)),a=this.exports.send_tcp_chunk(r,c,s.length);for(;a<s.length;){await new Promise(m=>{this.#r.set(r,m)});let i=s.length-a;a+=this.exports.send_tcp_chunk(r,c+a,i)}},updateReceiveBuffer:s=>{this.exports.update_tcp_receive_buffer(r,s)},close:async()=>{let s=this.exports.close_tcp_connection(r);if(s!==A.ERR_OK)throw new Error(`failed to close tcp connection: ${s}`)}}),this.#t.set(r,n),q.getInner(t).accept(n)},connected_tcp_connection:async e=>{await g();let r=new L;_.setOuter(r,{send:async t=>{let n=Number(this.copyToMemory(t)),s=this.exports.send_tcp_chunk(e,n,t.length);for(;s<t.length;){await new Promise(a=>{this.#r.set(e,a)});let c=t.length-s;s+=this.exports.send_tcp_chunk(e,n+s,c)}},updateReceiveBuffer:t=>{this.exports.update_tcp_receive_buffer(e,t)},close:async()=>{this.exports.close_tcp_connection(e)}}),this.#t.set(e,r)},closed_tcp_connection:async e=>{let r=this.#t.get(e);if(!r){console.error("received close on unknown tcp connection");return}await _.getInner(r).close()},receive_tcp_chunk:async(e,r,t)=>{let n=this.copyFromMemory(r,t),s=this.#t.get(e);if(!s){console.error("received chunk on unknown tcp connection");return}await g(),_.getInner(s).receive(new Uint8Array(n))},sent_tcp_chunk:(e,r)=>{let t=this.#r.get(e);this.#r.delete(e),_optionalChain([t, 'optionalCall', _12 => _12(r)])}}}async listen(e){var s=[];try{let r=_chunkDVPTIOIVcjs.a.call(void 0, s,e.host?this.copyToMemory(await this.#s(e.host)):null);let t=this.exports.create_tcp_listener(r,e.port);let n=new $;q.setOuter(n,{});this.#e.set(t,n);return n}catch(c){var a=c,i=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, s,a,i)}}async connect(e){var s=[];try{let r=_chunkDVPTIOIVcjs.a.call(void 0, s,this.copyToMemory(await this.#s(e.host)));let t=this.exports.create_tcp_connection(r,e.port);let n=await this.#t.wait(t);if(!n)throw new Error("tcp failed to connect");return n}catch(c){var a=c,i=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, s,a,i)}}}, _class7),$=class{#e=[];#t;constructor(){q.setInner(this,{accept:async e=>{this.#e.push(e),_optionalChain([this, 'access', _13 => _13.#t, 'optionalCall', _14 => _14()])}})}async*[Symbol.asyncIterator](){for(;;)await new Promise(e=>{this.#t=e}),yield*this.#e,this.#e=[]}},L=class{#e=[];#t;#r;constructor(){_.setInner(this,{receive:async e=>{this.#e.push(e),this.#n()},close:async()=>{this.close()}}),this.readable=new ReadableStream({start:e=>{this.#t=e},pull:()=>{this.#n()}},{highWaterMark:ye,size:e=>e.byteLength}),this.writable=new WritableStream({start:e=>{this.#r=e},write:async e=>{await _.getOuter(this).send(e)}},{highWaterMark:0})}#n(){if(!(_optionalChain([this, 'access', _15 => _15.#t, 'optionalAccess', _16 => _16.desiredSize])>0))return;let e=0;for(;this.#e.length>0;){let r=this.#e[0].length;if(e>0&&e+r>this.#t.desiredSize)break;let t=this.#e.shift();this.#t.enqueue(t),e+=t.length}e>0&&_.getOuter(this).updateReceiveBuffer(e)}async close(){await _.getOuter(this).close(),_optionalChain([this, 'access', _17 => _17.#t, 'optionalAccess', _18 => _18.error, 'call', _19 => _19(new Error("tcp connection closed"))]),_optionalChain([this, 'access', _20 => _20.#r, 'optionalAccess', _21 => _21.error, 'call', _22 => _22(new Error("tcp connection closed"))])}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}};var x=new l,B= (_class8 =class extends f{constructor(...args4) { super(...args4); _class8.prototype.__init11.call(this);_class8.prototype.__init12.call(this); }__init11() {this.interfaces=new Map}__init12() {this.imports={register_tun_interface:e=>{let r=new Q;x.setOuter(r,{handle:e,sendPacket:t=>{let n=this.copyToMemory(t);this.exports.send_tun_interface(e,n,t.length)},getIPv4Address:()=>{let t=this.exports.get_interface_ip4_address(e);if(t===0)return;let n=this.viewFromMemory(t,4);return _wire.parseIPv4Address.call(void 0, n)},getIPv4Netmask:()=>{let t=this.exports.get_interface_ip4_netmask(e);if(t===0)return;let n=this.viewFromMemory(t,4);return _wire.parseIPv4Address.call(void 0, n)}}),this.interfaces.set(e,r)},receive_packet:async(e,r,t)=>{let n=this.copyFromMemory(r,t);await g();let s=this.interfaces.get(e);if(!s){console.error("received packet on unknown tun interface");return}x.getInner(s).receivePacket(new Uint8Array(n))}}}async create(e){var i=[];try{let{ipAddress:r,netmask:t}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let n=_chunkDVPTIOIVcjs.a.call(void 0, i,r?this.copyToMemory(r):void 0);let s=_chunkDVPTIOIVcjs.a.call(void 0, i,t?this.copyToMemory(t):void 0);let c=this.exports.create_tun_interface(_nullishCoalesce(n, () => (0)),_nullishCoalesce(s, () => (0)));let a=this.interfaces.get(c);if(!a)throw new Error("tun interface failed to register");return a}catch(m){var d=m,y=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, i,d,y)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_tun_interface(r),this.interfaces.delete(r);return}}}, _class8),Q= (_class9 =class{#e;#t=!1;__init13() {this.type="tun"}get ip(){return x.getOuter(this).getIPv4Address()}get netmask(){return x.getOuter(this).getIPv4Netmask()}constructor(){;_class9.prototype.__init13.call(this);x.setInner(this,{receivePacket:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");_optionalChain([this, 'access', _23 => _23.#e, 'optionalAccess', _24 => _24.enqueue, 'call', _25 => _25(e)])}}}),this.readable=new P({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{x.getOuter(this).sendPacket(e)}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}[Symbol.asyncIterator](){return this.listen()}}, _class9);var H=new l,N= (_class10 =class extends f{#e=new T;#t;async#r(e){try{return _wire.serializeIPv4Address.call(void 0, e)}catch (e3){let t=await this.#t.lookup(e);return _wire.serializeIPv4Address.call(void 0, t)}}constructor(e){super();_class10.prototype.__init14.call(this);,this.#t=e}__init14() {this.imports={receive_udp_datagram:async(e,r,t,n,s)=>{let c=this.copyFromMemory(r,4),a=this.copyFromMemory(n,s),i=this.#e.get(e);if(!i){console.error("received datagram on unknown udp socket");return}await g(),H.getInner(i).receive({host:_wire.parseIPv4Address.call(void 0, c),port:t,data:a})}}}async open(e){var s=[];try{let r=_chunkDVPTIOIVcjs.a.call(void 0, s,e.host?this.copyToMemory(await this.#r(e.host)):null);let t=this.exports.open_udp_socket(r,_nullishCoalesce(e.port, () => (0)));if(Number(t)===0)throw new Error("failed to open udp socket");let n=new Z;H.setOuter(n,{send:async m=>{var v=[];try{let d=_chunkDVPTIOIVcjs.a.call(void 0, v,this.copyToMemory(await this.#r(m.host)));let y=_chunkDVPTIOIVcjs.a.call(void 0, v,this.copyToMemory(m.data));let I=this.exports.send_udp_datagram(t,d,m.port,y,m.data.length);if(I!==A.ERR_OK)throw new Error(`failed to send udp datagram: ${I}`)}catch(D){var F=D,k=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, v,F,k)}},close:async()=>{this.exports.close_udp_socket(t),this.#e.delete(t)}});this.#e.set(t,n);return n}catch(c){var a=c,i=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, s,a,i)}}}, _class10),Z=class{#e;#t;constructor(){H.setInner(this,{receive:async e=>{if(!this.#e)throw new Error("readable controller not initialized");this.#e.enqueue(e)}}),this.readable=new ReadableStream({start:e=>{this.#e=e}}),this.writable=new WritableStream({start:e=>{this.#t=e},write:async e=>{await H.getOuter(this).send(e)}})}async close(){await H.getOuter(this).close(),_optionalChain([this, 'access', _26 => _26.#e, 'optionalAccess', _27 => _27.error, 'call', _28 => _28(new Error("udp socket closed"))]),_optionalChain([this, 'access', _29 => _29.#t, 'optionalAccess', _30 => _30.error, 'call', _31 => _31(new Error("udp socket closed"))])}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}};var ge=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";async function ne(o,e){return ge?be(o,e):fetch(o)}async function be(o,e){let r=await Promise.resolve().then(() => _interopRequireWildcard(require("fs"))),{Readable:t}=await Promise.resolve().then(() => _interopRequireWildcard(require("stream"))),n=r.createReadStream(o),s=t.toWeb(n);return new Response(s,{headers:{"Content-Type":e}})}async function Pe(o){let e=new X(o);return await e.ready,e}var X=class{#e;#t;#r;#n;#s;#o;#i;#a;#c;get interfaces(){return this.#d()}constructor(e={}){this.#e={...e,initializeLoopback:_nullishCoalesce(e.initializeLoopback, () => (!0))},this.#r=new (0, _dns.DnsClient)(this,{nameServer:_nullishCoalesce(e.nameServer, () => ({ip:"127.0.0.1",port:53}))}),this.#n=new C,this.#s=new B,this.#o=new O,this.#i=new U,this.#a=new M(this.#r),this.#c=new N(this.#r),this.ready=this.#p(),this.ready.then(async()=>{this.#e.initializeLoopback&&await this.createLoopbackInterface({ip:"127.0.0.1/8"})})}async#p(){let e=new (0, _browser_wasi_shim.WASI)([],[],[new (0, _browser_wasi_shim.OpenFile)(new (0, _browser_wasi_shim.File)([])),_browser_wasi_shim.ConsoleStdout.lineBuffered(s=>console.log(`[WASI stdout] ${s}`)),_browser_wasi_shim.ConsoleStdout.lineBuffered(s=>console.warn(`[WASI stderr] ${s}`))]),r=ne(new URL("../tcpip.wasm",import.meta.url),"application/wasm"),{instance:t}=await WebAssembly.instantiateStreaming(r,{wasi_snapshot_preview1:e.wasiImport,env:{...this.#n.imports,...this.#s.imports,...this.#o.imports,...this.#i.imports,...this.#a.imports,...this.#c.imports}}),n=t;this.#n.register(n.exports),this.#s.register(n.exports),this.#o.register(n.exports),this.#i.register(n.exports),this.#a.register(n.exports),this.#c.register(n.exports),e.initialize(n),this.#t=Number(setInterval(()=>{n.exports.process_queued_packets(),n.exports.process_timeouts()},100))}*#d(){yield*this.#n.interfaces.values(),yield*this.#s.interfaces.values(),yield*this.#o.interfaces.values(),yield*this.#i.interfaces.values()}async createLoopbackInterface(e){return await this.ready,this.#n.create(e)}async createTunInterface(e){return await this.ready,this.#s.create(e)}async createTapInterface(e={}){return await this.ready,this.#o.create(e)}async createBridgeInterface(e){return await this.ready,this.#i.create(e)}async removeInterface(e){switch(await this.ready,e.type){case"loopback":return this.#n.remove(e);case"tun":return this.#s.remove(e);case"tap":return this.#o.remove(e);case"bridge":return this.#i.remove(e);default:throw new Error("unknown interface type")}}async listenTcp(e){return await this.ready,this.#a.listen(e)}async connectTcp(e){return await this.ready,this.#a.connect(e)}async openUdp(e={}){return await this.ready,this.#c.open(e)}};exports.connectStreams = ie; exports.createStack = Pe;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10;var _chunkDVPTIOIVcjs = require('./chunk-DVPTIOIV.cjs');var _browser_wasi_shim = require('@bjorn3/browser_wasi_shim');var _dns = require('@tcpip/dns');var _wire = require('@tcpip/wire');var l=class{#e=new WeakMap;#t=new WeakMap;setOuter(e,t){this.#e.set(e,t)}setInner(e,t){this.#t.set(e,t)}getOuter(e){let t=this.#e.get(e);if(!t)throw new Error(`outer hooks not set for ${e}`);return t}getInner(e){let t=this.#t.get(e);if(!t)throw new Error(`inner hooks not set for ${e}`);return t}},S=class extends Number{constructor(e,t){super(e),this.free=t}[_chunkDVPTIOIVcjs.c](){this.free(this.valueOf())}},P=class extends Map{#e=new Map;wait(e){return new Promise(t=>{let r=_nullishCoalesce(this.#e.get(e), () => (new Set));r.add(t),this.#e.set(e,r)})}set(e,t){super.set(e,t);let r=this.#e.get(e);if(r)for(let n of r)n(t),r.delete(n);return this}};function v(o,e){let t=o.getReader();return oe(t,e)}async function*oe(o,e){try{for(;;){let{done:t,value:r}=await o.read();if(t)return r;yield r}}finally{_optionalChain([e, 'optionalAccess', _2 => _2.preventCancel])||await o.cancel(),o.releaseLock()}}var A=class extends ReadableStream{#e;constructor({lock:e,...t},r){super(t,r),this.#e=e}getReader(){let e=super.getReader();return this.locked&&_optionalChain([this, 'access', _3 => _3.#e, 'optionalCall', _4 => _4()]),e}pipeThrough(e,t){let r=super.pipeThrough(e,t);return this.locked&&_optionalChain([this, 'access', _5 => _5.#e, 'optionalCall', _6 => _6()]),r}pipeTo(e,t){let r=super.pipeTo(e,t);return this.locked&&_optionalChain([this, 'access', _7 => _7.#e, 'optionalCall', _8 => _8()]),r}tee(){let[e,t]=super.tee();return this.locked&&_optionalChain([this, 'access', _9 => _9.#e, 'optionalCall', _10 => _10()]),[e,t]}};async function g(){return await new Promise(o=>queueMicrotask(o))}function ie(o,e,{transformAtoB:t,transformBtoA:r}={}){let n=t?o.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=t(c);a.enqueue(i)}catch(i){console.warn("Error transforming A to B",i)}}})):o.readable,s=r?e.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=r(c);a.enqueue(i)}catch(i){console.warn("Error transforming B to A",i)}}})):e.readable;n.pipeTo(e.writable),s.pipeTo(o.writable)}var f=class{#e;get exports(){if(!this.#e)throw new Error("exports were not registered");return this.#e}register(e){this.#e=e}smartMalloc(e){return new S(this.exports.malloc(e),this.exports.free)}copyToMemory(e){let t=e.length,r=this.smartMalloc(t);return new Uint8Array(this.exports.memory.buffer,r.valueOf(),t).set(e),r}copyFromMemory(e,t){let r=this.exports.memory.buffer.slice(Number(e),Number(e)+t);return new Uint8Array(r)}viewFromMemory(e,t){return new Uint8Array(this.exports.memory.buffer,Number(e),t)}};var b={ERR_OK:0,ERR_MEM:-1,ERR_BUF:-2,ERR_TIMEOUT:-3,ERR_RTE:-4,ERR_INPROGRESS:-5,ERR_VAL:-6,ERR_WOULDBLOCK:-7,ERR_USE:-8,ERR_ALREADY:-9,ERR_ISCONN:-10,ERR_CONN:-11,ERR_IF:-12,ERR_ABRT:-13,ERR_RST:-14,ERR_CLSD:-15,ERR_ARG:-16};var w=new l,E= (_class =class extends f{constructor(...args) { super(...args); _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }__init() {this.interfaces=new Map}__init2() {this.imports={register_tap_interface:e=>{let t=new F;w.setOuter(t,{handle:e,sendFrame:r=>{let n=this.copyToMemory(r),s=this.exports.send_tap_interface(e,n,r.length);if(s!==b.ERR_OK)throw new Error(`failed to send frame: ${s}`)},getMacAddress:()=>{let r=this.exports.get_interface_mac_address(e),n=this.viewFromMemory(r,6);return _wire.parseMacAddress.call(void 0, n)},getIPv4Address:()=>{let r=this.exports.get_interface_ip4_address(e);if(r===0)return;let n=this.viewFromMemory(r,4);return _wire.parseIPv4Address.call(void 0, n)},getIPv4Netmask:()=>{let r=this.exports.get_interface_ip4_netmask(e);if(r===0)return;let n=this.viewFromMemory(r,4);return _wire.parseIPv4Address.call(void 0, n)}}),this.interfaces.set(e,t)},receive_frame:async(e,t,r)=>{let n=this.copyFromMemory(t,r);await g();let s=this.interfaces.get(e);if(!s){console.error("received frame on unknown tap interface");return}w.getInner(s).receiveFrame(new Uint8Array(n))}}}async create(e){var d=[];try{let t=e.mac?_wire.serializeMacAddress.call(void 0, e.mac):_wire.generateMacAddress.call(void 0, );let{ipAddress:r,netmask:n}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let s=_chunkDVPTIOIVcjs.a.call(void 0, d,this.copyToMemory(t));let c=_chunkDVPTIOIVcjs.a.call(void 0, d,r?this.copyToMemory(r):void 0);let a=_chunkDVPTIOIVcjs.a.call(void 0, d,n?this.copyToMemory(n):void 0);let i=this.exports.create_tap_interface(s,_nullishCoalesce(c, () => (0)),_nullishCoalesce(a, () => (0)));let m=this.interfaces.get(i);if(!m)throw new Error("tap interface failed to register");return m}catch(y){var I=y,T=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, d,I,T)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_tap_interface(t),this.interfaces.delete(t);return}}}, _class),F= (_class2 =class{#e;#t=!1;__init3() {this.type="tap"}get mac(){return w.getOuter(this).getMacAddress()}get ip(){return w.getOuter(this).getIPv4Address()}get netmask(){return w.getOuter(this).getIPv4Netmask()}constructor(){;_class2.prototype.__init3.call(this);w.setInner(this,{receiveFrame:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");this.#e.enqueue(e)}}}),this.readable=new A({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{try{w.getOuter(this).sendFrame(e)}catch(t){console.error("tap interface send failed",t)}}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}[Symbol.asyncIterator](){return this.listen()}}, _class2);var O=new l,C= (_class3 =class extends f{constructor(...args2) { super(...args2); _class3.prototype.__init4.call(this);_class3.prototype.__init5.call(this); }__init4() {this.interfaces=new Map}__init5() {this.imports={}}async create(e){var I=[];try{let t=e.mac?_wire.serializeMacAddress.call(void 0, e.mac):_wire.generateMacAddress.call(void 0, );let{ipAddress:r,netmask:n}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let s=_chunkDVPTIOIVcjs.a.call(void 0, I,this.copyToMemory(t));let c=_chunkDVPTIOIVcjs.a.call(void 0, I,r?this.copyToMemory(r):void 0);let a=_chunkDVPTIOIVcjs.a.call(void 0, I,n?this.copyToMemory(n):void 0);let i=new Uint32Array(e.ports.map(k=>Number(w.getOuter(k).handle)));let m=_chunkDVPTIOIVcjs.a.call(void 0, I,this.copyToMemory(new Uint8Array(i.buffer)));let d=this.exports.create_bridge_interface(s,_nullishCoalesce(c, () => (0)),_nullishCoalesce(a, () => (0)),m,e.ports.length);let y=new K;O.setOuter(y,{handle:d,getMacAddress:()=>{let k=this.exports.get_interface_mac_address(d),R=this.viewFromMemory(k,6);return _wire.parseMacAddress.call(void 0, R)},getIPv4Address:()=>{let k=this.exports.get_interface_ip4_address(d);if(k===0)return;let R=this.viewFromMemory(k,4);return _wire.parseIPv4Address.call(void 0, R)},getIPv4Netmask:()=>{let k=this.exports.get_interface_ip4_netmask(d);if(k===0)return;let R=this.viewFromMemory(k,4);return _wire.parseIPv4Address.call(void 0, R)}});this.interfaces.set(d,y);return y}catch(T){var W=T,D=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, I,W,D)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_bridge_interface(t),this.interfaces.delete(t);return}}}, _class3),K= (_class4 =class{constructor() { _class4.prototype.__init6.call(this); }__init6() {this.type="bridge"}get mac(){return O.getOuter(this).getMacAddress()}get ip(){return O.getOuter(this).getIPv4Address()}get netmask(){return O.getOuter(this).getIPv4Netmask()}}, _class4);var j=new l,U= (_class5 =class extends f{constructor(...args3) { super(...args3); _class5.prototype.__init7.call(this);_class5.prototype.__init8.call(this); }__init7() {this.interfaces=new Map}__init8() {this.imports={register_loopback_interface:e=>{let t=new z;j.setOuter(t,{handle:e,getIPv4Address:()=>{let r=this.exports.get_interface_ip4_address(e);if(r===0)return;let n=this.viewFromMemory(r,4);return _wire.parseIPv4Address.call(void 0, n)},getIPv4Netmask:()=>{let r=this.exports.get_interface_ip4_netmask(e);if(r===0)return;let n=this.viewFromMemory(r,4);return _wire.parseIPv4Address.call(void 0, n)}}),this.interfaces.set(e,t)}}}async create(e){var i=[];try{let{ipAddress:t,netmask:r}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let n=_chunkDVPTIOIVcjs.a.call(void 0, i,t?this.copyToMemory(t):void 0);let s=_chunkDVPTIOIVcjs.a.call(void 0, i,r?this.copyToMemory(r):void 0);let c=this.exports.create_loopback_interface(_nullishCoalesce(n, () => (0)),_nullishCoalesce(s, () => (0)));let a=this.interfaces.get(c);if(!a)throw new Error("loopback interface failed to register");return a}catch(m){var d=m,y=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, i,d,y)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_loopback_interface(t),this.interfaces.delete(t);return}}}, _class5),z= (_class6 =class{constructor() { _class6.prototype.__init9.call(this); }__init9() {this.type="loopback"}get ip(){return j.getOuter(this).getIPv4Address()}get netmask(){return j.getOuter(this).getIPv4Netmask()}}, _class6);var q=new l,_=new l,G=1448,nt=G*4,st=G*4,ye=G,M= (_class7 =class extends f{#e=new Map;#t=new P;#r=new Map;#n=new Map;#s;async#o(e){try{return _wire.serializeIPv4Address.call(void 0, e)}catch (e2){let r=await this.#s.lookup(e);return _wire.serializeIPv4Address.call(void 0, r)}}constructor(e){super();_class7.prototype.__init10.call(this);,this.#s=e}async#a(e){for(;;){let t=this.exports.close_tcp_connection(e);if(t===b.ERR_OK)return;if(t!==b.ERR_MEM)throw new Error(`failed to close tcp connection: ${t}`);await new Promise(r=>{this.#n.set(e,r)})}}async#i(e){for(;;){let t=this.exports.shutdown_tcp_connection_write(e);if(t===b.ERR_OK)return;if(t!==b.ERR_MEM)throw new Error(`failed to shutdown tcp write side: ${t}`);await new Promise(r=>{this.#n.set(e,r)})}}__init10() {this.imports={accept_tcp_connection:async(e,t)=>{let r=this.#e.get(e);if(!r){console.error("new tcp connection to unknown listener");return}await g();let n=new L;_.setOuter(n,{send:async s=>{let c=Number(this.copyToMemory(s)),a=this.exports.send_tcp_chunk(t,c,s.length);for(;a<s.length;){await new Promise(m=>{this.#r.set(t,m)});let i=s.length-a;a+=this.exports.send_tcp_chunk(t,c+a,i)}},updateReceiveBuffer:s=>{this.exports.update_tcp_receive_buffer(t,s)},close:async()=>{await this.#a(t)},closeWrite:async()=>{await this.#i(t)}}),this.#t.set(t,n),q.getInner(r).accept(n)},connected_tcp_connection:async e=>{await g();let t=new L;_.setOuter(t,{send:async r=>{let n=Number(this.copyToMemory(r)),s=this.exports.send_tcp_chunk(e,n,r.length);for(;s<r.length;){await new Promise(a=>{this.#r.set(e,a)});let c=r.length-s;s+=this.exports.send_tcp_chunk(e,n+s,c)}},updateReceiveBuffer:r=>{this.exports.update_tcp_receive_buffer(e,r)},close:async()=>{await this.#a(e)},closeWrite:async()=>{await this.#i(e)}}),this.#t.set(e,t)},closed_tcp_connection:async e=>{let t=this.#t.get(e);if(!t){console.error("received close on unknown tcp connection");return}await _.getInner(t).close()},receive_tcp_chunk:async(e,t,r)=>{let n=this.copyFromMemory(t,r),s=this.#t.get(e);if(!s){console.error("received chunk on unknown tcp connection");return}await g(),_.getInner(s).receive(new Uint8Array(n))},sent_tcp_chunk:(e,t)=>{let r=this.#r.get(e);this.#r.delete(e),_optionalChain([r, 'optionalCall', _13 => _13(t)]);let n=this.#n.get(e);this.#n.delete(e),_optionalChain([n, 'optionalCall', _14 => _14()])}}}async listen(e){var s=[];try{let t=_chunkDVPTIOIVcjs.a.call(void 0, s,e.host?this.copyToMemory(await this.#o(e.host)):null);let r=this.exports.create_tcp_listener(t,e.port);let n=new $;q.setOuter(n,{});this.#e.set(r,n);return n}catch(c){var a=c,i=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, s,a,i)}}async connect(e){var s=[];try{let t=_chunkDVPTIOIVcjs.a.call(void 0, s,this.copyToMemory(await this.#o(e.host)));let r=this.exports.create_tcp_connection(t,e.port);let n=await this.#t.wait(r);if(!n)throw new Error("tcp failed to connect");return n}catch(c){var a=c,i=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, s,a,i)}}}, _class7),$=class{#e=[];#t;constructor(){q.setInner(this,{accept:async e=>{this.#e.push(e),_optionalChain([this, 'access', _15 => _15.#t, 'optionalCall', _16 => _16()])}})}async*[Symbol.asyncIterator](){for(;;)await new Promise(e=>{this.#t=e}),yield*this.#e,this.#e=[]}},L=class{#e=[];#t;#r;#n=!1;#s=!1;constructor(){_.setInner(this,{receive:async e=>{this.#e.push(e),this.#i()},close:async()=>{await g(),this.#n=!0,this.#i()}}),this.readable=new ReadableStream({start:e=>{this.#t=e},pull:()=>{this.#i()}},{highWaterMark:ye,size:e=>e.byteLength}),this.writable=new WritableStream({start:e=>{this.#r=e},write:async e=>{await _.getOuter(this).send(e)},close:async()=>{await _.getOuter(this).closeWrite()}},{highWaterMark:1})}#o(){if(!this.#s){this.#s=!0;try{_optionalChain([this, 'access', _17 => _17.#t, 'optionalAccess', _18 => _18.close, 'call', _19 => _19()])}catch (e3){}}}#a(e){if(!this.#s){this.#s=!0;try{_optionalChain([this, 'access', _20 => _20.#t, 'optionalAccess', _21 => _21.error, 'call', _22 => _22(e)])}catch (e4){}}}#i(){if(this.#n&&this.#e.length===0){this.#o(),_optionalChain([this, 'access', _23 => _23.#r, 'optionalAccess', _24 => _24.error, 'call', _25 => _25(new Error("tcp connection closed"))]);return}if(!(_optionalChain([this, 'access', _26 => _26.#t, 'optionalAccess', _27 => _27.desiredSize])>0))return;let e=0;for(;this.#e.length>0;){let t=this.#e[0].length;if(e>0&&e+t>this.#t.desiredSize)break;let r=this.#e.shift();this.#t.enqueue(r),e+=r.length}e>0&&_.getOuter(this).updateReceiveBuffer(e),this.#n&&this.#e.length===0&&(this.#o(),_optionalChain([this, 'access', _28 => _28.#r, 'optionalAccess', _29 => _29.error, 'call', _30 => _30(new Error("tcp connection closed"))]))}async close(){await _.getOuter(this).close(),this.#a(new Error("tcp connection closed")),_optionalChain([this, 'access', _31 => _31.#r, 'optionalAccess', _32 => _32.error, 'call', _33 => _33(new Error("tcp connection closed"))])}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}};var x=new l,B= (_class8 =class extends f{constructor(...args4) { super(...args4); _class8.prototype.__init11.call(this);_class8.prototype.__init12.call(this); }__init11() {this.interfaces=new Map}__init12() {this.imports={register_tun_interface:e=>{let t=new Q;x.setOuter(t,{handle:e,sendPacket:r=>{let n=this.copyToMemory(r);this.exports.send_tun_interface(e,n,r.length)},getIPv4Address:()=>{let r=this.exports.get_interface_ip4_address(e);if(r===0)return;let n=this.viewFromMemory(r,4);return _wire.parseIPv4Address.call(void 0, n)},getIPv4Netmask:()=>{let r=this.exports.get_interface_ip4_netmask(e);if(r===0)return;let n=this.viewFromMemory(r,4);return _wire.parseIPv4Address.call(void 0, n)}}),this.interfaces.set(e,t)},receive_packet:async(e,t,r)=>{let n=this.copyFromMemory(t,r);await g();let s=this.interfaces.get(e);if(!s){console.error("received packet on unknown tun interface");return}x.getInner(s).receivePacket(new Uint8Array(n))}}}async create(e){var i=[];try{let{ipAddress:t,netmask:r}=e.ip?_wire.serializeIPv4Cidr.call(void 0, e.ip):{};let n=_chunkDVPTIOIVcjs.a.call(void 0, i,t?this.copyToMemory(t):void 0);let s=_chunkDVPTIOIVcjs.a.call(void 0, i,r?this.copyToMemory(r):void 0);let c=this.exports.create_tun_interface(_nullishCoalesce(n, () => (0)),_nullishCoalesce(s, () => (0)));let a=this.interfaces.get(c);if(!a)throw new Error("tun interface failed to register");return a}catch(m){var d=m,y=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, i,d,y)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_tun_interface(t),this.interfaces.delete(t);return}}}, _class8),Q= (_class9 =class{#e;#t=!1;__init13() {this.type="tun"}get ip(){return x.getOuter(this).getIPv4Address()}get netmask(){return x.getOuter(this).getIPv4Netmask()}constructor(){;_class9.prototype.__init13.call(this);x.setInner(this,{receivePacket:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");_optionalChain([this, 'access', _34 => _34.#e, 'optionalAccess', _35 => _35.enqueue, 'call', _36 => _36(e)])}}}),this.readable=new A({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{x.getOuter(this).sendPacket(e)}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}[Symbol.asyncIterator](){return this.listen()}}, _class9);var H=new l,N= (_class10 =class extends f{#e=new P;#t;async#r(e){try{return _wire.serializeIPv4Address.call(void 0, e)}catch (e5){let r=await this.#t.lookup(e);return _wire.serializeIPv4Address.call(void 0, r)}}constructor(e){super();_class10.prototype.__init14.call(this);,this.#t=e}__init14() {this.imports={receive_udp_datagram:async(e,t,r,n,s)=>{let c=this.copyFromMemory(t,4),a=this.copyFromMemory(n,s),i=this.#e.get(e);if(!i){console.error("received datagram on unknown udp socket");return}await g(),H.getInner(i).receive({host:_wire.parseIPv4Address.call(void 0, c),port:r,data:a})}}}async open(e){var s=[];try{let t=_chunkDVPTIOIVcjs.a.call(void 0, s,e.host?this.copyToMemory(await this.#r(e.host)):null);let r=this.exports.open_udp_socket(t,_nullishCoalesce(e.port, () => (0)));if(Number(r)===0)throw new Error("failed to open udp socket");let n=new Z;H.setOuter(n,{send:async m=>{var T=[];try{let d=_chunkDVPTIOIVcjs.a.call(void 0, T,this.copyToMemory(await this.#r(m.host)));let y=_chunkDVPTIOIVcjs.a.call(void 0, T,this.copyToMemory(m.data));let I=this.exports.send_udp_datagram(r,d,m.port,y,m.data.length);if(I!==b.ERR_OK)throw new Error(`failed to send udp datagram: ${I}`)}catch(W){var D=W,k=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, T,D,k)}},close:async()=>{this.exports.close_udp_socket(r),this.#e.delete(r)}});this.#e.set(r,n);return n}catch(c){var a=c,i=!0}finally{_chunkDVPTIOIVcjs.b.call(void 0, s,a,i)}}}, _class10),Z=class{#e;#t;constructor(){H.setInner(this,{receive:async e=>{if(!this.#e)throw new Error("readable controller not initialized");this.#e.enqueue(e)}}),this.readable=new ReadableStream({start:e=>{this.#e=e}}),this.writable=new WritableStream({start:e=>{this.#t=e},write:async e=>{await H.getOuter(this).send(e)}})}async close(){await H.getOuter(this).close(),_optionalChain([this, 'access', _37 => _37.#e, 'optionalAccess', _38 => _38.error, 'call', _39 => _39(new Error("udp socket closed"))]),_optionalChain([this, 'access', _40 => _40.#t, 'optionalAccess', _41 => _41.error, 'call', _42 => _42(new Error("udp socket closed"))])}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}};var Ie=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";async function ne(o,e){return Ie?be(o,e):fetch(o)}async function be(o,e){let t=await Promise.resolve().then(() => _interopRequireWildcard(require("fs"))),{Readable:r}=await Promise.resolve().then(() => _interopRequireWildcard(require("stream"))),n=t.createReadStream(o),s=r.toWeb(n);return new Response(s,{headers:{"Content-Type":e}})}async function Pe(o){let e=new X(o);return await e.ready,e}var X=class{#e;#t;#r;#n;#s;#o;#a;#i;#c;get interfaces(){return this.#d()}constructor(e={}){this.#e={...e,initializeLoopback:_nullishCoalesce(e.initializeLoopback, () => (!0))},this.#r=new (0, _dns.DnsClient)(this,{nameServer:_nullishCoalesce(e.nameServer, () => ({ip:"127.0.0.1",port:53}))}),this.#n=new U,this.#s=new B,this.#o=new E,this.#a=new C,this.#i=new M(this.#r),this.#c=new N(this.#r),this.ready=this.#p(),this.ready.then(async()=>{this.#e.initializeLoopback&&await this.createLoopbackInterface({ip:"127.0.0.1/8"})})}async#p(){let e=new (0, _browser_wasi_shim.WASI)([],[],[new (0, _browser_wasi_shim.OpenFile)(new (0, _browser_wasi_shim.File)([])),_browser_wasi_shim.ConsoleStdout.lineBuffered(s=>console.log(`[WASI stdout] ${s}`)),_browser_wasi_shim.ConsoleStdout.lineBuffered(s=>console.warn(`[WASI stderr] ${s}`))]),t=ne(new URL("../tcpip.wasm",import.meta.url),"application/wasm"),{instance:r}=await WebAssembly.instantiateStreaming(t,{wasi_snapshot_preview1:e.wasiImport,env:{...this.#n.imports,...this.#s.imports,...this.#o.imports,...this.#a.imports,...this.#i.imports,...this.#c.imports}}),n=r;this.#n.register(n.exports),this.#s.register(n.exports),this.#o.register(n.exports),this.#a.register(n.exports),this.#i.register(n.exports),this.#c.register(n.exports),e.initialize(n),this.#t=Number(setInterval(()=>{n.exports.process_queued_packets(),n.exports.process_timeouts()},100))}*#d(){yield*this.#n.interfaces.values(),yield*this.#s.interfaces.values(),yield*this.#o.interfaces.values(),yield*this.#a.interfaces.values()}async createLoopbackInterface(e){return await this.ready,this.#n.create(e)}async createTunInterface(e){return await this.ready,this.#s.create(e)}async createTapInterface(e={}){return await this.ready,this.#o.create(e)}async createBridgeInterface(e){return await this.ready,this.#a.create(e)}async removeInterface(e){switch(await this.ready,e.type){case"loopback":return this.#n.remove(e);case"tun":return this.#s.remove(e);case"tap":return this.#o.remove(e);case"bridge":return this.#a.remove(e);default:throw new Error("unknown interface type")}}async listenTcp(e){return await this.ready,this.#i.listen(e)}async connectTcp(e){return await this.ready,this.#i.connect(e)}async openUdp(e={}){return await this.ready,this.#c.open(e)}};exports.connectStreams = ie; exports.createStack = Pe;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as p,b as u,c as h}from"./chunk-T54CGJHW.js";import{ConsoleStdout as se,File as we,OpenFile as _e,WASI as ve}from"@bjorn3/browser_wasi_shim";import{DnsClient as Te}from"@tcpip/dns";import{generateMacAddress as me,parseIPv4Address as J,parseMacAddress as le,serializeIPv4Cidr as ue,serializeMacAddress as fe}from"@tcpip/wire";var l=class{#e=new WeakMap;#t=new WeakMap;setOuter(e,r){this.#e.set(e,r)}setInner(e,r){this.#t.set(e,r)}getOuter(e){let r=this.#e.get(e);if(!r)throw new Error(`outer hooks not set for ${e}`);return r}getInner(e){let r=this.#t.get(e);if(!r)throw new Error(`inner hooks not set for ${e}`);return r}},R=class extends Number{free;constructor(e,r){super(e),this.free=r}[h](){this.free(this.valueOf())}},T=class extends Map{#e=new Map;wait(e){return new Promise(r=>{let t=this.#e.get(e)??new Set;t.add(r),this.#e.set(e,t)})}set(e,r){super.set(e,r);let t=this.#e.get(e);if(t)for(let n of t)n(r),t.delete(n);return this}};function w(o,e){let r=o.getReader();return oe(r,e)}async function*oe(o,e){try{for(;;){let{done:r,value:t}=await o.read();if(r)return t;yield t}}finally{e?.preventCancel||await o.cancel(),o.releaseLock()}}var P=class extends ReadableStream{#e;constructor({lock:e,...r},t){super(r,t),this.#e=e}getReader(){let e=super.getReader();return this.locked&&this.#e?.(),e}pipeThrough(e,r){let t=super.pipeThrough(e,r);return this.locked&&this.#e?.(),t}pipeTo(e,r){let t=super.pipeTo(e,r);return this.locked&&this.#e?.(),t}tee(){let[e,r]=super.tee();return this.locked&&this.#e?.(),[e,r]}};async function g(){return await new Promise(o=>queueMicrotask(o))}function ie(o,e,{transformAtoB:r,transformBtoA:t}={}){let n=r?o.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=r(c);a.enqueue(i)}catch(i){console.warn("Error transforming A to B",i)}}})):o.readable,s=t?e.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=t(c);a.enqueue(i)}catch(i){console.warn("Error transforming B to A",i)}}})):e.readable;n.pipeTo(e.writable),s.pipeTo(o.writable)}var f=class{#e;get exports(){if(!this.#e)throw new Error("exports were not registered");return this.#e}register(e){this.#e=e}smartMalloc(e){return new R(this.exports.malloc(e),this.exports.free)}copyToMemory(e){let r=e.length,t=this.smartMalloc(r);return new Uint8Array(this.exports.memory.buffer,t.valueOf(),r).set(e),t}copyFromMemory(e,r){let t=this.exports.memory.buffer.slice(Number(e),Number(e)+r);return new Uint8Array(t)}viewFromMemory(e,r){return new Uint8Array(this.exports.memory.buffer,Number(e),r)}};import{generateMacAddress as ae,parseIPv4Address as Y,parseMacAddress as ce,serializeIPv4Cidr as pe,serializeMacAddress as de}from"@tcpip/wire";var A={ERR_OK:0,ERR_MEM:-1,ERR_BUF:-2,ERR_TIMEOUT:-3,ERR_RTE:-4,ERR_INPROGRESS:-5,ERR_VAL:-6,ERR_WOULDBLOCK:-7,ERR_USE:-8,ERR_ALREADY:-9,ERR_ISCONN:-10,ERR_CONN:-11,ERR_IF:-12,ERR_ABRT:-13,ERR_RST:-14,ERR_CLSD:-15,ERR_ARG:-16};var b=new l,O=class extends f{interfaces=new Map;imports={register_tap_interface:e=>{let r=new W;b.setOuter(r,{handle:e,sendFrame:t=>{let n=this.copyToMemory(t),s=this.exports.send_tap_interface(e,n,t.length);if(s!==A.ERR_OK)throw new Error(`failed to send frame: ${s}`)},getMacAddress:()=>{let t=this.exports.get_interface_mac_address(e),n=this.viewFromMemory(t,6);return ce(n)},getIPv4Address:()=>{let t=this.exports.get_interface_ip4_address(e);if(t===0)return;let n=this.viewFromMemory(t,4);return Y(n)},getIPv4Netmask:()=>{let t=this.exports.get_interface_ip4_netmask(e);if(t===0)return;let n=this.viewFromMemory(t,4);return Y(n)}}),this.interfaces.set(e,r)},receive_frame:async(e,r,t)=>{let n=this.copyFromMemory(r,t);await g();let s=this.interfaces.get(e);if(!s){console.error("received frame on unknown tap interface");return}b.getInner(s).receiveFrame(new Uint8Array(n))}};async create(e){var d=[];try{let r=e.mac?de(e.mac):ae();let{ipAddress:t,netmask:n}=e.ip?pe(e.ip):{};let s=p(d,this.copyToMemory(r));let c=p(d,t?this.copyToMemory(t):void 0);let a=p(d,n?this.copyToMemory(n):void 0);let i=this.exports.create_tap_interface(s,c??0,a??0);let m=this.interfaces.get(i);if(!m)throw new Error("tap interface failed to register");return m}catch(y){var I=y,v=!0}finally{u(d,I,v)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_tap_interface(r),this.interfaces.delete(r);return}}},W=class{#e;#t=!1;type="tap";get mac(){return b.getOuter(this).getMacAddress()}get ip(){return b.getOuter(this).getIPv4Address()}get netmask(){return b.getOuter(this).getIPv4Netmask()}readable;writable;constructor(){b.setInner(this,{receiveFrame:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");this.#e.enqueue(e)}}}),this.readable=new P({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{try{b.getOuter(this).sendFrame(e)}catch(r){console.error("tap interface send failed",r)}}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}[Symbol.asyncIterator](){return this.listen()}};var E=new l,U=class extends f{interfaces=new Map;imports={};async create(e){var I=[];try{let r=e.mac?fe(e.mac):me();let{ipAddress:t,netmask:n}=e.ip?ue(e.ip):{};let s=p(I,this.copyToMemory(r));let c=p(I,t?this.copyToMemory(t):void 0);let a=p(I,n?this.copyToMemory(n):void 0);let i=new Uint32Array(e.ports.map(k=>Number(b.getOuter(k).handle)));let m=p(I,this.copyToMemory(new Uint8Array(i.buffer)));let d=this.exports.create_bridge_interface(s,c??0,a??0,m,e.ports.length);let y=new j;E.setOuter(y,{handle:d,getMacAddress:()=>{let k=this.exports.get_interface_mac_address(d),S=this.viewFromMemory(k,6);return le(S)},getIPv4Address:()=>{let k=this.exports.get_interface_ip4_address(d);if(k===0)return;let S=this.viewFromMemory(k,4);return J(S)},getIPv4Netmask:()=>{let k=this.exports.get_interface_ip4_netmask(d);if(k===0)return;let S=this.viewFromMemory(k,4);return J(S)}});this.interfaces.set(d,y);return y}catch(v){var D=v,F=!0}finally{u(I,D,F)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_bridge_interface(r),this.interfaces.delete(r);return}}},j=class{type="bridge";get mac(){return E.getOuter(this).getMacAddress()}get ip(){return E.getOuter(this).getIPv4Address()}get netmask(){return E.getOuter(this).getIPv4Netmask()}};import{parseIPv4Address as V,serializeIPv4Cidr as he}from"@tcpip/wire";var z=new l,C=class extends f{interfaces=new Map;imports={register_loopback_interface:e=>{let r=new K;z.setOuter(r,{handle:e,getIPv4Address:()=>{let t=this.exports.get_interface_ip4_address(e);if(t===0)return;let n=this.viewFromMemory(t,4);return V(n)},getIPv4Netmask:()=>{let t=this.exports.get_interface_ip4_netmask(e);if(t===0)return;let n=this.viewFromMemory(t,4);return V(n)}}),this.interfaces.set(e,r)}};async create(e){var i=[];try{let{ipAddress:r,netmask:t}=e.ip?he(e.ip):{};let n=p(i,r?this.copyToMemory(r):void 0);let s=p(i,t?this.copyToMemory(t):void 0);let c=this.exports.create_loopback_interface(n??0,s??0);let a=this.interfaces.get(c);if(!a)throw new Error("loopback interface failed to register");return a}catch(m){var d=m,y=!0}finally{u(i,d,y)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_loopback_interface(r),this.interfaces.delete(r);return}}},K=class{type="loopback";get ip(){return z.getOuter(this).getIPv4Address()}get netmask(){return z.getOuter(this).getIPv4Netmask()}};import{serializeIPv4Address as ee}from"@tcpip/wire";var q=new l,_=new l,G=1448,nt=G*4,st=G*4,ye=G,M=class extends f{#e=new Map;#t=new T;#r=new Map;#n;async#s(e){try{return ee(e)}catch{let t=await this.#n.lookup(e);return ee(t)}}constructor(e){super(),this.#n=e}imports={accept_tcp_connection:async(e,r)=>{let t=this.#e.get(e);if(!t){console.error("new tcp connection to unknown listener");return}await g();let n=new L;_.setOuter(n,{send:async s=>{let c=Number(this.copyToMemory(s)),a=this.exports.send_tcp_chunk(r,c,s.length);for(;a<s.length;){await new Promise(m=>{this.#r.set(r,m)});let i=s.length-a;a+=this.exports.send_tcp_chunk(r,c+a,i)}},updateReceiveBuffer:s=>{this.exports.update_tcp_receive_buffer(r,s)},close:async()=>{let s=this.exports.close_tcp_connection(r);if(s!==A.ERR_OK)throw new Error(`failed to close tcp connection: ${s}`)}}),this.#t.set(r,n),q.getInner(t).accept(n)},connected_tcp_connection:async e=>{await g();let r=new L;_.setOuter(r,{send:async t=>{let n=Number(this.copyToMemory(t)),s=this.exports.send_tcp_chunk(e,n,t.length);for(;s<t.length;){await new Promise(a=>{this.#r.set(e,a)});let c=t.length-s;s+=this.exports.send_tcp_chunk(e,n+s,c)}},updateReceiveBuffer:t=>{this.exports.update_tcp_receive_buffer(e,t)},close:async()=>{this.exports.close_tcp_connection(e)}}),this.#t.set(e,r)},closed_tcp_connection:async e=>{let r=this.#t.get(e);if(!r){console.error("received close on unknown tcp connection");return}await _.getInner(r).close()},receive_tcp_chunk:async(e,r,t)=>{let n=this.copyFromMemory(r,t),s=this.#t.get(e);if(!s){console.error("received chunk on unknown tcp connection");return}await g(),_.getInner(s).receive(new Uint8Array(n))},sent_tcp_chunk:(e,r)=>{let t=this.#r.get(e);this.#r.delete(e),t?.(r)}};async listen(e){var s=[];try{let r=p(s,e.host?this.copyToMemory(await this.#s(e.host)):null);let t=this.exports.create_tcp_listener(r,e.port);let n=new $;q.setOuter(n,{});this.#e.set(t,n);return n}catch(c){var a=c,i=!0}finally{u(s,a,i)}}async connect(e){var s=[];try{let r=p(s,this.copyToMemory(await this.#s(e.host)));let t=this.exports.create_tcp_connection(r,e.port);let n=await this.#t.wait(t);if(!n)throw new Error("tcp failed to connect");return n}catch(c){var a=c,i=!0}finally{u(s,a,i)}}},$=class{#e=[];#t;constructor(){q.setInner(this,{accept:async e=>{this.#e.push(e),this.#t?.()}})}async*[Symbol.asyncIterator](){for(;;)await new Promise(e=>{this.#t=e}),yield*this.#e,this.#e=[]}},L=class{#e=[];#t;#r;readable;writable;constructor(){_.setInner(this,{receive:async e=>{this.#e.push(e),this.#n()},close:async()=>{this.close()}}),this.readable=new ReadableStream({start:e=>{this.#t=e},pull:()=>{this.#n()}},{highWaterMark:ye,size:e=>e.byteLength}),this.writable=new WritableStream({start:e=>{this.#r=e},write:async e=>{await _.getOuter(this).send(e)}},{highWaterMark:0})}#n(){if(!(this.#t?.desiredSize>0))return;let e=0;for(;this.#e.length>0;){let r=this.#e[0].length;if(e>0&&e+r>this.#t.desiredSize)break;let t=this.#e.shift();this.#t.enqueue(t),e+=t.length}e>0&&_.getOuter(this).updateReceiveBuffer(e)}async close(){await _.getOuter(this).close(),this.#t?.error(new Error("tcp connection closed")),this.#r?.error(new Error("tcp connection closed"))}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}};import{parseIPv4Address as te,serializeIPv4Cidr as ke}from"@tcpip/wire";var x=new l,B=class extends f{interfaces=new Map;imports={register_tun_interface:e=>{let r=new Q;x.setOuter(r,{handle:e,sendPacket:t=>{let n=this.copyToMemory(t);this.exports.send_tun_interface(e,n,t.length)},getIPv4Address:()=>{let t=this.exports.get_interface_ip4_address(e);if(t===0)return;let n=this.viewFromMemory(t,4);return te(n)},getIPv4Netmask:()=>{let t=this.exports.get_interface_ip4_netmask(e);if(t===0)return;let n=this.viewFromMemory(t,4);return te(n)}}),this.interfaces.set(e,r)},receive_packet:async(e,r,t)=>{let n=this.copyFromMemory(r,t);await g();let s=this.interfaces.get(e);if(!s){console.error("received packet on unknown tun interface");return}x.getInner(s).receivePacket(new Uint8Array(n))}};async create(e){var i=[];try{let{ipAddress:r,netmask:t}=e.ip?ke(e.ip):{};let n=p(i,r?this.copyToMemory(r):void 0);let s=p(i,t?this.copyToMemory(t):void 0);let c=this.exports.create_tun_interface(n??0,s??0);let a=this.interfaces.get(c);if(!a)throw new Error("tun interface failed to register");return a}catch(m){var d=m,y=!0}finally{u(i,d,y)}}async remove(e){for(let[r,t]of this.interfaces.entries())if(t===e){this.exports.remove_tun_interface(r),this.interfaces.delete(r);return}}},Q=class{#e;#t=!1;type="tun";get ip(){return x.getOuter(this).getIPv4Address()}get netmask(){return x.getOuter(this).getIPv4Netmask()}readable;writable;constructor(){x.setInner(this,{receivePacket:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");this.#e?.enqueue(e)}}}),this.readable=new P({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{x.getOuter(this).sendPacket(e)}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}[Symbol.asyncIterator](){return this.listen()}};import{parseIPv4Address as Ie,serializeIPv4Address as re}from"@tcpip/wire";var H=new l,N=class extends f{#e=new T;#t;async#r(e){try{return re(e)}catch{let t=await this.#t.lookup(e);return re(t)}}constructor(e){super(),this.#t=e}imports={receive_udp_datagram:async(e,r,t,n,s)=>{let c=this.copyFromMemory(r,4),a=this.copyFromMemory(n,s),i=this.#e.get(e);if(!i){console.error("received datagram on unknown udp socket");return}await g(),H.getInner(i).receive({host:Ie(c),port:t,data:a})}};async open(e){var s=[];try{let r=p(s,e.host?this.copyToMemory(await this.#r(e.host)):null);let t=this.exports.open_udp_socket(r,e.port??0);if(Number(t)===0)throw new Error("failed to open udp socket");let n=new Z;H.setOuter(n,{send:async m=>{var v=[];try{let d=p(v,this.copyToMemory(await this.#r(m.host)));let y=p(v,this.copyToMemory(m.data));let I=this.exports.send_udp_datagram(t,d,m.port,y,m.data.length);if(I!==A.ERR_OK)throw new Error(`failed to send udp datagram: ${I}`)}catch(D){var F=D,k=!0}finally{u(v,F,k)}},close:async()=>{this.exports.close_udp_socket(t),this.#e.delete(t)}});this.#e.set(t,n);return n}catch(c){var a=c,i=!0}finally{u(s,a,i)}}},Z=class{#e;#t;readable;writable;constructor(){H.setInner(this,{receive:async e=>{if(!this.#e)throw new Error("readable controller not initialized");this.#e.enqueue(e)}}),this.readable=new ReadableStream({start:e=>{this.#e=e}}),this.writable=new WritableStream({start:e=>{this.#t=e},write:async e=>{await H.getOuter(this).send(e)}})}async close(){await H.getOuter(this).close(),this.#e?.error(new Error("udp socket closed")),this.#t?.error(new Error("udp socket closed"))}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return w(this.readable)}};var ge=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";async function ne(o,e){return ge?be(o,e):fetch(o)}async function be(o,e){let r=await import("fs"),{Readable:t}=await import("stream"),n=r.createReadStream(o),s=t.toWeb(n);return new Response(s,{headers:{"Content-Type":e}})}async function Pe(o){let e=new X(o);return await e.ready,e}var X=class{#e;#t;#r;#n;#s;#o;#i;#a;#c;ready;get interfaces(){return this.#d()}constructor(e={}){this.#e={...e,initializeLoopback:e.initializeLoopback??!0},this.#r=new Te(this,{nameServer:e.nameServer??{ip:"127.0.0.1",port:53}}),this.#n=new C,this.#s=new B,this.#o=new O,this.#i=new U,this.#a=new M(this.#r),this.#c=new N(this.#r),this.ready=this.#p(),this.ready.then(async()=>{this.#e.initializeLoopback&&await this.createLoopbackInterface({ip:"127.0.0.1/8"})})}async#p(){let e=new ve([],[],[new _e(new we([])),se.lineBuffered(s=>console.log(`[WASI stdout] ${s}`)),se.lineBuffered(s=>console.warn(`[WASI stderr] ${s}`))]),r=ne(new URL("../tcpip.wasm",import.meta.url),"application/wasm"),{instance:t}=await WebAssembly.instantiateStreaming(r,{wasi_snapshot_preview1:e.wasiImport,env:{...this.#n.imports,...this.#s.imports,...this.#o.imports,...this.#i.imports,...this.#a.imports,...this.#c.imports}}),n=t;this.#n.register(n.exports),this.#s.register(n.exports),this.#o.register(n.exports),this.#i.register(n.exports),this.#a.register(n.exports),this.#c.register(n.exports),e.initialize(n),this.#t=Number(setInterval(()=>{n.exports.process_queued_packets(),n.exports.process_timeouts()},100))}*#d(){yield*this.#n.interfaces.values(),yield*this.#s.interfaces.values(),yield*this.#o.interfaces.values(),yield*this.#i.interfaces.values()}async createLoopbackInterface(e){return await this.ready,this.#n.create(e)}async createTunInterface(e){return await this.ready,this.#s.create(e)}async createTapInterface(e={}){return await this.ready,this.#o.create(e)}async createBridgeInterface(e){return await this.ready,this.#i.create(e)}async removeInterface(e){switch(await this.ready,e.type){case"loopback":return this.#n.remove(e);case"tun":return this.#s.remove(e);case"tap":return this.#o.remove(e);case"bridge":return this.#i.remove(e);default:throw new Error("unknown interface type")}}async listenTcp(e){return await this.ready,this.#a.listen(e)}async connectTcp(e){return await this.ready,this.#a.connect(e)}async openUdp(e={}){return await this.ready,this.#c.open(e)}};export{ie as connectStreams,Pe as createStack};
1
+ import{a as p,b as u,c as h}from"./chunk-T54CGJHW.js";import{ConsoleStdout as se,File as we,OpenFile as _e,WASI as ve}from"@bjorn3/browser_wasi_shim";import{DnsClient as Te}from"@tcpip/dns";import{generateMacAddress as me,parseIPv4Address as J,parseMacAddress as le,serializeIPv4Cidr as ue,serializeMacAddress as fe}from"@tcpip/wire";var l=class{#e=new WeakMap;#t=new WeakMap;setOuter(e,t){this.#e.set(e,t)}setInner(e,t){this.#t.set(e,t)}getOuter(e){let t=this.#e.get(e);if(!t)throw new Error(`outer hooks not set for ${e}`);return t}getInner(e){let t=this.#t.get(e);if(!t)throw new Error(`inner hooks not set for ${e}`);return t}},S=class extends Number{free;constructor(e,t){super(e),this.free=t}[h](){this.free(this.valueOf())}},P=class extends Map{#e=new Map;wait(e){return new Promise(t=>{let r=this.#e.get(e)??new Set;r.add(t),this.#e.set(e,r)})}set(e,t){super.set(e,t);let r=this.#e.get(e);if(r)for(let n of r)n(t),r.delete(n);return this}};function v(o,e){let t=o.getReader();return oe(t,e)}async function*oe(o,e){try{for(;;){let{done:t,value:r}=await o.read();if(t)return r;yield r}}finally{e?.preventCancel||await o.cancel(),o.releaseLock()}}var A=class extends ReadableStream{#e;constructor({lock:e,...t},r){super(t,r),this.#e=e}getReader(){let e=super.getReader();return this.locked&&this.#e?.(),e}pipeThrough(e,t){let r=super.pipeThrough(e,t);return this.locked&&this.#e?.(),r}pipeTo(e,t){let r=super.pipeTo(e,t);return this.locked&&this.#e?.(),r}tee(){let[e,t]=super.tee();return this.locked&&this.#e?.(),[e,t]}};async function g(){return await new Promise(o=>queueMicrotask(o))}function ie(o,e,{transformAtoB:t,transformBtoA:r}={}){let n=t?o.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=t(c);a.enqueue(i)}catch(i){console.warn("Error transforming A to B",i)}}})):o.readable,s=r?e.readable.pipeThrough(new TransformStream({transform(c,a){try{let i=r(c);a.enqueue(i)}catch(i){console.warn("Error transforming B to A",i)}}})):e.readable;n.pipeTo(e.writable),s.pipeTo(o.writable)}var f=class{#e;get exports(){if(!this.#e)throw new Error("exports were not registered");return this.#e}register(e){this.#e=e}smartMalloc(e){return new S(this.exports.malloc(e),this.exports.free)}copyToMemory(e){let t=e.length,r=this.smartMalloc(t);return new Uint8Array(this.exports.memory.buffer,r.valueOf(),t).set(e),r}copyFromMemory(e,t){let r=this.exports.memory.buffer.slice(Number(e),Number(e)+t);return new Uint8Array(r)}viewFromMemory(e,t){return new Uint8Array(this.exports.memory.buffer,Number(e),t)}};import{generateMacAddress as ae,parseIPv4Address as Y,parseMacAddress as ce,serializeIPv4Cidr as pe,serializeMacAddress as de}from"@tcpip/wire";var b={ERR_OK:0,ERR_MEM:-1,ERR_BUF:-2,ERR_TIMEOUT:-3,ERR_RTE:-4,ERR_INPROGRESS:-5,ERR_VAL:-6,ERR_WOULDBLOCK:-7,ERR_USE:-8,ERR_ALREADY:-9,ERR_ISCONN:-10,ERR_CONN:-11,ERR_IF:-12,ERR_ABRT:-13,ERR_RST:-14,ERR_CLSD:-15,ERR_ARG:-16};var w=new l,E=class extends f{interfaces=new Map;imports={register_tap_interface:e=>{let t=new F;w.setOuter(t,{handle:e,sendFrame:r=>{let n=this.copyToMemory(r),s=this.exports.send_tap_interface(e,n,r.length);if(s!==b.ERR_OK)throw new Error(`failed to send frame: ${s}`)},getMacAddress:()=>{let r=this.exports.get_interface_mac_address(e),n=this.viewFromMemory(r,6);return ce(n)},getIPv4Address:()=>{let r=this.exports.get_interface_ip4_address(e);if(r===0)return;let n=this.viewFromMemory(r,4);return Y(n)},getIPv4Netmask:()=>{let r=this.exports.get_interface_ip4_netmask(e);if(r===0)return;let n=this.viewFromMemory(r,4);return Y(n)}}),this.interfaces.set(e,t)},receive_frame:async(e,t,r)=>{let n=this.copyFromMemory(t,r);await g();let s=this.interfaces.get(e);if(!s){console.error("received frame on unknown tap interface");return}w.getInner(s).receiveFrame(new Uint8Array(n))}};async create(e){var d=[];try{let t=e.mac?de(e.mac):ae();let{ipAddress:r,netmask:n}=e.ip?pe(e.ip):{};let s=p(d,this.copyToMemory(t));let c=p(d,r?this.copyToMemory(r):void 0);let a=p(d,n?this.copyToMemory(n):void 0);let i=this.exports.create_tap_interface(s,c??0,a??0);let m=this.interfaces.get(i);if(!m)throw new Error("tap interface failed to register");return m}catch(y){var I=y,T=!0}finally{u(d,I,T)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_tap_interface(t),this.interfaces.delete(t);return}}},F=class{#e;#t=!1;type="tap";get mac(){return w.getOuter(this).getMacAddress()}get ip(){return w.getOuter(this).getIPv4Address()}get netmask(){return w.getOuter(this).getIPv4Netmask()}readable;writable;constructor(){w.setInner(this,{receiveFrame:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");this.#e.enqueue(e)}}}),this.readable=new A({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{try{w.getOuter(this).sendFrame(e)}catch(t){console.error("tap interface send failed",t)}}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}[Symbol.asyncIterator](){return this.listen()}};var O=new l,C=class extends f{interfaces=new Map;imports={};async create(e){var I=[];try{let t=e.mac?fe(e.mac):me();let{ipAddress:r,netmask:n}=e.ip?ue(e.ip):{};let s=p(I,this.copyToMemory(t));let c=p(I,r?this.copyToMemory(r):void 0);let a=p(I,n?this.copyToMemory(n):void 0);let i=new Uint32Array(e.ports.map(k=>Number(w.getOuter(k).handle)));let m=p(I,this.copyToMemory(new Uint8Array(i.buffer)));let d=this.exports.create_bridge_interface(s,c??0,a??0,m,e.ports.length);let y=new K;O.setOuter(y,{handle:d,getMacAddress:()=>{let k=this.exports.get_interface_mac_address(d),R=this.viewFromMemory(k,6);return le(R)},getIPv4Address:()=>{let k=this.exports.get_interface_ip4_address(d);if(k===0)return;let R=this.viewFromMemory(k,4);return J(R)},getIPv4Netmask:()=>{let k=this.exports.get_interface_ip4_netmask(d);if(k===0)return;let R=this.viewFromMemory(k,4);return J(R)}});this.interfaces.set(d,y);return y}catch(T){var W=T,D=!0}finally{u(I,W,D)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_bridge_interface(t),this.interfaces.delete(t);return}}},K=class{type="bridge";get mac(){return O.getOuter(this).getMacAddress()}get ip(){return O.getOuter(this).getIPv4Address()}get netmask(){return O.getOuter(this).getIPv4Netmask()}};import{parseIPv4Address as V,serializeIPv4Cidr as he}from"@tcpip/wire";var j=new l,U=class extends f{interfaces=new Map;imports={register_loopback_interface:e=>{let t=new z;j.setOuter(t,{handle:e,getIPv4Address:()=>{let r=this.exports.get_interface_ip4_address(e);if(r===0)return;let n=this.viewFromMemory(r,4);return V(n)},getIPv4Netmask:()=>{let r=this.exports.get_interface_ip4_netmask(e);if(r===0)return;let n=this.viewFromMemory(r,4);return V(n)}}),this.interfaces.set(e,t)}};async create(e){var i=[];try{let{ipAddress:t,netmask:r}=e.ip?he(e.ip):{};let n=p(i,t?this.copyToMemory(t):void 0);let s=p(i,r?this.copyToMemory(r):void 0);let c=this.exports.create_loopback_interface(n??0,s??0);let a=this.interfaces.get(c);if(!a)throw new Error("loopback interface failed to register");return a}catch(m){var d=m,y=!0}finally{u(i,d,y)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_loopback_interface(t),this.interfaces.delete(t);return}}},z=class{type="loopback";get ip(){return j.getOuter(this).getIPv4Address()}get netmask(){return j.getOuter(this).getIPv4Netmask()}};import{serializeIPv4Address as ee}from"@tcpip/wire";var q=new l,_=new l,G=1448,nt=G*4,st=G*4,ye=G,M=class extends f{#e=new Map;#t=new P;#r=new Map;#n=new Map;#s;async#o(e){try{return ee(e)}catch{let r=await this.#s.lookup(e);return ee(r)}}constructor(e){super(),this.#s=e}async#a(e){for(;;){let t=this.exports.close_tcp_connection(e);if(t===b.ERR_OK)return;if(t!==b.ERR_MEM)throw new Error(`failed to close tcp connection: ${t}`);await new Promise(r=>{this.#n.set(e,r)})}}async#i(e){for(;;){let t=this.exports.shutdown_tcp_connection_write(e);if(t===b.ERR_OK)return;if(t!==b.ERR_MEM)throw new Error(`failed to shutdown tcp write side: ${t}`);await new Promise(r=>{this.#n.set(e,r)})}}imports={accept_tcp_connection:async(e,t)=>{let r=this.#e.get(e);if(!r){console.error("new tcp connection to unknown listener");return}await g();let n=new L;_.setOuter(n,{send:async s=>{let c=Number(this.copyToMemory(s)),a=this.exports.send_tcp_chunk(t,c,s.length);for(;a<s.length;){await new Promise(m=>{this.#r.set(t,m)});let i=s.length-a;a+=this.exports.send_tcp_chunk(t,c+a,i)}},updateReceiveBuffer:s=>{this.exports.update_tcp_receive_buffer(t,s)},close:async()=>{await this.#a(t)},closeWrite:async()=>{await this.#i(t)}}),this.#t.set(t,n),q.getInner(r).accept(n)},connected_tcp_connection:async e=>{await g();let t=new L;_.setOuter(t,{send:async r=>{let n=Number(this.copyToMemory(r)),s=this.exports.send_tcp_chunk(e,n,r.length);for(;s<r.length;){await new Promise(a=>{this.#r.set(e,a)});let c=r.length-s;s+=this.exports.send_tcp_chunk(e,n+s,c)}},updateReceiveBuffer:r=>{this.exports.update_tcp_receive_buffer(e,r)},close:async()=>{await this.#a(e)},closeWrite:async()=>{await this.#i(e)}}),this.#t.set(e,t)},closed_tcp_connection:async e=>{let t=this.#t.get(e);if(!t){console.error("received close on unknown tcp connection");return}await _.getInner(t).close()},receive_tcp_chunk:async(e,t,r)=>{let n=this.copyFromMemory(t,r),s=this.#t.get(e);if(!s){console.error("received chunk on unknown tcp connection");return}await g(),_.getInner(s).receive(new Uint8Array(n))},sent_tcp_chunk:(e,t)=>{let r=this.#r.get(e);this.#r.delete(e),r?.(t);let n=this.#n.get(e);this.#n.delete(e),n?.()}};async listen(e){var s=[];try{let t=p(s,e.host?this.copyToMemory(await this.#o(e.host)):null);let r=this.exports.create_tcp_listener(t,e.port);let n=new $;q.setOuter(n,{});this.#e.set(r,n);return n}catch(c){var a=c,i=!0}finally{u(s,a,i)}}async connect(e){var s=[];try{let t=p(s,this.copyToMemory(await this.#o(e.host)));let r=this.exports.create_tcp_connection(t,e.port);let n=await this.#t.wait(r);if(!n)throw new Error("tcp failed to connect");return n}catch(c){var a=c,i=!0}finally{u(s,a,i)}}},$=class{#e=[];#t;constructor(){q.setInner(this,{accept:async e=>{this.#e.push(e),this.#t?.()}})}async*[Symbol.asyncIterator](){for(;;)await new Promise(e=>{this.#t=e}),yield*this.#e,this.#e=[]}},L=class{#e=[];#t;#r;#n=!1;#s=!1;readable;writable;constructor(){_.setInner(this,{receive:async e=>{this.#e.push(e),this.#i()},close:async()=>{await g(),this.#n=!0,this.#i()}}),this.readable=new ReadableStream({start:e=>{this.#t=e},pull:()=>{this.#i()}},{highWaterMark:ye,size:e=>e.byteLength}),this.writable=new WritableStream({start:e=>{this.#r=e},write:async e=>{await _.getOuter(this).send(e)},close:async()=>{await _.getOuter(this).closeWrite()}},{highWaterMark:1})}#o(){if(!this.#s){this.#s=!0;try{this.#t?.close()}catch{}}}#a(e){if(!this.#s){this.#s=!0;try{this.#t?.error(e)}catch{}}}#i(){if(this.#n&&this.#e.length===0){this.#o(),this.#r?.error(new Error("tcp connection closed"));return}if(!(this.#t?.desiredSize>0))return;let e=0;for(;this.#e.length>0;){let t=this.#e[0].length;if(e>0&&e+t>this.#t.desiredSize)break;let r=this.#e.shift();this.#t.enqueue(r),e+=r.length}e>0&&_.getOuter(this).updateReceiveBuffer(e),this.#n&&this.#e.length===0&&(this.#o(),this.#r?.error(new Error("tcp connection closed")))}async close(){await _.getOuter(this).close(),this.#a(new Error("tcp connection closed")),this.#r?.error(new Error("tcp connection closed"))}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}};import{parseIPv4Address as te,serializeIPv4Cidr as ke}from"@tcpip/wire";var x=new l,B=class extends f{interfaces=new Map;imports={register_tun_interface:e=>{let t=new Q;x.setOuter(t,{handle:e,sendPacket:r=>{let n=this.copyToMemory(r);this.exports.send_tun_interface(e,n,r.length)},getIPv4Address:()=>{let r=this.exports.get_interface_ip4_address(e);if(r===0)return;let n=this.viewFromMemory(r,4);return te(n)},getIPv4Netmask:()=>{let r=this.exports.get_interface_ip4_netmask(e);if(r===0)return;let n=this.viewFromMemory(r,4);return te(n)}}),this.interfaces.set(e,t)},receive_packet:async(e,t,r)=>{let n=this.copyFromMemory(t,r);await g();let s=this.interfaces.get(e);if(!s){console.error("received packet on unknown tun interface");return}x.getInner(s).receivePacket(new Uint8Array(n))}};async create(e){var i=[];try{let{ipAddress:t,netmask:r}=e.ip?ke(e.ip):{};let n=p(i,t?this.copyToMemory(t):void 0);let s=p(i,r?this.copyToMemory(r):void 0);let c=this.exports.create_tun_interface(n??0,s??0);let a=this.interfaces.get(c);if(!a)throw new Error("tun interface failed to register");return a}catch(m){var d=m,y=!0}finally{u(i,d,y)}}async remove(e){for(let[t,r]of this.interfaces.entries())if(r===e){this.exports.remove_tun_interface(t),this.interfaces.delete(t);return}}},Q=class{#e;#t=!1;type="tun";get ip(){return x.getOuter(this).getIPv4Address()}get netmask(){return x.getOuter(this).getIPv4Netmask()}readable;writable;constructor(){x.setInner(this,{receivePacket:async e=>{if(this.#t){if(!this.#e)throw new Error("readable stream not initialized");this.#e?.enqueue(e)}}}),this.readable=new A({start:e=>{this.#e=e},lock:()=>{this.#t=!0}}),this.writable=new WritableStream({write:e=>{x.getOuter(this).sendPacket(e)}})}listen(){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}[Symbol.asyncIterator](){return this.listen()}};import{parseIPv4Address as ge,serializeIPv4Address as re}from"@tcpip/wire";var H=new l,N=class extends f{#e=new P;#t;async#r(e){try{return re(e)}catch{let r=await this.#t.lookup(e);return re(r)}}constructor(e){super(),this.#t=e}imports={receive_udp_datagram:async(e,t,r,n,s)=>{let c=this.copyFromMemory(t,4),a=this.copyFromMemory(n,s),i=this.#e.get(e);if(!i){console.error("received datagram on unknown udp socket");return}await g(),H.getInner(i).receive({host:ge(c),port:r,data:a})}};async open(e){var s=[];try{let t=p(s,e.host?this.copyToMemory(await this.#r(e.host)):null);let r=this.exports.open_udp_socket(t,e.port??0);if(Number(r)===0)throw new Error("failed to open udp socket");let n=new Z;H.setOuter(n,{send:async m=>{var T=[];try{let d=p(T,this.copyToMemory(await this.#r(m.host)));let y=p(T,this.copyToMemory(m.data));let I=this.exports.send_udp_datagram(r,d,m.port,y,m.data.length);if(I!==b.ERR_OK)throw new Error(`failed to send udp datagram: ${I}`)}catch(W){var D=W,k=!0}finally{u(T,D,k)}},close:async()=>{this.exports.close_udp_socket(r),this.#e.delete(r)}});this.#e.set(r,n);return n}catch(c){var a=c,i=!0}finally{u(s,a,i)}}},Z=class{#e;#t;readable;writable;constructor(){H.setInner(this,{receive:async e=>{if(!this.#e)throw new Error("readable controller not initialized");this.#e.enqueue(e)}}),this.readable=new ReadableStream({start:e=>{this.#e=e}}),this.writable=new WritableStream({start:e=>{this.#t=e},write:async e=>{await H.getOuter(this).send(e)}})}async close(){await H.getOuter(this).close(),this.#e?.error(new Error("udp socket closed")),this.#t?.error(new Error("udp socket closed"))}[Symbol.asyncIterator](){if(this.readable.locked)throw new Error("readable stream already locked");return v(this.readable)}};var Ie=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";async function ne(o,e){return Ie?be(o,e):fetch(o)}async function be(o,e){let t=await import("fs"),{Readable:r}=await import("stream"),n=t.createReadStream(o),s=r.toWeb(n);return new Response(s,{headers:{"Content-Type":e}})}async function Pe(o){let e=new X(o);return await e.ready,e}var X=class{#e;#t;#r;#n;#s;#o;#a;#i;#c;ready;get interfaces(){return this.#d()}constructor(e={}){this.#e={...e,initializeLoopback:e.initializeLoopback??!0},this.#r=new Te(this,{nameServer:e.nameServer??{ip:"127.0.0.1",port:53}}),this.#n=new U,this.#s=new B,this.#o=new E,this.#a=new C,this.#i=new M(this.#r),this.#c=new N(this.#r),this.ready=this.#p(),this.ready.then(async()=>{this.#e.initializeLoopback&&await this.createLoopbackInterface({ip:"127.0.0.1/8"})})}async#p(){let e=new ve([],[],[new _e(new we([])),se.lineBuffered(s=>console.log(`[WASI stdout] ${s}`)),se.lineBuffered(s=>console.warn(`[WASI stderr] ${s}`))]),t=ne(new URL("../tcpip.wasm",import.meta.url),"application/wasm"),{instance:r}=await WebAssembly.instantiateStreaming(t,{wasi_snapshot_preview1:e.wasiImport,env:{...this.#n.imports,...this.#s.imports,...this.#o.imports,...this.#a.imports,...this.#i.imports,...this.#c.imports}}),n=r;this.#n.register(n.exports),this.#s.register(n.exports),this.#o.register(n.exports),this.#a.register(n.exports),this.#i.register(n.exports),this.#c.register(n.exports),e.initialize(n),this.#t=Number(setInterval(()=>{n.exports.process_queued_packets(),n.exports.process_timeouts()},100))}*#d(){yield*this.#n.interfaces.values(),yield*this.#s.interfaces.values(),yield*this.#o.interfaces.values(),yield*this.#a.interfaces.values()}async createLoopbackInterface(e){return await this.ready,this.#n.create(e)}async createTunInterface(e){return await this.ready,this.#s.create(e)}async createTapInterface(e={}){return await this.ready,this.#o.create(e)}async createBridgeInterface(e){return await this.ready,this.#a.create(e)}async removeInterface(e){switch(await this.ready,e.type){case"loopback":return this.#n.remove(e);case"tun":return this.#s.remove(e);case"tap":return this.#o.remove(e);case"bridge":return this.#a.remove(e);default:throw new Error("unknown interface type")}}async listenTcp(e){return await this.ready,this.#i.listen(e)}async connectTcp(e){return await this.ready,this.#i.connect(e)}async openUdp(e={}){return await this.ready,this.#c.open(e)}};export{ie as connectStreams,Pe as createStack};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stack.ts","../src/bindings/bridge-interface.ts","../src/util.ts","../src/bindings/base.ts","../src/bindings/tap-interface.ts","../src/lwip/errors.ts","../src/bindings/loopback-interface.ts","../src/bindings/tcp.ts","../src/bindings/tun-interface.ts","../src/bindings/udp.ts","../src/fetch-file.ts"],"sourcesContent":["import { ConsoleStdout, File, OpenFile, WASI } from '@bjorn3/browser_wasi_shim';\nimport { DnsClient, type NameServer } from '@tcpip/dns';\nimport { BridgeBindings } from './bindings/bridge-interface.js';\nimport { LoopbackBindings } from './bindings/loopback-interface.js';\nimport { TapBindings } from './bindings/tap-interface.js';\nimport { TcpBindings } from './bindings/tcp.js';\nimport { TunBindings } from './bindings/tun-interface.js';\nimport type { WasmInstance } from './bindings/types.js';\nimport { UdpBindings } from './bindings/udp.js';\nimport { fetchFile } from './fetch-file.js';\nimport type {\n BridgeInterfaceOptions,\n LoopbackInterface,\n LoopbackInterfaceOptions,\n NetworkInterface,\n NetworkStack,\n TapInterface,\n TapInterfaceOptions,\n TcpConnectionOptions,\n TcpListenerOptions,\n TunInterface,\n TunInterfaceOptions,\n UdpSocketOptions,\n} from './types.js';\n\nexport async function createStack(\n options?: NetworkStackOptions\n): Promise<NetworkStack> {\n const stack = new VirtualNetworkStack(options);\n await stack.ready;\n return stack;\n}\n\nexport type NetworkStackOptions = {\n /**\n * Whether to initialize a loopback interface on startup.\n *\n * @default true\n */\n initializeLoopback?: boolean;\n\n /**\n * Name server used for DNS resolution.\n *\n * @default { ip: '127.0.0.1', port: 53 }\n */\n nameServer?: NameServer;\n};\n\nexport class VirtualNetworkStack implements NetworkStack {\n #options: NetworkStackOptions;\n #loopIntervalId?: number;\n #dnsClient: DnsClient;\n\n #loopbackBindings: LoopbackBindings;\n #tunBindings: TunBindings;\n #tapBindings: TapBindings;\n #bridgeBindings: BridgeBindings;\n #tcpBindings: TcpBindings;\n #udpBindings: UdpBindings;\n\n ready: Promise<void>;\n get interfaces() {\n return this.#listInterfaces();\n }\n\n constructor(options: NetworkStackOptions = {}) {\n this.#options = {\n ...options,\n initializeLoopback: options.initializeLoopback ?? true,\n };\n\n this.#dnsClient = new DnsClient(this, {\n nameServer: options.nameServer ?? { ip: '127.0.0.1', port: 53 },\n });\n\n // Initialize bindings\n this.#loopbackBindings = new LoopbackBindings();\n this.#tunBindings = new TunBindings();\n this.#tapBindings = new TapBindings();\n this.#bridgeBindings = new BridgeBindings();\n this.#tcpBindings = new TcpBindings(this.#dnsClient);\n this.#udpBindings = new UdpBindings(this.#dnsClient);\n\n // Initialize the stack\n this.ready = this.#init();\n\n // Post-init setup\n this.ready.then(async () => {\n if (this.#options.initializeLoopback) {\n await this.createLoopbackInterface({\n ip: '127.0.0.1/8',\n });\n }\n });\n }\n\n async #init() {\n const wasi = new WASI(\n [],\n [],\n [\n new OpenFile(new File([])), // stdin\n ConsoleStdout.lineBuffered((msg) =>\n console.log(`[WASI stdout] ${msg}`)\n ),\n ConsoleStdout.lineBuffered((msg) =>\n console.warn(`[WASI stderr] ${msg}`)\n ),\n ]\n );\n\n const source = fetchFile(\n new URL('../tcpip.wasm', import.meta.url),\n 'application/wasm'\n );\n\n // Instantiate with both WASI and custom imports\n const { instance } = await WebAssembly.instantiateStreaming(source, {\n wasi_snapshot_preview1: wasi.wasiImport,\n env: {\n ...this.#loopbackBindings.imports,\n ...this.#tunBindings.imports,\n ...this.#tapBindings.imports,\n ...this.#bridgeBindings.imports,\n ...this.#tcpBindings.imports,\n ...this.#udpBindings.imports,\n },\n });\n\n const wasmInstance = instance as WasmInstance;\n\n this.#loopbackBindings.register(wasmInstance.exports);\n this.#tunBindings.register(wasmInstance.exports);\n this.#tapBindings.register(wasmInstance.exports);\n this.#bridgeBindings.register(wasmInstance.exports);\n this.#tcpBindings.register(wasmInstance.exports);\n this.#udpBindings.register(wasmInstance.exports);\n\n // Our WASM binary is a WASI reactor module (ie. a lib),\n // so we call `initialize()` instead of `start()`.\n wasi.initialize(wasmInstance);\n\n // Call lwIP's main loop regularly (required in NO_SYS mode)\n // Used to process queued packets (eg. loopback) and expired timeouts\n this.#loopIntervalId = Number(\n setInterval(() => {\n wasmInstance.exports.process_queued_packets();\n wasmInstance.exports.process_timeouts();\n }, 100)\n );\n }\n\n *#listInterfaces(): Iterable<NetworkInterface> {\n yield* this.#loopbackBindings.interfaces.values();\n yield* this.#tunBindings.interfaces.values();\n yield* this.#tapBindings.interfaces.values();\n yield* this.#bridgeBindings.interfaces.values();\n }\n\n async createLoopbackInterface(\n options: LoopbackInterfaceOptions\n ): Promise<LoopbackInterface> {\n await this.ready;\n return this.#loopbackBindings.create(options);\n }\n\n async createTunInterface(\n options: TunInterfaceOptions\n ): Promise<TunInterface> {\n await this.ready;\n return this.#tunBindings.create(options);\n }\n\n async createTapInterface(\n options: TapInterfaceOptions = {}\n ): Promise<TapInterface> {\n await this.ready;\n return this.#tapBindings.create(options);\n }\n\n async createBridgeInterface(options: BridgeInterfaceOptions) {\n await this.ready;\n return this.#bridgeBindings.create(options);\n }\n\n async removeInterface(netInterface: NetworkInterface) {\n await this.ready;\n\n switch (netInterface.type) {\n case 'loopback':\n return this.#loopbackBindings.remove(netInterface);\n case 'tun':\n return this.#tunBindings.remove(netInterface);\n case 'tap':\n return this.#tapBindings.remove(netInterface);\n case 'bridge':\n return this.#bridgeBindings.remove(netInterface);\n default:\n throw new Error('unknown interface type');\n }\n }\n\n /**\n * Listens for incoming TCP connections on the specified host/port.\n */\n async listenTcp(options: TcpListenerOptions) {\n await this.ready;\n return this.#tcpBindings.listen(options);\n }\n\n /**\n * Establishes an outbound TCP connection to a remote host/port.\n */\n async connectTcp(options: TcpConnectionOptions) {\n await this.ready;\n return this.#tcpBindings.connect(options);\n }\n\n /**\n * Opens a UDP socket for sending and receiving datagrams.\n *\n * If no local host is provided, the socket will bind to all available interfaces.\n * If no local port is provided, the socket will bind to a random port.\n */\n async openUdp(options: UdpSocketOptions = {}) {\n await this.ready;\n return this.#udpBindings.open(options);\n }\n}\n","import {\n type IPv4Address,\n type MacAddress,\n generateMacAddress,\n parseIPv4Address,\n parseMacAddress,\n serializeIPv4Cidr,\n serializeMacAddress,\n} from '@tcpip/wire';\nimport type { BridgeInterface, BridgeInterfaceOptions } from '../types.js';\nimport { Hooks } from '../util.js';\nimport { Bindings } from './base.js';\nimport { tapInterfaceHooks } from './tap-interface.js';\nimport type { Pointer } from './types.js';\n\ntype BridgeInterfaceHandle = Pointer;\n\ntype BridgeInterfaceOuterHooks = {\n handle: BridgeInterfaceHandle;\n getMacAddress(): MacAddress;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty hook type\ntype BridgeInterfaceInnerHooks = {};\n\nexport const bridgeInterfaceHooks = new Hooks<\n BridgeInterface,\n BridgeInterfaceOuterHooks,\n BridgeInterfaceInnerHooks\n>();\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty imports type\nexport type BridgeImports = {};\n\nexport type BridgeExports = {\n create_bridge_interface(\n macAddress: Pointer,\n ipAddress: Pointer,\n netmask: Pointer,\n ports: Pointer,\n ports_length: number\n ): BridgeInterfaceHandle;\n remove_bridge_interface(handle: BridgeInterfaceHandle): void;\n};\n\nexport class BridgeBindings extends Bindings<BridgeImports, BridgeExports> {\n interfaces = new Map<BridgeInterfaceHandle, BridgeInterface>();\n\n imports = {};\n\n async create(options: BridgeInterfaceOptions) {\n const macAddress = options.mac\n ? serializeMacAddress(options.mac)\n : generateMacAddress();\n\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using macAddressPtr = this.copyToMemory(macAddress);\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n const portHandles = new Uint32Array(\n options.ports.map((port) =>\n Number(tapInterfaceHooks.getOuter(port).handle)\n )\n );\n\n using portHandlesPtr = this.copyToMemory(\n new Uint8Array(portHandles.buffer)\n );\n\n const handle = this.exports.create_bridge_interface(\n macAddressPtr,\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0,\n portHandlesPtr,\n options.ports.length\n );\n\n const bridgeInterface = new VirtualBridgeInterface();\n\n bridgeInterfaceHooks.setOuter(bridgeInterface, {\n handle,\n getMacAddress: () => {\n const macPtr = this.exports.get_interface_mac_address(handle);\n\n const macBytes = this.viewFromMemory(macPtr, 6);\n return parseMacAddress(macBytes);\n },\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, bridgeInterface);\n\n return bridgeInterface;\n }\n\n async remove(bridgeInterface: BridgeInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === bridgeInterface) {\n this.exports.remove_bridge_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualBridgeInterface implements BridgeInterface {\n readonly type = 'bridge';\n get mac(): MacAddress {\n return bridgeInterfaceHooks.getOuter(this).getMacAddress();\n }\n get ip(): IPv4Address | undefined {\n return bridgeInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return bridgeInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n}\n","import type { DuplexStream } from './types.js';\n\n/**\n * Utility class to facilitate internal communication\n * between bindings and JS instances.\n * Hooks are created for both the outer (bindings) and\n * inner (JS instance) sides of the communication.\n *\n * Uses `WeakMap` to map each JS instance to a set of\n * hooks while avoiding memory leaks.\n */\nexport class Hooks<K extends WeakKey, O, I> {\n #outerHooks = new WeakMap<K, O>();\n #innerHooks = new WeakMap<K, I>();\n\n setOuter(key: K, hooks: O) {\n this.#outerHooks.set(key, hooks);\n }\n\n setInner(key: K, hooks: I) {\n this.#innerHooks.set(key, hooks);\n }\n\n getOuter(key: K) {\n const hooks = this.#outerHooks.get(key);\n\n if (!hooks) {\n throw new Error(`outer hooks not set for ${key}`);\n }\n\n return hooks;\n }\n\n getInner(key: K) {\n const hooks = this.#innerHooks.get(key);\n\n if (!hooks) {\n throw new Error(`inner hooks not set for ${key}`);\n }\n\n return hooks;\n }\n}\n\nexport class UniquePointer extends Number {\n free: (ptr: number) => void;\n\n /**\n * A unique pointer that will automatically free virtual memory when\n * it is disposed. Named after the C++ concept of a unique pointer.\n *\n * Should be used with the `using` keyword to ensure that the pointer is\n * freed (via dispose function) when it is no longer in scope.\n *\n * Useful with WASM modules that require allocating and freeing memory.\n *\n * @example\n * ```ts\n * using ptr = new UniquePointer(wasmBridge.malloc(10), wasmBridge.free);\n * ```\n *\n * @param address The address of the pointer\n * @param free The function to call to free the pointer\n */\n constructor(address: number, free: (ptr: number) => void) {\n super(address);\n this.free = free;\n }\n\n [Symbol.dispose]() {\n this.free(this.valueOf());\n }\n}\n\n/**\n * Map that allows waiting for changes to values.\n */\nexport class EventMap<K, V> extends Map<K, V> {\n #listeners = new Map<K, Set<(value: V) => void>>();\n\n /**\n * Waits for the next `set()` call on the given key.\n */\n wait(key: K): Promise<V> {\n return new Promise((resolve) => {\n const listeners = this.#listeners.get(key) ?? new Set();\n listeners.add(resolve);\n this.#listeners.set(key, listeners);\n });\n }\n\n override set(key: K, value: V) {\n super.set(key, value);\n\n const listeners = this.#listeners.get(key);\n\n if (listeners) {\n for (const listener of listeners) {\n listener(value);\n listeners.delete(listener);\n }\n }\n\n return this;\n }\n}\n\n/**\n * Converts a `ReadableStream` into an `AsyncIterableIterator`.\n *\n * Allows you to use ReadableStreams in a `for await ... of` loop.\n */\nexport function fromReadable<R>(\n readable: ReadableStream<R>,\n options?: { preventCancel?: boolean }\n): AsyncIterableIterator<R> {\n const reader = readable.getReader();\n return fromReader(reader, options);\n}\n\n/**\n * Converts a `ReadableStreamDefaultReader` into an `AsyncIterableIterator`.\n *\n * Allows you to use Readers in a `for await ... of` loop.\n */\nexport async function* fromReader<R>(\n reader: ReadableStreamDefaultReader<R>,\n options?: { preventCancel?: boolean }\n): AsyncIterableIterator<R> {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n return value;\n }\n yield value;\n }\n } finally {\n if (!options?.preventCancel) {\n await reader.cancel();\n }\n reader.releaseLock();\n }\n}\n\nexport type UnderlyingSourceLockCallback = () => void;\n\n/**\n * `ReadableStream` with an optional lock callback.\n */\nexport class ExtendedReadableStream<R> extends ReadableStream<R> {\n #notifyLock?: () => void;\n\n constructor(\n {\n lock,\n ...underlyingSource\n }: UnderlyingSource & { lock?: UnderlyingSourceLockCallback },\n strategy?: QueuingStrategy<R>\n ) {\n super(underlyingSource, strategy);\n this.#notifyLock = lock;\n }\n\n override getReader() {\n // biome-ignore lint/suspicious/noExplicitAny: ReadableStream types don't expose internal reader methods\n const reader = super.getReader() as any;\n if (this.locked) {\n this.#notifyLock?.();\n }\n return reader;\n }\n\n override pipeThrough<T>(\n transform: ReadableWritablePair<T, R>,\n options?: StreamPipeOptions\n ): ReadableStream<T> {\n const stream = super.pipeThrough(transform, options);\n if (this.locked) {\n this.#notifyLock?.();\n }\n return stream;\n }\n\n override pipeTo(\n dest: WritableStream<R>,\n options?: StreamPipeOptions\n ): Promise<void> {\n const promise = super.pipeTo(dest, options);\n if (this.locked) {\n this.#notifyLock?.();\n }\n return promise;\n }\n\n override tee(): [ReadableStream<R>, ReadableStream<R>] {\n const [a, b] = super.tee();\n if (this.locked) {\n this.#notifyLock?.();\n }\n return [a, b];\n }\n}\n\n/**\n * Queues a microtask and returns a promise that resolves when\n * the microtask is executed.\n *\n * Microtasks are executed after the current task has completed,\n * but before the next task begins (tasks are the main unit of\n * work in the event loop).\n *\n * Useful when you want synchronous code from the current task to\n * complete before executing asynchronous code.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide\n */\nexport async function nextMicrotask() {\n return await new Promise<void>((resolve) => queueMicrotask(resolve));\n}\n\nexport type ConnectInterfacesOptions = {\n transformAtoB?: (chunk: Uint8Array) => Uint8Array;\n transformBtoA?: (chunk: Uint8Array) => Uint8Array;\n};\n\n/**\n * Connects two duplex streams by piping each stream's `readable`\n * to the other's `writable`.\n *\n * This is useful for connecting two network interfaces together\n * (e.g. a tap interface and a v86 network interface).\n *\n * Optionally supports transforming the data as it is passed\n * between the two streams. Use this to log or modify the data.\n */\nexport function connectStreams(\n interfaceA: DuplexStream<Uint8Array>,\n interfaceB: DuplexStream<Uint8Array>,\n { transformAtoB, transformBtoA }: ConnectInterfacesOptions = {}\n) {\n const streamA = transformAtoB\n ? interfaceA.readable.pipeThrough(\n new TransformStream<Uint8Array>({\n transform(chunk, controller) {\n try {\n const transformedChunk = transformAtoB(chunk);\n controller.enqueue(transformedChunk);\n } catch (error) {\n console.warn('Error transforming A to B', error);\n }\n },\n })\n )\n : interfaceA.readable;\n\n const streamB = transformBtoA\n ? interfaceB.readable.pipeThrough(\n new TransformStream<Uint8Array>({\n transform(chunk, controller) {\n try {\n const transformedChunk = transformBtoA(chunk);\n controller.enqueue(transformedChunk);\n } catch (error) {\n console.warn('Error transforming B to A', error);\n }\n },\n })\n )\n : interfaceB.readable;\n\n streamA.pipeTo(interfaceB.writable);\n streamB.pipeTo(interfaceA.writable);\n}\n","import { UniquePointer } from '../util.js';\nimport type {\n CommonExports,\n Pointer,\n SysExports,\n WasiExports,\n} from './types.js';\n\nexport abstract class Bindings<Imports, Exports> {\n #exports?: Exports & CommonExports & WasiExports & SysExports;\n\n abstract imports: Imports;\n\n get exports(): Exports & CommonExports & WasiExports & SysExports {\n if (!this.#exports) {\n throw new Error('exports were not registered');\n }\n return this.#exports;\n }\n\n /**\n * Register the exports object from the wasm module.\n */\n register(exports: Exports & CommonExports & WasiExports & SysExports) {\n this.#exports = exports;\n }\n\n /**\n * Allocates a region of wasm memory and returns a `UniquePointer` to the start.\n *\n * `UniquePointer` will automatically free the memory when it is disposed.\n * It is intended to be used with the `using` statement which will automatically\n * dispose of the pointer when the current scope ends.\n */\n smartMalloc(size: number) {\n return new UniquePointer(this.exports.malloc(size), this.exports.free);\n }\n\n /**\n * Copies a Uint8Array to a newly allocated region of wasm memory.\n *\n * @returns A pointer to the start of the copied data.\n */\n copyToMemory(data: Uint8Array) {\n const length = data.length;\n const pointer = this.smartMalloc(length);\n\n const memoryView = new Uint8Array(\n this.exports.memory.buffer,\n pointer.valueOf(),\n length\n );\n\n memoryView.set(data);\n\n return pointer;\n }\n\n /**\n * Copies a region of wasm memory to a new Uint8Array.\n *\n * @returns A new Uint8Array containing the copied data.\n */\n copyFromMemory(ptr: Pointer | number, length: number): Uint8Array {\n const buffer = this.exports.memory.buffer.slice(\n Number(ptr),\n Number(ptr) + length\n );\n return new Uint8Array(buffer);\n }\n\n /**\n * Creates a Uint8Array view over a region of wasm memory.\n */\n viewFromMemory(ptr: Pointer | number, length: number): Uint8Array {\n return new Uint8Array(this.exports.memory.buffer, Number(ptr), length);\n }\n}\n","import {\n type IPv4Address,\n type MacAddress,\n generateMacAddress,\n parseIPv4Address,\n parseMacAddress,\n serializeIPv4Cidr,\n serializeMacAddress,\n} from '@tcpip/wire';\nimport { LwipError } from '../lwip/errors.js';\nimport type { TapInterface, TapInterfaceOptions } from '../types.js';\nimport {\n ExtendedReadableStream,\n Hooks,\n fromReadable,\n nextMicrotask,\n} from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype TapInterfaceHandle = Pointer;\n\ntype TapInterfaceOuterHooks = {\n handle: TapInterfaceHandle;\n sendFrame(frame: Uint8Array): void;\n getMacAddress(): MacAddress;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\ntype TapInterfaceInnerHooks = {\n receiveFrame(frame: Uint8Array): void;\n};\n\nexport const tapInterfaceHooks = new Hooks<\n TapInterface,\n TapInterfaceOuterHooks,\n TapInterfaceInnerHooks\n>();\n\nexport type TapImports = {\n register_tap_interface(handle: TapInterfaceHandle): void;\n receive_frame(\n handle: TapInterfaceHandle,\n framePtr: number,\n length: number\n ): Promise<void>;\n};\n\nexport type TapExports = {\n create_tap_interface(\n macAddress: Pointer,\n ipAddress: Pointer,\n netmask: Pointer\n ): TapInterfaceHandle;\n remove_tap_interface(handle: TapInterfaceHandle): void;\n send_tap_interface(\n handle: TapInterfaceHandle,\n frame: Pointer,\n length: number\n ): number;\n enable_tap_interface(handle: TapInterfaceHandle): void;\n disable_tap_interface(handle: TapInterfaceHandle): void;\n};\n\nexport class TapBindings extends Bindings<TapImports, TapExports> {\n interfaces = new Map<TapInterfaceHandle, TapInterface>();\n\n imports = {\n register_tap_interface: (handle: TapInterfaceHandle) => {\n const tapInterface = new VirtualTapInterface();\n\n tapInterfaceHooks.setOuter(tapInterface, {\n handle,\n sendFrame: (frame) => {\n const framePtr = this.copyToMemory(frame);\n const result = this.exports.send_tap_interface(\n handle,\n framePtr,\n frame.length\n );\n\n if (result !== LwipError.ERR_OK) {\n throw new Error(`failed to send frame: ${result}`);\n }\n },\n getMacAddress: () => {\n const macPtr = this.exports.get_interface_mac_address(handle);\n\n const macBytes = this.viewFromMemory(macPtr, 6);\n return parseMacAddress(macBytes);\n },\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, tapInterface);\n },\n receive_frame: async (\n handle: TapInterfaceHandle,\n framePtr: number,\n length: number\n ) => {\n const frame = this.copyFromMemory(framePtr, length);\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n // This also gives the consumer a chance to start listening before we enqueue the first frame\n await nextMicrotask();\n\n const tapInterface = this.interfaces.get(handle);\n\n if (!tapInterface) {\n console.error('received frame on unknown tap interface');\n return;\n }\n\n tapInterfaceHooks\n .getInner(tapInterface)\n .receiveFrame(new Uint8Array(frame));\n },\n };\n\n async create(options: TapInterfaceOptions) {\n const macAddress = options.mac\n ? serializeMacAddress(options.mac)\n : generateMacAddress();\n\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using macAddressPtr = this.copyToMemory(macAddress);\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n\n const handle = this.exports.create_tap_interface(\n macAddressPtr,\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0\n );\n\n const tapInterface = this.interfaces.get(handle);\n\n if (!tapInterface) {\n throw new Error('tap interface failed to register');\n }\n\n return tapInterface;\n }\n\n async remove(tapInterface: TapInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === tapInterface) {\n this.exports.remove_tap_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualTapInterface implements TapInterface {\n #readableController?: ReadableStreamController<Uint8Array>;\n #isListening = false;\n\n readonly type = 'tap' as const;\n get mac(): MacAddress {\n return tapInterfaceHooks.getOuter(this).getMacAddress();\n }\n get ip(): IPv4Address | undefined {\n return tapInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return tapInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n\n constructor() {\n tapInterfaceHooks.setInner(this, {\n receiveFrame: async (frame: Uint8Array<ArrayBuffer>) => {\n // Do not buffer frames until the consumer signals intent\n // to listen - otherwise memory will grow indefinitely\n if (!this.#isListening) {\n return;\n }\n\n if (!this.#readableController) {\n throw new Error('readable stream not initialized');\n }\n\n this.#readableController.enqueue(frame);\n },\n });\n\n this.readable = new ExtendedReadableStream<Uint8Array>({\n start: (controller) => {\n this.#readableController = controller;\n },\n lock: () => {\n // We interpret anything that locks the stream (getReader, pipeThrough, pipeTo, tee)\n // as intent to start listening\n this.#isListening = true;\n },\n });\n\n this.writable = new WritableStream({\n write: (packet) => {\n try {\n tapInterfaceHooks.getOuter(this).sendFrame(packet);\n } catch (err) {\n console.error('tap interface send failed', err);\n }\n },\n });\n }\n\n listen() {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<Uint8Array> {\n return this.listen();\n }\n}\n","// Intentionally not using enum to avoid need for a transpiler\nexport const LwipError = {\n ERR_OK: 0,\n ERR_MEM: -1,\n ERR_BUF: -2,\n ERR_TIMEOUT: -3,\n ERR_RTE: -4,\n ERR_INPROGRESS: -5,\n ERR_VAL: -6,\n ERR_WOULDBLOCK: -7,\n ERR_USE: -8,\n ERR_ALREADY: -9,\n ERR_ISCONN: -10,\n ERR_CONN: -11,\n ERR_IF: -12,\n ERR_ABRT: -13,\n ERR_RST: -14,\n ERR_CLSD: -15,\n ERR_ARG: -16,\n} as const;\n\nexport type LwipError = (typeof LwipError)[keyof typeof LwipError];\n","import {\n type IPv4Address,\n parseIPv4Address,\n serializeIPv4Cidr,\n} from '@tcpip/wire';\nimport type { LoopbackInterface, LoopbackInterfaceOptions } from '../types.js';\nimport { Hooks } from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype LoopbackInterfaceHandle = Pointer;\n\ntype LoopbackInterfaceOuterHooks = {\n handle: LoopbackInterfaceHandle;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty hook type\ntype LoopbackInterfaceInnerHooks = {};\n\nexport const loopbackInterfaceHooks = new Hooks<\n LoopbackInterface,\n LoopbackInterfaceOuterHooks,\n LoopbackInterfaceInnerHooks\n>();\n\nexport type LoopbackImports = {\n register_loopback_interface(handle: LoopbackInterfaceHandle): void;\n};\n\nexport type LoopbackExports = {\n create_loopback_interface(\n ipAddress: Pointer,\n netmask: Pointer\n ): LoopbackInterfaceHandle;\n remove_loopback_interface(handle: LoopbackInterfaceHandle): void;\n};\n\nexport class LoopbackBindings extends Bindings<\n LoopbackImports,\n LoopbackExports\n> {\n interfaces = new Map<LoopbackInterfaceHandle, LoopbackInterface>();\n\n imports = {\n register_loopback_interface: (handle: LoopbackInterfaceHandle) => {\n const loopbackInterface = new VirtualLoopbackInterface();\n\n loopbackInterfaceHooks.setOuter(loopbackInterface, {\n handle,\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, loopbackInterface);\n },\n };\n\n async create(options: LoopbackInterfaceOptions) {\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n\n const handle = this.exports.create_loopback_interface(\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0\n );\n\n const loopbackInterface = this.interfaces.get(handle);\n\n if (!loopbackInterface) {\n throw new Error('loopback interface failed to register');\n }\n\n return loopbackInterface;\n }\n\n async remove(loopbackInterface: LoopbackInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === loopbackInterface) {\n this.exports.remove_loopback_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualLoopbackInterface implements LoopbackInterface {\n readonly type = 'loopback';\n get ip(): IPv4Address | undefined {\n return loopbackInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return loopbackInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n}\n","import type { DnsClient } from '@tcpip/dns';\nimport { serializeIPv4Address } from '@tcpip/wire';\nimport { LwipError } from '../lwip/errors.js';\nimport type {\n TcpConnection,\n TcpConnectionOptions,\n TcpListener,\n TcpListenerOptions,\n} from '../types.js';\nimport { EventMap, Hooks, fromReadable, nextMicrotask } from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype TcpListenerHandle = Pointer;\ntype TcpConnectionHandle = Pointer;\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty hook type\ntype TcpListenerOuterHooks = {};\n\ntype TcpListenerInnerHooks = {\n accept(connection: TcpConnection): void;\n};\n\ntype TcpConnectionOuterHooks = {\n send(data: Uint8Array): Promise<void>;\n updateReceiveBuffer(length: number): void;\n close(): Promise<void>;\n};\n\ntype TcpConnectionInnerHooks = {\n receive(data: Uint8Array): Promise<void>;\n close(): Promise<void>;\n};\n\nconst tcpListenerHooks = new Hooks<\n TcpListener,\n TcpListenerOuterHooks,\n TcpListenerInnerHooks\n>();\n\nconst tcpConnectionHooks = new Hooks<\n TcpConnection,\n TcpConnectionOuterHooks,\n TcpConnectionInnerHooks\n>();\n\nexport const MAX_SEGMENT_SIZE = 1448; // effective data per segment: TCP_MSS (1460) - timestamp option (12)\nexport const MAX_WINDOW_SIZE = MAX_SEGMENT_SIZE * 4; // This must match TCP_WND in lwipopts.h\nexport const SEND_BUFFER_SIZE = MAX_SEGMENT_SIZE * 4; // This must match TCP_SND_BUF in lwipopts.h\nexport const READABLE_HIGH_WATER_MARK = MAX_SEGMENT_SIZE;\n\nexport type TcpImports = {\n accept_tcp_connection(\n listenerHandle: TcpListenerHandle,\n connectionHandle: TcpConnectionHandle\n ): Promise<void>;\n connected_tcp_connection(handle: TcpConnectionHandle): Promise<void>;\n closed_tcp_connection(handle: TcpConnectionHandle): Promise<void>;\n receive_tcp_chunk(\n handle: TcpConnectionHandle,\n chunkPtr: number,\n length: number\n ): Promise<void>;\n sent_tcp_chunk(handle: TcpConnectionHandle, length: number): void;\n};\n\nexport type TcpExports = {\n create_tcp_listener(host: Pointer | null, port: number): TcpListenerHandle;\n create_tcp_connection(host: Pointer, port: number): TcpConnectionHandle;\n close_tcp_connection(handle: TcpConnectionHandle): number;\n send_tcp_chunk(\n handle: TcpConnectionHandle,\n chunk: number,\n length: number\n ): number;\n update_tcp_receive_buffer(handle: TcpConnectionHandle, length: number): void;\n};\n\nexport class TcpBindings extends Bindings<TcpImports, TcpExports> {\n #tcpListeners = new Map<TcpListenerHandle, TcpListener>();\n #tcpConnections = new EventMap<TcpConnectionHandle, TcpConnection>();\n #tcpAcks = new Map<TcpConnectionHandle, (length: number) => void>();\n #dnsClient: DnsClient;\n\n async #resolveHost(host: string) {\n try {\n return serializeIPv4Address(host);\n } catch (e) {\n const ip = await this.#dnsClient.lookup(host);\n return serializeIPv4Address(ip);\n }\n }\n\n constructor(dnsClient: DnsClient) {\n super();\n this.#dnsClient = dnsClient;\n }\n\n imports = {\n accept_tcp_connection: async (\n listenerHandle: TcpListenerHandle,\n connectionHandle: TcpConnectionHandle\n ) => {\n const listener = this.#tcpListeners.get(listenerHandle);\n\n if (!listener) {\n console.error('new tcp connection to unknown listener');\n return;\n }\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n const connection = new VirtualTcpConnection();\n\n tcpConnectionHooks.setOuter(connection, {\n send: async (data) => {\n const dataPtr = Number(this.copyToMemory(data));\n\n let bytesQueued = this.exports.send_tcp_chunk(\n connectionHandle,\n dataPtr,\n data.length\n );\n\n // If the entire data was not queued, send the remaining\n // chunks as space becomes available\n while (bytesQueued < data.length) {\n await new Promise<number>((resolve) => {\n this.#tcpAcks.set(connectionHandle, resolve);\n });\n const bytesRemaining = data.length - bytesQueued;\n\n bytesQueued += this.exports.send_tcp_chunk(\n connectionHandle,\n dataPtr + bytesQueued,\n bytesRemaining\n );\n }\n },\n updateReceiveBuffer: (length: number) => {\n this.exports.update_tcp_receive_buffer(connectionHandle, length);\n },\n close: async () => {\n const result = this.exports.close_tcp_connection(connectionHandle);\n\n if (result !== LwipError.ERR_OK) {\n throw new Error(`failed to close tcp connection: ${result}`);\n }\n },\n });\n\n this.#tcpConnections.set(connectionHandle, connection);\n\n tcpListenerHooks.getInner(listener).accept(connection);\n },\n connected_tcp_connection: async (handle: TcpConnectionHandle) => {\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n const connection = new VirtualTcpConnection();\n\n tcpConnectionHooks.setOuter(connection, {\n send: async (data) => {\n const dataPtr = Number(this.copyToMemory(data));\n\n let bytesQueued = this.exports.send_tcp_chunk(\n handle,\n dataPtr,\n data.length\n );\n\n // If the entire data was not queued, send the remaining\n // chunks as space becomes available\n while (bytesQueued < data.length) {\n await new Promise<number>((resolve) => {\n this.#tcpAcks.set(handle, resolve);\n });\n const bytesRemaining = data.length - bytesQueued;\n\n bytesQueued += this.exports.send_tcp_chunk(\n handle,\n dataPtr + bytesQueued,\n bytesRemaining\n );\n }\n },\n updateReceiveBuffer: (length: number) => {\n this.exports.update_tcp_receive_buffer(handle, length);\n },\n close: async () => {\n this.exports.close_tcp_connection(handle);\n },\n });\n\n this.#tcpConnections.set(handle, connection);\n },\n closed_tcp_connection: async (handle: TcpConnectionHandle) => {\n const connection = this.#tcpConnections.get(handle);\n\n if (!connection) {\n console.error('received close on unknown tcp connection');\n return;\n }\n\n await tcpConnectionHooks.getInner(connection).close();\n },\n receive_tcp_chunk: async (\n handle: TcpConnectionHandle,\n chunkPtr: number,\n length: number\n ) => {\n const chunk = this.copyFromMemory(chunkPtr, length);\n const connection = this.#tcpConnections.get(handle);\n\n if (!connection) {\n console.error('received chunk on unknown tcp connection');\n return;\n }\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n tcpConnectionHooks.getInner(connection).receive(new Uint8Array(chunk));\n },\n sent_tcp_chunk: (handle: TcpConnectionHandle, length: number) => {\n const notifyAck = this.#tcpAcks.get(handle);\n this.#tcpAcks.delete(handle);\n notifyAck?.(length);\n },\n };\n\n async listen(options: TcpListenerOptions) {\n using hostPtr = options.host\n ? this.copyToMemory(await this.#resolveHost(options.host))\n : null;\n\n const handle = this.exports.create_tcp_listener(hostPtr, options.port);\n\n const tcpListener = new VirtualTcpListener();\n\n tcpListenerHooks.setOuter(tcpListener, {});\n\n this.#tcpListeners.set(handle, tcpListener);\n\n return tcpListener;\n }\n\n async connect(options: TcpConnectionOptions) {\n using hostPtr = this.copyToMemory(await this.#resolveHost(options.host));\n\n const handle = this.exports.create_tcp_connection(hostPtr, options.port);\n\n const tcpConnection = await this.#tcpConnections.wait(handle);\n\n if (!tcpConnection) {\n throw new Error('tcp failed to connect');\n }\n\n return tcpConnection;\n }\n}\n\nexport class VirtualTcpListener\n implements TcpListener, AsyncIterable<TcpConnection>\n{\n #connections: TcpConnection[] = [];\n #notifyConnection?: () => void;\n\n constructor() {\n tcpListenerHooks.setInner(this, {\n accept: async (connection: TcpConnection) => {\n this.#connections.push(connection);\n this.#notifyConnection?.();\n },\n });\n }\n\n async *[Symbol.asyncIterator](): AsyncIterableIterator<TcpConnection> {\n while (true) {\n await new Promise<void>((resolve) => {\n this.#notifyConnection = resolve;\n });\n\n yield* this.#connections;\n this.#connections = [];\n }\n }\n}\n\nexport class VirtualTcpConnection\n implements TcpConnection, AsyncIterable<Uint8Array>\n{\n #receiveBuffer: Uint8Array[] = [];\n #readableController?: ReadableStreamDefaultController<Uint8Array>;\n #writableController?: WritableStreamDefaultController;\n\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n\n constructor() {\n tcpConnectionHooks.setInner(this, {\n receive: async (data: Uint8Array) => {\n // We maintain our own receive buffer prior to enqueueing to the readable\n // stream so that we can send window updates as data is consumed\n this.#receiveBuffer.push(data);\n this.#enqueueBuffer();\n },\n close: async () => {\n this.close();\n },\n });\n\n this.readable = new ReadableStream(\n {\n start: (controller) => {\n this.#readableController = controller;\n },\n pull: () => {\n this.#enqueueBuffer();\n },\n },\n {\n highWaterMark: READABLE_HIGH_WATER_MARK,\n size: (chunk) => chunk.byteLength,\n }\n );\n\n this.writable = new WritableStream(\n {\n start: (controller) => {\n this.#writableController = controller;\n },\n write: async (chunk) => {\n await tcpConnectionHooks.getOuter(this).send(chunk);\n },\n },\n {\n // Send buffer is managed by the TCP stack\n highWaterMark: 0,\n }\n );\n }\n\n #enqueueBuffer() {\n if (!(this.#readableController?.desiredSize! > 0)) {\n return;\n }\n\n let bytesEnqueued = 0;\n\n // Enqueue chunks until the desired size is reached.\n // Always enqueue at least one chunk (desiredSize is a soft limit per the\n // WHATWG Streams spec - chunks can push it negative).\n while (this.#receiveBuffer.length > 0) {\n const chunkLength = this.#receiveBuffer[0]!.length;\n\n if (\n bytesEnqueued > 0 &&\n bytesEnqueued + chunkLength > this.#readableController!.desiredSize!\n ) {\n break;\n }\n\n const chunk = this.#receiveBuffer.shift()!;\n this.#readableController!.enqueue(chunk);\n bytesEnqueued += chunk.length;\n }\n\n // Notify the TCP stack that we've consumed data to reopen the receive window\n if (bytesEnqueued > 0) {\n tcpConnectionHooks.getOuter(this).updateReceiveBuffer(bytesEnqueued);\n }\n }\n\n async close() {\n await tcpConnectionHooks.getOuter(this).close();\n this.#readableController?.error(new Error('tcp connection closed'));\n this.#writableController?.error(new Error('tcp connection closed'));\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Uint8Array> {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n}\n","import {\n type IPv4Address,\n parseIPv4Address,\n serializeIPv4Cidr,\n} from '@tcpip/wire';\nimport type { TunInterface, TunInterfaceOptions } from '../types.js';\nimport {\n ExtendedReadableStream,\n Hooks,\n fromReadable,\n nextMicrotask,\n} from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype TunInterfaceHandle = Pointer;\n\ntype TunInterfaceOuterHooks = {\n handle: TunInterfaceHandle;\n sendPacket(packet: Uint8Array): void;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\ntype TunInterfaceInnerHooks = {\n receivePacket(packet: Uint8Array): void;\n};\n\nconst tunInterfaceHooks = new Hooks<\n TunInterface,\n TunInterfaceOuterHooks,\n TunInterfaceInnerHooks\n>();\n\nexport type TunImports = {\n register_tun_interface(handle: TunInterfaceHandle): void;\n receive_packet(\n handle: TunInterfaceHandle,\n packetPtr: number,\n length: number\n ): Promise<void>;\n};\n\nexport type TunExports = {\n create_tun_interface(\n ipAddress: Pointer,\n netmask: Pointer\n ): TunInterfaceHandle;\n remove_tun_interface(handle: TunInterfaceHandle): void;\n send_tun_interface(\n handle: TunInterfaceHandle,\n packet: Pointer,\n length: number\n ): void;\n};\n\nexport class TunBindings extends Bindings<TunImports, TunExports> {\n interfaces = new Map<TunInterfaceHandle, TunInterface>();\n\n imports = {\n register_tun_interface: (handle: TunInterfaceHandle) => {\n const tunInterface = new VirtualTunInterface();\n\n tunInterfaceHooks.setOuter(tunInterface, {\n handle,\n sendPacket: (packet) => {\n const packetPtr = this.copyToMemory(packet);\n this.exports.send_tun_interface(handle, packetPtr, packet.length);\n },\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, tunInterface);\n },\n receive_packet: async (\n handle: TunInterfaceHandle,\n packetPtr: number,\n length: number\n ) => {\n const packet = this.copyFromMemory(packetPtr, length);\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n // This also gives the consumer a chance to start listening before we enqueue the first packet\n await nextMicrotask();\n\n const tunInterface = this.interfaces.get(handle);\n\n if (!tunInterface) {\n console.error('received packet on unknown tun interface');\n return;\n }\n\n tunInterfaceHooks\n .getInner(tunInterface)\n .receivePacket(new Uint8Array(packet));\n },\n };\n\n async create(options: TunInterfaceOptions) {\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n\n const handle = this.exports.create_tun_interface(\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0\n );\n\n const tunInterface = this.interfaces.get(handle);\n\n if (!tunInterface) {\n throw new Error('tun interface failed to register');\n }\n\n return tunInterface;\n }\n\n async remove(tunInterface: TunInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === tunInterface) {\n this.exports.remove_tun_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualTunInterface implements TunInterface {\n #readableController?: ReadableStreamController<Uint8Array>;\n #isListening = false;\n\n readonly type = 'tun' as const;\n get ip(): IPv4Address | undefined {\n return tunInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return tunInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n\n constructor() {\n tunInterfaceHooks.setInner(this, {\n receivePacket: async (packet: Uint8Array<ArrayBuffer>) => {\n // Do not buffer packets until the consumer signals intent\n // to listen - otherwise memory will grow indefinitely\n if (!this.#isListening) {\n return;\n }\n\n if (!this.#readableController) {\n throw new Error('readable stream not initialized');\n }\n\n this.#readableController?.enqueue(packet);\n },\n });\n\n this.readable = new ExtendedReadableStream<Uint8Array>({\n start: (controller) => {\n this.#readableController = controller;\n },\n lock: () => {\n // We interpret anything that locks the stream (getReader, pipeThrough, pipeTo, tee)\n // as intent to start listening\n this.#isListening = true;\n },\n });\n\n this.writable = new WritableStream({\n write: (packet) => {\n tunInterfaceHooks.getOuter(this).sendPacket(packet);\n },\n });\n }\n\n listen() {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<Uint8Array> {\n return this.listen();\n }\n}\n","import type { DnsClient } from '@tcpip/dns';\nimport { parseIPv4Address, serializeIPv4Address } from '@tcpip/wire';\nimport { LwipError } from '../lwip/errors.js';\nimport type { UdpDatagram, UdpSocket, UdpSocketOptions } from '../types.js';\nimport { EventMap, Hooks, fromReadable, nextMicrotask } from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype UdpSocketHandle = Pointer;\n\ntype UdpSocketOuterHooks = {\n send(datagram: UdpDatagram): Promise<void>;\n close(): Promise<void>;\n};\n\ntype UdpSocketInnerHooks = {\n receive(datagram: UdpDatagram): Promise<void>;\n};\n\nconst udpSocketHooks = new Hooks<\n UdpSocket,\n UdpSocketOuterHooks,\n UdpSocketInnerHooks\n>();\n\nexport type UdpImports = {\n receive_udp_datagram(\n handle: UdpSocketHandle,\n ip: number,\n port: number,\n datagramPtr: number,\n length: number\n ): Promise<void>;\n};\n\nexport type UdpExports = {\n open_udp_socket(host: Pointer | null, port: number): UdpSocketHandle;\n close_udp_socket(handle: UdpSocketHandle): void;\n send_udp_datagram(\n handle: UdpSocketHandle,\n ip: Pointer | null,\n port: number,\n datagram: Pointer,\n length: number\n ): number;\n};\n\nexport class UdpBindings extends Bindings<UdpImports, UdpExports> {\n #udpSockets = new EventMap<UdpSocketHandle, UdpSocket>();\n #dnsClient: DnsClient;\n\n async #resolveHost(host: string) {\n try {\n return serializeIPv4Address(host);\n } catch (e) {\n const ip = await this.#dnsClient.lookup(host);\n return serializeIPv4Address(ip);\n }\n }\n\n constructor(dnsClient: DnsClient) {\n super();\n this.#dnsClient = dnsClient;\n }\n\n imports = {\n receive_udp_datagram: async (\n handle: UdpSocketHandle,\n hostPtr: number,\n port: number,\n datagramPtr: number,\n length: number\n ) => {\n const host = this.copyFromMemory(hostPtr, 4);\n const datagram = this.copyFromMemory(datagramPtr, length);\n const socket = this.#udpSockets.get(handle);\n\n if (!socket) {\n console.error('received datagram on unknown udp socket');\n return;\n }\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n udpSocketHooks.getInner(socket).receive({\n host: parseIPv4Address(host),\n port,\n data: datagram,\n });\n },\n };\n\n async open(options: UdpSocketOptions) {\n using hostPtr = options.host\n ? this.copyToMemory(await this.#resolveHost(options.host))\n : null;\n\n const handle = this.exports.open_udp_socket(hostPtr, options.port ?? 0);\n\n if (Number(handle) === 0) {\n throw new Error('failed to open udp socket');\n }\n\n const udpSocket = new VirtualUdpSocket();\n\n udpSocketHooks.setOuter(udpSocket, {\n send: async (datagram: UdpDatagram) => {\n using hostPtr = this.copyToMemory(\n await this.#resolveHost(datagram.host)\n );\n using datagramPtr = this.copyToMemory(datagram.data);\n\n const result = this.exports.send_udp_datagram(\n handle,\n hostPtr,\n datagram.port,\n datagramPtr,\n datagram.data.length\n );\n\n if (result !== LwipError.ERR_OK) {\n throw new Error(`failed to send udp datagram: ${result}`);\n }\n },\n close: async () => {\n this.exports.close_udp_socket(handle);\n this.#udpSockets.delete(handle);\n },\n });\n\n this.#udpSockets.set(handle, udpSocket);\n\n return udpSocket;\n }\n}\n\nexport class VirtualUdpSocket implements UdpSocket, AsyncIterable<UdpDatagram> {\n #readableController?: ReadableStreamDefaultController<UdpDatagram>;\n #writableController?: WritableStreamDefaultController;\n\n readable: ReadableStream<UdpDatagram>;\n writable: WritableStream<UdpDatagram>;\n\n constructor() {\n udpSocketHooks.setInner(this, {\n receive: async (datagram: UdpDatagram) => {\n if (!this.#readableController) {\n throw new Error('readable controller not initialized');\n }\n this.#readableController.enqueue(datagram);\n },\n });\n\n this.readable = new ReadableStream({\n start: (controller) => {\n this.#readableController = controller;\n },\n });\n\n this.writable = new WritableStream({\n start: (controller) => {\n this.#writableController = controller;\n },\n write: async (datagram) => {\n await udpSocketHooks.getOuter(this).send(datagram);\n },\n });\n }\n\n async close() {\n await udpSocketHooks.getOuter(this).close();\n this.#readableController?.error(new Error('udp socket closed'));\n this.#writableController?.error(new Error('udp socket closed'));\n }\n\n [Symbol.asyncIterator](): AsyncIterator<UdpDatagram> {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n}\n","const IN_NODE =\n typeof process === 'object' &&\n typeof process.versions === 'object' &&\n typeof process.versions.node === 'string';\n\n/**\n * Fetches a file from the network or filesystem\n * depending on the environment.\n */\nexport async function fetchFile(input: string | URL, type: string) {\n if (IN_NODE) {\n return fetchFileNode(input, type);\n }\n return fetch(input);\n}\n\nasync function fetchFileNode(input: string | URL, type: string) {\n const fs = await import('node:fs');\n const { Readable } = await import('node:stream');\n const nodeStream = fs.createReadStream(input);\n const stream = Readable.toWeb(nodeStream) as ReadableStream<Uint8Array>;\n return new Response(stream, { headers: { 'Content-Type': type } });\n}\n"],"mappings":"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","names":["ConsoleStdout","File","OpenFile","WASI","DnsClient","generateMacAddress","parseIPv4Address","parseMacAddress","serializeIPv4Cidr","serializeMacAddress","Hooks","#outerHooks","#innerHooks","key","hooks","UniquePointer","address","free","DisposeSymbol","EventMap","#listeners","resolve","listeners","value","listener","fromReadable","readable","options","reader","fromReader","done","ExtendedReadableStream","#notifyLock","lock","underlyingSource","strategy","transform","stream","dest","promise","a","b","nextMicrotask","connectStreams","interfaceA","interfaceB","transformAtoB","transformBtoA","streamA","chunk","controller","transformedChunk","error","streamB","Bindings","#exports","exports","size","UniquePointer","data","length","pointer","ptr","buffer","generateMacAddress","parseIPv4Address","parseMacAddress","serializeIPv4Cidr","serializeMacAddress","LwipError","tapInterfaceHooks","Hooks","TapBindings","Bindings","handle","tapInterface","VirtualTapInterface","frame","framePtr","result","LwipError","macPtr","macBytes","parseMacAddress","ipPtr","ipBytes","parseIPv4Address","netmaskPtr","netmaskBytes","length","nextMicrotask","options","_stack","macAddress","serializeMacAddress","generateMacAddress","ipAddress","netmask","serializeIPv4Cidr","macAddressPtr","__using","ipAddressPtr","_","_error","_hasError","__callDispose","loopback","#readableController","#isListening","ExtendedReadableStream","controller","packet","err","fromReadable","bridgeInterfaceHooks","Hooks","BridgeBindings","Bindings","options","_stack","macAddress","serializeMacAddress","generateMacAddress","ipAddress","netmask","serializeIPv4Cidr","macAddressPtr","__using","ipAddressPtr","netmaskPtr","portHandles","port","tapInterfaceHooks","portHandlesPtr","handle","bridgeInterface","VirtualBridgeInterface","macPtr","macBytes","parseMacAddress","ipPtr","ipBytes","parseIPv4Address","netmaskBytes","_","_error","_hasError","__callDispose","loopback","parseIPv4Address","serializeIPv4Cidr","loopbackInterfaceHooks","Hooks","LoopbackBindings","Bindings","handle","loopbackInterface","VirtualLoopbackInterface","ipPtr","ipBytes","parseIPv4Address","netmaskPtr","netmaskBytes","options","_stack","ipAddress","netmask","serializeIPv4Cidr","ipAddressPtr","__using","_","_error","_hasError","__callDispose","loopback","serializeIPv4Address","tcpListenerHooks","Hooks","tcpConnectionHooks","MAX_SEGMENT_SIZE","MAX_WINDOW_SIZE","SEND_BUFFER_SIZE","READABLE_HIGH_WATER_MARK","TcpBindings","Bindings","#tcpListeners","#tcpConnections","EventMap","#tcpAcks","#dnsClient","#resolveHost","host","serializeIPv4Address","ip","dnsClient","listenerHandle","connectionHandle","listener","nextMicrotask","connection","VirtualTcpConnection","data","dataPtr","bytesQueued","resolve","bytesRemaining","length","result","LwipError","handle","chunkPtr","chunk","notifyAck","options","_stack","hostPtr","__using","tcpListener","VirtualTcpListener","_","_error","_hasError","__callDispose","tcpConnection","#connections","#notifyConnection","#receiveBuffer","#readableController","#writableController","#enqueueBuffer","controller","bytesEnqueued","chunkLength","fromReadable","parseIPv4Address","serializeIPv4Cidr","tunInterfaceHooks","Hooks","TunBindings","Bindings","handle","tunInterface","VirtualTunInterface","packet","packetPtr","ipPtr","ipBytes","parseIPv4Address","netmaskPtr","netmaskBytes","length","nextMicrotask","options","_stack","ipAddress","netmask","serializeIPv4Cidr","ipAddressPtr","__using","_","_error","_hasError","__callDispose","loopback","#readableController","#isListening","ExtendedReadableStream","controller","fromReadable","parseIPv4Address","serializeIPv4Address","udpSocketHooks","Hooks","UdpBindings","Bindings","#udpSockets","EventMap","#dnsClient","#resolveHost","host","serializeIPv4Address","ip","dnsClient","handle","hostPtr","port","datagramPtr","length","datagram","socket","nextMicrotask","parseIPv4Address","options","_stack","__using","udpSocket","VirtualUdpSocket","result","LwipError","_","_error","_hasError","__callDispose","#readableController","#writableController","controller","fromReadable","IN_NODE","fetchFile","input","type","fetchFileNode","fs","Readable","nodeStream","stream","createStack","options","stack","VirtualNetworkStack","#options","#loopIntervalId","#dnsClient","#loopbackBindings","#tunBindings","#tapBindings","#bridgeBindings","#tcpBindings","#udpBindings","#listInterfaces","DnsClient","LoopbackBindings","TunBindings","TapBindings","BridgeBindings","TcpBindings","UdpBindings","#init","wasi","WASI","OpenFile","File","ConsoleStdout","msg","source","fetchFile","instance","wasmInstance","netInterface"]}
1
+ {"version":3,"sources":["../src/stack.ts","../src/bindings/bridge-interface.ts","../src/util.ts","../src/bindings/base.ts","../src/bindings/tap-interface.ts","../src/lwip/errors.ts","../src/bindings/loopback-interface.ts","../src/bindings/tcp.ts","../src/bindings/tun-interface.ts","../src/bindings/udp.ts","../src/fetch-file.ts"],"sourcesContent":["import { ConsoleStdout, File, OpenFile, WASI } from '@bjorn3/browser_wasi_shim';\nimport { DnsClient, type NameServer } from '@tcpip/dns';\nimport { BridgeBindings } from './bindings/bridge-interface.js';\nimport { LoopbackBindings } from './bindings/loopback-interface.js';\nimport { TapBindings } from './bindings/tap-interface.js';\nimport { TcpBindings } from './bindings/tcp.js';\nimport { TunBindings } from './bindings/tun-interface.js';\nimport type { WasmInstance } from './bindings/types.js';\nimport { UdpBindings } from './bindings/udp.js';\nimport { fetchFile } from './fetch-file.js';\nimport type {\n BridgeInterfaceOptions,\n LoopbackInterface,\n LoopbackInterfaceOptions,\n NetworkInterface,\n NetworkStack,\n TapInterface,\n TapInterfaceOptions,\n TcpConnectionOptions,\n TcpListenerOptions,\n TunInterface,\n TunInterfaceOptions,\n UdpSocketOptions,\n} from './types.js';\n\nexport async function createStack(\n options?: NetworkStackOptions\n): Promise<NetworkStack> {\n const stack = new VirtualNetworkStack(options);\n await stack.ready;\n return stack;\n}\n\nexport type NetworkStackOptions = {\n /**\n * Whether to initialize a loopback interface on startup.\n *\n * @default true\n */\n initializeLoopback?: boolean;\n\n /**\n * Name server used for DNS resolution.\n *\n * @default { ip: '127.0.0.1', port: 53 }\n */\n nameServer?: NameServer;\n};\n\nexport class VirtualNetworkStack implements NetworkStack {\n #options: NetworkStackOptions;\n #loopIntervalId?: number;\n #dnsClient: DnsClient;\n\n #loopbackBindings: LoopbackBindings;\n #tunBindings: TunBindings;\n #tapBindings: TapBindings;\n #bridgeBindings: BridgeBindings;\n #tcpBindings: TcpBindings;\n #udpBindings: UdpBindings;\n\n ready: Promise<void>;\n get interfaces() {\n return this.#listInterfaces();\n }\n\n constructor(options: NetworkStackOptions = {}) {\n this.#options = {\n ...options,\n initializeLoopback: options.initializeLoopback ?? true,\n };\n\n this.#dnsClient = new DnsClient(this, {\n nameServer: options.nameServer ?? { ip: '127.0.0.1', port: 53 },\n });\n\n // Initialize bindings\n this.#loopbackBindings = new LoopbackBindings();\n this.#tunBindings = new TunBindings();\n this.#tapBindings = new TapBindings();\n this.#bridgeBindings = new BridgeBindings();\n this.#tcpBindings = new TcpBindings(this.#dnsClient);\n this.#udpBindings = new UdpBindings(this.#dnsClient);\n\n // Initialize the stack\n this.ready = this.#init();\n\n // Post-init setup\n this.ready.then(async () => {\n if (this.#options.initializeLoopback) {\n await this.createLoopbackInterface({\n ip: '127.0.0.1/8',\n });\n }\n });\n }\n\n async #init() {\n const wasi = new WASI(\n [],\n [],\n [\n new OpenFile(new File([])), // stdin\n ConsoleStdout.lineBuffered((msg) =>\n console.log(`[WASI stdout] ${msg}`)\n ),\n ConsoleStdout.lineBuffered((msg) =>\n console.warn(`[WASI stderr] ${msg}`)\n ),\n ]\n );\n\n const source = fetchFile(\n new URL('../tcpip.wasm', import.meta.url),\n 'application/wasm'\n );\n\n // Instantiate with both WASI and custom imports\n const { instance } = await WebAssembly.instantiateStreaming(source, {\n wasi_snapshot_preview1: wasi.wasiImport,\n env: {\n ...this.#loopbackBindings.imports,\n ...this.#tunBindings.imports,\n ...this.#tapBindings.imports,\n ...this.#bridgeBindings.imports,\n ...this.#tcpBindings.imports,\n ...this.#udpBindings.imports,\n },\n });\n\n const wasmInstance = instance as WasmInstance;\n\n this.#loopbackBindings.register(wasmInstance.exports);\n this.#tunBindings.register(wasmInstance.exports);\n this.#tapBindings.register(wasmInstance.exports);\n this.#bridgeBindings.register(wasmInstance.exports);\n this.#tcpBindings.register(wasmInstance.exports);\n this.#udpBindings.register(wasmInstance.exports);\n\n // Our WASM binary is a WASI reactor module (ie. a lib),\n // so we call `initialize()` instead of `start()`.\n wasi.initialize(wasmInstance);\n\n // Call lwIP's main loop regularly (required in NO_SYS mode)\n // Used to process queued packets (eg. loopback) and expired timeouts\n this.#loopIntervalId = Number(\n setInterval(() => {\n wasmInstance.exports.process_queued_packets();\n wasmInstance.exports.process_timeouts();\n }, 100)\n );\n }\n\n *#listInterfaces(): Iterable<NetworkInterface> {\n yield* this.#loopbackBindings.interfaces.values();\n yield* this.#tunBindings.interfaces.values();\n yield* this.#tapBindings.interfaces.values();\n yield* this.#bridgeBindings.interfaces.values();\n }\n\n async createLoopbackInterface(\n options: LoopbackInterfaceOptions\n ): Promise<LoopbackInterface> {\n await this.ready;\n return this.#loopbackBindings.create(options);\n }\n\n async createTunInterface(\n options: TunInterfaceOptions\n ): Promise<TunInterface> {\n await this.ready;\n return this.#tunBindings.create(options);\n }\n\n async createTapInterface(\n options: TapInterfaceOptions = {}\n ): Promise<TapInterface> {\n await this.ready;\n return this.#tapBindings.create(options);\n }\n\n async createBridgeInterface(options: BridgeInterfaceOptions) {\n await this.ready;\n return this.#bridgeBindings.create(options);\n }\n\n async removeInterface(netInterface: NetworkInterface) {\n await this.ready;\n\n switch (netInterface.type) {\n case 'loopback':\n return this.#loopbackBindings.remove(netInterface);\n case 'tun':\n return this.#tunBindings.remove(netInterface);\n case 'tap':\n return this.#tapBindings.remove(netInterface);\n case 'bridge':\n return this.#bridgeBindings.remove(netInterface);\n default:\n throw new Error('unknown interface type');\n }\n }\n\n /**\n * Listens for incoming TCP connections on the specified host/port.\n */\n async listenTcp(options: TcpListenerOptions) {\n await this.ready;\n return this.#tcpBindings.listen(options);\n }\n\n /**\n * Establishes an outbound TCP connection to a remote host/port.\n */\n async connectTcp(options: TcpConnectionOptions) {\n await this.ready;\n return this.#tcpBindings.connect(options);\n }\n\n /**\n * Opens a UDP socket for sending and receiving datagrams.\n *\n * If no local host is provided, the socket will bind to all available interfaces.\n * If no local port is provided, the socket will bind to a random port.\n */\n async openUdp(options: UdpSocketOptions = {}) {\n await this.ready;\n return this.#udpBindings.open(options);\n }\n}\n","import {\n type IPv4Address,\n type MacAddress,\n generateMacAddress,\n parseIPv4Address,\n parseMacAddress,\n serializeIPv4Cidr,\n serializeMacAddress,\n} from '@tcpip/wire';\nimport type { BridgeInterface, BridgeInterfaceOptions } from '../types.js';\nimport { Hooks } from '../util.js';\nimport { Bindings } from './base.js';\nimport { tapInterfaceHooks } from './tap-interface.js';\nimport type { Pointer } from './types.js';\n\ntype BridgeInterfaceHandle = Pointer;\n\ntype BridgeInterfaceOuterHooks = {\n handle: BridgeInterfaceHandle;\n getMacAddress(): MacAddress;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty hook type\ntype BridgeInterfaceInnerHooks = {};\n\nexport const bridgeInterfaceHooks = new Hooks<\n BridgeInterface,\n BridgeInterfaceOuterHooks,\n BridgeInterfaceInnerHooks\n>();\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty imports type\nexport type BridgeImports = {};\n\nexport type BridgeExports = {\n create_bridge_interface(\n macAddress: Pointer,\n ipAddress: Pointer,\n netmask: Pointer,\n ports: Pointer,\n ports_length: number\n ): BridgeInterfaceHandle;\n remove_bridge_interface(handle: BridgeInterfaceHandle): void;\n};\n\nexport class BridgeBindings extends Bindings<BridgeImports, BridgeExports> {\n interfaces = new Map<BridgeInterfaceHandle, BridgeInterface>();\n\n imports = {};\n\n async create(options: BridgeInterfaceOptions) {\n const macAddress = options.mac\n ? serializeMacAddress(options.mac)\n : generateMacAddress();\n\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using macAddressPtr = this.copyToMemory(macAddress);\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n const portHandles = new Uint32Array(\n options.ports.map((port) =>\n Number(tapInterfaceHooks.getOuter(port).handle)\n )\n );\n\n using portHandlesPtr = this.copyToMemory(\n new Uint8Array(portHandles.buffer)\n );\n\n const handle = this.exports.create_bridge_interface(\n macAddressPtr,\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0,\n portHandlesPtr,\n options.ports.length\n );\n\n const bridgeInterface = new VirtualBridgeInterface();\n\n bridgeInterfaceHooks.setOuter(bridgeInterface, {\n handle,\n getMacAddress: () => {\n const macPtr = this.exports.get_interface_mac_address(handle);\n\n const macBytes = this.viewFromMemory(macPtr, 6);\n return parseMacAddress(macBytes);\n },\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, bridgeInterface);\n\n return bridgeInterface;\n }\n\n async remove(bridgeInterface: BridgeInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === bridgeInterface) {\n this.exports.remove_bridge_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualBridgeInterface implements BridgeInterface {\n readonly type = 'bridge';\n get mac(): MacAddress {\n return bridgeInterfaceHooks.getOuter(this).getMacAddress();\n }\n get ip(): IPv4Address | undefined {\n return bridgeInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return bridgeInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n}\n","import type { DuplexStream } from './types.js';\n\n/**\n * Utility class to facilitate internal communication\n * between bindings and JS instances.\n * Hooks are created for both the outer (bindings) and\n * inner (JS instance) sides of the communication.\n *\n * Uses `WeakMap` to map each JS instance to a set of\n * hooks while avoiding memory leaks.\n */\nexport class Hooks<K extends WeakKey, O, I> {\n #outerHooks = new WeakMap<K, O>();\n #innerHooks = new WeakMap<K, I>();\n\n setOuter(key: K, hooks: O) {\n this.#outerHooks.set(key, hooks);\n }\n\n setInner(key: K, hooks: I) {\n this.#innerHooks.set(key, hooks);\n }\n\n getOuter(key: K) {\n const hooks = this.#outerHooks.get(key);\n\n if (!hooks) {\n throw new Error(`outer hooks not set for ${key}`);\n }\n\n return hooks;\n }\n\n getInner(key: K) {\n const hooks = this.#innerHooks.get(key);\n\n if (!hooks) {\n throw new Error(`inner hooks not set for ${key}`);\n }\n\n return hooks;\n }\n}\n\nexport class UniquePointer extends Number {\n free: (ptr: number) => void;\n\n /**\n * A unique pointer that will automatically free virtual memory when\n * it is disposed. Named after the C++ concept of a unique pointer.\n *\n * Should be used with the `using` keyword to ensure that the pointer is\n * freed (via dispose function) when it is no longer in scope.\n *\n * Useful with WASM modules that require allocating and freeing memory.\n *\n * @example\n * ```ts\n * using ptr = new UniquePointer(wasmBridge.malloc(10), wasmBridge.free);\n * ```\n *\n * @param address The address of the pointer\n * @param free The function to call to free the pointer\n */\n constructor(address: number, free: (ptr: number) => void) {\n super(address);\n this.free = free;\n }\n\n [Symbol.dispose]() {\n this.free(this.valueOf());\n }\n}\n\n/**\n * Map that allows waiting for changes to values.\n */\nexport class EventMap<K, V> extends Map<K, V> {\n #listeners = new Map<K, Set<(value: V) => void>>();\n\n /**\n * Waits for the next `set()` call on the given key.\n */\n wait(key: K): Promise<V> {\n return new Promise((resolve) => {\n const listeners = this.#listeners.get(key) ?? new Set();\n listeners.add(resolve);\n this.#listeners.set(key, listeners);\n });\n }\n\n override set(key: K, value: V) {\n super.set(key, value);\n\n const listeners = this.#listeners.get(key);\n\n if (listeners) {\n for (const listener of listeners) {\n listener(value);\n listeners.delete(listener);\n }\n }\n\n return this;\n }\n}\n\n/**\n * Converts a `ReadableStream` into an `AsyncIterableIterator`.\n *\n * Allows you to use ReadableStreams in a `for await ... of` loop.\n */\nexport function fromReadable<R>(\n readable: ReadableStream<R>,\n options?: { preventCancel?: boolean }\n): AsyncIterableIterator<R> {\n const reader = readable.getReader();\n return fromReader(reader, options);\n}\n\n/**\n * Converts a `ReadableStreamDefaultReader` into an `AsyncIterableIterator`.\n *\n * Allows you to use Readers in a `for await ... of` loop.\n */\nexport async function* fromReader<R>(\n reader: ReadableStreamDefaultReader<R>,\n options?: { preventCancel?: boolean }\n): AsyncIterableIterator<R> {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n return value;\n }\n yield value;\n }\n } finally {\n if (!options?.preventCancel) {\n await reader.cancel();\n }\n reader.releaseLock();\n }\n}\n\nexport type UnderlyingSourceLockCallback = () => void;\n\n/**\n * `ReadableStream` with an optional lock callback.\n */\nexport class ExtendedReadableStream<R> extends ReadableStream<R> {\n #notifyLock?: () => void;\n\n constructor(\n {\n lock,\n ...underlyingSource\n }: UnderlyingSource & { lock?: UnderlyingSourceLockCallback },\n strategy?: QueuingStrategy<R>\n ) {\n super(underlyingSource, strategy);\n this.#notifyLock = lock;\n }\n\n override getReader() {\n // biome-ignore lint/suspicious/noExplicitAny: ReadableStream types don't expose internal reader methods\n const reader = super.getReader() as any;\n if (this.locked) {\n this.#notifyLock?.();\n }\n return reader;\n }\n\n override pipeThrough<T>(\n transform: ReadableWritablePair<T, R>,\n options?: StreamPipeOptions\n ): ReadableStream<T> {\n const stream = super.pipeThrough(transform, options);\n if (this.locked) {\n this.#notifyLock?.();\n }\n return stream;\n }\n\n override pipeTo(\n dest: WritableStream<R>,\n options?: StreamPipeOptions\n ): Promise<void> {\n const promise = super.pipeTo(dest, options);\n if (this.locked) {\n this.#notifyLock?.();\n }\n return promise;\n }\n\n override tee(): [ReadableStream<R>, ReadableStream<R>] {\n const [a, b] = super.tee();\n if (this.locked) {\n this.#notifyLock?.();\n }\n return [a, b];\n }\n}\n\n/**\n * Queues a microtask and returns a promise that resolves when\n * the microtask is executed.\n *\n * Microtasks are executed after the current task has completed,\n * but before the next task begins (tasks are the main unit of\n * work in the event loop).\n *\n * Useful when you want synchronous code from the current task to\n * complete before executing asynchronous code.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide\n */\nexport async function nextMicrotask() {\n return await new Promise<void>((resolve) => queueMicrotask(resolve));\n}\n\nexport type ConnectInterfacesOptions = {\n transformAtoB?: (chunk: Uint8Array) => Uint8Array;\n transformBtoA?: (chunk: Uint8Array) => Uint8Array;\n};\n\n/**\n * Connects two duplex streams by piping each stream's `readable`\n * to the other's `writable`.\n *\n * This is useful for connecting two network interfaces together\n * (e.g. a tap interface and a v86 network interface).\n *\n * Optionally supports transforming the data as it is passed\n * between the two streams. Use this to log or modify the data.\n */\nexport function connectStreams(\n interfaceA: DuplexStream<Uint8Array>,\n interfaceB: DuplexStream<Uint8Array>,\n { transformAtoB, transformBtoA }: ConnectInterfacesOptions = {}\n) {\n const streamA = transformAtoB\n ? interfaceA.readable.pipeThrough(\n new TransformStream<Uint8Array>({\n transform(chunk, controller) {\n try {\n const transformedChunk = transformAtoB(chunk);\n controller.enqueue(transformedChunk);\n } catch (error) {\n console.warn('Error transforming A to B', error);\n }\n },\n })\n )\n : interfaceA.readable;\n\n const streamB = transformBtoA\n ? interfaceB.readable.pipeThrough(\n new TransformStream<Uint8Array>({\n transform(chunk, controller) {\n try {\n const transformedChunk = transformBtoA(chunk);\n controller.enqueue(transformedChunk);\n } catch (error) {\n console.warn('Error transforming B to A', error);\n }\n },\n })\n )\n : interfaceB.readable;\n\n streamA.pipeTo(interfaceB.writable);\n streamB.pipeTo(interfaceA.writable);\n}\n","import { UniquePointer } from '../util.js';\nimport type {\n CommonExports,\n Pointer,\n SysExports,\n WasiExports,\n} from './types.js';\n\nexport abstract class Bindings<Imports, Exports> {\n #exports?: Exports & CommonExports & WasiExports & SysExports;\n\n abstract imports: Imports;\n\n get exports(): Exports & CommonExports & WasiExports & SysExports {\n if (!this.#exports) {\n throw new Error('exports were not registered');\n }\n return this.#exports;\n }\n\n /**\n * Register the exports object from the wasm module.\n */\n register(exports: Exports & CommonExports & WasiExports & SysExports) {\n this.#exports = exports;\n }\n\n /**\n * Allocates a region of wasm memory and returns a `UniquePointer` to the start.\n *\n * `UniquePointer` will automatically free the memory when it is disposed.\n * It is intended to be used with the `using` statement which will automatically\n * dispose of the pointer when the current scope ends.\n */\n smartMalloc(size: number) {\n return new UniquePointer(this.exports.malloc(size), this.exports.free);\n }\n\n /**\n * Copies a Uint8Array to a newly allocated region of wasm memory.\n *\n * @returns A pointer to the start of the copied data.\n */\n copyToMemory(data: Uint8Array) {\n const length = data.length;\n const pointer = this.smartMalloc(length);\n\n const memoryView = new Uint8Array(\n this.exports.memory.buffer,\n pointer.valueOf(),\n length\n );\n\n memoryView.set(data);\n\n return pointer;\n }\n\n /**\n * Copies a region of wasm memory to a new Uint8Array.\n *\n * @returns A new Uint8Array containing the copied data.\n */\n copyFromMemory(ptr: Pointer | number, length: number): Uint8Array {\n const buffer = this.exports.memory.buffer.slice(\n Number(ptr),\n Number(ptr) + length\n );\n return new Uint8Array(buffer);\n }\n\n /**\n * Creates a Uint8Array view over a region of wasm memory.\n */\n viewFromMemory(ptr: Pointer | number, length: number): Uint8Array {\n return new Uint8Array(this.exports.memory.buffer, Number(ptr), length);\n }\n}\n","import {\n type IPv4Address,\n type MacAddress,\n generateMacAddress,\n parseIPv4Address,\n parseMacAddress,\n serializeIPv4Cidr,\n serializeMacAddress,\n} from '@tcpip/wire';\nimport { LwipError } from '../lwip/errors.js';\nimport type { TapInterface, TapInterfaceOptions } from '../types.js';\nimport {\n ExtendedReadableStream,\n Hooks,\n fromReadable,\n nextMicrotask,\n} from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype TapInterfaceHandle = Pointer;\n\ntype TapInterfaceOuterHooks = {\n handle: TapInterfaceHandle;\n sendFrame(frame: Uint8Array): void;\n getMacAddress(): MacAddress;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\ntype TapInterfaceInnerHooks = {\n receiveFrame(frame: Uint8Array): void;\n};\n\nexport const tapInterfaceHooks = new Hooks<\n TapInterface,\n TapInterfaceOuterHooks,\n TapInterfaceInnerHooks\n>();\n\nexport type TapImports = {\n register_tap_interface(handle: TapInterfaceHandle): void;\n receive_frame(\n handle: TapInterfaceHandle,\n framePtr: number,\n length: number\n ): Promise<void>;\n};\n\nexport type TapExports = {\n create_tap_interface(\n macAddress: Pointer,\n ipAddress: Pointer,\n netmask: Pointer\n ): TapInterfaceHandle;\n remove_tap_interface(handle: TapInterfaceHandle): void;\n send_tap_interface(\n handle: TapInterfaceHandle,\n frame: Pointer,\n length: number\n ): number;\n enable_tap_interface(handle: TapInterfaceHandle): void;\n disable_tap_interface(handle: TapInterfaceHandle): void;\n};\n\nexport class TapBindings extends Bindings<TapImports, TapExports> {\n interfaces = new Map<TapInterfaceHandle, TapInterface>();\n\n imports = {\n register_tap_interface: (handle: TapInterfaceHandle) => {\n const tapInterface = new VirtualTapInterface();\n\n tapInterfaceHooks.setOuter(tapInterface, {\n handle,\n sendFrame: (frame) => {\n const framePtr = this.copyToMemory(frame);\n const result = this.exports.send_tap_interface(\n handle,\n framePtr,\n frame.length\n );\n\n if (result !== LwipError.ERR_OK) {\n throw new Error(`failed to send frame: ${result}`);\n }\n },\n getMacAddress: () => {\n const macPtr = this.exports.get_interface_mac_address(handle);\n\n const macBytes = this.viewFromMemory(macPtr, 6);\n return parseMacAddress(macBytes);\n },\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, tapInterface);\n },\n receive_frame: async (\n handle: TapInterfaceHandle,\n framePtr: number,\n length: number\n ) => {\n const frame = this.copyFromMemory(framePtr, length);\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n // This also gives the consumer a chance to start listening before we enqueue the first frame\n await nextMicrotask();\n\n const tapInterface = this.interfaces.get(handle);\n\n if (!tapInterface) {\n console.error('received frame on unknown tap interface');\n return;\n }\n\n tapInterfaceHooks\n .getInner(tapInterface)\n .receiveFrame(new Uint8Array(frame));\n },\n };\n\n async create(options: TapInterfaceOptions) {\n const macAddress = options.mac\n ? serializeMacAddress(options.mac)\n : generateMacAddress();\n\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using macAddressPtr = this.copyToMemory(macAddress);\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n\n const handle = this.exports.create_tap_interface(\n macAddressPtr,\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0\n );\n\n const tapInterface = this.interfaces.get(handle);\n\n if (!tapInterface) {\n throw new Error('tap interface failed to register');\n }\n\n return tapInterface;\n }\n\n async remove(tapInterface: TapInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === tapInterface) {\n this.exports.remove_tap_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualTapInterface implements TapInterface {\n #readableController?: ReadableStreamController<Uint8Array>;\n #isListening = false;\n\n readonly type = 'tap' as const;\n get mac(): MacAddress {\n return tapInterfaceHooks.getOuter(this).getMacAddress();\n }\n get ip(): IPv4Address | undefined {\n return tapInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return tapInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n\n constructor() {\n tapInterfaceHooks.setInner(this, {\n receiveFrame: async (frame: Uint8Array<ArrayBuffer>) => {\n // Do not buffer frames until the consumer signals intent\n // to listen - otherwise memory will grow indefinitely\n if (!this.#isListening) {\n return;\n }\n\n if (!this.#readableController) {\n throw new Error('readable stream not initialized');\n }\n\n this.#readableController.enqueue(frame);\n },\n });\n\n this.readable = new ExtendedReadableStream<Uint8Array>({\n start: (controller) => {\n this.#readableController = controller;\n },\n lock: () => {\n // We interpret anything that locks the stream (getReader, pipeThrough, pipeTo, tee)\n // as intent to start listening\n this.#isListening = true;\n },\n });\n\n this.writable = new WritableStream({\n write: (packet) => {\n try {\n tapInterfaceHooks.getOuter(this).sendFrame(packet);\n } catch (err) {\n console.error('tap interface send failed', err);\n }\n },\n });\n }\n\n listen() {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<Uint8Array> {\n return this.listen();\n }\n}\n","// Intentionally not using enum to avoid need for a transpiler\nexport const LwipError = {\n ERR_OK: 0,\n ERR_MEM: -1,\n ERR_BUF: -2,\n ERR_TIMEOUT: -3,\n ERR_RTE: -4,\n ERR_INPROGRESS: -5,\n ERR_VAL: -6,\n ERR_WOULDBLOCK: -7,\n ERR_USE: -8,\n ERR_ALREADY: -9,\n ERR_ISCONN: -10,\n ERR_CONN: -11,\n ERR_IF: -12,\n ERR_ABRT: -13,\n ERR_RST: -14,\n ERR_CLSD: -15,\n ERR_ARG: -16,\n} as const;\n\nexport type LwipError = (typeof LwipError)[keyof typeof LwipError];\n","import {\n type IPv4Address,\n parseIPv4Address,\n serializeIPv4Cidr,\n} from '@tcpip/wire';\nimport type { LoopbackInterface, LoopbackInterfaceOptions } from '../types.js';\nimport { Hooks } from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype LoopbackInterfaceHandle = Pointer;\n\ntype LoopbackInterfaceOuterHooks = {\n handle: LoopbackInterfaceHandle;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty hook type\ntype LoopbackInterfaceInnerHooks = {};\n\nexport const loopbackInterfaceHooks = new Hooks<\n LoopbackInterface,\n LoopbackInterfaceOuterHooks,\n LoopbackInterfaceInnerHooks\n>();\n\nexport type LoopbackImports = {\n register_loopback_interface(handle: LoopbackInterfaceHandle): void;\n};\n\nexport type LoopbackExports = {\n create_loopback_interface(\n ipAddress: Pointer,\n netmask: Pointer\n ): LoopbackInterfaceHandle;\n remove_loopback_interface(handle: LoopbackInterfaceHandle): void;\n};\n\nexport class LoopbackBindings extends Bindings<\n LoopbackImports,\n LoopbackExports\n> {\n interfaces = new Map<LoopbackInterfaceHandle, LoopbackInterface>();\n\n imports = {\n register_loopback_interface: (handle: LoopbackInterfaceHandle) => {\n const loopbackInterface = new VirtualLoopbackInterface();\n\n loopbackInterfaceHooks.setOuter(loopbackInterface, {\n handle,\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, loopbackInterface);\n },\n };\n\n async create(options: LoopbackInterfaceOptions) {\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n\n const handle = this.exports.create_loopback_interface(\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0\n );\n\n const loopbackInterface = this.interfaces.get(handle);\n\n if (!loopbackInterface) {\n throw new Error('loopback interface failed to register');\n }\n\n return loopbackInterface;\n }\n\n async remove(loopbackInterface: LoopbackInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === loopbackInterface) {\n this.exports.remove_loopback_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualLoopbackInterface implements LoopbackInterface {\n readonly type = 'loopback';\n get ip(): IPv4Address | undefined {\n return loopbackInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return loopbackInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n}\n","import type { DnsClient } from '@tcpip/dns';\nimport { serializeIPv4Address } from '@tcpip/wire';\nimport { LwipError } from '../lwip/errors.js';\nimport type {\n TcpConnection,\n TcpConnectionOptions,\n TcpListener,\n TcpListenerOptions,\n} from '../types.js';\nimport { EventMap, Hooks, fromReadable, nextMicrotask } from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype TcpListenerHandle = Pointer;\ntype TcpConnectionHandle = Pointer;\n\n// biome-ignore lint/complexity/noBannedTypes: intentionally empty hook type\ntype TcpListenerOuterHooks = {};\n\ntype TcpListenerInnerHooks = {\n accept(connection: TcpConnection): void;\n};\n\ntype TcpConnectionOuterHooks = {\n send(data: Uint8Array): Promise<void>;\n updateReceiveBuffer(length: number): void;\n close(): Promise<void>;\n closeWrite(): Promise<void>;\n};\n\ntype TcpConnectionInnerHooks = {\n receive(data: Uint8Array): Promise<void>;\n close(): Promise<void>;\n};\n\nconst tcpListenerHooks = new Hooks<\n TcpListener,\n TcpListenerOuterHooks,\n TcpListenerInnerHooks\n>();\n\nconst tcpConnectionHooks = new Hooks<\n TcpConnection,\n TcpConnectionOuterHooks,\n TcpConnectionInnerHooks\n>();\n\nexport const MAX_SEGMENT_SIZE = 1448; // effective data per segment: TCP_MSS (1460) - timestamp option (12)\nexport const MAX_WINDOW_SIZE = MAX_SEGMENT_SIZE * 4; // This must match TCP_WND in lwipopts.h\nexport const SEND_BUFFER_SIZE = MAX_SEGMENT_SIZE * 4; // This must match TCP_SND_BUF in lwipopts.h\nexport const READABLE_HIGH_WATER_MARK = MAX_SEGMENT_SIZE;\n\nexport type TcpImports = {\n accept_tcp_connection(\n listenerHandle: TcpListenerHandle,\n connectionHandle: TcpConnectionHandle\n ): Promise<void>;\n connected_tcp_connection(handle: TcpConnectionHandle): Promise<void>;\n closed_tcp_connection(handle: TcpConnectionHandle): Promise<void>;\n receive_tcp_chunk(\n handle: TcpConnectionHandle,\n chunkPtr: number,\n length: number\n ): Promise<void>;\n sent_tcp_chunk(handle: TcpConnectionHandle, length: number): void;\n};\n\nexport type TcpExports = {\n create_tcp_listener(host: Pointer | null, port: number): TcpListenerHandle;\n create_tcp_connection(host: Pointer, port: number): TcpConnectionHandle;\n close_tcp_connection(handle: TcpConnectionHandle): number;\n shutdown_tcp_connection_write(handle: TcpConnectionHandle): number;\n send_tcp_chunk(\n handle: TcpConnectionHandle,\n chunk: number,\n length: number\n ): number;\n update_tcp_receive_buffer(handle: TcpConnectionHandle, length: number): void;\n};\n\nexport class TcpBindings extends Bindings<TcpImports, TcpExports> {\n #tcpListeners = new Map<TcpListenerHandle, TcpListener>();\n #tcpConnections = new EventMap<TcpConnectionHandle, TcpConnection>();\n #tcpAcks = new Map<TcpConnectionHandle, (length: number) => void>();\n #tcpCloseAcks = new Map<TcpConnectionHandle, () => void>();\n #dnsClient: DnsClient;\n\n async #resolveHost(host: string) {\n try {\n return serializeIPv4Address(host);\n } catch (e) {\n const ip = await this.#dnsClient.lookup(host);\n return serializeIPv4Address(ip);\n }\n }\n\n constructor(dnsClient: DnsClient) {\n super();\n this.#dnsClient = dnsClient;\n }\n\n async #closeConnection(handle: TcpConnectionHandle) {\n while (true) {\n const result = this.exports.close_tcp_connection(handle);\n\n if (result === LwipError.ERR_OK) {\n return;\n }\n\n if (result !== LwipError.ERR_MEM) {\n throw new Error(`failed to close tcp connection: ${result}`);\n }\n\n await new Promise<void>((resolve) => {\n this.#tcpCloseAcks.set(handle, resolve);\n });\n }\n }\n\n async #closeConnectionWrite(handle: TcpConnectionHandle) {\n while (true) {\n const result = this.exports.shutdown_tcp_connection_write(handle);\n\n if (result === LwipError.ERR_OK) {\n return;\n }\n\n if (result !== LwipError.ERR_MEM) {\n throw new Error(`failed to shutdown tcp write side: ${result}`);\n }\n\n await new Promise<void>((resolve) => {\n this.#tcpCloseAcks.set(handle, resolve);\n });\n }\n }\n\n imports = {\n accept_tcp_connection: async (\n listenerHandle: TcpListenerHandle,\n connectionHandle: TcpConnectionHandle\n ) => {\n const listener = this.#tcpListeners.get(listenerHandle);\n\n if (!listener) {\n console.error('new tcp connection to unknown listener');\n return;\n }\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n const connection = new VirtualTcpConnection();\n\n tcpConnectionHooks.setOuter(connection, {\n send: async (data) => {\n const dataPtr = Number(this.copyToMemory(data));\n\n let bytesQueued = this.exports.send_tcp_chunk(\n connectionHandle,\n dataPtr,\n data.length\n );\n\n // If the entire data was not queued, send the remaining\n // chunks as space becomes available\n while (bytesQueued < data.length) {\n await new Promise<number>((resolve) => {\n this.#tcpAcks.set(connectionHandle, resolve);\n });\n const bytesRemaining = data.length - bytesQueued;\n\n bytesQueued += this.exports.send_tcp_chunk(\n connectionHandle,\n dataPtr + bytesQueued,\n bytesRemaining\n );\n }\n },\n updateReceiveBuffer: (length: number) => {\n this.exports.update_tcp_receive_buffer(connectionHandle, length);\n },\n close: async () => {\n await this.#closeConnection(connectionHandle);\n },\n closeWrite: async () => {\n await this.#closeConnectionWrite(connectionHandle);\n },\n });\n\n this.#tcpConnections.set(connectionHandle, connection);\n\n tcpListenerHooks.getInner(listener).accept(connection);\n },\n connected_tcp_connection: async (handle: TcpConnectionHandle) => {\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n const connection = new VirtualTcpConnection();\n\n tcpConnectionHooks.setOuter(connection, {\n send: async (data) => {\n const dataPtr = Number(this.copyToMemory(data));\n\n let bytesQueued = this.exports.send_tcp_chunk(\n handle,\n dataPtr,\n data.length\n );\n\n // If the entire data was not queued, send the remaining\n // chunks as space becomes available\n while (bytesQueued < data.length) {\n await new Promise<number>((resolve) => {\n this.#tcpAcks.set(handle, resolve);\n });\n const bytesRemaining = data.length - bytesQueued;\n\n bytesQueued += this.exports.send_tcp_chunk(\n handle,\n dataPtr + bytesQueued,\n bytesRemaining\n );\n }\n },\n updateReceiveBuffer: (length: number) => {\n this.exports.update_tcp_receive_buffer(handle, length);\n },\n close: async () => {\n await this.#closeConnection(handle);\n },\n closeWrite: async () => {\n await this.#closeConnectionWrite(handle);\n },\n });\n\n this.#tcpConnections.set(handle, connection);\n },\n closed_tcp_connection: async (handle: TcpConnectionHandle) => {\n const connection = this.#tcpConnections.get(handle);\n\n if (!connection) {\n console.error('received close on unknown tcp connection');\n return;\n }\n\n await tcpConnectionHooks.getInner(connection).close();\n },\n receive_tcp_chunk: async (\n handle: TcpConnectionHandle,\n chunkPtr: number,\n length: number\n ) => {\n const chunk = this.copyFromMemory(chunkPtr, length);\n const connection = this.#tcpConnections.get(handle);\n\n if (!connection) {\n console.error('received chunk on unknown tcp connection');\n return;\n }\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n tcpConnectionHooks.getInner(connection).receive(new Uint8Array(chunk));\n },\n sent_tcp_chunk: (handle: TcpConnectionHandle, length: number) => {\n const notifyAck = this.#tcpAcks.get(handle);\n this.#tcpAcks.delete(handle);\n notifyAck?.(length);\n\n const notifyCloseAck = this.#tcpCloseAcks.get(handle);\n this.#tcpCloseAcks.delete(handle);\n notifyCloseAck?.();\n },\n };\n\n async listen(options: TcpListenerOptions) {\n using hostPtr = options.host\n ? this.copyToMemory(await this.#resolveHost(options.host))\n : null;\n\n const handle = this.exports.create_tcp_listener(hostPtr, options.port);\n\n const tcpListener = new VirtualTcpListener();\n\n tcpListenerHooks.setOuter(tcpListener, {});\n\n this.#tcpListeners.set(handle, tcpListener);\n\n return tcpListener;\n }\n\n async connect(options: TcpConnectionOptions) {\n using hostPtr = this.copyToMemory(await this.#resolveHost(options.host));\n\n const handle = this.exports.create_tcp_connection(hostPtr, options.port);\n\n const tcpConnection = await this.#tcpConnections.wait(handle);\n\n if (!tcpConnection) {\n throw new Error('tcp failed to connect');\n }\n\n return tcpConnection;\n }\n}\n\nexport class VirtualTcpListener\n implements TcpListener, AsyncIterable<TcpConnection>\n{\n #connections: TcpConnection[] = [];\n #notifyConnection?: () => void;\n\n constructor() {\n tcpListenerHooks.setInner(this, {\n accept: async (connection: TcpConnection) => {\n this.#connections.push(connection);\n this.#notifyConnection?.();\n },\n });\n }\n\n async *[Symbol.asyncIterator](): AsyncIterableIterator<TcpConnection> {\n while (true) {\n await new Promise<void>((resolve) => {\n this.#notifyConnection = resolve;\n });\n\n yield* this.#connections;\n this.#connections = [];\n }\n }\n}\n\nexport class VirtualTcpConnection\n implements TcpConnection, AsyncIterable<Uint8Array>\n{\n #receiveBuffer: Uint8Array[] = [];\n #readableController?: ReadableStreamDefaultController<Uint8Array>;\n #writableController?: WritableStreamDefaultController;\n #remoteClosed = false;\n #readableClosed = false;\n\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n\n constructor() {\n tcpConnectionHooks.setInner(this, {\n receive: async (data: Uint8Array) => {\n // We maintain our own receive buffer prior to enqueueing to the readable\n // stream so that we can send window updates as data is consumed\n this.#receiveBuffer.push(data);\n this.#enqueueBuffer();\n },\n close: async () => {\n await nextMicrotask();\n this.#remoteClosed = true;\n this.#enqueueBuffer();\n },\n });\n\n this.readable = new ReadableStream(\n {\n start: (controller) => {\n this.#readableController = controller;\n },\n pull: () => {\n this.#enqueueBuffer();\n },\n },\n {\n highWaterMark: READABLE_HIGH_WATER_MARK,\n size: (chunk) => chunk.byteLength,\n }\n );\n\n this.writable = new WritableStream(\n {\n start: (controller) => {\n this.#writableController = controller;\n },\n write: async (chunk) => {\n await tcpConnectionHooks.getOuter(this).send(chunk);\n },\n close: async () => {\n await tcpConnectionHooks.getOuter(this).closeWrite();\n },\n },\n {\n // Send buffer capacity is managed by the TCP stack. Allow one queued\n // write so standard stream utilities like pipeTo() can start flowing.\n highWaterMark: 1,\n }\n );\n }\n\n #closeReadable() {\n if (this.#readableClosed) {\n return;\n }\n\n this.#readableClosed = true;\n try {\n this.#readableController?.close();\n } catch {}\n }\n\n #errorReadable(error: Error) {\n if (this.#readableClosed) {\n return;\n }\n\n this.#readableClosed = true;\n try {\n this.#readableController?.error(error);\n } catch {}\n }\n\n #enqueueBuffer() {\n if (this.#remoteClosed && this.#receiveBuffer.length === 0) {\n this.#closeReadable();\n this.#writableController?.error(new Error('tcp connection closed'));\n return;\n }\n\n if (!(this.#readableController?.desiredSize! > 0)) {\n return;\n }\n\n let bytesEnqueued = 0;\n\n // Enqueue chunks until the desired size is reached.\n // Always enqueue at least one chunk (desiredSize is a soft limit per the\n // WHATWG Streams spec - chunks can push it negative).\n while (this.#receiveBuffer.length > 0) {\n const chunkLength = this.#receiveBuffer[0]!.length;\n\n if (\n bytesEnqueued > 0 &&\n bytesEnqueued + chunkLength > this.#readableController!.desiredSize!\n ) {\n break;\n }\n\n const chunk = this.#receiveBuffer.shift()!;\n this.#readableController!.enqueue(chunk);\n bytesEnqueued += chunk.length;\n }\n\n // Notify the TCP stack that we've consumed data to reopen the receive window\n if (bytesEnqueued > 0) {\n tcpConnectionHooks.getOuter(this).updateReceiveBuffer(bytesEnqueued);\n }\n\n if (this.#remoteClosed && this.#receiveBuffer.length === 0) {\n this.#closeReadable();\n this.#writableController?.error(new Error('tcp connection closed'));\n }\n }\n\n async close() {\n await tcpConnectionHooks.getOuter(this).close();\n this.#errorReadable(new Error('tcp connection closed'));\n this.#writableController?.error(new Error('tcp connection closed'));\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Uint8Array> {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n}\n","import {\n type IPv4Address,\n parseIPv4Address,\n serializeIPv4Cidr,\n} from '@tcpip/wire';\nimport type { TunInterface, TunInterfaceOptions } from '../types.js';\nimport {\n ExtendedReadableStream,\n Hooks,\n fromReadable,\n nextMicrotask,\n} from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype TunInterfaceHandle = Pointer;\n\ntype TunInterfaceOuterHooks = {\n handle: TunInterfaceHandle;\n sendPacket(packet: Uint8Array): void;\n getIPv4Address(): IPv4Address | undefined;\n getIPv4Netmask(): IPv4Address | undefined;\n};\n\ntype TunInterfaceInnerHooks = {\n receivePacket(packet: Uint8Array): void;\n};\n\nconst tunInterfaceHooks = new Hooks<\n TunInterface,\n TunInterfaceOuterHooks,\n TunInterfaceInnerHooks\n>();\n\nexport type TunImports = {\n register_tun_interface(handle: TunInterfaceHandle): void;\n receive_packet(\n handle: TunInterfaceHandle,\n packetPtr: number,\n length: number\n ): Promise<void>;\n};\n\nexport type TunExports = {\n create_tun_interface(\n ipAddress: Pointer,\n netmask: Pointer\n ): TunInterfaceHandle;\n remove_tun_interface(handle: TunInterfaceHandle): void;\n send_tun_interface(\n handle: TunInterfaceHandle,\n packet: Pointer,\n length: number\n ): void;\n};\n\nexport class TunBindings extends Bindings<TunImports, TunExports> {\n interfaces = new Map<TunInterfaceHandle, TunInterface>();\n\n imports = {\n register_tun_interface: (handle: TunInterfaceHandle) => {\n const tunInterface = new VirtualTunInterface();\n\n tunInterfaceHooks.setOuter(tunInterface, {\n handle,\n sendPacket: (packet) => {\n const packetPtr = this.copyToMemory(packet);\n this.exports.send_tun_interface(handle, packetPtr, packet.length);\n },\n getIPv4Address: () => {\n const ipPtr = this.exports.get_interface_ip4_address(handle);\n\n if (ipPtr === 0) {\n return;\n }\n\n const ipBytes = this.viewFromMemory(ipPtr, 4);\n return parseIPv4Address(ipBytes);\n },\n getIPv4Netmask: () => {\n const netmaskPtr = this.exports.get_interface_ip4_netmask(handle);\n\n if (netmaskPtr === 0) {\n return;\n }\n\n const netmaskBytes = this.viewFromMemory(netmaskPtr, 4);\n return parseIPv4Address(netmaskBytes);\n },\n });\n\n this.interfaces.set(handle, tunInterface);\n },\n receive_packet: async (\n handle: TunInterfaceHandle,\n packetPtr: number,\n length: number\n ) => {\n const packet = this.copyFromMemory(packetPtr, length);\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n // This also gives the consumer a chance to start listening before we enqueue the first packet\n await nextMicrotask();\n\n const tunInterface = this.interfaces.get(handle);\n\n if (!tunInterface) {\n console.error('received packet on unknown tun interface');\n return;\n }\n\n tunInterfaceHooks\n .getInner(tunInterface)\n .receivePacket(new Uint8Array(packet));\n },\n };\n\n async create(options: TunInterfaceOptions) {\n const { ipAddress, netmask } = options.ip\n ? serializeIPv4Cidr(options.ip)\n : {};\n\n using ipAddressPtr = ipAddress ? this.copyToMemory(ipAddress) : undefined;\n using netmaskPtr = netmask ? this.copyToMemory(netmask) : undefined;\n\n const handle = this.exports.create_tun_interface(\n ipAddressPtr ?? 0,\n netmaskPtr ?? 0\n );\n\n const tunInterface = this.interfaces.get(handle);\n\n if (!tunInterface) {\n throw new Error('tun interface failed to register');\n }\n\n return tunInterface;\n }\n\n async remove(tunInterface: TunInterface) {\n for (const [handle, loopback] of this.interfaces.entries()) {\n if (loopback === tunInterface) {\n this.exports.remove_tun_interface(handle);\n this.interfaces.delete(handle);\n return;\n }\n }\n }\n}\n\nexport class VirtualTunInterface implements TunInterface {\n #readableController?: ReadableStreamController<Uint8Array>;\n #isListening = false;\n\n readonly type = 'tun' as const;\n get ip(): IPv4Address | undefined {\n return tunInterfaceHooks.getOuter(this).getIPv4Address();\n }\n get netmask(): IPv4Address | undefined {\n return tunInterfaceHooks.getOuter(this).getIPv4Netmask();\n }\n readable: ReadableStream<Uint8Array>;\n writable: WritableStream<Uint8Array>;\n\n constructor() {\n tunInterfaceHooks.setInner(this, {\n receivePacket: async (packet: Uint8Array<ArrayBuffer>) => {\n // Do not buffer packets until the consumer signals intent\n // to listen - otherwise memory will grow indefinitely\n if (!this.#isListening) {\n return;\n }\n\n if (!this.#readableController) {\n throw new Error('readable stream not initialized');\n }\n\n this.#readableController?.enqueue(packet);\n },\n });\n\n this.readable = new ExtendedReadableStream<Uint8Array>({\n start: (controller) => {\n this.#readableController = controller;\n },\n lock: () => {\n // We interpret anything that locks the stream (getReader, pipeThrough, pipeTo, tee)\n // as intent to start listening\n this.#isListening = true;\n },\n });\n\n this.writable = new WritableStream({\n write: (packet) => {\n tunInterfaceHooks.getOuter(this).sendPacket(packet);\n },\n });\n }\n\n listen() {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<Uint8Array> {\n return this.listen();\n }\n}\n","import type { DnsClient } from '@tcpip/dns';\nimport { parseIPv4Address, serializeIPv4Address } from '@tcpip/wire';\nimport { LwipError } from '../lwip/errors.js';\nimport type { UdpDatagram, UdpSocket, UdpSocketOptions } from '../types.js';\nimport { EventMap, Hooks, fromReadable, nextMicrotask } from '../util.js';\nimport { Bindings } from './base.js';\nimport type { Pointer } from './types.js';\n\ntype UdpSocketHandle = Pointer;\n\ntype UdpSocketOuterHooks = {\n send(datagram: UdpDatagram): Promise<void>;\n close(): Promise<void>;\n};\n\ntype UdpSocketInnerHooks = {\n receive(datagram: UdpDatagram): Promise<void>;\n};\n\nconst udpSocketHooks = new Hooks<\n UdpSocket,\n UdpSocketOuterHooks,\n UdpSocketInnerHooks\n>();\n\nexport type UdpImports = {\n receive_udp_datagram(\n handle: UdpSocketHandle,\n ip: number,\n port: number,\n datagramPtr: number,\n length: number\n ): Promise<void>;\n};\n\nexport type UdpExports = {\n open_udp_socket(host: Pointer | null, port: number): UdpSocketHandle;\n close_udp_socket(handle: UdpSocketHandle): void;\n send_udp_datagram(\n handle: UdpSocketHandle,\n ip: Pointer | null,\n port: number,\n datagram: Pointer,\n length: number\n ): number;\n};\n\nexport class UdpBindings extends Bindings<UdpImports, UdpExports> {\n #udpSockets = new EventMap<UdpSocketHandle, UdpSocket>();\n #dnsClient: DnsClient;\n\n async #resolveHost(host: string) {\n try {\n return serializeIPv4Address(host);\n } catch (e) {\n const ip = await this.#dnsClient.lookup(host);\n return serializeIPv4Address(ip);\n }\n }\n\n constructor(dnsClient: DnsClient) {\n super();\n this.#dnsClient = dnsClient;\n }\n\n imports = {\n receive_udp_datagram: async (\n handle: UdpSocketHandle,\n hostPtr: number,\n port: number,\n datagramPtr: number,\n length: number\n ) => {\n const host = this.copyFromMemory(hostPtr, 4);\n const datagram = this.copyFromMemory(datagramPtr, length);\n const socket = this.#udpSockets.get(handle);\n\n if (!socket) {\n console.error('received datagram on unknown udp socket');\n return;\n }\n\n // Wait for synchronous lwIP operations to complete to prevent reentrancy issues\n await nextMicrotask();\n\n udpSocketHooks.getInner(socket).receive({\n host: parseIPv4Address(host),\n port,\n data: datagram,\n });\n },\n };\n\n async open(options: UdpSocketOptions) {\n using hostPtr = options.host\n ? this.copyToMemory(await this.#resolveHost(options.host))\n : null;\n\n const handle = this.exports.open_udp_socket(hostPtr, options.port ?? 0);\n\n if (Number(handle) === 0) {\n throw new Error('failed to open udp socket');\n }\n\n const udpSocket = new VirtualUdpSocket();\n\n udpSocketHooks.setOuter(udpSocket, {\n send: async (datagram: UdpDatagram) => {\n using hostPtr = this.copyToMemory(\n await this.#resolveHost(datagram.host)\n );\n using datagramPtr = this.copyToMemory(datagram.data);\n\n const result = this.exports.send_udp_datagram(\n handle,\n hostPtr,\n datagram.port,\n datagramPtr,\n datagram.data.length\n );\n\n if (result !== LwipError.ERR_OK) {\n throw new Error(`failed to send udp datagram: ${result}`);\n }\n },\n close: async () => {\n this.exports.close_udp_socket(handle);\n this.#udpSockets.delete(handle);\n },\n });\n\n this.#udpSockets.set(handle, udpSocket);\n\n return udpSocket;\n }\n}\n\nexport class VirtualUdpSocket implements UdpSocket, AsyncIterable<UdpDatagram> {\n #readableController?: ReadableStreamDefaultController<UdpDatagram>;\n #writableController?: WritableStreamDefaultController;\n\n readable: ReadableStream<UdpDatagram>;\n writable: WritableStream<UdpDatagram>;\n\n constructor() {\n udpSocketHooks.setInner(this, {\n receive: async (datagram: UdpDatagram) => {\n if (!this.#readableController) {\n throw new Error('readable controller not initialized');\n }\n this.#readableController.enqueue(datagram);\n },\n });\n\n this.readable = new ReadableStream({\n start: (controller) => {\n this.#readableController = controller;\n },\n });\n\n this.writable = new WritableStream({\n start: (controller) => {\n this.#writableController = controller;\n },\n write: async (datagram) => {\n await udpSocketHooks.getOuter(this).send(datagram);\n },\n });\n }\n\n async close() {\n await udpSocketHooks.getOuter(this).close();\n this.#readableController?.error(new Error('udp socket closed'));\n this.#writableController?.error(new Error('udp socket closed'));\n }\n\n [Symbol.asyncIterator](): AsyncIterator<UdpDatagram> {\n if (this.readable.locked) {\n throw new Error('readable stream already locked');\n }\n return fromReadable(this.readable);\n }\n}\n","const IN_NODE =\n typeof process === 'object' &&\n typeof process.versions === 'object' &&\n typeof process.versions.node === 'string';\n\n/**\n * Fetches a file from the network or filesystem\n * depending on the environment.\n */\nexport async function fetchFile(input: string | URL, type: string) {\n if (IN_NODE) {\n return fetchFileNode(input, type);\n }\n return fetch(input);\n}\n\nasync function fetchFileNode(input: string | URL, type: string) {\n const fs = await import('node:fs');\n const { Readable } = await import('node:stream');\n const nodeStream = fs.createReadStream(input);\n const stream = Readable.toWeb(nodeStream) as ReadableStream<Uint8Array>;\n return new Response(stream, { headers: { 'Content-Type': type } });\n}\n"],"mappings":"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","names":["ConsoleStdout","File","OpenFile","WASI","DnsClient","generateMacAddress","parseIPv4Address","parseMacAddress","serializeIPv4Cidr","serializeMacAddress","Hooks","#outerHooks","#innerHooks","key","hooks","UniquePointer","address","free","DisposeSymbol","EventMap","#listeners","resolve","listeners","value","listener","fromReadable","readable","options","reader","fromReader","done","ExtendedReadableStream","#notifyLock","lock","underlyingSource","strategy","transform","stream","dest","promise","a","b","nextMicrotask","connectStreams","interfaceA","interfaceB","transformAtoB","transformBtoA","streamA","chunk","controller","transformedChunk","error","streamB","Bindings","#exports","exports","size","UniquePointer","data","length","pointer","ptr","buffer","generateMacAddress","parseIPv4Address","parseMacAddress","serializeIPv4Cidr","serializeMacAddress","LwipError","tapInterfaceHooks","Hooks","TapBindings","Bindings","handle","tapInterface","VirtualTapInterface","frame","framePtr","result","LwipError","macPtr","macBytes","parseMacAddress","ipPtr","ipBytes","parseIPv4Address","netmaskPtr","netmaskBytes","length","nextMicrotask","options","_stack","macAddress","serializeMacAddress","generateMacAddress","ipAddress","netmask","serializeIPv4Cidr","macAddressPtr","__using","ipAddressPtr","_","_error","_hasError","__callDispose","loopback","#readableController","#isListening","ExtendedReadableStream","controller","packet","err","fromReadable","bridgeInterfaceHooks","Hooks","BridgeBindings","Bindings","options","_stack","macAddress","serializeMacAddress","generateMacAddress","ipAddress","netmask","serializeIPv4Cidr","macAddressPtr","__using","ipAddressPtr","netmaskPtr","portHandles","port","tapInterfaceHooks","portHandlesPtr","handle","bridgeInterface","VirtualBridgeInterface","macPtr","macBytes","parseMacAddress","ipPtr","ipBytes","parseIPv4Address","netmaskBytes","_","_error","_hasError","__callDispose","loopback","parseIPv4Address","serializeIPv4Cidr","loopbackInterfaceHooks","Hooks","LoopbackBindings","Bindings","handle","loopbackInterface","VirtualLoopbackInterface","ipPtr","ipBytes","parseIPv4Address","netmaskPtr","netmaskBytes","options","_stack","ipAddress","netmask","serializeIPv4Cidr","ipAddressPtr","__using","_","_error","_hasError","__callDispose","loopback","serializeIPv4Address","tcpListenerHooks","Hooks","tcpConnectionHooks","MAX_SEGMENT_SIZE","MAX_WINDOW_SIZE","SEND_BUFFER_SIZE","READABLE_HIGH_WATER_MARK","TcpBindings","Bindings","#tcpListeners","#tcpConnections","EventMap","#tcpAcks","#tcpCloseAcks","#dnsClient","#resolveHost","host","serializeIPv4Address","ip","dnsClient","#closeConnection","handle","result","LwipError","resolve","#closeConnectionWrite","listenerHandle","connectionHandle","listener","nextMicrotask","connection","VirtualTcpConnection","data","dataPtr","bytesQueued","bytesRemaining","length","chunkPtr","chunk","notifyAck","notifyCloseAck","options","_stack","hostPtr","__using","tcpListener","VirtualTcpListener","_","_error","_hasError","__callDispose","tcpConnection","#connections","#notifyConnection","#receiveBuffer","#readableController","#writableController","#remoteClosed","#readableClosed","#enqueueBuffer","controller","#closeReadable","#errorReadable","error","bytesEnqueued","chunkLength","fromReadable","parseIPv4Address","serializeIPv4Cidr","tunInterfaceHooks","Hooks","TunBindings","Bindings","handle","tunInterface","VirtualTunInterface","packet","packetPtr","ipPtr","ipBytes","parseIPv4Address","netmaskPtr","netmaskBytes","length","nextMicrotask","options","_stack","ipAddress","netmask","serializeIPv4Cidr","ipAddressPtr","__using","_","_error","_hasError","__callDispose","loopback","#readableController","#isListening","ExtendedReadableStream","controller","fromReadable","parseIPv4Address","serializeIPv4Address","udpSocketHooks","Hooks","UdpBindings","Bindings","#udpSockets","EventMap","#dnsClient","#resolveHost","host","serializeIPv4Address","ip","dnsClient","handle","hostPtr","port","datagramPtr","length","datagram","socket","nextMicrotask","parseIPv4Address","options","_stack","__using","udpSocket","VirtualUdpSocket","result","LwipError","_","_error","_hasError","__callDispose","#readableController","#writableController","controller","fromReadable","IN_NODE","fetchFile","input","type","fetchFileNode","fs","Readable","nodeStream","stream","createStack","options","stack","VirtualNetworkStack","#options","#loopIntervalId","#dnsClient","#loopbackBindings","#tunBindings","#tapBindings","#bridgeBindings","#tcpBindings","#udpBindings","#listInterfaces","DnsClient","LoopbackBindings","TunBindings","TapBindings","BridgeBindings","TcpBindings","UdpBindings","#init","wasi","WASI","OpenFile","File","ConsoleStdout","msg","source","fetchFile","instance","wasmInstance","netInterface"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tcpip",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Virtual TCP/IP stack that can run anywhere",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,8 +30,8 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@bjorn3/browser_wasi_shim": "^0.3.0",
33
- "@tcpip/dns": "0.2.2",
34
- "@tcpip/wire": "0.1.3"
33
+ "@tcpip/wire": "0.1.3",
34
+ "@tcpip/dns": "0.2.2"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@playwright/test": "^1.52.0",
@@ -39,7 +39,7 @@
39
39
  "@types/node": "^22.15.19",
40
40
  "@vitest/browser": "^3.1.2",
41
41
  "tsup": "^8.3.5",
42
- "tsx": "^4.19.2",
42
+ "tsx": "^4.21.0",
43
43
  "typescript": "^5.8.3",
44
44
  "vitest": "^3.1.4"
45
45
  },
package/tcpip.wasm CHANGED
Binary file