static int send_invoke_response(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; double seqnum; char filename[64]; char command[64]; int stringlen; char *pchar; const uint8_t *p = pkt->data; uint8_t *pp = NULL; RTMPPacket spkt = { 0 }; GetByteContext gbc; int ret; bytestream2_init(&gbc, p, pkt->size); if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) { av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n"); return AVERROR_INVALIDDATA; } ret = ff_amf_read_number(&gbc, &seqnum); if (ret) return ret; ret = ff_amf_read_null(&gbc); if (ret) return ret; if (!strcmp(command, "FCPublish") || !strcmp(command, "publish")) { ret = ff_amf_read_string(&gbc, filename, sizeof(filename), &stringlen); if (ret) { if (ret == AVERROR(EINVAL)) av_log(s, AV_LOG_ERROR, "Unable to parse stream name - name too long?\n"); else av_log(s, AV_LOG_ERROR, "Unable to parse stream name\n"); return ret; } // check with url if (s->filename) { pchar = strrchr(s->filename, '/'); if (!pchar) { av_log(s, AV_LOG_WARNING, "Unable to find / in url %s, bad format\n", s->filename); pchar = s->filename; } pchar++; if (strcmp(pchar, filename)) av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting" " %s\n", filename, pchar); } rt->state = STATE_RECEIVING; } if (!strcmp(command, "FCPublish")) { 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; ff_amf_write_string(&pp, "onFCPublish"); } else if (!strcmp(command, "publish")) { ret = write_begin(s); if (ret < 0) return ret; // Send onStatus(NetStream.Publish.Start) return write_status(s, pkt, "NetStream.Publish.Start", filename); } else if (!strcmp(command, "play")) { ret = write_begin(s); if (ret < 0) return ret; rt->state = STATE_SENDING; return write_status(s, pkt, "NetStream.Play.Start", filename); } else { 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; ff_amf_write_string(&pp, "_result"); ff_amf_write_number(&pp, seqnum); ff_amf_write_null(&pp); if (!strcmp(command, "createStream")) { rt->nb_streamid++; if (rt->nb_streamid == 0 || rt->nb_streamid == 2) rt->nb_streamid++; /* Values 0 and 2 are reserved */ ff_amf_write_number(&pp, rt->nb_streamid); /* By now we don't control which streams are removed in * deleteStream. There is no stream creation control * if a client creates more than 2^32 - 2 streams. */ } } spkt.size = pp - spkt.data; ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, &rt->prev_pkt[1], &rt->nb_prev_pkt[1]); ff_rtmp_packet_destroy(&spkt); return ret; }