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