25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

10 ay önce
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825
  1. #include "sdp.h"
  2. #include <errno.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #if defined(OS_WINDOWS)
  7. #define strdup _strdup
  8. #define strcasecmp _stricmp
  9. #endif
  10. #define N_EMAIL 1
  11. #define N_PHONE 1
  12. #define N_CONNECTION 1
  13. #define N_BANDWIDTH 1
  14. #define N_TIMING 1
  15. #define N_REPEAT 1
  16. #define N_TIMEZONE 1
  17. #define N_REPEAT_OFFSET 1
  18. #define N_ATTRIBUTE 5
  19. #define N_MEDIA 3 // audio/video/whiteboard
  20. #define N_MEDIA_FORMAT 5
  21. struct sdp_connection
  22. {
  23. char* network;
  24. char* addrtype;
  25. char* address;
  26. };
  27. struct sdp_origin
  28. {
  29. char* username;
  30. char* session;
  31. char* session_version;
  32. struct sdp_connection c;
  33. };
  34. struct sdp_email
  35. {
  36. char* email;
  37. };
  38. struct sdp_phone
  39. {
  40. char* phone;
  41. };
  42. struct sdp_bandwidth
  43. {
  44. char* bwtype;
  45. char* bandwidth;
  46. };
  47. struct bandwidths
  48. {
  49. int count;
  50. int capacity;
  51. struct sdp_bandwidth bandwidths[N_BANDWIDTH];
  52. struct sdp_bandwidth *ptr;
  53. };
  54. struct sdp_repeat
  55. {
  56. char* interval;
  57. char* duration;
  58. struct offset
  59. {
  60. int count;
  61. int capacity;
  62. char *offsets[N_REPEAT_OFFSET];
  63. char **ptr;
  64. } offsets;
  65. };
  66. struct sdp_timezone
  67. {
  68. char* time;
  69. char* offset;
  70. };
  71. struct sdp_timing
  72. {
  73. char* start;
  74. char* stop;
  75. struct repeat
  76. {
  77. int count;
  78. int capacity;
  79. struct sdp_repeat repeats[N_REPEAT];
  80. struct sdp_repeat *ptr;
  81. } r;
  82. struct timezone_t
  83. {
  84. int count;
  85. int capacity;
  86. struct sdp_timezone timezones[N_TIMEZONE];
  87. struct sdp_timezone *ptr;
  88. } z;
  89. };
  90. struct sdp_encryption
  91. {
  92. char* method;
  93. char* key;
  94. };
  95. struct sdp_attribute
  96. {
  97. char* name;
  98. char* value;
  99. };
  100. struct attributes
  101. {
  102. int count;
  103. int capacity;
  104. struct sdp_attribute attrs[N_ATTRIBUTE];
  105. struct sdp_attribute *ptr;
  106. };
  107. struct sdp_media
  108. {
  109. char* media; //audio, video, text, application, message
  110. char* port;
  111. char* proto; // udp, RTP/AVP, RTP/SAVP
  112. struct format
  113. {
  114. int count;
  115. int capacity;
  116. char *formats[N_MEDIA_FORMAT];
  117. char **ptr;
  118. } fmt;
  119. char* i;
  120. struct connection
  121. {
  122. int count;
  123. int capacity;
  124. struct sdp_connection connections[N_EMAIL];
  125. struct sdp_connection *ptr;
  126. } c;
  127. struct attributes a;
  128. struct bandwidths b;
  129. struct sdp_encryption k;
  130. };
  131. struct sdp_t
  132. {
  133. char *raw; // raw source string
  134. int offset; // parse offset
  135. int v;
  136. struct sdp_origin o;
  137. char* s;
  138. char* i;
  139. char* u;
  140. struct email
  141. {
  142. int count;
  143. int capacity;
  144. struct sdp_email emails[N_EMAIL];
  145. struct sdp_email *ptr;
  146. } e;
  147. struct phone
  148. {
  149. int count;
  150. int capacity;
  151. struct sdp_phone phones[N_PHONE];
  152. struct sdp_phone *ptr;
  153. } p;
  154. struct sdp_connection c;
  155. struct bandwidths b;
  156. struct timing
  157. {
  158. int count;
  159. int capacity;
  160. struct sdp_timing times[N_TIMING];
  161. struct sdp_timing *ptr;
  162. } t;
  163. struct sdp_encryption k;
  164. struct attributes a;
  165. struct media
  166. {
  167. int count;
  168. int capacity;
  169. struct sdp_media medias[N_MEDIA];
  170. struct sdp_media *ptr;
  171. } m;
  172. };
  173. static inline void sdp_skip_space(struct sdp_t* sdp)
  174. {
  175. char c = sdp->raw[sdp->offset];
  176. while(' ' == c || '\t' == c)
  177. c = sdp->raw[++sdp->offset];
  178. }
  179. static inline int sdp_token_word(struct sdp_t* sdp, const char* escape)
  180. {
  181. int n = sdp->offset;
  182. sdp->offset += strcspn(sdp->raw + sdp->offset, escape);
  183. return sdp->offset - n;
  184. }
  185. static inline int sdp_token_crlf(struct sdp_t* sdp)
  186. {
  187. sdp_skip_space(sdp);
  188. if('\r' == sdp->raw[sdp->offset])
  189. ++sdp->offset;
  190. if('\n' == sdp->raw[sdp->offset])
  191. {
  192. ++sdp->offset;
  193. return 0;
  194. }
  195. // sdp end line
  196. if('\0' == sdp->raw[sdp->offset])
  197. return 0;
  198. return -1;
  199. }
  200. static inline void trim_right(const char* s, int *len)
  201. {
  202. //// left trim
  203. //while(*len > 0 && isspace(s[*pos]))
  204. //{
  205. // --*len;
  206. // ++*pos;
  207. //}
  208. // right trim
  209. while(*len > 0 && ' '==(s[*len - 1]))
  210. {
  211. --*len;
  212. }
  213. }
  214. static inline struct sdp_timing* sdp_get_timing(struct sdp_t* sdp, int idx)
  215. {
  216. if(idx >= sdp->t.count)
  217. return NULL;
  218. return idx >= N_TIMING ? &sdp->t.ptr[idx - N_TIMING] : &sdp->t.times[idx];
  219. }
  220. static inline struct sdp_media* sdp_get_media(struct sdp_t* sdp, int idx)
  221. {
  222. if(idx >= sdp->m.count)
  223. return NULL;
  224. return idx >= N_MEDIA ? &sdp->m.ptr[idx - N_MEDIA] : &sdp->m.medias[idx];
  225. }
  226. // RFC4566 5.1
  227. static int sdp_parse_version(struct sdp_t* sdp)
  228. {
  229. char c;
  230. assert(sdp);
  231. if(!sdp) return -1;
  232. sdp->v = 0;
  233. sdp_skip_space(sdp);
  234. c = sdp->raw[sdp->offset];
  235. while('0' <= c && c <= '9')
  236. {
  237. sdp->v = sdp->v * 10 + (c - '0');
  238. c = sdp->raw[++sdp->offset];
  239. }
  240. return sdp_token_crlf(sdp);
  241. }
  242. // RFC4566 5.2
  243. // o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
  244. // <username> "-" if the originating host does not support the concept of user IDs.
  245. // <sess-id> is a numeric string
  246. // <sess-version> is a version number for this session description
  247. // <nettype> IN
  248. // <addrtype> IP4/IP6
  249. static int sdp_parse_origin(struct sdp_t* sdp)
  250. {
  251. char* v[6];
  252. char** vv[6];
  253. int i, j, n[6];
  254. struct sdp_origin *o;
  255. static const char* default_username = "-";
  256. o = &sdp->o;
  257. memset(o, 0, sizeof(struct sdp_origin));
  258. memset(n, 0, sizeof(n));
  259. sdp_skip_space(sdp);
  260. for (i = 0; i < 6 && sdp->raw[sdp->offset] && !strchr("\r\n", sdp->raw[sdp->offset]); i++)
  261. {
  262. v[i] = sdp->raw + sdp->offset;
  263. n[i] = sdp_token_word(sdp, " \t\r\n");
  264. sdp_skip_space(sdp);
  265. }
  266. sdp_token_crlf(sdp);
  267. if (i < 5)
  268. return 0;
  269. o->username = (char*)default_username; // default value
  270. vv[0] = &o->username;
  271. vv[1] = &o->session;
  272. vv[2] = &o->session_version;
  273. vv[3] = &o->c.network;
  274. vv[4] = &o->c.addrtype;
  275. vv[5] = &o->c.address;
  276. for (j = 5; i > 0; j--)
  277. {
  278. i--;
  279. v[i][n[i]] = '\0';
  280. *vv[j] = v[i];
  281. }
  282. return 0;
  283. }
  284. // RFC4566 5.3
  285. // s=<session name>
  286. // There MUST be one and only one "s=" field per session description. can be empty
  287. static int sdp_parse_session(struct sdp_t* sdp)
  288. {
  289. int n = 0;
  290. sdp->s = sdp->raw + sdp->offset;
  291. n = sdp_token_word(sdp, "\r\n");
  292. if(0 != sdp_token_crlf(sdp))
  293. return -1;
  294. sdp->s[n] = '\0';
  295. return 0;
  296. }
  297. // RFC4566 5.4
  298. // i=<session description>
  299. // There MUST be at most one session-level "i=" field per session description,
  300. // and at most one "i=" field per media.
  301. // default UTF-8
  302. static int sdp_parse_information(struct sdp_t* sdp)
  303. {
  304. int n = 0;
  305. char **i;
  306. if(sdp->m.count > 0)
  307. {
  308. i = &sdp_get_media(sdp, sdp->m.count-1)->i;
  309. }
  310. else
  311. {
  312. i = &sdp->i;
  313. }
  314. *i = sdp->raw + sdp->offset;
  315. n = sdp_token_word(sdp, "\r\n");
  316. if(0 != sdp_token_crlf(sdp))
  317. return -1;
  318. (*i)[n] = '\0';
  319. return 0;
  320. }
  321. // RFC4566 5.5
  322. // u=<uri>
  323. // This field is OPTIONAL, but if it is present it MUST be
  324. // specified before the first media field.
  325. static int sdp_parse_uri(struct sdp_t* sdp)
  326. {
  327. int n = 0;
  328. // No more than one URI field is allowed per session description.
  329. assert(!sdp->u);
  330. sdp->u = sdp->raw + sdp->offset;
  331. n = sdp_token_word(sdp, "\r\n");
  332. if(0 != sdp_token_crlf(sdp))
  333. return -1;
  334. sdp->u[n] = '\0';
  335. return 0;
  336. }
  337. // RFC4566 5.6
  338. // e=<email-address>
  339. // p=<phone-number>
  340. // OPTIONAL, If an email address or phone number is present, it MUST be specified
  341. // before the first media field. More than one email or phone field can
  342. // be given for a session description.
  343. // p=+1 617 555-6011
  344. // e=j.doe@example.com (Jane Doe)
  345. // e=Jane Doe <j.doe@example.com>
  346. static int sdp_parse_email(struct sdp_t* sdp)
  347. {
  348. int n = 0;
  349. struct sdp_email *e;
  350. if(sdp->e.count >= N_EMAIL)
  351. {
  352. if(sdp->e.count - N_EMAIL >= sdp->e.capacity)
  353. {
  354. void* ptr;
  355. ptr = (struct sdp_email*)realloc(sdp->e.ptr, (sdp->e.capacity+8)*sizeof(struct sdp_email));
  356. if(!ptr)
  357. return -ENOMEM;
  358. sdp->e.ptr = ptr;
  359. sdp->e.capacity += 8;
  360. }
  361. e = &sdp->e.ptr[sdp->e.count - N_EMAIL];
  362. }
  363. else
  364. {
  365. e = &sdp->e.emails[sdp->e.count];
  366. }
  367. memset(e, 0, sizeof(struct sdp_email));
  368. e->email = sdp->raw + sdp->offset;
  369. n = sdp_token_word(sdp, "\r\n");
  370. if(0 != sdp_token_crlf(sdp))
  371. return -1;
  372. e->email[n] = '\0';
  373. ++sdp->e.count;
  374. return 0;
  375. }
  376. static int sdp_parse_phone(struct sdp_t* sdp)
  377. {
  378. int n = 0;
  379. struct sdp_phone *p;
  380. if(sdp->p.count >= N_PHONE)
  381. {
  382. if(sdp->p.count - N_PHONE >= sdp->p.capacity)
  383. {
  384. void* ptr;
  385. ptr = (struct sdp_phone*)realloc(sdp->p.ptr, (sdp->p.capacity+8)*sizeof(struct sdp_phone));
  386. if(!ptr)
  387. return -ENOMEM;
  388. sdp->p.ptr = ptr;
  389. sdp->p.capacity += 8;
  390. }
  391. p = &sdp->p.ptr[sdp->p.count - N_PHONE];
  392. }
  393. else
  394. {
  395. p = &sdp->p.phones[sdp->p.count];
  396. }
  397. memset(p, 0, sizeof(struct sdp_phone));
  398. p->phone = sdp->raw + sdp->offset;
  399. n = sdp_token_word(sdp, "\r\n");
  400. if(0 != sdp_token_crlf(sdp))
  401. return -1;
  402. trim_right(p->phone, &n);
  403. p->phone[n] = '\0';
  404. ++sdp->p.count;
  405. return 0;
  406. }
  407. // RFC4566 5.7
  408. // c=<nettype> <addrtype> <connection-address>
  409. // A session description MUST contain either at least one "c=" field in
  410. // each media description or a single "c=" field at the session level.
  411. // c=IN IP4 224.2.36.42/127
  412. // c=IN IP4 224.2.1.1/127/3
  413. // c=IN IP6 FF15::101/3
  414. // The slash notation for multiple addresses described above MUST NOT be
  415. // used for IP unicast addresses
  416. static int sdp_parse_connection(struct sdp_t* sdp)
  417. {
  418. int n[3];
  419. struct sdp_media *m;
  420. struct sdp_connection *c;
  421. m = NULL;
  422. if(sdp->m.count > 0)
  423. {
  424. m = sdp_get_media(sdp, sdp->m.count-1);
  425. if(m->c.count >= N_CONNECTION)
  426. {
  427. if(m->c.count - N_CONNECTION >= m->c.capacity)
  428. {
  429. void* ptr;
  430. ptr = (struct sdp_connection*)realloc(m->c.ptr, (m->c.capacity+8)*sizeof(struct sdp_connection));
  431. if(!ptr)
  432. return -ENOMEM;
  433. m->c.ptr = ptr;
  434. m->c.capacity += 8;
  435. }
  436. c = &m->c.ptr[m->c.count - N_CONNECTION];
  437. }
  438. else
  439. {
  440. c = &m->c.connections[m->c.count];
  441. }
  442. }
  443. else
  444. {
  445. c = &sdp->c;
  446. }
  447. memset(c, 0, sizeof(struct sdp_connection));
  448. memset(n, 0, sizeof(n));
  449. sdp_skip_space(sdp);
  450. c->network = sdp->raw + sdp->offset;
  451. n[0] = sdp_token_word(sdp, " \t\r\n");
  452. sdp_skip_space(sdp);
  453. c->addrtype = sdp->raw + sdp->offset;
  454. n[1] = sdp_token_word(sdp, " \t\r\n");
  455. sdp_skip_space(sdp);
  456. c->address = sdp->raw + sdp->offset;
  457. n[2] = sdp_token_word(sdp, "\r\n");
  458. trim_right(c->address, &n[2]);
  459. // check before assign '\0'
  460. if(0==sdp_token_crlf(sdp) && n[0]>0 && n[1]>0 && n[2]>0)
  461. {
  462. c->network[n[0]] = '\0';
  463. c->addrtype[n[1]] = '\0';
  464. c->address[n[2]] = '\0';
  465. if(m) ++m->c.count; // add media connection
  466. return 0;
  467. }
  468. return -1;
  469. }
  470. // RFC4566 5.8
  471. // b=<bwtype>:<bandwidth>
  472. // bwtype: CT/AS
  473. // bandwidth: kilobits per second by default
  474. // A prefix "X-" is defined for <bwtype> names.
  475. // b=X-YZ:128
  476. static int sdp_parse_bandwidth(struct sdp_t* sdp)
  477. {
  478. int n[2];
  479. struct bandwidths *bs;
  480. struct sdp_bandwidth *b;
  481. if(sdp->m.count > 0)
  482. {
  483. bs = &sdp_get_media(sdp, sdp->m.count-1)->b;
  484. }
  485. else
  486. {
  487. bs = &sdp->b;
  488. }
  489. if(bs->count >= N_BANDWIDTH)
  490. {
  491. if(bs->count - N_BANDWIDTH >= bs->capacity)
  492. {
  493. void* ptr;
  494. ptr = (struct sdp_bandwidth*)realloc(bs->ptr, (bs->capacity+8)*sizeof(struct sdp_bandwidth));
  495. if(!ptr)
  496. return -ENOMEM;
  497. bs->ptr = ptr;
  498. bs->capacity += 8;
  499. }
  500. b = &bs->ptr[bs->count - N_BANDWIDTH];
  501. }
  502. else
  503. {
  504. b = &bs->bandwidths[bs->count];
  505. }
  506. memset(n, 0, sizeof(n));
  507. memset(b, 0, sizeof(struct sdp_bandwidth));
  508. sdp_skip_space(sdp);
  509. b->bwtype = sdp->raw + sdp->offset;
  510. n[0] = sdp_token_word(sdp, ":\r\n");
  511. trim_right(b->bwtype, &n[0]);
  512. if(':' == sdp->raw[sdp->offset])
  513. ++sdp->offset;
  514. sdp_skip_space(sdp);
  515. b->bandwidth = sdp->raw + sdp->offset;
  516. n[1] = sdp_token_word(sdp, "\r\n");
  517. trim_right(b->bandwidth, &n[1]);
  518. if(0 == sdp_token_crlf(sdp))
  519. {
  520. ++bs->count;
  521. b->bwtype[n[0]] = '\0';
  522. b->bandwidth[n[1]] = '\0';
  523. return 0;
  524. }
  525. return -1;
  526. }
  527. // RFC4566 5.9 (p17)
  528. // t=<start-time> <stop-time>
  529. // If the <stop-time> is set to zero, then the session is not bounded,
  530. // though it will not become active until after the <start-time>. If
  531. // the <start-time> is also zero, the session is regarded as permanent.
  532. //
  533. // 1. These values are the decimal representation of Network Time Protocol (NTP) time values in seconds
  534. // since 1900 [13]. To convert these values to UNIX time, subtract decimal 2208988800.
  535. // 2. If the <stop-time> is set to zero, then the session is not bounded, though it will not become active
  536. // until after the <start-time>. If the <start-time> is also zero, the session is regarded as permanent.
  537. static int sdp_parse_timing(struct sdp_t* sdp)
  538. {
  539. int n[2];
  540. struct sdp_timing *t;
  541. if(sdp->t.count >= N_TIMING)
  542. {
  543. if(sdp->t.count - N_TIMING >= sdp->t.capacity)
  544. {
  545. void* ptr;
  546. ptr = (struct sdp_timing*)realloc(sdp->t.ptr, (sdp->t.capacity+8)*sizeof(struct sdp_timing));
  547. if(!ptr)
  548. return -ENOMEM;
  549. sdp->t.ptr = ptr;
  550. sdp->t.capacity += 8;
  551. }
  552. t = &sdp->t.ptr[sdp->t.count - N_TIMING];
  553. }
  554. else
  555. {
  556. t = &sdp->t.times[sdp->t.count];
  557. }
  558. memset(n, 0, sizeof(n));
  559. memset(t, 0, sizeof(struct sdp_timing));
  560. sdp_skip_space(sdp);
  561. t->start = sdp->raw + sdp->offset;
  562. n[0] = sdp_token_word(sdp, " \t\r\n");
  563. sdp_skip_space(sdp);
  564. t->stop = sdp->raw + sdp->offset;
  565. n[1] = sdp_token_word(sdp, "\r\n");
  566. trim_right(t->stop, &n[1]);
  567. if(0 == sdp_token_crlf(sdp))
  568. {
  569. t->start[n[0]] = '\0';
  570. t->stop[n[1]] = '\0';
  571. ++sdp->t.count;
  572. return 0;
  573. }
  574. return -1;
  575. }
  576. static int sdp_append_timing_repeat_offset(struct sdp_repeat *r, char* offset)
  577. {
  578. if(r->offsets.count >= N_REPEAT_OFFSET)
  579. {
  580. if(r->offsets.count - N_REPEAT_OFFSET >= r->offsets.capacity)
  581. {
  582. void* ptr;
  583. ptr = (char**)realloc(r->offsets.ptr, (r->offsets.capacity+8)*sizeof(char*));
  584. if(!ptr)
  585. return -ENOMEM;
  586. r->offsets.ptr = ptr;
  587. r->offsets.capacity += 8;
  588. }
  589. r->offsets.ptr[r->offsets.count - N_REPEAT_OFFSET] = offset;
  590. }
  591. else
  592. {
  593. r->offsets.offsets[r->offsets.count] = offset;
  594. }
  595. ++r->offsets.count;
  596. return 0;
  597. }
  598. // RFC4566 5.10
  599. // r=<repeat interval> <active duration> <offsets from start-time>
  600. // t=3034423619 3042462419
  601. // r=604800 3600 0 90000
  602. // r=7d 1h 0 25h
  603. static int sdp_parse_repeat(struct sdp_t* sdp)
  604. {
  605. int ret;
  606. int n[3];
  607. char *offset;
  608. struct sdp_timing *t;
  609. struct sdp_repeat *r;
  610. assert(sdp->t.count > 0);
  611. if(sdp->t.count < 1)
  612. return -1; // repeat must after timing
  613. t = sdp_get_timing(sdp, sdp->t.count-1);
  614. if(t->r.count >= N_REPEAT)
  615. {
  616. if(t->r.count - N_REPEAT >= t->r.capacity)
  617. {
  618. void* ptr;
  619. ptr = (struct sdp_repeat*)realloc(t->r.ptr, (t->r.capacity+8)*sizeof(struct sdp_repeat));
  620. if(!ptr)
  621. return -ENOMEM;
  622. t->r.ptr = ptr;
  623. t->r.capacity += 8;
  624. }
  625. r = &t->r.ptr[t->r.count - N_REPEAT];
  626. }
  627. else
  628. {
  629. r = &t->r.repeats[t->r.count];
  630. }
  631. offset = NULL;
  632. memset(n, 0, sizeof(n));
  633. memset(r, 0, sizeof(struct sdp_repeat));
  634. sdp_skip_space(sdp);
  635. r->interval = sdp->raw + sdp->offset;
  636. n[0] = sdp_token_word(sdp, " \t\r\n");
  637. sdp_skip_space(sdp);
  638. r->duration = sdp->raw + sdp->offset;
  639. n[1] = sdp_token_word(sdp, " \t\r\n");
  640. while(strchr(" \t", sdp->raw[sdp->offset]))
  641. {
  642. if(n[2] > 0 && offset)
  643. {
  644. offset[n[2]] = '\0';
  645. ret = sdp_append_timing_repeat_offset(r, offset);
  646. if(0 != ret)
  647. return ret;
  648. }
  649. sdp_skip_space(sdp);
  650. offset = sdp->raw + sdp->offset;
  651. n[2] = sdp_token_word(sdp, " \t\r\n");
  652. }
  653. if(0 == sdp_token_crlf(sdp))
  654. {
  655. r->interval[n[0]] = '\0';
  656. r->duration[n[1]] = '\0';
  657. if(n[2] > 0 && offset)
  658. {
  659. offset[n[2]] = '\0';
  660. ret = sdp_append_timing_repeat_offset(r, offset);
  661. if(0 != ret)
  662. return ret;
  663. }
  664. ++t->r.count;
  665. return 0;
  666. }
  667. return -1;
  668. }
  669. // RFC4566 5.11
  670. // z=<adjustment time> <offset> <adjustment time> <offset> ....
  671. // z=2882844526 -1h 2898848070 0
  672. static int sdp_parse_timezone(struct sdp_t* sdp)
  673. {
  674. int n[2];
  675. char *time, *offset;
  676. struct sdp_timing *t;
  677. struct sdp_timezone *z;
  678. assert(sdp->t.count > 0);
  679. if(sdp->t.count < 1)
  680. return -1; // timezone must after timing
  681. t = sdp_get_timing(sdp, sdp->t.count-1);
  682. do
  683. {
  684. sdp_skip_space(sdp);
  685. time = sdp->raw + sdp->offset;
  686. n[0] = sdp_token_word(sdp, " \t\r\n");
  687. sdp_skip_space(sdp);
  688. offset = sdp->raw + sdp->offset;
  689. n[1] = sdp_token_word(sdp, " \t\r\n");
  690. if(n[0] < 1 || n[1] < 1)
  691. break;
  692. if(t->z.count >= N_TIMEZONE)
  693. {
  694. if(t->z.count - N_TIMEZONE >= t->z.capacity)
  695. {
  696. void* ptr;
  697. ptr = (struct sdp_timezone*)realloc(t->z.ptr, (t->z.capacity+8)*sizeof(struct sdp_timezone));
  698. if(!ptr)
  699. return -ENOMEM;
  700. t->z.ptr = ptr;
  701. t->z.capacity += 8;
  702. }
  703. z = &t->z.ptr[t->r.count - N_TIMEZONE];
  704. }
  705. else
  706. {
  707. z = &t->z.timezones[t->r.count];
  708. }
  709. z->time = time;
  710. z->offset = offset;
  711. ++t->z.count;
  712. } while(n[0] > 0 && n[1] > 0);
  713. return sdp_token_crlf(sdp);
  714. }
  715. // RFC4566 5.12
  716. // k=<method>
  717. // k=<method>:<encryption key>
  718. // k=clear:<encryption key>
  719. // k=base64:<encoded encryption key>
  720. // k=uri:<URI to obtain key>
  721. // k=prompt
  722. // A key field is permitted before the first media entry (in which case
  723. // it applies to all media in the session), or for each media entry as required.
  724. static int sdp_parse_encryption(struct sdp_t* sdp)
  725. {
  726. int n[2];
  727. struct sdp_encryption *k;
  728. if(sdp->m.count > 0)
  729. {
  730. k = &sdp_get_media(sdp, sdp->m.count-1)->k;
  731. }
  732. else
  733. {
  734. k = &sdp->k;
  735. }
  736. memset(k, 0, sizeof(struct sdp_encryption));
  737. sdp_skip_space(sdp);
  738. k->method = sdp->raw + sdp->offset;
  739. n[0] = sdp_token_word(sdp, ":\r\n");
  740. trim_right(k->method, &n[0]);
  741. if(':' == sdp->raw[sdp->offset])
  742. ++sdp->offset; // skip ':'
  743. sdp_skip_space(sdp);
  744. k->key = sdp->raw + sdp->offset;
  745. n[1] = sdp_token_word(sdp, "\r\n");
  746. trim_right(k->key, &n[1]);
  747. if(0 == sdp_token_crlf(sdp))
  748. {
  749. k->method[n[0]] = '\0';
  750. k->key[n[1]] = '\0';
  751. return 0;
  752. }
  753. return -1;
  754. }
  755. // RFC4566 5.13
  756. // a=<attribute>
  757. // a=<attribute>:<value>
  758. // a=cat:<category>
  759. // a=keywds:<keywords>
  760. // a=tool:<name and version of tool>
  761. // a=ptime:<packet time>
  762. // a=maxptime:<maximum packet time>
  763. // a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
  764. // a=recvonly
  765. // a=sendrecv
  766. // a=sendonly
  767. // a=inactive
  768. // a=orient:<orientation>
  769. // a=type:<conference type>
  770. // a=charset:<character set>
  771. // a=sdplang:<language tag>
  772. // a=lang:<language tag>
  773. // a=framerate:<frame rate>
  774. // a=quality:<quality>
  775. // a=fmtp:<format> <format specific parameters>
  776. static int sdp_parse_attribute(struct sdp_t* sdp)
  777. {
  778. int n[2];
  779. struct attributes *as;
  780. struct sdp_attribute *a;
  781. if(sdp->m.count > 0)
  782. {
  783. as = &sdp_get_media(sdp, sdp->m.count-1)->a;
  784. }
  785. else
  786. {
  787. as = &sdp->a;
  788. }
  789. if(as->count >= N_ATTRIBUTE)
  790. {
  791. if(as->count - N_ATTRIBUTE >= as->capacity)
  792. {
  793. void* ptr;
  794. ptr = (struct sdp_attribute*)realloc(as->ptr, (as->capacity+8)*sizeof(struct sdp_attribute));
  795. if(!ptr)
  796. return -ENOMEM;
  797. as->ptr = ptr;
  798. as->capacity += 8;
  799. }
  800. a = &as->ptr[as->count - N_ATTRIBUTE];
  801. }
  802. else
  803. {
  804. a = &as->attrs[as->count];
  805. }
  806. memset(a, 0, sizeof(struct sdp_attribute));
  807. sdp_skip_space(sdp);
  808. a->name = sdp->raw + sdp->offset;
  809. n[0] = sdp_token_word(sdp, ":\r\n");
  810. trim_right(a->name, &n[0]);
  811. if(':' == sdp->raw[sdp->offset])
  812. ++sdp->offset; // skip ':'
  813. sdp_skip_space(sdp);
  814. a->value = sdp->raw + sdp->offset;
  815. n[1] = sdp_token_word(sdp, "\r\n");
  816. trim_right(a->value, &n[1]);
  817. if(0 == sdp_token_crlf(sdp))
  818. {
  819. ++as->count;
  820. a->name[n[0]] = '\0';
  821. a->value[n[1]] = '\0';
  822. return 0;
  823. }
  824. return -1;
  825. }
  826. static int sdp_append_media_format(struct sdp_media *m, char* fmt)
  827. {
  828. if(m->fmt.count >= N_MEDIA_FORMAT)
  829. {
  830. if(m->fmt.count - N_MEDIA_FORMAT >= m->fmt.capacity)
  831. {
  832. void* ptr;
  833. ptr = (char**)realloc(m->fmt.ptr, (m->fmt.capacity+8)*sizeof(char*));
  834. if(!ptr)
  835. return -ENOMEM;
  836. m->fmt.ptr = ptr;
  837. m->fmt.capacity += 8;
  838. }
  839. m->fmt.ptr[m->fmt.count - N_MEDIA_FORMAT] = fmt;
  840. }
  841. else
  842. {
  843. m->fmt.formats[m->fmt.count] = fmt;
  844. }
  845. ++m->fmt.count;
  846. return 0;
  847. }
  848. // RFC4566 5.14
  849. // m=<media> <port> <proto> <fmt> ...
  850. // media: audio/video/text/application/message
  851. // proto: udp, RTP/AVP, RTP/SAVP
  852. // m=<media> <port>/<number of ports> <proto> <fmt> ...
  853. // m=video 49170/2 RTP/AVP 31
  854. // c=IN IP4 224.2.1.1/127/2
  855. // m=video 49170/2 RTP/AVP 31
  856. static int sdp_parse_media(struct sdp_t* sdp)
  857. {
  858. int ret;
  859. int n[4];
  860. char *fmt;
  861. struct sdp_media *m;
  862. if(sdp->m.count >= N_MEDIA)
  863. {
  864. if(sdp->m.count - N_MEDIA >= sdp->m.capacity)
  865. {
  866. void* ptr;
  867. ptr = (struct sdp_media*)realloc(sdp->m.ptr, (sdp->m.capacity+8)*sizeof(struct sdp_media));
  868. if(!ptr)
  869. return -ENOMEM;
  870. sdp->m.ptr = ptr;
  871. sdp->m.capacity += 8;
  872. }
  873. m = &sdp->m.ptr[sdp->m.count - N_MEDIA];
  874. }
  875. else
  876. {
  877. m = &sdp->m.medias[sdp->m.count];
  878. }
  879. memset(m, 0, sizeof(struct sdp_media));
  880. sdp_skip_space(sdp);
  881. m->media = sdp->raw + sdp->offset;
  882. n[0] = sdp_token_word(sdp, " \t\r\n");
  883. sdp_skip_space(sdp);
  884. m->port = sdp->raw + sdp->offset;
  885. n[1] = sdp_token_word(sdp, " \t\r\n");
  886. sdp_skip_space(sdp);
  887. m->proto = sdp->raw + sdp->offset;
  888. n[2] = sdp_token_word(sdp, " \t\r\n");
  889. sdp_skip_space(sdp);
  890. fmt = sdp->raw + sdp->offset;
  891. n[3] = sdp_token_word(sdp, " \t\r\n");
  892. while (' ' == fmt[n[3]] || '\t' == fmt[n[3]])
  893. {
  894. fmt[n[3]] = '\0';
  895. ret = sdp_append_media_format(m, fmt);
  896. if(0 != ret)
  897. return ret;
  898. sdp->offset += 1; // skip '\0'
  899. sdp_skip_space(sdp);
  900. fmt = sdp->raw + sdp->offset;
  901. n[3] = sdp_token_word(sdp, " \t\r\n");
  902. }
  903. if(0 == sdp_token_crlf(sdp))
  904. {
  905. m->media[n[0]] = '\0';
  906. m->port[n[1]] = '\0';
  907. m->proto[n[2]] = '\0';
  908. if(n[3] > 0)
  909. {
  910. fmt[n[3]] = '\0';
  911. ret = sdp_append_media_format(m, fmt);
  912. if(0 != ret)
  913. return ret;
  914. }
  915. ++sdp->m.count;
  916. return 0;
  917. }
  918. return -1;
  919. }
  920. // gb28181 extension
  921. static int sdp_parse_gb28181_ssrc(struct sdp_t* sdp)
  922. {
  923. int n;
  924. struct attributes* as;
  925. struct sdp_attribute* a;
  926. if (sdp->m.count > 0)
  927. {
  928. as = &sdp_get_media(sdp, sdp->m.count - 1)->a;
  929. }
  930. else
  931. {
  932. as = &sdp->a;
  933. }
  934. if (as->count >= N_ATTRIBUTE)
  935. {
  936. if (as->count - N_ATTRIBUTE >= as->capacity)
  937. {
  938. void* ptr;
  939. ptr = (struct sdp_attribute*)realloc(as->ptr, (as->capacity + 8) * sizeof(struct sdp_attribute));
  940. if (!ptr)
  941. return -ENOMEM;
  942. as->ptr = ptr;
  943. as->capacity += 8;
  944. }
  945. a = &as->ptr[as->count - N_ATTRIBUTE];
  946. }
  947. else
  948. {
  949. a = &as->attrs[as->count];
  950. }
  951. memset(a, 0, sizeof(struct sdp_attribute));
  952. a->name = "ssrc";
  953. a->value = sdp->raw + sdp->offset;
  954. n = sdp_token_word(sdp, "\r\n");
  955. if (0 != sdp_token_crlf(sdp))
  956. return -1;
  957. a->value[n] = '\0';
  958. ++as->count;
  959. return 0;
  960. }
  961. static void* sdp_create(const char* s, int len)
  962. {
  963. struct sdp_t *sdp;
  964. sdp = (struct sdp_t*)malloc(sizeof(struct sdp_t) + len + 1);
  965. if( !sdp )
  966. return NULL;
  967. memset(sdp, 0, sizeof(struct sdp_t));
  968. sdp->raw = (char*)(sdp + 1);
  969. memcpy(sdp->raw, s, len);
  970. sdp->raw[len] = 0;
  971. return sdp;
  972. }
  973. void sdp_destroy(struct sdp_t* sdp)
  974. {
  975. int i;
  976. struct sdp_media *m;
  977. struct sdp_timing *t;
  978. if(sdp->e.count > N_EMAIL)
  979. free(sdp->e.ptr);
  980. if(sdp->p.count > N_PHONE)
  981. free(sdp->p.ptr);
  982. if(sdp->b.count > N_BANDWIDTH)
  983. free(sdp->b.ptr);
  984. for(i = 0; i < sdp->t.count; i++)
  985. {
  986. t = sdp_get_timing(sdp, i);
  987. if(t->r.count > N_REPEAT)
  988. free(t->r.ptr);
  989. if(t->z.count > N_TIMEZONE)
  990. free(t->z.ptr);
  991. }
  992. if(sdp->t.count > N_TIMING)
  993. free(sdp->t.ptr);
  994. if(sdp->a.count > N_ATTRIBUTE)
  995. free(sdp->a.ptr);
  996. for(i = 0; i < sdp->m.count; i++)
  997. {
  998. m = sdp_get_media(sdp, i);
  999. if(m->fmt.count > N_MEDIA_FORMAT)
  1000. free(m->fmt.ptr);
  1001. if(m->a.count > N_ATTRIBUTE)
  1002. free(m->a.ptr);
  1003. if(m->c.count > N_CONNECTION)
  1004. free(m->c.ptr);
  1005. if (m->b.count > N_BANDWIDTH)
  1006. free(m->b.ptr);
  1007. }
  1008. if(sdp->m.count > N_MEDIA)
  1009. free(sdp->m.ptr);
  1010. free(sdp);
  1011. }
  1012. struct sdp_t* sdp_parse(const char* s, int len)
  1013. {
  1014. int r;
  1015. char c;
  1016. struct sdp_t *sdp;
  1017. assert(s);
  1018. sdp = (struct sdp_t*)sdp_create(s, len);
  1019. if(!sdp)
  1020. return NULL;
  1021. while(sdp->raw[sdp->offset] && !strchr("\r\n", sdp->raw[sdp->offset]))
  1022. {
  1023. sdp_skip_space(sdp);
  1024. c = sdp->raw[sdp->offset++];
  1025. sdp_skip_space(sdp);
  1026. if('=' != sdp->raw[sdp->offset++])
  1027. goto parse_failed;
  1028. sdp_skip_space(sdp);
  1029. switch(c)
  1030. {
  1031. case 'v':
  1032. r = sdp_parse_version(sdp);
  1033. break;
  1034. case 'o':
  1035. r = sdp_parse_origin(sdp);
  1036. break;
  1037. case 's':
  1038. r = sdp_parse_session(sdp);
  1039. break;
  1040. case 'i':
  1041. r = sdp_parse_information(sdp);
  1042. break;
  1043. case 'u':
  1044. r = sdp_parse_uri(sdp);
  1045. break;
  1046. case 'e':
  1047. r = sdp_parse_email(sdp);
  1048. break;
  1049. case 'p':
  1050. r = sdp_parse_phone(sdp);
  1051. break;
  1052. case 'c':
  1053. r = sdp_parse_connection(sdp);
  1054. break;
  1055. case 'b':
  1056. r = sdp_parse_bandwidth(sdp);
  1057. break;
  1058. case 't':
  1059. r = sdp_parse_timing(sdp);
  1060. break;
  1061. case 'r':
  1062. r = sdp_parse_repeat(sdp);
  1063. break;
  1064. case 'z':
  1065. r = sdp_parse_timezone(sdp);
  1066. break;
  1067. case 'k':
  1068. r = sdp_parse_encryption(sdp);
  1069. break;
  1070. case 'a':
  1071. r = sdp_parse_attribute(sdp);
  1072. break;
  1073. case 'm':
  1074. r = sdp_parse_media(sdp);
  1075. break;
  1076. case 'y':
  1077. r = sdp_parse_gb28181_ssrc(sdp);
  1078. break;
  1079. default:
  1080. // unknown sdp
  1081. sdp_token_word(sdp, "\r\n");
  1082. r = sdp_token_crlf(sdp);
  1083. break;
  1084. }
  1085. if(0 != r)
  1086. goto parse_failed;
  1087. }
  1088. return sdp;
  1089. parse_failed:
  1090. sdp_destroy(sdp);
  1091. return NULL;
  1092. }
  1093. int sdp_version_get(struct sdp_t* sdp)
  1094. {
  1095. return sdp->v;
  1096. }
  1097. //void sdp_version_set(struct sdp_t* sdp, int version)
  1098. //{
  1099. // struct sdp_t *sdp;
  1100. // sdp = (struct sdp_t*)sdp;
  1101. // sdp->v = version;
  1102. //}
  1103. int sdp_origin_get(struct sdp_t* sdp, const char **username, const char** session, const char** version, const char** network, const char** addrtype, const char** address)
  1104. {
  1105. if(sdp->o.username && sdp->o.session && sdp->o.session_version
  1106. && sdp->o.c.network && sdp->o.c.addrtype && sdp->o.c.address)
  1107. {
  1108. *username = sdp->o.username;
  1109. *session = sdp->o.session;
  1110. *version = sdp->o.session_version;
  1111. *network = sdp->o.c.network;
  1112. *addrtype = sdp->o.c.addrtype;
  1113. *address = sdp->o.c.address;
  1114. return 0;
  1115. }
  1116. return -1;
  1117. }
  1118. int sdp_origin_get_network(struct sdp_t* sdp)
  1119. {
  1120. if(0 == strcasecmp("IN", sdp->o.c.network))
  1121. return SDP_C_NETWORK_IN;
  1122. return SDP_C_NETWORK_UNKNOWN;
  1123. }
  1124. int sdp_origin_get_addrtype(struct sdp_t* sdp)
  1125. {
  1126. if(0 == strcasecmp("IP4", sdp->o.c.addrtype))
  1127. return SDP_C_ADDRESS_IP4;
  1128. if(0 == strcasecmp("IP6", sdp->o.c.addrtype))
  1129. return SDP_C_ADDRESS_IP6;
  1130. return SDP_C_ADDRESS_UNKNOWN;
  1131. }
  1132. const char* sdp_session_get_name(struct sdp_t* sdp)
  1133. {
  1134. return sdp->s;
  1135. }
  1136. const char* sdp_session_get_information(struct sdp_t* sdp)
  1137. {
  1138. return sdp->i;
  1139. }
  1140. const char* sdp_uri_get(struct sdp_t* sdp)
  1141. {
  1142. return sdp->u;
  1143. }
  1144. int sdp_email_count(struct sdp_t* sdp)
  1145. {
  1146. return sdp->e.count;
  1147. }
  1148. const char* sdp_email_get(struct sdp_t* sdp, int idx)
  1149. {
  1150. if(idx >= sdp->e.count || idx < 0)
  1151. return NULL;
  1152. return idx < N_EMAIL ? sdp->e.emails[idx].email : sdp->e.ptr[idx - N_EMAIL].email;
  1153. }
  1154. int sdp_phone_count(struct sdp_t* sdp)
  1155. {
  1156. return sdp->p.count;
  1157. }
  1158. const char* sdp_phone_get(struct sdp_t* sdp, int idx)
  1159. {
  1160. if(idx >= sdp->p.count || idx < 0)
  1161. return NULL;
  1162. return idx < N_PHONE ? sdp->p.phones[idx].phone : sdp->p.ptr[idx - N_PHONE].phone;
  1163. }
  1164. int sdp_connection_get(struct sdp_t* sdp, const char** network, const char** addrtype, const char** address)
  1165. {
  1166. if(sdp->c.network && sdp->c.addrtype && sdp->c.address)
  1167. {
  1168. *network = sdp->c.network;
  1169. *addrtype = sdp->c.addrtype;
  1170. *address = sdp->c.address;
  1171. return 0;
  1172. }
  1173. return -1;
  1174. }
  1175. int sdp_connection_get_address(struct sdp_t* sdp, char* ip, int bytes)
  1176. {
  1177. const char* p;
  1178. if(sdp->c.address && bytes > 0)
  1179. {
  1180. p = sdp->c.address;
  1181. while(*p && '/' != *p && bytes > 1)
  1182. {
  1183. *ip++ = *p;
  1184. --bytes;
  1185. }
  1186. if(0 == *p || '/' == *p)
  1187. {
  1188. *ip = '\0';
  1189. return 0;
  1190. }
  1191. }
  1192. return -1;
  1193. }
  1194. int sdp_connection_get_network(struct sdp_t* sdp)
  1195. {
  1196. if(0 == strcasecmp("IN", sdp->c.network))
  1197. return SDP_C_NETWORK_IN;
  1198. return SDP_C_NETWORK_UNKNOWN;
  1199. }
  1200. int sdp_connection_get_addrtype(struct sdp_t* sdp)
  1201. {
  1202. if(0 == strcasecmp("IP4", sdp->c.addrtype))
  1203. return SDP_C_ADDRESS_IP4;
  1204. if(0 == strcasecmp("IP6", sdp->c.addrtype))
  1205. return SDP_C_ADDRESS_IP6;
  1206. return SDP_C_ADDRESS_UNKNOWN;
  1207. }
  1208. int sdp_bandwidth_count(struct sdp_t* sdp)
  1209. {
  1210. return sdp->b.count;
  1211. }
  1212. const char* sdp_bandwidth_get_type(struct sdp_t* sdp, int idx)
  1213. {
  1214. if(idx >= (int)sdp->b.count || idx < 0)
  1215. return NULL;
  1216. return idx < N_BANDWIDTH ? sdp->b.bandwidths[idx].bwtype : sdp->b.ptr[idx - N_BANDWIDTH].bwtype;
  1217. }
  1218. int sdp_bandwidth_get_value(struct sdp_t* sdp, int idx)
  1219. {
  1220. const char* b;
  1221. if(idx >= (int)sdp->b.count || idx < 0)
  1222. return -1;
  1223. b = idx < N_BANDWIDTH ? sdp->b.bandwidths[idx].bandwidth : sdp->b.ptr[idx - N_BANDWIDTH].bandwidth;
  1224. return atoi(b);
  1225. }
  1226. int sdp_timing_count(struct sdp_t* sdp)
  1227. {
  1228. return sdp->t.count;
  1229. }
  1230. int sdp_timing_get(sdp_t* sdp, int idx, const char** start, const char** stop)
  1231. {
  1232. struct sdp_timing* t;
  1233. t = sdp_get_timing(sdp, idx);
  1234. if (NULL == t)
  1235. return -1;
  1236. *start = t->start;
  1237. *stop = t->stop;
  1238. return 0;
  1239. }
  1240. int sdp_timing_repeat_count(sdp_t* sdp, int idx)
  1241. {
  1242. struct sdp_timing* t;
  1243. t = sdp_get_timing(sdp, idx);
  1244. return t ? t->r.count : -1;
  1245. }
  1246. int sdp_timing_timezone_count(sdp_t* sdp, int idx)
  1247. {
  1248. struct sdp_timing* t;
  1249. t = sdp_get_timing(sdp, idx);
  1250. return t ? t->z.count : -1;
  1251. }
  1252. int sdp_media_count(struct sdp_t* sdp)
  1253. {
  1254. return sdp->m.count;
  1255. }
  1256. const char* sdp_media_type(struct sdp_t* sdp, int media)
  1257. {
  1258. struct sdp_media *m;
  1259. m = sdp_get_media(sdp, media);
  1260. return m ? m->media : NULL;
  1261. }
  1262. int sdp_media_port(struct sdp_t* sdp, int media, int port[], int num)
  1263. {
  1264. int i, n;
  1265. const char* p;
  1266. struct sdp_media *m;
  1267. m = sdp_get_media(sdp, media);
  1268. if (!m || !port)
  1269. return -1;
  1270. p = strchr(m->port, '/');
  1271. port[0] = atoi(m->port);
  1272. n = atoi(p ? p + 1 : "1");
  1273. for (i = 1; i < num && i < n; i++)
  1274. port[i] = port[0] + i;
  1275. return i;
  1276. }
  1277. const char* sdp_media_proto(struct sdp_t* sdp, int media)
  1278. {
  1279. struct sdp_media *m;
  1280. m = sdp_get_media(sdp, media);
  1281. return m ? m->proto : NULL;
  1282. }
  1283. // rfc 4566 5.14. Media Descriptions ("m=")
  1284. // (p24) If the <proto> sub-field is "udp" the <fmt> sub-fields MUST
  1285. // reference a media type describing the format under the "audio",
  1286. // "video", "text", "application", or "message" top-level media types.
  1287. static inline int sdp_media_format_value(const char* format)
  1288. {
  1289. switch(format[0])
  1290. {
  1291. case 'a': return ('u' == format[1]) ? SDP_M_MEDIA_AUDIO : SDP_M_MEDIA_APPLICATION;
  1292. case 'v': return SDP_M_MEDIA_VIDEO;
  1293. case 't': return SDP_M_MEDIA_TEXT;
  1294. case 'm': return SDP_M_MEDIA_MESSAGE;
  1295. default: return atoi(format);
  1296. }
  1297. //if(0 == strcasecmp("video", format))
  1298. // return SDP_M_MEDIA_VIDEO;
  1299. //else if(0 == strcasecmp("audio", format))
  1300. // return SDP_M_MEDIA_AUDIO;
  1301. //else if(0 == strcasecmp("text", format))
  1302. // return SDP_M_MEDIA_TEXT;
  1303. //else if(0 == strcasecmp("application", format))
  1304. // return SDP_M_MEDIA_APPLICATION;
  1305. //else if(0 == strcasecmp("message", format))
  1306. // return SDP_M_MEDIA_MESSAGE;
  1307. //else
  1308. // return atoi(format);
  1309. }
  1310. int sdp_media_formats(struct sdp_t* sdp, int media, int *formats, int count)
  1311. {
  1312. int i;
  1313. struct sdp_media *m;
  1314. m = sdp_get_media(sdp, media);
  1315. if(!m)
  1316. return -1;
  1317. for(i = 0; i < count && i < m->fmt.count; i++)
  1318. {
  1319. if(i < N_MEDIA_FORMAT)
  1320. formats[i] = sdp_media_format_value(m->fmt.formats[i]);
  1321. else
  1322. formats[i] = sdp_media_format_value(m->fmt.ptr[i-N_MEDIA_FORMAT]);
  1323. }
  1324. return (int)m->fmt.count;
  1325. }
  1326. int sdp_media_get_connection(sdp_t* sdp, int media, const char** network, const char** addrtype, const char** address)
  1327. {
  1328. struct sdp_media *m;
  1329. struct sdp_connection *conn;
  1330. m = sdp_get_media(sdp, media);
  1331. if(m && m->c.count > 0)
  1332. conn = &m->c.connections[0];
  1333. else
  1334. conn = &sdp->c;
  1335. if(conn && conn->network && conn->addrtype && conn->address)
  1336. {
  1337. *network = conn->network;
  1338. *addrtype = conn->addrtype;
  1339. *address = conn->address;
  1340. return 0;
  1341. }
  1342. return -1;
  1343. }
  1344. int sdp_media_get_connection_address(struct sdp_t* sdp, int media, char* ip, int bytes)
  1345. {
  1346. const char* p;
  1347. struct sdp_media *m;
  1348. struct sdp_connection *conn;
  1349. m = sdp_get_media(sdp, media);
  1350. if(m && m->c.count > 0)
  1351. conn = &m->c.connections[0];
  1352. else
  1353. conn = &sdp->c;
  1354. if(conn->address && bytes > 0)
  1355. {
  1356. p = conn->address;
  1357. while(*p && '/' != *p && bytes > 1)
  1358. {
  1359. *ip++ = *p;
  1360. --bytes;
  1361. }
  1362. if(0 == *p || '/' == *p)
  1363. {
  1364. *ip = '\0';
  1365. return 0;
  1366. }
  1367. }
  1368. return -1;
  1369. }
  1370. int sdp_media_get_connection_network(struct sdp_t* sdp, int media)
  1371. {
  1372. struct sdp_media *m;
  1373. struct sdp_connection *conn;
  1374. m = sdp_get_media(sdp, media);
  1375. if(m && m->c.count > 0)
  1376. conn = &m->c.connections[0];
  1377. else
  1378. conn = &sdp->c;
  1379. if(conn->network)
  1380. {
  1381. if(0 == strcasecmp("IN", conn->network))
  1382. return SDP_C_NETWORK_IN;
  1383. }
  1384. return SDP_C_NETWORK_UNKNOWN;
  1385. }
  1386. int sdp_media_get_connection_addrtype(struct sdp_t* sdp, int media)
  1387. {
  1388. struct sdp_media *m;
  1389. struct sdp_connection *conn;
  1390. m = sdp_get_media(sdp, media);
  1391. if(m && m->c.count > 0)
  1392. conn = &m->c.connections[0];
  1393. else
  1394. conn = &sdp->c;
  1395. if(conn->addrtype)
  1396. {
  1397. if(0 == strcasecmp("IP4", conn->addrtype))
  1398. return SDP_C_ADDRESS_IP4;
  1399. if(0 == strcasecmp("IP6", conn->addrtype))
  1400. return SDP_C_ADDRESS_IP6;
  1401. }
  1402. return SDP_C_ADDRESS_UNKNOWN;
  1403. }
  1404. int sdp_media_bandwidth_count(struct sdp_t* sdp, int media)
  1405. {
  1406. struct sdp_media *m;
  1407. m = sdp_get_media(sdp, media);
  1408. if(!m)
  1409. return 0;
  1410. return m->b.count;
  1411. }
  1412. const char* sdp_media_bandwidth_get_type(struct sdp_t* sdp, int media, int idx)
  1413. {
  1414. struct sdp_media *m;
  1415. m = sdp_get_media(sdp, media);
  1416. if(!m)
  1417. return NULL;
  1418. if(idx >= (int)m->b.count || idx < 0)
  1419. return NULL;
  1420. return idx < N_BANDWIDTH ? m->b.bandwidths[idx].bwtype : m->b.ptr[idx - N_BANDWIDTH].bwtype;
  1421. }
  1422. int sdp_media_bandwidth_get_value(struct sdp_t* sdp, int media, int idx)
  1423. {
  1424. const char* b;
  1425. struct sdp_media *m;
  1426. m = sdp_get_media(sdp, media);
  1427. if(!m)
  1428. return -1;
  1429. if(idx >= (int)m->b.count || idx < 0)
  1430. return -1;
  1431. b = idx < N_BANDWIDTH ? m->b.bandwidths[idx].bandwidth : m->b.ptr[idx - N_BANDWIDTH].bandwidth;
  1432. return atoi(b);
  1433. }
  1434. int sdp_attribute_count(struct sdp_t* sdp)
  1435. {
  1436. return sdp->a.count;
  1437. }
  1438. int sdp_attribute_get(struct sdp_t* sdp, int idx, const char** name, const char** value)
  1439. {
  1440. struct sdp_attribute *attr;
  1441. if(idx < 0 || idx > sdp->a.count)
  1442. return -1; // not found
  1443. if(idx < N_ATTRIBUTE)
  1444. attr = sdp->a.attrs + idx;
  1445. else
  1446. attr = sdp->a.ptr + idx - N_ATTRIBUTE;
  1447. *name = attr->name;
  1448. *value = attr->value;
  1449. return 0;
  1450. }
  1451. static const char* sdp_attribute_find_impl(const struct attributes* a, const char* name)
  1452. {
  1453. int i;
  1454. const struct sdp_attribute* attr;
  1455. for (i = 0; name && i < a->count; i++)
  1456. {
  1457. if (i < N_ATTRIBUTE)
  1458. attr = a->attrs + i;
  1459. else
  1460. attr = a->ptr + i - N_ATTRIBUTE;
  1461. if (attr->name && 0 == strcmp(attr->name, name))
  1462. return attr->value;
  1463. }
  1464. return NULL;
  1465. }
  1466. static int sdp_attribute_list_impl(const struct attributes* a, const char* name, void (*onattr)(void* param, const char* name, const char* value), void* param)
  1467. {
  1468. int i;
  1469. const struct sdp_attribute* attr;
  1470. for (i = 0; i < a->count; i++)
  1471. {
  1472. if (i < N_ATTRIBUTE)
  1473. attr = a->attrs + i;
  1474. else
  1475. attr = a->ptr + i - N_ATTRIBUTE;
  1476. if (!name || (attr->name && 0 == strcmp(attr->name, name)))
  1477. onattr(param, attr->name, attr->value);
  1478. }
  1479. return 0;
  1480. }
  1481. const char* sdp_media_attribute_find(struct sdp_t* sdp, int media, const char* name)
  1482. {
  1483. struct sdp_media* m;
  1484. m = sdp_get_media(sdp, media);
  1485. return m ? sdp_attribute_find_impl(&m->a, name) : NULL;
  1486. }
  1487. int sdp_media_attribute_list(struct sdp_t* sdp, int media, const char* name, void (*onattr)(void* param, const char* name, const char* value), void* param)
  1488. {
  1489. struct sdp_media* m;
  1490. m = sdp_get_media(sdp, media);
  1491. return m ? sdp_attribute_list_impl(&m->a, name, onattr, param) : -1;
  1492. }
  1493. const char* sdp_attribute_find(struct sdp_t* sdp, const char* name)
  1494. {
  1495. return sdp_attribute_find_impl(&sdp->a, name);
  1496. }
  1497. int sdp_attribute_list(struct sdp_t* sdp, const char* name, void (*onattr)(void* param, const char* name, const char* value), void* param)
  1498. {
  1499. return sdp_attribute_list_impl(&sdp->a, name, onattr, param);
  1500. }
  1501. static int sdp_attribute_mode(struct attributes* a)
  1502. {
  1503. static const int values[] = { SDP_A_SENDRECV, SDP_A_SENDONLY, SDP_A_RECVONLY, SDP_A_INACTIVE };
  1504. static const char* strings[] = { "sendrecv", "sendonly", "recvonly", "inactive" };
  1505. int i, j;
  1506. const struct sdp_attribute *attr;
  1507. for (i = 0; i < a->count; i++)
  1508. {
  1509. if (i < N_ATTRIBUTE)
  1510. attr = a->attrs + i;
  1511. else
  1512. attr = a->ptr + i - N_ATTRIBUTE;
  1513. for (j = 0; j < sizeof(values) / sizeof(values[0]); j++)
  1514. {
  1515. if (attr->name && 0 == strcmp(strings[j], attr->name))
  1516. return values[j];
  1517. }
  1518. }
  1519. return -1;
  1520. }
  1521. int sdp_media_mode(struct sdp_t* sdp, int media)
  1522. {
  1523. int mode;
  1524. struct sdp_media *m;
  1525. m = sdp_get_media(sdp, media);
  1526. mode = m ? sdp_attribute_mode(&m->a) : -1;
  1527. mode = -1 == mode ? sdp_attribute_mode(&sdp->a) : mode;
  1528. return -1 == mode ? SDP_A_SENDRECV : mode; // default SDP_A_SENDRECV
  1529. }