@tomgiee/tsdp 1.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/LICENSE +21 -0
- package/README.md +124 -0
- package/dist/src/builder/media-builder.d.ts +221 -0
- package/dist/src/builder/media-builder.d.ts.map +1 -0
- package/dist/src/builder/media-builder.js +385 -0
- package/dist/src/builder/session-builder.d.ts +195 -0
- package/dist/src/builder/session-builder.d.ts.map +1 -0
- package/dist/src/builder/session-builder.js +366 -0
- package/dist/src/index.d.ts +67 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +250 -0
- package/dist/src/parser/attribute-parser.d.ts +100 -0
- package/dist/src/parser/attribute-parser.d.ts.map +1 -0
- package/dist/src/parser/attribute-parser.js +217 -0
- package/dist/src/parser/field-parser.d.ts +124 -0
- package/dist/src/parser/field-parser.d.ts.map +1 -0
- package/dist/src/parser/field-parser.js +335 -0
- package/dist/src/parser/media-parser.d.ts +45 -0
- package/dist/src/parser/media-parser.d.ts.map +1 -0
- package/dist/src/parser/media-parser.js +157 -0
- package/dist/src/parser/primitive-parser.d.ts +138 -0
- package/dist/src/parser/primitive-parser.d.ts.map +1 -0
- package/dist/src/parser/primitive-parser.js +316 -0
- package/dist/src/parser/scanner.d.ts +142 -0
- package/dist/src/parser/scanner.d.ts.map +1 -0
- package/dist/src/parser/scanner.js +284 -0
- package/dist/src/parser/session-parser.d.ts +35 -0
- package/dist/src/parser/session-parser.d.ts.map +1 -0
- package/dist/src/parser/session-parser.js +207 -0
- package/dist/src/parser/time-parser.d.ts +74 -0
- package/dist/src/parser/time-parser.d.ts.map +1 -0
- package/dist/src/parser/time-parser.js +168 -0
- package/dist/src/serializer/attribute-serializer.d.ts +18 -0
- package/dist/src/serializer/attribute-serializer.d.ts.map +1 -0
- package/dist/src/serializer/attribute-serializer.js +34 -0
- package/dist/src/serializer/field-serializer.d.ts +112 -0
- package/dist/src/serializer/field-serializer.d.ts.map +1 -0
- package/dist/src/serializer/field-serializer.js +212 -0
- package/dist/src/serializer/media-serializer.d.ts +31 -0
- package/dist/src/serializer/media-serializer.d.ts.map +1 -0
- package/dist/src/serializer/media-serializer.js +83 -0
- package/dist/src/serializer/session-serializer.d.ts +29 -0
- package/dist/src/serializer/session-serializer.d.ts.map +1 -0
- package/dist/src/serializer/session-serializer.js +99 -0
- package/dist/src/serializer/time-serializer.d.ts +46 -0
- package/dist/src/serializer/time-serializer.d.ts.map +1 -0
- package/dist/src/serializer/time-serializer.js +86 -0
- package/dist/src/types/attributes.d.ts +318 -0
- package/dist/src/types/attributes.d.ts.map +1 -0
- package/dist/src/types/attributes.js +225 -0
- package/dist/src/types/errors.d.ts +129 -0
- package/dist/src/types/errors.d.ts.map +1 -0
- package/dist/src/types/errors.js +186 -0
- package/dist/src/types/fields.d.ts +100 -0
- package/dist/src/types/fields.d.ts.map +1 -0
- package/dist/src/types/fields.js +48 -0
- package/dist/src/types/media.d.ts +148 -0
- package/dist/src/types/media.d.ts.map +1 -0
- package/dist/src/types/media.js +137 -0
- package/dist/src/types/network.d.ts +136 -0
- package/dist/src/types/network.d.ts.map +1 -0
- package/dist/src/types/network.js +130 -0
- package/dist/src/types/primitives.d.ts +193 -0
- package/dist/src/types/primitives.d.ts.map +1 -0
- package/dist/src/types/primitives.js +195 -0
- package/dist/src/types/session.d.ts +122 -0
- package/dist/src/types/session.d.ts.map +1 -0
- package/dist/src/types/session.js +81 -0
- package/dist/src/types/time.d.ts +129 -0
- package/dist/src/types/time.d.ts.map +1 -0
- package/dist/src/types/time.js +84 -0
- package/dist/src/utils/address-parser.d.ts +100 -0
- package/dist/src/utils/address-parser.d.ts.map +1 -0
- package/dist/src/utils/address-parser.js +338 -0
- package/dist/src/utils/format-validators.d.ts +77 -0
- package/dist/src/utils/format-validators.d.ts.map +1 -0
- package/dist/src/utils/format-validators.js +504 -0
- package/dist/src/utils/line-reader.d.ts +84 -0
- package/dist/src/utils/line-reader.d.ts.map +1 -0
- package/dist/src/utils/line-reader.js +169 -0
- package/dist/src/utils/time-converter.d.ts +99 -0
- package/dist/src/utils/time-converter.d.ts.map +1 -0
- package/dist/src/utils/time-converter.js +195 -0
- package/dist/src/validator/media-validator.d.ts +27 -0
- package/dist/src/validator/media-validator.d.ts.map +1 -0
- package/dist/src/validator/media-validator.js +241 -0
- package/dist/src/validator/semantic-validator.d.ts +47 -0
- package/dist/src/validator/semantic-validator.d.ts.map +1 -0
- package/dist/src/validator/semantic-validator.js +207 -0
- package/dist/src/validator/session-validator.d.ts +36 -0
- package/dist/src/validator/session-validator.d.ts.map +1 -0
- package/dist/src/validator/session-validator.js +280 -0
- package/dist/tests/integration/round-trip.test.d.ts +5 -0
- package/dist/tests/integration/round-trip.test.d.ts.map +1 -0
- package/dist/tests/integration/round-trip.test.js +320 -0
- package/dist/tests/integration/voip-examples.test.d.ts +5 -0
- package/dist/tests/integration/voip-examples.test.d.ts.map +1 -0
- package/dist/tests/integration/voip-examples.test.js +361 -0
- package/dist/tests/unit/builder/media-builder.test.d.ts +5 -0
- package/dist/tests/unit/builder/media-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/builder/media-builder.test.js +524 -0
- package/dist/tests/unit/builder/session-builder.test.d.ts +5 -0
- package/dist/tests/unit/builder/session-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/builder/session-builder.test.js +367 -0
- package/dist/tests/unit/parser/attribute-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/attribute-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/attribute-parser.test.js +319 -0
- package/dist/tests/unit/parser/field-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/field-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/field-parser.test.js +355 -0
- package/dist/tests/unit/parser/media-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/media-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/media-parser.test.js +241 -0
- package/dist/tests/unit/parser/primitive-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/primitive-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/primitive-parser.test.js +261 -0
- package/dist/tests/unit/parser/scanner.test.d.ts +5 -0
- package/dist/tests/unit/parser/scanner.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/scanner.test.js +241 -0
- package/dist/tests/unit/parser/session-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/session-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/session-parser.test.js +346 -0
- package/dist/tests/unit/parser/time-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/time-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/time-parser.test.js +173 -0
- package/dist/tests/unit/serializer/attribute-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/attribute-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/attribute-serializer.test.js +78 -0
- package/dist/tests/unit/serializer/field-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/field-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/field-serializer.test.js +159 -0
- package/dist/tests/unit/serializer/media-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/media-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/media-serializer.test.js +155 -0
- package/dist/tests/unit/serializer/session-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/session-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/session-serializer.test.js +317 -0
- package/dist/tests/unit/serializer/time-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/time-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/time-serializer.test.js +115 -0
- package/dist/tests/unit/types/errors.test.d.ts +5 -0
- package/dist/tests/unit/types/errors.test.d.ts.map +1 -0
- package/dist/tests/unit/types/errors.test.js +127 -0
- package/dist/tests/unit/types/network.test.d.ts +5 -0
- package/dist/tests/unit/types/network.test.d.ts.map +1 -0
- package/dist/tests/unit/types/network.test.js +132 -0
- package/dist/tests/unit/types/primitives.test.d.ts +5 -0
- package/dist/tests/unit/types/primitives.test.d.ts.map +1 -0
- package/dist/tests/unit/types/primitives.test.js +108 -0
- package/dist/tests/unit/utils/address-parser.test.d.ts +5 -0
- package/dist/tests/unit/utils/address-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/address-parser.test.js +203 -0
- package/dist/tests/unit/utils/format-validators.test.d.ts +5 -0
- package/dist/tests/unit/utils/format-validators.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/format-validators.test.js +224 -0
- package/dist/tests/unit/utils/line-reader.test.d.ts +5 -0
- package/dist/tests/unit/utils/line-reader.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/line-reader.test.js +157 -0
- package/dist/tests/unit/utils/time-converter.test.d.ts +5 -0
- package/dist/tests/unit/utils/time-converter.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/time-converter.test.js +190 -0
- package/dist/tests/unit/validator/media-validator.test.d.ts +5 -0
- package/dist/tests/unit/validator/media-validator.test.d.ts.map +1 -0
- package/dist/tests/unit/validator/media-validator.test.js +313 -0
- package/dist/tests/unit/validator/semantic-validator.test.d.ts +5 -0
- package/dist/tests/unit/validator/semantic-validator.test.d.ts.map +1 -0
- package/dist/tests/unit/validator/semantic-validator.test.js +262 -0
- package/dist/tests/unit/validator/session-validator.test.d.ts +5 -0
- package/dist/tests/unit/validator/session-validator.test.d.ts.map +1 -0
- package/dist/tests/unit/validator/session-validator.test.js +447 -0
- package/package.json +50 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session builder for SDP (RFC 8866)
|
|
4
|
+
*
|
|
5
|
+
* Provides a fluent builder API for creating SDP session descriptions.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.SessionBuilder = void 0;
|
|
9
|
+
exports.sessionBuilder = sessionBuilder;
|
|
10
|
+
const fields_1 = require("../types/fields");
|
|
11
|
+
const time_1 = require("../types/time");
|
|
12
|
+
const attributes_1 = require("../types/attributes");
|
|
13
|
+
const network_1 = require("../types/network");
|
|
14
|
+
const primitives_1 = require("../types/primitives");
|
|
15
|
+
const errors_1 = require("../types/errors");
|
|
16
|
+
const media_builder_1 = require("./media-builder");
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Session Builder
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Fluent builder for creating SDP session descriptions
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const sdp = new SessionBuilder()
|
|
26
|
+
* .origin('alice', '2890844526', '2890842807', '192.168.1.1')
|
|
27
|
+
* .sessionName('My Session')
|
|
28
|
+
* .connection('192.168.1.100')
|
|
29
|
+
* .addAudioMedia(49170, 'RTP/AVP', ['0', '8'])
|
|
30
|
+
* .build();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
class SessionBuilder {
|
|
34
|
+
constructor() {
|
|
35
|
+
this._version = 0;
|
|
36
|
+
this._emails = [];
|
|
37
|
+
this._phones = [];
|
|
38
|
+
this._bandwidths = [];
|
|
39
|
+
this._timeDescriptions = [];
|
|
40
|
+
this._attributes = [];
|
|
41
|
+
this._mediaDescriptions = [];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Set the origin field
|
|
45
|
+
*
|
|
46
|
+
* @param username - Username (use '-' if no username)
|
|
47
|
+
* @param sessId - Session ID (recommend NTP timestamp string)
|
|
48
|
+
* @param sessVersion - Session version (recommend NTP timestamp string)
|
|
49
|
+
* @param address - Origin address (IPv4, IPv6, or FQDN)
|
|
50
|
+
* @param addrType - Address type ('IP4' or 'IP6'), auto-detected if not provided
|
|
51
|
+
*/
|
|
52
|
+
origin(username, sessId, sessVersion, address, addrType) {
|
|
53
|
+
const detectedAddrType = addrType !== null && addrType !== void 0 ? addrType : this.detectAddressType(address);
|
|
54
|
+
const unicastAddress = this.parseAddress(address, detectedAddrType);
|
|
55
|
+
this._origin = (0, fields_1.createOrigin)(username, sessId, sessVersion, 'IN', detectedAddrType, unicastAddress);
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Set the origin with auto-generated session ID and version
|
|
60
|
+
*
|
|
61
|
+
* @param username - Username (use '-' if no username)
|
|
62
|
+
* @param address - Origin address
|
|
63
|
+
*/
|
|
64
|
+
originAuto(username, address) {
|
|
65
|
+
const now = Date.now().toString();
|
|
66
|
+
return this.origin(username, now, now, address);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Set the session name
|
|
70
|
+
*
|
|
71
|
+
* @param name - Session name (use ' ' if no meaningful name)
|
|
72
|
+
*/
|
|
73
|
+
sessionName(name) {
|
|
74
|
+
if (name.length === 0) {
|
|
75
|
+
throw errors_1.BuilderError.invalidConfiguration('Session name cannot be empty (use " " if no meaningful name)');
|
|
76
|
+
}
|
|
77
|
+
this._sessionName = name;
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Set the session information/title
|
|
82
|
+
*/
|
|
83
|
+
sessionInformation(info) {
|
|
84
|
+
this._sessionInformation = info;
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Set the URI for more information
|
|
89
|
+
*/
|
|
90
|
+
uri(uri) {
|
|
91
|
+
this._uri = uri;
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Add an email address
|
|
96
|
+
*/
|
|
97
|
+
addEmail(email) {
|
|
98
|
+
this._emails.push(email);
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Add a phone number
|
|
103
|
+
*/
|
|
104
|
+
addPhone(phone) {
|
|
105
|
+
this._phones.push(phone);
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Set the session-level connection
|
|
110
|
+
*
|
|
111
|
+
* @param address - Connection address (IPv4, IPv6, or FQDN)
|
|
112
|
+
* @param addrType - Address type, auto-detected if not provided
|
|
113
|
+
*/
|
|
114
|
+
connection(address, addrType) {
|
|
115
|
+
const detectedAddrType = addrType !== null && addrType !== void 0 ? addrType : this.detectAddressType(address);
|
|
116
|
+
const connectionAddress = this.parseAddress(address, detectedAddrType);
|
|
117
|
+
this._connection = (0, fields_1.createConnection)('IN', detectedAddrType, connectionAddress);
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Set the session-level connection with multicast TTL
|
|
122
|
+
*/
|
|
123
|
+
connectionMulticast(address, ttl, addrType) {
|
|
124
|
+
const detectedAddrType = addrType !== null && addrType !== void 0 ? addrType : this.detectAddressType(address);
|
|
125
|
+
let connectionAddress;
|
|
126
|
+
if (detectedAddrType === 'IP4') {
|
|
127
|
+
connectionAddress = (0, network_1.createIP4MulticastAddress)((0, network_1.createIP4Address)(address), ttl);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
connectionAddress = (0, network_1.createIP6MulticastAddress)((0, network_1.createIP6Address)(address));
|
|
131
|
+
}
|
|
132
|
+
this._connection = (0, fields_1.createConnection)('IN', detectedAddrType, connectionAddress);
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Add bandwidth information
|
|
137
|
+
*
|
|
138
|
+
* @param type - Bandwidth type ('CT' for conference total, 'AS' for application specific)
|
|
139
|
+
* @param kbps - Bandwidth in kilobits per second
|
|
140
|
+
*/
|
|
141
|
+
addBandwidth(type, kbps) {
|
|
142
|
+
this._bandwidths.push((0, fields_1.createBandwidth)(type, kbps));
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Add a time description
|
|
147
|
+
*
|
|
148
|
+
* @param startTime - Start time (NTP timestamp, 0 for unbounded)
|
|
149
|
+
* @param stopTime - Stop time (NTP timestamp, 0 for unbounded)
|
|
150
|
+
*/
|
|
151
|
+
addTiming(startTime, stopTime) {
|
|
152
|
+
this._timeDescriptions.push((0, time_1.createTimeDescription)((0, time_1.createTiming)(startTime, stopTime)));
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Add permanent timing (0 to 0 = unbounded session)
|
|
157
|
+
*/
|
|
158
|
+
permanentTiming() {
|
|
159
|
+
this._timeDescriptions.push((0, time_1.createTimeDescription)((0, time_1.createPermanentTiming)()));
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Add a time description object
|
|
164
|
+
*/
|
|
165
|
+
addTimeDescription(timeDescription) {
|
|
166
|
+
this._timeDescriptions.push(timeDescription);
|
|
167
|
+
return this;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Set encryption key (OBSOLETE per RFC 8866)
|
|
171
|
+
*
|
|
172
|
+
* @param keyValue - The key value (e.g., "clear:password" or "base64:encoded")
|
|
173
|
+
*/
|
|
174
|
+
key(keyValue) {
|
|
175
|
+
this._key = (0, primitives_1.createKey)(keyValue);
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Add a session-level attribute
|
|
180
|
+
*/
|
|
181
|
+
addAttribute(attr) {
|
|
182
|
+
this._attributes.push(attr);
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Add a custom property attribute
|
|
187
|
+
*/
|
|
188
|
+
addPropertyAttribute(name) {
|
|
189
|
+
this._attributes.push({ kind: 'property', name });
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Add a custom value attribute
|
|
194
|
+
*/
|
|
195
|
+
addValueAttribute(name, value) {
|
|
196
|
+
this._attributes.push((0, attributes_1.createValueAttribute)(name, value));
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Set direction to sendrecv
|
|
201
|
+
*/
|
|
202
|
+
sendrecv() {
|
|
203
|
+
return this.addAttribute((0, attributes_1.createSendrecv)());
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Set direction to recvonly
|
|
207
|
+
*/
|
|
208
|
+
recvonly() {
|
|
209
|
+
return this.addAttribute((0, attributes_1.createRecvonly)());
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Set direction to sendonly
|
|
213
|
+
*/
|
|
214
|
+
sendonly() {
|
|
215
|
+
return this.addAttribute((0, attributes_1.createSendonly)());
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Set direction to inactive
|
|
219
|
+
*/
|
|
220
|
+
inactive() {
|
|
221
|
+
return this.addAttribute((0, attributes_1.createInactive)());
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Add a category attribute
|
|
225
|
+
*/
|
|
226
|
+
category(cat) {
|
|
227
|
+
return this.addValueAttribute('cat', cat);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Add keywords attribute
|
|
231
|
+
*/
|
|
232
|
+
keywords(keywords) {
|
|
233
|
+
return this.addValueAttribute('keywds', keywords);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Add tool attribute
|
|
237
|
+
*/
|
|
238
|
+
tool(tool) {
|
|
239
|
+
return this.addValueAttribute('tool', tool);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Add charset attribute
|
|
243
|
+
*/
|
|
244
|
+
charset(charset) {
|
|
245
|
+
return this.addValueAttribute('charset', charset);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Add a media description
|
|
249
|
+
*/
|
|
250
|
+
addMedia(mediaDescription) {
|
|
251
|
+
this._mediaDescriptions.push(mediaDescription);
|
|
252
|
+
return this;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Add a media description using a builder
|
|
256
|
+
*
|
|
257
|
+
* @param builderFn - Function that configures the media builder
|
|
258
|
+
*/
|
|
259
|
+
addMediaBuilder(builderFn) {
|
|
260
|
+
const builder = new media_builder_1.MediaBuilder();
|
|
261
|
+
const configuredBuilder = builderFn(builder);
|
|
262
|
+
this._mediaDescriptions.push(configuredBuilder.build());
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Add an audio media description
|
|
267
|
+
*
|
|
268
|
+
* @param port - Port number
|
|
269
|
+
* @param proto - Protocol (e.g., 'RTP/AVP')
|
|
270
|
+
* @param formats - Format list (e.g., ['0', '8'] for PCMU and PCMA)
|
|
271
|
+
*/
|
|
272
|
+
addAudioMedia(port, proto, formats) {
|
|
273
|
+
const builder = new media_builder_1.MediaBuilder()
|
|
274
|
+
.type('audio')
|
|
275
|
+
.port(port)
|
|
276
|
+
.protocol(proto)
|
|
277
|
+
.formats(formats);
|
|
278
|
+
this._mediaDescriptions.push(builder.build());
|
|
279
|
+
return this;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Add a video media description
|
|
283
|
+
*/
|
|
284
|
+
addVideoMedia(port, proto, formats) {
|
|
285
|
+
const builder = new media_builder_1.MediaBuilder()
|
|
286
|
+
.type('video')
|
|
287
|
+
.port(port)
|
|
288
|
+
.protocol(proto)
|
|
289
|
+
.formats(formats);
|
|
290
|
+
this._mediaDescriptions.push(builder.build());
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Build the session description
|
|
295
|
+
*
|
|
296
|
+
* @throws BuilderError if required fields are missing
|
|
297
|
+
*/
|
|
298
|
+
build() {
|
|
299
|
+
// Validate required fields
|
|
300
|
+
if (!this._origin) {
|
|
301
|
+
throw errors_1.BuilderError.missingRequired('origin');
|
|
302
|
+
}
|
|
303
|
+
if (!this._sessionName) {
|
|
304
|
+
throw errors_1.BuilderError.missingRequired('sessionName');
|
|
305
|
+
}
|
|
306
|
+
// Add permanent timing if no time descriptions
|
|
307
|
+
if (this._timeDescriptions.length === 0) {
|
|
308
|
+
this._timeDescriptions.push((0, time_1.createTimeDescription)((0, time_1.createPermanentTiming)()));
|
|
309
|
+
}
|
|
310
|
+
// Validate connection coverage
|
|
311
|
+
const hasSessionConnection = this._connection !== undefined;
|
|
312
|
+
if (!hasSessionConnection && this._mediaDescriptions.length > 0) {
|
|
313
|
+
const allMediaHaveConnection = this._mediaDescriptions.every((md) => md.connections.length > 0);
|
|
314
|
+
if (!allMediaHaveConnection) {
|
|
315
|
+
throw errors_1.BuilderError.invalidConfiguration('Connection information required: must be present at session level or in every media description');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
version: this._version,
|
|
320
|
+
origin: this._origin,
|
|
321
|
+
sessionName: this._sessionName,
|
|
322
|
+
sessionInformation: this._sessionInformation,
|
|
323
|
+
uri: this._uri,
|
|
324
|
+
emails: this._emails,
|
|
325
|
+
phones: this._phones,
|
|
326
|
+
connection: this._connection,
|
|
327
|
+
bandwidths: this._bandwidths,
|
|
328
|
+
timeDescriptions: this._timeDescriptions,
|
|
329
|
+
key: this._key,
|
|
330
|
+
attributes: this._attributes,
|
|
331
|
+
mediaDescriptions: this._mediaDescriptions,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
// ============================================================================
|
|
335
|
+
// Private Helpers
|
|
336
|
+
// ============================================================================
|
|
337
|
+
detectAddressType(address) {
|
|
338
|
+
// Simple heuristic: if it contains ':', it's IPv6
|
|
339
|
+
if (address.includes(':')) {
|
|
340
|
+
return 'IP6';
|
|
341
|
+
}
|
|
342
|
+
return 'IP4';
|
|
343
|
+
}
|
|
344
|
+
parseAddress(address, addrType) {
|
|
345
|
+
// Check if it's an IP address or FQDN
|
|
346
|
+
if (addrType === 'IP6' || address.includes(':')) {
|
|
347
|
+
return (0, network_1.createIP6Address)(address);
|
|
348
|
+
}
|
|
349
|
+
// Check if it looks like an IPv4 address (contains dots and numbers only)
|
|
350
|
+
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(address)) {
|
|
351
|
+
return (0, network_1.createIP4Address)(address);
|
|
352
|
+
}
|
|
353
|
+
// Otherwise treat as FQDN
|
|
354
|
+
return (0, network_1.createFQDN)(address);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
exports.SessionBuilder = SessionBuilder;
|
|
358
|
+
// ============================================================================
|
|
359
|
+
// Factory Function
|
|
360
|
+
// ============================================================================
|
|
361
|
+
/**
|
|
362
|
+
* Create a new session builder
|
|
363
|
+
*/
|
|
364
|
+
function sessionBuilder() {
|
|
365
|
+
return new SessionBuilder();
|
|
366
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TSDP - TypeScript SDP Library
|
|
3
|
+
*
|
|
4
|
+
* A complete, RFC 8866-compliant SDP (Session Description Protocol) library
|
|
5
|
+
* for TypeScript/JavaScript applications.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Full RFC 8866 compliance
|
|
9
|
+
* - Type-safe with branded types
|
|
10
|
+
* - Fluent builder APIs
|
|
11
|
+
* - Comprehensive validation
|
|
12
|
+
* - Parse and serialize SDP
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { parseSessionDescription, serializeSessionDescription, SessionBuilder } from 'tsdp';
|
|
17
|
+
*
|
|
18
|
+
* // Parse SDP
|
|
19
|
+
* const sdp = parseSessionDescription(sdpString);
|
|
20
|
+
*
|
|
21
|
+
* // Build SDP
|
|
22
|
+
* const session = new SessionBuilder()
|
|
23
|
+
* .origin('alice', '123', '456', '192.168.1.1')
|
|
24
|
+
* .sessionName('My Call')
|
|
25
|
+
* .connection('192.168.1.100')
|
|
26
|
+
* .addAudioMedia(49170, 'RTP/AVP', ['0', '8'])
|
|
27
|
+
* .build();
|
|
28
|
+
*
|
|
29
|
+
* // Serialize SDP
|
|
30
|
+
* const sdpString = serializeSessionDescription(session);
|
|
31
|
+
*
|
|
32
|
+
* // Validate SDP
|
|
33
|
+
* const result = validateSdp(session);
|
|
34
|
+
* if (!result.valid) {
|
|
35
|
+
* console.error(result.errors);
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @packageDocumentation
|
|
40
|
+
*/
|
|
41
|
+
export { SessionDescription, createSessionDescription, createMinimalSessionDescription, } from './types/session';
|
|
42
|
+
export { MediaDescription, Media, Port, SimplePort, PortRange, createMedia, createSimplePort, createPortRange, createMediaDescription, isSimplePort, isPortRange, getPortNumber, getPortNumbers, } from './types/media';
|
|
43
|
+
export { Origin, Connection, Bandwidth, createOrigin, createConnection, createBandwidth, } from './types/fields';
|
|
44
|
+
export { TimeDescription, Timing, Repeat, Timezone, TimezoneAdjustment, createTiming, createPermanentTiming, createRepeat, createTimezoneAdjustment, createTimezone, createTimeDescription, } from './types/time';
|
|
45
|
+
export { Attribute, PropertyAttribute, ValueAttribute, RtpmapValue, FmtpValue, createPropertyAttribute, createValueAttribute, createRecvonly, createSendrecv, createSendonly, createInactive, createRtpmap, createFmtp, createPtime, createMaxptime, isPropertyAttribute, isValueAttribute, isDirectionAttribute, } from './types/attributes';
|
|
46
|
+
export { IP4Address, IP6Address, FQDN, ExtensionAddress, UnicastAddress, IP4MulticastAddress, IP6MulticastAddress, FQDNMulticastAddress, MulticastAddress, ConnectionAddress, createIP4Address, createIP6Address, createFQDN, createExtensionAddress, createIP4MulticastAddress, createIP6MulticastAddress, createFQDNMulticastAddress, isMulticastAddress, isUnicastAddress, isIP4MulticastAddress, isIP6MulticastAddress, isFQDNMulticastAddress, } from './types/network';
|
|
47
|
+
export { Position, Version, SessionName, Username, SessionId, SessionVersion, Information, URI, Email, Phone, Key, BandwidthType, Protocol, Format, AttributeName, AttributeValue, NetType, AddrType, MediaType, NtpTime, TimeUnit, TypedTime, createVersion, createSessionName, createUsername, createNtpTime, createTypedTime, } from './types/primitives';
|
|
48
|
+
export { SdpError, ParseError, GrammarError, ValidationError, SerializationError, BuilderError, } from './types/errors';
|
|
49
|
+
export { parseSessionDescription } from './parser/session-parser';
|
|
50
|
+
export { parseVersionField, parseOriginField, parseSessionNameField, parseInformationField, parseUriField, parseEmailField, parsePhoneField, parseConnectionField, parseBandwidthField, parseKeyField, } from './parser/field-parser';
|
|
51
|
+
export { parseTimingField, parseRepeatField, parseTimezoneField, parseTimeDescription, } from './parser/time-parser';
|
|
52
|
+
export { parseAttributeField, parseRtpmapValue, parseFmtpValue, parsePtimeValue, parseMaxptimeValue, parseFramerateValue, parseQualityValue, } from './parser/attribute-parser';
|
|
53
|
+
export { parseMediaField, parseMediaDescription } from './parser/media-parser';
|
|
54
|
+
export { serializeSessionDescription } from './serializer/session-serializer';
|
|
55
|
+
export { serializeVersionField, serializeOriginField, serializeSessionNameField, serializeInformationField, serializeUriField, serializeEmailField, serializePhoneField, serializeConnectionField, serializeConnectionAddress, serializeBandwidthField, serializeKeyField, } from './serializer/field-serializer';
|
|
56
|
+
export { serializeTimingField, serializeRepeatField, serializeTimezoneField, serializeTimeDescription, } from './serializer/time-serializer';
|
|
57
|
+
export { serializeAttributeField } from './serializer/attribute-serializer';
|
|
58
|
+
export { serializeMediaField, serializeMediaDescription } from './serializer/media-serializer';
|
|
59
|
+
export { validateSdp, validateSemanticConstraints, ValidationOptions, } from './validator/semantic-validator';
|
|
60
|
+
export { validateSessionDescription, ValidationResult, validResult, invalidResult, } from './validator/session-validator';
|
|
61
|
+
export { validateMediaDescription, validateAllMediaDescriptions } from './validator/media-validator';
|
|
62
|
+
export { SessionBuilder, sessionBuilder } from './builder/session-builder';
|
|
63
|
+
export { MediaBuilder, mediaBuilder, audioBuilder, videoBuilder } from './builder/media-builder';
|
|
64
|
+
export { isIP4Address, isIP6Address, isFQDN, isIP4MulticastAddress as isIP4MulticastRange, isIP6MulticastAddress as isIP6MulticastRange, parseIP4Address, parseIP6Address, parseFQDN, parseUnicastAddress, detectAddressType, } from './utils/address-parser';
|
|
65
|
+
export { parseTypedTime, serializeTypedTime, typedTimeToSeconds, secondsToTypedTime, addTypedTimes, compareTypedTimes, typedTimesEqual, normalizeTypedTime, } from './utils/time-converter';
|
|
66
|
+
export { splitLines, parseLine, parseLines, joinLines, formatLine, isValidLineType, getLineTypeName, ParsedLine, } from './utils/line-reader';
|
|
67
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|