amf.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275
  1. /*
  2. * Copyright (C) 2005-2008 Team XBMC
  3. * http://www.xbmc.org
  4. * Copyright (C) 2008-2009 Andrej Stepanchuk
  5. * Copyright (C) 2009-2010 Howard Chu
  6. *
  7. * This file is part of librtmp.
  8. *
  9. * librtmp is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as
  11. * published by the Free Software Foundation; either version 2.1,
  12. * or (at your option) any later version.
  13. *
  14. * librtmp is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with librtmp see the file COPYING. If not, write to
  21. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  22. * Boston, MA 02110-1301, USA.
  23. * http://www.gnu.org/copyleft/lgpl.html
  24. */
  25. #include "rtmp_sys.h"
  26. #include "amf.h"
  27. #include "log.h"
  28. #include "bytes.h"
  29. static const AMFObjectProperty AMFProp_Invalid = { {0, 0}, AMF_INVALID };
  30. static const AVal AV_empty = { 0, 0 };
  31. /* Data is Big-Endian */
  32. unsigned short
  33. AMF_DecodeInt16(const char *data)
  34. {
  35. unsigned char *c = (unsigned char *) data;
  36. unsigned short val;
  37. val = (c[0] << 8) | c[1];
  38. return val;
  39. }
  40. unsigned int
  41. AMF_DecodeInt24(const char *data)
  42. {
  43. unsigned char *c = (unsigned char *) data;
  44. unsigned int val;
  45. val = (c[0] << 16) | (c[1] << 8) | c[2];
  46. return val;
  47. }
  48. unsigned int
  49. AMF_DecodeInt32(const char *data)
  50. {
  51. unsigned char *c = (unsigned char *)data;
  52. unsigned int val;
  53. val = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
  54. return val;
  55. }
  56. void
  57. AMF_DecodeString(const char *data, AVal *bv)
  58. {
  59. bv->av_len = AMF_DecodeInt16(data);
  60. bv->av_val = (bv->av_len > 0) ? (char *)data + 2 : NULL;
  61. }
  62. void
  63. AMF_DecodeLongString(const char *data, AVal *bv)
  64. {
  65. bv->av_len = AMF_DecodeInt32(data);
  66. bv->av_val = (bv->av_len > 0) ? (char *)data + 4 : NULL;
  67. }
  68. double
  69. AMF_DecodeNumber(const char *data)
  70. {
  71. double dVal;
  72. #if __FLOAT_WORD_ORDER == __BYTE_ORDER
  73. #if __BYTE_ORDER == __BIG_ENDIAN
  74. memcpy(&dVal, data, 8);
  75. #elif __BYTE_ORDER == __LITTLE_ENDIAN
  76. unsigned char *ci, *co;
  77. ci = (unsigned char *)data;
  78. co = (unsigned char *)&dVal;
  79. co[0] = ci[7];
  80. co[1] = ci[6];
  81. co[2] = ci[5];
  82. co[3] = ci[4];
  83. co[4] = ci[3];
  84. co[5] = ci[2];
  85. co[6] = ci[1];
  86. co[7] = ci[0];
  87. #endif
  88. #else
  89. #if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */
  90. unsigned char *ci, *co;
  91. ci = (unsigned char *)data;
  92. co = (unsigned char *)&dVal;
  93. co[0] = ci[3];
  94. co[1] = ci[2];
  95. co[2] = ci[1];
  96. co[3] = ci[0];
  97. co[4] = ci[7];
  98. co[5] = ci[6];
  99. co[6] = ci[5];
  100. co[7] = ci[4];
  101. #else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */
  102. unsigned char *ci, *co;
  103. ci = (unsigned char *)data;
  104. co = (unsigned char *)&dVal;
  105. co[0] = ci[4];
  106. co[1] = ci[5];
  107. co[2] = ci[6];
  108. co[3] = ci[7];
  109. co[4] = ci[0];
  110. co[5] = ci[1];
  111. co[6] = ci[2];
  112. co[7] = ci[3];
  113. #endif
  114. #endif
  115. return dVal;
  116. }
  117. int
  118. AMF_DecodeBoolean(const char *data)
  119. {
  120. return *data != 0;
  121. }
  122. char *
  123. AMF_EncodeInt16(char *output, char *outend, short nVal)
  124. {
  125. if (output+2 > outend)
  126. return NULL;
  127. output[1] = nVal & 0xff;
  128. output[0] = nVal >> 8;
  129. return output+2;
  130. }
  131. char *
  132. AMF_EncodeInt24(char *output, char *outend, int nVal)
  133. {
  134. if (output+3 > outend)
  135. return NULL;
  136. output[2] = nVal & 0xff;
  137. output[1] = nVal >> 8;
  138. output[0] = nVal >> 16;
  139. return output+3;
  140. }
  141. char *
  142. AMF_EncodeInt32(char *output, char *outend, int nVal)
  143. {
  144. if (output+4 > outend)
  145. return NULL;
  146. output[3] = nVal & 0xff;
  147. output[2] = nVal >> 8;
  148. output[1] = nVal >> 16;
  149. output[0] = nVal >> 24;
  150. return output+4;
  151. }
  152. char *
  153. AMF_EncodeString(char *output, char *outend, const AVal *bv)
  154. {
  155. if ((bv->av_len < 65536 && output + 1 + 2 + bv->av_len > outend) ||
  156. output + 1 + 4 + bv->av_len > outend)
  157. return NULL;
  158. if (bv->av_len < 65536)
  159. {
  160. *output++ = AMF_STRING;
  161. output = AMF_EncodeInt16(output, outend, bv->av_len);
  162. }
  163. else
  164. {
  165. *output++ = AMF_LONG_STRING;
  166. output = AMF_EncodeInt32(output, outend, bv->av_len);
  167. }
  168. memcpy(output, bv->av_val, bv->av_len);
  169. output += bv->av_len;
  170. return output;
  171. }
  172. char *
  173. AMF_EncodeNumber(char *output, char *outend, double dVal)
  174. {
  175. if (output+1+8 > outend)
  176. return NULL;
  177. *output++ = AMF_NUMBER; /* type: Number */
  178. #if __FLOAT_WORD_ORDER == __BYTE_ORDER
  179. #if __BYTE_ORDER == __BIG_ENDIAN
  180. memcpy(output, &dVal, 8);
  181. #elif __BYTE_ORDER == __LITTLE_ENDIAN
  182. {
  183. unsigned char *ci, *co;
  184. ci = (unsigned char *)&dVal;
  185. co = (unsigned char *)output;
  186. co[0] = ci[7];
  187. co[1] = ci[6];
  188. co[2] = ci[5];
  189. co[3] = ci[4];
  190. co[4] = ci[3];
  191. co[5] = ci[2];
  192. co[6] = ci[1];
  193. co[7] = ci[0];
  194. }
  195. #endif
  196. #else
  197. #if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */
  198. {
  199. unsigned char *ci, *co;
  200. ci = (unsigned char *)&dVal;
  201. co = (unsigned char *)output;
  202. co[0] = ci[3];
  203. co[1] = ci[2];
  204. co[2] = ci[1];
  205. co[3] = ci[0];
  206. co[4] = ci[7];
  207. co[5] = ci[6];
  208. co[6] = ci[5];
  209. co[7] = ci[4];
  210. }
  211. #else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */
  212. {
  213. unsigned char *ci, *co;
  214. ci = (unsigned char *)&dVal;
  215. co = (unsigned char *)output;
  216. co[0] = ci[4];
  217. co[1] = ci[5];
  218. co[2] = ci[6];
  219. co[3] = ci[7];
  220. co[4] = ci[0];
  221. co[5] = ci[1];
  222. co[6] = ci[2];
  223. co[7] = ci[3];
  224. }
  225. #endif
  226. #endif
  227. return output+8;
  228. }
  229. char *
  230. AMF_EncodeBoolean(char *output, char *outend, int bVal)
  231. {
  232. if (output+2 > outend)
  233. return NULL;
  234. *output++ = AMF_BOOLEAN;
  235. *output++ = bVal ? 0x01 : 0x00;
  236. return output;
  237. }
  238. char *
  239. AMF_EncodeNamedString(char *output, char *outend, const AVal *strName, const AVal *strValue)
  240. {
  241. if (output+2+strName->av_len > outend)
  242. return NULL;
  243. output = AMF_EncodeInt16(output, outend, strName->av_len);
  244. memcpy(output, strName->av_val, strName->av_len);
  245. output += strName->av_len;
  246. return AMF_EncodeString(output, outend, strValue);
  247. }
  248. char *
  249. AMF_EncodeNamedNumber(char *output, char *outend, const AVal *strName, double dVal)
  250. {
  251. if (output+2+strName->av_len > outend)
  252. return NULL;
  253. output = AMF_EncodeInt16(output, outend, strName->av_len);
  254. memcpy(output, strName->av_val, strName->av_len);
  255. output += strName->av_len;
  256. return AMF_EncodeNumber(output, outend, dVal);
  257. }
  258. char *
  259. AMF_EncodeNamedBoolean(char *output, char *outend, const AVal *strName, int bVal)
  260. {
  261. if (output+2+strName->av_len > outend)
  262. return NULL;
  263. output = AMF_EncodeInt16(output, outend, strName->av_len);
  264. memcpy(output, strName->av_val, strName->av_len);
  265. output += strName->av_len;
  266. return AMF_EncodeBoolean(output, outend, bVal);
  267. }
  268. void
  269. AMFProp_GetName(AMFObjectProperty *prop, AVal *name)
  270. {
  271. *name = prop->p_name;
  272. }
  273. void
  274. AMFProp_SetName(AMFObjectProperty *prop, AVal *name)
  275. {
  276. prop->p_name = *name;
  277. }
  278. AMFDataType
  279. AMFProp_GetType(AMFObjectProperty *prop)
  280. {
  281. return prop->p_type;
  282. }
  283. double
  284. AMFProp_GetNumber(AMFObjectProperty *prop)
  285. {
  286. return prop->p_vu.p_number;
  287. }
  288. int
  289. AMFProp_GetBoolean(AMFObjectProperty *prop)
  290. {
  291. return prop->p_vu.p_number != 0;
  292. }
  293. void
  294. AMFProp_GetString(AMFObjectProperty *prop, AVal *str)
  295. {
  296. *str = prop->p_vu.p_aval;
  297. }
  298. void
  299. AMFProp_GetObject(AMFObjectProperty *prop, AMFObject *obj)
  300. {
  301. *obj = prop->p_vu.p_object;
  302. }
  303. int
  304. AMFProp_IsValid(AMFObjectProperty *prop)
  305. {
  306. return prop->p_type != AMF_INVALID;
  307. }
  308. char *
  309. AMFProp_Encode(AMFObjectProperty *prop, char *pBuffer, char *pBufEnd)
  310. {
  311. if (prop->p_type == AMF_INVALID)
  312. return NULL;
  313. if (prop->p_type != AMF_NULL && pBuffer + prop->p_name.av_len + 2 + 1 >= pBufEnd)
  314. return NULL;
  315. if (prop->p_type != AMF_NULL && prop->p_name.av_len)
  316. {
  317. *pBuffer++ = prop->p_name.av_len >> 8;
  318. *pBuffer++ = prop->p_name.av_len & 0xff;
  319. memcpy(pBuffer, prop->p_name.av_val, prop->p_name.av_len);
  320. pBuffer += prop->p_name.av_len;
  321. }
  322. switch (prop->p_type)
  323. {
  324. case AMF_NUMBER:
  325. pBuffer = AMF_EncodeNumber(pBuffer, pBufEnd, prop->p_vu.p_number);
  326. break;
  327. case AMF_BOOLEAN:
  328. pBuffer = AMF_EncodeBoolean(pBuffer, pBufEnd, prop->p_vu.p_number != 0);
  329. break;
  330. case AMF_STRING:
  331. pBuffer = AMF_EncodeString(pBuffer, pBufEnd, &prop->p_vu.p_aval);
  332. break;
  333. case AMF_NULL:
  334. if (pBuffer+1 >= pBufEnd)
  335. return NULL;
  336. *pBuffer++ = AMF_NULL;
  337. break;
  338. case AMF_OBJECT:
  339. pBuffer = AMF_Encode(&prop->p_vu.p_object, pBuffer, pBufEnd);
  340. break;
  341. case AMF_ECMA_ARRAY:
  342. pBuffer = AMF_EncodeEcmaArray(&prop->p_vu.p_object, pBuffer, pBufEnd);
  343. break;
  344. case AMF_STRICT_ARRAY:
  345. pBuffer = AMF_EncodeArray(&prop->p_vu.p_object, pBuffer, pBufEnd);
  346. break;
  347. default:
  348. RTMP_Log(RTMP_LOGERROR, "%s, invalid type. %d", __FUNCTION__, prop->p_type);
  349. pBuffer = NULL;
  350. };
  351. return pBuffer;
  352. }
  353. #define AMF3_INTEGER_MAX 268435455
  354. #define AMF3_INTEGER_MIN -268435456
  355. int
  356. AMF3ReadInteger(const char *data, int32_t *valp)
  357. {
  358. int i = 0;
  359. int32_t val = 0;
  360. while (i <= 2)
  361. {
  362. /* handle first 3 bytes */
  363. if (data[i] & 0x80)
  364. {
  365. /* byte used */
  366. val <<= 7; /* shift up */
  367. val |= (data[i] & 0x7f); /* add bits */
  368. i++;
  369. }
  370. else
  371. {
  372. break;
  373. }
  374. }
  375. if (i > 2)
  376. {
  377. /* use 4th byte, all 8bits */
  378. val <<= 8;
  379. val |= data[3];
  380. /* range check */
  381. if (val > AMF3_INTEGER_MAX)
  382. val -= (1 << 29);
  383. }
  384. else
  385. {
  386. /* use 7bits of last unparsed byte (0xxxxxxx) */
  387. val <<= 7;
  388. val |= data[i];
  389. }
  390. *valp = val;
  391. return i > 2 ? 4 : i + 1;
  392. }
  393. int
  394. AMF3ReadString(const char *data, AVal *str)
  395. {
  396. int32_t ref = 0;
  397. int len;
  398. assert(str != 0);
  399. len = AMF3ReadInteger(data, &ref);
  400. data += len;
  401. if ((ref & 0x1) == 0)
  402. {
  403. /* reference: 0xxx */
  404. uint32_t refIndex = (ref >> 1);
  405. RTMP_Log(RTMP_LOGDEBUG,
  406. "%s, string reference, index: %d, not supported, ignoring!",
  407. __FUNCTION__, refIndex);
  408. return len;
  409. }
  410. else
  411. {
  412. uint32_t nSize = (ref >> 1);
  413. str->av_val = (char *)data;
  414. str->av_len = nSize;
  415. return len + nSize;
  416. }
  417. return len;
  418. }
  419. int
  420. AMF3Prop_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize,
  421. int bDecodeName)
  422. {
  423. int nOriginalSize = nSize;
  424. AMF3DataType type;
  425. prop->p_name.av_len = 0;
  426. prop->p_name.av_val = NULL;
  427. if (nSize == 0 || !pBuffer)
  428. {
  429. RTMP_Log(RTMP_LOGDEBUG, "empty buffer/no buffer pointer!");
  430. return -1;
  431. }
  432. /* decode name */
  433. if (bDecodeName)
  434. {
  435. AVal name = AV_empty;
  436. int nRes = AMF3ReadString(pBuffer, &name);
  437. if (name.av_len <= 0)
  438. return nRes;
  439. prop->p_name = name;
  440. pBuffer += nRes;
  441. nSize -= nRes;
  442. }
  443. /* decode */
  444. type = *pBuffer++;
  445. nSize--;
  446. switch (type)
  447. {
  448. case AMF3_UNDEFINED:
  449. case AMF3_NULL:
  450. prop->p_type = AMF_NULL;
  451. break;
  452. case AMF3_FALSE:
  453. prop->p_type = AMF_BOOLEAN;
  454. prop->p_vu.p_number = 0.0;
  455. break;
  456. case AMF3_TRUE:
  457. prop->p_type = AMF_BOOLEAN;
  458. prop->p_vu.p_number = 1.0;
  459. break;
  460. case AMF3_INTEGER:
  461. {
  462. int32_t res = 0;
  463. int len = AMF3ReadInteger(pBuffer, &res);
  464. prop->p_vu.p_number = (double)res;
  465. prop->p_type = AMF_NUMBER;
  466. nSize -= len;
  467. break;
  468. }
  469. case AMF3_DOUBLE:
  470. if (nSize < 8)
  471. return -1;
  472. prop->p_vu.p_number = AMF_DecodeNumber(pBuffer);
  473. prop->p_type = AMF_NUMBER;
  474. nSize -= 8;
  475. break;
  476. case AMF3_STRING:
  477. case AMF3_XML_DOC:
  478. case AMF3_XML:
  479. {
  480. int len = AMF3ReadString(pBuffer, &prop->p_vu.p_aval);
  481. prop->p_type = AMF_STRING;
  482. nSize -= len;
  483. break;
  484. }
  485. case AMF3_DATE:
  486. {
  487. int32_t res = 0;
  488. int len = AMF3ReadInteger(pBuffer, &res);
  489. nSize -= len;
  490. pBuffer += len;
  491. if ((res & 0x1) == 0)
  492. {
  493. /* reference */
  494. uint32_t nIndex = (res >> 1);
  495. RTMP_Log(RTMP_LOGDEBUG, "AMF3_DATE reference: %d, not supported!", nIndex);
  496. }
  497. else
  498. {
  499. if (nSize < 8)
  500. return -1;
  501. prop->p_vu.p_number = AMF_DecodeNumber(pBuffer);
  502. nSize -= 8;
  503. prop->p_type = AMF_NUMBER;
  504. }
  505. break;
  506. }
  507. case AMF3_OBJECT:
  508. {
  509. int nRes = AMF3_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE);
  510. if (nRes == -1)
  511. return -1;
  512. nSize -= nRes;
  513. prop->p_type = AMF_OBJECT;
  514. break;
  515. }
  516. case AMF3_ARRAY:
  517. case AMF3_BYTE_ARRAY:
  518. default:
  519. RTMP_Log(RTMP_LOGDEBUG, "%s - AMF3 unknown/unsupported datatype 0x%02x, @%p",
  520. __FUNCTION__, (unsigned char)(*pBuffer), pBuffer);
  521. return -1;
  522. }
  523. return nOriginalSize - nSize;
  524. }
  525. int
  526. AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize,
  527. int bDecodeName)
  528. {
  529. int nOriginalSize = nSize;
  530. int nRes;
  531. prop->p_name.av_len = 0;
  532. prop->p_name.av_val = NULL;
  533. if (nSize == 0 || !pBuffer)
  534. {
  535. RTMP_Log(RTMP_LOGDEBUG, "%s: Empty buffer/no buffer pointer!", __FUNCTION__);
  536. return -1;
  537. }
  538. if (bDecodeName && nSize < 4)
  539. {
  540. /* at least name (length + at least 1 byte) and 1 byte of data */
  541. RTMP_Log(RTMP_LOGDEBUG,
  542. "%s: Not enough data for decoding with name, less than 4 bytes!",
  543. __FUNCTION__);
  544. return -1;
  545. }
  546. if (bDecodeName)
  547. {
  548. unsigned short nNameSize = AMF_DecodeInt16(pBuffer);
  549. if (nNameSize > nSize - 2)
  550. {
  551. RTMP_Log(RTMP_LOGDEBUG,
  552. "%s: Name size out of range: namesize (%d) > len (%d) - 2",
  553. __FUNCTION__, nNameSize, nSize);
  554. return -1;
  555. }
  556. AMF_DecodeString(pBuffer, &prop->p_name);
  557. nSize -= 2 + nNameSize;
  558. pBuffer += 2 + nNameSize;
  559. }
  560. if (nSize == 0)
  561. {
  562. return -1;
  563. }
  564. nSize--;
  565. prop->p_type = *pBuffer++;
  566. switch (prop->p_type)
  567. {
  568. case AMF_NUMBER:
  569. if (nSize < 8)
  570. return -1;
  571. prop->p_vu.p_number = AMF_DecodeNumber(pBuffer);
  572. nSize -= 8;
  573. break;
  574. case AMF_BOOLEAN:
  575. if (nSize < 1)
  576. return -1;
  577. prop->p_vu.p_number = (double)AMF_DecodeBoolean(pBuffer);
  578. nSize--;
  579. break;
  580. case AMF_STRING:
  581. {
  582. unsigned short nStringSize = AMF_DecodeInt16(pBuffer);
  583. if (nSize < (long)nStringSize + 2)
  584. return -1;
  585. AMF_DecodeString(pBuffer, &prop->p_vu.p_aval);
  586. nSize -= (2 + nStringSize);
  587. break;
  588. }
  589. case AMF_OBJECT:
  590. {
  591. int nRes = AMF_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE);
  592. if (nRes == -1)
  593. return -1;
  594. nSize -= nRes;
  595. break;
  596. }
  597. case AMF_MOVIECLIP:
  598. {
  599. RTMP_Log(RTMP_LOGERROR, "AMF_MOVIECLIP reserved!");
  600. return -1;
  601. break;
  602. }
  603. case AMF_NULL:
  604. case AMF_UNDEFINED:
  605. case AMF_UNSUPPORTED:
  606. prop->p_type = AMF_NULL;
  607. break;
  608. case AMF_REFERENCE:
  609. {
  610. RTMP_Log(RTMP_LOGERROR, "AMF_REFERENCE not supported!");
  611. return -1;
  612. break;
  613. }
  614. case AMF_ECMA_ARRAY:
  615. {
  616. nSize -= 4;
  617. /* next comes the rest, mixed array has a final 0x000009 mark and names, so its an object */
  618. nRes = AMF_Decode(&prop->p_vu.p_object, pBuffer + 4, nSize, TRUE);
  619. if (nRes == -1)
  620. return -1;
  621. nSize -= nRes;
  622. break;
  623. }
  624. case AMF_OBJECT_END:
  625. {
  626. return -1;
  627. break;
  628. }
  629. case AMF_STRICT_ARRAY:
  630. {
  631. unsigned int nArrayLen = AMF_DecodeInt32(pBuffer);
  632. nSize -= 4;
  633. nRes = AMF_DecodeArray(&prop->p_vu.p_object, pBuffer + 4, nSize,
  634. nArrayLen, FALSE);
  635. if (nRes == -1)
  636. return -1;
  637. nSize -= nRes;
  638. break;
  639. }
  640. case AMF_DATE:
  641. {
  642. RTMP_Log(RTMP_LOGDEBUG, "AMF_DATE");
  643. if (nSize < 10)
  644. return -1;
  645. prop->p_vu.p_number = AMF_DecodeNumber(pBuffer);
  646. prop->p_UTCoffset = AMF_DecodeInt16(pBuffer + 8);
  647. nSize -= 10;
  648. break;
  649. }
  650. case AMF_LONG_STRING:
  651. case AMF_XML_DOC:
  652. {
  653. unsigned int nStringSize = AMF_DecodeInt32(pBuffer);
  654. if (nSize < (long)nStringSize + 4)
  655. return -1;
  656. AMF_DecodeLongString(pBuffer, &prop->p_vu.p_aval);
  657. nSize -= (4 + nStringSize);
  658. if (prop->p_type == AMF_LONG_STRING)
  659. prop->p_type = AMF_STRING;
  660. break;
  661. }
  662. case AMF_RECORDSET:
  663. {
  664. RTMP_Log(RTMP_LOGERROR, "AMF_RECORDSET reserved!");
  665. return -1;
  666. break;
  667. }
  668. case AMF_TYPED_OBJECT:
  669. {
  670. RTMP_Log(RTMP_LOGERROR, "AMF_TYPED_OBJECT not supported!");
  671. return -1;
  672. break;
  673. }
  674. case AMF_AVMPLUS:
  675. {
  676. int nRes = AMF3_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE);
  677. if (nRes == -1)
  678. return -1;
  679. nSize -= nRes;
  680. prop->p_type = AMF_OBJECT;
  681. break;
  682. }
  683. default:
  684. RTMP_Log(RTMP_LOGDEBUG, "%s - unknown datatype 0x%02x, @%p", __FUNCTION__,
  685. prop->p_type, pBuffer - 1);
  686. return -1;
  687. }
  688. return nOriginalSize - nSize;
  689. }
  690. void
  691. AMFProp_Dump(AMFObjectProperty *prop)
  692. {
  693. char strRes[256];
  694. char str[256];
  695. AVal name;
  696. if (prop->p_type == AMF_INVALID)
  697. {
  698. RTMP_Log(RTMP_LOGDEBUG, "Property: INVALID");
  699. return;
  700. }
  701. if (prop->p_type == AMF_NULL)
  702. {
  703. RTMP_Log(RTMP_LOGDEBUG, "Property: NULL");
  704. return;
  705. }
  706. if (prop->p_name.av_len)
  707. {
  708. name = prop->p_name;
  709. }
  710. else
  711. {
  712. name.av_val = "no-name.";
  713. name.av_len = sizeof("no-name.") - 1;
  714. }
  715. if (name.av_len > 18)
  716. name.av_len = 18;
  717. snprintf(strRes, 255, "Name: %18.*s, ", name.av_len, name.av_val);
  718. if (prop->p_type == AMF_OBJECT)
  719. {
  720. RTMP_Log(RTMP_LOGDEBUG, "Property: <%sOBJECT>", strRes);
  721. AMF_Dump(&prop->p_vu.p_object);
  722. return;
  723. }
  724. else if (prop->p_type == AMF_ECMA_ARRAY)
  725. {
  726. RTMP_Log(RTMP_LOGDEBUG, "Property: <%sECMA_ARRAY>", strRes);
  727. AMF_Dump(&prop->p_vu.p_object);
  728. return;
  729. }
  730. else if (prop->p_type == AMF_STRICT_ARRAY)
  731. {
  732. RTMP_Log(RTMP_LOGDEBUG, "Property: <%sSTRICT_ARRAY>", strRes);
  733. AMF_Dump(&prop->p_vu.p_object);
  734. return;
  735. }
  736. switch (prop->p_type)
  737. {
  738. case AMF_NUMBER:
  739. snprintf(str, 255, "NUMBER:\t%.2f", prop->p_vu.p_number);
  740. break;
  741. case AMF_BOOLEAN:
  742. snprintf(str, 255, "BOOLEAN:\t%s",
  743. prop->p_vu.p_number != 0.0 ? "TRUE" : "FALSE");
  744. break;
  745. case AMF_STRING:
  746. snprintf(str, 255, "STRING:\t%.*s", prop->p_vu.p_aval.av_len,
  747. prop->p_vu.p_aval.av_val);
  748. break;
  749. case AMF_DATE:
  750. snprintf(str, 255, "DATE:\ttimestamp: %.2f, UTC offset: %d",
  751. prop->p_vu.p_number, prop->p_UTCoffset);
  752. break;
  753. default:
  754. snprintf(str, 255, "INVALID TYPE 0x%02x", (unsigned char)prop->p_type);
  755. }
  756. RTMP_Log(RTMP_LOGDEBUG, "Property: <%s%s>", strRes, str);
  757. }
  758. void
  759. AMFProp_Reset(AMFObjectProperty *prop)
  760. {
  761. if (prop->p_type == AMF_OBJECT || prop->p_type == AMF_ECMA_ARRAY || prop->p_type == AMF_STRICT_ARRAY)
  762. AMF_Reset(&prop->p_vu.p_object);
  763. else
  764. {
  765. prop->p_vu.p_aval.av_len = 0;
  766. prop->p_vu.p_aval.av_val = NULL;
  767. }
  768. prop->p_type = AMF_INVALID;
  769. }
  770. /* AMFObject */
  771. char *
  772. AMF_Encode(AMFObject *obj, char *pBuffer, char *pBufEnd)
  773. {
  774. int i;
  775. if (pBuffer+4 >= pBufEnd)
  776. return NULL;
  777. *pBuffer++ = AMF_OBJECT;
  778. for (i = 0; i < obj->o_num; i++)
  779. {
  780. char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd);
  781. if (res == NULL)
  782. {
  783. RTMP_Log(RTMP_LOGERROR, "AMF_Encode - failed to encode property in index %d",
  784. i);
  785. break;
  786. }
  787. else
  788. {
  789. pBuffer = res;
  790. }
  791. }
  792. if (pBuffer + 3 >= pBufEnd)
  793. return NULL; /* no room for the end marker */
  794. pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END);
  795. return pBuffer;
  796. }
  797. char *
  798. AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd)
  799. {
  800. int i;
  801. if (pBuffer+4 >= pBufEnd)
  802. return NULL;
  803. *pBuffer++ = AMF_ECMA_ARRAY;
  804. pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num);
  805. for (i = 0; i < obj->o_num; i++)
  806. {
  807. char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd);
  808. if (res == NULL)
  809. {
  810. RTMP_Log(RTMP_LOGERROR, "AMF_Encode - failed to encode property in index %d",
  811. i);
  812. break;
  813. }
  814. else
  815. {
  816. pBuffer = res;
  817. }
  818. }
  819. if (pBuffer + 3 >= pBufEnd)
  820. return NULL; /* no room for the end marker */
  821. pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END);
  822. return pBuffer;
  823. }
  824. char *
  825. AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd)
  826. {
  827. int i;
  828. if (pBuffer+4 >= pBufEnd)
  829. return NULL;
  830. *pBuffer++ = AMF_STRICT_ARRAY;
  831. pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num);
  832. for (i = 0; i < obj->o_num; i++)
  833. {
  834. char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd);
  835. if (res == NULL)
  836. {
  837. RTMP_Log(RTMP_LOGERROR, "AMF_Encode - failed to encode property in index %d",
  838. i);
  839. break;
  840. }
  841. else
  842. {
  843. pBuffer = res;
  844. }
  845. }
  846. //if (pBuffer + 3 >= pBufEnd)
  847. // return NULL; /* no room for the end marker */
  848. //pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END);
  849. return pBuffer;
  850. }
  851. int
  852. AMF_DecodeArray(AMFObject *obj, const char *pBuffer, int nSize,
  853. int nArrayLen, int bDecodeName)
  854. {
  855. int nOriginalSize = nSize;
  856. int bError = FALSE;
  857. obj->o_num = 0;
  858. obj->o_props = NULL;
  859. while (nArrayLen > 0)
  860. {
  861. AMFObjectProperty prop;
  862. int nRes;
  863. nArrayLen--;
  864. nRes = AMFProp_Decode(&prop, pBuffer, nSize, bDecodeName);
  865. if (nRes == -1)
  866. bError = TRUE;
  867. else
  868. {
  869. nSize -= nRes;
  870. pBuffer += nRes;
  871. AMF_AddProp(obj, &prop);
  872. }
  873. }
  874. if (bError)
  875. return -1;
  876. return nOriginalSize - nSize;
  877. }
  878. int
  879. AMF3_Decode(AMFObject *obj, const char *pBuffer, int nSize, int bAMFData)
  880. {
  881. int nOriginalSize = nSize;
  882. int32_t ref;
  883. int len;
  884. obj->o_num = 0;
  885. obj->o_props = NULL;
  886. if (bAMFData)
  887. {
  888. if (*pBuffer != AMF3_OBJECT)
  889. RTMP_Log(RTMP_LOGERROR,
  890. "AMF3 Object encapsulated in AMF stream does not start with AMF3_OBJECT!");
  891. pBuffer++;
  892. nSize--;
  893. }
  894. ref = 0;
  895. len = AMF3ReadInteger(pBuffer, &ref);
  896. pBuffer += len;
  897. nSize -= len;
  898. if ((ref & 1) == 0)
  899. {
  900. /* object reference, 0xxx */
  901. uint32_t objectIndex = (ref >> 1);
  902. RTMP_Log(RTMP_LOGDEBUG, "Object reference, index: %d", objectIndex);
  903. }
  904. else /* object instance */
  905. {
  906. int32_t classRef = (ref >> 1);
  907. AMF3ClassDef cd = { {0, 0}
  908. };
  909. AMFObjectProperty prop;
  910. if ((classRef & 0x1) == 0)
  911. {
  912. /* class reference */
  913. uint32_t classIndex = (classRef >> 1);
  914. RTMP_Log(RTMP_LOGDEBUG, "Class reference: %d", classIndex);
  915. }
  916. else
  917. {
  918. int32_t classExtRef = (classRef >> 1);
  919. int i;
  920. cd.cd_externalizable = (classExtRef & 0x1) == 1;
  921. cd.cd_dynamic = ((classExtRef >> 1) & 0x1) == 1;
  922. cd.cd_num = classExtRef >> 2;
  923. /* class name */
  924. len = AMF3ReadString(pBuffer, &cd.cd_name);
  925. nSize -= len;
  926. pBuffer += len;
  927. /*std::string str = className; */
  928. RTMP_Log(RTMP_LOGDEBUG,
  929. "Class name: %s, externalizable: %d, dynamic: %d, classMembers: %d",
  930. cd.cd_name.av_val, cd.cd_externalizable, cd.cd_dynamic,
  931. cd.cd_num);
  932. for (i = 0; i < cd.cd_num; i++)
  933. {
  934. AVal memberName = AV_empty;
  935. len = AMF3ReadString(pBuffer, &memberName);
  936. RTMP_Log(RTMP_LOGDEBUG, "Member: %s", memberName.av_val);
  937. AMF3CD_AddProp(&cd, &memberName);
  938. nSize -= len;
  939. pBuffer += len;
  940. }
  941. }
  942. /* add as referencable object */
  943. if (cd.cd_externalizable)
  944. {
  945. int nRes;
  946. AVal name = AVC("DEFAULT_ATTRIBUTE");
  947. RTMP_Log(RTMP_LOGDEBUG, "Externalizable, TODO check");
  948. nRes = AMF3Prop_Decode(&prop, pBuffer, nSize, FALSE);
  949. if (nRes == -1)
  950. RTMP_Log(RTMP_LOGDEBUG, "%s, failed to decode AMF3 property!",
  951. __FUNCTION__);
  952. else
  953. {
  954. nSize -= nRes;
  955. pBuffer += nRes;
  956. }
  957. AMFProp_SetName(&prop, &name);
  958. AMF_AddProp(obj, &prop);
  959. }
  960. else
  961. {
  962. int nRes, i;
  963. for (i = 0; i < cd.cd_num; i++) /* non-dynamic */
  964. {
  965. nRes = AMF3Prop_Decode(&prop, pBuffer, nSize, FALSE);
  966. if (nRes == -1)
  967. RTMP_Log(RTMP_LOGDEBUG, "%s, failed to decode AMF3 property!",
  968. __FUNCTION__);
  969. AMFProp_SetName(&prop, AMF3CD_GetProp(&cd, i));
  970. AMF_AddProp(obj, &prop);
  971. pBuffer += nRes;
  972. nSize -= nRes;
  973. }
  974. if (cd.cd_dynamic)
  975. {
  976. int len = 0;
  977. do
  978. {
  979. nRes = AMF3Prop_Decode(&prop, pBuffer, nSize, TRUE);
  980. AMF_AddProp(obj, &prop);
  981. pBuffer += nRes;
  982. nSize -= nRes;
  983. len = prop.p_name.av_len;
  984. }
  985. while (len > 0);
  986. }
  987. }
  988. RTMP_Log(RTMP_LOGDEBUG, "class object!");
  989. }
  990. return nOriginalSize - nSize;
  991. }
  992. int
  993. AMF_Decode(AMFObject *obj, const char *pBuffer, int nSize, int bDecodeName)
  994. {
  995. int nOriginalSize = nSize;
  996. int bError = FALSE; /* if there is an error while decoding - try to at least find the end mark AMF_OBJECT_END */
  997. obj->o_num = 0;
  998. obj->o_props = NULL;
  999. while (nSize > 0)
  1000. {
  1001. AMFObjectProperty prop;
  1002. int nRes;
  1003. if (nSize >=3 && AMF_DecodeInt24(pBuffer) == AMF_OBJECT_END)
  1004. {
  1005. nSize -= 3;
  1006. bError = FALSE;
  1007. break;
  1008. }
  1009. if (bError)
  1010. {
  1011. RTMP_Log(RTMP_LOGERROR,
  1012. "DECODING ERROR, IGNORING BYTES UNTIL NEXT KNOWN PATTERN!");
  1013. nSize--;
  1014. pBuffer++;
  1015. continue;
  1016. }
  1017. nRes = AMFProp_Decode(&prop, pBuffer, nSize, bDecodeName);
  1018. if (nRes == -1)
  1019. bError = TRUE;
  1020. else
  1021. {
  1022. nSize -= nRes;
  1023. pBuffer += nRes;
  1024. AMF_AddProp(obj, &prop);
  1025. }
  1026. }
  1027. if (bError)
  1028. return -1;
  1029. return nOriginalSize - nSize;
  1030. }
  1031. void
  1032. AMF_AddProp(AMFObject *obj, const AMFObjectProperty *prop)
  1033. {
  1034. if (!(obj->o_num & 0x0f))
  1035. obj->o_props =
  1036. realloc(obj->o_props, (obj->o_num + 16) * sizeof(AMFObjectProperty));
  1037. memcpy(&obj->o_props[obj->o_num++], prop, sizeof(AMFObjectProperty));
  1038. }
  1039. int
  1040. AMF_CountProp(AMFObject *obj)
  1041. {
  1042. return obj->o_num;
  1043. }
  1044. AMFObjectProperty *
  1045. AMF_GetProp(AMFObject *obj, const AVal *name, int nIndex)
  1046. {
  1047. if (nIndex >= 0)
  1048. {
  1049. if (nIndex < obj->o_num)
  1050. return &obj->o_props[nIndex];
  1051. }
  1052. else
  1053. {
  1054. int n;
  1055. for (n = 0; n < obj->o_num; n++)
  1056. {
  1057. if (AVMATCH(&obj->o_props[n].p_name, name))
  1058. return &obj->o_props[n];
  1059. }
  1060. }
  1061. return (AMFObjectProperty *)&AMFProp_Invalid;
  1062. }
  1063. void
  1064. AMF_Dump(AMFObject *obj)
  1065. {
  1066. int n;
  1067. RTMP_Log(RTMP_LOGDEBUG, "(object begin)");
  1068. for (n = 0; n < obj->o_num; n++)
  1069. {
  1070. AMFProp_Dump(&obj->o_props[n]);
  1071. }
  1072. RTMP_Log(RTMP_LOGDEBUG, "(object end)");
  1073. }
  1074. void
  1075. AMF_Reset(AMFObject *obj)
  1076. {
  1077. int n;
  1078. for (n = 0; n < obj->o_num; n++)
  1079. {
  1080. AMFProp_Reset(&obj->o_props[n]);
  1081. }
  1082. free(obj->o_props);
  1083. obj->o_props = NULL;
  1084. obj->o_num = 0;
  1085. }
  1086. /* AMF3ClassDefinition */
  1087. void
  1088. AMF3CD_AddProp(AMF3ClassDef *cd, AVal *prop)
  1089. {
  1090. if (!(cd->cd_num & 0x0f))
  1091. cd->cd_props = realloc(cd->cd_props, (cd->cd_num + 16) * sizeof(AVal));
  1092. cd->cd_props[cd->cd_num++] = *prop;
  1093. }
  1094. AVal *
  1095. AMF3CD_GetProp(AMF3ClassDef *cd, int nIndex)
  1096. {
  1097. if (nIndex >= cd->cd_num)
  1098. return (AVal *)&AV_empty;
  1099. return &cd->cd_props[nIndex];
  1100. }