PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/librtmp/amf.c

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