On 15 September 2013 07:54, Luca Barbato <[email protected]> wrote:
> Will be reused for supporting play.
> ---
>  libavformat/rtmpproto.c | 121 
> +++++++++++++++++++++++++++++++-----------------
>  1 file changed, 78 insertions(+), 43 deletions(-)
>
> diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
> index 48eed56..03f5761 100644
> --- a/libavformat/rtmpproto.c
> +++ b/libavformat/rtmpproto.c
> @@ -1764,13 +1764,84 @@ static int handle_invoke_error(URLContext *s, 
> RTMPPacket *pkt)
>      return ret;
>  }
>
> +static int write_begin(URLContext *s)
> +{
> +    RTMPContext *rt = s->priv_data;
> +    PutByteContext pbc;
> +    RTMPPacket spkt = { 0 };
> +    int ret;
> +
> +    // Send Stream Begin 1
> +    if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
> +                                     RTMP_PT_PING, 0, 6)) < 0) {
> +        av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
> +        return ret;
> +    }
> +
> +    bytestream2_init_writer(&pbc, spkt.data, spkt.size);
> +    bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
> +    bytestream2_put_be32(&pbc, rt->nb_streamid);
> +
> +    ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
> +                               rt->prev_pkt[1]);
> +
> +    ff_rtmp_packet_destroy(&spkt);
> +
> +    return ret;
> +}
> +
> +static int write_status(URLContext *s, RTMPPacket *pkt,
> +                        const char *status, const char *filename)
> +{
> +    RTMPContext *rt = s->priv_data;
> +    RTMPPacket spkt = { 0 };
> +    char statusmsg[128];
> +    uint8_t *pp;
> +    int ret;
> +
> +    if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
> +                                     RTMP_PT_INVOKE, 0,
> +                                     RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
> +        av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
> +        return ret;
> +    }
> +
> +    pp = spkt.data;
> +    spkt.extra = pkt->extra;
> +    ff_amf_write_string(&pp, "onStatus");
> +    ff_amf_write_number(&pp, 0);
> +    ff_amf_write_null(&pp);
> +
> +    ff_amf_write_object_start(&pp);
> +    ff_amf_write_field_name(&pp, "level");
> +    ff_amf_write_string(&pp, "status");
> +    ff_amf_write_field_name(&pp, "code");
> +    ff_amf_write_string(&pp, status);
> +    ff_amf_write_field_name(&pp, "description");
> +    snprintf(statusmsg, sizeof(statusmsg),
> +             "%s is now published", filename);
> +    ff_amf_write_string(&pp, statusmsg);
> +    ff_amf_write_field_name(&pp, "details");
> +    ff_amf_write_string(&pp, filename);
> +    ff_amf_write_field_name(&pp, "clientid");
> +    snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
> +    ff_amf_write_string(&pp, statusmsg);
> +    ff_amf_write_object_end(&pp);
> +

This is an issue with the original code, but I'm a bit concerned with
writing out-of-bounds since "filename" is user controlled and the
ff_amf_write* functions are unchecked. Is there some upper limit to
the filename length that guarantees the whole message will be
<RTMP_PKTDATA_DEFAULT_SIZE ?

The rest of the patch looks OK otherwise.

> +    spkt.size = pp - spkt.data;
> +    ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
> +                               rt->prev_pkt[1]);
> +    ff_rtmp_packet_destroy(&spkt);
> +
> +    return ret;
> +}
> +
>  static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
>  {
>      RTMPContext *rt = s->priv_data;
>      double seqnum;
>      char filename[64];
>      char command[64];
> -    char statusmsg[128];
>      int stringlen;
>      char *pchar;
>      const uint8_t *p = pkt->data;
> @@ -1786,6 +1857,8 @@ static int send_invoke_response(URLContext *s, 
> RTMPPacket *pkt)
>          return AVERROR_INVALIDDATA;
>      }
>
> +    av_log(s, AV_LOG_ERROR, "Command %s\n", command);
> +
>      ret = ff_amf_read_number(&gbc, &seqnum);
>      if (ret)
>          return ret;
> @@ -1823,52 +1896,13 @@ static int send_invoke_response(URLContext *s, 
> RTMPPacket *pkt)
>          pp = spkt.data;
>          ff_amf_write_string(&pp, "onFCPublish");
>      } else if (!strcmp(command, "publish")) {
> -        PutByteContext pbc;
> -        // Send Stream Begin 1
> -        if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
> -                                         RTMP_PT_PING, 0, 6)) < 0) {
> -            av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
> -            return ret;
> -        }
> -        pp = spkt.data;
> -        bytestream2_init_writer(&pbc, pp, spkt.size);
> -        bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
> -        bytestream2_put_be32(&pbc, rt->nb_streamid);
> -        ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
> -                                   rt->prev_pkt[1]);
> -        ff_rtmp_packet_destroy(&spkt);
> +        ret = write_begin(s);
>          if (ret < 0)
>              return ret;
>
>          // Send onStatus(NetStream.Publish.Start)
> -        if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
> -                                         RTMP_PT_INVOKE, 0,
> -                                         RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
> -            av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
> -            return ret;
> -        }
> -        spkt.extra = pkt->extra;
> -        pp = spkt.data;
> -        ff_amf_write_string(&pp, "onStatus");
> -        ff_amf_write_number(&pp, 0);
> -        ff_amf_write_null(&pp);
> -
> -        ff_amf_write_object_start(&pp);
> -        ff_amf_write_field_name(&pp, "level");
> -        ff_amf_write_string(&pp, "status");
> -        ff_amf_write_field_name(&pp, "code");
> -        ff_amf_write_string(&pp, "NetStream.Publish.Start");
> -        ff_amf_write_field_name(&pp, "description");
> -        snprintf(statusmsg, sizeof(statusmsg),
> -                 "%s is now published", filename);
> -        ff_amf_write_string(&pp, statusmsg);
> -        ff_amf_write_field_name(&pp, "details");
> -        ff_amf_write_string(&pp, filename);
> -        ff_amf_write_field_name(&pp, "clientid");
> -        snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
> -        ff_amf_write_string(&pp, statusmsg);
> -        ff_amf_write_object_end(&pp);
> -
> +        return write_status(s, pkt, "NetStream.Publish.Start",
> +                           filename);
>      } else {
>          if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
>                                           RTMP_PT_INVOKE, 0,
> @@ -2016,6 +2050,7 @@ static int handle_invoke(URLContext *s, RTMPPacket *pkt)
>                 ff_amf_match_string(pkt->data, pkt->size, "FCPublish")     ||
>                 ff_amf_match_string(pkt->data, pkt->size, "publish")       ||
>                 ff_amf_match_string(pkt->data, pkt->size, "_checkbw")      ||
> +               ff_amf_match_string(pkt->data, pkt->size, "play")          ||
>                 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
>          if ((ret = send_invoke_response(s, pkt)) < 0)
>              return ret;
> --
> 1.8.3.2
>
> _______________________________________________
> libav-devel mailing list
> [email protected]
> https://lists.libav.org/mailman/listinfo/libav-devel
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to