• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

microsoft / botbuilder-js / 11576939296

29 Oct 2024 03:15PM UTC coverage: 84.703% (-0.5%) from 85.23%
11576939296

Pull #4774

github

web-flow
Merge fcec82c6b into 6ef82744a
Pull Request #4774: refactor: [#4684] Replace browserify with tsup

8186 of 10820 branches covered (75.66%)

Branch coverage included in aggregate %.

2 of 2 new or added lines in 1 file covered. (100.0%)

23 existing lines in 13 files now uncovered.

20514 of 23063 relevant lines covered (88.95%)

7295.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.6
/libraries/botframework-streaming/src/webSocket/webSocketTransport.ts
1
/**
6✔
2
 * @module botframework-streaming
3
 */
4
/**
5
 * Copyright (c) Microsoft Corporation. All rights reserved.
6
 * Licensed under the MIT License.
7
 */
8

9
import { INodeBuffer, ISocket, ITransportSender, ITransportReceiver } from '../interfaces';
10

11
/**
12
 * Web socket based transport.
13
 */
14
export class WebSocketTransport implements ITransportSender, ITransportReceiver {
2✔
15
    private readonly _queue: INodeBuffer[] = [];
86✔
16
    private _active: INodeBuffer;
17
    private _activeOffset = 0;
86✔
18
    private _activeReceiveResolve: (resolve: INodeBuffer) => void;
19
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
    private _activeReceiveReject: (reason?: any) => void;
21
    private _activeReceiveCount = 0;
86✔
22

23
    /**
24
     * Creates a new instance of the [WebSocketTransport](xref:botframework-streaming.WebSocketTransport) class.
25
     *
26
     * @param ws The ISocket to build this transport on top of.
27
     */
28
    constructor(private ws: ISocket) {
86✔
29
        this.ws.setOnMessageHandler((data): void => {
86✔
30
            this.onReceive(data);
88✔
31
        });
32
        this.ws.setOnErrorHandler((err): void => {
86✔
33
            this.onError(err);
×
34
        });
35
        this.ws.setOnCloseHandler((): void => {
86✔
36
            this.onClose();
78✔
37
        });
38
    }
39

40
    /**
41
     * Sends the given buffer out over the socket's connection.
42
     *
43
     * @param buffer The buffered data to send out over the connection.
44
     * @returns A number indicating the length of the sent data if the data was successfully sent, otherwise 0.
45
     */
46
    send(buffer: INodeBuffer): number {
47
        if (this.ws?.isConnected) {
100!
48
            this.ws.write(buffer);
98!
49

50
            return buffer.length;
98✔
51
        }
52

53
        return 0;
2✔
54
    }
55

56
    /**
57
     * Returns true if the transport is connected to a socket.
58
     *
59
     * @returns `true` if the the transport is connected and ready to send data, `false` otherwise.
60
     */
61
    get isConnected(): boolean {
62
        return !!this.ws?.isConnected;
18!
63
    }
64

65
    /**
66
     * Close the socket this transport is connected to.
67
     */
68
    close(): void {
69
        if (this.ws?.isConnected) {
173,279!
70
            this.ws.close();
32✔
71
        }
72
    }
73

74
    /**
75
     * Attempt to receive incoming data from the connected socket.
76
     *
77
     * @param count The number of bytes to attempt to receive.
78
     * @returns A buffer populated with the received data.
79
     */
UNCOV
80
    async receive(count: number): Promise<INodeBuffer> {
×
81
        if (this._activeReceiveResolve) {
140!
82
            throw new Error('Cannot call receive more than once before it has returned.');
×
83
        }
84

85
        this._activeReceiveCount = count;
140✔
86

87
        const promise = new Promise<INodeBuffer>((resolve, reject): void => {
140✔
88
            this._activeReceiveResolve = resolve;
140✔
89
            this._activeReceiveReject = reject;
140✔
90
        });
91

92
        this.trySignalData();
140✔
93

94
        return promise;
140✔
95
    }
96

97
    /**
98
     * Sets the transport to attempt to receive incoming data that has not yet arrived.
99
     *
100
     * @param data A buffer to store incoming data in.
101
     */
102
    onReceive(data: INodeBuffer): void {
103
        if (this._queue && data && data.byteLength > 0) {
92!
104
            this._queue.push(Buffer.from(data));
92✔
105
            this.trySignalData();
92✔
106
        }
107
    }
108

109
    private onClose(): void {
110
        if (this._activeReceiveReject) {
82!
111
            this._activeReceiveReject(new Error('Socket was closed.'));
62✔
112
        }
113

114
        this._active = null;
82✔
115
        this._activeOffset = 0;
82✔
116
        this._activeReceiveResolve = null;
82✔
117
        this._activeReceiveReject = null;
82✔
118
        this._activeReceiveCount = 0;
82✔
119
        this.ws = null;
82✔
120
    }
121

122
    private onError(err: Error): void {
123
        if (this._activeReceiveReject) {
2!
124
            this._activeReceiveReject(err);
×
125
        }
126
        this.onClose();
2✔
127
    }
128

129
    private trySignalData(): void {
130
        if (this._activeReceiveResolve) {
232!
131
            if (!this._active && this._queue.length > 0) {
166!
132
                this._active = this._queue.shift();
78✔
133
                this._activeOffset = 0;
78✔
134
            }
135

136
            if (this._active) {
166✔
137
                if (this._activeOffset === 0 && this._active.length === this._activeReceiveCount) {
78!
138
                    // can send the entire _active buffer
139
                    const buffer = this._active;
76✔
140
                    this._active = null;
76✔
141

142
                    this._activeReceiveResolve(buffer);
76✔
143
                } else {
144
                    // create a Buffer.from and copy some of the contents into it
145
                    const available = Math.min(this._activeReceiveCount, this._active.length - this._activeOffset);
2✔
146
                    const buffer = Buffer.alloc(available);
2✔
147
                    this._active.copy(buffer, 0, this._activeOffset, this._activeOffset + available);
2✔
148
                    this._activeOffset += available;
2✔
149

150
                    // if we used all of active, set it to undefined
151
                    if (this._activeOffset >= this._active.length) {
2!
152
                        this._active = null;
×
153
                        this._activeOffset = 0;
×
154
                    }
155

156
                    this._activeReceiveResolve(buffer);
2✔
157
                }
158

159
                this._activeReceiveCount = 0;
78✔
160
                this._activeReceiveReject = null;
78✔
161
                this._activeReceiveResolve = null;
78✔
162
            }
163
        }
164
    }
165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc