int MRtmpConnection::onCommand(MRtmpMessage *msg, const MString &name, double transactionID, MAMF0Any *arg1 , MAMF0Any *arg2, MAMF0Any *arg3, MAMF0Any *arg4) { // TODO refer check. // TODO set app msg to protocol int ret = E_SUCCESS; if (name == "connect") { if (!arg1->isAmf0Object()) return E_AMF_TYPE_ERROR; MAMF0Object *obj = dynamic_cast<MAMF0Object *>(arg1); if ((ret = parseUrl(obj)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->setAckSize(2500000)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->setPeerBandwidth(2500000)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->onConnect(transactionID)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->onBWDone()) != E_SUCCESS) { return ret; } } else if (name == "releaseStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverConnection; header.type = RTMP_MSG_AMF0CommandMessage; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, new MAMF0Undefined)) != E_SUCCESS) { return ret; } } else if (name == "FCPublish") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverConnection; header.type = RTMP_MSG_AMF0CommandMessage; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, new MAMF0Undefined)) != E_SUCCESS) { return ret; } } else if (name == "createStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverConnection; header.type = RTMP_MSG_AMF0CommandMessage; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID) , new MAMF0Null, new MAMF0Number(1))) != E_SUCCESS) { return ret; } m_protocol->getRtmpCtx()->streamID = 1; } else if (name == "publish") { MString cmdName = "FCPublish"; MAMF0Object *obj = new MAMF0Object; obj->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Publish_Start)); obj->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Publish_Start)); MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverStream; header.type = RTMP_MSG_AMF0CommandMessage; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj)) != E_SUCCESS) { return ret; } cmdName = RTMP_AMF0_COMMAND_ON_STATUS; MAMF0Object *obj1 = new MAMF0Object; obj1->setValue(STATUS_LEVEL, new MAMF0ShortString(STATUS_LEVEL_STATUS)); obj1->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Publish_Start)); obj1->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Publish_Start)); obj1->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj1)) != E_SUCCESS) { return ret; } MAMF0ShortString *str = dynamic_cast<MAMF0ShortString *>(arg2); if (!str) { return E_AMF_TYPE_ERROR; } MRtmpContext *ctx = m_protocol->getRtmpCtx(); ctx->setStreamName(str->var); MString url = ctx->rtmpUrl->url(); m_source = new MRtmpSource(url, this); log_trace("start publish %s", url.c_str()); } else if (name == "FCUnpublish") { MString cmdName = "onFCUnpublish"; MAMF0Object *obj = new MAMF0Object; obj->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Unpublish_Success)); obj->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Unpublish_Success)); MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverConnection; header.type = RTMP_MSG_AMF0CommandMessage; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj)) != E_SUCCESS) { return ret; } } else if (name == "closeStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverConnection; header.type = RTMP_MSG_AMF0CommandMessage; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID) , new MAMF0Null, new MAMF0Undefined)) != E_SUCCESS) { return ret; } cmdName = RTMP_AMF0_COMMAND_ON_STATUS; MAMF0Object *obj1 = new MAMF0Object; obj1->setValue(STATUS_LEVEL, new MAMF0ShortString(STATUS_LEVEL_STATUS)); obj1->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Unpublish_Success)); obj1->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Unpublish_Success)); obj1->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj1)) != E_SUCCESS) { return ret; } m_protocol->getRtmpCtx()->streamID = 0; } else if (name == "deleteStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverConnection; header.type = RTMP_MSG_AMF0CommandMessage; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID) , new MAMF0Null, new MAMF0Null)) != E_SUCCESS) { return ret; } } else if (name == "play") { if ((ret = m_protocol->setChunkSize(4096)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->setUCM(UCM_StreamBegin, m_protocol->getRtmpCtx()->streamID)) != E_SUCCESS) { return ret; } MRtmpMessageHeader header; header.perfer_cid = RTMP_CID_OverConnection2; header.type = RTMP_MSG_AMF0CommandMessage; MString cmdName = RTMP_AMF0_COMMAND_ON_STATUS; MAMF0Object *obj = new MAMF0Object; obj->setValue(STATUS_LEVEL, new MAMF0ShortString(STATUS_LEVEL_STATUS)); obj->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Play_Reset)); obj->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Play_Reset)); obj->setValue(STATUS_DETAILS, new MAMF0ShortString(NetStream_Play_Reset)); obj->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj)) != E_SUCCESS) { return ret; } MAMF0Object *obj1 = new MAMF0Object; obj1->setValue(STATUS_LEVEL, new MAMF0ShortString(STATUS_LEVEL_STATUS)); obj1->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Play_Start)); obj1->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Play_Start)); obj1->setValue(STATUS_DETAILS, new MAMF0ShortString(NetStream_Play_Start)); obj1->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj1)) != E_SUCCESS) { return ret; } header.type = RTMP_MSG_AMF0DataMessage; cmdName = RTMP_AMF0_DATA_SAMPLE_ACCESS; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Boolean(false), new MAMF0Boolean(false))) != E_SUCCESS) { return ret; } MAMF0ShortString *str = dynamic_cast<MAMF0ShortString *>(arg2); if (!str) { return E_AMF_TYPE_ERROR; } MRtmpContext *ctx = m_protocol->getRtmpCtx(); ctx->setStreamName(str->var); MString url = ctx->rtmpUrl->url(); while (true) { MRtmpSource *source = MRtmpSource::findSource(url); if (!source) { mSleep(1); continue; } m_source = source; break; } log_trace("start play : %s", url.c_str()); playService(); } else if (name == "_checkbw") { return ret; } else { log_error("MRtmpConnection onCommand : no method \"%s\"", name.c_str()); return E_INVOKE_NO_METHOD; } return ret; }
int MRtmpConnection::onCommand(MRtmpMessage *msg, const MString &name, double transactionID, MAMF0Any *arg1 , MAMF0Any *arg2, MAMF0Any *arg3, MAMF0Any *arg4) { // TODO refer check. // TODO set app msg to protocol int ret = E_SUCCESS; if (name == "connect") { if (!arg1->isAmf0Object()) return E_AMF_TYPE_ERROR; MAMF0Object *obj = dynamic_cast<MAMF0Object *>(arg1); if ((ret = parseUrl(obj)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->setAckSize(2500000)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->setPeerBandwidth(2500000)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->onConnect(transactionID)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->onBWDone()) != E_SUCCESS) { return ret; } } else if (name == "releaseStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverConnection); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, new MAMF0Undefined)) != E_SUCCESS) { return ret; } } else if (name == "FCPublish") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverConnection); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, new MAMF0Undefined)) != E_SUCCESS) { return ret; } } else if (name == "createStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverConnection); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID) , new MAMF0Null, new MAMF0Number(1))) != E_SUCCESS) { return ret; } m_protocol->getRtmpCtx()->streamID = 1; } else if (name == "publish") { MString cmdName = "FCPublish"; MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverStream); MRtmpNetStatusEvent *obj = new MRtmpNetStatusEvent(NetStream_Publish_Start); obj->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Publish_Start)); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj)) != E_SUCCESS) { return ret; } MRtmpNetStatusEvent *obj1 = new MRtmpNetStatusEvent(NetStream_Publish_Start, STATUS_LEVEL_STATUS); obj1->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Publish_Start)); obj1->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendNetStatusEvent(transactionID, obj1)) != E_SUCCESS) { return ret; } MAMF0ShortString *str = dynamic_cast<MAMF0ShortString *>(arg2); if (!str) { return E_AMF_TYPE_ERROR; } MRtmpContext *ctx = m_protocol->getRtmpCtx(); ctx->setStreamName(str->var); MString url = ctx->rtmpUrl->url(); m_source = MRtmpSource::findSource(url); m_role = Role_Connection_Publish; log_trace("start publish %s", url.c_str()); g_cchannel->sendLine(Internal_CMD_IHasBackSourced, url); BlsBackSource::instance()->setHasBackSource(url); } else if (name == "FCUnpublish") { MString cmdName = "onFCUnpublish"; MAMF0Object *obj = new MAMF0Object; obj->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Unpublish_Success)); obj->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Unpublish_Success)); MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverConnection); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj)) != E_SUCCESS) { return ret; } } else if (name == "closeStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverConnection); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID) , new MAMF0Null, new MAMF0Undefined)) != E_SUCCESS) { return ret; } cmdName = RTMP_AMF0_COMMAND_ON_STATUS; MAMF0Object *obj1 = new MAMF0Object; obj1->setValue(STATUS_LEVEL, new MAMF0ShortString(STATUS_LEVEL_STATUS)); obj1->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Unpublish_Success)); obj1->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Unpublish_Success)); obj1->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj1)) != E_SUCCESS) { return ret; } m_protocol->getRtmpCtx()->streamID = 0; } else if (name == "deleteStream") { MString cmdName = RTMP_AMF0_COMMAND_RESULT; MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverConnection); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID) , new MAMF0Null, new MAMF0Null)) != E_SUCCESS) { return ret; } } else if (name == "play") { if ((ret = m_protocol->setChunkSize(40960)) != E_SUCCESS) { return ret; } if ((ret = m_protocol->setUCM(UCM_StreamBegin, m_protocol->getRtmpCtx()->streamID)) != E_SUCCESS) { return ret; } MRtmpMessageHeader header(RTMP_MSG_AMF0CommandMessage, RTMP_CID_OverConnection2); MString cmdName = RTMP_AMF0_COMMAND_ON_STATUS; MRtmpNetStatusEvent *obj = new MRtmpNetStatusEvent(NetStream_Play_Reset, STATUS_LEVEL_STATUS); obj->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Play_Reset)); obj->setValue(STATUS_DETAILS, new MAMF0ShortString(NetStream_Play_Reset)); obj->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj)) != E_SUCCESS) { return ret; } MAMF0Object *obj1 = new MAMF0Object; obj1->setValue(STATUS_LEVEL, new MAMF0ShortString(STATUS_LEVEL_STATUS)); obj1->setValue(STATUS_CODE, new MAMF0ShortString(NetStream_Play_Start)); obj1->setValue(STATUS_DESC, new MAMF0ShortString(NetStream_Play_Start)); obj1->setValue(STATUS_DETAILS, new MAMF0ShortString(NetStream_Play_Start)); obj1->setValue(STATUS_CLIENT_ID, new MAMF0ShortString("ASAICiss")); if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Number(transactionID), new MAMF0Null, obj1)) != E_SUCCESS) { return ret; } header.type = RTMP_MSG_AMF0DataMessage; cmdName = RTMP_AMF0_DATA_SAMPLE_ACCESS; if ((ret = m_protocol->sendAny(header, new MAMF0ShortString(cmdName), new MAMF0Boolean(false), new MAMF0Boolean(false))) != E_SUCCESS) { return ret; } MAMF0ShortString *str = dynamic_cast<MAMF0ShortString *>(arg2); if (!str) { return E_AMF_TYPE_ERROR; } MRtmpContext *ctx = m_protocol->getRtmpCtx(); ctx->setStreamName(str->var); MString url = ctx->rtmpUrl->url(); MString vhost = ctx->rtmpUrl->vhost(); MString mode = BlsConf::instance()->getMode(vhost); MString fullUrl = ctx->rtmpUrl->fullUrl(); bool hasBackSource = BlsBackSource::instance()->hasBackSource(fullUrl); if (!hasBackSource) { // TODO if fails ? MString res; g_cchannel->sendLineAndWaitResponse(Internal_CMD_WhoHasBackSource, url, res); int port = getValue(res).toInt(); if (mode == Mode_Remote) { if (port == 0) { // back source to local server BlsBackSource::instance()->add(ctx->rtmpUrl->vhost(), ctx->rtmpUrl->port(), ctx->rtmpUrl->app(), ctx->rtmpUrl->fullUrl()); log_trace("begin back source to %s:%d pid=%d", ctx->rtmpUrl->vhost().c_str(), ctx->rtmpUrl->port(), getpid()); } else if (port > 0) { // back source to origin server BlsBackSource::instance()->add("127.0.0.1", port, ctx->rtmpUrl->app(), ctx->rtmpUrl->fullUrl()); log_trace("begin back source to %s:%d pid=%d", "127.0.0.1", port, getpid()); } } else if (mode == Mode_Local) { BlsBackSource::instance()->add("127.0.0.1", port, ctx->rtmpUrl->app(), ctx->rtmpUrl->fullUrl()); // back source to origin server } } log_trace("start play : %s", fullUrl.c_str()); m_source = MRtmpSource::findSource(url); m_role = Role_Connection_Play; playService(); } else if (name == "_checkbw") { return ret; } else { log_error("MRtmpConnection onCommand : no method \"%s\"", name.c_str()); return E_INVOKE_NO_METHOD; } return ret; }