drachtio-srf 4.5.31 → 4.5.32

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.
@@ -1,69 +1,143 @@
1
1
  declare module 'drachtio-srf' {
2
2
  import { Socket } from 'net';
3
3
  import { EventEmitter } from 'events';
4
-
4
+
5
5
  type SipMethod = 'ACK' | 'BYE' | 'CANCEL' | 'INFO' | 'INVITE' | 'MESSAGE' | 'NOTIFY' | 'OPTIONS' | 'PRACK' | 'PUBLISH' | 'REFER' | 'REGISTER' | 'SUBSCRIBE' | 'UPDATE';
6
-
6
+ type SipMessageHeaders = Record<string, string>;
7
+ type AOR = { name: string; uri: string; params?: Record<string, any>; };
8
+
7
9
  export interface SrfConfig {
8
10
  apiSecret?: string;
9
11
  host?: string;
10
12
  port?: number;
11
13
  secret?: string;
12
14
  }
13
-
15
+
16
+ export function parseUri(uri: string): { user: string; host: string; params?: Record<string, any>; };
17
+ export function stringifyUri(uri: object): string;
18
+
14
19
  export interface SipMessage {
15
- headers: {[name: string]: string | string[]};
16
- raw: string;
20
+ type: "request" | "response";
17
21
  body: string;
18
- method: SipMethod;
19
- version: string;
20
- uri: string;
21
22
  payload: object[];
23
+ source: "network" | "application";
24
+ source_address: string;
25
+ source_port: string;
26
+ protocol: string;
27
+ stackTime: string;
28
+ calledNumber: string;
29
+ callingNumber: string;
30
+ raw: string;
22
31
  get(name: string): string;
32
+ has(name: string): boolean;
33
+ set(name: string, value: string);
34
+ getParsedHeader(name: "contact" | "Contact"): Array<AOR>;
35
+ getParsedHeader(name: "via" | "Via"): Array<Via>;
36
+ getParsedHeader(name: "To" | "to" | "From" | "from" | "refer-to" | "referred-by" | "p-asserted-identity" | "remote-party-id"): AOR;
37
+ getParsedHeader(name: string): string;
23
38
  }
24
-
25
- export interface SrfRequest {
26
- headers: {[name: string]: any};
27
- msg: any;
39
+
40
+ export interface SrfRequest extends SipMessage {
28
41
  method: SipMethod;
29
- uri: string;
30
- from: string;
31
- to: string;
32
- callId: string;
42
+ isNewInvite(): boolean
43
+ cancel(callback: () => {})
33
44
  branch: string;
45
+ callId: string;
46
+ from: string;
47
+ headers: Record<string, string>;
48
+ msg: any;
34
49
  sdp: string;
35
- get(name: string): string;
36
- has(name: string): boolean;
50
+ srf: any;
51
+ to: string;
52
+ uri: string;
53
+ registration?: {
54
+ type: "unregister" | "register";
55
+ expires: number;
56
+ contact: Array<AOR>;
57
+ aor: string;
58
+ };
37
59
  }
38
-
39
- export interface SrfResponse {
40
- headers: {[name: string]: any};
60
+
61
+ export interface SrfResponse extends SipMessage {
41
62
  status: number;
42
- send(sdp?: string): void;
43
- end(): void;
44
- set(name: string, value: string | number): void;
45
- get(name: string): string;
63
+ statusCode: number;
64
+ reason: string;
65
+ finalResponseSent: boolean;
66
+ send(status: number);
67
+ send(status: number, opts: object);
68
+ send(status: number, reason: string, opts: object);
69
+ send(status: number, reason: string, opts: object, callback: (err, msg) => {});
70
+ end();
71
+ }
72
+
73
+ export interface Dialog {
74
+ sip: { callId: string; localTag: string; remoteTag: string; };
75
+ onHold: boolean;
76
+ other: Dialog;
77
+ type: "uac" | "uas";
78
+ local: { uri: string; sdp: string; };
79
+ remote: { uri: string; sdp: string; };
80
+ req: SrfRequest;
81
+ destroy(opts?: { headers: Record<string, string>; }, callback?: (err, msg) => {}): void;
82
+ modify(sdp, callback?: (err: any, msg: SrfResponse) => void): void;
83
+ modify({ noAck: boolean }, callback?: (err: any, resp: any, resAck: any) => void): void;
84
+ ack(string): void;
85
+ on(messageType: "ack", callback: (msg: SrfResponse) => void): void;
86
+ on(messageType: "destroy", callback: (msg: SrfRequest) => void): void;
87
+ on(messageType: "info", callback: (req: SrfRequest, res: SrfResponse) => void): void;
88
+ on(messageType: "message", callback: (req: SrfRequest, res: SrfResponse) => void): void;
89
+ on(messageType: "modify", callback: (req: SrfRequest, res: SrfResponse) => void): void;
90
+ on(messageType: "notify", callback: (req: SrfRequest, res: SrfResponse) => void): void;
91
+ on(messageType: "options", callback: (req: SrfRequest, res: SrfResponse) => void): void;
92
+ on(messageType: "refer", callback: (req: SrfRequest, res: SrfResponse) => void): void;
93
+ on(messageType: "refresh", callback: (msg: SrfResponse) => void): void;
94
+ on(messageType: "update", callback: (req: SrfRequest, res: SrfResponse) => void): void;
95
+ on(messageType: "modify", callback: (req: SrfRequest, res: SrfResponse) => void): void;
96
+ once(messageType: string, callback: (msg: SrfResponse) => void): void;
97
+ listeners(messageType: string): any[];
98
+ request(opts?: { method: SipMethod; headers?: Record<string, string | number>; body?: string; }, callback?: (err, msg) => {});
99
+ }
100
+
101
+ export interface CreateUASOptions {
102
+ localSdp: string;
103
+ headers?: SipMessageHeaders;
104
+ }
105
+
106
+ export interface CreateUACOptions {
107
+ headers?: SipMessageHeaders;
108
+ uri?: string;
109
+ noAck?: boolean;
110
+ localSdp?: string;
111
+ proxy?: string;
112
+ auth?: { username: string; password: string; };
113
+ }
114
+
115
+ export interface CreateB2BUAOptions {
116
+ headers?: SipMessageHeaders;
117
+ responseHeaders?: SipMessageHeaders | ((uacRes: SipMessageHeaders, headers: SipMessageHeaders) => SipMessageHeaders | null);
118
+ localSdpA?: string | ((sdp: string, res: SrfResponse) => string | Promise<string>);
119
+ localSdpB?: string | ((sdp: string) => string | Promise<string>);
120
+ proxyRequestHeaders?: string[];
121
+ proxyResponseHeaders?: string[];
122
+ passFailure?: boolean;
123
+ passProvisionalResponses?: boolean;
124
+ proxy?: string;
125
+ auth?: { username: string; password: string; };
46
126
  }
47
-
127
+
48
128
  class Srf extends EventEmitter {
49
129
  constructor();
50
130
  constructor(tags: string | string[]);
51
131
  connect(config?: SrfConfig): Promise<void>;
52
132
  disconnect(): void;
53
- register(options: any): void;
54
- invite(sipUri: string, options: any): void;
55
- bye(request: SrfRequest, options: any): void;
56
- cancel(request: SrfRequest, options: any): void;
57
- ack(request: SrfRequest, options: any): void;
58
- info(request: SrfRequest, options: any): void;
59
- message(request: SrfRequest, options: any): void;
60
- notify(request: SrfRequest, options: any): void;
61
- options(request: SrfRequest, options: any): void;
62
- prack(request: SrfRequest, options: any): void;
63
- publish(request: SrfRequest, options: any): void;
64
- refer(request: SrfRequest, target: string, options: any): void;
65
- subscribe(request: SrfRequest, target: string, options: any): void;
66
- update(request: SrfRequest, options: any): void;
133
+ use(callback: (req: SrfRequest, res: SrfResponse, next: Function) => void): void;
134
+ use(messageType: string, callback: (req: SrfRequest, res: SrfResponse, next: Function) => void): void;
135
+ invite(callback: (req: SrfRequest, res: SrfResponse) => void): void;
136
+ request(uri: string, opts, method, [body], callback?: (err, requestSent: SrfRequest) => void);
137
+ proxyRequest(req: SrfRequest, destination: string | string[], [opts], callback?: (err, results) => {}): void;
138
+ createUAS(req: SrfRequest, res: SrfResponse, opts: CreateUASOptions, callback?: (err, dialog: Dialog) => void): Promise<Dialog>;
139
+ createUAC(uri: string | CreateUACOptions, opts?: CreateUACOptions, progressCallbacks?: { cbRequest?: (req: SrfRequest) => void; cbProvisional?: (provisionalRes: SrfResponse) => void; }, callback?: (err, dialog: Dialog) => void): Promise<Dialog>;
140
+ createB2BUA(req: SrfRequest, res: SrfResponse, uri: string, opts: CreateB2BUAOptions, progressCallbacks?: { cbRequest?: (req: SrfRequest) => void; cbProvisional?: (provisionalRes: Response) => void; cbFinalizedUac?: (uac: Dialog) => void; }, callback?: (err, dialog: Dialog) => {}): Promise<{ uas: Dialog; uac: Dialog }>;
67
141
  on(event: 'connect', listener: (err: Error, hostPort: string) => void): this;
68
142
  on(event: 'error', listener: (err: Error) => void): this;
69
143
  on(event: 'disconnect', listener: () => void): this;
@@ -76,7 +150,6 @@ declare module 'drachtio-srf' {
76
150
  locals: {[name: string]: any};
77
151
  socket: Socket;
78
152
  }
79
-
153
+
80
154
  export default Srf
81
- }
82
-
155
+ }
package/lib/request.js CHANGED
@@ -273,6 +273,7 @@ module.exports = Request ;
273
273
  delegate(Request.prototype, 'msg')
274
274
  .method('get')
275
275
  .method('has')
276
+ .method('getHeaderName')
276
277
  .method('getParsedHeader')
277
278
  .method('set')
278
279
  .access('method')
package/lib/response.js CHANGED
@@ -191,6 +191,7 @@ module.exports = Response ;
191
191
  delegate(Response.prototype, 'msg')
192
192
  .method('get')
193
193
  .method('has')
194
+ .method('getHeaderName')
194
195
  .method('getParsedHeader')
195
196
  .method('set')
196
197
  .access('headers')
@@ -53,6 +53,11 @@ class SipMessage {
53
53
  return ('INVITE' === this.method || 'SUBSCRIBE' === this.method) && !this.get('to').tag ;
54
54
  }
55
55
 
56
+ getHeaderName(hdr) {
57
+ const hdrLowerCase = hdr.toLowerCase();
58
+ return Object.keys(this.headers).find((h) => h.toLowerCase() === hdrLowerCase);
59
+ }
60
+
56
61
  set(hdr, value) {
57
62
  const hdrs = {} ;
58
63
  if (typeof hdr === 'string') hdrs[hdr] = value ;
@@ -76,17 +81,18 @@ class SipMessage {
76
81
  }
77
82
 
78
83
  get(hdr) {
79
- if (this.has(hdr)) { return this.headers[parser.getHeaderName(hdr)] ; }
84
+ const headerName = this.getHeaderName(parser.getHeaderName(hdr));
85
+ if (headerName) {
86
+ return this.headers[headerName];
87
+ }
80
88
  }
81
89
 
82
90
  has(hdr) {
83
- const name = parser.getHeaderName(hdr) ;
84
- return name in this.headers ;
91
+ return !!this.getHeaderName(hdr);
85
92
  }
86
93
 
87
94
  getParsedHeader(hdr) {
88
- const name = parser.getHeaderName(hdr) ;
89
- const v = this.headers[name];
95
+ const v = this.get(hdr);
90
96
 
91
97
  if (!v) {
92
98
  throw new Error('header not available');
package/lib/srf.js CHANGED
@@ -814,8 +814,14 @@ class Srf extends Emitter {
814
814
  const reqHeaders = req.headers;
815
815
  possiblyRemoveHeaders(proxyRequestHeaders.slice(1), reqHeaders);
816
816
  copyAllHeaders(reqHeaders, opts.headers);
817
+ } else {
818
+ proxyRequestHeaders.forEach((hdr) => {
819
+ const headerName = req.getHeaderName(hdr);
820
+ if (headerName) {
821
+ opts.headers[headerName] = req.get(hdr);
822
+ }
823
+ });
817
824
  }
818
- else proxyRequestHeaders.forEach((hdr) => { if (req.has(hdr)) opts.headers[hdr] = req.get(hdr);}) ;
819
825
 
820
826
  if (!(opts.headers.from || opts.headers.From) && !opts.callingNumber) { opts.callingNumber = req.callingNumber; }
821
827
  if (!(opts.headers.from || opts.headers.From) && !opts.callingName) { opts.callingName = req.callingName; }
@@ -912,9 +918,10 @@ class Srf extends Emitter {
912
918
  else {
913
919
  proxyResponseHeaders.forEach((hdr) => {
914
920
  debug(`copyUACHeadersToUAS: hdr ${hdr}`);
915
- if (uacRes.has(hdr)) {
921
+ const headerName = uacRes.getHeaderName(hdr);
922
+ if (headerName) {
916
923
  debug(`copyUACHeadersToUAS: adding ${hdr}: uacRes.get(hdr)`);
917
- headers[hdr] = uacRes.get(hdr) ;
924
+ headers[headerName] = uacRes.get(hdr);
918
925
  }
919
926
  });
920
927
  }
@@ -1221,8 +1228,11 @@ class Srf extends Emitter {
1221
1228
  _b2bRequestWithinDialog(dlg, req, res, proxyRequestHeaders, proxyResponseHeaders, callback) {
1222
1229
  callback = callback || noop ;
1223
1230
  let headers = {} ;
1224
- proxyRequestHeaders.forEach((h) => {
1225
- if (req.has(h)) { headers[h] = req.get(h); }
1231
+ proxyRequestHeaders.forEach((hdr) => {
1232
+ const headerName = req.getHeaderName(hdr);
1233
+ if (headerName) {
1234
+ headers[headerName] = req.get(hdr);
1235
+ }
1226
1236
  }) ;
1227
1237
  dlg.request({
1228
1238
  method: req.method,
@@ -1230,8 +1240,13 @@ class Srf extends Emitter {
1230
1240
  body: req.body
1231
1241
  }, (err, response) => {
1232
1242
  headers = {} ;
1233
- proxyResponseHeaders.forEach((h) => {
1234
- if (!!response && response.has(h)) { headers[h] = response.get(h); }
1243
+ proxyResponseHeaders.forEach((hdr) => {
1244
+ if (!!response && response.has(hdr)) {
1245
+ const headerName = response.getHeaderName(hdr);
1246
+ if (headerName) {
1247
+ headers[headerName] = response.get(hdr);
1248
+ }
1249
+ }
1235
1250
  }) ;
1236
1251
 
1237
1252
  if (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drachtio-srf",
3
- "version": "4.5.31",
3
+ "version": "4.5.32",
4
4
  "description": "drachtio signaling resource framework",
5
5
  "main": "lib/srf.js",
6
6
  "types": "lib/@types/index.d.ts",
@@ -40,6 +40,16 @@ describe('Parser', function () {
40
40
  msg.set('From', '<sip:daveh@localhost>;tag=1234');
41
41
  msg.get('from').should.eql('<sip:daveh@localhost>;tag=1234');
42
42
  });
43
+ it('getting a private header should be case insensitive', function () {
44
+ var msg = new SipMessage();
45
+ msg.set('P-Called-Party-ID', '"Dave" <sip:daveh@localhost>');
46
+ msg.get('p-called-party-id').should.eql('"Dave" <sip:daveh@localhost>');
47
+ });
48
+ it('getting a custom header should be case insensitive', function () {
49
+ var msg = new SipMessage();
50
+ msg.set('X-Foo', 'bar');
51
+ msg.get('x-foo').should.eql('bar');
52
+ });
43
53
  it('should not parse a header when not available', function () {
44
54
  var msg = new SipMessage();
45
55
  should.throws(msg.getParsedHeader.bind(msg, 'contact'));