unmarshal.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. package sdp
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/url"
  6. "strconv"
  7. "strings"
  8. )
  9. var (
  10. errSDPInvalidSyntax = errors.New("sdp: invalid syntax")
  11. errSDPInvalidNumericValue = errors.New("sdp: invalid numeric value")
  12. errSDPInvalidValue = errors.New("sdp: invalid value")
  13. errSDPInvalidPortValue = errors.New("sdp: invalid port value")
  14. )
  15. // Unmarshal is the primary function that deserializes the session description
  16. // message and stores it inside of a structured SessionDescription object.
  17. //
  18. // The States Transition Table describes the computation flow between functions
  19. // (namely s1, s2, s3, ...) for a parsing procedure that complies with the
  20. // specifications laid out by the rfc4566#section-5 as well as by JavaScript
  21. // Session Establishment Protocol draft. Links:
  22. // https://tools.ietf.org/html/rfc4566#section-5
  23. // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24
  24. //
  25. // https://tools.ietf.org/html/rfc4566#section-5
  26. // Session description
  27. // v= (protocol version)
  28. // o= (originator and session identifier)
  29. // s= (session name)
  30. // i=* (session information)
  31. // u=* (URI of description)
  32. // e=* (email address)
  33. // p=* (phone number)
  34. // c=* (connection information -- not required if included in
  35. // all media)
  36. // b=* (zero or more bandwidth information lines)
  37. // One or more time descriptions ("t=" and "r=" lines; see below)
  38. // z=* (time zone adjustments)
  39. // k=* (encryption key)
  40. // a=* (zero or more session attribute lines)
  41. // Zero or more media descriptions
  42. //
  43. // Time description
  44. // t= (time the session is active)
  45. // r=* (zero or more repeat times)
  46. //
  47. // Media description, if present
  48. // m= (media name and transport address)
  49. // i=* (media title)
  50. // c=* (connection information -- optional if included at
  51. // session level)
  52. // b=* (zero or more bandwidth information lines)
  53. // k=* (encryption key)
  54. // a=* (zero or more media attribute lines)
  55. //
  56. // In order to generate the following state table and draw subsequent
  57. // deterministic finite-state automota ("DFA") the following regex was used to
  58. // derive the DFA:
  59. // vosi?u?e?p?c?b*(tr*)+z?k?a*(mi?c?b*k?a*)*
  60. // possible place and state to exit:
  61. // ** * * * ** * * * *
  62. // 99 1 1 1 11 1 1 1 1
  63. // 3 1 1 26 5 5 4 4
  64. //
  65. // Please pay close attention to the `k`, and `a` parsing states. In the table
  66. // below in order to distinguish between the states belonging to the media
  67. // description as opposed to the session description, the states are marked
  68. // with an asterisk ("a*", "k*").
  69. // +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+
  70. // | STATES | a* | a*,k* | a | a,k | b | b,c | e | i | m | o | p | r,t | s | t | u | v | z |
  71. // +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+
  72. // | s1 | | | | | | | | | | | | | | | | 2 | |
  73. // | s2 | | | | | | | | | | 3 | | | | | | | |
  74. // | s3 | | | | | | | | | | | | | 4 | | | | |
  75. // | s4 | | | | | | 5 | 6 | 7 | | | 8 | | | 9 | 10 | | |
  76. // | s5 | | | | | 5 | | | | | | | | | 9 | | | |
  77. // | s6 | | | | | | 5 | | | | | 8 | | | 9 | | | |
  78. // | s7 | | | | | | 5 | 6 | | | | 8 | | | 9 | 10 | | |
  79. // | s8 | | | | | | 5 | | | | | | | | 9 | | | |
  80. // | s9 | | | | 11 | | | | | 12 | | | 9 | | | | | 13 |
  81. // | s10 | | | | | | 5 | 6 | | | | 8 | | | 9 | | | |
  82. // | s11 | | | 11 | | | | | | 12 | | | | | | | | |
  83. // | s12 | | 14 | | | | 15 | | 16 | 12 | | | | | | | | |
  84. // | s13 | | | | 11 | | | | | 12 | | | | | | | | |
  85. // | s14 | 14 | | | | | | | | 12 | | | | | | | | |
  86. // | s15 | | 14 | | | 15 | | | | 12 | | | | | | | | |
  87. // | s16 | | 14 | | | | 15 | | | 12 | | | | | | | | |
  88. // +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+
  89. func (s *SessionDescription) Unmarshal(value []byte) error {
  90. l := new(lexer)
  91. l.desc = s
  92. l.value = value
  93. for state := s1; state != nil; {
  94. var err error
  95. state, err = state(l)
  96. if err != nil {
  97. return err
  98. }
  99. }
  100. return nil
  101. }
  102. func s1(l *lexer) (stateFn, error) {
  103. return l.handleType(func(key string) stateFn {
  104. if key == "v=" {
  105. return unmarshalProtocolVersion
  106. }
  107. return nil
  108. })
  109. }
  110. func s2(l *lexer) (stateFn, error) {
  111. return l.handleType(func(key string) stateFn {
  112. if key == "o=" {
  113. return unmarshalOrigin
  114. }
  115. return nil
  116. })
  117. }
  118. func s3(l *lexer) (stateFn, error) {
  119. return l.handleType(func(key string) stateFn {
  120. if key == "s=" {
  121. return unmarshalSessionName
  122. }
  123. return nil
  124. })
  125. }
  126. func s4(l *lexer) (stateFn, error) {
  127. return l.handleType(func(key string) stateFn {
  128. switch key {
  129. case "i=":
  130. return unmarshalSessionInformation
  131. case "u=":
  132. return unmarshalURI
  133. case "e=":
  134. return unmarshalEmail
  135. case "p=":
  136. return unmarshalPhone
  137. case "c=":
  138. return unmarshalSessionConnectionInformation
  139. case "b=":
  140. return unmarshalSessionBandwidth
  141. case "t=":
  142. return unmarshalTiming
  143. }
  144. return nil
  145. })
  146. }
  147. func s5(l *lexer) (stateFn, error) {
  148. return l.handleType(func(key string) stateFn {
  149. switch key {
  150. case "b=":
  151. return unmarshalSessionBandwidth
  152. case "t=":
  153. return unmarshalTiming
  154. }
  155. return nil
  156. })
  157. }
  158. func s6(l *lexer) (stateFn, error) {
  159. return l.handleType(func(key string) stateFn {
  160. switch key {
  161. case "p=":
  162. return unmarshalPhone
  163. case "c=":
  164. return unmarshalSessionConnectionInformation
  165. case "b=":
  166. return unmarshalSessionBandwidth
  167. case "t=":
  168. return unmarshalTiming
  169. }
  170. return nil
  171. })
  172. }
  173. func s7(l *lexer) (stateFn, error) {
  174. return l.handleType(func(key string) stateFn {
  175. switch key {
  176. case "u=":
  177. return unmarshalURI
  178. case "e=":
  179. return unmarshalEmail
  180. case "p=":
  181. return unmarshalPhone
  182. case "c=":
  183. return unmarshalSessionConnectionInformation
  184. case "b=":
  185. return unmarshalSessionBandwidth
  186. case "t=":
  187. return unmarshalTiming
  188. }
  189. return nil
  190. })
  191. }
  192. func s8(l *lexer) (stateFn, error) {
  193. return l.handleType(func(key string) stateFn {
  194. switch key {
  195. case "c=":
  196. return unmarshalSessionConnectionInformation
  197. case "b=":
  198. return unmarshalSessionBandwidth
  199. case "t=":
  200. return unmarshalTiming
  201. }
  202. return nil
  203. })
  204. }
  205. func s9(l *lexer) (stateFn, error) {
  206. return l.handleType(func(key string) stateFn {
  207. switch key {
  208. case "z=":
  209. return unmarshalTimeZones
  210. case "k=":
  211. return unmarshalSessionEncryptionKey
  212. case "a=":
  213. return unmarshalSessionAttribute
  214. case "r=":
  215. return unmarshalRepeatTimes
  216. case "t=":
  217. return unmarshalTiming
  218. case "m=":
  219. return unmarshalMediaDescription
  220. }
  221. return nil
  222. })
  223. }
  224. func s10(l *lexer) (stateFn, error) {
  225. return l.handleType(func(key string) stateFn {
  226. switch key {
  227. case "e=":
  228. return unmarshalEmail
  229. case "p=":
  230. return unmarshalPhone
  231. case "c=":
  232. return unmarshalSessionConnectionInformation
  233. case "b=":
  234. return unmarshalSessionBandwidth
  235. case "t=":
  236. return unmarshalTiming
  237. }
  238. return nil
  239. })
  240. }
  241. func s11(l *lexer) (stateFn, error) {
  242. return l.handleType(func(key string) stateFn {
  243. switch key {
  244. case "a=":
  245. return unmarshalSessionAttribute
  246. case "m=":
  247. return unmarshalMediaDescription
  248. }
  249. return nil
  250. })
  251. }
  252. func s12(l *lexer) (stateFn, error) {
  253. return l.handleType(func(key string) stateFn {
  254. switch key {
  255. case "a=":
  256. return unmarshalMediaAttribute
  257. case "k=":
  258. return unmarshalMediaEncryptionKey
  259. case "b=":
  260. return unmarshalMediaBandwidth
  261. case "c=":
  262. return unmarshalMediaConnectionInformation
  263. case "i=":
  264. return unmarshalMediaTitle
  265. case "m=":
  266. return unmarshalMediaDescription
  267. }
  268. return nil
  269. })
  270. }
  271. func s13(l *lexer) (stateFn, error) {
  272. return l.handleType(func(key string) stateFn {
  273. switch key {
  274. case "a=":
  275. return unmarshalSessionAttribute
  276. case "k=":
  277. return unmarshalSessionEncryptionKey
  278. case "m=":
  279. return unmarshalMediaDescription
  280. }
  281. return nil
  282. })
  283. }
  284. func s14(l *lexer) (stateFn, error) {
  285. return l.handleType(func(key string) stateFn {
  286. switch key {
  287. case "a=":
  288. return unmarshalMediaAttribute
  289. case "k=":
  290. // Non-spec ordering
  291. return unmarshalMediaEncryptionKey
  292. case "b=":
  293. // Non-spec ordering
  294. return unmarshalMediaBandwidth
  295. case "c=":
  296. // Non-spec ordering
  297. return unmarshalMediaConnectionInformation
  298. case "i=":
  299. // Non-spec ordering
  300. return unmarshalMediaTitle
  301. case "m=":
  302. return unmarshalMediaDescription
  303. }
  304. return nil
  305. })
  306. }
  307. func s15(l *lexer) (stateFn, error) {
  308. return l.handleType(func(key string) stateFn {
  309. switch key {
  310. case "a=":
  311. return unmarshalMediaAttribute
  312. case "k=":
  313. return unmarshalMediaEncryptionKey
  314. case "b=":
  315. return unmarshalMediaBandwidth
  316. case "c=":
  317. return unmarshalMediaConnectionInformation
  318. case "i=":
  319. // Non-spec ordering
  320. return unmarshalMediaTitle
  321. case "m=":
  322. return unmarshalMediaDescription
  323. }
  324. return nil
  325. })
  326. }
  327. func s16(l *lexer) (stateFn, error) {
  328. return l.handleType(func(key string) stateFn {
  329. switch key {
  330. case "a=":
  331. return unmarshalMediaAttribute
  332. case "k=":
  333. return unmarshalMediaEncryptionKey
  334. case "c=":
  335. return unmarshalMediaConnectionInformation
  336. case "b=":
  337. return unmarshalMediaBandwidth
  338. case "i=":
  339. // Non-spec ordering
  340. return unmarshalMediaTitle
  341. case "m=":
  342. return unmarshalMediaDescription
  343. }
  344. return nil
  345. })
  346. }
  347. func unmarshalProtocolVersion(l *lexer) (stateFn, error) {
  348. version, err := l.readUint64Field()
  349. if err != nil {
  350. return nil, err
  351. }
  352. // As off the latest draft of the rfc this value is required to be 0.
  353. // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-5.8.1
  354. if version != 0 {
  355. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, version)
  356. }
  357. if err := l.nextLine(); err != nil {
  358. return nil, err
  359. }
  360. return s2, nil
  361. }
  362. func unmarshalOrigin(l *lexer) (stateFn, error) {
  363. var err error
  364. l.desc.Origin.Username, err = l.readField()
  365. if err != nil {
  366. return nil, err
  367. }
  368. l.desc.Origin.SessionID, err = l.readUint64Field()
  369. if err != nil {
  370. return nil, err
  371. }
  372. l.desc.Origin.SessionVersion, err = l.readUint64Field()
  373. if err != nil {
  374. return nil, err
  375. }
  376. l.desc.Origin.NetworkType, err = l.readField()
  377. if err != nil {
  378. return nil, err
  379. }
  380. // Set according to currently registered with IANA
  381. // https://tools.ietf.org/html/rfc4566#section-8.2.6
  382. if !anyOf(l.desc.Origin.NetworkType, "IN") {
  383. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, l.desc.Origin.NetworkType)
  384. }
  385. l.desc.Origin.AddressType, err = l.readField()
  386. if err != nil {
  387. return nil, err
  388. }
  389. // Set according to currently registered with IANA
  390. // https://tools.ietf.org/html/rfc4566#section-8.2.7
  391. if !anyOf(l.desc.Origin.AddressType, "IP4", "IP6") {
  392. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, l.desc.Origin.AddressType)
  393. }
  394. l.desc.Origin.UnicastAddress, err = l.readField()
  395. if err != nil {
  396. return nil, err
  397. }
  398. if err := l.nextLine(); err != nil {
  399. return nil, err
  400. }
  401. return s3, nil
  402. }
  403. func unmarshalSessionName(l *lexer) (stateFn, error) {
  404. value, err := l.readLine()
  405. if err != nil {
  406. return nil, err
  407. }
  408. l.desc.SessionName = SessionName(value)
  409. return s4, nil
  410. }
  411. func unmarshalSessionInformation(l *lexer) (stateFn, error) {
  412. value, err := l.readLine()
  413. if err != nil {
  414. return nil, err
  415. }
  416. sessionInformation := Information(value)
  417. l.desc.SessionInformation = &sessionInformation
  418. return s7, nil
  419. }
  420. func unmarshalURI(l *lexer) (stateFn, error) {
  421. value, err := l.readLine()
  422. if err != nil {
  423. return nil, err
  424. }
  425. l.desc.URI, err = url.Parse(value)
  426. if err != nil {
  427. return nil, err
  428. }
  429. return s10, nil
  430. }
  431. func unmarshalEmail(l *lexer) (stateFn, error) {
  432. value, err := l.readLine()
  433. if err != nil {
  434. return nil, err
  435. }
  436. emailAddress := EmailAddress(value)
  437. l.desc.EmailAddress = &emailAddress
  438. return s6, nil
  439. }
  440. func unmarshalPhone(l *lexer) (stateFn, error) {
  441. value, err := l.readLine()
  442. if err != nil {
  443. return nil, err
  444. }
  445. phoneNumber := PhoneNumber(value)
  446. l.desc.PhoneNumber = &phoneNumber
  447. return s8, nil
  448. }
  449. func unmarshalSessionConnectionInformation(l *lexer) (stateFn, error) {
  450. var err error
  451. l.desc.ConnectionInformation, err = l.unmarshalConnectionInformation()
  452. if err != nil {
  453. return nil, err
  454. }
  455. return s5, nil
  456. }
  457. func (l *lexer) unmarshalConnectionInformation() (*ConnectionInformation, error) {
  458. var err error
  459. var c ConnectionInformation
  460. c.NetworkType, err = l.readField()
  461. if err != nil {
  462. return nil, err
  463. }
  464. // Set according to currently registered with IANA
  465. // https://tools.ietf.org/html/rfc4566#section-8.2.6
  466. if !anyOf(c.NetworkType, "IN") {
  467. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, c.NetworkType)
  468. }
  469. c.AddressType, err = l.readField()
  470. if err != nil {
  471. return nil, err
  472. }
  473. // Set according to currently registered with IANA
  474. // https://tools.ietf.org/html/rfc4566#section-8.2.7
  475. if !anyOf(c.AddressType, "IP4", "IP6") {
  476. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, c.AddressType)
  477. }
  478. address, err := l.readField()
  479. if err != nil {
  480. return nil, err
  481. }
  482. if address != "" {
  483. c.Address = new(Address)
  484. c.Address.Address = address
  485. }
  486. if err := l.nextLine(); err != nil {
  487. return nil, err
  488. }
  489. return &c, nil
  490. }
  491. func unmarshalSessionBandwidth(l *lexer) (stateFn, error) {
  492. value, err := l.readLine()
  493. if err != nil {
  494. return nil, err
  495. }
  496. bandwidth, err := unmarshalBandwidth(value)
  497. if err != nil {
  498. return nil, fmt.Errorf("%w `b=%v`", errSDPInvalidValue, value)
  499. }
  500. l.desc.Bandwidth = append(l.desc.Bandwidth, *bandwidth)
  501. return s5, nil
  502. }
  503. func unmarshalBandwidth(value string) (*Bandwidth, error) {
  504. parts := strings.Split(value, ":")
  505. if len(parts) != 2 {
  506. return nil, fmt.Errorf("%w `b=%v`", errSDPInvalidValue, parts)
  507. }
  508. experimental := strings.HasPrefix(parts[0], "X-")
  509. if experimental {
  510. parts[0] = strings.TrimPrefix(parts[0], "X-")
  511. } else if !anyOf(parts[0], "CT", "AS", "TIAS", "RS", "RR") {
  512. // Set according to currently registered with IANA
  513. // https://tools.ietf.org/html/rfc4566#section-5.8
  514. // https://tools.ietf.org/html/rfc3890#section-6.2
  515. // https://tools.ietf.org/html/rfc3556#section-2
  516. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, parts[0])
  517. }
  518. bandwidth, err := strconv.ParseUint(parts[1], 10, 64)
  519. if err != nil {
  520. return nil, fmt.Errorf("%w `%v`", errSDPInvalidNumericValue, parts[1])
  521. }
  522. return &Bandwidth{
  523. Experimental: experimental,
  524. Type: parts[0],
  525. Bandwidth: bandwidth,
  526. }, nil
  527. }
  528. func unmarshalTiming(l *lexer) (stateFn, error) {
  529. var err error
  530. var td TimeDescription
  531. td.Timing.StartTime, err = l.readUint64Field()
  532. if err != nil {
  533. return nil, err
  534. }
  535. td.Timing.StopTime, err = l.readUint64Field()
  536. if err != nil {
  537. return nil, err
  538. }
  539. if err := l.nextLine(); err != nil {
  540. return nil, err
  541. }
  542. l.desc.TimeDescriptions = append(l.desc.TimeDescriptions, td)
  543. return s9, nil
  544. }
  545. func unmarshalRepeatTimes(l *lexer) (stateFn, error) {
  546. var err error
  547. var newRepeatTime RepeatTime
  548. latestTimeDesc := &l.desc.TimeDescriptions[len(l.desc.TimeDescriptions)-1]
  549. field, err := l.readField()
  550. if err != nil {
  551. return nil, err
  552. }
  553. newRepeatTime.Interval, err = parseTimeUnits(field)
  554. if err != nil {
  555. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, field)
  556. }
  557. field, err = l.readField()
  558. if err != nil {
  559. return nil, err
  560. }
  561. newRepeatTime.Duration, err = parseTimeUnits(field)
  562. if err != nil {
  563. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, field)
  564. }
  565. for {
  566. field, err := l.readField()
  567. if err != nil {
  568. return nil, err
  569. }
  570. if field == "" {
  571. break
  572. }
  573. offset, err := parseTimeUnits(field)
  574. if err != nil {
  575. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, field)
  576. }
  577. newRepeatTime.Offsets = append(newRepeatTime.Offsets, offset)
  578. }
  579. if err := l.nextLine(); err != nil {
  580. return nil, err
  581. }
  582. latestTimeDesc.RepeatTimes = append(latestTimeDesc.RepeatTimes, newRepeatTime)
  583. return s9, nil
  584. }
  585. func unmarshalTimeZones(l *lexer) (stateFn, error) {
  586. // These fields are transimitted in pairs
  587. // z=<adjustment time> <offset> <adjustment time> <offset> ....
  588. // so we are making sure that there are actually multiple of 2 total.
  589. for {
  590. var err error
  591. var timeZone TimeZone
  592. timeZone.AdjustmentTime, err = l.readUint64Field()
  593. if err != nil {
  594. return nil, err
  595. }
  596. offset, err := l.readField()
  597. if err != nil {
  598. return nil, err
  599. }
  600. if offset == "" {
  601. break
  602. }
  603. timeZone.Offset, err = parseTimeUnits(offset)
  604. if err != nil {
  605. return nil, err
  606. }
  607. l.desc.TimeZones = append(l.desc.TimeZones, timeZone)
  608. }
  609. if err := l.nextLine(); err != nil {
  610. return nil, err
  611. }
  612. return s13, nil
  613. }
  614. func unmarshalSessionEncryptionKey(l *lexer) (stateFn, error) {
  615. value, err := l.readLine()
  616. if err != nil {
  617. return nil, err
  618. }
  619. encryptionKey := EncryptionKey(value)
  620. l.desc.EncryptionKey = &encryptionKey
  621. return s11, nil
  622. }
  623. func unmarshalSessionAttribute(l *lexer) (stateFn, error) {
  624. value, err := l.readLine()
  625. if err != nil {
  626. return nil, err
  627. }
  628. i := strings.IndexRune(value, ':')
  629. var a Attribute
  630. if i > 0 {
  631. a = NewAttribute(value[:i], value[i+1:])
  632. } else {
  633. a = NewPropertyAttribute(value)
  634. }
  635. l.desc.Attributes = append(l.desc.Attributes, a)
  636. return s11, nil
  637. }
  638. func unmarshalMediaDescription(l *lexer) (stateFn, error) {
  639. var newMediaDesc MediaDescription
  640. // <media>
  641. field, err := l.readField()
  642. if err != nil {
  643. return nil, err
  644. }
  645. // Set according to currently registered with IANA
  646. // https://tools.ietf.org/html/rfc4566#section-5.14
  647. if !anyOf(field, "audio", "video", "text", "application", "message") {
  648. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, field)
  649. }
  650. newMediaDesc.MediaName.Media = field
  651. // <port>
  652. field, err = l.readField()
  653. if err != nil {
  654. return nil, err
  655. }
  656. parts := strings.Split(field, "/")
  657. newMediaDesc.MediaName.Port.Value, err = parsePort(parts[0])
  658. if err != nil {
  659. return nil, fmt.Errorf("%w `%v`", errSDPInvalidPortValue, parts[0])
  660. }
  661. if len(parts) > 1 {
  662. var portRange int
  663. portRange, err = strconv.Atoi(parts[1])
  664. if err != nil {
  665. return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, parts)
  666. }
  667. newMediaDesc.MediaName.Port.Range = &portRange
  668. }
  669. // <proto>
  670. field, err = l.readField()
  671. if err != nil {
  672. return nil, err
  673. }
  674. // Set according to currently registered with IANA
  675. // https://tools.ietf.org/html/rfc4566#section-5.14
  676. // https://tools.ietf.org/html/rfc4975#section-8.1
  677. for _, proto := range strings.Split(field, "/") {
  678. if !anyOf(proto, "UDP", "RTP", "AVP", "SAVP", "SAVPF", "TLS", "DTLS", "SCTP", "AVPF", "TCP", "MSRP") {
  679. return nil, fmt.Errorf("%w `%v`", errSDPInvalidNumericValue, field)
  680. }
  681. newMediaDesc.MediaName.Protos = append(newMediaDesc.MediaName.Protos, proto)
  682. }
  683. // <fmt>...
  684. for {
  685. field, err = l.readField()
  686. if err != nil {
  687. return nil, err
  688. }
  689. if field == "" {
  690. break
  691. }
  692. newMediaDesc.MediaName.Formats = append(newMediaDesc.MediaName.Formats, field)
  693. }
  694. if err := l.nextLine(); err != nil {
  695. return nil, err
  696. }
  697. l.desc.MediaDescriptions = append(l.desc.MediaDescriptions, &newMediaDesc)
  698. return s12, nil
  699. }
  700. func unmarshalMediaTitle(l *lexer) (stateFn, error) {
  701. value, err := l.readLine()
  702. if err != nil {
  703. return nil, err
  704. }
  705. latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1]
  706. mediaTitle := Information(value)
  707. latestMediaDesc.MediaTitle = &mediaTitle
  708. return s16, nil
  709. }
  710. func unmarshalMediaConnectionInformation(l *lexer) (stateFn, error) {
  711. var err error
  712. latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1]
  713. latestMediaDesc.ConnectionInformation, err = l.unmarshalConnectionInformation()
  714. if err != nil {
  715. return nil, err
  716. }
  717. return s15, nil
  718. }
  719. func unmarshalMediaBandwidth(l *lexer) (stateFn, error) {
  720. value, err := l.readLine()
  721. if err != nil {
  722. return nil, err
  723. }
  724. latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1]
  725. bandwidth, err := unmarshalBandwidth(value)
  726. if err != nil {
  727. return nil, fmt.Errorf("%w `b=%v`", errSDPInvalidSyntax, value)
  728. }
  729. latestMediaDesc.Bandwidth = append(latestMediaDesc.Bandwidth, *bandwidth)
  730. return s15, nil
  731. }
  732. func unmarshalMediaEncryptionKey(l *lexer) (stateFn, error) {
  733. value, err := l.readLine()
  734. if err != nil {
  735. return nil, err
  736. }
  737. latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1]
  738. encryptionKey := EncryptionKey(value)
  739. latestMediaDesc.EncryptionKey = &encryptionKey
  740. return s14, nil
  741. }
  742. func unmarshalMediaAttribute(l *lexer) (stateFn, error) {
  743. value, err := l.readLine()
  744. if err != nil {
  745. return nil, err
  746. }
  747. i := strings.IndexRune(value, ':')
  748. var a Attribute
  749. if i > 0 {
  750. a = NewAttribute(value[:i], value[i+1:])
  751. } else {
  752. a = NewPropertyAttribute(value)
  753. }
  754. latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1]
  755. latestMediaDesc.Attributes = append(latestMediaDesc.Attributes, a)
  756. return s14, nil
  757. }
  758. func parseTimeUnits(value string) (num int64, err error) {
  759. k := timeShorthand(value[len(value)-1])
  760. if k > 0 {
  761. num, err = strconv.ParseInt(value[:len(value)-1], 10, 64)
  762. } else {
  763. k = 1
  764. num, err = strconv.ParseInt(value, 10, 64)
  765. }
  766. if err != nil {
  767. return 0, fmt.Errorf("%w `%v`", errSDPInvalidValue, value)
  768. }
  769. return num * k, nil
  770. }
  771. func timeShorthand(b byte) int64 {
  772. // Some time offsets in the protocol can be provided with a shorthand
  773. // notation. This code ensures to convert it to NTP timestamp format.
  774. switch b {
  775. case 'd': // days
  776. return 86400
  777. case 'h': // hours
  778. return 3600
  779. case 'm': // minutes
  780. return 60
  781. case 's': // seconds (allowed for completeness)
  782. return 1
  783. default:
  784. return 0
  785. }
  786. }
  787. func parsePort(value string) (int, error) {
  788. port, err := strconv.Atoi(value)
  789. if err != nil {
  790. return 0, fmt.Errorf("%w `%v`", errSDPInvalidPortValue, port)
  791. }
  792. if port < 0 || port > 65536 {
  793. return 0, fmt.Errorf("%w -- out of range `%v`", errSDPInvalidPortValue, port)
  794. }
  795. return port, nil
  796. }