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;