From d9fe2c458c7d2a52f98d793d723e4b72f4a29e9e Mon Sep 17 00:00:00 2001 From: Winlin Date: Tue, 2 Sep 2025 09:57:03 -0400 Subject: [PATCH] AI: GB28181: Remove embedded SIP server and enforce external SIP usage. v7.0.75 (#4466) This PR removes the embedded GB28181 SIP server implementation from SRS and enforces the use of external SIP servers for production deployments. The embedded SIP server depended on the deprecated `http-parser` library. With the planned migration to `llhttp` (which doesn't support SIP parsing), maintaining the embedded SIP server would require significant additional work. Since external SIP servers are already the recommended approach for production, removing the embedded implementation simplifies the codebase and eliminates this dependency. Eliminated `srs_gb28181_test` from CI workflow. Removed SIP configuration validation tests. --------- Co-authored-by: OSSRS-AI Co-authored-by: haibo.chen <495810242@qq.com> --- .github/workflows/test.yml | 3 +- trunk/conf/full.conf | 26 - trunk/conf/gb28181-without-sip.conf | 57 - trunk/conf/gb28181.conf | 6 - trunk/conf/push.gb28181.conf | 3 +- trunk/doc/CHANGELOG.md | 1 + trunk/src/app/srs_app_config.cpp | 115 -- trunk/src/app/srs_app_config.hpp | 10 - trunk/src/app/srs_app_gb28181.cpp | 1258 +--------------- trunk/src/app/srs_app_gb28181.hpp | 396 +---- trunk/src/core/srs_core_version7.hpp | 2 +- .../src/protocol/srs_protocol_http_stack.cpp | 70 - .../src/protocol/srs_protocol_http_stack.hpp | 8 +- trunk/src/utest/srs_utest_gb28181.cpp | 1329 ----------------- 14 files changed, 38 insertions(+), 3246 deletions(-) delete mode 100644 trunk/conf/gb28181-without-sip.conf diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c806e9ab2..f5f6005d2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -128,8 +128,7 @@ jobs: - name: Run SRS regression-test run: | docker run --rm srs:test bash -c './objs/srs -c conf/regression-test.conf && sleep 10 && \ - cd 3rdparty/srs-bench && (./objs/srs_test -test.v || (cat ../../objs/srs.log && exit 1)) && \ - ./objs/srs_gb28181_test -test.v' + cd 3rdparty/srs-bench && (./objs/srs_test -test.v || (cat ../../objs/srs.log && exit 1))' runs-on: ubuntu-22.04 coverage: diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 0f3d3551f..a3e5f27b3 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1648,32 +1648,6 @@ stream_caster { # For gb28181 converter, listen at TCP port. for example, 9000. # @remark We always enable bundle for media streams at this port. listen 9000; - # SIP server for GB28181. Please note that this is only a demonstrated SIP server, please never use it in your - # online production environment. Instead please use [jsip](https://github.com/usnistgov/jsip) and there is a demo - # [srs-sip](https://github.com/ossrs/srs-sip) also base on it, for more information please see project - # [GB: External SIP](https://ossrs.io/lts/en-us/docs/v7/doc/gb28181#external-sip). - sip { - # Whether enable embedded SIP server. Please disable it if you want to use your own SIP server, see - # [GB: External SIP](https://ossrs.io/lts/en-us/docs/v7/doc/gb28181#external-sip). - # Default: on - enabled on; - # The SIP listen port, for TCP protocol. - # Default: 5060 - listen 5060; - # The SIP or media transport timeout in seconds. - # Default: 60 - timeout 60; - # When media disconnect, the wait time in seconds to re-invite device to publish. During this wait time, device - # might send bye or unregister message(expire is 0), so that we will cancel the re-invite. - # Default: 5 - reinvite 5; - # The exposed candidate IPs, response in SDP connection line. It can be: - # * Retrieve server IP automatically, from all network interfaces. - # $CANDIDATE Read the IP from ENV variable, use * if not set. - # x.x.x.x A specified IP address or DNS name, use * if 0.0.0.0. - # Default: * - candidate *; - } } # diff --git a/trunk/conf/gb28181-without-sip.conf b/trunk/conf/gb28181-without-sip.conf deleted file mode 100644 index 31ab65f83..000000000 --- a/trunk/conf/gb28181-without-sip.conf +++ /dev/null @@ -1,57 +0,0 @@ - -max_connections 1000; -daemon off; -srs_log_tank console; - -# RTMP server configuration -rtmp { - listen 1935; -} - -stream_caster { - enabled on; - caster gb28181; - output rtmp://127.0.0.1/live/[stream]; - listen 9000; - sip { - enabled off; - } -} - -http_server { - enabled on; - listen 8080; - dir ./objs/nginx/html; -} - -http_api { - enabled on; - listen 1985; -} -stats { - network 0; -} -rtc_server { - enabled on; - listen 8000; # UDP port - # @see https://ossrs.io/lts/en-us/docs/v7/doc/webrtc#config-candidate - candidate $CANDIDATE; -} - -vhost __defaultVhost__ { - rtc { - enabled on; - # @see https://ossrs.io/lts/en-us/docs/v7/doc/webrtc#rtmp-to-rtc - rtmp_to_rtc on; - # @see https://ossrs.io/lts/en-us/docs/v7/doc/webrtc#rtc-to-rtmp - rtc_to_rtmp on; - } - http_remux { - enabled on; - mount [vhost]/[app]/[stream].flv; - } - hls { - enabled on; - } -} - diff --git a/trunk/conf/gb28181.conf b/trunk/conf/gb28181.conf index 020872d6f..2b35d3cc0 100644 --- a/trunk/conf/gb28181.conf +++ b/trunk/conf/gb28181.conf @@ -13,12 +13,6 @@ stream_caster { caster gb28181; output rtmp://127.0.0.1/live/[stream]; listen 9000; - sip { - enabled on; - listen 5060; - # @see https://ossrs.io/lts/en-us/docs/v7/doc/gb28181#config-candidate - candidate $CANDIDATE; - } } http_server { diff --git a/trunk/conf/push.gb28181.conf b/trunk/conf/push.gb28181.conf index 3b4157141..796eb1796 100644 --- a/trunk/conf/push.gb28181.conf +++ b/trunk/conf/push.gb28181.conf @@ -17,8 +17,7 @@ stream_caster { # @see https://ossrs.io/lts/en-us/docs/v7/doc/gb28181#config-candidate host $CANDIDATE; sip { - enabled on; - listen 5060; + enabled off; } } diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index f0d1e5324..5cee3e22c 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 7.0 Changelog +* v7.0, 2025-09-02, Merge [#4466](https://github.com/ossrs/srs/pull/4466): AI: GB28181: Remove embedded SIP server and enforce external SIP usage. v7.0.75 (#4466) * v7.0, 2025-09-01, Merge [#4465](https://github.com/ossrs/srs/pull/4465): AI: Replace SrsSharedPtrMessage with SrsMediaPacket for unified media packet handling. v7.0.74 (#4465) * v7.0, 2025-09-01, Merge [#4464](https://github.com/ossrs/srs/pull/4464): AI: Use shared ptr in RTMP message. v7.0.73 (#4464) * v7.0, 2025-09-01, Merge [#4463](https://github.com/ossrs/srs/pull/4463): AI: Use SrsHttpUri for URL parsing and add legacy RTMP URL conversion. v7.0.72 (#4463) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 0d35176f9..07abb27ae 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3188,121 +3188,6 @@ int SrsConfig::get_stream_caster_listen(SrsConfDirective *conf) return ::atoi(conf->arg0().c_str()); } -bool SrsConfig::get_stream_caster_sip_enable(SrsConfDirective *conf) -{ - static bool DEFAULT = true; - - if (!conf) { - return DEFAULT; - } - - conf = conf->get("sip"); - if (!conf) { - return DEFAULT; - } - - conf = conf->get("enabled"); - if (!conf || conf->arg0().empty()) { - return DEFAULT; - } - - return SRS_CONF_PREFER_TRUE(conf->arg0()); -} - -int SrsConfig::get_stream_caster_sip_listen(SrsConfDirective *conf) -{ - static int DEFAULT = 5060; - - if (!conf) { - return DEFAULT; - } - - conf = conf->get("sip"); - if (!conf) { - return DEFAULT; - } - - conf = conf->get("listen"); - if (!conf || conf->arg0().empty()) { - return DEFAULT; - } - - return ::atoi(conf->arg0().c_str()); -} - -srs_utime_t SrsConfig::get_stream_caster_sip_timeout(SrsConfDirective *conf) -{ - static srs_utime_t DEFAULT = 60 * SRS_UTIME_SECONDS; - - if (!conf) { - return DEFAULT; - } - - conf = conf->get("sip"); - if (!conf) { - return DEFAULT; - } - - conf = conf->get("timeout"); - if (!conf || conf->arg0().empty()) { - return DEFAULT; - } - - return ::atof(conf->arg0().c_str()) * SRS_UTIME_SECONDS; -} - -srs_utime_t SrsConfig::get_stream_caster_sip_reinvite(SrsConfDirective *conf) -{ - static srs_utime_t DEFAULT = 5 * SRS_UTIME_SECONDS; - - if (!conf) { - return DEFAULT; - } - - conf = conf->get("sip"); - if (!conf) { - return DEFAULT; - } - - conf = conf->get("reinvite"); - if (!conf || conf->arg0().empty()) { - return DEFAULT; - } - - return ::atof(conf->arg0().c_str()) * SRS_UTIME_SECONDS; -} - -std::string SrsConfig::get_stream_caster_sip_candidate(SrsConfDirective *conf) -{ - static string DEFAULT = "*"; - - if (!conf) { - return DEFAULT; - } - - conf = conf->get("sip"); - if (!conf) { - return DEFAULT; - } - - conf = conf->get("candidate"); - if (!conf || conf->arg0().empty()) { - return DEFAULT; - } - - string eip = srs_getenv(conf->arg0()); - if (!eip.empty()) { - return eip; - } - - // If configed as ENV, but no ENV set, use default value. - if (srs_strings_starts_with(conf->arg0(), "$")) { - return DEFAULT; - } - - return conf->arg0(); -} - bool SrsConfig::get_rtsp_server_enabled() { SrsConfDirective *conf = root->get("rtsp_server"); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 9d2fc0e17..bf1130fef 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -484,16 +484,6 @@ public: virtual std::string get_stream_caster_output(SrsConfDirective *conf); // Get the listen port of stream caster. virtual int get_stream_caster_listen(SrsConfDirective *conf); - // Get the sip.enabled configuration. - virtual bool get_stream_caster_sip_enable(SrsConfDirective *conf); - // Get the sip.listen port configuration. - virtual int get_stream_caster_sip_listen(SrsConfDirective *conf); - // Get the sip.timeout configuration. - virtual srs_utime_t get_stream_caster_sip_timeout(SrsConfDirective *conf); - // Get the sip.reinvite configuration. - virtual srs_utime_t get_stream_caster_sip_reinvite(SrsConfDirective *conf); - // Get the candidate for SDP. - virtual std::string get_stream_caster_sip_candidate(SrsConfDirective *conf); // rtsp section public: virtual bool get_rtsp_server_enabled(); diff --git a/trunk/src/app/srs_app_gb28181.cpp b/trunk/src/app/srs_app_gb28181.cpp index dda5bed40..46896e239 100644 --- a/trunk/src/app/srs_app_gb28181.cpp +++ b/trunk/src/app/srs_app_gb28181.cpp @@ -29,9 +29,6 @@ #include using namespace std; -// See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.7 -#define SRS_GB_BRANCH_MAGIC "z9hG4bK" -#define SRS_GB_SIP_PORT 5060 #define SRS_GB_MAX_RECOVER 16 #define SRS_GB_MAX_TIMEOUT 3 #define SRS_GB_LARGE_PACKET 1500 @@ -58,34 +55,7 @@ std::string srs_gb_state(SrsGbSessionState ostate, SrsGbSessionState state) return srs_fmt_sprintf("%s->%s", srs_gb_session_state(ostate).c_str(), srs_gb_session_state(state).c_str()); } -std::string srs_gb_sip_state(SrsGbSipState state) -{ - switch (state) { - case SrsGbSipStateInit: - return "Init"; - case SrsGbSipStateRegistered: - return "Registered"; - case SrsGbSipStateInviting: - return "Inviting"; - case SrsGbSipStateTrying: - return "Trying"; - case SrsGbSipStateStable: - return "Stable"; - case SrsGbSipStateReinviting: - return "Re-inviting"; - case SrsGbSipStateBye: - return "Bye"; - default: - return "Invalid"; - } -} - -std::string srs_sip_state(SrsGbSipState ostate, SrsGbSipState state) -{ - return srs_fmt_sprintf("%s->%s", srs_gb_sip_state(ostate).c_str(), srs_gb_sip_state(state).c_str()); -} - -SrsGbSession::SrsGbSession() : sip_(new SrsGbSipTcpConn()), media_(new SrsGbMediaTcpConn()) +SrsGbSession::SrsGbSession() : media_(new SrsGbMediaTcpConn()) { wrapper_ = NULL; owner_coroutine_ = NULL; @@ -95,10 +65,8 @@ SrsGbSession::SrsGbSession() : sip_(new SrsGbSipTcpConn()), media_(new SrsGbMedi state_ = SrsGbSessionStateInit; connecting_starttime_ = 0; - connecting_timeout_ = 0; nn_timeout_ = 0; reinviting_starttime_ = 0; - reinvite_wait_ = 0; ppp_ = new SrsAlonePithyPrint(); startime_ = srs_time_now_realtime(); @@ -128,18 +96,10 @@ SrsGbSession::~SrsGbSession() void SrsGbSession::setup(SrsConfDirective *conf) { - pip_ = candidate_ = _srs_config->get_stream_caster_sip_candidate(conf); - if (candidate_ == "*") { - pip_ = srs_get_public_internet_address(true); - } - std::string output = _srs_config->get_stream_caster_output(conf); muxer_->setup(output); - connecting_timeout_ = _srs_config->get_stream_caster_sip_timeout(conf); - reinvite_wait_ = _srs_config->get_stream_caster_sip_reinvite(conf); - srs_trace("Session: Start timeout=%dms, reinvite=%dms, candidate=%s, pip=%s, output=%s", srsu2msi(connecting_timeout_), - srsu2msi(reinvite_wait_), candidate_.c_str(), pip_.c_str(), output.c_str()); + srs_trace("Session: Start output=%s", output.c_str()); } void SrsGbSession::setup_owner(SrsSharedResource *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid) @@ -212,18 +172,6 @@ void SrsGbSession::on_ps_pack(SrsPackContext *ctx, SrsPsPacket *ps, const std::v } } -void SrsGbSession::on_sip_transport(SrsSharedResource sip) -{ - sip_ = sip; - // Change id of SIP and all its child coroutines. - sip_->set_cid(cid_); -} - -SrsSharedResource SrsGbSession::sip_transport() -{ - return sip_; -} - void SrsGbSession::on_media_transport(SrsSharedResource media) { media_ = media; @@ -232,11 +180,6 @@ void SrsGbSession::on_media_transport(SrsSharedResource media media_->set_cid(cid_); } -std::string SrsGbSession::pip() -{ - return pip_; -} - srs_error_t SrsGbSession::cycle() { srs_error_t err = srs_success; @@ -244,14 +187,13 @@ srs_error_t SrsGbSession::cycle() // Update all context id to cid of session. _srs_context->set_id(cid_); owner_cid_->set_cid(cid_); - sip_->set_cid(cid_); + media_->set_cid(cid_); // Drive the session cycle. err = do_cycle(); - // Interrupt the SIP and media transport when session terminated. - sip_->interrupt(); + // Interrupt the media transport when session terminated. media_->interrupt(); // success. @@ -295,12 +237,7 @@ srs_error_t SrsGbSession::do_cycle() // Drive the state in a fixed interval. srs_usleep(SRS_GB_SESSION_DRIVE_INTERVAL); - // Client send bye, we should dispose the session. - if (sip_->is_bye()) { - return err; - } - - // Regular state, driven by state of SIP and transport. + // Regular state, driven by state of transport. if ((err = drive_state()) != srs_success) { return srs_error_wrap(err, "drive"); } @@ -323,68 +260,24 @@ srs_error_t SrsGbSession::drive_state() { srs_error_t err = srs_success; -#define SRS_GB_CHANGE_STATE_TO(state) \ - { \ - SrsGbSessionState ostate = set_state(state); \ - srs_trace("Session: Change device=%s, state=%s", sip_->device_id().c_str(), \ - srs_gb_state(ostate, state_).c_str()); \ +#define SRS_GB_CHANGE_STATE_TO(state) \ + { \ + SrsGbSessionState ostate = set_state(state); \ + srs_trace("Session: Change device=%s, state=%s", device_id_.c_str(), \ + srs_gb_state(ostate, state_).c_str()); \ } if (state_ == SrsGbSessionStateInit) { - // Set to connecting, whatever media is connected or not, because the connecting state will handle it if media - // is connected, so we don't need to handle it here. - if (sip_->is_registered()) { - SRS_GB_CHANGE_STATE_TO(SrsGbSessionStateConnecting); - connecting_starttime_ = srs_time_now_realtime(); - } - - // Invite if media is not connected. - if (sip_->is_registered() && !media_->is_connected()) { - uint32_t ssrc = 0; - if ((err = sip_->invite_request(&ssrc)) != srs_success) { - return srs_error_wrap(err, "invite"); - } - - // Now, we're able to query session by ssrc, for media packets. - _srs_gb_manager->add_with_fast_id(ssrc, wrapper_); - } - } - - if (state_ == SrsGbSessionStateConnecting) { - if (srs_time_now_realtime() - connecting_starttime_ >= connecting_timeout_) { - if ((nn_timeout_++) > SRS_GB_MAX_TIMEOUT) { - return srs_error_new(ERROR_GB_TIMEOUT, "timeout"); - } - - srs_trace("Session: Connecting timeout, nn=%d, state=%s, sip=%s, media=%d", nn_timeout_, srs_gb_session_state(state_).c_str(), - srs_gb_sip_state(sip_->state()).c_str(), media_->is_connected()); - sip_->reset_to_register(); - SRS_GB_CHANGE_STATE_TO(SrsGbSessionStateInit); - } - - if (sip_->is_stable() && media_->is_connected()) { + // With external SIP server, we assume media connection is handled externally + if (media_->is_connected()) { SRS_GB_CHANGE_STATE_TO(SrsGbSessionStateEstablished); } } if (state_ == SrsGbSessionStateEstablished) { - if (sip_->is_bye()) { - srs_trace("Session: Dispose for client bye"); - return err; - } - - // When media disconnected, we wait for a while then reinvite. + // Simple state management - just check if media is still connected if (!media_->is_connected()) { - if (!reinviting_starttime_) { - reinviting_starttime_ = srs_time_now_realtime(); - } - if (srs_time_now_cached() - reinviting_starttime_ > reinvite_wait_) { - reinviting_starttime_ = 0; - srs_trace("Session: Re-invite for disconnect, state=%s, sip=%s, media=%d", srs_gb_session_state(state_).c_str(), - srs_gb_sip_state(sip_->state()).c_str(), media_->is_connected()); - sip_->reset_to_register(); - SRS_GB_CHANGE_STATE_TO(SrsGbSessionStateInit); - } + SRS_GB_CHANGE_STATE_TO(SrsGbSessionStateInit); } } @@ -411,14 +304,12 @@ std::string SrsGbSession::desc() SrsGbListener::SrsGbListener() { conf_ = NULL; - sip_listener_ = new SrsTcpListener(this); media_listener_ = new SrsTcpListener(this); } SrsGbListener::~SrsGbListener() { srs_freep(conf_); - srs_freep(sip_listener_); srs_freep(media_listener_); } @@ -435,14 +326,6 @@ srs_error_t SrsGbListener::initialize(SrsConfDirective *conf) media_listener_->set_endpoint(ip, port)->set_label("GB-TCP"); } - bool sip_enabled = _srs_config->get_stream_caster_sip_enable(conf); - if (!sip_enabled) { - srs_warn("GB SIP is disabled."); - } else { - int port = _srs_config->get_stream_caster_sip_listen(conf); - sip_listener_->set_endpoint(ip, port)->set_label("SIP-TCP"); - } - return err; } @@ -454,10 +337,6 @@ srs_error_t SrsGbListener::listen() return srs_error_wrap(err, "listen"); } - if ((err = sip_listener_->listen()) != srs_success) { - return srs_error_wrap(err, "listen"); - } - if ((err = listen_api()) != srs_success) { return srs_error_wrap(err, "listen api"); } @@ -486,21 +365,7 @@ srs_error_t SrsGbListener::on_tcp_client(ISrsListener *listener, srs_netfd_t stf srs_error_t err = srs_success; // Handle TCP connections. - if (listener == sip_listener_) { - SrsGbSipTcpConn *raw_conn = new SrsGbSipTcpConn(); - raw_conn->setup(conf_, sip_listener_, media_listener_, stfd); - - SrsSharedResource *conn = new SrsSharedResource(raw_conn); - _srs_gb_manager->add(conn, NULL); - - SrsExecutorCoroutine *executor = new SrsExecutorCoroutine(_srs_gb_manager, conn, raw_conn, raw_conn); - raw_conn->setup_owner(conn, executor, executor); - - if ((err = executor->start()) != srs_success) { - srs_freep(executor); - return srs_error_wrap(err, "gb sip"); - } - } else if (listener == media_listener_) { + if (listener == media_listener_) { SrsGbMediaTcpConn *raw_conn = new SrsGbMediaTcpConn(); raw_conn->setup(stfd); @@ -522,760 +387,6 @@ srs_error_t SrsGbListener::on_tcp_client(ISrsListener *listener, srs_netfd_t stf return err; } -SrsGbSipTcpConn::SrsGbSipTcpConn() -{ - wrapper_ = NULL; - owner_coroutine_ = NULL; - owner_cid_ = NULL; - cid_ = _srs_context->get_id(); - - session_ = NULL; - state_ = SrsGbSipStateInit; - register_ = new SrsSipMessage(); - invite_ok_ = new SrsSipMessage(); - ssrc_v_ = 0; - - conf_ = NULL; - sip_listener_ = NULL; - media_listener_ = NULL; - conn_ = NULL; - receiver_ = NULL; - sender_ = NULL; -} - -SrsGbSipTcpConn::~SrsGbSipTcpConn() -{ - srs_freep(receiver_); - srs_freep(sender_); - srs_freep(conn_); - srs_freep(register_); - srs_freep(invite_ok_); - srs_freep(conf_); -} - -void SrsGbSipTcpConn::setup(SrsConfDirective *conf, SrsTcpListener *sip, SrsTcpListener *media, srs_netfd_t stfd) -{ - srs_freep(conf_); - conf_ = conf->copy(); - - sip_listener_ = sip; - media_listener_ = media; - conn_ = new SrsTcpConnection(stfd); - receiver_ = new SrsGbSipTcpReceiver(this, conn_); - sender_ = new SrsGbSipTcpSender(conn_); -} - -void SrsGbSipTcpConn::setup_owner(SrsSharedResource *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid) -{ - wrapper_ = wrapper; - owner_coroutine_ = owner_coroutine; - owner_cid_ = owner_cid; -} - -void SrsGbSipTcpConn::on_executor_done(ISrsInterruptable *executor) -{ - owner_coroutine_ = NULL; -} - -std::string SrsGbSipTcpConn::device_id() -{ - return register_->device_id(); -} - -void SrsGbSipTcpConn::set_device_id(const std::string &id) -{ - register_->from_address_user_ = id; -} - -void SrsGbSipTcpConn::set_cid(const SrsContextId &cid) -{ - if (owner_cid_) - owner_cid_->set_cid(cid); - if (receiver_) - receiver_->set_cid(cid); - if (sender_) - sender_->set_cid(cid); - cid_ = cid; -} - -void SrsGbSipTcpConn::query_ports(int *sip, int *media) -{ - if (sip) - *sip = sip_listener_->port(); - if (media) - *media = media_listener_->port(); -} - -srs_error_t SrsGbSipTcpConn::on_sip_message(SrsSipMessage *msg) -{ - srs_error_t err = srs_success; - - // Finger out the GB session to handle SIP messages. - if (!session_ && (err = bind_session(msg, &session_)) != srs_success) { - return srs_error_wrap(err, "bind session"); - } - - // Ignore if session not found. - if (!session_) { - srs_warn("SIP: No session, drop message type=%d, id=%s, body=%s", msg->type_, - msg->device_id().c_str(), msg->body_escaped_.c_str()); - return err; - } - - // For state to use device id from register message. - if (msg->is_register()) { - srs_freep(register_); - register_ = msg->copy(); // Cache the register request message. - } - - // Drive state machine of SIP connection. - drive_state(msg); - - // Notify session about the SIP message. - if (msg->is_register()) { - register_response(msg); // Response for REGISTER. - } else if (msg->is_message()) { - // Response for MESSAGE, the heartbeat message. - // Set 403 to require client register, see https://www.ietf.org/rfc/rfc3261.html#section-21.4 - // Please note that it does not work for GB device, which just ignore 4xx packets like no response. - message_response(msg, (state_ == SrsGbSipStateInit ? HTTP_STATUS_FORBIDDEN : HTTP_STATUS_OK)); - } else if (msg->is_invite_ok()) { - srs_freep(invite_ok_); - invite_ok_ = msg->copy(); // Cache the invite ok message. - invite_ack(msg); // Response for INVITE OK. - } else if (msg->is_bye()) { - bye_response(msg); // Response for Bye OK. - } else if (msg->is_trying() || msg->is_bye_ok()) { - // Ignore SIP message 100(Trying). - // Ignore BYE ok. - } else { - srs_warn("SIP: Ignore message type=%d, status=%d, method=%d, body=%s", msg->type_, - msg->status_, msg->method_, msg->body_escaped_.c_str()); - } - - return err; -} - -void SrsGbSipTcpConn::enqueue_sip_message(SrsSipMessage *msg) -{ - // Drive state machine when enqueue message. - drive_state(msg); - - // TODO: Support SIP transaction and wait for response for request? - sender_->enqueue(msg); -} - -void SrsGbSipTcpConn::drive_state(SrsSipMessage *msg) -{ - srs_error_t err = srs_success; - -#define SRS_GB_SIP_CHANGE_STATE_TO(state) \ - { \ - SrsGbSipState ostate = set_state(state); \ - srs_trace("SIP: Change device=%s, state=%s", register_->device_id().c_str(), \ - srs_sip_state(ostate, state_).c_str()); \ - } - - // const char* mt = msg->type_ == HTTP_REQUEST ? "REQUEST" : "RESPONSE"; - // const char* mm = msg->type_ == HTTP_REQUEST ? http_method_str(msg->method_) : "Response"; - // int ms = msg->type_ == HTTP_REQUEST ? 200 : msg->status_; - // srs_trace("SIP: Got message type=%s, method=%s, status=%d, expire=%d", mt, mm, ms, msg->expires_); - - if (state_ == SrsGbSipStateInit) { - // The register message, we will invite it automatically. - if (msg->is_register() && msg->expires_ > 0) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateRegistered); - // Client bye or unregister, we should destroy the session because it might never publish again. - if (msg->is_register() && msg->expires_ == 0) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateBye); - // When got heartbeat message, we restore to stable state. - if (msg->is_message()) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateStable); - } - - if (state_ == SrsGbSipStateRegistered) { - if (msg->is_invite()) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateInviting); - } - - if (state_ == SrsGbSipStateInviting) { - if (msg->is_trying()) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateTrying); - if (msg->is_invite_ok()) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateStable); - - // If device got invite request and disconnect, it might register again, we should re-invite. - if (msg->is_register()) { - srs_warn("SIP: Re-invite for got REGISTER in state=%s", srs_gb_sip_state(state_).c_str()); - if ((err = invite_request(NULL)) != srs_success) { - // TODO: FIXME: Should fail the SIP session. - srs_freep(err); - } - } - } - - if (state_ == SrsGbSipStateTrying) { - if (msg->is_invite_ok()) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateStable); - } - - if (state_ == SrsGbSipStateStable) { - // Client bye or unregister, we should destroy the session because it might never publish again. - if (msg->is_register() && msg->expires_ == 0) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateBye); - if (msg->is_bye()) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateBye); - } - - if (state_ == SrsGbSipStateReinviting) { - if (msg->is_bye_ok()) - SRS_GB_SIP_CHANGE_STATE_TO(SrsGbSipStateInviting); - } -} - -void SrsGbSipTcpConn::register_response(SrsSipMessage *msg) -{ - SrsSipMessage *res = new SrsSipMessage(); - - res->type_ = HTTP_RESPONSE; - res->status_ = HTTP_STATUS_OK; - res->via_ = msg->via_; - res->from_ = msg->from_; - res->to_ = msg->to_; - res->cseq_ = msg->cseq_; - res->call_id_ = msg->call_id_; - res->contact_ = msg->contact_; - res->expires_ = msg->expires_; - - enqueue_sip_message(res); -} - -void SrsGbSipTcpConn::message_response(SrsSipMessage *msg, http_status status) -{ - SrsSipMessage *res = new SrsSipMessage(); - - res->type_ = HTTP_RESPONSE; - res->status_ = status; - res->via_ = msg->via_; - res->from_ = msg->from_; - res->to_ = msg->to_; - res->cseq_ = msg->cseq_; - res->call_id_ = msg->call_id_; - - enqueue_sip_message(res); -} - -void SrsGbSipTcpConn::invite_ack(SrsSipMessage *msg) -{ - string pip = session_->pip(); // Parse from CANDIDATE - int sip_port; - query_ports(&sip_port, NULL); - string gb_device_id = srs_fmt_sprintf("sip:%s@%s", msg->to_address_user_.c_str(), msg->to_address_host_.c_str()); - string branch = srs_rand_gen_str(6); - - SrsSipMessage *req = new SrsSipMessage(); - req->type_ = HTTP_REQUEST; - req->method_ = HTTP_ACK; - req->request_uri_ = gb_device_id; - req->via_ = srs_fmt_sprintf("SIP/2.0/TCP %s:%d;rport;branch=%s%s", pip.c_str(), sip_port, SRS_GB_BRANCH_MAGIC, branch.c_str()); - req->from_ = msg->from_; - req->to_ = msg->to_; - req->cseq_ = srs_fmt_sprintf("%d ACK", msg->cseq_number_); - req->call_id_ = msg->call_id_; - req->max_forwards_ = 70; - - enqueue_sip_message(req); -} - -void SrsGbSipTcpConn::bye_response(SrsSipMessage *msg) -{ - SrsSipMessage *res = new SrsSipMessage(); - - res->type_ = HTTP_RESPONSE; - res->status_ = HTTP_STATUS_OK; - res->via_ = msg->via_; - res->from_ = msg->from_; - res->to_ = msg->to_; - res->cseq_ = msg->cseq_; - res->call_id_ = msg->call_id_; - - enqueue_sip_message(res); -} - -srs_error_t SrsGbSipTcpConn::invite_request(uint32_t *pssrc) -{ - srs_error_t err = srs_success; - - srs_assert(register_); - - if (true) { - // Generate SSRC, detect conflict. - string ssrc = ssrc_str_; - for (int i = 0; ssrc.empty() && i < 16; i++) { - int flag = 0; // 0 is realtime. - string ssrc_str = srs_fmt_sprintf("%d%s%04d", flag, register_->ssrc_domain_id().c_str(), srs_rand_integer() % 10000); - uint32_t ssrc_v = (uint32_t)::atol(ssrc_str.c_str()); - if (!_srs_gb_manager->find_by_fast_id(ssrc_v)) { - ssrc = ssrc_str; - break; - } - } - if (ssrc.empty()) { - return srs_error_new(ERROR_GB_SSRC_GENERATE, "Generate SSRC failed"); - } - - // Update and cache the SSRC for re-invite. - ssrc_str_ = ssrc; - ssrc_v_ = (uint32_t)::atol(ssrc_str_.c_str()); - if (pssrc) - *pssrc = ssrc_v_; - } - - string pip = session_->pip(); // Parse from CANDIDATE - int sip_port, media_port; - query_ports(&sip_port, &media_port); - string srs_device_id = srs_fmt_sprintf("sip:%s@%s", register_->request_uri_user_.c_str(), register_->request_uri_host_.c_str()); - string gb_device_id = srs_fmt_sprintf("sip:%s@%s", register_->from_address_user_.c_str(), register_->from_address_host_.c_str()); - string subject = srs_fmt_sprintf("%s:%s,%s:0", register_->from_address_user_.c_str(), ssrc_str_.c_str(), register_->request_uri_user_.c_str()); - string branch = srs_rand_gen_str(6); - string tag = srs_rand_gen_str(8); - string call_id = srs_rand_gen_str(16); - int cseq = (int)(srs_rand_integer() % 1000); // TODO: FIXME: Increase. - - SrsSdp local_sdp; - local_sdp.version_ = "0"; - local_sdp.username_ = register_->contact_user_; - local_sdp.session_id_ = "0"; - local_sdp.session_version_ = "0"; - local_sdp.nettype_ = "IN"; - local_sdp.addrtype_ = "IP4"; - local_sdp.unicast_address_ = pip; // Parse from CANDIDATE - local_sdp.session_name_ = "Play"; - local_sdp.start_time_ = 0; - local_sdp.end_time_ = 0; - local_sdp.ice_lite_ = ""; // Disable this line. - local_sdp.connection_ = srs_fmt_sprintf("c=IN IP4 %s", pip.c_str()); // Session level connection. - - local_sdp.media_descs_.push_back(SrsMediaDesc("video")); - SrsMediaDesc &media = local_sdp.media_descs_.at(0); - media.port_ = media_port; // Read from config. - media.protos_ = "TCP/RTP/AVP"; - media.connection_ = ""; // Disable media level connection. - media.recvonly_ = true; - - media.payload_types_.push_back(SrsMediaPayloadType(96)); - SrsMediaPayloadType &ps = media.payload_types_.at(0); - ps.encoding_name_ = "PS"; - ps.clock_rate_ = 90000; - - media.ssrc_infos_.push_back(SrsSSRCInfo()); - SrsSSRCInfo &ssrc_info = media.ssrc_infos_.at(0); - ssrc_info.cname_ = ssrc_str_; - ssrc_info.ssrc_ = ssrc_v_; - ssrc_info.label_ = "gb28181"; - - ostringstream ss; - if ((err = local_sdp.encode(ss)) != srs_success) { - return srs_error_wrap(err, "encode sdp"); - } - - SrsSipMessage *req = new SrsSipMessage(); - req->type_ = HTTP_REQUEST; - req->method_ = HTTP_INVITE; - req->request_uri_ = gb_device_id; - req->via_ = srs_fmt_sprintf("SIP/2.0/TCP %s:%d;rport;branch=%s%s", pip.c_str(), sip_port, SRS_GB_BRANCH_MAGIC, branch.c_str()); - req->from_ = srs_fmt_sprintf("<%s>;tag=SRS%s", srs_device_id.c_str(), tag.c_str()); - req->to_ = srs_fmt_sprintf("<%s>", gb_device_id.c_str()); - req->cseq_ = srs_fmt_sprintf("%d INVITE", cseq); - req->call_id_ = call_id; - req->content_type_ = "Application/SDP"; - req->contact_ = srs_fmt_sprintf("<%s>", srs_device_id.c_str()); - req->max_forwards_ = 70; - req->subject_ = subject; - req->set_body(ss.str()); - - enqueue_sip_message(req); - srs_trace("SIP: INVITE device=%s, branch=%s, tag=%s, call=%s, ssrc=%s, sdp is %s", gb_device_id.c_str(), branch.c_str(), - tag.c_str(), call_id.c_str(), ssrc_str_.c_str(), req->body_escaped_.c_str()); - - return err; -} - -void SrsGbSipTcpConn::interrupt() -{ - receiver_->interrupt(); - sender_->interrupt(); - if (owner_coroutine_) - owner_coroutine_->interrupt(); -} - -SrsGbSipState SrsGbSipTcpConn::state() -{ - return state_; -} - -void SrsGbSipTcpConn::reset_to_register() -{ - state_ = SrsGbSipStateRegistered; -} - -bool SrsGbSipTcpConn::is_registered() -{ - return state_ >= SrsGbSipStateRegistered && state_ <= SrsGbSipStateStable; -} - -bool SrsGbSipTcpConn::is_stable() -{ - return state_ == SrsGbSipStateStable; -} - -bool SrsGbSipTcpConn::is_bye() -{ - return state_ == SrsGbSipStateBye; -} - -SrsGbSipState SrsGbSipTcpConn::set_state(SrsGbSipState v) -{ - SrsGbSipState state = state_; - state_ = v; - return state; -} - -const SrsContextId &SrsGbSipTcpConn::get_id() -{ - return cid_; -} - -std::string SrsGbSipTcpConn::desc() -{ - return "GB-SIP-TCP"; -} - -srs_error_t SrsGbSipTcpConn::cycle() -{ - srs_error_t err = srs_success; - - if ((err = receiver_->start()) != srs_success) { - return srs_error_wrap(err, "receiver"); - } - - if ((err = sender_->start()) != srs_success) { - return srs_error_wrap(err, "sender"); - } - - // Wait for the SIP connection to be terminated. - err = do_cycle(); - - // Interrupt the receiver and sender coroutine. - receiver_->interrupt(); - sender_->interrupt(); - - // success. - if (err == srs_success) { - srs_trace("client finished."); - return err; - } - - // It maybe success with message. - if (srs_error_code(err) == ERROR_SUCCESS) { - srs_trace("client finished%s.", srs_error_summary(err).c_str()); - srs_freep(err); - return err; - } - - // client close peer. - // TODO: FIXME: Only reset the error when client closed it. - if (srs_is_client_gracefully_close(err)) { - srs_warn("client disconnect peer. ret=%d", srs_error_code(err)); - } else if (srs_is_server_gracefully_close(err)) { - srs_warn("server disconnect. ret=%d", srs_error_code(err)); - } else { - srs_error("serve error %s", srs_error_desc(err).c_str()); - } - - srs_freep(err); - return srs_success; -} - -srs_error_t SrsGbSipTcpConn::do_cycle() -{ - srs_error_t err = srs_success; - - while (true) { - if (!owner_coroutine_) - return err; - if ((err = owner_coroutine_->pull()) != srs_success) { - return srs_error_wrap(err, "pull"); - } - - srs_usleep(SRS_UTIME_NO_TIMEOUT); - } - - return err; -} - -srs_error_t SrsGbSipTcpConn::bind_session(SrsSipMessage *msg, SrsGbSession **psession) -{ - srs_error_t err = srs_success; - - string device = msg->device_id(); - if (device.empty()) - return err; - - // Only create session for REGISTER request. - if (msg->type_ != HTTP_REQUEST || msg->method_ != HTTP_REGISTER) - return err; - - // Find exists session for register, might be created by another object and still alive. - SrsSharedResource *session = dynamic_cast *>(_srs_gb_manager->find_by_id(device)); - SrsGbSession *raw_session = session ? (*session).get() : NULL; - if (!session) { - // Create new GB session. - raw_session = new SrsGbSession(); - raw_session->setup(conf_); - - session = new SrsSharedResource(raw_session); - _srs_gb_manager->add_with_id(device, session); - - SrsExecutorCoroutine *executor = new SrsExecutorCoroutine(_srs_gb_manager, session, raw_session, raw_session); - raw_session->setup_owner(session, executor, executor); - - if ((err = executor->start()) != srs_success) { - srs_freep(executor); - return srs_error_wrap(err, "gb session"); - } - } - - // Try to load state from previous SIP connection. - SrsSharedResource pre = raw_session->sip_transport(); - if (pre.get() && pre.get() != this) { - state_ = pre->state_; - ssrc_str_ = pre->ssrc_str_; - ssrc_v_ = pre->ssrc_v_; - srs_freep(register_); - register_ = pre->register_->copy(); - srs_freep(invite_ok_); - invite_ok_ = pre->invite_ok_->copy(); - } - - // Notice session to use current SIP connection. - raw_session->on_sip_transport(*wrapper_); - *psession = raw_session; - - return err; -} - -SrsGbSipTcpReceiver::SrsGbSipTcpReceiver(SrsGbSipTcpConn *sip, SrsTcpConnection *conn) -{ - sip_ = sip; - conn_ = conn; - trd_ = new SrsSTCoroutine("sip-receiver", this); -} - -SrsGbSipTcpReceiver::~SrsGbSipTcpReceiver() -{ - srs_freep(trd_); -} - -void SrsGbSipTcpReceiver::interrupt() -{ - trd_->interrupt(); -} - -void SrsGbSipTcpReceiver::set_cid(const SrsContextId &cid) -{ - trd_->set_cid(cid); -} - -srs_error_t SrsGbSipTcpReceiver::start() -{ - srs_error_t err = srs_success; - - if ((err = trd_->start()) != srs_success) { - return srs_error_wrap(err, "coroutine"); - } - - return err; -} - -srs_error_t SrsGbSipTcpReceiver::cycle() -{ - srs_error_t err = do_cycle(); - - // TODO: FIXME: Notify SIP transport to cleanup. - if (err != srs_success) { - srs_error("SIP: Receive err %s", srs_error_desc(err).c_str()); - } - - return err; -} - -srs_error_t SrsGbSipTcpReceiver::do_cycle() -{ - srs_error_t err = srs_success; - - SrsUniquePtr parser(new SrsHttpParser()); - - // We might get SIP request or response message. - if ((err = parser->initialize(HTTP_BOTH)) != srs_success) { - return srs_error_wrap(err, "init parser"); - } - - while (true) { - if ((err = trd_->pull()) != srs_success) { - return srs_error_wrap(err, "pull"); - } - - // Use HTTP parser to parse SIP messages. - ISrsHttpMessage *hmsg_raw = NULL; - if ((err = parser->parse_message(conn_, &hmsg_raw)) != srs_success) { - return srs_error_wrap(err, "parse message"); - } - SrsUniquePtr hmsg(hmsg_raw); - - SrsSipMessage smsg; - if ((err = smsg.parse(hmsg.get())) != srs_success) { - srs_warn("SIP: Drop msg type=%d, method=%d, err is %s", hmsg->message_type(), hmsg->method(), srs_error_summary(err).c_str()); - srs_freep(err); - continue; - } - - if ((err = sip_->on_sip_message(&smsg)) != srs_success) { - srs_warn("SIP: Ignore on msg err %s", srs_error_desc(err).c_str()); - srs_freep(err); - continue; - } - } - - return err; -} - -SrsGbSipTcpSender::SrsGbSipTcpSender(SrsTcpConnection *conn) -{ - conn_ = conn; - wait_ = srs_cond_new(); - trd_ = new SrsSTCoroutine("sip-sender", this); -} - -SrsGbSipTcpSender::~SrsGbSipTcpSender() -{ - srs_freep(trd_); - srs_cond_destroy(wait_); - - for (vector::iterator it = msgs_.begin(); it != msgs_.end(); ++it) { - SrsSipMessage *msg = *it; - srs_freep(msg); - } -} - -void SrsGbSipTcpSender::enqueue(SrsSipMessage *msg) -{ - msgs_.push_back(msg); - srs_cond_signal(wait_); -} - -void SrsGbSipTcpSender::interrupt() -{ - trd_->interrupt(); -} - -void SrsGbSipTcpSender::set_cid(const SrsContextId &cid) -{ - trd_->set_cid(cid); -} - -srs_error_t SrsGbSipTcpSender::start() -{ - srs_error_t err = srs_success; - - if ((err = trd_->start()) != srs_success) { - return srs_error_wrap(err, "coroutine"); - } - - return err; -} - -srs_error_t SrsGbSipTcpSender::cycle() -{ - srs_error_t err = do_cycle(); - - // TODO: FIXME: Notify SIP transport to cleanup. - if (err != srs_success) { - srs_error("SIP: Send err %s", srs_error_desc(err).c_str()); - } - - return err; -} - -srs_error_t SrsGbSipTcpSender::do_cycle() -{ - srs_error_t err = srs_success; - - while (true) { - if (msgs_.empty()) { - srs_cond_wait(wait_); - } - - if ((err = trd_->pull()) != srs_success) { - return srs_error_wrap(err, "pull"); - } - - SrsUniquePtr msg(msgs_.front()); - msgs_.erase(msgs_.begin()); - - if (msg->type_ == HTTP_RESPONSE) { - SrsSipResponseWriter res(conn_); - res.header()->set("Via", msg->via_); - res.header()->set("From", msg->from_); - res.header()->set("To", msg->to_); - res.header()->set("CSeq", msg->cseq_); - res.header()->set("Call-ID", msg->call_id_); - res.header()->set("User-Agent", RTMP_SIG_SRS_SERVER); - if (!msg->contact_.empty()) - res.header()->set("Contact", msg->contact_); - if (msg->expires_ != UINT32_MAX) - res.header()->set("Expires", srs_strconv_format_int(msg->expires_)); - - res.header()->set_content_length(msg->body_.length()); - res.write_header(msg->status_); - if (!msg->body_.empty()) - res.write((char *)msg->body_.c_str(), msg->body_.length()); - if ((err = res.final_request()) != srs_success) { - return srs_error_wrap(err, "response"); - } - } else if (msg->type_ == HTTP_REQUEST) { - SrsSipRequestWriter req(conn_); - req.header()->set("Via", msg->via_); - req.header()->set("From", msg->from_); - req.header()->set("To", msg->to_); - req.header()->set("CSeq", msg->cseq_); - req.header()->set("Call-ID", msg->call_id_); - req.header()->set("User-Agent", RTMP_SIG_SRS_SERVER); - if (!msg->contact_.empty()) - req.header()->set("Contact", msg->contact_); - if (!msg->subject_.empty()) - req.header()->set("Subject", msg->subject_); - if (msg->max_forwards_) - req.header()->set("Max-Forwards", srs_strconv_format_int(msg->max_forwards_)); - - if (!msg->content_type_.empty()) - req.header()->set_content_type(msg->content_type_); - req.header()->set_content_length(msg->body_.length()); - req.write_header(http_method_str(msg->method_), msg->request_uri_); - if (!msg->body_.empty()) - req.write((char *)msg->body_.c_str(), msg->body_.length()); - if ((err = req.final_request()) != srs_success) { - return srs_error_wrap(err, "request"); - } - } else { - srs_warn("SIP: Sender drop message type=%d, method=%s, body=%dB", msg->type_, - http_method_str(msg->method_), msg->body_.length()); - } - } - - return err; -} - ISrsPsPackHandler::ISrsPsPackHandler() { } @@ -2156,7 +1267,7 @@ srs_error_t SrsGbMuxer::connect() // Cleanup the data before connect again. close(); - string url = srs_strings_replace(output_, "[stream]", session_->sip_transport()->device_id()); + string url = srs_strings_replace(output_, "[stream]", session_->device_id_); srs_trace("Muxer: Convert GB to RTMP %s", url.c_str()); srs_utime_t cto = SRS_CONSTS_RTMP_TIMEOUT; @@ -2189,318 +1300,6 @@ void SrsGbMuxer::close() h264_pps_ = ""; } -SrsSipResponseWriter::SrsSipResponseWriter(ISrsProtocolReadWriter *io) : SrsHttpResponseWriter(io) -{ -} - -SrsSipResponseWriter::~SrsSipResponseWriter() -{ -} - -srs_error_t SrsSipResponseWriter::build_first_line(std::stringstream &ss, char *data, int size) -{ - // Write status line for response. - ss << "SIP/2.0 " << status << " " << srs_generate_http_status_text(status) << SRS_HTTP_CRLF; - return srs_success; -} - -SrsSipRequestWriter::SrsSipRequestWriter(ISrsProtocolReadWriter *io) : SrsHttpRequestWriter(io) -{ -} - -SrsSipRequestWriter::~SrsSipRequestWriter() -{ -} - -srs_error_t SrsSipRequestWriter::build_first_line(std::stringstream &ss, char *data, int size) -{ - // Write status line for response. - ss << method_ << " " << path_ << " SIP/2.0" << SRS_HTTP_CRLF; - return srs_success; -} - -SrsSipMessage::SrsSipMessage() -{ - method_ = HTTP_GET; - cseq_number_ = 0; - expires_ = UINT32_MAX; // Never use 0 because it means unregister. - max_forwards_ = 0; - via_send_by_port_ = SRS_GB_SIP_PORT; - contact_host_port_ = SRS_GB_SIP_PORT; -} - -SrsSipMessage::~SrsSipMessage() -{ -} - -SrsSipMessage *SrsSipMessage::copy() -{ - SrsSipMessage *cp = new SrsSipMessage(); - *cp = *this; - return cp; -} - -const std::string &SrsSipMessage::device_id() -{ - // If request is sent by device, then the "from" address must be the ID of device. While we use id to identify the - // requests of device, so we can use the "from" address. - return from_address_user_; -} - -std::string SrsSipMessage::ssrc_domain_id() -{ - // The request uri user is GB domain, the 4-8 is used as domain id for SSRC, so the length must be 8+ bytes, - // see https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=469659DC56B9B8187671FF08748CEC89 - return (request_uri_user_.length() < 8) ? "00000" : request_uri_user_.substr(3, 5); -} - -SrsSipMessage *SrsSipMessage::set_body(std::string v) -{ - body_ = v; - body_escaped_ = v; - body_escaped_ = srs_strings_replace(body_escaped_, "\r", "\\r"); - body_escaped_ = srs_strings_replace(body_escaped_, "\n", "\\n"); - return this; -} - -srs_error_t SrsSipMessage::parse(ISrsHttpMessage *m) -{ - srs_error_t err = srs_success; - - // Parse body if exists any. Note that we must read body even the message is invalid, because we might need to parse - // the next message when skip current invalid message. - string v; - ISrsHttpResponseReader *br = m->body_reader(); - if (!br->eof() && (err = srs_io_readall(br, v)) != srs_success) { - return srs_error_wrap(err, "read body"); - } - - set_body(v); - - // Parse the first line. - type_ = (http_parser_type)m->message_type(); - if (type_ == HTTP_REQUEST) { - // Parse request line. - method_ = (http_method)m->method(); - request_uri_ = srs_strings_trim_start(m->path(), "/"); - srs_sip_parse_address(request_uri_, request_uri_user_, request_uri_host_); - } else if (type_ == HTTP_RESPONSE) { - // Parse status line for response. - status_ = (http_status)m->status_code(); - } else { - return srs_error_new(ERROR_GB_SIP_HEADER, "Invalid message type=%d", type_); - } - - // Check fields for SIP request. - if (type_ == HTTP_REQUEST) { - if (method_ < HTTP_REGISTER || method_ > HTTP_BYE) { - return srs_error_new(ERROR_GB_SIP_MESSAGE, "Invalid method=%d(%s) of message", method_, http_method_str(method_)); - } - if (request_uri_.empty()) - return srs_error_new(ERROR_GB_SIP_MESSAGE, "No Request-URI in message"); - } - - // Get fields of SIP. - via_ = m->header()->get("Via"); - from_ = m->header()->get("From"); - to_ = m->header()->get("To"); - call_id_ = m->header()->get("Call-ID"); - cseq_ = m->header()->get("CSeq"); - contact_ = m->header()->get("Contact"); - subject_ = m->header()->get("Subject"); - content_type_ = m->header()->content_type(); - - string expires = m->header()->get("Expires"); - if (!expires.empty()) { - expires_ = (uint32_t)::atol(expires.c_str()); - // See https://www.ietf.org/rfc/rfc3261.html#section-20.19 - if (!expires_ && expires != "0") { - return srs_error_new(ERROR_GB_SIP_HEADER, "Invalid Expires=%s in header", expires.c_str()); - } - } - - string max_forwards = m->header()->get("Max-Forwards"); - if (!max_forwards.empty() && max_forwards != "0") { - max_forwards_ = (uint32_t)::atol(max_forwards.c_str()); - // See https://www.ietf.org/rfc/rfc3261.html#section-20.22 - if (!max_forwards_) { - return srs_error_new(ERROR_GB_SIP_HEADER, "Invalid Max-Forwards=%s in header", max_forwards.c_str()); - } - } - - if (via_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "No Via in header"); - if (from_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "No From in header"); - if (to_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "No To in header"); - if (call_id_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "No Call-ID in header"); - if (cseq_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "No CSeq in header"); - - // Parse more information from fields. - if ((err = parse_via(via_)) != srs_success) { - return srs_error_wrap(err, "parse via=%s", via_.c_str()); - } - if ((err = parse_from(from_)) != srs_success) { - return srs_error_wrap(err, "parse from=%s", from_.c_str()); - } - if ((err = parse_to(to_)) != srs_success) { - return srs_error_wrap(err, "parse to=%s", to_.c_str()); - } - if ((err = parse_cseq(cseq_)) != srs_success) { - return srs_error_wrap(err, "parse cseq=%s", cseq_.c_str()); - } - if ((err = parse_contact(contact_)) != srs_success) { - return srs_error_wrap(err, "parse contact=%s", contact_.c_str()); - } - - srs_sip_parse_address(from_address_, from_address_user_, from_address_host_); - srs_sip_parse_address(to_address_, to_address_user_, to_address_host_); - - // Except REGISTER, the initial Request-URI of the message SHOULD be set to the value of the URI in the To field. - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.1 - if (type_ == HTTP_REQUEST && method_ != HTTP_REGISTER && to_address_user_ != request_uri_user_) { - return srs_error_new(ERROR_GB_SIP_HEADER, "User of Request-URI=%s not in To=%s", request_uri_.c_str(), to_.c_str()); - } - - return err; -} - -srs_error_t SrsSipMessage::parse_via(const std::string &via) -{ - srs_error_t err = srs_success; - - if (!srs_strings_starts_with(via, "SIP/2.0/")) { - return srs_error_new(ERROR_GB_SIP_HEADER, "Via protocol invalid"); - } - - if (srs_strings_starts_with(via, "SIP/2.0/TCP")) { - via_transport_ = "TCP"; - } else if (srs_strings_starts_with(via, "SIP/2.0/UDP")) { - via_transport_ = "UDP"; - } else { - return srs_error_new(ERROR_GB_SIP_HEADER, "Via transport invalid"); - } - - vector vs = srs_strings_split(via, " "); - if (vs.size() <= 1) - return srs_error_new(ERROR_GB_SIP_HEADER, "Via no send-by"); - - vector params = srs_strings_split(vs[1], ";"); - if (params.size() <= 1) - return srs_error_new(ERROR_GB_SIP_HEADER, "Via no params"); - - via_send_by_ = params[0]; - srs_net_split_hostport(via_send_by_, via_send_by_address_, via_send_by_port_); - - for (int i = 1; i < (int)params.size(); i++) { - string param = params[i]; - if (srs_strings_starts_with(param, "rport")) { - via_rport_ = param; - } else if (srs_strings_starts_with(param, "branch")) { - via_branch_ = param; - } - } - - // Before a request is sent, the client transport MUST insert a value of the "sent-by" field into the Via header - // field. See https://www.ietf.org/rfc/rfc3261.html#section-18.1.1 - if (via_send_by_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "Via no sent-by"); - // The Via header field value MUST contain a branch parameter. - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.7 - if (via_branch_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "Via no branch"); - // The branch ID inserted by an element compliant with this specification MUST always begin with the characters - // "z9hG4bK". See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.7 - if (!srs_strings_starts_with(via_branch_, string("branch=") + SRS_GB_BRANCH_MAGIC)) { - return srs_error_new(ERROR_GB_SIP_HEADER, "Invalid branch=%s", via_branch_.c_str()); - } - - return err; -} - -srs_error_t SrsSipMessage::parse_from(const std::string &from) -{ - srs_error_t err = srs_success; - - vector params = srs_strings_split(from, ";"); - if (params.size() < 2) - return srs_error_new(ERROR_GB_SIP_HEADER, "From no params"); - - from_address_ = params[0]; - for (int i = 1; i < (int)params.size(); i++) { - string param = params[i]; - if (srs_strings_starts_with(param, "tag")) { - from_tag_ = param; - } - } - - // The From field MUST contain a new "tag" parameter, chosen by the UAC. - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.3 - if (from_tag_.empty()) - return srs_error_new(ERROR_GB_SIP_HEADER, "From no tag"); - - return err; -} - -srs_error_t SrsSipMessage::parse_to(const std::string &to) -{ - srs_error_t err = srs_success; - - vector params = srs_strings_split(to, ";"); - if (params.size() < 1) - return srs_error_new(ERROR_GB_SIP_HEADER, "To is empty"); - - to_address_ = params[0]; - for (int i = 1; i < (int)params.size(); i++) { - string param = params[i]; - if (srs_strings_starts_with(param, "tag")) { - to_tag_ = param; - } - } - - return err; -} - -srs_error_t SrsSipMessage::parse_cseq(const std::string &cseq) -{ - srs_error_t err = srs_success; - - vector params = srs_strings_split(cseq, " "); - if (params.size() < 2) - return srs_error_new(ERROR_GB_SIP_HEADER, "CSeq is empty"); - - string sno = params[0]; - if (sno != "0") { - cseq_number_ = (uint32_t)::atol(sno.c_str()); - - // The sequence number MUST be expressible as a 32-bit unsigned integer. - // See https://www.ietf.org/rfc/rfc3261.html#section-20.16 - if (!cseq_number_) - return srs_error_new(ERROR_GB_SIP_HEADER, "CSeq number is invalid"); - } - - cseq_method_ = params[1]; - // The method part of CSeq is case-sensitive. See https://www.ietf.org/rfc/rfc3261.html#section-20.16 - if (type_ == HTTP_REQUEST && string(http_method_str(method_)) != cseq_method_) { - return srs_error_new(ERROR_GB_SIP_HEADER, "CSeq method=%s is invalid, expect=%d(%s)", cseq_method_.c_str(), method_, http_method_str(method_)); - } - - return err; -} - -srs_error_t SrsSipMessage::parse_contact(const std::string &contact) -{ - srs_error_t err = srs_success; - - srs_sip_parse_address(contact, contact_user_, contact_host_); - srs_net_split_hostport(contact_host_, contact_host_address_, contact_host_port_); - - return err; -} - SrsPackContext::SrsPackContext(ISrsPsPackHandler *handler) { static uint32_t gid = 0; @@ -2748,29 +1547,6 @@ bool srs_skip_util_pack(SrsBuffer *stream) return false; } -void srs_sip_parse_address(const std::string &address, std::string &user, std::string &host) -{ - string v = address; - - size_t pos; - - if ((pos = v.find("<")) != string::npos) { - v = v.substr(pos + 1); - } - if ((pos = v.find(">")) != string::npos) { - v = v.substr(0, pos); - } - if ((pos = v.find("sip:")) != string::npos) { - v = v.substr(4); - } - - user = v; - if ((pos = v.find("@")) != string::npos) { - user = v.substr(0, pos); - host = v.substr(pos + 1); - } -} - SrsGoApiGbPublish::SrsGoApiGbPublish(SrsConfDirective *conf) { conf_ = conf->copy(); @@ -2873,7 +1649,7 @@ srs_error_t SrsGoApiGbPublish::bind_session(std::string id, uint64_t ssrc) 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); + raw_session->device_id_ = id; if ((err = executor->start()) != srs_success) { srs_freep(executor); diff --git a/trunk/src/app/srs_app_gb28181.hpp b/trunk/src/app/srs_app_gb28181.hpp index 77e3d9bf0..c73504a9a 100644 --- a/trunk/src/app/srs_app_gb28181.hpp +++ b/trunk/src/app/srs_app_gb28181.hpp @@ -25,12 +25,11 @@ class SrsTcpConnection; class SrsCoroutine; class SrsPackContext; class SrsBuffer; -class SrsSipMessage; + class SrsGbSession; -class SrsGbSipTcpConn; + class SrsGbMediaTcpConn; -class SrsGbSipTcpReceiver; -class SrsGbSipTcpSender; + class SrsAlonePithyPrint; class SrsGbMuxer; class SrsSimpleRtmpClient; @@ -58,34 +57,6 @@ enum SrsGbSessionState { }; std::string srs_gb_session_state(SrsGbSessionState state); -// The state machine for GB SIP connection. -// init: -// to registered: Got REGISTER SIP message. -// to stable: Got MESSAGE SIP message, when SIP TCP connection re-connect. -// registered: -// to inviting: Sent INVITE SIP message. -// inviting: -// to trying: Got TRYING SIP message. -// to stable: Got INVITE 200 OK and sent INVITE OK response. -// trying: -// to stable: Got INVITE 200 OK and sent INVITE OK response. -// stable: -// to re-inviting: Sent bye to device before re-inviting. -// to bye: Got bye SIP message from device. -// re-inviting: -// to inviting: Got bye OK response from deivce. -// Please see SrsGbSipTcpConn::drive_state for detail. -enum SrsGbSipState { - SrsGbSipStateInit = 0, - SrsGbSipStateRegistered, - SrsGbSipStateInviting, - SrsGbSipStateTrying, - SrsGbSipStateReinviting, - SrsGbSipStateStable, - SrsGbSipStateBye, -}; -std::string srs_gb_sip_state(SrsGbSipState state); - // For external SIP server mode, where SRS acts only as a media relay server // 1. SIP server POST request via HTTP API with stream ID and SSRC // 2. SRS create session using ID and SSRC, return a port for receiving media streams (indicated in conf). @@ -118,9 +89,9 @@ private: }; // The main logic object for GB, the session. -// Each session contains a SIP object and a media object, that are managed by session. This means session always -// lives longer than SIP and media, and session will dispose SIP and media when session disposed. In another word, -// SIP and media objects use directly pointer to session, while session use shared ptr. +// Each session contains a media object, that are managed by session. This means session always +// lives longer than media, and session will dispose media when session disposed. In another word, +// media objects use directly pointer to session, while session use shared ptr. class SrsGbSession : public ISrsResource, public ISrsCoroutineHandler, public ISrsExecutorHandler { private: @@ -135,23 +106,15 @@ private: private: SrsGbSessionState state_; - SrsSharedResource sip_; + SrsSharedResource media_; SrsGbMuxer *muxer_; private: - // The candidate for SDP in configuration. - std::string candidate_; - // The public IP for SDP, generated by SRS. - std::string pip_; - // When wait for SIP and media connecting, timeout if exceed. + // When wait for media connecting, timeout if exceed. srs_utime_t connecting_starttime_; - // The max timeout for connecting. - srs_utime_t connecting_timeout_; // The time we enter reinviting state. srs_utime_t reinviting_starttime_; - // The wait time for re-invite. - srs_utime_t reinvite_wait_; // The number of timeout, dispose session if exceed. uint32_t nn_timeout_; @@ -173,6 +136,11 @@ private: uint64_t media_msgs_dropped_; uint64_t media_reserved_; +public: + // The device ID generated and set by external SIP server, using SRS HTTP API. This + // device ID is used to generate the RTMP stream name. + std::string device_id_; + public: SrsGbSession(); virtual ~SrsGbSession(); @@ -189,13 +157,10 @@ public: public: // When got a pack of messages. void on_ps_pack(SrsPackContext *ctx, SrsPsPacket *ps, const std::vector &msgs); - // When got available SIP transport. - void on_sip_transport(SrsSharedResource sip); - SrsSharedResource sip_transport(); + // When got available media transport. void on_media_transport(SrsSharedResource media); - // Get the candidate for SDP generation, the public IP address for device to connect to. - std::string pip(); + // Interface ISrsCoroutineHandler public: virtual srs_error_t cycle(); @@ -212,13 +177,12 @@ public: virtual std::string desc(); }; -// The SIP and Media listener for GB. +// The Media listener for GB. class SrsGbListener : public ISrsListener, public ISrsTcpHandler { private: SrsConfDirective *conf_; SrsTcpListener *media_listener_; - SrsTcpListener *sip_listener_; public: SrsGbListener(); @@ -236,174 +200,6 @@ private: srs_error_t listen_api(); }; -// A GB28181 TCP SIP connection. -class SrsGbSipTcpConn : public ISrsResource, public ISrsCoroutineHandler, public ISrsExecutorHandler -{ -private: - SrsGbSipState state_; - // The owner session object, note that we use the raw pointer and should never free it. - SrsGbSession *session_; - SrsSipMessage *register_; - SrsSipMessage *invite_ok_; - -private: - std::string ssrc_str_; - uint32_t ssrc_v_; - -private: - SrsConfDirective *conf_; - SrsTcpListener *sip_listener_; - SrsTcpListener *media_listener_; - -private: - // The shared resource which own this object, we should never free it because it's managed by shared ptr. - SrsSharedResource *wrapper_; - // The owner coroutine, allow user to interrupt the loop. - ISrsInterruptable *owner_coroutine_; - ISrsContextIdSetter *owner_cid_; - SrsContextId cid_; - -private: - SrsTcpConnection *conn_; - SrsGbSipTcpReceiver *receiver_; - SrsGbSipTcpSender *sender_; - -public: - SrsGbSipTcpConn(); - virtual ~SrsGbSipTcpConn(); - -public: - // Setup object, to keep empty constructor. - void setup(SrsConfDirective *conf, SrsTcpListener *sip, SrsTcpListener *media, srs_netfd_t stfd); - // Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id. - void setup_owner(SrsSharedResource *wrapper, ISrsInterruptable *owner_coroutine, ISrsContextIdSetter *owner_cid); - // Interface ISrsExecutorHandler -public: - virtual void on_executor_done(ISrsInterruptable *executor); - -public: - // Get the SIP device id. - std::string device_id(); - // For use with external SIP signaling server ONLY - // When using an external SIP signaling server, device id are not available, so manual configuration is required - // This id will be used as the stream name in the RTMP protocol - void set_device_id(const std::string &id); - // Set the cid of all coroutines. - virtual void set_cid(const SrsContextId &cid); - -private: - // Get the sip and media listen port. - void query_ports(int *sip, int *media); - -public: - // When got a SIP message. - srs_error_t on_sip_message(SrsSipMessage *msg); - // Enqueue a SIP message to send, which might be a request or response. - void enqueue_sip_message(SrsSipMessage *msg); - -private: - void drive_state(SrsSipMessage *msg); - void register_response(SrsSipMessage *msg); - void message_response(SrsSipMessage *msg, http_status status); - void invite_ack(SrsSipMessage *msg); - void bye_response(SrsSipMessage *msg); - -public: - srs_error_t invite_request(uint32_t *pssrc); - -public: - // Interrupt transport by session. - void interrupt(); - // Get the SIP state. - SrsGbSipState state(); - // Reset the SIP state to registered, for re-inviting. - void reset_to_register(); - // Whether SIP state is registered or more. - bool is_registered(); - // Whether SIP state is stable state, established. - bool is_stable(); - // Whether SIP is bye bye. - bool is_bye(); - -private: - SrsGbSipState set_state(SrsGbSipState v); - // Interface ISrsResource -public: - virtual const SrsContextId &get_id(); - virtual std::string desc(); - // Interface ISrsCoroutineHandler -public: - virtual srs_error_t cycle(); - -private: - srs_error_t do_cycle(); - -private: - // Create session if no one, or bind to an existed session. - srs_error_t bind_session(SrsSipMessage *msg, SrsGbSession **psession); -}; - -// Start a coroutine to receive SIP messages. -class SrsGbSipTcpReceiver : public ISrsStartable, public ISrsCoroutineHandler -{ -private: - SrsCoroutine *trd_; - SrsTcpConnection *conn_; - SrsGbSipTcpConn *sip_; - -public: - SrsGbSipTcpReceiver(SrsGbSipTcpConn *sip, SrsTcpConnection *conn); - virtual ~SrsGbSipTcpReceiver(); - -public: - // Interrupt the receiver coroutine. - void interrupt(); - // Set the cid of all coroutines. - virtual void set_cid(const SrsContextId &cid); - // Interface ISrsStartable -public: - virtual srs_error_t start(); - // Interface ISrsCoroutineHandler -public: - virtual srs_error_t cycle(); - -private: - srs_error_t do_cycle(); -}; - -// Start a coroutine to send out SIP messages. -class SrsGbSipTcpSender : public ISrsStartable, public ISrsCoroutineHandler -{ -private: - SrsCoroutine *trd_; - SrsTcpConnection *conn_; - -private: - std::vector msgs_; - srs_cond_t wait_; - -public: - SrsGbSipTcpSender(SrsTcpConnection *conn); - virtual ~SrsGbSipTcpSender(); - -public: - // Push message to queue, and sender will send out in dedicate coroutine. - void enqueue(SrsSipMessage *msg); - // Interrupt the sender coroutine. - void interrupt(); - // Set the cid of all coroutines. - virtual void set_cid(const SrsContextId &cid); - // Interface ISrsStartable -public: - virtual srs_error_t start(); - // Interface ISrsCoroutineHandler -public: - virtual srs_error_t cycle(); - -private: - srs_error_t do_cycle(); -}; - // The handler for a pack of PS PES packets. class ISrsPsPackHandler { @@ -557,156 +353,6 @@ private: virtual void close(); }; -// Response writer for SIP. -class SrsSipResponseWriter : public SrsHttpResponseWriter -{ -public: - SrsSipResponseWriter(ISrsProtocolReadWriter *io); - virtual ~SrsSipResponseWriter(); - // Interface ISrsHttpFirstLineWriter -public: - virtual srs_error_t build_first_line(std::stringstream &ss, char *data, int size); -}; - -// Request writer for SIP. -class SrsSipRequestWriter : public SrsHttpRequestWriter -{ -public: - SrsSipRequestWriter(ISrsProtocolReadWriter *io); - virtual ~SrsSipRequestWriter(); - // Interface ISrsHttpFirstLineWriter -public: - virtual srs_error_t build_first_line(std::stringstream &ss, char *data, int size); -}; - -// SIP message, covert with HTTP message. -class SrsSipMessage -{ -public: - // SIP message type, request or response. - http_parser_type type_; - // For SIP request. - http_method method_; // For example: HTTP_INVITE - std::string request_uri_; // For example: sip:34020000001320000001@3402000000 - std::string request_uri_user_; // For example: 34020000001320000001 - std::string request_uri_host_; // For example: 3402000000 - // For SIP response. - http_status status_; // For example: HTTP_STATUS_OK -public: - // The Via header field indicates the path taken by the request so far and indicates the path that should be - // followed in routing responses. See https://www.ietf.org/rfc/rfc3261.html#section-20.42 - // @param transport TCP or UDP, the transport protocol. - // @param send_by The host and port which send the packet. - // @param branch Transaction identifier, see https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.7 - // @param rport For UDP to traverse NATs, see https://www.ietf.org/rfc/rfc3581.html - std::string via_; // For example: SIP/2.0/TCP 192.168.3.82:5060;rport;branch=z9hG4bK0l31rx - std::string via_transport_; // For example: TCP - std::string via_send_by_; // For example: 192.168.3.82:5060 - std::string via_send_by_address_; // For example: 192.168.3.82 - int via_send_by_port_; // For example: 5060 - std::string via_branch_; // For example: branch=z9hG4bK0l31rx - std::string via_rport_; // For example: rport -public: - // See https://www.ietf.org/rfc/rfc3261.html#section-20.20 - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.3 - std::string from_; // For example: ;tag=SRSk1er282t - std::string from_address_; // For example: - std::string from_address_user_; // For example: 34020000002000000001 - std::string from_address_host_; // For example: 3402000000 - std::string from_tag_; // For example: tag=SRSk1er282t -public: - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.2 - // See https://www.ietf.org/rfc/rfc3261.html#section-20.39 - std::string to_; // For example: ;tag=SRSk1er282t - std::string to_address_; // For example: - std::string to_address_user_; // For example: 34020000001320000001 - std::string to_address_host_; // For example: 3402000000 - std::string to_tag_; // For example: tag=SRSk1er282t -public: - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.4 - // See https://www.ietf.org/rfc/rfc3261.html#section-20.8 - std::string call_id_; // For example: 854k7337207yxpfj - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.8 - // See https://www.ietf.org/rfc/rfc3261.html#section-20.10 - std::string contact_; // For example: - std::string contact_user_; // For example: - std::string contact_host_; // For example: 3402000000 - std::string contact_host_address_; // For example: 3402000000 - int contact_host_port_; // For example: 5060 - // See https://www.ietf.org/rfc/rfc3261.html#section-20.19 - uint32_t expires_; - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.6 - // See https://www.ietf.org/rfc/rfc3261.html#section-20.22 - uint32_t max_forwards_; - -public: - // See https://www.ietf.org/rfc/rfc3261.html#section-8.1.1.5 - // See https://www.ietf.org/rfc/rfc3261.html#section-20.16 - std::string cseq_; - uint32_t cseq_number_; - std::string cseq_method_; - -public: - // See https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=469659DC56B9B8187671FF08748CEC89 - std::string subject_; - // The content type. - std::string content_type_; - -public: - // SIP message body. - std::string body_; - // Escape \r to \\r, \n to \\n. - std::string body_escaped_; - -public: - SrsSipMessage(); - virtual ~SrsSipMessage(); - -public: - SrsSipMessage *copy(); - const std::string &device_id(); - std::string ssrc_domain_id(); - SrsSipMessage *set_body(std::string v); - srs_error_t parse(ISrsHttpMessage *m); - -private: - srs_error_t parse_via(const std::string &via); - srs_error_t parse_from(const std::string &from); - srs_error_t parse_to(const std::string &to); - srs_error_t parse_cseq(const std::string &cseq); - srs_error_t parse_contact(const std::string &contact); - -public: - bool is_register() - { - return type_ == HTTP_REQUEST && method_ == HTTP_REGISTER; - } - bool is_message() - { - return type_ == HTTP_REQUEST && method_ == HTTP_MESSAGE; - } - bool is_invite() - { - return type_ == HTTP_REQUEST && method_ == HTTP_INVITE; - } - bool is_trying() - { - return type_ == HTTP_RESPONSE && cseq_method_ == "INVITE" && status_ == HTTP_STATUS_CONTINUE; - } - bool is_invite_ok() - { - return type_ == HTTP_RESPONSE && cseq_method_ == "INVITE" && status_ == HTTP_STATUS_OK; - } - bool is_bye() - { - return type_ == HTTP_REQUEST && method_ == HTTP_BYE; - } - bool is_bye_ok() - { - return type_ == HTTP_RESPONSE && cseq_method_ == "BYE" && status_ == HTTP_STATUS_OK; - } -}; - // Recoverable PS context for GB28181. class SrsRecoverablePsContext { @@ -774,16 +420,6 @@ public: // Find the pack header which starts with bytes (00 00 01 ba). extern bool srs_skip_util_pack(SrsBuffer *stream); -// Parse the address from SIP string, for example: -// sip:bob@ossrs.io:5060 -// -// Bob -// Parsed as: -// user: bob -// host: ossrs.io:5060 -// Note that the host can be parsed by srs_net_split_hostport as host(ossrs.io) and port(5060). -extern void srs_sip_parse_address(const std::string &address, std::string &user, std::string &host); - // Manager for GB connections. extern SrsResourceManager *_srs_gb_manager; diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index a76ba6b5e..b2c448982 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 74 +#define VERSION_REVISION 75 #endif \ No newline at end of file diff --git a/trunk/src/protocol/srs_protocol_http_stack.cpp b/trunk/src/protocol/srs_protocol_http_stack.cpp index 1586d9073..1745d77ae 100644 --- a/trunk/src/protocol/srs_protocol_http_stack.cpp +++ b/trunk/src/protocol/srs_protocol_http_stack.cpp @@ -1979,12 +1979,6 @@ enum state { s_dead = 1 /* important that this is > 0 */ s_res_HT, s_res_HTT, s_res_HTTP, - s_res_S /* SIP https://www.ietf.org/rfc/rfc3261.html */ - , - s_res_SI /* SIP https://www.ietf.org/rfc/rfc3261.html */ - , - s_res_SIP /* SIP https://www.ietf.org/rfc/rfc3261.html */ - , s_res_http_major, s_res_http_dot, s_res_http_minor, @@ -2019,12 +2013,6 @@ enum state { s_dead = 1 /* important that this is > 0 */ s_req_http_HTTP, s_req_http_I, s_req_http_IC, - s_req_http_S /* SIP https://www.ietf.org/rfc/rfc3261.html */ - , - s_req_http_SI /* SIP https://www.ietf.org/rfc/rfc3261.html */ - , - s_req_http_SIP /* SIP https://www.ietf.org/rfc/rfc3261.html */ - , s_req_http_major, s_req_http_dot, s_req_http_minor, @@ -2442,11 +2430,6 @@ size_t http_parser_execute(http_parser *parser, if (ch == 'H') { UPDATE_STATE(s_res_or_resp_H); - CALLBACK_NOTIFY(message_begin); - } else if (ch == 'S') { /* SIP https://www.ietf.org/rfc/rfc3261.html */ - parser->type = HTTP_RESPONSE; - UPDATE_STATE(s_res_S); - CALLBACK_NOTIFY(message_begin); } else { parser->type = HTTP_REQUEST; @@ -2482,8 +2465,6 @@ size_t http_parser_execute(http_parser *parser, if (ch == 'H') { UPDATE_STATE(s_res_H); - } else if (ch == 'S') { /* SIP https://www.ietf.org/rfc/rfc3261.html */ - UPDATE_STATE(s_res_S); } else { SET_ERRNO(HPE_INVALID_CONSTANT); goto error; @@ -2513,24 +2494,6 @@ size_t http_parser_execute(http_parser *parser, UPDATE_STATE(s_res_http_major); break; - /* SIP https://www.ietf.org/rfc/rfc3261.html */ - case s_res_S: - STRICT_CHECK(ch != 'I'); - UPDATE_STATE(s_res_SI); - break; - - /* SIP https://www.ietf.org/rfc/rfc3261.html */ - case s_res_SI: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_res_SIP); - break; - - /* SIP https://www.ietf.org/rfc/rfc3261.html */ - case s_res_SIP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_res_http_major); - break; - case s_res_http_major: if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_VERSION); @@ -2677,9 +2640,6 @@ size_t http_parser_execute(http_parser *parser, case 'H': parser->method = HTTP_HEAD; break; - case 'I': - parser->method = HTTP_INVITE; - break; /* SIP https://www.ietf.org/rfc/rfc3261.html */ case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; @@ -2743,8 +2703,6 @@ size_t http_parser_execute(http_parser *parser, XX(POST, 1, 'A', PATCH) XX(POST, 1, 'R', PROPFIND) XX(PUT, 2, 'R', PURGE) - XX(ACL, 2, 'K', ACK) /* SIP https://www.ietf.org/rfc/rfc3261.html */ - XX(BIND, 1, 'Y', BYE) /* SIP https://www.ietf.org/rfc/rfc3261.html */ XX(CONNECT, 1, 'H', CHECKOUT) XX(CONNECT, 2, 'P', COPY) XX(MKCOL, 1, 'O', MOVE) @@ -2752,11 +2710,9 @@ size_t http_parser_execute(http_parser *parser, XX(MKCOL, 1, '-', MSEARCH) XX(MKCOL, 2, 'A', MKACTIVITY) XX(MKCOL, 3, 'A', MKCALENDAR) - XX(MERGE, 2, 'S', MESSAGE) /* SIP https://www.ietf.org/rfc/rfc3261.html */ XX(SUBSCRIBE, 1, 'E', SEARCH) XX(SUBSCRIBE, 1, 'O', SOURCE) XX(REPORT, 2, 'B', REBIND) - XX(REPORT, 2, 'G', REGISTER) /* SIP https://www.ietf.org/rfc/rfc3261.html */ XX(PROPFIND, 4, 'P', PROPPATCH) XX(LOCK, 1, 'I', LINK) XX(UNLOCK, 2, 'S', UNSUBSCRIBE) @@ -2785,11 +2741,6 @@ size_t http_parser_execute(http_parser *parser, UPDATE_STATE(s_req_server_start); } - /* SIP https://www.ietf.org/rfc/rfc3261.html */ - if (parser->method >= HTTP_REGISTER && parser->method <= HTTP_BYE) { - UPDATE_STATE(s_req_path); - } - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); if (UNLIKELY(CURRENT_STATE() == s_dead)) { SET_ERRNO(HPE_INVALID_URL); @@ -2857,9 +2808,6 @@ size_t http_parser_execute(http_parser *parser, case 'H': UPDATE_STATE(s_req_http_H); break; - case 'S': /* SIP https://www.ietf.org/rfc/rfc3261.html */ - UPDATE_STATE(s_req_http_S); /* SIP https://www.ietf.org/rfc/rfc3261.html */ - break; /* SIP https://www.ietf.org/rfc/rfc3261.html */ case 'I': if (parser->method == HTTP_SOURCE) { UPDATE_STATE(s_req_http_I); @@ -2902,24 +2850,6 @@ size_t http_parser_execute(http_parser *parser, UPDATE_STATE(s_req_http_major); break; - /* SIP https://www.ietf.org/rfc/rfc3261.html */ - case s_req_http_S: - STRICT_CHECK(ch != 'I'); - UPDATE_STATE(s_req_http_SI); - break; - - /* SIP https://www.ietf.org/rfc/rfc3261.html */ - case s_req_http_SI: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_req_http_SIP); - break; - - /* SIP https://www.ietf.org/rfc/rfc3261.html */ - case s_req_http_SIP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_req_http_major); - break; - case s_req_http_major: if (UNLIKELY(!IS_NUM(ch))) { SET_ERRNO(HPE_INVALID_VERSION); diff --git a/trunk/src/protocol/srs_protocol_http_stack.hpp b/trunk/src/protocol/srs_protocol_http_stack.hpp index 9327f67f0..a12ada741 100644 --- a/trunk/src/protocol/srs_protocol_http_stack.hpp +++ b/trunk/src/protocol/srs_protocol_http_stack.hpp @@ -905,13 +905,7 @@ enum http_status { XX(31, LINK, LINK) \ XX(32, UNLINK, UNLINK) \ /* icecast */ \ - XX(33, SOURCE, SOURCE) \ - /* SIP https://www.ietf.org/rfc/rfc3261.html */ \ - XX(34, REGISTER, REGISTER) \ - XX(35, INVITE, INVITE) \ - XX(36, ACK, ACK) \ - XX(37, MESSAGE, MESSAGE) \ - XX(38, BYE, BYE) + XX(33, SOURCE, SOURCE) enum http_method { #define XX(num, name, string) HTTP_##name = num, diff --git a/trunk/src/utest/srs_utest_gb28181.cpp b/trunk/src/utest/srs_utest_gb28181.cpp index 09ec4c193..ac0eaf5f8 100644 --- a/trunk/src/utest/srs_utest_gb28181.cpp +++ b/trunk/src/utest/srs_utest_gb28181.cpp @@ -22,1335 +22,6 @@ using namespace std; #include #include -extern void srs_sip_parse_address(const std::string &address, std::string &user, std::string &host); - -VOID TEST(ProtocolGbSipTest, SipParseAddress) -{ - if (true) { - string user, host; - srs_sip_parse_address("", user, host); - EXPECT_STREQ("", user.c_str()); - EXPECT_STREQ("", host.c_str()); - } - - if (true) { - string user, host; - srs_sip_parse_address("sip:", user, host); - EXPECT_STREQ("", user.c_str()); - EXPECT_STREQ("", host.c_str()); - } - - if (true) { - string user, host; - srs_sip_parse_address("sip:bob", user, host); - EXPECT_STREQ("bob", user.c_str()); - EXPECT_STREQ("", host.c_str()); - } - - if (true) { - string user, host; - srs_sip_parse_address("sip:bob@", user, host); - EXPECT_STREQ("bob", user.c_str()); - EXPECT_STREQ("", host.c_str()); - } - - if (true) { - string user, host; - srs_sip_parse_address("sip:bob@host.com", user, host); - EXPECT_STREQ("bob", user.c_str()); - EXPECT_STREQ("host.com", host.c_str()); - } - - if (true) { - string user, host; - srs_sip_parse_address("Bob ", user, host); - EXPECT_STREQ("bob", user.c_str()); - EXPECT_STREQ("host.com", host.c_str()); - } - - if (true) { - string user, host; - srs_sip_parse_address("Bob ", user, host); - EXPECT_STREQ("bob", user.c_str()); - EXPECT_STREQ("host.com", host.c_str()); - } -} - -VOID TEST(ProtocolGbSipTest, SipViaBranchMagic) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back("REGISTER sip:registrar.biloxi.com SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP bobspc.biloxi.com:5060;branch=xxxx\r\n"); - r.in_bytes.push_back("To: Bob \r\n"); - r.in_bytes.push_back("From: Bob ;tag=456248\r\n"); - r.in_bytes.push_back("Call-ID: 843817637684230@998sdasdh09\r\n"); - r.in_bytes.push_back("CSeq: 1826 REGISTER\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_FAILED(smsg.parse(msg)); -} - -VOID TEST(ProtocolGbSipTest, SipRegisterRequest) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.1 - MockMSegmentsReader source; - source.in_bytes.push_back("REGISTER sip:registrar.biloxi.com SIP/2.0\r\n"); - source.in_bytes.push_back("Via: SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7\r\n"); - source.in_bytes.push_back("Max-Forwards: 70\r\n"); - source.in_bytes.push_back("To: Bob \r\n"); - source.in_bytes.push_back("From: Bob ;tag=456248\r\n"); - source.in_bytes.push_back("Call-ID: 843817637684230@998sdasdh09\r\n"); - source.in_bytes.push_back("CSeq: 1826 REGISTER\r\n"); - source.in_bytes.push_back("Contact: \r\n"); - source.in_bytes.push_back("Expires: 7200\r\n"); - source.in_bytes.push_back("Content-Length: 0\r\n"); - source.in_bytes.push_back("\r\n"); - - if (true) { - MockMSegmentsReader r = source; - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_REQUEST)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_REGISTER, msg->method()); - EXPECT_STREQ("/sip:registrar.biloxi.com", msg->path().c_str()); - EXPECT_STREQ("SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7", msg->header()->get("Via").c_str()); - EXPECT_STREQ("70", msg->header()->get("Max-Forwards").c_str()); - EXPECT_STREQ("Bob ", msg->header()->get("To").c_str()); - EXPECT_STREQ("Bob ;tag=456248", msg->header()->get("From").c_str()); - EXPECT_STREQ("843817637684230@998sdasdh09", msg->header()->get("Call-ID").c_str()); - EXPECT_STREQ("1826 REGISTER", msg->header()->get("CSeq").c_str()); - EXPECT_STREQ("", msg->header()->get("Contact").c_str()); - EXPECT_STREQ("7200", msg->header()->get("Expires").c_str()); - EXPECT_EQ(0, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_REGISTER, smsg.method_); - EXPECT_STREQ("sip:registrar.biloxi.com", smsg.request_uri_.c_str()); - EXPECT_STREQ("SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("bobspc.biloxi.com:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("bobspc.biloxi.com", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bKnashds7", smsg.via_branch_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_address_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("Bob ;tag=456248", smsg.from_.c_str()); - EXPECT_STREQ("Bob ", smsg.from_address_.c_str()); - EXPECT_STREQ("tag=456248", smsg.from_tag_.c_str()); - EXPECT_STREQ("843817637684230@998sdasdh09", smsg.call_id_.c_str()); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("bob", smsg.contact_user_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.contact_host_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_STREQ("1826 REGISTER", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)1826, smsg.cseq_number_); - EXPECT_EQ((uint32_t)7200, smsg.expires_); - EXPECT_EQ((uint32_t)70, smsg.max_forwards_); - } - - // Parse in HTTP_REQUEST mode. - if (true) { - MockMSegmentsReader r = source; - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_REQUEST)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_REQUEST, (http_parser_type)msg->message_type()); - EXPECT_EQ(HTTP_REGISTER, msg->method()); - EXPECT_STREQ("/sip:registrar.biloxi.com", msg->path().c_str()); - } - - // Parse in HTTP_BOTH mode. - if (true) { - MockMSegmentsReader r = source; - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_REQUEST, (http_parser_type)msg->message_type()); - EXPECT_EQ(HTTP_REGISTER, msg->method()); - EXPECT_STREQ("/sip:registrar.biloxi.com", msg->path().c_str()); - } -} - -VOID TEST(ProtocolGbSipTest, SipRegisterResponse) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.1 - MockMSegmentsReader source; - source.in_bytes.push_back("SIP/2.0 200 OK\r\n"); - source.in_bytes.push_back("Via: SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7;received=192.0.2.4\r\n"); - source.in_bytes.push_back("To: Bob ;tag=2493k59kd\r\n"); - source.in_bytes.push_back("From: Bob ;tag=456248\r\n"); - source.in_bytes.push_back("Call-ID: 843817637684230@998sdasdh09\r\n"); - source.in_bytes.push_back("CSeq: 1826 REGISTER\r\n"); - source.in_bytes.push_back("Contact: \r\n"); - source.in_bytes.push_back("Expires: 7200\r\n"); - source.in_bytes.push_back("Content-Length: 0\r\n"); - source.in_bytes.push_back("\r\n"); - - if (true) { - MockMSegmentsReader r = source; - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_RESPONSE)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_RESPONSE, (http_parser_type)msg->message_type()); - EXPECT_EQ(200, msg->status_code()); - EXPECT_STREQ("SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7;received=192.0.2.4", - msg->header()->get("Via").c_str()); - EXPECT_STREQ("Bob ;tag=2493k59kd", msg->header()->get("To").c_str()); - EXPECT_STREQ("Bob ;tag=456248", msg->header()->get("From").c_str()); - EXPECT_STREQ("843817637684230@998sdasdh09", msg->header()->get("Call-ID").c_str()); - EXPECT_STREQ("1826 REGISTER", msg->header()->get("CSeq").c_str()); - EXPECT_STREQ("", msg->header()->get("Contact").c_str()); - EXPECT_STREQ("7200", msg->header()->get("Expires").c_str()); - EXPECT_EQ(0, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(HTTP_STATUS_OK, smsg.status_); - EXPECT_STREQ("SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7;received=192.0.2.4", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("bobspc.biloxi.com:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("bobspc.biloxi.com", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bKnashds7", smsg.via_branch_.c_str()); - EXPECT_STREQ("Bob ;tag=2493k59kd", smsg.to_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_address_.c_str()); - EXPECT_STREQ("tag=2493k59kd", smsg.to_tag_.c_str()); - EXPECT_STREQ("Bob ;tag=456248", smsg.from_.c_str()); - EXPECT_STREQ("Bob ", smsg.from_address_.c_str()); - EXPECT_STREQ("tag=456248", smsg.from_tag_.c_str()); - EXPECT_STREQ("843817637684230@998sdasdh09", smsg.call_id_.c_str()); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("bob", smsg.contact_user_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.contact_host_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_STREQ("1826 REGISTER", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)1826, smsg.cseq_number_); - } - - // Parse in HTTP_RESPONSE mode. - if (true) { - MockMSegmentsReader r = source; - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_RESPONSE)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_RESPONSE, (http_parser_type)msg->message_type()); - EXPECT_EQ(200, msg->status_code()); - } - - // Parse in HTTP_BOTH mode. - if (true) { - MockMSegmentsReader r = source; - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_RESPONSE, (http_parser_type)msg->message_type()); - EXPECT_EQ(200, msg->status_code()); - } -} - -VOID TEST(ProtocolGbSipTest, SipSessionUacInviteRequest) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back("INVITE sip:bob@biloxi.com SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\r\n"); - r.in_bytes.push_back("Max-Forwards: 70\r\n"); - r.in_bytes.push_back("To: Bob \r\n"); - r.in_bytes.push_back("From: Alice ;tag=1928301774\r\n"); - r.in_bytes.push_back("Call-ID: a84b4c76e66710\r\n"); - r.in_bytes.push_back("CSeq: 314159 INVITE\r\n"); - r.in_bytes.push_back("Contact: \r\n"); - r.in_bytes.push_back("Content-Type: application/sdp\r\n"); - r.in_bytes.push_back("Content-Length: 142\r\n"); - r.in_bytes.push_back("\r\n"); - r.in_bytes.push_back(string(142, 'x')); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_INVITE, msg->method()); - EXPECT_STREQ("/sip:bob@biloxi.com", msg->path().c_str()); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8", msg->header()->get("Via").c_str()); - EXPECT_STREQ("70", msg->header()->get("Max-Forwards").c_str()); - EXPECT_STREQ("Bob ", msg->header()->get("To").c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", msg->header()->get("From").c_str()); - EXPECT_STREQ("a84b4c76e66710", msg->header()->get("Call-ID").c_str()); - EXPECT_STREQ("314159 INVITE", msg->header()->get("CSeq").c_str()); - EXPECT_STREQ("", msg->header()->get("Contact").c_str()); - EXPECT_EQ(142, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_INVITE, smsg.method_); - EXPECT_STREQ("sip:bob@biloxi.com", smsg.request_uri_.c_str()); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bKnashds8", smsg.via_branch_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_address_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", smsg.from_.c_str()); - EXPECT_STREQ("Alice ", smsg.from_address_.c_str()); - EXPECT_STREQ("tag=1928301774", smsg.from_tag_.c_str()); - EXPECT_STREQ("a84b4c76e66710", smsg.call_id_.c_str()); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("alice", smsg.contact_user_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.contact_host_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_STREQ("314159 INVITE", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)314159, smsg.cseq_number_); - EXPECT_EQ((uint32_t)70, smsg.max_forwards_); - EXPECT_EQ((size_t)142, smsg.body_.length()); -} - -VOID TEST(ProtocolGbSipTest, SipSessionUasTryingResponse) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back("SIP/2.0 100 Trying\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1\r\n"); - r.in_bytes.push_back("To: Bob \r\n"); - r.in_bytes.push_back("From: Alice ;tag=1928301774\r\n"); - r.in_bytes.push_back("Call-ID: a84b4c76e66710\r\n"); - r.in_bytes.push_back("CSeq: 314159 INVITE\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_RESPONSE)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_RESPONSE, (http_parser_type)msg->message_type()); - EXPECT_EQ(100, msg->status_code()); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1", msg->header()->get("Via").c_str()); - EXPECT_STREQ("Bob ", msg->header()->get("To").c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", msg->header()->get("From").c_str()); - EXPECT_STREQ("a84b4c76e66710", msg->header()->get("Call-ID").c_str()); - EXPECT_STREQ("314159 INVITE", msg->header()->get("CSeq").c_str()); - EXPECT_EQ(0, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(100, smsg.status_); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bKnashds8", smsg.via_branch_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_address_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", smsg.from_.c_str()); - EXPECT_STREQ("Alice ", smsg.from_address_.c_str()); - EXPECT_STREQ("tag=1928301774", smsg.from_tag_.c_str()); - EXPECT_STREQ("a84b4c76e66710", smsg.call_id_.c_str()); - EXPECT_STREQ("314159 INVITE", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)314159, smsg.cseq_number_); -} - -VOID TEST(ProtocolGbSipTest, SipSessionUas200OkResponse) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back("SIP/2.0 200 OK\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP server10.biloxi.com;branch=z9hG4bK4b43c2ff8.1;received=192.0.2.3\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1\r\n"); - r.in_bytes.push_back("To: Bob ;tag=a6c85cf\r\n"); - r.in_bytes.push_back("From: Alice ;tag=1928301774\r\n"); - r.in_bytes.push_back("Call-ID: a84b4c76e66710\r\n"); - r.in_bytes.push_back("CSeq: 314159 INVITE\r\n"); - r.in_bytes.push_back("Contact: \r\n"); - r.in_bytes.push_back("Content-Type: application/sdp\r\n"); - r.in_bytes.push_back("Content-Length: 131\r\n"); - r.in_bytes.push_back("\r\n"); - r.in_bytes.push_back(string(131, 'x')); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_RESPONSE)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_RESPONSE, (http_parser_type)msg->message_type()); - EXPECT_EQ(200, msg->status_code()); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1", msg->header()->get("Via").c_str()); - EXPECT_STREQ("Bob ;tag=a6c85cf", msg->header()->get("To").c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", msg->header()->get("From").c_str()); - EXPECT_STREQ("", msg->header()->get("Contact").c_str()); - EXPECT_STREQ("a84b4c76e66710", msg->header()->get("Call-ID").c_str()); - EXPECT_STREQ("314159 INVITE", msg->header()->get("CSeq").c_str()); - EXPECT_EQ(131, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(200, smsg.status_); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bKnashds8", smsg.via_branch_.c_str()); - EXPECT_STREQ("Bob ;tag=a6c85cf", smsg.to_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_address_.c_str()); - EXPECT_STREQ("tag=a6c85cf", smsg.to_tag_.c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", smsg.from_.c_str()); - EXPECT_STREQ("Alice ", smsg.from_address_.c_str()); - EXPECT_STREQ("tag=1928301774", smsg.from_tag_.c_str()); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("bob", smsg.contact_user_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.contact_host_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_STREQ("a84b4c76e66710", smsg.call_id_.c_str()); - EXPECT_STREQ("314159 INVITE", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)314159, smsg.cseq_number_); - EXPECT_EQ((size_t)131, smsg.body_.length()); -} - -VOID TEST(ProtocolGbSipTest, SipSessionUacAckRequest) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back("ACK sip:bob@192.0.2.4 SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds9\r\n"); - r.in_bytes.push_back("Max-Forwards: 70\r\n"); - r.in_bytes.push_back("To: Bob ;tag=a6c85cf\r\n"); - r.in_bytes.push_back("From: Alice ;tag=1928301774\r\n"); - r.in_bytes.push_back("Call-ID: a84b4c76e66710\r\n"); - r.in_bytes.push_back("CSeq: 314159 ACK\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_ACK, msg->method()); - EXPECT_STREQ("/sip:bob@192.0.2.4", msg->path().c_str()); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds9", msg->header()->get("Via").c_str()); - EXPECT_STREQ("70", msg->header()->get("Max-Forwards").c_str()); - EXPECT_STREQ("Bob ;tag=a6c85cf", msg->header()->get("To").c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", msg->header()->get("From").c_str()); - EXPECT_STREQ("a84b4c76e66710", msg->header()->get("Call-ID").c_str()); - EXPECT_STREQ("314159 ACK", msg->header()->get("CSeq").c_str()); - EXPECT_EQ(0, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_ACK, smsg.method_); - EXPECT_STREQ("sip:bob@192.0.2.4", smsg.request_uri_.c_str()); - EXPECT_STREQ("SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds9", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_.c_str()); - EXPECT_STREQ("pc33.atlanta.com", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bKnashds9", smsg.via_branch_.c_str()); - EXPECT_STREQ("Bob ;tag=a6c85cf", smsg.to_.c_str()); - EXPECT_STREQ("Bob ", smsg.to_address_.c_str()); - EXPECT_STREQ("tag=a6c85cf", smsg.to_tag_.c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", smsg.from_.c_str()); - EXPECT_STREQ("Alice ", smsg.from_address_.c_str()); - EXPECT_STREQ("tag=1928301774", smsg.from_tag_.c_str()); - EXPECT_STREQ("a84b4c76e66710", smsg.call_id_.c_str()); - EXPECT_STREQ("314159 ACK", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)314159, smsg.cseq_number_); - EXPECT_EQ((uint32_t)70, smsg.max_forwards_); -} - -VOID TEST(ProtocolGbSipTest, SipSessionUacByeRequest) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back("BYE sip:alice@pc33.atlanta.com SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10\r\n"); - r.in_bytes.push_back("Max-Forwards: 70\r\n"); - r.in_bytes.push_back("From: Bob ;tag=a6c85cf\r\n"); - r.in_bytes.push_back("To: Alice ;tag=1928301774\r\n"); - r.in_bytes.push_back("Call-ID: a84b4c76e66710\r\n"); - r.in_bytes.push_back("CSeq: 231 BYE\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_BYE, msg->method()); - EXPECT_STREQ("/sip:alice@pc33.atlanta.com", msg->path().c_str()); - EXPECT_STREQ("SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10", msg->header()->get("Via").c_str()); - EXPECT_STREQ("70", msg->header()->get("Max-Forwards").c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", msg->header()->get("To").c_str()); - EXPECT_STREQ("Bob ;tag=a6c85cf", msg->header()->get("From").c_str()); - EXPECT_STREQ("a84b4c76e66710", msg->header()->get("Call-ID").c_str()); - EXPECT_STREQ("231 BYE", msg->header()->get("CSeq").c_str()); - EXPECT_EQ(0, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_BYE, smsg.method_); - EXPECT_STREQ("sip:alice@pc33.atlanta.com", smsg.request_uri_.c_str()); - EXPECT_STREQ("SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.via_send_by_.c_str()); - EXPECT_STREQ("192.0.2.4", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bKnashds10", smsg.via_branch_.c_str()); - EXPECT_STREQ("Alice ;tag=1928301774", smsg.to_.c_str()); - EXPECT_STREQ("Alice ", smsg.to_address_.c_str()); - EXPECT_STREQ("tag=1928301774", smsg.to_tag_.c_str()); - EXPECT_STREQ("Bob ;tag=a6c85cf", smsg.from_.c_str()); - EXPECT_STREQ("Bob ", smsg.from_address_.c_str()); - EXPECT_STREQ("tag=a6c85cf", smsg.from_tag_.c_str()); - EXPECT_STREQ("a84b4c76e66710", smsg.call_id_.c_str()); - EXPECT_STREQ("231 BYE", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)231, smsg.cseq_number_); - EXPECT_EQ((uint32_t)70, smsg.max_forwards_); -} - -VOID TEST(ProtocolGbSipTest, SipRegisterExpires) -{ - srs_error_t err = srs_success; - - if (true) { - MockMSegmentsReader r; - r.in_bytes.push_back("REGISTER sip:registrar.biloxi.com SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7\r\n"); - r.in_bytes.push_back("To: Bob \r\n"); - r.in_bytes.push_back("From: Bob ;tag=456248\r\n"); - r.in_bytes.push_back("Call-ID: 843817637684230@998sdasdh09\r\n"); - r.in_bytes.push_back("CSeq: 1826 REGISTER\r\n"); - r.in_bytes.push_back("Expires: 7200\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_REQUEST)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_REGISTER, smsg.method_); - EXPECT_EQ((uint32_t)7200, smsg.expires_); - } - - if (true) { - MockMSegmentsReader r; - r.in_bytes.push_back("REGISTER sip:registrar.biloxi.com SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7\r\n"); - r.in_bytes.push_back("To: Bob \r\n"); - r.in_bytes.push_back("From: Bob ;tag=456248\r\n"); - r.in_bytes.push_back("Call-ID: 843817637684230@998sdasdh09\r\n"); - r.in_bytes.push_back("CSeq: 1826 REGISTER\r\n"); - r.in_bytes.push_back("Expires: 0\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_REQUEST)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_REGISTER, smsg.method_); - EXPECT_EQ((uint32_t)0, smsg.expires_); - } -} - -VOID TEST(ProtocolGbSipTest, SipSmallMessagesInOneBuffer) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back( - "SIP/2.0 100 Trying\r\n" - "Via: SIP/2.0/TCP 192.168.3.85:5060;rport=5060;branch=z9hG4bK95108j;received=127.0.0.1\r\n" - "From: ;tag=SRS6600q9p4\r\n" - "To: \r\n" - "Call-ID: x220zl3805088272\r\n" - "CSeq: 831 INVITE\r\n" - "Content-Length: 0\r\n" - "\r\n" - "SIP/2.0 200 OK\r\n" - "Via: SIP/2.0/TCP 192.168.3.85:5060;rport=5060;branch=z9hG4bK95108j;received=127.0.0.1\r\n" - "From: ;tag=SRS6600q9p4\r\n" - "To: \r\n" - "Call-ID: x220zl3805088272\r\n" - "CSeq: 831 INVITE\r\n" - "Content-Length: 0\r\n" - "\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - if (true) { - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(100, smsg.status_); - } - - if (true) { - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(200, smsg.status_); - } -} - -VOID TEST(ProtocolGbSipTest, SipSmallMessagesWithBody) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.2 - MockMSegmentsReader r; - r.in_bytes.push_back( - "SIP/2.0 100 Trying\r\n" - "Via: SIP/2.0/TCP 192.168.3.85:5060;rport=5060;branch=z9hG4bK95108j;received=127.0.0.1\r\n" - "From: ;tag=SRS6600q9p4\r\n" - "To: \r\n" - "Call-ID: x220zl3805088272\r\n" - "CSeq: 831 INVITE\r\n" - "Content-Length: 10\r\n" - "\r\n" - "HelloWorld" - "SIP/2.0 200 OK\r\n" - "Via: SIP/2.0/TCP 192.168.3.85:5060;rport=5060;branch=z9hG4bK95108j;received=127.0.0.1\r\n" - "From: ;tag=SRS6600q9p4\r\n" - "To: \r\n" - "Call-ID: x220zl3805088272\r\n" - "CSeq: 831 INVITE\r\n" - "Content-Length: 11\r\n" - "\r\n" - "HelloServer"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - if (true) { - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(100, smsg.status_); - EXPECT_STREQ("HelloWorld", smsg.body_.c_str()); - } - - if (true) { - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(200, smsg.status_); - EXPECT_STREQ("HelloServer", smsg.body_.c_str()); - } -} - -VOID TEST(ProtocolGbSipTest, SipStandardOfferDecode) -{ - srs_error_t err = srs_success; - - string str = - "v=0\r\n" - "o=64010600002020000001 0 0 IN IP4 172.20.16.3\r\n" - "s=Play\r\n" - "c=IN IP4 172.20.16.3\r\n" - "t=0 0\r\n" - "m=video 6000 RTP/AVP 96 98 97\r\n" - "a=recvonly\r\n" - "a=rtpmap:96 PS/90000\r\n" - "a=rtpmap:98 H264/90000\r\n" - "a=rtpmap:97 MPEG4/90000\r\n"; - SrsSdp o; - HELPER_ASSERT_SUCCESS(o.parse(str)); - EXPECT_STREQ("0", o.version_.c_str()); - EXPECT_STREQ("64010600002020000001", o.username_.c_str()); - EXPECT_STREQ("0", o.session_id_.c_str()); - EXPECT_STREQ("0", o.session_version_.c_str()); - EXPECT_STREQ("IN", o.nettype_.c_str()); - EXPECT_STREQ("IP4", o.addrtype_.c_str()); - EXPECT_STREQ("172.20.16.3", o.unicast_address_.c_str()); - EXPECT_STREQ("Play", o.session_name_.c_str()); - EXPECT_EQ(0, o.start_time_); - EXPECT_EQ(0, o.end_time_); - - ASSERT_EQ((size_t)1, o.media_descs_.size()); - const SrsMediaDesc &m = o.media_descs_.at(0); - EXPECT_STREQ("video", m.type_.c_str()); - EXPECT_EQ(6000, m.port_); - EXPECT_STREQ("RTP/AVP", m.protos_.c_str()); - EXPECT_EQ((size_t)3, m.payload_types_.size()); - - const SrsMediaPayloadType &ps = m.payload_types_.at(0); - EXPECT_EQ(96, ps.payload_type_); - EXPECT_STREQ("PS", ps.encoding_name_.c_str()); - EXPECT_EQ(90000, ps.clock_rate_); - - const SrsMediaPayloadType &h264 = m.payload_types_.at(1); - EXPECT_EQ(98, h264.payload_type_); - EXPECT_STREQ("H264", h264.encoding_name_.c_str()); - EXPECT_EQ(90000, h264.clock_rate_); - - const SrsMediaPayloadType &mpeg4 = m.payload_types_.at(2); - EXPECT_EQ(97, mpeg4.payload_type_); - EXPECT_STREQ("MPEG4", mpeg4.encoding_name_.c_str()); - EXPECT_EQ(90000, mpeg4.clock_rate_); -} - -VOID TEST(ProtocolGbSipTest, SipStandardOfferEncode) -{ - srs_error_t err = srs_success; - - SrsSdp o; - o.version_ = "0"; - o.username_ = "64010600002020000001"; - o.session_id_ = "0"; - o.session_version_ = "0"; - o.nettype_ = "IN"; - o.addrtype_ = "IP4"; - o.unicast_address_ = "172.20.16.3"; - o.session_name_ = "Play"; - o.start_time_ = 0; - o.end_time_ = 0; - o.ice_lite_ = ""; // Disable this line. - o.connection_ = "c=IN IP4 172.20.16.3"; // Session level connection. - - o.media_descs_.push_back(SrsMediaDesc("video")); - SrsMediaDesc &m = o.media_descs_.at(0); - m.port_ = 6000; - m.protos_ = "RTP/AVP"; - m.connection_ = ""; // Disable media level connection. - m.recvonly_ = true; - - m.payload_types_.push_back(SrsMediaPayloadType(96)); - SrsMediaPayloadType &ps = m.payload_types_.at(0); - ps.encoding_name_ = "PS"; - ps.clock_rate_ = 90000; - - m.payload_types_.push_back(SrsMediaPayloadType(98)); - SrsMediaPayloadType &h264 = m.payload_types_.at(1); - h264.encoding_name_ = "H264"; - h264.clock_rate_ = 90000; - - m.payload_types_.push_back(SrsMediaPayloadType(97)); - SrsMediaPayloadType &mpeg4 = m.payload_types_.at(2); - mpeg4.encoding_name_ = "MPEG4"; - mpeg4.clock_rate_ = 90000; - - ostringstream os; - HELPER_ASSERT_SUCCESS(o.encode(os)); - string ostr = os.str(); - string str = - "v=0\r\n" - "o=64010600002020000001 0 0 IN IP4 172.20.16.3\r\n" - "s=Play\r\n" - "c=IN IP4 172.20.16.3\r\n" - "t=0 0\r\n" - "m=video 6000 RTP/AVP 96 98 97\r\n" - "a=recvonly\r\n" - "a=rtpmap:96 PS/90000\r\n" - "a=rtpmap:98 H264/90000\r\n" - "a=rtpmap:97 MPEG4/90000\r\n"; - EXPECT_STREQ(ostr.c_str(), str.c_str()); -} - -VOID TEST(ProtocolGbSipTest, SipGb28181OfferDecode) -{ - srs_error_t err = srs_success; - - string str = - "v=0\r\n" - "o=64010600002020000001 0 0 IN IP4 172.20.16.3\r\n" - "s=Play\r\n" - "c=IN IP4 172.20.16.3\r\n" - "t=0 0\r\n" - "m=video 6000 RTP/AVP 96 98 97\r\n" - "a=recvonly\r\n" - "a=rtpmap:96 PS/90000\r\n" - "a=rtpmap:98 H264/90000\r\n" - "a=rtpmap:97 MPEG4/90000\r\n" - "y=0100008888\r\n"; - SrsSdp o; - HELPER_ASSERT_SUCCESS(o.parse(str)); - EXPECT_STREQ("0", o.version_.c_str()); - EXPECT_STREQ("64010600002020000001", o.username_.c_str()); - EXPECT_STREQ("0", o.session_id_.c_str()); - EXPECT_STREQ("0", o.session_version_.c_str()); - EXPECT_STREQ("IN", o.nettype_.c_str()); - EXPECT_STREQ("IP4", o.addrtype_.c_str()); - EXPECT_STREQ("172.20.16.3", o.unicast_address_.c_str()); - EXPECT_STREQ("Play", o.session_name_.c_str()); - EXPECT_EQ(0, o.start_time_); - EXPECT_EQ(0, o.end_time_); - - ASSERT_EQ((size_t)1, o.media_descs_.size()); - const SrsMediaDesc &m = o.media_descs_.at(0); - EXPECT_STREQ("video", m.type_.c_str()); - EXPECT_EQ(6000, m.port_); - EXPECT_STREQ("RTP/AVP", m.protos_.c_str()); - EXPECT_EQ((size_t)3, m.payload_types_.size()); - ASSERT_EQ((size_t)1, m.ssrc_infos_.size()); - - const SrsSSRCInfo &ssrc = m.ssrc_infos_.at(0); - EXPECT_EQ((uint32_t)100008888, ssrc.ssrc_); - EXPECT_STREQ("0100008888", ssrc.cname_.c_str()); - EXPECT_STREQ("gb28181", ssrc.label_.c_str()); - - const SrsMediaPayloadType &ps = m.payload_types_.at(0); - EXPECT_EQ(96, ps.payload_type_); - EXPECT_STREQ("PS", ps.encoding_name_.c_str()); - EXPECT_EQ(90000, ps.clock_rate_); - - const SrsMediaPayloadType &h264 = m.payload_types_.at(1); - EXPECT_EQ(98, h264.payload_type_); - EXPECT_STREQ("H264", h264.encoding_name_.c_str()); - EXPECT_EQ(90000, h264.clock_rate_); - - const SrsMediaPayloadType &mpeg4 = m.payload_types_.at(2); - EXPECT_EQ(97, mpeg4.payload_type_); - EXPECT_STREQ("MPEG4", mpeg4.encoding_name_.c_str()); - EXPECT_EQ(90000, mpeg4.clock_rate_); -} - -VOID TEST(ProtocolGbSipTest, SipGb28181OfferEncode) -{ - srs_error_t err = srs_success; - - SrsSdp o; - o.version_ = "0"; - o.username_ = "64010600002020000001"; - o.session_id_ = "0"; - o.session_version_ = "0"; - o.nettype_ = "IN"; - o.addrtype_ = "IP4"; - o.unicast_address_ = "172.20.16.3"; - o.session_name_ = "Play"; - o.start_time_ = 0; - o.end_time_ = 0; - o.ice_lite_ = ""; // Disable this line. - o.connection_ = "c=IN IP4 172.20.16.3"; // Session level connection. - - o.media_descs_.push_back(SrsMediaDesc("video")); - SrsMediaDesc &m = o.media_descs_.at(0); - m.port_ = 6000; - m.protos_ = "RTP/AVP"; - m.connection_ = ""; // Disable media level connection. - m.recvonly_ = true; - - m.payload_types_.push_back(SrsMediaPayloadType(96)); - SrsMediaPayloadType &ps = m.payload_types_.at(0); - ps.encoding_name_ = "PS"; - ps.clock_rate_ = 90000; - - m.payload_types_.push_back(SrsMediaPayloadType(98)); - SrsMediaPayloadType &h264 = m.payload_types_.at(1); - h264.encoding_name_ = "H264"; - h264.clock_rate_ = 90000; - - m.payload_types_.push_back(SrsMediaPayloadType(97)); - SrsMediaPayloadType &mpeg4 = m.payload_types_.at(2); - mpeg4.encoding_name_ = "MPEG4"; - mpeg4.clock_rate_ = 90000; - - m.ssrc_infos_.push_back(SrsSSRCInfo()); - SrsSSRCInfo &ssrc = m.ssrc_infos_.at(0); - ssrc.ssrc_ = 100008888; - ssrc.cname_ = "0100008888"; - ssrc.label_ = "gb28181"; - - ostringstream os; - HELPER_ASSERT_SUCCESS(o.encode(os)); - string ostr = os.str(); - string str = - "v=0\r\n" - "o=64010600002020000001 0 0 IN IP4 172.20.16.3\r\n" - "s=Play\r\n" - "c=IN IP4 172.20.16.3\r\n" - "t=0 0\r\n" - "m=video 6000 RTP/AVP 96 98 97\r\n" - "a=recvonly\r\n" - "a=rtpmap:96 PS/90000\r\n" - "a=rtpmap:98 H264/90000\r\n" - "a=rtpmap:97 MPEG4/90000\r\n" - "y=0100008888\r\n"; - EXPECT_STREQ(ostr.c_str(), str.c_str()); -} - -VOID TEST(ProtocolGbSipTest, GbRegisterRequest) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.1 - MockMSegmentsReader r; - r.in_bytes.push_back("REGISTER sip:34020000002000000001@3402000000 SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP 192.168.3.99:5060;rport;branch=z9hG4bK442003727\r\n"); - r.in_bytes.push_back("From: ;tag=307202390\r\n"); - r.in_bytes.push_back("To: \r\n"); - r.in_bytes.push_back("Call-ID: 393945367\r\n"); - r.in_bytes.push_back("CSeq: 1 REGISTER\r\n"); - r.in_bytes.push_back("Contact: \r\n"); - r.in_bytes.push_back("Max-Forwards: 70\r\n"); - r.in_bytes.push_back("User-Agent: IP Camera\r\n"); - r.in_bytes.push_back("Expires: 3600\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_REQUEST)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_REGISTER, msg->method()); - EXPECT_EQ(0, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_REGISTER, smsg.method_); - EXPECT_STREQ("sip:34020000002000000001@3402000000", smsg.request_uri_.c_str()); - EXPECT_STREQ("SIP/2.0/UDP 192.168.3.99:5060;rport;branch=z9hG4bK442003727", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("192.168.3.99:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("192.168.3.99", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bK442003727", smsg.via_branch_.c_str()); - EXPECT_STREQ(";tag=307202390", smsg.from_.c_str()); - EXPECT_STREQ("", smsg.from_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.from_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.from_address_host_.c_str()); - EXPECT_STREQ("tag=307202390", smsg.from_tag_.c_str()); - EXPECT_STREQ("", smsg.to_.c_str()); - EXPECT_STREQ("", smsg.to_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.to_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.to_address_host_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("393945367", smsg.call_id_.c_str()); - EXPECT_STREQ("1 REGISTER", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)1, smsg.cseq_number_); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.contact_user_.c_str()); - EXPECT_STREQ("192.168.3.99:5060", smsg.contact_host_.c_str()); - EXPECT_STREQ("192.168.3.99", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_EQ((uint32_t)70, smsg.max_forwards_); - EXPECT_EQ((uint32_t)3600, smsg.expires_); - - EXPECT_STREQ(smsg.from_address_.c_str(), smsg.to_address_.c_str()); -} - -VOID TEST(ProtocolGbSipTest, GbRegisterResponse) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.1 - MockMSegmentsReader r; - r.in_bytes.push_back("SIP/2.0 200 OK\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/UDP 192.168.3.99:5060;rport;branch=z9hG4bK442003727\r\n"); - r.in_bytes.push_back("From: ;tag=307202390\r\n"); - r.in_bytes.push_back("To: \r\n"); - r.in_bytes.push_back("Call-ID: 393945367\r\n"); - r.in_bytes.push_back("CSeq: 1 REGISTER\r\n"); - r.in_bytes.push_back("Contact: \r\n"); - r.in_bytes.push_back("User-Agent: SRS/5.0.65(Bee)\r\n"); - r.in_bytes.push_back("Expires: 3600\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_RESPONSE)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - EXPECT_EQ(HTTP_RESPONSE, (http_parser_type)msg->message_type()); - EXPECT_EQ(200, msg->status_code()); - EXPECT_EQ(0, msg->content_length()); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(HTTP_STATUS_OK, smsg.status_); - EXPECT_STREQ("SIP/2.0/UDP 192.168.3.99:5060;rport;branch=z9hG4bK442003727", smsg.via_.c_str()); - EXPECT_STREQ("UDP", smsg.via_transport_.c_str()); - EXPECT_STREQ("192.168.3.99:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("192.168.3.99", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bK442003727", smsg.via_branch_.c_str()); - EXPECT_STREQ(";tag=307202390", smsg.from_.c_str()); - EXPECT_STREQ("", smsg.from_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.from_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.from_address_host_.c_str()); - EXPECT_STREQ("tag=307202390", smsg.from_tag_.c_str()); - EXPECT_STREQ("", smsg.to_.c_str()); - EXPECT_STREQ("", smsg.to_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.to_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.to_address_host_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("393945367", smsg.call_id_.c_str()); - EXPECT_STREQ("1 REGISTER", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)1, smsg.cseq_number_); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.contact_user_.c_str()); - EXPECT_STREQ("192.168.3.99:5060", smsg.contact_host_.c_str()); - EXPECT_STREQ("192.168.3.99", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_EQ((uint32_t)3600, smsg.expires_); -} - -VOID TEST(ProtocolGbSipTest, GbInviteRequest) -{ - srs_error_t err = srs_success; - - string sdp = - "v=0\r\n" - "o=34020000001320000001 0 0 IN IP4 192.168.3.82\r\n" - "s=Play\r\n" - "c=IN IP4 192.168.3.82\r\n" - "t=0 0\r\n" - "m=video 9000 TCP/RTP/AVP 96\r\n" - "a=recvonly\r\n" - "a=rtpmap:96 PS/90000\r\n" - "y=0200007585\r\n"; - - MockMSegmentsReader r; - r.in_bytes.push_back("INVITE sip:34020000001320000001@3402000000 SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/TCP 192.168.3.82:5060;rport;branch=z9hG4bK0l31rx\r\n"); - r.in_bytes.push_back("From: ;tag=SRSk1er282t\r\n"); - r.in_bytes.push_back("To: \r\n"); - r.in_bytes.push_back("CSeq: 854 INVITE\r\n"); - r.in_bytes.push_back("Call-ID: 854k7337207yxpfj\r\n"); - r.in_bytes.push_back("Content-Type: application/sdp\r\n"); - r.in_bytes.push_back("Contact: \r\n"); - r.in_bytes.push_back("Max-Forwards: 70\r\n"); - r.in_bytes.push_back("Subject: 34020000001320000001:0200007585,34020000002000000001:0\r\n"); - r.in_bytes.push_back("Server: SRS/5.0.65(Bee)\r\n"); - r.in_bytes.push_back(srs_fmt_sprintf("Content-Length: %d\r\n", sdp.length())); - r.in_bytes.push_back("\r\n"); - r.in_bytes.push_back(sdp); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_INVITE, smsg.method_); - EXPECT_STREQ("sip:34020000001320000001@3402000000", smsg.request_uri_.c_str()); - EXPECT_STREQ("SIP/2.0/TCP 192.168.3.82:5060;rport;branch=z9hG4bK0l31rx", smsg.via_.c_str()); - EXPECT_STREQ("TCP", smsg.via_transport_.c_str()); - EXPECT_STREQ("192.168.3.82:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("192.168.3.82", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bK0l31rx", smsg.via_branch_.c_str()); - EXPECT_STREQ(";tag=SRSk1er282t", smsg.from_.c_str()); - EXPECT_STREQ("", smsg.from_address_.c_str()); - EXPECT_STREQ("34020000002000000001", smsg.from_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.from_address_host_.c_str()); - EXPECT_STREQ("tag=SRSk1er282t", smsg.from_tag_.c_str()); - EXPECT_STREQ("", smsg.to_.c_str()); - EXPECT_STREQ("", smsg.to_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.to_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.to_address_host_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("854 INVITE", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)854, smsg.cseq_number_); - EXPECT_STREQ("854k7337207yxpfj", smsg.call_id_.c_str()); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("34020000002000000001", smsg.contact_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.contact_host_.c_str()); - EXPECT_STREQ("3402000000", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_EQ((uint32_t)70, smsg.max_forwards_); - EXPECT_STREQ("34020000001320000001:0200007585,34020000002000000001:0", smsg.subject_.c_str()); - EXPECT_STREQ(sdp.c_str(), smsg.body_.c_str()); -} - -VOID TEST(ProtocolGbSipTest, GbTringResponse) -{ - srs_error_t err = srs_success; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.1 - MockMSegmentsReader r; - r.in_bytes.push_back("SIP/2.0 100 Trying\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/TCP 192.168.3.82:5060;rport=5060;branch=z9hG4bK0l31rx\r\n"); - r.in_bytes.push_back("From: ;tag=SRSk1er282t\r\n"); - r.in_bytes.push_back("To: \r\n"); - r.in_bytes.push_back("Call-ID: 854k7337207yxpfj\r\n"); - r.in_bytes.push_back("CSeq: 854 INVITE\r\n"); - r.in_bytes.push_back("User-Agent: IP Camera\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_RESPONSE)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(100, smsg.status_); - EXPECT_STREQ("SIP/2.0/TCP 192.168.3.82:5060;rport=5060;branch=z9hG4bK0l31rx", smsg.via_.c_str()); - EXPECT_STREQ("TCP", smsg.via_transport_.c_str()); - EXPECT_STREQ("192.168.3.82:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("192.168.3.82", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bK0l31rx", smsg.via_branch_.c_str()); - EXPECT_STREQ(";tag=SRSk1er282t", smsg.from_.c_str()); - EXPECT_STREQ("", smsg.from_address_.c_str()); - EXPECT_STREQ("34020000002000000001", smsg.from_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.from_address_host_.c_str()); - EXPECT_STREQ("tag=SRSk1er282t", smsg.from_tag_.c_str()); - EXPECT_STREQ("", smsg.to_.c_str()); - EXPECT_STREQ("", smsg.to_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.to_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.to_address_host_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("854 INVITE", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)854, smsg.cseq_number_); - EXPECT_STREQ("854k7337207yxpfj", smsg.call_id_.c_str()); - EXPECT_EQ((size_t)0, smsg.body_.length()); -} - -VOID TEST(ProtocolGbSipTest, Gb200OkResponse) -{ - srs_error_t err = srs_success; - - string sdp = - "v=0\r\n" - "o=34020000001320000001 1941 1941 IN IP4 192.168.3.99\r\n" - "s=Play\r\n" - "c=IN IP4 192.168.3.99\r\n" - "t=0 0\r\n" - "m=video 15060 TCP/RTP/AVP 96\r\n" - "a=setup:active\r\n" - "a=sendonly\r\n" - "a=rtpmap:96 PS/90000\r\n" - "a=filesize:0\r\n" - "y=0200007585\r\n"; - - // See https://www.ietf.org/rfc/rfc3261.html#section-24.1 - MockMSegmentsReader r; - r.in_bytes.push_back("SIP/2.0 200 OK\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/TCP 192.168.3.82:5060;rport=5060;branch=z9hG4bK0l31rx\r\n"); - r.in_bytes.push_back("From: ;tag=SRSk1er282t\r\n"); - r.in_bytes.push_back("To: \r\n"); - r.in_bytes.push_back("Call-ID: 854k7337207yxpfj\r\n"); - r.in_bytes.push_back("CSeq: 854 INVITE\r\n"); - r.in_bytes.push_back("Contact: \r\n"); - r.in_bytes.push_back("Content-Type: application/sdp\r\n"); - r.in_bytes.push_back("User-Agent: IP Camera\r\n"); - r.in_bytes.push_back(srs_fmt_sprintf("Content-Length: %d\r\n", sdp.length())); - r.in_bytes.push_back("\r\n"); - r.in_bytes.push_back(sdp); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_RESPONSE)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_RESPONSE, smsg.type_); - EXPECT_EQ(200, smsg.status_); - EXPECT_STREQ("SIP/2.0/TCP 192.168.3.82:5060;rport=5060;branch=z9hG4bK0l31rx", smsg.via_.c_str()); - EXPECT_STREQ("TCP", smsg.via_transport_.c_str()); - EXPECT_STREQ("192.168.3.82:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("192.168.3.82", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bK0l31rx", smsg.via_branch_.c_str()); - EXPECT_STREQ(";tag=SRSk1er282t", smsg.from_.c_str()); - EXPECT_STREQ("", smsg.from_address_.c_str()); - EXPECT_STREQ("34020000002000000001", smsg.from_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.from_address_host_.c_str()); - EXPECT_STREQ("tag=SRSk1er282t", smsg.from_tag_.c_str()); - EXPECT_STREQ("", smsg.to_.c_str()); - EXPECT_STREQ("", smsg.to_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.to_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.to_address_host_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("854 INVITE", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)854, smsg.cseq_number_); - EXPECT_STREQ("854k7337207yxpfj", smsg.call_id_.c_str()); - EXPECT_STREQ("", smsg.contact_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.contact_user_.c_str()); - EXPECT_STREQ("192.168.3.99:5060", smsg.contact_host_.c_str()); - EXPECT_STREQ("192.168.3.99", smsg.contact_host_address_.c_str()); - EXPECT_EQ(5060, smsg.contact_host_port_); - EXPECT_STREQ(sdp.c_str(), smsg.body_.c_str()); -} - -VOID TEST(ProtocolGbSipTest, GbAckRequest) -{ - srs_error_t err = srs_success; - - MockMSegmentsReader r; - r.in_bytes.push_back("ACK sip:34020000001320000001@3402000000 SIP/2.0\r\n"); - r.in_bytes.push_back("Via: SIP/2.0/TCP 192.168.3.82:5060;rport;branch=z9hG4bK9k30b6\r\n"); - r.in_bytes.push_back("From: ;tag=SRSk1er282t\r\n"); - r.in_bytes.push_back("To: \r\n"); - r.in_bytes.push_back("CSeq: 854 ACK\r\n"); - r.in_bytes.push_back("Call-ID: 854k7337207yxpfj\r\n"); - r.in_bytes.push_back("Max-Forwards: 70\r\n"); - r.in_bytes.push_back("Server: SRS/5.0.65(Bee)\r\n"); - r.in_bytes.push_back("Content-Length: 0\r\n"); - r.in_bytes.push_back("\r\n"); - - SrsHttpParser p; - HELPER_ASSERT_SUCCESS(p.initialize(HTTP_BOTH)); - - ISrsHttpMessage *msg = NULL; - HELPER_ASSERT_SUCCESS(p.parse_message(&r, &msg)); - SrsUniquePtr msg_uptr(msg); - - SrsSipMessage smsg; - HELPER_ASSERT_SUCCESS(smsg.parse(msg)); - EXPECT_EQ(HTTP_REQUEST, smsg.type_); - EXPECT_EQ(HTTP_ACK, smsg.method_); - EXPECT_STREQ("sip:34020000001320000001@3402000000", smsg.request_uri_.c_str()); - EXPECT_STREQ("SIP/2.0/TCP 192.168.3.82:5060;rport;branch=z9hG4bK9k30b6", smsg.via_.c_str()); - EXPECT_STREQ("TCP", smsg.via_transport_.c_str()); - EXPECT_STREQ("192.168.3.82:5060", smsg.via_send_by_.c_str()); - EXPECT_STREQ("192.168.3.82", smsg.via_send_by_address_.c_str()); - EXPECT_EQ(5060, smsg.via_send_by_port_); - EXPECT_STREQ("branch=z9hG4bK9k30b6", smsg.via_branch_.c_str()); - EXPECT_STREQ(";tag=SRSk1er282t", smsg.from_.c_str()); - EXPECT_STREQ("", smsg.from_address_.c_str()); - EXPECT_STREQ("34020000002000000001", smsg.from_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.from_address_host_.c_str()); - EXPECT_STREQ("tag=SRSk1er282t", smsg.from_tag_.c_str()); - EXPECT_STREQ("", smsg.to_.c_str()); - EXPECT_STREQ("", smsg.to_address_.c_str()); - EXPECT_STREQ("34020000001320000001", smsg.to_address_user_.c_str()); - EXPECT_STREQ("3402000000", smsg.to_address_host_.c_str()); - EXPECT_STREQ("", smsg.to_tag_.c_str()); - EXPECT_STREQ("854 ACK", smsg.cseq_.c_str()); - EXPECT_EQ((uint32_t)854, smsg.cseq_number_); - EXPECT_STREQ("854k7337207yxpfj", smsg.call_id_.c_str()); - EXPECT_EQ((uint32_t)70, smsg.max_forwards_); - EXPECT_EQ((size_t)0, smsg.body_.length()); -} - VOID TEST(KernelPSTest, PsPacketDecodePartialPesHeader) { srs_error_t err = srs_success;