camstreamerlib 1.9.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/RtspClient.js DELETED
@@ -1,288 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RtspClient = void 0;
4
- const net = require("net");
5
- const EventEmitter = require("events");
6
- const Digest_1 = require("./Digest");
7
- class RtspClient extends EventEmitter {
8
- constructor(options) {
9
- var _a, _b, _c;
10
- super();
11
- this.authorizationType = 'basic';
12
- this.wwwAuthenticateHeader = '';
13
- this.sessioncookie = Math.random().toString(36).substring(7);
14
- this.clientGet = null;
15
- this.clientPost = null;
16
- this.inputBuffer = null;
17
- this.state = 'HTTP_INIT';
18
- this.rtspPath = '';
19
- this.rtspCSeq = 0;
20
- this.control = '';
21
- this.session = '';
22
- this.authorizationSent = false;
23
- this.keepAliveTimer = null;
24
- this.disconnected = false;
25
- this.rtpMsgBuffer = '';
26
- this.ip = (_a = options === null || options === void 0 ? void 0 : options.ip) !== null && _a !== void 0 ? _a : '127.0.0.1';
27
- this.port = (_b = options === null || options === void 0 ? void 0 : options.port) !== null && _b !== void 0 ? _b : 80;
28
- this.auth = (_c = options === null || options === void 0 ? void 0 : options.auth) !== null && _c !== void 0 ? _c : '';
29
- EventEmitter.call(this);
30
- }
31
- connect(eventTopicFilter) {
32
- this.rtspPath = '/axis-media/media.amp?video=0&audio=0&event=on';
33
- if (eventTopicFilter.length != 0) {
34
- this.rtspPath += '&eventtopic=' + eventTopicFilter;
35
- }
36
- this.clientGet = new net.Socket();
37
- this.clientGet.connect(this.port, this.ip, () => {
38
- this.clientGet.write(this.getInitializationMessageGet());
39
- });
40
- this.clientGet.on('data', (data) => this.processGetMessage(data));
41
- this.clientGet.on('close', () => this.closeConnection);
42
- this.clientPost = new net.Socket();
43
- this.clientPost.connect(this.port, this.ip, () => {
44
- this.clientPost.write(this.getInitializationMessagePost());
45
- });
46
- this.clientPost.on('data', (data) => { });
47
- this.clientPost.on('close', () => this.closeConnection);
48
- }
49
- disconnect() {
50
- this.closeConnection('');
51
- }
52
- closeConnection(reason) {
53
- if (!this.disconnected) {
54
- this.disconnected = true;
55
- this.emit('disconnect', reason);
56
- }
57
- clearInterval(this.keepAliveTimer);
58
- this.clientGet.destroy();
59
- this.clientPost.destroy();
60
- }
61
- processGetMessage(data) {
62
- if (this.inputBuffer == null) {
63
- this.inputBuffer = Buffer.from(data, 'binary');
64
- }
65
- else {
66
- this.inputBuffer = Buffer.concat([this.inputBuffer, Buffer.from(data, 'binary')]);
67
- }
68
- if (this.state == 'HTTP_INIT') {
69
- const msg = this.parseRtspMessage();
70
- if (msg != null) {
71
- if (msg.statusLine.indexOf('200 OK') != -1) {
72
- this.state = 'RTSP_OPTION';
73
- this.sendRtspMessage(this.getRtspMessage());
74
- }
75
- else if (msg.statusLine.indexOf('401') != -1 && !this.authorizationSent) {
76
- this.authorizationSent = true;
77
- this.authorizationType = 'digest';
78
- this.wwwAuthenticateHeader = msg.headers['www-authenticate'];
79
- this.clientGet.write(this.getInitializationMessageGet());
80
- }
81
- else {
82
- this.closeConnection(msg.statusLine.toString());
83
- }
84
- }
85
- return;
86
- }
87
- while (this.inputBuffer.length > 0) {
88
- let msgType = '';
89
- let firstChar = String.fromCharCode(this.inputBuffer[0]);
90
- if (firstChar == 'R') {
91
- msgType = 'RTSP';
92
- }
93
- else if (firstChar == '$') {
94
- msgType = 'RTP';
95
- }
96
- else {
97
- this.closeConnection('Unknown message found: ' + this.inputBuffer);
98
- return;
99
- }
100
- if (msgType == 'RTSP') {
101
- let msg = this.parseRtspMessage();
102
- if (!msg) {
103
- break;
104
- }
105
- if (msg.statusLine.indexOf('401') != -1 && !this.authorizationSent) {
106
- this.authorizationSent = true;
107
- this.authorizationType = 'digest';
108
- this.wwwAuthenticateHeader = msg.headers['www-authenticate'];
109
- this.sendRtspMessage(this.getRtspMessage());
110
- return;
111
- }
112
- if (this.state != 'HTTP_INIT' && msg.statusLine.indexOf('RTSP/1.0 200 OK') == -1) {
113
- this.closeConnection('Invalid RTSP response: ' + msg.headersRaw + msg.body);
114
- return;
115
- }
116
- this.authorizationSent = false;
117
- switch (this.state) {
118
- case 'RTSP_OPTION': {
119
- this.state = 'RTSP_DESCRIBE';
120
- this.sendRtspMessage(this.getRtspMessage());
121
- break;
122
- }
123
- case 'RTSP_DESCRIBE': {
124
- const regex = /(a=control):(.*)/g;
125
- this.control = regex.exec(msg.body.toString())[2];
126
- this.state = 'RTSP_SETUP';
127
- this.sendRtspMessage(this.getRtspMessage());
128
- break;
129
- }
130
- case 'RTSP_SETUP': {
131
- this.session = msg.headers['session'].split(';')[0];
132
- this.state = 'RTSP_PLAY';
133
- this.sendRtspMessage(this.getRtspMessage());
134
- break;
135
- }
136
- case 'RTSP_PLAY': {
137
- this.emit('connect');
138
- this.state = 'RTSP_GET_PARAMETER';
139
- this.keepAliveTimer = setInterval(() => {
140
- this.sendRtspMessage(this.getRtspMessage());
141
- }, 30000);
142
- break;
143
- }
144
- }
145
- }
146
- else if (msgType == 'RTP') {
147
- let msg = this.parseRtpMessage();
148
- if (!msg) {
149
- break;
150
- }
151
- if (msg.channel == 0) {
152
- this.rtpMsgBuffer += msg.body.toString();
153
- while (true) {
154
- let msgEnd = this.rtpMsgBuffer.indexOf('</tt:MetadataStream>');
155
- if (msgEnd == -1) {
156
- break;
157
- }
158
- this.emit('event', this.rtpMsgBuffer.substring(0, msgEnd + 20));
159
- this.rtpMsgBuffer = this.rtpMsgBuffer.substring(msgEnd + 20);
160
- }
161
- }
162
- }
163
- }
164
- }
165
- parseRtspMessage() {
166
- const msgEndFound = this.inputBuffer.indexOf('\r\n\r\n');
167
- if (msgEndFound == -1) {
168
- return null;
169
- }
170
- const msgHeaders = this.inputBuffer.subarray(0, msgEndFound + 4);
171
- const headers = {};
172
- const regex = /([\w-]+): (.*)/g;
173
- const stringHeaders = msgHeaders.toString();
174
- let tmp;
175
- while ((tmp = regex.exec(stringHeaders))) {
176
- headers[tmp[1].toLowerCase()] = tmp[2];
177
- }
178
- let msgSize = msgEndFound + 4;
179
- if (headers['content-length'] != undefined) {
180
- msgSize += parseInt(headers['content-length']);
181
- }
182
- let body = this.inputBuffer.subarray(msgEndFound + 4, msgSize);
183
- this.inputBuffer = this.inputBuffer.subarray(msgSize);
184
- return {
185
- statusLine: msgHeaders.subarray(0, msgHeaders.indexOf('\r\n')),
186
- headers: headers,
187
- headersRaw: msgHeaders,
188
- body: body,
189
- };
190
- }
191
- parseRtpMessage() {
192
- const INTERLEAVED_HEADER_SIZE = 4;
193
- const RTP_HEADER_SIZE = 12;
194
- if (this.inputBuffer.length < INTERLEAVED_HEADER_SIZE) {
195
- return null;
196
- }
197
- let channel = this.inputBuffer[1];
198
- let msgDataSize = (this.inputBuffer[2] << 8) | this.inputBuffer[3];
199
- msgDataSize += INTERLEAVED_HEADER_SIZE;
200
- if (channel < 0 || channel > 1) {
201
- this.closeConnection(`InterleavedMessage - invalid channel found: ${channel}`);
202
- return null;
203
- }
204
- if (msgDataSize > this.inputBuffer.length) {
205
- return null;
206
- }
207
- let body = this.inputBuffer.subarray(INTERLEAVED_HEADER_SIZE + RTP_HEADER_SIZE, msgDataSize);
208
- this.inputBuffer = this.inputBuffer.subarray(msgDataSize);
209
- return { channel: channel, body: body };
210
- }
211
- getInitializationMessageGet() {
212
- return ('GET /axis-media/media.amp HTTP/1.1\r\n' +
213
- 'CSeq: 1\r\n' +
214
- 'User-Agent: Camstreamer RTSP Client\r\n' +
215
- `Host: ${this.ip}'\r\n` +
216
- `x-sessioncookie: ${this.sessioncookie}\r\n` +
217
- 'Accept: application/x-rtsp-tunnelled\r\n' +
218
- 'Pragma: no-cache\r\n' +
219
- `Authorization: ${this.getAuthHeader('GET', '/axis-media/media.amp')}\r\n` +
220
- 'Cache-Control: no-cache\r\n\r\n');
221
- }
222
- getInitializationMessagePost() {
223
- return ('POST /axis-media/media.amp HTTP/1.1\r\n' +
224
- 'CSeq: 1\r\n' +
225
- 'User-Agent: Camstreamer RTSP Client\r\n' +
226
- `Host: ${this.ip}\r\n` +
227
- `x-sessioncookie: ${this.sessioncookie}\r\n` +
228
- 'Content-Type: application/x-rtsp-tunnelled\r\n' +
229
- 'Pragma: no-cache\r\n' +
230
- 'Cache-Control: no-cache\r\n' +
231
- `Authorization: ${this.getAuthHeader('POST', '/axis-media/media.amp')}\r\n` +
232
- 'Content-Length: 32767\r\n\r\n');
233
- }
234
- getRtspMessage() {
235
- this.rtspCSeq++;
236
- switch (this.state) {
237
- case 'RTSP_OPTION': {
238
- return (`OPTIONS ${this.rtspPath} RTSP/1.0\r\n` +
239
- `CSeq: ${this.rtspCSeq}\r\n` +
240
- 'User-Agent: Camstreamer RTSP Client\r\n' +
241
- `Authorization: ${this.getAuthHeader('OPTIONS', this.rtspPath)}\r\n\r\n`);
242
- }
243
- case 'RTSP_DESCRIBE': {
244
- return (`DESCRIBE ${this.rtspPath} RTSP/1.0\r\n` +
245
- `CSeq: ${this.rtspCSeq}\r\n` +
246
- 'User-Agent: Camstreamer RTSP Client\r\n' +
247
- `Authorization: ${this.getAuthHeader('DESCRIBE', this.rtspPath)}\r\n` +
248
- 'Accept: application/sdp\r\n\r\n');
249
- }
250
- case 'RTSP_SETUP': {
251
- return (`SETUP ${this.control} RTSP/1.0\r\n` +
252
- `CSeq: ${this.rtspCSeq}\r\n` +
253
- 'User-Agent: Camstreamer RTSP Client\r\n' +
254
- `Authorization: ${this.getAuthHeader('SETUP', this.rtspPath)}\r\n` +
255
- 'Transport: RTP/AVP/TCP;unicast;interleaved=0-1\r\n\r\n');
256
- }
257
- case 'RTSP_PLAY': {
258
- return (`PLAY ${this.rtspPath} RTSP/1.0\r\n` +
259
- `CSeq: ${this.rtspCSeq}\r\n` +
260
- 'User-Agent: Camstreamer RTSP Client\r\n' +
261
- `Authorization: ${this.getAuthHeader('PLAY', this.rtspPath)}\r\n` +
262
- `Session: ${this.session}\r\n` +
263
- 'Range: npt=0.000-\r\n\r\n');
264
- }
265
- case 'RTSP_GET_PARAMETER': {
266
- return (`GET_PARAMETER ${this.rtspPath} RTSP/1.0\r\n` +
267
- `CSeq: ${this.rtspCSeq}\r\n` +
268
- 'User-Agent: Camstreamer RTSP Client\r\n' +
269
- `Authorization: ${this.getAuthHeader('GET_PARAMETER', this.rtspPath)}\r\n` +
270
- `Session: ${this.session}\r\n\r\n`);
271
- }
272
- }
273
- }
274
- getAuthHeader(method, path) {
275
- if (this.authorizationType == 'basic') {
276
- return `Basic ${Buffer.from(this.auth).toString('base64')}`;
277
- }
278
- else {
279
- const userPass = this.auth.split(':');
280
- return Digest_1.Digest.getAuthHeader(userPass[0], userPass[1], method, path, this.wwwAuthenticateHeader);
281
- }
282
- }
283
- sendRtspMessage(message) {
284
- const msgBase64 = Buffer.from(message).toString('base64');
285
- this.clientPost.write(msgBase64);
286
- }
287
- }
288
- exports.RtspClient = RtspClient;
File without changes
File without changes