00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavcodec/bytestream.h"
00028 #include "libavutil/avstring.h"
00029 #include "libavutil/intfloat.h"
00030 #include "libavutil/lfg.h"
00031 #include "libavutil/opt.h"
00032 #include "libavutil/random_seed.h"
00033 #include "libavutil/sha.h"
00034 #include "avformat.h"
00035 #include "internal.h"
00036
00037 #include "network.h"
00038
00039 #include "flv.h"
00040 #include "rtmp.h"
00041 #include "rtmpcrypt.h"
00042 #include "rtmppkt.h"
00043 #include "url.h"
00044
00045 #if CONFIG_ZLIB
00046 #include <zlib.h>
00047 #endif
00048
00049
00050
00051 #define APP_MAX_LENGTH 128
00052 #define PLAYPATH_MAX_LENGTH 256
00053 #define TCURL_MAX_LENGTH 512
00054 #define FLASHVER_MAX_LENGTH 64
00055 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
00056
00058 typedef enum {
00059 STATE_START,
00060 STATE_HANDSHAKED,
00061 STATE_FCPUBLISH,
00062 STATE_PLAYING,
00063 STATE_PUBLISHING,
00064 STATE_RECEIVING,
00065 STATE_STOPPED,
00066 } ClientState;
00067
00068 typedef struct TrackedMethod {
00069 char *name;
00070 int id;
00071 } TrackedMethod;
00072
00074 typedef struct RTMPContext {
00075 const AVClass *class;
00076 URLContext* stream;
00077 RTMPPacket prev_pkt[2][RTMP_CHANNELS];
00078 int in_chunk_size;
00079 int out_chunk_size;
00080 int is_input;
00081 char *playpath;
00082 int live;
00083 char *app;
00084 char *conn;
00085 ClientState state;
00086 int main_channel_id;
00087 uint8_t* flv_data;
00088 int flv_size;
00089 int flv_off;
00090 int flv_nb_packets;
00091 RTMPPacket out_pkt;
00092 uint32_t client_report_size;
00093 uint32_t bytes_read;
00094 uint32_t last_bytes_read;
00095 int skip_bytes;
00096 uint8_t flv_header[11];
00097 int flv_header_bytes;
00098 int nb_invokes;
00099 char* tcurl;
00100 char* flashver;
00101 char* swfhash;
00102 int swfhash_len;
00103 int swfsize;
00104 char* swfurl;
00105 char* swfverify;
00106 char swfverification[42];
00107 char* pageurl;
00108 char* subscribe;
00109 int server_bw;
00110 int client_buffer_time;
00111 int flush_interval;
00112 int encrypted;
00113 TrackedMethod*tracked_methods;
00114 int nb_tracked_methods;
00115 int tracked_methods_size;
00116 int listen;
00117 int listen_timeout;
00118 int nb_streamid;
00119 } RTMPContext;
00120
00121 #define PLAYER_KEY_OPEN_PART_LEN 30
00122
00123 static const uint8_t rtmp_player_key[] = {
00124 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
00125 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
00126
00127 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
00128 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
00129 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
00130 };
00131
00132 #define SERVER_KEY_OPEN_PART_LEN 36
00133
00134 static const uint8_t rtmp_server_key[] = {
00135 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
00136 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
00137 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
00138
00139 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
00140 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
00141 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
00142 };
00143
00144 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
00145 {
00146 void *ptr;
00147
00148 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
00149 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
00150 ptr = av_realloc(rt->tracked_methods,
00151 rt->tracked_methods_size * sizeof(*rt->tracked_methods));
00152 if (!ptr)
00153 return AVERROR(ENOMEM);
00154 rt->tracked_methods = ptr;
00155 }
00156
00157 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
00158 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
00159 return AVERROR(ENOMEM);
00160 rt->tracked_methods[rt->nb_tracked_methods].id = id;
00161 rt->nb_tracked_methods++;
00162
00163 return 0;
00164 }
00165
00166 static void del_tracked_method(RTMPContext *rt, int index)
00167 {
00168 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
00169 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
00170 rt->nb_tracked_methods--;
00171 }
00172
00173 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
00174 char **tracked_method)
00175 {
00176 RTMPContext *rt = s->priv_data;
00177 GetByteContext gbc;
00178 double pkt_id;
00179 int ret;
00180 int i;
00181
00182 bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
00183 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
00184 return ret;
00185
00186 for (i = 0; i < rt->nb_tracked_methods; i++) {
00187 if (rt->tracked_methods[i].id != pkt_id)
00188 continue;
00189
00190 *tracked_method = rt->tracked_methods[i].name;
00191 del_tracked_method(rt, i);
00192 break;
00193 }
00194
00195 return 0;
00196 }
00197
00198 static void free_tracked_methods(RTMPContext *rt)
00199 {
00200 int i;
00201
00202 for (i = 0; i < rt->nb_tracked_methods; i ++)
00203 av_free(rt->tracked_methods[i].name);
00204 av_free(rt->tracked_methods);
00205 }
00206
00207 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
00208 {
00209 int ret;
00210
00211 if (pkt->type == RTMP_PT_INVOKE && track) {
00212 GetByteContext gbc;
00213 char name[128];
00214 double pkt_id;
00215 int len;
00216
00217 bytestream2_init(&gbc, pkt->data, pkt->data_size);
00218 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
00219 goto fail;
00220
00221 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
00222 goto fail;
00223
00224 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
00225 goto fail;
00226 }
00227
00228 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
00229 rt->prev_pkt[1]);
00230 fail:
00231 ff_rtmp_packet_destroy(pkt);
00232 return ret;
00233 }
00234
00235 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
00236 {
00237 char *field, *value;
00238 char type;
00239
00240
00241
00242
00243
00244
00245
00246
00247 if (param[0] && param[1] == ':') {
00248 type = param[0];
00249 value = param + 2;
00250 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
00251 type = param[1];
00252 field = param + 3;
00253 value = strchr(field, ':');
00254 if (!value)
00255 goto fail;
00256 *value = '\0';
00257 value++;
00258
00259 ff_amf_write_field_name(p, field);
00260 } else {
00261 goto fail;
00262 }
00263
00264 switch (type) {
00265 case 'B':
00266 ff_amf_write_bool(p, value[0] != '0');
00267 break;
00268 case 'S':
00269 ff_amf_write_string(p, value);
00270 break;
00271 case 'N':
00272 ff_amf_write_number(p, strtod(value, NULL));
00273 break;
00274 case 'Z':
00275 ff_amf_write_null(p);
00276 break;
00277 case 'O':
00278 if (value[0] != '0')
00279 ff_amf_write_object_start(p);
00280 else
00281 ff_amf_write_object_end(p);
00282 break;
00283 default:
00284 goto fail;
00285 break;
00286 }
00287
00288 return 0;
00289
00290 fail:
00291 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
00292 return AVERROR(EINVAL);
00293 }
00294
00298 static int gen_connect(URLContext *s, RTMPContext *rt)
00299 {
00300 RTMPPacket pkt;
00301 uint8_t *p;
00302 int ret;
00303
00304 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00305 0, 4096)) < 0)
00306 return ret;
00307
00308 p = pkt.data;
00309
00310 ff_amf_write_string(&p, "connect");
00311 ff_amf_write_number(&p, ++rt->nb_invokes);
00312 ff_amf_write_object_start(&p);
00313 ff_amf_write_field_name(&p, "app");
00314 ff_amf_write_string(&p, rt->app);
00315
00316 if (!rt->is_input) {
00317 ff_amf_write_field_name(&p, "type");
00318 ff_amf_write_string(&p, "nonprivate");
00319 }
00320 ff_amf_write_field_name(&p, "flashVer");
00321 ff_amf_write_string(&p, rt->flashver);
00322
00323 if (rt->swfurl) {
00324 ff_amf_write_field_name(&p, "swfUrl");
00325 ff_amf_write_string(&p, rt->swfurl);
00326 }
00327
00328 ff_amf_write_field_name(&p, "tcUrl");
00329 ff_amf_write_string(&p, rt->tcurl);
00330 if (rt->is_input) {
00331 ff_amf_write_field_name(&p, "fpad");
00332 ff_amf_write_bool(&p, 0);
00333 ff_amf_write_field_name(&p, "capabilities");
00334 ff_amf_write_number(&p, 15.0);
00335
00336
00337
00338
00339 ff_amf_write_field_name(&p, "audioCodecs");
00340 ff_amf_write_number(&p, 4071.0);
00341 ff_amf_write_field_name(&p, "videoCodecs");
00342 ff_amf_write_number(&p, 252.0);
00343 ff_amf_write_field_name(&p, "videoFunction");
00344 ff_amf_write_number(&p, 1.0);
00345
00346 if (rt->pageurl) {
00347 ff_amf_write_field_name(&p, "pageUrl");
00348 ff_amf_write_string(&p, rt->pageurl);
00349 }
00350 }
00351 ff_amf_write_object_end(&p);
00352
00353 if (rt->conn) {
00354 char *param = rt->conn;
00355
00356
00357 while (param != NULL) {
00358 char *sep;
00359 param += strspn(param, " ");
00360 if (!*param)
00361 break;
00362 sep = strchr(param, ' ');
00363 if (sep)
00364 *sep = '\0';
00365 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
00366
00367 ff_rtmp_packet_destroy(&pkt);
00368 return ret;
00369 }
00370
00371 if (sep)
00372 param = sep + 1;
00373 else
00374 break;
00375 }
00376 }
00377
00378 pkt.data_size = p - pkt.data;
00379
00380 return rtmp_send_packet(rt, &pkt, 1);
00381 }
00382
00383 static int read_connect(URLContext *s, RTMPContext *rt)
00384 {
00385 RTMPPacket pkt = { 0 };
00386 uint8_t *p;
00387 const uint8_t *cp;
00388 int ret;
00389 char command[64];
00390 int stringlen;
00391 double seqnum;
00392 uint8_t tmpstr[256];
00393 GetByteContext gbc;
00394
00395 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
00396 rt->prev_pkt[1])) < 0)
00397 return ret;
00398 cp = pkt.data;
00399 bytestream2_init(&gbc, cp, pkt.data_size);
00400 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
00401 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
00402 ff_rtmp_packet_destroy(&pkt);
00403 return AVERROR_INVALIDDATA;
00404 }
00405 if (strcmp(command, "connect")) {
00406 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
00407 ff_rtmp_packet_destroy(&pkt);
00408 return AVERROR_INVALIDDATA;
00409 }
00410 ret = ff_amf_read_number(&gbc, &seqnum);
00411 if (ret)
00412 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
00413
00414 ret = ff_amf_get_field_value(gbc.buffer,
00415 gbc.buffer + bytestream2_get_bytes_left(&gbc),
00416 "app", tmpstr, sizeof(tmpstr));
00417 if (ret)
00418 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
00419 if (!ret && strcmp(tmpstr, rt->app))
00420 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
00421 tmpstr, rt->app);
00422 ff_rtmp_packet_destroy(&pkt);
00423
00424
00425 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
00426 RTMP_PT_SERVER_BW, 0, 4)) < 0)
00427 return ret;
00428 p = pkt.data;
00429 bytestream_put_be32(&p, rt->server_bw);
00430 pkt.data_size = p - pkt.data;
00431 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
00432 rt->prev_pkt[1]);
00433 ff_rtmp_packet_destroy(&pkt);
00434 if (ret < 0)
00435 return ret;
00436
00437 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
00438 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
00439 return ret;
00440 p = pkt.data;
00441 bytestream_put_be32(&p, rt->server_bw);
00442 bytestream_put_byte(&p, 2);
00443 pkt.data_size = p - pkt.data;
00444 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
00445 rt->prev_pkt[1]);
00446 ff_rtmp_packet_destroy(&pkt);
00447 if (ret < 0)
00448 return ret;
00449
00450
00451 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
00452 RTMP_PT_PING, 0, 6)) < 0)
00453 return ret;
00454
00455 p = pkt.data;
00456 bytestream_put_be16(&p, 0);
00457 bytestream_put_be32(&p, 0);
00458 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
00459 rt->prev_pkt[1]);
00460 ff_rtmp_packet_destroy(&pkt);
00461 if (ret < 0)
00462 return ret;
00463
00464
00465 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
00466 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
00467 return ret;
00468
00469 p = pkt.data;
00470 bytestream_put_be32(&p, rt->out_chunk_size);
00471 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
00472 rt->prev_pkt[1]);
00473 ff_rtmp_packet_destroy(&pkt);
00474 if (ret < 0)
00475 return ret;
00476
00477
00478 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
00479 RTMP_PT_INVOKE, 0,
00480 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
00481 return ret;
00482
00483 p = pkt.data;
00484 ff_amf_write_string(&p, "_result");
00485 ff_amf_write_number(&p, seqnum);
00486
00487 ff_amf_write_object_start(&p);
00488 ff_amf_write_field_name(&p, "fmsVer");
00489 ff_amf_write_string(&p, "FMS/3,0,1,123");
00490 ff_amf_write_field_name(&p, "capabilities");
00491 ff_amf_write_number(&p, 31);
00492 ff_amf_write_object_end(&p);
00493
00494 ff_amf_write_object_start(&p);
00495 ff_amf_write_field_name(&p, "level");
00496 ff_amf_write_string(&p, "status");
00497 ff_amf_write_field_name(&p, "code");
00498 ff_amf_write_string(&p, "NetConnection.Connect.Success");
00499 ff_amf_write_field_name(&p, "description");
00500 ff_amf_write_string(&p, "Connection succeeded.");
00501 ff_amf_write_field_name(&p, "objectEncoding");
00502 ff_amf_write_number(&p, 0);
00503 ff_amf_write_object_end(&p);
00504
00505 pkt.data_size = p - pkt.data;
00506 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
00507 rt->prev_pkt[1]);
00508 ff_rtmp_packet_destroy(&pkt);
00509 if (ret < 0)
00510 return ret;
00511
00512 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
00513 RTMP_PT_INVOKE, 0, 30)) < 0)
00514 return ret;
00515 p = pkt.data;
00516 ff_amf_write_string(&p, "onBWDone");
00517 ff_amf_write_number(&p, 0);
00518 ff_amf_write_null(&p);
00519 ff_amf_write_number(&p, 8192);
00520 pkt.data_size = p - pkt.data;
00521 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
00522 rt->prev_pkt[1]);
00523 ff_rtmp_packet_destroy(&pkt);
00524
00525 return ret;
00526 }
00527
00532 static int gen_release_stream(URLContext *s, RTMPContext *rt)
00533 {
00534 RTMPPacket pkt;
00535 uint8_t *p;
00536 int ret;
00537
00538 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00539 0, 29 + strlen(rt->playpath))) < 0)
00540 return ret;
00541
00542 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
00543 p = pkt.data;
00544 ff_amf_write_string(&p, "releaseStream");
00545 ff_amf_write_number(&p, ++rt->nb_invokes);
00546 ff_amf_write_null(&p);
00547 ff_amf_write_string(&p, rt->playpath);
00548
00549 return rtmp_send_packet(rt, &pkt, 1);
00550 }
00551
00556 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
00557 {
00558 RTMPPacket pkt;
00559 uint8_t *p;
00560 int ret;
00561
00562 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00563 0, 25 + strlen(rt->playpath))) < 0)
00564 return ret;
00565
00566 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
00567 p = pkt.data;
00568 ff_amf_write_string(&p, "FCPublish");
00569 ff_amf_write_number(&p, ++rt->nb_invokes);
00570 ff_amf_write_null(&p);
00571 ff_amf_write_string(&p, rt->playpath);
00572
00573 return rtmp_send_packet(rt, &pkt, 1);
00574 }
00575
00580 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
00581 {
00582 RTMPPacket pkt;
00583 uint8_t *p;
00584 int ret;
00585
00586 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00587 0, 27 + strlen(rt->playpath))) < 0)
00588 return ret;
00589
00590 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
00591 p = pkt.data;
00592 ff_amf_write_string(&p, "FCUnpublish");
00593 ff_amf_write_number(&p, ++rt->nb_invokes);
00594 ff_amf_write_null(&p);
00595 ff_amf_write_string(&p, rt->playpath);
00596
00597 return rtmp_send_packet(rt, &pkt, 0);
00598 }
00599
00604 static int gen_create_stream(URLContext *s, RTMPContext *rt)
00605 {
00606 RTMPPacket pkt;
00607 uint8_t *p;
00608 int ret;
00609
00610 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
00611
00612 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00613 0, 25)) < 0)
00614 return ret;
00615
00616 p = pkt.data;
00617 ff_amf_write_string(&p, "createStream");
00618 ff_amf_write_number(&p, ++rt->nb_invokes);
00619 ff_amf_write_null(&p);
00620
00621 return rtmp_send_packet(rt, &pkt, 1);
00622 }
00623
00624
00629 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
00630 {
00631 RTMPPacket pkt;
00632 uint8_t *p;
00633 int ret;
00634
00635 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
00636
00637 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00638 0, 34)) < 0)
00639 return ret;
00640
00641 p = pkt.data;
00642 ff_amf_write_string(&p, "deleteStream");
00643 ff_amf_write_number(&p, ++rt->nb_invokes);
00644 ff_amf_write_null(&p);
00645 ff_amf_write_number(&p, rt->main_channel_id);
00646
00647 return rtmp_send_packet(rt, &pkt, 0);
00648 }
00649
00653 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
00654 {
00655 RTMPPacket pkt;
00656 uint8_t *p;
00657 int ret;
00658
00659 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
00660 1, 10)) < 0)
00661 return ret;
00662
00663 p = pkt.data;
00664 bytestream_put_be16(&p, 3);
00665 bytestream_put_be32(&p, rt->main_channel_id);
00666 bytestream_put_be32(&p, rt->client_buffer_time);
00667
00668 return rtmp_send_packet(rt, &pkt, 0);
00669 }
00670
00675 static int gen_play(URLContext *s, RTMPContext *rt)
00676 {
00677 RTMPPacket pkt;
00678 uint8_t *p;
00679 int ret;
00680
00681 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
00682
00683 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
00684 0, 29 + strlen(rt->playpath))) < 0)
00685 return ret;
00686
00687 pkt.extra = rt->main_channel_id;
00688
00689 p = pkt.data;
00690 ff_amf_write_string(&p, "play");
00691 ff_amf_write_number(&p, ++rt->nb_invokes);
00692 ff_amf_write_null(&p);
00693 ff_amf_write_string(&p, rt->playpath);
00694 ff_amf_write_number(&p, rt->live);
00695
00696 return rtmp_send_packet(rt, &pkt, 1);
00697 }
00698
00702 static int gen_publish(URLContext *s, RTMPContext *rt)
00703 {
00704 RTMPPacket pkt;
00705 uint8_t *p;
00706 int ret;
00707
00708 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
00709
00710 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
00711 0, 30 + strlen(rt->playpath))) < 0)
00712 return ret;
00713
00714 pkt.extra = rt->main_channel_id;
00715
00716 p = pkt.data;
00717 ff_amf_write_string(&p, "publish");
00718 ff_amf_write_number(&p, ++rt->nb_invokes);
00719 ff_amf_write_null(&p);
00720 ff_amf_write_string(&p, rt->playpath);
00721 ff_amf_write_string(&p, "live");
00722
00723 return rtmp_send_packet(rt, &pkt, 1);
00724 }
00725
00729 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
00730 {
00731 RTMPPacket pkt;
00732 uint8_t *p;
00733 int ret;
00734
00735 if (ppkt->data_size < 6) {
00736 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
00737 ppkt->data_size);
00738 return AVERROR_INVALIDDATA;
00739 }
00740
00741 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
00742 ppkt->timestamp + 1, 6)) < 0)
00743 return ret;
00744
00745 p = pkt.data;
00746 bytestream_put_be16(&p, 7);
00747 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
00748
00749 return rtmp_send_packet(rt, &pkt, 0);
00750 }
00751
00755 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
00756 {
00757 RTMPPacket pkt;
00758 uint8_t *p;
00759 int ret;
00760
00761 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
00762 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
00763 0, 44)) < 0)
00764 return ret;
00765
00766 p = pkt.data;
00767 bytestream_put_be16(&p, 27);
00768 memcpy(p, rt->swfverification, 42);
00769
00770 return rtmp_send_packet(rt, &pkt, 0);
00771 }
00772
00776 static int gen_server_bw(URLContext *s, RTMPContext *rt)
00777 {
00778 RTMPPacket pkt;
00779 uint8_t *p;
00780 int ret;
00781
00782 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
00783 0, 4)) < 0)
00784 return ret;
00785
00786 p = pkt.data;
00787 bytestream_put_be32(&p, rt->server_bw);
00788
00789 return rtmp_send_packet(rt, &pkt, 0);
00790 }
00791
00795 static int gen_check_bw(URLContext *s, RTMPContext *rt)
00796 {
00797 RTMPPacket pkt;
00798 uint8_t *p;
00799 int ret;
00800
00801 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00802 0, 21)) < 0)
00803 return ret;
00804
00805 p = pkt.data;
00806 ff_amf_write_string(&p, "_checkbw");
00807 ff_amf_write_number(&p, ++rt->nb_invokes);
00808 ff_amf_write_null(&p);
00809
00810 return rtmp_send_packet(rt, &pkt, 1);
00811 }
00812
00816 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
00817 {
00818 RTMPPacket pkt;
00819 uint8_t *p;
00820 int ret;
00821
00822 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
00823 ts, 4)) < 0)
00824 return ret;
00825
00826 p = pkt.data;
00827 bytestream_put_be32(&p, rt->bytes_read);
00828
00829 return rtmp_send_packet(rt, &pkt, 0);
00830 }
00831
00832 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
00833 const char *subscribe)
00834 {
00835 RTMPPacket pkt;
00836 uint8_t *p;
00837 int ret;
00838
00839 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00840 0, 27 + strlen(subscribe))) < 0)
00841 return ret;
00842
00843 p = pkt.data;
00844 ff_amf_write_string(&p, "FCSubscribe");
00845 ff_amf_write_number(&p, ++rt->nb_invokes);
00846 ff_amf_write_null(&p);
00847 ff_amf_write_string(&p, subscribe);
00848
00849 return rtmp_send_packet(rt, &pkt, 1);
00850 }
00851
00852 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
00853 const uint8_t *key, int keylen, uint8_t *dst)
00854 {
00855 struct AVSHA *sha;
00856 uint8_t hmac_buf[64+32] = {0};
00857 int i;
00858
00859 sha = av_sha_alloc();
00860 if (!sha)
00861 return AVERROR(ENOMEM);
00862
00863 if (keylen < 64) {
00864 memcpy(hmac_buf, key, keylen);
00865 } else {
00866 av_sha_init(sha, 256);
00867 av_sha_update(sha,key, keylen);
00868 av_sha_final(sha, hmac_buf);
00869 }
00870 for (i = 0; i < 64; i++)
00871 hmac_buf[i] ^= HMAC_IPAD_VAL;
00872
00873 av_sha_init(sha, 256);
00874 av_sha_update(sha, hmac_buf, 64);
00875 if (gap <= 0) {
00876 av_sha_update(sha, src, len);
00877 } else {
00878 av_sha_update(sha, src, gap);
00879 av_sha_update(sha, src + gap + 32, len - gap - 32);
00880 }
00881 av_sha_final(sha, hmac_buf + 64);
00882
00883 for (i = 0; i < 64; i++)
00884 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL;
00885 av_sha_init(sha, 256);
00886 av_sha_update(sha, hmac_buf, 64+32);
00887 av_sha_final(sha, dst);
00888
00889 av_free(sha);
00890
00891 return 0;
00892 }
00893
00894 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
00895 int add_val)
00896 {
00897 int i, digest_pos = 0;
00898
00899 for (i = 0; i < 4; i++)
00900 digest_pos += buf[i + off];
00901 digest_pos = digest_pos % mod_val + add_val;
00902
00903 return digest_pos;
00904 }
00905
00914 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
00915 {
00916 int ret, digest_pos;
00917
00918 if (encrypted)
00919 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
00920 else
00921 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
00922
00923 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
00924 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
00925 buf + digest_pos);
00926 if (ret < 0)
00927 return ret;
00928
00929 return digest_pos;
00930 }
00931
00939 static int rtmp_validate_digest(uint8_t *buf, int off)
00940 {
00941 uint8_t digest[32];
00942 int ret, digest_pos;
00943
00944 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
00945
00946 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
00947 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
00948 digest);
00949 if (ret < 0)
00950 return ret;
00951
00952 if (!memcmp(digest, buf + digest_pos, 32))
00953 return digest_pos;
00954 return 0;
00955 }
00956
00957 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
00958 uint8_t *buf)
00959 {
00960 uint8_t *p;
00961 int ret;
00962
00963 if (rt->swfhash_len != 32) {
00964 av_log(s, AV_LOG_ERROR,
00965 "Hash of the decompressed SWF file is not 32 bytes long.\n");
00966 return AVERROR(EINVAL);
00967 }
00968
00969 p = &rt->swfverification[0];
00970 bytestream_put_byte(&p, 1);
00971 bytestream_put_byte(&p, 1);
00972 bytestream_put_be32(&p, rt->swfsize);
00973 bytestream_put_be32(&p, rt->swfsize);
00974
00975 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
00976 return ret;
00977
00978 return 0;
00979 }
00980
00981 #if CONFIG_ZLIB
00982 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
00983 uint8_t **out_data, int64_t *out_size)
00984 {
00985 z_stream zs = { 0 };
00986 void *ptr;
00987 int size;
00988 int ret = 0;
00989
00990 zs.avail_in = in_size;
00991 zs.next_in = in_data;
00992 ret = inflateInit(&zs);
00993 if (ret != Z_OK)
00994 return AVERROR_UNKNOWN;
00995
00996 do {
00997 uint8_t tmp_buf[16384];
00998
00999 zs.avail_out = sizeof(tmp_buf);
01000 zs.next_out = tmp_buf;
01001
01002 ret = inflate(&zs, Z_NO_FLUSH);
01003 if (ret != Z_OK && ret != Z_STREAM_END) {
01004 ret = AVERROR_UNKNOWN;
01005 goto fail;
01006 }
01007
01008 size = sizeof(tmp_buf) - zs.avail_out;
01009 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
01010 ret = AVERROR(ENOMEM);
01011 goto fail;
01012 }
01013 *out_data = ptr;
01014
01015 memcpy(*out_data + *out_size, tmp_buf, size);
01016 *out_size += size;
01017 } while (zs.avail_out == 0);
01018
01019 fail:
01020 inflateEnd(&zs);
01021 return ret;
01022 }
01023 #endif
01024
01025 static int rtmp_calc_swfhash(URLContext *s)
01026 {
01027 RTMPContext *rt = s->priv_data;
01028 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
01029 int64_t in_size, out_size;
01030 URLContext *stream;
01031 char swfhash[32];
01032 int swfsize;
01033 int ret = 0;
01034
01035
01036 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
01037 &s->interrupt_callback, NULL)) < 0) {
01038 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
01039 goto fail;
01040 }
01041
01042 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
01043 ret = AVERROR(EIO);
01044 goto fail;
01045 }
01046
01047 if (!(in_data = av_malloc(in_size))) {
01048 ret = AVERROR(ENOMEM);
01049 goto fail;
01050 }
01051
01052 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
01053 goto fail;
01054
01055 if (in_size < 3) {
01056 ret = AVERROR_INVALIDDATA;
01057 goto fail;
01058 }
01059
01060 if (!memcmp(in_data, "CWS", 3)) {
01061
01062 if (!(out_data = av_malloc(8))) {
01063 ret = AVERROR(ENOMEM);
01064 goto fail;
01065 }
01066 *in_data = 'F';
01067 memcpy(out_data, in_data, 8);
01068 out_size = 8;
01069
01070 #if CONFIG_ZLIB
01071 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
01072 &out_data, &out_size)) < 0)
01073 goto fail;
01074 #else
01075 av_log(s, AV_LOG_ERROR,
01076 "Zlib is required for decompressing the SWF player file.\n");
01077 ret = AVERROR(EINVAL);
01078 goto fail;
01079 #endif
01080 swfsize = out_size;
01081 swfdata = out_data;
01082 } else {
01083 swfsize = in_size;
01084 swfdata = in_data;
01085 }
01086
01087
01088 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
01089 "Genuine Adobe Flash Player 001", 30,
01090 swfhash)) < 0)
01091 goto fail;
01092
01093
01094 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
01095 rt->swfsize = swfsize;
01096
01097 fail:
01098 av_freep(&in_data);
01099 av_freep(&out_data);
01100 ffurl_close(stream);
01101 return ret;
01102 }
01103
01110 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
01111 {
01112 AVLFG rnd;
01113 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
01114 3,
01115 0, 0, 0, 0,
01116 RTMP_CLIENT_VER1,
01117 RTMP_CLIENT_VER2,
01118 RTMP_CLIENT_VER3,
01119 RTMP_CLIENT_VER4,
01120 };
01121 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
01122 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
01123 int i;
01124 int server_pos, client_pos;
01125 uint8_t digest[32], signature[32];
01126 int ret, type = 0;
01127
01128 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
01129
01130 av_lfg_init(&rnd, 0xDEADC0DE);
01131
01132 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
01133 tosend[i] = av_lfg_get(&rnd) >> 24;
01134
01135 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
01136
01137
01138
01139 tosend[0] = 6;
01140 tosend[5] = 128;
01141 tosend[6] = 0;
01142 tosend[7] = 3;
01143 tosend[8] = 2;
01144
01145
01146
01147 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
01148 return ret;
01149 }
01150
01151 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
01152 if (client_pos < 0)
01153 return client_pos;
01154
01155 if ((ret = ffurl_write(rt->stream, tosend,
01156 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
01157 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
01158 return ret;
01159 }
01160
01161 if ((ret = ffurl_read_complete(rt->stream, serverdata,
01162 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
01163 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
01164 return ret;
01165 }
01166
01167 if ((ret = ffurl_read_complete(rt->stream, clientdata,
01168 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
01169 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
01170 return ret;
01171 }
01172
01173 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
01174 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
01175 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
01176
01177 if (rt->is_input && serverdata[5] >= 3) {
01178 server_pos = rtmp_validate_digest(serverdata + 1, 772);
01179 if (server_pos < 0)
01180 return server_pos;
01181
01182 if (!server_pos) {
01183 type = 1;
01184 server_pos = rtmp_validate_digest(serverdata + 1, 8);
01185 if (server_pos < 0)
01186 return server_pos;
01187
01188 if (!server_pos) {
01189 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
01190 return AVERROR(EIO);
01191 }
01192 }
01193
01194
01195
01196 if (rt->swfsize) {
01197 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
01198 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
01199 return ret;
01200 }
01201
01202 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
01203 rtmp_server_key, sizeof(rtmp_server_key),
01204 digest);
01205 if (ret < 0)
01206 return ret;
01207
01208 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
01209 0, digest, 32, signature);
01210 if (ret < 0)
01211 return ret;
01212
01213 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
01214
01215
01216 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
01217 tosend + 1, type)) < 0)
01218 return ret;
01219
01220
01221 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
01222 }
01223
01224 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
01225 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
01226 return AVERROR(EIO);
01227 }
01228
01229 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
01230 tosend[i] = av_lfg_get(&rnd) >> 24;
01231 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
01232 rtmp_player_key, sizeof(rtmp_player_key),
01233 digest);
01234 if (ret < 0)
01235 return ret;
01236
01237 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
01238 digest, 32,
01239 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
01240 if (ret < 0)
01241 return ret;
01242
01243 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
01244
01245 ff_rtmpe_encrypt_sig(rt->stream, tosend +
01246 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
01247 serverdata[0]);
01248 }
01249
01250
01251 if ((ret = ffurl_write(rt->stream, tosend,
01252 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
01253 return ret;
01254
01255 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
01256
01257 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
01258 return ret;
01259 }
01260 } else {
01261 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
01262
01263
01264 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
01265 tosend + 1, 1)) < 0)
01266 return ret;
01267
01268 if (serverdata[0] == 9) {
01269
01270 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
01271 serverdata[0]);
01272 }
01273 }
01274
01275 if ((ret = ffurl_write(rt->stream, serverdata + 1,
01276 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
01277 return ret;
01278
01279 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
01280
01281 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
01282 return ret;
01283 }
01284 }
01285
01286 return 0;
01287 }
01288
01289 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
01290 uint32_t *second_int, char *arraydata,
01291 int size)
01292 {
01293 int inoutsize;
01294
01295 inoutsize = ffurl_read_complete(rt->stream, arraydata,
01296 RTMP_HANDSHAKE_PACKET_SIZE);
01297 if (inoutsize <= 0)
01298 return AVERROR(EIO);
01299 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
01300 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
01301 " not following standard\n", (int)inoutsize);
01302 return AVERROR(EINVAL);
01303 }
01304
01305 *first_int = AV_RB32(arraydata);
01306 *second_int = AV_RB32(arraydata + 4);
01307 return 0;
01308 }
01309
01310 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
01311 uint32_t second_int, char *arraydata, int size)
01312 {
01313 int inoutsize;
01314
01315 AV_WB32(arraydata, first_int);
01316 AV_WB32(arraydata + 4, first_int);
01317 inoutsize = ffurl_write(rt->stream, arraydata,
01318 RTMP_HANDSHAKE_PACKET_SIZE);
01319 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
01320 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
01321 return AVERROR(EIO);
01322 }
01323
01324 return 0;
01325 }
01326
01330 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
01331 {
01332 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
01333 uint32_t hs_epoch;
01334 uint32_t hs_my_epoch;
01335 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
01336 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
01337 uint32_t zeroes;
01338 uint32_t temp = 0;
01339 int randomidx = 0;
01340 int inoutsize = 0;
01341 int ret;
01342
01343 inoutsize = ffurl_read_complete(rt->stream, buffer, 1);
01344 if (inoutsize <= 0) {
01345 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
01346 return AVERROR(EIO);
01347 }
01348
01349 if (buffer[0] != 3) {
01350 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
01351 return AVERROR(EIO);
01352 }
01353 if (ffurl_write(rt->stream, buffer, 1) <= 0) {
01354 av_log(s, AV_LOG_ERROR,
01355 "Unable to write answer - RTMP S0\n");
01356 return AVERROR(EIO);
01357 }
01358
01359 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
01360 RTMP_HANDSHAKE_PACKET_SIZE);
01361 if (ret) {
01362 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
01363 return ret;
01364 }
01365 if (zeroes)
01366 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
01367
01368
01369 hs_my_epoch = hs_epoch;
01370
01371 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
01372 randomidx += 4)
01373 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
01374
01375 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
01376 RTMP_HANDSHAKE_PACKET_SIZE);
01377 if (ret) {
01378 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
01379 return ret;
01380 }
01381
01382 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
01383 RTMP_HANDSHAKE_PACKET_SIZE);
01384 if (ret) {
01385 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
01386 return ret;
01387 }
01388
01389 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
01390 RTMP_HANDSHAKE_PACKET_SIZE);
01391 if (ret) {
01392 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
01393 return ret;
01394 }
01395 if (temp != hs_my_epoch)
01396 av_log(s, AV_LOG_WARNING,
01397 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
01398 if (memcmp(buffer + 8, hs_s1 + 8,
01399 RTMP_HANDSHAKE_PACKET_SIZE - 8))
01400 av_log(s, AV_LOG_WARNING,
01401 "Erroneous C2 Message random does not match up\n");
01402
01403 return 0;
01404 }
01405
01406 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
01407 {
01408 RTMPContext *rt = s->priv_data;
01409 int ret;
01410
01411 if (pkt->data_size < 4) {
01412 av_log(s, AV_LOG_ERROR,
01413 "Too short chunk size change packet (%d)\n",
01414 pkt->data_size);
01415 return AVERROR_INVALIDDATA;
01416 }
01417
01418 if (!rt->is_input) {
01419
01420
01421 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
01422 rt->prev_pkt[1])) < 0)
01423 return ret;
01424 rt->out_chunk_size = AV_RB32(pkt->data);
01425 }
01426
01427 rt->in_chunk_size = AV_RB32(pkt->data);
01428 if (rt->in_chunk_size <= 0) {
01429 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
01430 rt->in_chunk_size);
01431 return AVERROR_INVALIDDATA;
01432 }
01433 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
01434 rt->in_chunk_size);
01435
01436 return 0;
01437 }
01438
01439 static int handle_ping(URLContext *s, RTMPPacket *pkt)
01440 {
01441 RTMPContext *rt = s->priv_data;
01442 int t, ret;
01443
01444 if (pkt->data_size < 2) {
01445 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
01446 pkt->data_size);
01447 return AVERROR_INVALIDDATA;
01448 }
01449
01450 t = AV_RB16(pkt->data);
01451 if (t == 6) {
01452 if ((ret = gen_pong(s, rt, pkt)) < 0)
01453 return ret;
01454 } else if (t == 26) {
01455 if (rt->swfsize) {
01456 if ((ret = gen_swf_verification(s, rt)) < 0)
01457 return ret;
01458 } else {
01459 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
01460 }
01461 }
01462
01463 return 0;
01464 }
01465
01466 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
01467 {
01468 RTMPContext *rt = s->priv_data;
01469
01470 if (pkt->data_size < 4) {
01471 av_log(s, AV_LOG_ERROR,
01472 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
01473 pkt->data_size);
01474 return AVERROR_INVALIDDATA;
01475 }
01476
01477 rt->client_report_size = AV_RB32(pkt->data);
01478 if (rt->client_report_size <= 0) {
01479 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
01480 rt->client_report_size);
01481 return AVERROR_INVALIDDATA;
01482
01483 }
01484 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
01485 rt->client_report_size >>= 1;
01486
01487 return 0;
01488 }
01489
01490 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
01491 {
01492 RTMPContext *rt = s->priv_data;
01493
01494 if (pkt->data_size < 4) {
01495 av_log(s, AV_LOG_ERROR,
01496 "Too short server bandwidth report packet (%d)\n",
01497 pkt->data_size);
01498 return AVERROR_INVALIDDATA;
01499 }
01500
01501 rt->server_bw = AV_RB32(pkt->data);
01502 if (rt->server_bw <= 0) {
01503 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
01504 rt->server_bw);
01505 return AVERROR_INVALIDDATA;
01506 }
01507 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
01508
01509 return 0;
01510 }
01511
01512 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
01513 {
01514 const uint8_t *data_end = pkt->data + pkt->data_size;
01515 char *tracked_method = NULL;
01516 int level = AV_LOG_ERROR;
01517 uint8_t tmpstr[256];
01518 int ret;
01519
01520 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
01521 return ret;
01522
01523 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
01524 "description", tmpstr, sizeof(tmpstr))) {
01525 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
01526 !strcmp(tracked_method, "releaseStream") ||
01527 !strcmp(tracked_method, "FCSubscribe") ||
01528 !strcmp(tracked_method, "FCPublish"))) {
01529
01530 level = AV_LOG_WARNING;
01531 ret = 0;
01532 } else
01533 ret = -1;
01534 av_log(s, level, "Server error: %s\n", tmpstr);
01535 }
01536
01537 av_free(tracked_method);
01538 return ret;
01539 }
01540
01541 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
01542 {
01543 RTMPContext *rt = s->priv_data;
01544 double seqnum;
01545 char filename[64];
01546 char command[64];
01547 char statusmsg[128];
01548 int stringlen;
01549 char *pchar;
01550 const uint8_t *p = pkt->data;
01551 uint8_t *pp = NULL;
01552 RTMPPacket spkt = { 0 };
01553 GetByteContext gbc;
01554 int ret;
01555
01556 bytestream2_init(&gbc, p, pkt->data_size);
01557 if (ff_amf_read_string(&gbc, command, sizeof(command),
01558 &stringlen)) {
01559 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
01560 return AVERROR_INVALIDDATA;
01561 }
01562
01563 ret = ff_amf_read_number(&gbc, &seqnum);
01564 if (ret)
01565 return ret;
01566 ret = ff_amf_read_null(&gbc);
01567 if (ret)
01568 return ret;
01569 if (!strcmp(command, "FCPublish") ||
01570 !strcmp(command, "publish")) {
01571 ret = ff_amf_read_string(&gbc, filename,
01572 sizeof(filename), &stringlen);
01573
01574 if (s->filename) {
01575 pchar = strrchr(s->filename, '/');
01576 if (!pchar) {
01577 av_log(s, AV_LOG_WARNING,
01578 "Unable to find / in url %s, bad format\n",
01579 s->filename);
01580 pchar = s->filename;
01581 }
01582 pchar++;
01583 if (strcmp(pchar, filename))
01584 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
01585 " %s\n", filename, pchar);
01586 }
01587 rt->state = STATE_RECEIVING;
01588 }
01589
01590 if (!strcmp(command, "FCPublish")) {
01591 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
01592 RTMP_PT_INVOKE, 0,
01593 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
01594 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
01595 return ret;
01596 }
01597 pp = spkt.data;
01598 ff_amf_write_string(&pp, "onFCPublish");
01599 } else if (!strcmp(command, "publish")) {
01600 PutByteContext pbc;
01601
01602 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
01603 RTMP_PT_PING, 0, 6)) < 0) {
01604 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
01605 return ret;
01606 }
01607 pp = spkt.data;
01608 bytestream2_init_writer(&pbc, pp, spkt.data_size);
01609 bytestream2_put_be16(&pbc, 0);
01610 bytestream2_put_be32(&pbc, rt->nb_streamid);
01611 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
01612 rt->prev_pkt[1]);
01613 ff_rtmp_packet_destroy(&spkt);
01614 if (ret < 0)
01615 return ret;
01616
01617
01618 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
01619 RTMP_PT_INVOKE, 0,
01620 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
01621 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
01622 return ret;
01623 }
01624 spkt.extra = pkt->extra;
01625 pp = spkt.data;
01626 ff_amf_write_string(&pp, "onStatus");
01627 ff_amf_write_number(&pp, 0);
01628 ff_amf_write_null(&pp);
01629
01630 ff_amf_write_object_start(&pp);
01631 ff_amf_write_field_name(&pp, "level");
01632 ff_amf_write_string(&pp, "status");
01633 ff_amf_write_field_name(&pp, "code");
01634 ff_amf_write_string(&pp, "NetStream.Publish.Start");
01635 ff_amf_write_field_name(&pp, "description");
01636 snprintf(statusmsg, sizeof(statusmsg),
01637 "%s is now published", filename);
01638 ff_amf_write_string(&pp, statusmsg);
01639 ff_amf_write_field_name(&pp, "details");
01640 ff_amf_write_string(&pp, filename);
01641 ff_amf_write_field_name(&pp, "clientid");
01642 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
01643 ff_amf_write_string(&pp, statusmsg);
01644 ff_amf_write_object_end(&pp);
01645
01646 } else {
01647 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
01648 RTMP_PT_INVOKE, 0,
01649 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
01650 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
01651 return ret;
01652 }
01653 pp = spkt.data;
01654 ff_amf_write_string(&pp, "_result");
01655 ff_amf_write_number(&pp, seqnum);
01656 ff_amf_write_null(&pp);
01657 if (!strcmp(command, "createStream")) {
01658 rt->nb_streamid++;
01659 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
01660 rt->nb_streamid++;
01661 ff_amf_write_number(&pp, rt->nb_streamid);
01662
01663
01664
01665 }
01666 }
01667 spkt.data_size = pp - spkt.data;
01668 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
01669 rt->prev_pkt[1]);
01670 ff_rtmp_packet_destroy(&spkt);
01671 return ret;
01672 }
01673
01674 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
01675 {
01676 RTMPContext *rt = s->priv_data;
01677 char *tracked_method = NULL;
01678 int ret = 0;
01679
01680 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
01681 return ret;
01682
01683 if (!tracked_method) {
01684
01685 return ret;
01686 }
01687
01688 if (!memcmp(tracked_method, "connect", 7)) {
01689 if (!rt->is_input) {
01690 if ((ret = gen_release_stream(s, rt)) < 0)
01691 goto fail;
01692
01693 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
01694 goto fail;
01695 } else {
01696 if ((ret = gen_server_bw(s, rt)) < 0)
01697 goto fail;
01698 }
01699
01700 if ((ret = gen_create_stream(s, rt)) < 0)
01701 goto fail;
01702
01703 if (rt->is_input) {
01704
01705
01706 if (rt->subscribe) {
01707 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
01708 goto fail;
01709 } else if (rt->live == -1) {
01710 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
01711 goto fail;
01712 }
01713 }
01714 } else if (!memcmp(tracked_method, "createStream", 12)) {
01715
01716 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
01717 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
01718 } else {
01719 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
01720 }
01721
01722 if (!rt->is_input) {
01723 if ((ret = gen_publish(s, rt)) < 0)
01724 goto fail;
01725 } else {
01726 if ((ret = gen_play(s, rt)) < 0)
01727 goto fail;
01728 if ((ret = gen_buffer_time(s, rt)) < 0)
01729 goto fail;
01730 }
01731 }
01732
01733 fail:
01734 av_free(tracked_method);
01735 return ret;
01736 }
01737
01738 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
01739 {
01740 RTMPContext *rt = s->priv_data;
01741 const uint8_t *data_end = pkt->data + pkt->data_size;
01742 const uint8_t *ptr = pkt->data + 11;
01743 uint8_t tmpstr[256];
01744 int i, t;
01745
01746 for (i = 0; i < 2; i++) {
01747 t = ff_amf_tag_size(ptr, data_end);
01748 if (t < 0)
01749 return 1;
01750 ptr += t;
01751 }
01752
01753 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
01754 if (!t && !strcmp(tmpstr, "error")) {
01755 if (!ff_amf_get_field_value(ptr, data_end,
01756 "description", tmpstr, sizeof(tmpstr)))
01757 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
01758 return -1;
01759 }
01760
01761 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
01762 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
01763 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
01764 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
01765 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
01766
01767 return 0;
01768 }
01769
01770 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
01771 {
01772 RTMPContext *rt = s->priv_data;
01773 int ret = 0;
01774
01775
01776 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
01777 if ((ret = handle_invoke_error(s, pkt)) < 0)
01778 return ret;
01779 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
01780 if ((ret = handle_invoke_result(s, pkt)) < 0)
01781 return ret;
01782 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
01783 if ((ret = handle_invoke_status(s, pkt)) < 0)
01784 return ret;
01785 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
01786 if ((ret = gen_check_bw(s, rt)) < 0)
01787 return ret;
01788 } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
01789 !memcmp(pkt->data, "\002\000\011FCPublish", 12) ||
01790 !memcmp(pkt->data, "\002\000\007publish", 10) ||
01791 !memcmp(pkt->data, "\002\000\010_checkbw", 11) ||
01792 !memcmp(pkt->data, "\002\000\014createStream", 15)) {
01793 if (ret = send_invoke_response(s, pkt) < 0)
01794 return ret;
01795 }
01796
01797 return ret;
01798 }
01799
01800 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
01801 RTMPContext *rt = s->priv_data;
01802 const uint8_t *p = NULL;
01803 uint8_t *cp = NULL;
01804 uint8_t commandbuffer[64];
01805 char statusmsg[128];
01806 int stringlen;
01807 GetByteContext gbc;
01808 PutByteContext pbc;
01809 uint32_t ts;
01810 int old_flv_size;
01811 const uint8_t *datatowrite;
01812 unsigned datatowritelength;
01813
01814 p = pkt->data;
01815 bytestream2_init(&gbc, p, pkt->data_size);
01816 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
01817 &stringlen))
01818 return AVERROR_INVALIDDATA;
01819 if (!strcmp(commandbuffer, "@setDataFrame")) {
01820 datatowrite = gbc.buffer;
01821 datatowritelength = bytestream2_get_bytes_left(&gbc);
01822 if (ff_amf_read_string(&gbc, statusmsg,
01823 sizeof(statusmsg), &stringlen))
01824 return AVERROR_INVALIDDATA;
01825 if (strcmp(statusmsg, "onMetaData")) {
01826 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
01827 statusmsg);
01828 return 0;
01829 }
01830
01831
01832 ts = pkt->timestamp;
01833
01834
01835 if (rt->flv_off < rt->flv_size) {
01836 old_flv_size = rt->flv_size;
01837 rt->flv_size += datatowritelength + 15;
01838 } else {
01839 old_flv_size = 0;
01840 rt->flv_size = datatowritelength + 15;
01841 rt->flv_off = 0;
01842 }
01843
01844 cp = av_realloc(rt->flv_data, rt->flv_size);
01845 if (!cp)
01846 return AVERROR(ENOMEM);
01847 rt->flv_data = cp;
01848 bytestream2_init_writer(&pbc, cp, rt->flv_size);
01849 bytestream2_skip_p(&pbc, old_flv_size);
01850 bytestream2_put_byte(&pbc, pkt->type);
01851 bytestream2_put_be24(&pbc, datatowritelength);
01852 bytestream2_put_be24(&pbc, ts);
01853 bytestream2_put_byte(&pbc, ts >> 24);
01854 bytestream2_put_be24(&pbc, 0);
01855 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
01856 bytestream2_put_be32(&pbc, 0);
01857 }
01858 return 0;
01859 }
01860
01867 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
01868 {
01869 int ret;
01870
01871 #ifdef DEBUG
01872 ff_rtmp_packet_dump(s, pkt);
01873 #endif
01874
01875 switch (pkt->type) {
01876 case RTMP_PT_BYTES_READ:
01877 av_dlog(s, "received bytes read report\n");
01878 break;
01879 case RTMP_PT_CHUNK_SIZE:
01880 if ((ret = handle_chunk_size(s, pkt)) < 0)
01881 return ret;
01882 break;
01883 case RTMP_PT_PING:
01884 if ((ret = handle_ping(s, pkt)) < 0)
01885 return ret;
01886 break;
01887 case RTMP_PT_CLIENT_BW:
01888 if ((ret = handle_client_bw(s, pkt)) < 0)
01889 return ret;
01890 break;
01891 case RTMP_PT_SERVER_BW:
01892 if ((ret = handle_server_bw(s, pkt)) < 0)
01893 return ret;
01894 break;
01895 case RTMP_PT_INVOKE:
01896 if ((ret = handle_invoke(s, pkt)) < 0)
01897 return ret;
01898 break;
01899 case RTMP_PT_VIDEO:
01900 case RTMP_PT_AUDIO:
01901 case RTMP_PT_METADATA:
01902 case RTMP_PT_NOTIFY:
01903
01904 break;
01905 default:
01906 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
01907 break;
01908 }
01909 return 0;
01910 }
01911
01923 static int get_packet(URLContext *s, int for_header)
01924 {
01925 RTMPContext *rt = s->priv_data;
01926 int ret;
01927 uint8_t *p;
01928 const uint8_t *next;
01929 uint32_t data_size;
01930 uint32_t ts, cts, pts=0;
01931
01932 if (rt->state == STATE_STOPPED)
01933 return AVERROR_EOF;
01934
01935 for (;;) {
01936 RTMPPacket rpkt = { 0 };
01937 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
01938 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
01939 if (ret == 0) {
01940 return AVERROR(EAGAIN);
01941 } else {
01942 return AVERROR(EIO);
01943 }
01944 }
01945 rt->bytes_read += ret;
01946 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
01947 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
01948 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
01949 return ret;
01950 rt->last_bytes_read = rt->bytes_read;
01951 }
01952
01953 ret = rtmp_parse_result(s, rt, &rpkt);
01954 if (ret < 0) {
01955 ff_rtmp_packet_destroy(&rpkt);
01956 return ret;
01957 }
01958 if (rt->state == STATE_STOPPED) {
01959 ff_rtmp_packet_destroy(&rpkt);
01960 return AVERROR_EOF;
01961 }
01962 if (for_header && (rt->state == STATE_PLAYING ||
01963 rt->state == STATE_PUBLISHING ||
01964 rt->state == STATE_RECEIVING)) {
01965 ff_rtmp_packet_destroy(&rpkt);
01966 return 0;
01967 }
01968 if (!rpkt.data_size || !rt->is_input) {
01969 ff_rtmp_packet_destroy(&rpkt);
01970 continue;
01971 }
01972 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
01973 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
01974 ts = rpkt.timestamp;
01975
01976
01977 rt->flv_off = 0;
01978 rt->flv_size = rpkt.data_size + 15;
01979 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
01980 bytestream_put_byte(&p, rpkt.type);
01981 bytestream_put_be24(&p, rpkt.data_size);
01982 bytestream_put_be24(&p, ts);
01983 bytestream_put_byte(&p, ts >> 24);
01984 bytestream_put_be24(&p, 0);
01985 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
01986 bytestream_put_be32(&p, 0);
01987 ff_rtmp_packet_destroy(&rpkt);
01988 return 0;
01989 } else if (rpkt.type == RTMP_PT_NOTIFY) {
01990 ret = handle_notify(s, &rpkt);
01991 ff_rtmp_packet_destroy(&rpkt);
01992 if (ret) {
01993 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
01994 return ret;
01995 }
01996 return 0;
01997 } else if (rpkt.type == RTMP_PT_METADATA) {
01998
01999 rt->flv_off = 0;
02000 rt->flv_size = rpkt.data_size;
02001 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
02002
02003 next = rpkt.data;
02004 ts = rpkt.timestamp;
02005 while (next - rpkt.data < rpkt.data_size - 11) {
02006 next++;
02007 data_size = bytestream_get_be24(&next);
02008 p=next;
02009 cts = bytestream_get_be24(&next);
02010 cts |= bytestream_get_byte(&next) << 24;
02011 if (pts==0)
02012 pts=cts;
02013 ts += cts - pts;
02014 pts = cts;
02015 bytestream_put_be24(&p, ts);
02016 bytestream_put_byte(&p, ts >> 24);
02017 next += data_size + 3 + 4;
02018 }
02019 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
02020 ff_rtmp_packet_destroy(&rpkt);
02021 return 0;
02022 }
02023 ff_rtmp_packet_destroy(&rpkt);
02024 }
02025 }
02026
02027 static int rtmp_close(URLContext *h)
02028 {
02029 RTMPContext *rt = h->priv_data;
02030 int ret = 0;
02031
02032 if (!rt->is_input) {
02033 rt->flv_data = NULL;
02034 if (rt->out_pkt.data_size)
02035 ff_rtmp_packet_destroy(&rt->out_pkt);
02036 if (rt->state > STATE_FCPUBLISH)
02037 ret = gen_fcunpublish_stream(h, rt);
02038 }
02039 if (rt->state > STATE_HANDSHAKED)
02040 ret = gen_delete_stream(h, rt);
02041
02042 free_tracked_methods(rt);
02043 av_freep(&rt->flv_data);
02044 ffurl_close(rt->stream);
02045 return ret;
02046 }
02047
02057 static int rtmp_open(URLContext *s, const char *uri, int flags)
02058 {
02059 RTMPContext *rt = s->priv_data;
02060 char proto[8], hostname[256], path[1024], *fname;
02061 char *old_app;
02062 uint8_t buf[2048];
02063 int port;
02064 AVDictionary *opts = NULL;
02065 int ret;
02066
02067 if (rt->listen_timeout > 0)
02068 rt->listen = 1;
02069
02070 rt->is_input = !(flags & AVIO_FLAG_WRITE);
02071
02072 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
02073 path, sizeof(path), s->filename);
02074
02075 if (rt->listen && strcmp(proto, "rtmp")) {
02076 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
02077 proto);
02078 return AVERROR(EINVAL);
02079 }
02080 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
02081 if (!strcmp(proto, "rtmpts"))
02082 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
02083
02084
02085 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
02086 } else if (!strcmp(proto, "rtmps")) {
02087
02088 if (port < 0)
02089 port = RTMPS_DEFAULT_PORT;
02090 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
02091 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
02092 if (!strcmp(proto, "rtmpte"))
02093 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
02094
02095
02096 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
02097 rt->encrypted = 1;
02098 } else {
02099
02100 if (port < 0)
02101 port = RTMP_DEFAULT_PORT;
02102 if (rt->listen)
02103 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
02104 "?listen&listen_timeout=%d",
02105 rt->listen_timeout * 1000);
02106 else
02107 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
02108 }
02109
02110 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
02111 &s->interrupt_callback, &opts)) < 0) {
02112 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
02113 goto fail;
02114 }
02115
02116 if (rt->swfverify) {
02117 if ((ret = rtmp_calc_swfhash(s)) < 0)
02118 goto fail;
02119 }
02120
02121 rt->state = STATE_START;
02122 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
02123 goto fail;
02124 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
02125 goto fail;
02126
02127 rt->out_chunk_size = 128;
02128 rt->in_chunk_size = 128;
02129 rt->state = STATE_HANDSHAKED;
02130
02131
02132 old_app = rt->app;
02133
02134 rt->app = av_malloc(APP_MAX_LENGTH);
02135 if (!rt->app) {
02136 ret = AVERROR(ENOMEM);
02137 goto fail;
02138 }
02139
02140
02141 if (!strncmp(path, "/ondemand/", 10)) {
02142 fname = path + 10;
02143 memcpy(rt->app, "ondemand", 9);
02144 } else {
02145 char *next = *path ? path + 1 : path;
02146 char *p = strchr(next, '/');
02147 if (!p) {
02148 fname = next;
02149 rt->app[0] = '\0';
02150 } else {
02151
02152 char *c = strchr(p + 1, ':');
02153 fname = strchr(p + 1, '/');
02154 if (!fname || (c && c < fname)) {
02155 fname = p + 1;
02156 av_strlcpy(rt->app, path + 1, p - path);
02157 } else {
02158 fname++;
02159 av_strlcpy(rt->app, path + 1, fname - path - 1);
02160 }
02161 }
02162 }
02163
02164 if (old_app) {
02165
02166 av_free(rt->app);
02167 rt->app = old_app;
02168 }
02169
02170 if (!rt->playpath) {
02171 int len = strlen(fname);
02172
02173 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
02174 if (!rt->playpath) {
02175 ret = AVERROR(ENOMEM);
02176 goto fail;
02177 }
02178
02179 if (!strchr(fname, ':') && len >= 4 &&
02180 (!strcmp(fname + len - 4, ".f4v") ||
02181 !strcmp(fname + len - 4, ".mp4"))) {
02182 memcpy(rt->playpath, "mp4:", 5);
02183 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
02184 fname[len - 4] = '\0';
02185 } else {
02186 rt->playpath[0] = 0;
02187 }
02188 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
02189 }
02190
02191 if (!rt->tcurl) {
02192 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
02193 if (!rt->tcurl) {
02194 ret = AVERROR(ENOMEM);
02195 goto fail;
02196 }
02197 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
02198 port, "/%s", rt->app);
02199 }
02200
02201 if (!rt->flashver) {
02202 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
02203 if (!rt->flashver) {
02204 ret = AVERROR(ENOMEM);
02205 goto fail;
02206 }
02207 if (rt->is_input) {
02208 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
02209 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
02210 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
02211 } else {
02212 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
02213 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
02214 }
02215 }
02216
02217 rt->client_report_size = 1048576;
02218 rt->bytes_read = 0;
02219 rt->last_bytes_read = 0;
02220 rt->server_bw = 2500000;
02221
02222 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
02223 proto, path, rt->app, rt->playpath);
02224 if (!rt->listen) {
02225 if ((ret = gen_connect(s, rt)) < 0)
02226 goto fail;
02227 } else {
02228 if (read_connect(s, s->priv_data) < 0)
02229 goto fail;
02230 rt->is_input = 1;
02231 }
02232
02233 do {
02234 ret = get_packet(s, 1);
02235 } while (ret == EAGAIN);
02236 if (ret < 0)
02237 goto fail;
02238
02239 if (rt->is_input) {
02240
02241 rt->flv_size = 13;
02242 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
02243 rt->flv_off = 0;
02244 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
02245 } else {
02246 rt->flv_size = 0;
02247 rt->flv_data = NULL;
02248 rt->flv_off = 0;
02249 rt->skip_bytes = 13;
02250 }
02251
02252 s->max_packet_size = rt->stream->max_packet_size;
02253 s->is_streamed = 1;
02254 return 0;
02255
02256 fail:
02257 av_dict_free(&opts);
02258 rtmp_close(s);
02259 return ret;
02260 }
02261
02262 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
02263 {
02264 RTMPContext *rt = s->priv_data;
02265 int orig_size = size;
02266 int ret;
02267
02268 while (size > 0) {
02269 int data_left = rt->flv_size - rt->flv_off;
02270
02271 if (data_left >= size) {
02272 memcpy(buf, rt->flv_data + rt->flv_off, size);
02273 rt->flv_off += size;
02274 return orig_size;
02275 }
02276 if (data_left > 0) {
02277 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
02278 buf += data_left;
02279 size -= data_left;
02280 rt->flv_off = rt->flv_size;
02281 return data_left;
02282 }
02283 if ((ret = get_packet(s, 0)) < 0)
02284 return ret;
02285 }
02286 return orig_size;
02287 }
02288
02289 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
02290 {
02291 RTMPContext *rt = s->priv_data;
02292 int size_temp = size;
02293 int pktsize, pkttype;
02294 uint32_t ts;
02295 const uint8_t *buf_temp = buf;
02296 uint8_t c;
02297 int ret;
02298
02299 do {
02300 if (rt->skip_bytes) {
02301 int skip = FFMIN(rt->skip_bytes, size_temp);
02302 buf_temp += skip;
02303 size_temp -= skip;
02304 rt->skip_bytes -= skip;
02305 continue;
02306 }
02307
02308 if (rt->flv_header_bytes < 11) {
02309 const uint8_t *header = rt->flv_header;
02310 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
02311 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
02312 rt->flv_header_bytes += copy;
02313 size_temp -= copy;
02314 if (rt->flv_header_bytes < 11)
02315 break;
02316
02317 pkttype = bytestream_get_byte(&header);
02318 pktsize = bytestream_get_be24(&header);
02319 ts = bytestream_get_be24(&header);
02320 ts |= bytestream_get_byte(&header) << 24;
02321 bytestream_get_be24(&header);
02322 rt->flv_size = pktsize;
02323
02324
02325 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
02326 pkttype == RTMP_PT_NOTIFY) {
02327 if (pkttype == RTMP_PT_NOTIFY)
02328 pktsize += 16;
02329 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
02330 }
02331
02332
02333 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
02334 pkttype, ts, pktsize)) < 0)
02335 return ret;
02336
02337 rt->out_pkt.extra = rt->main_channel_id;
02338 rt->flv_data = rt->out_pkt.data;
02339
02340 if (pkttype == RTMP_PT_NOTIFY)
02341 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
02342 }
02343
02344 if (rt->flv_size - rt->flv_off > size_temp) {
02345 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
02346 rt->flv_off += size_temp;
02347 size_temp = 0;
02348 } else {
02349 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
02350 size_temp -= rt->flv_size - rt->flv_off;
02351 rt->flv_off += rt->flv_size - rt->flv_off;
02352 }
02353
02354 if (rt->flv_off == rt->flv_size) {
02355 rt->skip_bytes = 4;
02356
02357 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
02358 return ret;
02359 rt->flv_size = 0;
02360 rt->flv_off = 0;
02361 rt->flv_header_bytes = 0;
02362 rt->flv_nb_packets++;
02363 }
02364 } while (buf_temp - buf < size);
02365
02366 if (rt->flv_nb_packets < rt->flush_interval)
02367 return size;
02368 rt->flv_nb_packets = 0;
02369
02370
02371 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
02372
02373
02374 ret = ffurl_read(rt->stream, &c, 1);
02375
02376
02377 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
02378
02379 if (ret == AVERROR(EAGAIN)) {
02380
02381 return size;
02382 } else if (ret < 0) {
02383 return ret;
02384 } else if (ret == 1) {
02385 RTMPPacket rpkt = { 0 };
02386
02387 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
02388 rt->in_chunk_size,
02389 rt->prev_pkt[0], c)) <= 0)
02390 return ret;
02391
02392 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
02393 return ret;
02394
02395 ff_rtmp_packet_destroy(&rpkt);
02396 }
02397
02398 return size;
02399 }
02400
02401 #define OFFSET(x) offsetof(RTMPContext, x)
02402 #define DEC AV_OPT_FLAG_DECODING_PARAM
02403 #define ENC AV_OPT_FLAG_ENCODING_PARAM
02404
02405 static const AVOption rtmp_options[] = {
02406 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
02407 {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
02408 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
02409 {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
02410 {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
02411 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
02412 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
02413 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
02414 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
02415 {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
02416 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
02417 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
02418 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
02419 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
02420 {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
02421 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
02422 {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
02423 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
02424 {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
02425 { NULL },
02426 };
02427
02428 #define RTMP_PROTOCOL(flavor) \
02429 static const AVClass flavor##_class = { \
02430 .class_name = #flavor, \
02431 .item_name = av_default_item_name, \
02432 .option = rtmp_options, \
02433 .version = LIBAVUTIL_VERSION_INT, \
02434 }; \
02435 \
02436 URLProtocol ff_##flavor##_protocol = { \
02437 .name = #flavor, \
02438 .url_open = rtmp_open, \
02439 .url_read = rtmp_read, \
02440 .url_write = rtmp_write, \
02441 .url_close = rtmp_close, \
02442 .priv_data_size = sizeof(RTMPContext), \
02443 .flags = URL_PROTOCOL_FLAG_NETWORK, \
02444 .priv_data_class= &flavor##_class, \
02445 };
02446
02447
02448 RTMP_PROTOCOL(rtmp)
02449 RTMP_PROTOCOL(rtmpe)
02450 RTMP_PROTOCOL(rtmps)
02451 RTMP_PROTOCOL(rtmpt)
02452 RTMP_PROTOCOL(rtmpte)
02453 RTMP_PROTOCOL(rtmpts)