11'use strict' ;
22
33import { NativeModules } from 'react-native' ;
4+ /**
5+ * Provide a local JSDoc alias for stream.Transform so the JS file's type
6+ * annotations don't require @types/node at the project root. This keeps the
7+ * IntelliSense/types consistent while avoiding a hard dependency on Node types
8+ * for React Native consumers.
9+ * @typedef {import('stream').Transform } _Transform
10+ */
411import EventEmitter from 'eventemitter3' ;
512import { Buffer } from 'buffer' ;
613const Sockets = NativeModules . TcpSockets ;
714import { nativeEventEmitter , getNextId } from './Globals' ;
15+ import { FrameEncoder , FrameDecoder } from './FrameCodec' ;
816
917/**
1018 * @typedef {"ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex" } BufferEncoding
1119 *
1220 * @typedef {import('react-native').NativeEventEmitter } NativeEventEmitter
1321 *
22+ * Minimal interface for the frame encoder/decoder streams used in this
23+ * module. We declare only the members the Socket uses so the JSDoc types
24+ * don't require @types/node.
25+ * @typedef {{
26+ * write: (chunk: Buffer | Uint8Array) => boolean;
27+ * end: () => void;
28+ * once: (event: string, cb: (...args: any[]) => void) => void;
29+ * on: (event: string, cb: (...args: any[]) => void) => void;
30+ * pipe?: (dest: any) => any;
31+ * }} FrameStream
32+ *
1433 * @typedef {{address: string, family: string, port: number} } AddressInfo
1534 *
1635 * @typedef {{localAddress: string, localPort: number, remoteAddress: string, remotePort: number, remoteFamily: string} } NativeConnectionInfo
@@ -25,6 +44,7 @@ import { nativeEventEmitter, getNextId } from './Globals';
2544 * tls?: boolean,
2645 * tlsCheckValidity?: boolean,
2746 * tlsCert?: any,
47+ * frameMode?: boolean,
2848 * }} ConnectionOptions
2949 *
3050 * @typedef {object } ReadableEvents
@@ -39,6 +59,7 @@ import { nativeEventEmitter, getNextId } from './Globals';
3959 * @property {(err: Error) => void } error
4060 * @property {() => void } timeout
4161 * @property {() => void } secureConnect
62+ * @property {() => void } end
4263 *
4364 * @extends {EventEmitter<SocketEvents & ReadableEvents, any> }
4465 */
@@ -95,6 +116,12 @@ export default class Socket extends EventEmitter {
95116 this . remoteAddress = undefined ;
96117 this . remotePort = undefined ;
97118 this . remoteFamily = undefined ;
119+ /** @type {boolean } @private */
120+ this . _frameMode = false ;
121+ /** @type {any | null } @private */
122+ this . _frameEncoder = null ;
123+ /** @type {any | null } @private */
124+ this . _frameDecoder = null ;
98125 this . _registerEvents ( ) ;
99126 }
100127
@@ -159,6 +186,15 @@ export default class Socket extends EventEmitter {
159186 // Normalize args
160187 customOptions . host = customOptions . host || 'localhost' ;
161188 customOptions . port = Number ( customOptions . port ) || 0 ;
189+
190+ // Enable frame mode if requested
191+ if ( customOptions . frameMode ) {
192+ this . _frameMode = true ;
193+ this . _frameEncoder = /** @type {any } */ ( new FrameEncoder ( ) ) ;
194+ this . _frameDecoder = /** @type {any } */ ( new FrameDecoder ( ) ) ;
195+ this . _setupFrameCodec ( ) ;
196+ }
197+
162198 this . once ( 'connect' , ( ) => {
163199 if ( callback ) callback ( ) ;
164200 } ) ;
@@ -309,6 +345,11 @@ export default class Socket extends EventEmitter {
309345 if ( this . _destroyed ) return this ;
310346 this . _destroyed = true ;
311347 this . _clearTimeout ( ) ;
348+
349+ // Clean up frame codec references
350+ this . _frameDecoder = null ;
351+ this . _frameEncoder = null ;
352+
312353 Sockets . destroy ( this . _id ) ;
313354 return this ;
314355 }
@@ -351,7 +392,15 @@ export default class Socket extends EventEmitter {
351392 write ( buffer , encoding , cb ) {
352393 if ( this . _pending || this . _destroyed ) throw new Error ( 'Socket is closed.' ) ;
353394
354- const generatedBuffer = this . _generateSendBuffer ( buffer , encoding ) ;
395+ let generatedBuffer = this . _generateSendBuffer ( buffer , encoding ) ;
396+
397+ // Apply frame encoding if in frame mode
398+ if ( this . _frameMode ) {
399+ // Use varint encoding for libp2p compatibility
400+ const varint = this . _encodeVarint ( generatedBuffer . byteLength ) ;
401+ generatedBuffer = Buffer . concat ( [ varint , generatedBuffer ] ) ;
402+ }
403+
355404 this . _writeBufferSize += generatedBuffer . byteLength ;
356405 const currentMsgId = this . _msgId ;
357406 this . _msgId = ( this . _msgId + 1 ) % Number . MAX_SAFE_INTEGER ;
@@ -450,6 +499,22 @@ export default class Socket extends EventEmitter {
450499 Sockets . resume ( this . _id ) ;
451500 }
452501
502+ /**
503+ * @private
504+ */
505+ _setupFrameCodec ( ) {
506+ if ( ! this . _frameDecoder || ! this . _frameEncoder ) return ;
507+
508+ // Wire up decoder to emit framed data
509+ this . _frameDecoder . on ( 'data' , ( /** @type {Buffer } */ frame ) => {
510+ this . emit ( 'data' , this . _encoding ? frame . toString ( this . _encoding ) : frame ) ;
511+ } ) ;
512+
513+ this . _frameDecoder . on ( 'error' , ( /** @type {Error } */ err ) => {
514+ this . emit ( 'error' , err ) ;
515+ } ) ;
516+ }
517+
453518 /**
454519 * @private
455520 */
@@ -459,8 +524,14 @@ export default class Socket extends EventEmitter {
459524 if ( ! this . _paused ) {
460525 const bufferData = Buffer . from ( evt . data , 'base64' ) ;
461526 this . _bytesRead += bufferData . byteLength ;
462- const finalData = this . _encoding ? bufferData . toString ( this . _encoding ) : bufferData ;
463- this . emit ( 'data' , finalData ) ;
527+
528+ if ( this . _frameMode && this . _frameDecoder ) {
529+ // Feed raw data into frame decoder
530+ this . _frameDecoder . write ( bufferData ) ;
531+ } else {
532+ const finalData = this . _encoding ? bufferData . toString ( this . _encoding ) : bufferData ;
533+ this . emit ( 'data' , finalData ) ;
534+ }
464535 } else {
465536 // If the socket is paused, save the data events for later
466537 this . _pausedDataEvents . push ( evt ) ;
@@ -525,6 +596,22 @@ export default class Socket extends EventEmitter {
525596 }
526597 }
527598
599+ /**
600+ * @private
601+ * @param {number } n
602+ */
603+ _encodeVarint ( n ) {
604+ if ( n < 0 ) throw new RangeError ( 'varint unsigned only' ) ;
605+ const o = [ ] ;
606+ do {
607+ let b = n & 0x7f ;
608+ n = Math . floor ( n / 128 ) ;
609+ if ( n > 0 ) b |= 0x80 ;
610+ o . push ( b ) ;
611+ } while ( n > 0 ) ;
612+ return Buffer . from ( o ) ;
613+ }
614+
528615 /**
529616 * @private
530617 */
0 commit comments