Repository: ossrs/srs
File: trunk/src/app/srs_app_gb28181.cpp (C++)

Code before:
        req = json->to_object();
    }

    // Fetch params from req object.
    SrsJsonAny* prop = NULL;
    if ((prop = req->ensure_property_string("id")) == NULL) {
        return srs_error_wrap(err, "not id");
    }
    string id = prop->to_str();

    if ((prop = req->ensure_property_string("ssrc")) == NULL) {
        return srs_error_wrap(err, "not ssrc");
    }
    uint64_t ssrc = atoi(prop->to_str().c_str());

    if ((err = bind_session(id, ssrc)) != srs_success) {
        return srs_error_wrap(err, "bind session");
    }

    res->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
    int port = _srs_config->get_stream_caster_listen(conf_);
    res->set("port", SrsJsonAny::integer(port));
    res->set("is_tcp", SrsJsonAny::boolean(true)); // only tcp supported

    srs_trace("GB publish id: %s, ssrc=%lu", id.c_str(), ssrc);

    return err;
}

srs_error_t SrsGoApiGbPublish::bind_session(std::string id, uint64_t ssrc)
{
    srs_error_t err = srs_success;

    SrsSharedResource<SrsGbSession>* session = NULL;
    session = dynamic_cast<SrsSharedResource<SrsGbSession>*>(_srs_gb_manager->find_by_id(id));
    if (session) {
        return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "stream already exists");
    }

    session = dynamic_cast<SrsSharedResource<SrsGbSession>*>(_srs_gb_manager->find_by_fast_id(ssrc));
    if (session) {
        return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "ssrc already exists");
    }

    // Create new GB session.
    SrsGbSession* raw_session = new SrsGbSession();
    raw_session->setup(conf_);

    session = new SrsSharedResource<SrsGbSession>(raw_session);
    _srs_gb_manager->add_with_id(id, session);
    _srs_gb_manager->add_with_fast_id(ssrc, session);

Review comment (refactor):
This is a suggestion, is it possible to refactor this, `SrsGoApiGbPublish::bind_session` and `SrsGbMediaTcpConn::bind_session`, to one service object, whose duty is to `bind_session`? While the benefit is that just one piece of code to manager the `session`. This is maybe a big refactor, let gb28181 support both the internal sip and external sip(http api) by a more explicit way, let sip do just the message transport duty, the session is managed by another object.

Code after:
    SrsJsonAny* prop = NULL;
    if ((prop = req->ensure_property_string("id")) == NULL) {
        return srs_error_new(ERROR_HTTP_DATA_INVALID, "id required");
    }
    string id = prop->to_str();

    if ((prop = req->ensure_property_string("ssrc")) == NULL) {
        return srs_error_new(ERROR_HTTP_DATA_INVALID, "ssrc required");
    }
    uint64_t ssrc = atoi(prop->to_str().c_str());

    if ((err = bind_session(id, ssrc)) != srs_success) {
        return srs_error_wrap(err, "bind session");
    }

    res->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
    int port = _srs_config->get_stream_caster_listen(conf_);
    res->set("port", SrsJsonAny::integer(port));
    res->set("is_tcp", SrsJsonAny::boolean(true)); // only tcp supported

    srs_trace("GB publish id: %s, ssrc=%lu", id.c_str(), ssrc);

    return err;
}

srs_error_t SrsGoApiGbPublish::bind_session(std::string id, uint64_t ssrc)
{
    srs_error_t err = srs_success;

    SrsSharedResource<SrsGbSession>* session = NULL;
    session = dynamic_cast<SrsSharedResource<SrsGbSession>*>(_srs_gb_manager->find_by_id(id));
    if (session) {
        return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "stream already exists");
    }

    session = dynamic_cast<SrsSharedResource<SrsGbSession>*>(_srs_gb_manager->find_by_fast_id(ssrc));
    if (session) {
        return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "ssrc already exists");
    }

    // Create new GB session.
    SrsGbSession* raw_session = new SrsGbSession();
    raw_session->setup(conf_);

    session = new SrsSharedResource<SrsGbSession>(raw_session);
    _srs_gb_manager->add_with_id(id, session);
    _srs_gb_manager->add_with_fast_id(ssrc, session);

    SrsExecutorCoroutine* executor = new SrsExecutorCoroutine(_srs_gb_manager, session, raw_session, raw_session);
    raw_session->setup_owner(session, executor, executor);
    raw_session->sip_transport()->set_device_id(id);