diff --git a/src/utils/sdp.c b/src/utils/sdp.c index 02045f506..7416f1841 100644 --- a/src/utils/sdp.c +++ b/src/utils/sdp.c @@ -101,6 +101,8 @@ struct sdp { struct stream_info stream[MAX_STREAMS]; int stream_count; //between 1 and MAX_STREAMS char *sdp_dump; + void (*address_callback)(void *udata, const char *address); + void *address_callback_udata; }; struct sdp *new_sdp(int ip_version, const char *receiver) { @@ -284,6 +286,12 @@ void clean_sdp(struct sdp *sdp){ #define SECURITY_TXT "Contact: http://www.ultragrid.cz/contact\n" struct Response* createResponseForRequest(const struct Request* request, struct Connection* connection) { + struct sdp *sdp = connection->server->tag; + + if (sdp->address_callback){ + sdp->address_callback(sdp->address_callback_udata, connection->remoteHost); + } + log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Requested %s.\n", request->pathDecoded); if (strcasecmp(request->pathDecoded, "/robots.txt") == 0 || @@ -295,7 +303,7 @@ struct Response* createResponseForRequest(const struct Request* request, struct } log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Returning the SDP.\n"); - const char *sdp_content = ((struct sdp *) connection->server->tag)->sdp_dump; + const char *sdp_content = sdp->sdp_dump; struct Response* response = responseAlloc(200, "OK", "application/sdp", 0); heapStringSetToCString(&response->body, sdp_content); return response; @@ -344,11 +352,14 @@ static void print_http_path(struct sdp *sdp) { } } -bool sdp_run_http_server(struct sdp *sdp, int port) +bool sdp_run_http_server(struct sdp *sdp, int port, address_callback_t addr_callback, void *addr_callback_udata) { assert(port >= 0 && port < 65536); assert(sdp->sdp_dump != NULL); + sdp->address_callback = addr_callback; + sdp->address_callback_udata = addr_callback_udata; + portInHostOrder = port; struct Server *http_server = calloc(1, sizeof(struct Server)); serverInit(http_server); diff --git a/src/utils/sdp.h b/src/utils/sdp.h index 987c9da51..cbb9f1bc1 100644 --- a/src/utils/sdp.h +++ b/src/utils/sdp.h @@ -54,6 +54,8 @@ extern "C" { #define DEFAULT_SDP_HTTP_PORT 8554 +typedef void (*address_callback_t)(void *udata, const char *address); + struct sdp *new_sdp(int ip_version, const char *receiver); int sdp_add_audio(struct sdp *sdp, int port, int sample_rate, int channels, audio_codec_t codec); int sdp_add_video(struct sdp *sdp, int port, codec_t codec); @@ -64,7 +66,7 @@ int sdp_add_video(struct sdp *sdp, int port, codec_t codec); * @param output textual representation of sdp */ bool gen_sdp(struct sdp *sdp, const char *sdp_file_name); -bool sdp_run_http_server(struct sdp *sdp, int port); +bool sdp_run_http_server(struct sdp *sdp, int port, address_callback_t addr_callback, void *addr_callback_udata); void clean_sdp(struct sdp *sdp); #ifdef __cplusplus diff --git a/src/video_rxtx/h264_sdp.cpp b/src/video_rxtx/h264_sdp.cpp index 453c7dd0d..0f8da537e 100644 --- a/src/video_rxtx/h264_sdp.cpp +++ b/src/video_rxtx/h264_sdp.cpp @@ -45,11 +45,13 @@ #include "config_win32.h" #endif // HAVE_CONFIG_H +#include #include #include "debug.h" #include "host.h" #include "lib_common.h" +#include "rang.hpp" #include "rtp/rtp.h" #include "rtp/rtp_callback.h" // PCMA/PCMU packet types #include "rtp/rtpenc_h264.h" @@ -58,8 +60,11 @@ #include "utils/sdp.h" #include "video.h" #include "video_rxtx.h" -#include "video_rxtx/h264_sdp.h" +#include "video_rxtx/h264_sdp.hpp" +using rang::fg; +using rang::style; +using std::array; using std::cout; using std::shared_ptr; using std::string; @@ -69,12 +74,16 @@ h264_sdp_video_rxtx::h264_sdp_video_rxtx(std::map const &p { auto opts = params.at("opts").str; if (strcmp(opts, "help") == 0) { - cout << "Usage:\n\tuv --protocol sdp[:port=][:file=|no]\n"; + cout << "Usage:\n"; + cout << style::bold << "\tuv " << fg::red << "--protocol sdp" << fg::reset << "[:autorun][:file=|no][:port=]\n" << style::reset; + cout << "where:\n"; + cout << style::bold << "\tautorun" << style::reset << " - automatically send to the address that requested the SDP over HTTP without giving an address (use with caution!)\n"; throw 0; } LOG(LOG_LEVEL_WARNING) << "Warning: SDP support is experimental only. Things may be broken - feel free to report them but the support may be limited.\n"; m_sdp = new_sdp(params.at("force_ip_version").i, m_requested_receiver.c_str()); + m_saved_addr = m_requested_receiver; if (m_sdp == nullptr) { throw string("[SDP] SDP creation failed\n"); } @@ -94,6 +103,8 @@ h264_sdp_video_rxtx::h264_sdp_video_rxtx(std::map const &p m_requested_http_port = stoi(str.substr((str.find_first_of('=') + 1))); } else if (strstr(item, "file=") == item) { m_requested_file = str.substr((str.find_first_of('=') + 1)); + } else if (strstr(item, "autorun") == item) { + m_autorun = true; } else { throw string("[SDP] Wrong option: ") + item + "\n"; } @@ -101,6 +112,35 @@ h264_sdp_video_rxtx::h264_sdp_video_rxtx(std::map const &p } } +void h264_sdp_video_rxtx::change_address_callback(void *udata, const char *address) +{ + auto *s = static_cast(udata); + if (!s->m_autorun || s->m_saved_addr == address) { + return; + } + s->m_saved_addr = address; + array pathV{}; + + array path_sender{ MODULE_CLASS_SENDER, + MODULE_CLASS_NONE }; + append_message_path(pathV.data(), pathV.size(), path_sender.data()); + + //CHANGE DST ADDRESS + auto *msgV2 = reinterpret_cast(new_message( + sizeof(struct msg_sender))); + strncpy(static_cast(msgV2->receiver), address, + sizeof(msgV2->receiver) - 1); + msgV2->type = SENDER_MSG_CHANGE_RECEIVER; + + auto *resp = send_message(get_root_module(s->m_parent), pathV.data(), reinterpret_cast(msgV2)); + if (response_get_status(resp) == RESPONSE_OK) { + LOG(LOG_LEVEL_NOTICE) << "[SDP] Changing address to " << address << "\n"; + } else { + LOG(LOG_LEVEL_WARNING) << "[SDP] Unagle to change address to " << address << " (" << response_get_status(resp) << ")\n"; + } + free_response(resp); +} + void h264_sdp_video_rxtx::sdp_add_video(codec_t codec) { int rc = ::sdp_add_video(m_sdp, m_saved_tx_port, codec); @@ -116,7 +156,7 @@ void h264_sdp_video_rxtx::sdp_add_video(codec_t codec) throw string("[SDP] File creation failed\n"); } #ifdef SDP_HTTP - if (!sdp_run_http_server(m_sdp, m_requested_http_port)) { + if (!sdp_run_http_server(m_sdp, m_requested_http_port, h264_sdp_video_rxtx::change_address_callback, this)) { throw string("[SDP] Server run failed!\n"); } #endif diff --git a/src/video_rxtx/h264_sdp.h b/src/video_rxtx/h264_sdp.hpp similarity index 91% rename from src/video_rxtx/h264_sdp.h rename to src/video_rxtx/h264_sdp.hpp index 8affaac7d..79f2f4175 100644 --- a/src/video_rxtx/h264_sdp.h +++ b/src/video_rxtx/h264_sdp.hpp @@ -1,5 +1,5 @@ /** - * @file video_rxtx/h264_sdp.h + * @file video_rxtx/h264_sdp.hpp * @author Martin Pulec * @author David Cassany * @author Ignacio Contreras @@ -53,6 +53,7 @@ public: h264_sdp_video_rxtx(std::map const &); virtual ~h264_sdp_video_rxtx(); private: + static void change_address_callback(void *udata, const char *address); virtual void send_frame(std::shared_ptr); virtual void *(*get_receiver_thread())(void *arg) { return NULL; @@ -64,6 +65,9 @@ private: std::string m_requested_file; int m_requested_http_port = DEFAULT_SDP_HTTP_PORT; bool m_sent_compress_change = false; + + bool m_autorun = false; + std::string m_saved_addr; ///< for dynamic address reconfiguration, @see m_autorun }; #endif // VIDEO_RXTX_H264_SDP_H_