(
private readonly client: WebSocket,
private readonly request: IncomingHttpMessage,
private readonly webSocketServer: IWebSocketServerAdapter,
private readonly createMessageHandler: Factory<IMessageHandler, [IncomingMessage, IWebSocketAdapter]>,
private readonly rateLimiter: Factory<IRateLimiter>,
private readonly settings: Factory<Settings>,
)
| 37 | private readonly authenticatedPubkeys: Set<string> |
| 38 | |
| 39 | public constructor( |
| 40 | private readonly client: WebSocket, |
| 41 | private readonly request: IncomingHttpMessage, |
| 42 | private readonly webSocketServer: IWebSocketServerAdapter, |
| 43 | private readonly createMessageHandler: Factory<IMessageHandler, [IncomingMessage, IWebSocketAdapter]>, |
| 44 | private readonly rateLimiter: Factory<IRateLimiter>, |
| 45 | private readonly settings: Factory<Settings>, |
| 46 | ) { |
| 47 | super() |
| 48 | this.alive = true |
| 49 | this.subscriptions = new Map() |
| 50 | |
| 51 | this.clientId = Buffer.from(this.request.headers['sec-websocket-key'] as string, 'base64').toString('hex') |
| 52 | |
| 53 | const address = getRemoteAddress(this.request, this.settings()) |
| 54 | |
| 55 | this.clientAddress = new SocketAddress({ |
| 56 | address: address, |
| 57 | family: address.indexOf(':') >= 0 ? 'ipv6' : 'ipv4', |
| 58 | }) |
| 59 | |
| 60 | this.client |
| 61 | .on('error', (error) => { |
| 62 | if (error.name === 'RangeError' && error.message === 'Max payload size exceeded') { |
| 63 | logger.error(`web-socket-adapter: client ${this.clientId} (${this.getClientAddress()}) sent payload too large`) |
| 64 | } else if (error.name === 'RangeError' && error.message === 'Invalid WebSocket frame: RSV1 must be clear') { |
| 65 | logger(`client ${this.clientId} (${this.getClientAddress()}) enabled compression`) |
| 66 | } else { |
| 67 | logger.error(`web-socket-adapter: client error ${this.clientId} (${this.getClientAddress()}):`, error) |
| 68 | } |
| 69 | |
| 70 | this.client.close() |
| 71 | }) |
| 72 | .on('message', this.onClientMessage.bind(this)) |
| 73 | .on('close', this.onClientClose.bind(this)) |
| 74 | .on('pong', this.onClientPong.bind(this)) |
| 75 | .on('ping', this.onClientPing.bind(this)) |
| 76 | |
| 77 | this.on(WebSocketAdapterEvent.Heartbeat, this.onHeartbeat.bind(this)) |
| 78 | .on(WebSocketAdapterEvent.Subscribe, this.onSubscribed.bind(this)) |
| 79 | .on(WebSocketAdapterEvent.Unsubscribe, this.onUnsubscribed.bind(this)) |
| 80 | .on(WebSocketAdapterEvent.Event, this.onSendEvent.bind(this)) |
| 81 | .on(WebSocketAdapterEvent.Broadcast, this.onBroadcast.bind(this)) |
| 82 | .on(WebSocketAdapterEvent.Message, this.sendMessage.bind(this)) |
| 83 | |
| 84 | logger('client %s connected from %s', this.clientId, this.clientAddress.address) |
| 85 | |
| 86 | // NIP-42 |
| 87 | this.challenge = randomBytes(32).toString('base64url') |
| 88 | this.authenticatedPubkeys = new Set() |
| 89 | this.sendMessage(createAuthChallengeMessage(this.challenge)) |
| 90 | } |
| 91 | |
| 92 | public getClientId(): string { |
| 93 | return this.clientId |
nothing calls this directly
no test coverage detected