You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

632 lines
20KB

  1. #include "rtmp-server.h"
  2. #include "rtmp-internal.h"
  3. #include "rtmp-msgtypeid.h"
  4. #include "rtmp-handshake.h"
  5. #include "rtmp-netstream.h"
  6. #include "rtmp-netconnection.h"
  7. #include "rtmp-control-message.h"
  8. #include "rtmp-event.h"
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <assert.h>
  14. #include <time.h>
  15. #define RTMP_FMSVER "FMS/3,0,1,123"
  16. #define RTMP_CAPABILITIES 31
  17. #define RTMP_OUTPUT_CHUNK_SIZE 4096
  18. struct rtmp_server_t
  19. {
  20. struct rtmp_t rtmp;
  21. uint32_t recv_bytes[2]; // for rtmp_acknowledgement
  22. void* param;
  23. struct rtmp_server_handler_t handler;
  24. uint8_t payload[2 * 1024];
  25. uint8_t handshake[2 * RTMP_HANDSHAKE_SIZE + 1]; // only for handshake
  26. size_t handshake_bytes;
  27. int handshake_state; // RTMP_HANDSHAKE_XXX
  28. struct rtmp_connect_t info; // Server application name, e.g.: testapp
  29. char stream_name[256]; // Play/Publishing stream name, flv:sample, mp3:sample, H.264/AAC: mp4:sample.m4v
  30. char stream_type[18]; // Publishing type: live/record/append
  31. uint32_t stream_id; // createStream/deleteStream
  32. uint8_t receiveAudio; // 1-enable audio, 0-no audio
  33. uint8_t receiveVideo; // 1-enable video, 0-no video
  34. // onpublish/onplay only
  35. struct
  36. {
  37. double transaction;
  38. int reset;
  39. int play; // 1-play, 2-publish, other-error
  40. } start;
  41. };
  42. static int rtmp_server_send_control(struct rtmp_t* rtmp, const uint8_t* payload, uint32_t bytes, uint32_t stream_id)
  43. {
  44. struct rtmp_chunk_header_t header;
  45. header.fmt = RTMP_CHUNK_TYPE_0; // disable compact header
  46. header.cid = RTMP_CHANNEL_INVOKE;
  47. header.timestamp = 0;
  48. header.length = bytes;
  49. header.type = RTMP_TYPE_INVOKE;
  50. header.stream_id = stream_id; /* default 0 */
  51. return rtmp_chunk_write(rtmp, &header, payload);
  52. }
  53. static int rtmp_server_send_onstatus(struct rtmp_server_t* ctx, double transaction, int r, const char* success, const char* fail, const char* description)
  54. {
  55. r = (int)(rtmp_netstream_onstatus(ctx->payload, sizeof(ctx->payload), transaction, 0==r ? RTMP_LEVEL_STATUS : RTMP_LEVEL_ERROR, 0==r ? success : fail, description) - ctx->payload);
  56. return rtmp_server_send_control(&ctx->rtmp, ctx->payload, r, ctx->stream_id);
  57. }
  58. // handshake
  59. static int rtmp_server_send_handshake(struct rtmp_server_t* ctx)
  60. {
  61. int n, r;
  62. n = rtmp_handshake_s0(ctx->handshake, RTMP_VERSION);
  63. n += rtmp_handshake_s1(ctx->handshake + n, (uint32_t)time(NULL));
  64. n += rtmp_handshake_s2(ctx->handshake + n, (uint32_t)time(NULL), ctx->payload, RTMP_HANDSHAKE_SIZE);
  65. assert(n == 1 + RTMP_HANDSHAKE_SIZE + RTMP_HANDSHAKE_SIZE);
  66. r = ctx->handler.send(ctx->param, ctx->handshake, n, NULL, 0);
  67. return n == r ? 0 : r;
  68. }
  69. /// 5.4.1. Set Chunk Size (1)
  70. static int rtmp_server_send_set_chunk_size(struct rtmp_server_t* ctx)
  71. {
  72. int n, r;
  73. n = rtmp_set_chunk_size(ctx->payload, sizeof(ctx->payload), RTMP_OUTPUT_CHUNK_SIZE);
  74. r = ctx->handler.send(ctx->param, ctx->payload, n, NULL, 0);
  75. ctx->rtmp.out_chunk_size = RTMP_OUTPUT_CHUNK_SIZE;
  76. return n == r ? 0 : r;
  77. }
  78. /// 5.4.3. Acknowledgement (3)
  79. static int rtmp_server_send_acknowledgement(struct rtmp_server_t* ctx, size_t size)
  80. {
  81. int n, r;
  82. ctx->recv_bytes[0] += (uint32_t)size;
  83. if (ctx->rtmp.window_size && ctx->recv_bytes[0] - ctx->recv_bytes[1] > ctx->rtmp.window_size)
  84. {
  85. n = rtmp_acknowledgement(ctx->payload, sizeof(ctx->payload), ctx->recv_bytes[0]);
  86. r = ctx->handler.send(ctx->param, ctx->payload, n, NULL, 0);
  87. ctx->recv_bytes[1] = ctx->recv_bytes[0];
  88. return n == r ? 0 : r;
  89. }
  90. return 0;
  91. }
  92. /// 5.4.4. Window Acknowledgement Size (5)
  93. static int rtmp_server_send_server_bandwidth(struct rtmp_server_t* ctx)
  94. {
  95. int n, r;
  96. n = rtmp_window_acknowledgement_size(ctx->payload, sizeof(ctx->payload), ctx->rtmp.window_size);
  97. r = ctx->handler.send(ctx->param, ctx->payload, n, NULL, 0);
  98. return n == r ? 0 : r;
  99. }
  100. /// 5.4.5. Set Peer Bandwidth (6)
  101. static int rtmp_server_send_client_bandwidth(struct rtmp_server_t* ctx)
  102. {
  103. int n, r;
  104. n = rtmp_set_peer_bandwidth(ctx->payload, sizeof(ctx->payload), ctx->rtmp.peer_bandwidth, RTMP_BANDWIDTH_LIMIT_DYNAMIC);
  105. r = ctx->handler.send(ctx->param, ctx->payload, n, NULL, 0);
  106. return n == r ? 0 : r;
  107. }
  108. static int rtmp_server_send_stream_is_record(struct rtmp_server_t* ctx)
  109. {
  110. int n, r;
  111. n = rtmp_event_stream_is_record(ctx->payload, sizeof(ctx->payload), ctx->stream_id);
  112. r = ctx->handler.send(ctx->param, ctx->payload, n, NULL, 0);
  113. return n == r ? 0 : r;
  114. }
  115. static int rtmp_server_send_stream_begin(struct rtmp_server_t* ctx)
  116. {
  117. int n, r;
  118. n = rtmp_event_stream_begin(ctx->payload, sizeof(ctx->payload), ctx->stream_id);
  119. r = ctx->handler.send(ctx->param, ctx->payload, n, NULL, 0);
  120. return n == r ? 0 : r;
  121. }
  122. static int rtmp_server_rtmp_sample_access(struct rtmp_server_t* ctx)
  123. {
  124. int n;
  125. struct rtmp_chunk_header_t header;
  126. n = (int)(rtmp_netstream_rtmpsampleaccess(ctx->payload, sizeof(ctx->payload)) - ctx->payload);
  127. header.fmt = RTMP_CHUNK_TYPE_0; // disable compact header
  128. header.cid = RTMP_CHANNEL_INVOKE;
  129. header.timestamp = 0;
  130. header.length = n;
  131. header.type = RTMP_TYPE_DATA;
  132. header.stream_id = ctx->stream_id;
  133. return rtmp_chunk_write(&ctx->rtmp, &header, ctx->payload);
  134. }
  135. static void rtmp_server_onabort(void* param, uint32_t chunk_stream_id)
  136. {
  137. struct rtmp_server_t* ctx;
  138. ctx = (struct rtmp_server_t*)param;
  139. (void)ctx, (void)chunk_stream_id;
  140. // ctx->handler.onerror(ctx->param, -1, "client abort");
  141. }
  142. static int rtmp_server_onaudio(void* param, const uint8_t* data, size_t bytes, uint32_t timestamp)
  143. {
  144. struct rtmp_server_t* ctx;
  145. ctx = (struct rtmp_server_t*)param;
  146. return ctx->handler.onaudio(ctx->param, data, bytes, timestamp);
  147. }
  148. static int rtmp_server_onvideo(void* param, const uint8_t* data, size_t bytes, uint32_t timestamp)
  149. {
  150. struct rtmp_server_t* ctx;
  151. ctx = (struct rtmp_server_t*)param;
  152. return ctx->handler.onvideo(ctx->param, data, bytes, timestamp);
  153. }
  154. static int rtmp_server_onscript(void* param, const uint8_t* data, size_t bytes, uint32_t timestamp)
  155. {
  156. struct rtmp_server_t* ctx;
  157. ctx = (struct rtmp_server_t*)param;
  158. return ctx->handler.onscript(ctx->param, data, bytes, timestamp);
  159. }
  160. // 7.2.1.1. connect (p29)
  161. // _result/_error
  162. static int rtmp_server_onconnect(void* param, int r, double transaction, const struct rtmp_connect_t* connect)
  163. {
  164. int n;
  165. struct rtmp_server_t* ctx;
  166. ctx = (struct rtmp_server_t*)param;
  167. assert((double)RTMP_ENCODING_AMF_0 == connect->encoding || (double)RTMP_ENCODING_AMF_3 == connect->encoding);
  168. if (0 == r)
  169. {
  170. assert(1 == (int)transaction);
  171. memcpy(&ctx->info, connect, sizeof(ctx->info));
  172. r = rtmp_server_send_server_bandwidth(ctx);
  173. r = 0 == r ? rtmp_server_send_client_bandwidth(ctx) : r;
  174. r = 0 == r ? rtmp_server_send_set_chunk_size(ctx) : r;
  175. }
  176. if(0 == r)
  177. {
  178. n = (int)(rtmp_netconnection_connect_reply(ctx->payload, sizeof(ctx->payload), transaction, RTMP_FMSVER, RTMP_CAPABILITIES, "NetConnection.Connect.Success", RTMP_LEVEL_STATUS, "Connection Succeeded.", connect->encoding) - ctx->payload);
  179. r = rtmp_server_send_control(&ctx->rtmp, ctx->payload, n, 0);
  180. }
  181. return r;
  182. }
  183. // 7.2.1.3. createStream (p36)
  184. // _result/_error
  185. static int rtmp_server_oncreate_stream(void* param, int r, double transaction)
  186. {
  187. struct rtmp_server_t* ctx;
  188. ctx = (struct rtmp_server_t*)param;
  189. if (0 == r)
  190. {
  191. ctx->stream_id = 1;
  192. //r = ctx->handler.oncreate_stream(ctx->param, &ctx->stream_id);
  193. if (0 == r)
  194. r = (int)(rtmp_netconnection_create_stream_reply(ctx->payload, sizeof(ctx->payload), transaction, ctx->stream_id) - ctx->payload);
  195. else
  196. r = (int)(rtmp_netconnection_error(ctx->payload, sizeof(ctx->payload), transaction, "NetConnection.CreateStream.Failed", RTMP_LEVEL_ERROR, "createStream failed.") - ctx->payload);
  197. r = rtmp_server_send_control(&ctx->rtmp, ctx->payload, r, 0/*ctx->stream_id*/); // must be 0
  198. }
  199. return r;
  200. }
  201. // 7.2.2.3. deleteStream (p43)
  202. // The server does not send any response
  203. static int rtmp_server_ondelete_stream(void* param, int r, double transaction, double stream_id)
  204. {
  205. struct rtmp_server_t* ctx;
  206. ctx = (struct rtmp_server_t*)param;
  207. if (0 == r)
  208. {
  209. stream_id = ctx->stream_id = 0; // clear stream id
  210. //r = ctx->handler.ondelete_stream(ctx->param, (uint32_t)stream_id);
  211. r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.DeleteStream.Suceess", "NetStream.DeleteStream.Failed", "");
  212. }
  213. return r;
  214. }
  215. static int rtmp_server_onget_stream_length(void* param, int r, double transaction, const char* stream_name)
  216. {
  217. double duration = -1;
  218. struct rtmp_server_t* ctx;
  219. ctx = (struct rtmp_server_t*)param;
  220. if (0 == r && ctx->handler.ongetduration)
  221. {
  222. // get duration (seconds)
  223. r = ctx->handler.ongetduration(ctx->param, ctx->info.app, stream_name, &duration);
  224. if (0 == r)
  225. {
  226. r = (int)(rtmp_netconnection_get_stream_length_reply(ctx->payload, sizeof(ctx->payload), transaction, duration) - ctx->payload);
  227. r = rtmp_server_send_control(&ctx->rtmp, ctx->payload, r, ctx->stream_id);
  228. }
  229. }
  230. return r;
  231. }
  232. // 7.2.2.6. publish (p45)
  233. // The server responds with the onStatus command
  234. static int rtmp_server_onpublish(void* param, int r, double transaction, const char* stream_name, const char* stream_type)
  235. {
  236. struct rtmp_server_t* ctx;
  237. ctx = (struct rtmp_server_t*)param;
  238. if (0 == r)
  239. {
  240. snprintf(ctx->stream_name, sizeof(ctx->stream_name) - 1, "%s", stream_name ? stream_name : "");
  241. snprintf(ctx->stream_type, sizeof(ctx->stream_type) - 1, "%s", stream_type ? stream_type : "");
  242. r = ctx->handler.onpublish(ctx->param, ctx->info.app, stream_name, stream_type);
  243. if (0 == r)
  244. {
  245. // User Control (StreamBegin)
  246. r = rtmp_server_send_stream_begin(ctx);
  247. if(0 != r)
  248. return r;
  249. }
  250. r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.Publish.Start", "NetStream.Publish.BadName", "");
  251. }
  252. return r;
  253. }
  254. // 7.2.2.1. play (p38)
  255. // reply onStatus NetStream.Play.Start & NetStream.Play.Reset
  256. static int rtmp_server_onplay(void* param, int r, double transaction, const char* stream_name, double start, double duration, uint8_t reset)
  257. {
  258. struct rtmp_server_t* ctx;
  259. ctx = (struct rtmp_server_t*)param;
  260. if (0 == r)
  261. {
  262. ctx->start.play = 1;
  263. ctx->start.reset = reset;
  264. ctx->start.transaction = transaction;
  265. snprintf(ctx->stream_name, sizeof(ctx->stream_name) - 1, "%s", stream_name ? stream_name : "");
  266. snprintf(ctx->stream_type, sizeof(ctx->stream_type) - 1, "%s", -1 == start ? RTMP_STREAM_LIVE : RTMP_STREAM_RECORD);
  267. r = ctx->handler.onplay(ctx->param, ctx->info.app, stream_name, start, duration, reset);
  268. //if (0 == r)
  269. //{
  270. // // User Control (StreamBegin)
  271. // r = 0 == r ? rtmp_server_send_stream_begin(ctx) : r;
  272. // // NetStream.Play.Reset
  273. // if (reset) r = 0 == r ? rtmp_server_send_onstatus(ctx, transaction, 0, "NetStream.Play.Reset", "NetStream.Play.Failed", "") : r;
  274. // if(0 != r)
  275. // return r;
  276. //}
  277. //r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.Play.Start", "NetStream.Play.Failed", "Start video on demand");
  278. //// User Control (StreamIsRecorded)
  279. //r = 0 == r ? rtmp_server_send_stream_is_record(ctx) : r;
  280. //r = 0 == r ? rtmp_server_rtmp_sample_access(ctx) : r;
  281. }
  282. return r;
  283. }
  284. // 7.2.2.8. pause (p47)
  285. // sucessful: NetStream.Pause.Notify/NetStream.Unpause.Notify
  286. // failure: _error message
  287. static int rtmp_server_onpause(void* param, int r, double transaction, uint8_t pause, double milliSeconds)
  288. {
  289. struct rtmp_server_t* ctx;
  290. ctx = (struct rtmp_server_t*)param;
  291. if (0 == r)
  292. {
  293. r = ctx->handler.onpause(ctx->param, pause, (uint32_t)milliSeconds);
  294. r = rtmp_server_send_onstatus(ctx, transaction, r, pause ? "NetStream.Pause.Notify" : "NetStream.Unpause.Notify", "NetStream.Pause.Failed", "");
  295. }
  296. return r;
  297. }
  298. // 7.2.2.7. seek (p46)
  299. // successful : NetStream.Seek.Notify
  300. // failure: _error message
  301. static int rtmp_server_onseek(void* param, int r, double transaction, double milliSeconds)
  302. {
  303. struct rtmp_server_t* ctx;
  304. ctx = (struct rtmp_server_t*)param;
  305. if (0 == r)
  306. {
  307. r = ctx->handler.onseek(ctx->param, (uint32_t)milliSeconds);
  308. r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.Seek.Notify", "NetStream.Seek.Failed", "");
  309. }
  310. return r;
  311. }
  312. // 7.2.2.4. receiveAudio (p44)
  313. // false: The server does not send any response,
  314. // true: server responds with status messages NetStream.Seek.Notify and NetStream.Play.Start
  315. static int rtmp_server_onreceive_audio(void* param, int r, double transaction, uint8_t audio)
  316. {
  317. struct rtmp_server_t* ctx;
  318. ctx = (struct rtmp_server_t*)param;
  319. if(0 == r)
  320. {
  321. ctx->receiveAudio = audio;
  322. if (audio)
  323. {
  324. r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.Seek.Notify", "NetStream.Seek.Failed", "");
  325. r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.Play.Start", "NetStream.Play.Failed", "");
  326. }
  327. }
  328. return r;
  329. }
  330. static int rtmp_server_onreceive_video(void* param, int r, double transaction, uint8_t video)
  331. {
  332. struct rtmp_server_t* ctx;
  333. ctx = (struct rtmp_server_t*)param;
  334. if(0 == r)
  335. {
  336. ctx->receiveVideo = video;
  337. if (video)
  338. {
  339. r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.Seek.Notify", "NetStream.Seek.Failed", "");
  340. r = rtmp_server_send_onstatus(ctx, transaction, r, "NetStream.Play.Start", "NetStream.Play.Failed", "");
  341. }
  342. }
  343. return r;
  344. }
  345. static int rtmp_server_send(void* param, const uint8_t* header, uint32_t headerBytes, const uint8_t* payload, uint32_t payloadBytes)
  346. {
  347. int r;
  348. struct rtmp_server_t* ctx;
  349. ctx = (struct rtmp_server_t*)param;
  350. r = ctx->handler.send(ctx->param, header, headerBytes, payload, payloadBytes);
  351. return (r == (int)(payloadBytes + headerBytes)) ? 0 : -1;
  352. }
  353. struct rtmp_server_t* rtmp_server_create(void* param, const struct rtmp_server_handler_t* handler)
  354. {
  355. struct rtmp_server_t* ctx;
  356. ctx = (struct rtmp_server_t*)calloc(1, sizeof(*ctx));
  357. if (NULL == ctx)
  358. return NULL;
  359. memcpy(&ctx->handler, handler, sizeof(ctx->handler));
  360. ctx->param = param;
  361. ctx->stream_id = 0;
  362. ctx->receiveAudio = 1;
  363. ctx->receiveVideo = 1;
  364. ctx->handshake_state = RTMP_HANDSHAKE_UNINIT;
  365. ctx->rtmp.parser.state = RTMP_PARSE_INIT;
  366. ctx->rtmp.in_chunk_size = RTMP_CHUNK_SIZE;
  367. ctx->rtmp.out_chunk_size = RTMP_CHUNK_SIZE;
  368. ctx->rtmp.window_size = 5000000;
  369. ctx->rtmp.peer_bandwidth = 5000000;
  370. ctx->rtmp.buffer_length_ms = 30000;
  371. ctx->rtmp.param = ctx;
  372. ctx->rtmp.send = rtmp_server_send;
  373. ctx->rtmp.onaudio = rtmp_server_onaudio;
  374. ctx->rtmp.onvideo = rtmp_server_onvideo;
  375. ctx->rtmp.onabort = rtmp_server_onabort;
  376. ctx->rtmp.onscript = rtmp_server_onscript;
  377. ctx->rtmp.server.onconnect = rtmp_server_onconnect;
  378. ctx->rtmp.server.oncreate_stream = rtmp_server_oncreate_stream;
  379. ctx->rtmp.server.ondelete_stream = rtmp_server_ondelete_stream;
  380. ctx->rtmp.server.onget_stream_length = rtmp_server_onget_stream_length;
  381. ctx->rtmp.server.onpublish = rtmp_server_onpublish;
  382. ctx->rtmp.server.onplay = rtmp_server_onplay;
  383. ctx->rtmp.server.onpause = rtmp_server_onpause;
  384. ctx->rtmp.server.onseek = rtmp_server_onseek;
  385. ctx->rtmp.server.onreceive_audio = rtmp_server_onreceive_audio;
  386. ctx->rtmp.server.onreceive_video = rtmp_server_onreceive_video;
  387. ctx->rtmp.out_packets[RTMP_CHANNEL_PROTOCOL].header.cid = RTMP_CHANNEL_PROTOCOL;
  388. ctx->rtmp.out_packets[RTMP_CHANNEL_INVOKE].header.cid = RTMP_CHANNEL_INVOKE;
  389. ctx->rtmp.out_packets[RTMP_CHANNEL_AUDIO].header.cid = RTMP_CHANNEL_AUDIO;
  390. ctx->rtmp.out_packets[RTMP_CHANNEL_VIDEO].header.cid = RTMP_CHANNEL_VIDEO;
  391. ctx->rtmp.out_packets[RTMP_CHANNEL_DATA].header.cid = RTMP_CHANNEL_DATA;
  392. return ctx;
  393. }
  394. void rtmp_server_destroy(struct rtmp_server_t* ctx)
  395. {
  396. size_t i;
  397. assert(sizeof(ctx->rtmp.in_packets) == sizeof(ctx->rtmp.out_packets));
  398. for (i = 0; i < N_CHUNK_STREAM; i++)
  399. {
  400. assert(NULL == ctx->rtmp.out_packets[i].payload);
  401. if (ctx->rtmp.in_packets[i].payload)
  402. free(ctx->rtmp.in_packets[i].payload);
  403. }
  404. free(ctx);
  405. }
  406. int rtmp_server_getstate(struct rtmp_server_t* ctx)
  407. {
  408. return ctx->handshake_state;
  409. }
  410. int rtmp_server_input(struct rtmp_server_t* ctx, const uint8_t* data, size_t bytes)
  411. {
  412. int r;
  413. size_t n;
  414. const uint8_t* p;
  415. p = data;
  416. while (bytes > 0)
  417. {
  418. switch (ctx->handshake_state)
  419. {
  420. case RTMP_HANDSHAKE_UNINIT: // C0: version
  421. ctx->handshake_state = RTMP_HANDSHAKE_0;
  422. ctx->handshake_bytes = 0; // clear buffer
  423. assert(*p <= RTMP_VERSION);
  424. bytes -= 1;
  425. p += 1;
  426. break;
  427. case RTMP_HANDSHAKE_0: // C1: 4-time + 4-zero + 1528-random
  428. assert(RTMP_HANDSHAKE_SIZE > ctx->handshake_bytes);
  429. n = RTMP_HANDSHAKE_SIZE - ctx->handshake_bytes;
  430. n = n <= bytes ? n : bytes;
  431. memcpy(ctx->payload + ctx->handshake_bytes, p, n);
  432. ctx->handshake_bytes += n;
  433. bytes -= n;
  434. p += n;
  435. if (ctx->handshake_bytes == RTMP_HANDSHAKE_SIZE)
  436. {
  437. ctx->handshake_state = RTMP_HANDSHAKE_1;
  438. ctx->handshake_bytes = 0; // clear buffer
  439. r = rtmp_server_send_handshake(ctx);
  440. if(0 != r) return r;
  441. }
  442. break;
  443. case RTMP_HANDSHAKE_1: // C2: 4-time + 4-time2 + 1528-echo
  444. assert(RTMP_HANDSHAKE_SIZE > ctx->handshake_bytes);
  445. n = RTMP_HANDSHAKE_SIZE - ctx->handshake_bytes;
  446. n = n <= bytes ? n : bytes;
  447. memcpy(ctx->payload + ctx->handshake_bytes, p, n);
  448. ctx->handshake_bytes += n;
  449. bytes -= n;
  450. p += n;
  451. if (ctx->handshake_bytes == RTMP_HANDSHAKE_SIZE)
  452. {
  453. ctx->handshake_state = RTMP_HANDSHAKE_2;
  454. ctx->handshake_bytes = 0; // clear buffer
  455. }
  456. break;
  457. case RTMP_HANDSHAKE_2:
  458. default:
  459. rtmp_server_send_acknowledgement(ctx, bytes);
  460. return rtmp_chunk_read(&ctx->rtmp, (const uint8_t*)p, bytes);
  461. }
  462. }
  463. return 0;
  464. }
  465. int rtmp_server_start(rtmp_server_t* rtmp, int r, const char* msg)
  466. {
  467. (void)msg; // ignore
  468. if (1 == rtmp->start.play)
  469. {
  470. if (0 == r)
  471. {
  472. // User Control (StreamBegin)
  473. r = 0 == r ? rtmp_server_send_stream_begin(rtmp) : r;
  474. // NetStream.Play.Reset
  475. if (rtmp->start.reset) r = 0 == r ? rtmp_server_send_onstatus(rtmp, rtmp->start.transaction, 0, "NetStream.Play.Reset", "NetStream.Play.Failed", "") : r;
  476. if (0 != r)
  477. return r;
  478. }
  479. r = rtmp_server_send_onstatus(rtmp, rtmp->start.transaction, r, "NetStream.Play.Start", "NetStream.Play.Failed", "Start video on demand");
  480. // User Control (StreamIsRecorded)
  481. r = 0 == r ? rtmp_server_send_stream_is_record(rtmp) : r;
  482. r = 0 == r ? rtmp_server_rtmp_sample_access(rtmp) : r;
  483. }
  484. //else if(2 == rtmp->start.play)
  485. //{
  486. // if (0 == r)
  487. // {
  488. // // User Control (StreamBegin)
  489. // r = rtmp_server_send_stream_begin(rtmp);
  490. // if (0 != r)
  491. // return r;
  492. // }
  493. // r = rtmp_server_send_onstatus(rtmp, rtmp->start.transaction, r, "NetStream.Publish.Start", "NetStream.Publish.BadName", "");
  494. //}
  495. rtmp->start.play = 0;
  496. return r;
  497. }
  498. #define RTMP_SERVER_CHECK_START(rtmp) do {int r; r = rtmp->start.play ? rtmp_server_start(rtmp, 0, NULL) : 0; if (0 != r) return r; } while(0)
  499. int rtmp_server_send_audio(struct rtmp_server_t* ctx, const void* data, size_t bytes, uint32_t timestamp)
  500. {
  501. struct rtmp_chunk_header_t header;
  502. RTMP_SERVER_CHECK_START(ctx);
  503. if (0 == ctx->receiveAudio)
  504. return 0; // client don't want receive audio
  505. header.fmt = RTMP_CHUNK_TYPE_1; // enable compact header
  506. header.cid = RTMP_CHANNEL_AUDIO;
  507. header.timestamp = timestamp;
  508. header.length = (uint32_t)bytes;
  509. header.type = RTMP_TYPE_AUDIO;
  510. header.stream_id = ctx->stream_id;
  511. return rtmp_chunk_write(&ctx->rtmp, &header, (const uint8_t*)data);
  512. }
  513. int rtmp_server_send_video(struct rtmp_server_t* ctx, const void* data, size_t bytes, uint32_t timestamp)
  514. {
  515. struct rtmp_chunk_header_t header;
  516. RTMP_SERVER_CHECK_START(ctx);
  517. if (0 == ctx->receiveVideo)
  518. return 0; // client don't want receive video
  519. header.fmt = RTMP_CHUNK_TYPE_1; // enable compact header
  520. header.cid = RTMP_CHANNEL_VIDEO;
  521. header.timestamp = timestamp;
  522. header.length = (uint32_t)bytes;
  523. header.type = RTMP_TYPE_VIDEO;
  524. header.stream_id = ctx->stream_id;
  525. return rtmp_chunk_write(&ctx->rtmp, &header, (const uint8_t*)data);
  526. }
  527. int rtmp_server_send_script(struct rtmp_server_t* ctx, const void* data, size_t bytes, uint32_t timestamp)
  528. {
  529. struct rtmp_chunk_header_t header;
  530. RTMP_SERVER_CHECK_START(ctx);
  531. header.fmt = RTMP_CHUNK_TYPE_1; // enable compact header
  532. header.cid = RTMP_CHANNEL_INVOKE;
  533. header.timestamp = timestamp;
  534. header.length = (uint32_t)bytes;
  535. header.type = RTMP_TYPE_DATA;
  536. header.stream_id = ctx->stream_id;
  537. return rtmp_chunk_write(&ctx->rtmp, &header, (const uint8_t*)data);
  538. }