From d02ee1559287a82c67e6befbcc19210da65bf701 Mon Sep 17 00:00:00 2001 From: "H.Yavari" Date: Mon, 11 Sep 2023 21:26:34 -0700 Subject: [PATCH 1/5] add grammer for precondition a attributes --- lib/grammar.js | 318 ++++++++++++++++++++++++++++--------------------- 1 file changed, 185 insertions(+), 133 deletions(-) diff --git a/lib/grammar.js b/lib/grammar.js index d8178e8..839ff90 100644 --- a/lib/grammar.js +++ b/lib/grammar.js @@ -1,16 +1,27 @@ -var grammar = module.exports = { - v: [{ - name: 'version', - reg: /^(\d*)$/ - }], - o: [{ - // o=- 20518 0 IN IP4 203.0.113.1 - // NB: sessionId will be a String in most cases because it is huge - name: 'origin', - reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, - names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], - format: '%s %s %d %s IP%d %s' - }], +var grammar = (module.exports = { + v: [ + { + name: 'version', + reg: /^(\d*)$/, + }, + ], + o: [ + { + // o=- 20518 0 IN IP4 203.0.113.1 + // NB: sessionId will be a String in most cases because it is huge + name: 'origin', + reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, + names: [ + 'username', + 'sessionId', + 'sessionVersion', + 'netType', + 'ipVer', + 'address', + ], + format: '%s %s %d %s IP%d %s', + }, + ], // default parsing of these only (though some of these feel outdated) s: [{ name: 'name' }], i: [{ name: 'description' }], @@ -18,37 +29,45 @@ var grammar = module.exports = { e: [{ name: 'email' }], p: [{ name: 'phone' }], z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly... - r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly + r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly // k: [{}], // outdated thing ignored - t: [{ - // t=0 0 - name: 'timing', - reg: /^(\d*) (\d*)/, - names: ['start', 'stop'], - format: '%d %d' - }], - c: [{ - // c=IN IP4 10.47.197.26 - name: 'connection', - reg: /^IN IP(\d) (\S*)/, - names: ['version', 'ip'], - format: 'IN IP%d %s' - }], - b: [{ - // b=AS:4000 - push: 'bandwidth', - reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, - names: ['type', 'limit'], - format: '%s:%s' - }], - m: [{ - // m=video 51744 RTP/AVP 126 97 98 34 31 - // NB: special - pushes to session - // TODO: rtp/fmtp should be filtered by the payloads found here? - reg: /^(\w*) (\d*) ([\w/]*)(?: (.*))?/, - names: ['type', 'port', 'protocol', 'payloads'], - format: '%s %d %s %s' - }], + t: [ + { + // t=0 0 + name: 'timing', + reg: /^(\d*) (\d*)/, + names: ['start', 'stop'], + format: '%d %d', + }, + ], + c: [ + { + // c=IN IP4 10.47.197.26 + name: 'connection', + reg: /^IN IP(\d) (\S*)/, + names: ['version', 'ip'], + format: 'IN IP%d %s', + }, + ], + b: [ + { + // b=AS:4000 + push: 'bandwidth', + reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, + names: ['type', 'limit'], + format: '%s:%s', + }, + ], + m: [ + { + // m=video 51744 RTP/AVP 126 97 98 34 31 + // NB: special - pushes to session + // TODO: rtp/fmtp should be filtered by the payloads found here? + reg: /^(\w*) (\d*) ([\w/]*)(?: (.*))?/, + names: ['type', 'port', 'protocol', 'payloads'], + format: '%s %d %s %s', + }, + ], a: [ { // a=rtpmap:110 opus/48000/2 @@ -56,12 +75,12 @@ var grammar = module.exports = { reg: /^rtpmap:(\d*) ([\w\-.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, names: ['payload', 'codec', 'rate', 'encoding'], format: function (o) { - return (o.encoding) + return o.encoding ? 'rtpmap:%d %s/%s/%s' : o.rate ? 'rtpmap:%d %s/%s' : 'rtpmap:%d %s'; - } + }, }, { // a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 @@ -69,13 +88,13 @@ var grammar = module.exports = { push: 'fmtp', reg: /^fmtp:(\d*) ([\S| ]*)/, names: ['payload', 'config'], - format: 'fmtp:%d %s' + format: 'fmtp:%d %s', }, { // a=control:streamid=0 name: 'control', reg: /^control:(.*)/, - format: 'control:%s' + format: 'control:%s', }, { // a=rtcp:65179 IN IP4 193.84.77.194 @@ -83,17 +102,15 @@ var grammar = module.exports = { reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, names: ['port', 'netType', 'ipVer', 'address'], format: function (o) { - return (o.address != null) - ? 'rtcp:%d %s IP%d %s' - : 'rtcp:%d'; - } + return o.address != null ? 'rtcp:%d %s IP%d %s' : 'rtcp:%d'; + }, }, { // a=rtcp-fb:98 trr-int 100 push: 'rtcpFbTrrInt', reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, names: ['payload', 'value'], - format: 'rtcp-fb:%s trr-int %d' + format: 'rtcp-fb:%s trr-int %d', }, { // a=rtcp-fb:98 nack rpsi @@ -101,10 +118,8 @@ var grammar = module.exports = { reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, names: ['payload', 'type', 'subtype'], format: function (o) { - return (o.subtype != null) - ? 'rtcp-fb:%s %s %s' - : 'rtcp-fb:%s %s'; - } + return o.subtype != null ? 'rtcp-fb:%s %s %s' : 'rtcp-fb:%s %s'; + }, }, { // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset @@ -121,12 +136,12 @@ var grammar = module.exports = { ' %s' + (o.config ? ' %s' : '') ); - } + }, }, { // a=extmap-allow-mixed name: 'extmapAllowMixed', - reg: /^(extmap-allow-mixed)/ + reg: /^(extmap-allow-mixed)/, }, { // a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 @@ -134,75 +149,75 @@ var grammar = module.exports = { reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, names: ['id', 'suite', 'config', 'sessionConfig'], format: function (o) { - return (o.sessionConfig != null) + return o.sessionConfig != null ? 'crypto:%d %s %s %s' : 'crypto:%d %s %s'; - } + }, }, { // a=setup:actpass name: 'setup', reg: /^setup:(\w*)/, - format: 'setup:%s' + format: 'setup:%s', }, { // a=connection:new name: 'connectionType', reg: /^connection:(new|existing)/, - format: 'connection:%s' + format: 'connection:%s', }, { // a=mid:1 name: 'mid', reg: /^mid:([^\s]*)/, - format: 'mid:%s' + format: 'mid:%s', }, { // a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a name: 'msid', reg: /^msid:(.*)/, - format: 'msid:%s' + format: 'msid:%s', }, { // a=ptime:20 name: 'ptime', reg: /^ptime:(\d*(?:\.\d*)*)/, - format: 'ptime:%d' + format: 'ptime:%d', }, { // a=maxptime:60 name: 'maxptime', reg: /^maxptime:(\d*(?:\.\d*)*)/, - format: 'maxptime:%d' + format: 'maxptime:%d', }, { // a=sendrecv name: 'direction', - reg: /^(sendrecv|recvonly|sendonly|inactive)/ + reg: /^(sendrecv|recvonly|sendonly|inactive)/, }, { // a=ice-lite name: 'icelite', - reg: /^(ice-lite)/ + reg: /^(ice-lite)/, }, { // a=ice-ufrag:F7gI name: 'iceUfrag', reg: /^ice-ufrag:(\S*)/, - format: 'ice-ufrag:%s' + format: 'ice-ufrag:%s', }, { // a=ice-pwd:x9cml/YzichV2+XlhiMu8g name: 'icePwd', reg: /^ice-pwd:(\S*)/, - format: 'ice-pwd:%s' + format: 'ice-pwd:%s', }, { // a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 name: 'fingerprint', reg: /^fingerprint:(\S*) (\S*)/, names: ['type', 'hash'], - format: 'fingerprint:%s %s' + format: 'fingerprint:%s %s', }, { // a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host @@ -210,42 +225,56 @@ var grammar = module.exports = { // a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10 // a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10 // a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10 - push:'candidates', + push: 'candidates', reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?(?: network-id (\d*))?(?: network-cost (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'], + names: [ + 'foundation', + 'component', + 'transport', + 'priority', + 'ip', + 'port', + 'type', + 'raddr', + 'rport', + 'tcptype', + 'generation', + 'network-id', + 'network-cost', + ], format: function (o) { var str = 'candidate:%s %d %s %d %s %d typ %s'; - str += (o.raddr != null) ? ' raddr %s rport %d' : '%v%v'; + str += o.raddr != null ? ' raddr %s rport %d' : '%v%v'; // NB: candidate has three optional chunks, so %void middles one if it's missing - str += (o.tcptype != null) ? ' tcptype %s' : '%v'; + str += o.tcptype != null ? ' tcptype %s' : '%v'; if (o.generation != null) { str += ' generation %d'; } - str += (o['network-id'] != null) ? ' network-id %d' : '%v'; - str += (o['network-cost'] != null) ? ' network-cost %d' : '%v'; + str += o['network-id'] != null ? ' network-id %d' : '%v'; + str += o['network-cost'] != null ? ' network-cost %d' : '%v'; return str; - } + }, }, { // a=end-of-candidates (keep after the candidates line for readability) name: 'endOfCandidates', - reg: /^(end-of-candidates)/ + reg: /^(end-of-candidates)/, }, { // a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... name: 'remoteCandidates', reg: /^remote-candidates:(.*)/, - format: 'remote-candidates:%s' + format: 'remote-candidates:%s', }, { // a=ice-options:google-ice name: 'iceOptions', reg: /^ice-options:(\S*)/, - format: 'ice-options:%s' + format: 'ice-options:%s', }, { // a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 @@ -261,7 +290,7 @@ var grammar = module.exports = { } } return str; - } + }, }, { // a=ssrc-group:FEC 1 2 @@ -270,31 +299,31 @@ var grammar = module.exports = { // token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E reg: /^ssrc-group:([\x21\x23\x24\x25\x26\x27\x2A\x2B\x2D\x2E\w]*) (.*)/, names: ['semantics', 'ssrcs'], - format: 'ssrc-group:%s %s' + format: 'ssrc-group:%s %s', }, { // a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV name: 'msidSemantic', reg: /^msid-semantic:\s?(\w*) (\S*)/, names: ['semantic', 'token'], - format: 'msid-semantic: %s %s' // space after ':' is not accidental + format: 'msid-semantic: %s %s', // space after ':' is not accidental }, { // a=group:BUNDLE audio video push: 'groups', reg: /^group:(\w*) (.*)/, names: ['type', 'mids'], - format: 'group:%s %s' + format: 'group:%s %s', }, { // a=rtcp-mux name: 'rtcpMux', - reg: /^(rtcp-mux)/ + reg: /^(rtcp-mux)/, }, { // a=rtcp-rsize name: 'rtcpRsize', - reg: /^(rtcp-rsize)/ + reg: /^(rtcp-rsize)/, }, { // a=sctpmap:5000 webrtc-datachannel 1024 @@ -302,16 +331,14 @@ var grammar = module.exports = { reg: /^sctpmap:([\w_/]*) (\S*)(?: (\S*))?/, names: ['sctpmapNumber', 'app', 'maxMessageSize'], format: function (o) { - return (o.maxMessageSize != null) - ? 'sctpmap:%s %s %s' - : 'sctpmap:%s %s'; - } + return o.maxMessageSize != null ? 'sctpmap:%s %s %s' : 'sctpmap:%s %s'; + }, }, { // a=x-google-flag:conference name: 'xGoogleFlag', reg: /^x-google-flag:([^\s]*)/, - format: 'x-google-flag:%s' + format: 'x-google-flag:%s', }, { // a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0 @@ -319,8 +346,8 @@ var grammar = module.exports = { reg: /^rid:([\d\w]+) (\w+)(?: ([\S| ]*))?/, names: ['id', 'direction', 'params'], format: function (o) { - return (o.params) ? 'rid:%s %s %s' : 'rid:%s %s'; - } + return o.params ? 'rid:%s %s %s' : 'rid:%s %s'; + }, }, { // a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250] @@ -330,15 +357,15 @@ var grammar = module.exports = { reg: new RegExp( // a=imageattr:97 '^imageattr:(\\d+|\\*)' + - // send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] - '[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' + - // recv [x=330,y=250] - '(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?' + // send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] + '[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' + + // recv [x=330,y=250] + '(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?' ), names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'], format: function (o) { return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : ''); - } + }, }, { // a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8 @@ -347,17 +374,17 @@ var grammar = module.exports = { reg: new RegExp( // a=simulcast: '^simulcast:' + - // send 1,2,3;~4,~5 - '(send|recv) ([a-zA-Z0-9\\-_~;,]+)' + - // space + recv 6;~7,~8 - '(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' + - // end - '$' + // send 1,2,3;~4,~5 + '(send|recv) ([a-zA-Z0-9\\-_~;,]+)' + + // space + recv 6;~7,~8 + '(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' + + // end + '$' ), names: ['dir1', 'list1', 'dir2', 'list2'], format: function (o) { return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : ''); - } + }, }, { // old simulcast draft 03 (implemented by Firefox) @@ -367,118 +394,143 @@ var grammar = module.exports = { name: 'simulcast_03', reg: /^simulcast:[\s\t]+([\S+\s\t]+)$/, names: ['value'], - format: 'simulcast: %s' + format: 'simulcast: %s', }, { // a=framerate:25 // a=framerate:29.97 name: 'framerate', reg: /^framerate:(\d+(?:$|\.\d+))/, - format: 'framerate:%s' + format: 'framerate:%s', }, { // RFC4570 // a=source-filter: incl IN IP4 239.5.2.31 10.1.15.5 name: 'sourceFilter', reg: /^source-filter: *(excl|incl) (\S*) (IP4|IP6|\*) (\S*) (.*)/, - names: ['filterMode', 'netType', 'addressTypes', 'destAddress', 'srcList'], - format: 'source-filter: %s %s %s %s %s' + names: [ + 'filterMode', + 'netType', + 'addressTypes', + 'destAddress', + 'srcList', + ], + format: 'source-filter: %s %s %s %s %s', }, { // a=bundle-only name: 'bundleOnly', - reg: /^(bundle-only)/ + reg: /^(bundle-only)/, }, { // a=label:1 name: 'label', reg: /^label:(.+)/, - format: 'label:%s' + format: 'label:%s', }, { // RFC version 26 for SCTP over DTLS // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-5 name: 'sctpPort', reg: /^sctp-port:(\d+)$/, - format: 'sctp-port:%s' + format: 'sctp-port:%s', }, { // RFC version 26 for SCTP over DTLS // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6 name: 'maxMessageSize', reg: /^max-message-size:(\d+)$/, - format: 'max-message-size:%s' + format: 'max-message-size:%s', }, { // RFC7273 // a=ts-refclk:ptp=IEEE1588-2008:39-A7-94-FF-FE-07-CB-D0:37 - push:'tsRefClocks', + push: 'tsRefClocks', reg: /^ts-refclk:([^\s=]*)(?:=(\S*))?/, names: ['clksrc', 'clksrcExt'], format: function (o) { return 'ts-refclk:%s' + (o.clksrcExt != null ? '=%s' : ''); - } + }, }, { // RFC7273 // a=mediaclk:direct=963214424 - name:'mediaClk', + name: 'mediaClk', reg: /^mediaclk:(?:id=(\S*))? *([^\s=]*)(?:=(\S*))?(?: *rate=(\d+)\/(\d+))?/, - names: ['id', 'mediaClockName', 'mediaClockValue', 'rateNumerator', 'rateDenominator'], + names: [ + 'id', + 'mediaClockName', + 'mediaClockValue', + 'rateNumerator', + 'rateDenominator', + ], format: function (o) { var str = 'mediaclk:'; - str += (o.id != null ? 'id=%s %s' : '%v%s'); - str += (o.mediaClockValue != null ? '=%s' : ''); - str += (o.rateNumerator != null ? ' rate=%s' : ''); - str += (o.rateDenominator != null ? '/%s' : ''); + str += o.id != null ? 'id=%s %s' : '%v%s'; + str += o.mediaClockValue != null ? '=%s' : ''; + str += o.rateNumerator != null ? ' rate=%s' : ''; + str += o.rateDenominator != null ? '/%s' : ''; return str; - } + }, }, { // a=keywds:keywords name: 'keywords', reg: /^keywds:(.+)$/, - format: 'keywds:%s' + format: 'keywds:%s', }, { // a=content:main name: 'content', reg: /^content:(.+)/, - format: 'content:%s' + format: 'content:%s', }, // BFCP https://tools.ietf.org/html/rfc4583 { // a=floorctrl:c-s name: 'bfcpFloorCtrl', reg: /^floorctrl:(c-only|s-only|c-s)/, - format: 'floorctrl:%s' + format: 'floorctrl:%s', }, { // a=confid:1 name: 'bfcpConfId', reg: /^confid:(\d+)/, - format: 'confid:%s' + format: 'confid:%s', }, { // a=userid:1 name: 'bfcpUserId', reg: /^userid:(\d+)/, - format: 'userid:%s' + format: 'userid:%s', }, { // a=floorid:1 name: 'bfcpFloorId', reg: /^floorid:(.+) (?:m-stream|mstrm):(.+)/, names: ['id', 'mStream'], - format: 'floorid:%s mstrm:%s' + format: 'floorid:%s mstrm:%s', + }, + { + // RFC 3312 precondition + push: 'precondition', + reg: /^(curr|des|conf):(qos|\S*)(?: (mandatory|optional|none|failure|unknown))? (e2e|local|remote) (none|sendrecv|send|recv)/, + names: ['state', 'type', 'strength', 'status', 'direction'], + format: function (o) { + var str = '%s:%s '; + str += o.strength != null ? '%s ' : '%v'; + str += o.status != null ? '%s ' : ''; + str += o.direction != null ? '%s ' : ''; + return str; + }, }, { // any a= that we don't understand is kept verbatim on media.invalid push: 'invalid', - names: ['value'] - } - ] -}; + names: ['value'], + }, + ], +}); // set sensible defaults to avoid polluting the grammar with boring details Object.keys(grammar).forEach(function (key) { From f5a883af9a4a7dd31695df3df4b437ff8d3cfe96 Mon Sep 17 00:00:00 2001 From: "H.Yavari" Date: Tue, 12 Sep 2023 07:21:23 -0700 Subject: [PATCH 2/5] revert grammar formating --- lib/grammar.js | 307 +++++++++++++++++++++---------------------------- 1 file changed, 134 insertions(+), 173 deletions(-) diff --git a/lib/grammar.js b/lib/grammar.js index 839ff90..ebd7243 100644 --- a/lib/grammar.js +++ b/lib/grammar.js @@ -1,27 +1,16 @@ -var grammar = (module.exports = { - v: [ - { - name: 'version', - reg: /^(\d*)$/, - }, - ], - o: [ - { - // o=- 20518 0 IN IP4 203.0.113.1 - // NB: sessionId will be a String in most cases because it is huge - name: 'origin', - reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, - names: [ - 'username', - 'sessionId', - 'sessionVersion', - 'netType', - 'ipVer', - 'address', - ], - format: '%s %s %d %s IP%d %s', - }, - ], +var grammar = module.exports = { + v: [{ + name: 'version', + reg: /^(\d*)$/ + }], + o: [{ + // o=- 20518 0 IN IP4 203.0.113.1 + // NB: sessionId will be a String in most cases because it is huge + name: 'origin', + reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, + names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], + format: '%s %s %d %s IP%d %s' + }], // default parsing of these only (though some of these feel outdated) s: [{ name: 'name' }], i: [{ name: 'description' }], @@ -29,45 +18,37 @@ var grammar = (module.exports = { e: [{ name: 'email' }], p: [{ name: 'phone' }], z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly... - r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly + r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly // k: [{}], // outdated thing ignored - t: [ - { - // t=0 0 - name: 'timing', - reg: /^(\d*) (\d*)/, - names: ['start', 'stop'], - format: '%d %d', - }, - ], - c: [ - { - // c=IN IP4 10.47.197.26 - name: 'connection', - reg: /^IN IP(\d) (\S*)/, - names: ['version', 'ip'], - format: 'IN IP%d %s', - }, - ], - b: [ - { - // b=AS:4000 - push: 'bandwidth', - reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, - names: ['type', 'limit'], - format: '%s:%s', - }, - ], - m: [ - { - // m=video 51744 RTP/AVP 126 97 98 34 31 - // NB: special - pushes to session - // TODO: rtp/fmtp should be filtered by the payloads found here? - reg: /^(\w*) (\d*) ([\w/]*)(?: (.*))?/, - names: ['type', 'port', 'protocol', 'payloads'], - format: '%s %d %s %s', - }, - ], + t: [{ + // t=0 0 + name: 'timing', + reg: /^(\d*) (\d*)/, + names: ['start', 'stop'], + format: '%d %d' + }], + c: [{ + // c=IN IP4 10.47.197.26 + name: 'connection', + reg: /^IN IP(\d) (\S*)/, + names: ['version', 'ip'], + format: 'IN IP%d %s' + }], + b: [{ + // b=AS:4000 + push: 'bandwidth', + reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, + names: ['type', 'limit'], + format: '%s:%s' + }], + m: [{ + // m=video 51744 RTP/AVP 126 97 98 34 31 + // NB: special - pushes to session + // TODO: rtp/fmtp should be filtered by the payloads found here? + reg: /^(\w*) (\d*) ([\w/]*)(?: (.*))?/, + names: ['type', 'port', 'protocol', 'payloads'], + format: '%s %d %s %s' + }], a: [ { // a=rtpmap:110 opus/48000/2 @@ -75,12 +56,12 @@ var grammar = (module.exports = { reg: /^rtpmap:(\d*) ([\w\-.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, names: ['payload', 'codec', 'rate', 'encoding'], format: function (o) { - return o.encoding + return (o.encoding) ? 'rtpmap:%d %s/%s/%s' : o.rate ? 'rtpmap:%d %s/%s' : 'rtpmap:%d %s'; - }, + } }, { // a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 @@ -88,13 +69,13 @@ var grammar = (module.exports = { push: 'fmtp', reg: /^fmtp:(\d*) ([\S| ]*)/, names: ['payload', 'config'], - format: 'fmtp:%d %s', + format: 'fmtp:%d %s' }, { // a=control:streamid=0 name: 'control', reg: /^control:(.*)/, - format: 'control:%s', + format: 'control:%s' }, { // a=rtcp:65179 IN IP4 193.84.77.194 @@ -102,15 +83,17 @@ var grammar = (module.exports = { reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, names: ['port', 'netType', 'ipVer', 'address'], format: function (o) { - return o.address != null ? 'rtcp:%d %s IP%d %s' : 'rtcp:%d'; - }, + return (o.address != null) + ? 'rtcp:%d %s IP%d %s' + : 'rtcp:%d'; + } }, { // a=rtcp-fb:98 trr-int 100 push: 'rtcpFbTrrInt', reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, names: ['payload', 'value'], - format: 'rtcp-fb:%s trr-int %d', + format: 'rtcp-fb:%s trr-int %d' }, { // a=rtcp-fb:98 nack rpsi @@ -118,8 +101,10 @@ var grammar = (module.exports = { reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, names: ['payload', 'type', 'subtype'], format: function (o) { - return o.subtype != null ? 'rtcp-fb:%s %s %s' : 'rtcp-fb:%s %s'; - }, + return (o.subtype != null) + ? 'rtcp-fb:%s %s %s' + : 'rtcp-fb:%s %s'; + } }, { // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset @@ -136,12 +121,12 @@ var grammar = (module.exports = { ' %s' + (o.config ? ' %s' : '') ); - }, + } }, { // a=extmap-allow-mixed name: 'extmapAllowMixed', - reg: /^(extmap-allow-mixed)/, + reg: /^(extmap-allow-mixed)/ }, { // a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 @@ -149,75 +134,75 @@ var grammar = (module.exports = { reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, names: ['id', 'suite', 'config', 'sessionConfig'], format: function (o) { - return o.sessionConfig != null + return (o.sessionConfig != null) ? 'crypto:%d %s %s %s' : 'crypto:%d %s %s'; - }, + } }, { // a=setup:actpass name: 'setup', reg: /^setup:(\w*)/, - format: 'setup:%s', + format: 'setup:%s' }, { // a=connection:new name: 'connectionType', reg: /^connection:(new|existing)/, - format: 'connection:%s', + format: 'connection:%s' }, { // a=mid:1 name: 'mid', reg: /^mid:([^\s]*)/, - format: 'mid:%s', + format: 'mid:%s' }, { // a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a name: 'msid', reg: /^msid:(.*)/, - format: 'msid:%s', + format: 'msid:%s' }, { // a=ptime:20 name: 'ptime', reg: /^ptime:(\d*(?:\.\d*)*)/, - format: 'ptime:%d', + format: 'ptime:%d' }, { // a=maxptime:60 name: 'maxptime', reg: /^maxptime:(\d*(?:\.\d*)*)/, - format: 'maxptime:%d', + format: 'maxptime:%d' }, { // a=sendrecv name: 'direction', - reg: /^(sendrecv|recvonly|sendonly|inactive)/, + reg: /^(sendrecv|recvonly|sendonly|inactive)/ }, { // a=ice-lite name: 'icelite', - reg: /^(ice-lite)/, + reg: /^(ice-lite)/ }, { // a=ice-ufrag:F7gI name: 'iceUfrag', reg: /^ice-ufrag:(\S*)/, - format: 'ice-ufrag:%s', + format: 'ice-ufrag:%s' }, { // a=ice-pwd:x9cml/YzichV2+XlhiMu8g name: 'icePwd', reg: /^ice-pwd:(\S*)/, - format: 'ice-pwd:%s', + format: 'ice-pwd:%s' }, { // a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 name: 'fingerprint', reg: /^fingerprint:(\S*) (\S*)/, names: ['type', 'hash'], - format: 'fingerprint:%s %s', + format: 'fingerprint:%s %s' }, { // a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host @@ -225,56 +210,42 @@ var grammar = (module.exports = { // a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10 // a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10 // a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10 - push: 'candidates', + push:'candidates', reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?(?: network-id (\d*))?(?: network-cost (\d*))?/, - names: [ - 'foundation', - 'component', - 'transport', - 'priority', - 'ip', - 'port', - 'type', - 'raddr', - 'rport', - 'tcptype', - 'generation', - 'network-id', - 'network-cost', - ], + names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'], format: function (o) { var str = 'candidate:%s %d %s %d %s %d typ %s'; - str += o.raddr != null ? ' raddr %s rport %d' : '%v%v'; + str += (o.raddr != null) ? ' raddr %s rport %d' : '%v%v'; // NB: candidate has three optional chunks, so %void middles one if it's missing - str += o.tcptype != null ? ' tcptype %s' : '%v'; + str += (o.tcptype != null) ? ' tcptype %s' : '%v'; if (o.generation != null) { str += ' generation %d'; } - str += o['network-id'] != null ? ' network-id %d' : '%v'; - str += o['network-cost'] != null ? ' network-cost %d' : '%v'; + str += (o['network-id'] != null) ? ' network-id %d' : '%v'; + str += (o['network-cost'] != null) ? ' network-cost %d' : '%v'; return str; - }, + } }, { // a=end-of-candidates (keep after the candidates line for readability) name: 'endOfCandidates', - reg: /^(end-of-candidates)/, + reg: /^(end-of-candidates)/ }, { // a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... name: 'remoteCandidates', reg: /^remote-candidates:(.*)/, - format: 'remote-candidates:%s', + format: 'remote-candidates:%s' }, { // a=ice-options:google-ice name: 'iceOptions', reg: /^ice-options:(\S*)/, - format: 'ice-options:%s', + format: 'ice-options:%s' }, { // a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 @@ -290,7 +261,7 @@ var grammar = (module.exports = { } } return str; - }, + } }, { // a=ssrc-group:FEC 1 2 @@ -299,31 +270,31 @@ var grammar = (module.exports = { // token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E reg: /^ssrc-group:([\x21\x23\x24\x25\x26\x27\x2A\x2B\x2D\x2E\w]*) (.*)/, names: ['semantics', 'ssrcs'], - format: 'ssrc-group:%s %s', + format: 'ssrc-group:%s %s' }, { // a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV name: 'msidSemantic', reg: /^msid-semantic:\s?(\w*) (\S*)/, names: ['semantic', 'token'], - format: 'msid-semantic: %s %s', // space after ':' is not accidental + format: 'msid-semantic: %s %s' // space after ':' is not accidental }, { // a=group:BUNDLE audio video push: 'groups', reg: /^group:(\w*) (.*)/, names: ['type', 'mids'], - format: 'group:%s %s', + format: 'group:%s %s' }, { // a=rtcp-mux name: 'rtcpMux', - reg: /^(rtcp-mux)/, + reg: /^(rtcp-mux)/ }, { // a=rtcp-rsize name: 'rtcpRsize', - reg: /^(rtcp-rsize)/, + reg: /^(rtcp-rsize)/ }, { // a=sctpmap:5000 webrtc-datachannel 1024 @@ -331,14 +302,16 @@ var grammar = (module.exports = { reg: /^sctpmap:([\w_/]*) (\S*)(?: (\S*))?/, names: ['sctpmapNumber', 'app', 'maxMessageSize'], format: function (o) { - return o.maxMessageSize != null ? 'sctpmap:%s %s %s' : 'sctpmap:%s %s'; - }, + return (o.maxMessageSize != null) + ? 'sctpmap:%s %s %s' + : 'sctpmap:%s %s'; + } }, { // a=x-google-flag:conference name: 'xGoogleFlag', reg: /^x-google-flag:([^\s]*)/, - format: 'x-google-flag:%s', + format: 'x-google-flag:%s' }, { // a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0 @@ -346,8 +319,8 @@ var grammar = (module.exports = { reg: /^rid:([\d\w]+) (\w+)(?: ([\S| ]*))?/, names: ['id', 'direction', 'params'], format: function (o) { - return o.params ? 'rid:%s %s %s' : 'rid:%s %s'; - }, + return (o.params) ? 'rid:%s %s %s' : 'rid:%s %s'; + } }, { // a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250] @@ -357,15 +330,15 @@ var grammar = (module.exports = { reg: new RegExp( // a=imageattr:97 '^imageattr:(\\d+|\\*)' + - // send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] - '[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' + - // recv [x=330,y=250] - '(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?' + // send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] + '[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' + + // recv [x=330,y=250] + '(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?' ), names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'], format: function (o) { return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : ''); - }, + } }, { // a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8 @@ -374,17 +347,17 @@ var grammar = (module.exports = { reg: new RegExp( // a=simulcast: '^simulcast:' + - // send 1,2,3;~4,~5 - '(send|recv) ([a-zA-Z0-9\\-_~;,]+)' + - // space + recv 6;~7,~8 - '(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' + - // end - '$' + // send 1,2,3;~4,~5 + '(send|recv) ([a-zA-Z0-9\\-_~;,]+)' + + // space + recv 6;~7,~8 + '(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' + + // end + '$' ), names: ['dir1', 'list1', 'dir2', 'list2'], format: function (o) { return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : ''); - }, + } }, { // old simulcast draft 03 (implemented by Firefox) @@ -394,122 +367,110 @@ var grammar = (module.exports = { name: 'simulcast_03', reg: /^simulcast:[\s\t]+([\S+\s\t]+)$/, names: ['value'], - format: 'simulcast: %s', + format: 'simulcast: %s' }, { // a=framerate:25 // a=framerate:29.97 name: 'framerate', reg: /^framerate:(\d+(?:$|\.\d+))/, - format: 'framerate:%s', + format: 'framerate:%s' }, { // RFC4570 // a=source-filter: incl IN IP4 239.5.2.31 10.1.15.5 name: 'sourceFilter', reg: /^source-filter: *(excl|incl) (\S*) (IP4|IP6|\*) (\S*) (.*)/, - names: [ - 'filterMode', - 'netType', - 'addressTypes', - 'destAddress', - 'srcList', - ], - format: 'source-filter: %s %s %s %s %s', + names: ['filterMode', 'netType', 'addressTypes', 'destAddress', 'srcList'], + format: 'source-filter: %s %s %s %s %s' }, { // a=bundle-only name: 'bundleOnly', - reg: /^(bundle-only)/, + reg: /^(bundle-only)/ }, { // a=label:1 name: 'label', reg: /^label:(.+)/, - format: 'label:%s', + format: 'label:%s' }, { // RFC version 26 for SCTP over DTLS // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-5 name: 'sctpPort', reg: /^sctp-port:(\d+)$/, - format: 'sctp-port:%s', + format: 'sctp-port:%s' }, { // RFC version 26 for SCTP over DTLS // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6 name: 'maxMessageSize', reg: /^max-message-size:(\d+)$/, - format: 'max-message-size:%s', + format: 'max-message-size:%s' }, { // RFC7273 // a=ts-refclk:ptp=IEEE1588-2008:39-A7-94-FF-FE-07-CB-D0:37 - push: 'tsRefClocks', + push:'tsRefClocks', reg: /^ts-refclk:([^\s=]*)(?:=(\S*))?/, names: ['clksrc', 'clksrcExt'], format: function (o) { return 'ts-refclk:%s' + (o.clksrcExt != null ? '=%s' : ''); - }, + } }, { // RFC7273 // a=mediaclk:direct=963214424 - name: 'mediaClk', + name:'mediaClk', reg: /^mediaclk:(?:id=(\S*))? *([^\s=]*)(?:=(\S*))?(?: *rate=(\d+)\/(\d+))?/, - names: [ - 'id', - 'mediaClockName', - 'mediaClockValue', - 'rateNumerator', - 'rateDenominator', - ], + names: ['id', 'mediaClockName', 'mediaClockValue', 'rateNumerator', 'rateDenominator'], format: function (o) { var str = 'mediaclk:'; - str += o.id != null ? 'id=%s %s' : '%v%s'; - str += o.mediaClockValue != null ? '=%s' : ''; - str += o.rateNumerator != null ? ' rate=%s' : ''; - str += o.rateDenominator != null ? '/%s' : ''; + str += (o.id != null ? 'id=%s %s' : '%v%s'); + str += (o.mediaClockValue != null ? '=%s' : ''); + str += (o.rateNumerator != null ? ' rate=%s' : ''); + str += (o.rateDenominator != null ? '/%s' : ''); return str; - }, + } }, { // a=keywds:keywords name: 'keywords', reg: /^keywds:(.+)$/, - format: 'keywds:%s', + format: 'keywds:%s' }, { // a=content:main name: 'content', reg: /^content:(.+)/, - format: 'content:%s', + format: 'content:%s' }, // BFCP https://tools.ietf.org/html/rfc4583 { // a=floorctrl:c-s name: 'bfcpFloorCtrl', reg: /^floorctrl:(c-only|s-only|c-s)/, - format: 'floorctrl:%s', + format: 'floorctrl:%s' }, { // a=confid:1 name: 'bfcpConfId', reg: /^confid:(\d+)/, - format: 'confid:%s', + format: 'confid:%s' }, { // a=userid:1 name: 'bfcpUserId', reg: /^userid:(\d+)/, - format: 'userid:%s', + format: 'userid:%s' }, { // a=floorid:1 name: 'bfcpFloorId', reg: /^floorid:(.+) (?:m-stream|mstrm):(.+)/, names: ['id', 'mStream'], - format: 'floorid:%s mstrm:%s', + format: 'floorid:%s mstrm:%s' }, { // RFC 3312 precondition @@ -527,10 +488,10 @@ var grammar = (module.exports = { { // any a= that we don't understand is kept verbatim on media.invalid push: 'invalid', - names: ['value'], - }, - ], -}); + names: ['value'] + } + ] +}; // set sensible defaults to avoid polluting the grammar with boring details Object.keys(grammar).forEach(function (key) { @@ -543,4 +504,4 @@ Object.keys(grammar).forEach(function (key) { obj.format = '%s'; } }); -}); +}); \ No newline at end of file From e1bb4411c2d20abc0c518148052de28198d91db9 Mon Sep 17 00:00:00 2001 From: hyavari Date: Tue, 12 Sep 2023 08:24:38 -0700 Subject: [PATCH 3/5] adding test for precondition grammar --- test/compose.test.js | 3 ++- test/coverage.test.js | 3 ++- test/parse.test.js | 13 +++++++++++++ test/precondition.sdp | 27 +++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 test/precondition.sdp diff --git a/test/compose.test.js b/test/compose.test.js index f35ebcf..2d99a19 100644 --- a/test/compose.test.js +++ b/test/compose.test.js @@ -48,7 +48,8 @@ var sdps = [ 'mediaclk-rtp.sdp', 'ts-refclk-media.sdp', 'ts-refclk-sess.sdp', - 'rtcp-fb.sdp' + 'rtcp-fb.sdp', + `precondition.sdp`, ]; sdps.forEach((name) => { diff --git a/test/coverage.test.js b/test/coverage.test.js index 5eb5f63..9ed6363 100644 --- a/test/coverage.test.js +++ b/test/coverage.test.js @@ -39,7 +39,8 @@ var sdps = [ 'mediaclk-rtp.sdp', 'ts-refclk-media.sdp', 'ts-refclk-sess.sdp', - 'rtcp-fb.sdp' + 'rtcp-fb.sdp', + `precondition.sdp`, ]; sdps.forEach((name) => { diff --git a/test/parse.test.js b/test/parse.test.js index 47e3ee0..84b43a3 100644 --- a/test/parse.test.js +++ b/test/parse.test.js @@ -975,4 +975,17 @@ test('ts-refclk-sess', function *(t) { t.ok(sessTsRefClocks && sessTsRefClocks.length == 1, 'got one TS Ref Clock at Session Level'); t.equal(sessTsRefClocks[0].clksrc, 'ntp', 'NTP Clock Source'); t.equal(sessTsRefClocks[0].clksrcExt, '/traceable/', 'traceable Clock Source'); +}); + +test('precondition', function* (t) { + var sdp = yield fs.readFile(__dirname + '/precondition.sdp', 'utf8'); + + var session = parse(sdp + ''); + t.ok(session, 'got session info'); + t.equal(session.media[0].precondition[0].status, 'local', 'precondition parsed'); + + var rew = write(session); + console.log(rew.indexOf('m=')); + t.ok(rew.indexOf('a=curr:qos') >= 0, 'got qos precondition'); + t.ok(rew.indexOf('a=des:qos') > rew.indexOf('a=curr:qos'), 'precondition curr and then des state'); }); \ No newline at end of file diff --git a/test/precondition.sdp b/test/precondition.sdp new file mode 100644 index 0000000..264b122 --- /dev/null +++ b/test/precondition.sdp @@ -0,0 +1,27 @@ +v=0 +o=KSIC 564321 0 IN IP6 2001:56f:b006:abf7:8d62:bff:7d9c:79f9 +s=SS VoLTE +i=A VoLTE IMS Session +c=IN IP6 2001:55f:b006:abf7:8d62:bff:7d9c:79f9 +t=0 0 +m=audio 30000 RTP/AVP 114 116 118 111 110 +b=AS:50 +b=RS:0 +b=RR:2000 +a=rtpmap:114 EVS/16000/1 +a=fmtp:114 br=16.4; br-send=16.4; br-recv=16.4; bw=WB; bw-send=WB; bw-recv=WB; hf-only=0; max-red=220 +a=rtpmap:116 AMR-WB/16000/1 +a=fmtp:116 mode-set=8; mode-change-capability=2; max-red=220 +a=rtpmap:111 telephone-event/16000 +a=fmtp:111 0-15 +a=rtpmap:118 AMR/8000/1 +a=fmtp:118 mode-set=7; mode-change-capability=2; max-red=220 +a=rtpmap:110 telephone-event/8000 +a=fmtp:110 0-15 +a=curr:qos local none +a=curr:qos remote none +a=des:qos mandatory local sendrecv +a=des:qos none remote sendrecv +a=sendrecv +a=ptime:20 +a=maxptime:240 From 4c47c189073f0242107a46d2b3bc3c7423295940 Mon Sep 17 00:00:00 2001 From: hyavari Date: Tue, 12 Sep 2023 11:04:37 -0700 Subject: [PATCH 4/5] adding grammar for MRCP sdp attributes --- lib/grammar.js | 12 ++++++++++++ test/mrcp.sdp | 21 +++++++++++++++++++++ test/parse.test.js | 15 ++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 test/mrcp.sdp diff --git a/lib/grammar.js b/lib/grammar.js index ebd7243..f5f2bbb 100644 --- a/lib/grammar.js +++ b/lib/grammar.js @@ -485,6 +485,18 @@ var grammar = module.exports = { return str; }, }, + { + // RFC 6787; a=cmid:1 + name: 'cmid', + reg: /^cmid:([^\s]*)/, + format: 'cmid:%s' + }, + { + // RFC 6787; a=cmid:1 + name: "resource", + reg: /^resource:([^\s]*)/, + format: "resource:%s", + }, { // any a= that we don't understand is kept verbatim on media.invalid push: 'invalid', diff --git a/test/mrcp.sdp b/test/mrcp.sdp new file mode 100644 index 0000000..3c6ccf4 --- /dev/null +++ b/test/mrcp.sdp @@ -0,0 +1,21 @@ +v=0 +o=hossein 2890844526 2890844527 IN IP4 192.0.2.12 +s=- +c=IN IP4 192.0.2.12 +t=0 0 +m=application 9 TCP/MRCPv2 1 +a=setup:active +a=connection:existing +a=resource:speechsynth +a=cmid:1 +m=audio 49170 RTP/AVP 0 96 +a=rtpmap:0 pcmu/8000 +a=rtpmap:96 telephone-event/8000 +a=fmtp:96 0-15 +a=sendrecv +a=mid:1 +m=application 9 TCP/MRCPv2 1 +a=setup:active +a=connection:existing +a=resource:speechrecog +a=cmid:1 \ No newline at end of file diff --git a/test/parse.test.js b/test/parse.test.js index 84b43a3..5e7c83b 100644 --- a/test/parse.test.js +++ b/test/parse.test.js @@ -985,7 +985,20 @@ test('precondition', function* (t) { t.equal(session.media[0].precondition[0].status, 'local', 'precondition parsed'); var rew = write(session); - console.log(rew.indexOf('m=')); t.ok(rew.indexOf('a=curr:qos') >= 0, 'got qos precondition'); t.ok(rew.indexOf('a=des:qos') > rew.indexOf('a=curr:qos'), 'precondition curr and then des state'); +}); + + +test('mrcp', function* (t) { + var sdp = yield fs.readFile(__dirname + '/mrcp.sdp', 'utf8'); + + var session = parse(sdp + ''); + t.ok(session, 'got session info'); + t.equal(session.media[0].resource, 'speechsynth', 'MRCP resource parsed'); + t.equal(session.media[0].cmid, 1, 'MRCP cmid parsed'); + + var rew = write(session); + t.ok(rew.indexOf('a=resource:') >= 0, 'got MRCP resource'); + t.ok(rew.indexOf('a=cmid:') >= 0, 'got MRCP cmid'); }); \ No newline at end of file From a9ee71d63141c111a2910cac2a519213dc957e61 Mon Sep 17 00:00:00 2001 From: hyavari Date: Tue, 12 Sep 2023 12:05:54 -0700 Subject: [PATCH 5/5] adding order for MRCP atts --- lib/grammar.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/grammar.js b/lib/grammar.js index f5f2bbb..8b1591b 100644 --- a/lib/grammar.js +++ b/lib/grammar.js @@ -487,15 +487,15 @@ var grammar = module.exports = { }, { // RFC 6787; a=cmid:1 - name: 'cmid', - reg: /^cmid:([^\s]*)/, - format: 'cmid:%s' + name: 'resource', + reg: /^resource:([^\s]*)/, + format: 'resource:%s', }, { // RFC 6787; a=cmid:1 - name: "resource", - reg: /^resource:([^\s]*)/, - format: "resource:%s", + name: 'cmid', + reg: /^cmid:([^\s]*)/, + format: 'cmid:%s' }, { // any a= that we don't understand is kept verbatim on media.invalid