diff --git a/server/WebApi.cpp b/server/WebApi.cpp index aea85a6c..bc170cd0 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -1628,18 +1628,21 @@ void installWebApi() { }); }); + static constexpr char delete_webrtc_url [] = "/index/api/delete_webrtc"; static auto whip_whep_func = [](const char *type, API_ARGS_STRING_ASYNC) { auto offer = allArgs.getArgs(); CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty"); - WebRtcPluginManager::Instance().getAnswerSdp(static_cast(sender), type, - WebRtcArgsImp(allArgs, sender.getIdentifier()), - [invoker, offer, headerOut](const WebRtcInterface &exchanger) mutable { + auto &session = static_cast(sender); + auto location = std::string("http") + (session.overSsl() ? "s" : "") + "://" + allArgs["host"] + delete_webrtc_url; + WebRtcPluginManager::Instance().getAnswerSdp(session, type, WebRtcArgsImp(allArgs, sender.getIdentifier()), + [invoker, offer, headerOut, location](const WebRtcInterface &exchanger) mutable { // 设置跨域 headerOut["Access-Control-Allow-Origin"] = "*"; try { // 设置返回类型 headerOut["Content-Type"] = "application/sdp"; + headerOut["Location"] = location + "?id=" + exchanger.getIdentifier() + "&token=" + exchanger.deleteRandStr(); invoker(201, headerOut, exchangeSdp(exchanger, offer)); } catch (std::exception &ex) { headerOut["Content-Type"] = "text/plain"; @@ -1650,6 +1653,22 @@ void installWebApi() { api_regist("/index/api/whip", [](API_ARGS_STRING_ASYNC) { whip_whep_func("push", API_ARGS_VALUE, invoker); }); api_regist("/index/api/whep", [](API_ARGS_STRING_ASYNC) { whip_whep_func("play", API_ARGS_VALUE, invoker); }); + + api_regist(delete_webrtc_url, [](API_ARGS_MAP_ASYNC) { + CHECK_ARGS("id", "token"); + CHECK(allArgs.getParser().Method() == "DELETE", "http method is not DELETE: " + allArgs.getParser().Method()); + auto obj = WebRtcTransportManager::Instance().getItem(allArgs["id"]); + if (!obj) { + invoker(404, headerOut, "id not found"); + return; + } + if (obj->deleteRandStr() != allArgs["token"]) { + invoker(401, headerOut, "token incorrect"); + return; + } + obj->safeShutdown(SockException(Err_shutdown, "deleted by http api")); + invoker(200, headerOut, ""); + }); #endif #if defined(ENABLE_VERSION) diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index 8243cba0..a990f98b 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -52,6 +52,7 @@ ssize_t HttpSession::onRecvHeader(const char *header,size_t len) { static unordered_map s_func_map; static onceToken token([]() { s_func_map.emplace("GET",&HttpSession::Handle_Req_GET); + s_func_map.emplace("DELETE",&HttpSession::Handle_Req_GET); s_func_map.emplace("POST",&HttpSession::Handle_Req_POST); s_func_map.emplace("HEAD",&HttpSession::Handle_Req_HEAD); s_func_map.emplace("OPTIONS",&HttpSession::Handle_Req_OPTIONS); diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index 470ef733..7dc9e816 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -113,6 +113,13 @@ const string &WebRtcTransport::getIdentifier() const { return _identifier; } +const std::string& WebRtcTransport::deleteRandStr() const { + if (_delete_rand_str.empty()) { + _delete_rand_str = makeRandStr(32); + } + return _delete_rand_str; +} + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void WebRtcTransport::OnIceServerSendStunPacket( @@ -1053,6 +1060,15 @@ void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, int &len, void *ctx } } +void WebRtcTransportImp::safeShutdown(const SockException &ex) { + std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); + getPoller()->async([ex, weak_self]() { + if (auto strong_self = weak_self.lock()) { + strong_self->onShutdown(ex); + } + }); +} + void WebRtcTransportImp::onShutdown(const SockException &ex) { WarnL << ex; unrefSelf(); diff --git a/webrtc/WebRtcTransport.h b/webrtc/WebRtcTransport.h index eb33b090..2534ca3b 100644 --- a/webrtc/WebRtcTransport.h +++ b/webrtc/WebRtcTransport.h @@ -40,7 +40,8 @@ public: WebRtcInterface() = default; virtual ~WebRtcInterface() = default; virtual std::string getAnswerSdp(const std::string &offer) = 0; - virtual const std::string &getIdentifier() const = 0; + virtual const std::string& getIdentifier() const = 0; + virtual const std::string& deleteRandStr() const { static std::string s_null; return s_null; } }; std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& offer); @@ -92,6 +93,7 @@ public: * 获取对象唯一id */ const std::string& getIdentifier() const override; + const std::string& deleteRandStr() const override; /** * socket收到udp数据 @@ -174,6 +176,7 @@ protected: std::shared_ptr _ice_server; private: + mutable std::string _delete_rand_str; std::string _identifier; EventPoller::Ptr _poller; std::shared_ptr _dtls_transport; @@ -248,6 +251,7 @@ public: void createRtpChannel(const std::string &rid, uint32_t ssrc, MediaTrack &track); void removeTuple(RTC::TransportTuple* tuple); + void safeShutdown(const SockException &ex); protected: void OnIceServerSelectedTuple(const RTC::IceServer *iceServer, RTC::TransportTuple *tuple) override;