|
|
|
@ -52,6 +52,7 @@
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
|
|
#if ZM_MEM_MAPPED
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
@ -1122,10 +1123,9 @@ bool Monitor::connect() {
|
|
|
|
|
|
|
|
|
|
#if HAVE_LIBCURL //janus setup. Depends on libcurl.
|
|
|
|
|
if (janus_enabled && (path.find("rtsp://") != std::string::npos)) {
|
|
|
|
|
get_janus_session();
|
|
|
|
|
if (add_to_janus() != 0) {
|
|
|
|
|
if (add_to_janus() != 0) { //The initial attempt may fail. This is a temporary workaround.
|
|
|
|
|
Warning("Failed to add monitor stream to Janus!");
|
|
|
|
|
}
|
|
|
|
|
Warning("Failed to add monitor stream to Janus!"); //The first attempt may fail. Will be reattempted in the Poller thread
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
@ -1797,6 +1797,8 @@ void Monitor::UpdateFPS() {
|
|
|
|
|
//Thread where ONVIF polling, and other similar status polling can happen.
|
|
|
|
|
//Since these can be blocking, run here to avoid intefering with other processing
|
|
|
|
|
bool Monitor::Poll() {
|
|
|
|
|
//We want to trigger every 5 seconds or so. so grab the time at the beginning of the loop, and sleep at the end.
|
|
|
|
|
std::chrono::system_clock::time_point loop_start_time = std::chrono::system_clock::now();
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_GSOAP
|
|
|
|
|
if (ONVIF_Healthy) {
|
|
|
|
@ -1838,10 +1840,17 @@ bool Monitor::Poll() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
std::this_thread::sleep_for (std::chrono::seconds(1)); //thread sleep to avoid the busy loop.
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (janus_enabled) {
|
|
|
|
|
if (janus_session.empty()) {
|
|
|
|
|
get_janus_session();
|
|
|
|
|
}
|
|
|
|
|
if (check_janus() == 0) {
|
|
|
|
|
add_to_janus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
std::this_thread::sleep_until(loop_start_time + std::chrono::seconds(5));
|
|
|
|
|
return TRUE;
|
|
|
|
|
} //end Poll
|
|
|
|
|
|
|
|
|
@ -3166,10 +3175,8 @@ int Monitor::PrimeCapture() {
|
|
|
|
|
}
|
|
|
|
|
} // end if rtsp_server
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_GSOAP //For now, just don't run the thread if no ONVIF support. This may change if we add other long polling options.
|
|
|
|
|
//ONVIF Thread
|
|
|
|
|
|
|
|
|
|
if (onvif_event_listener && ONVIF_Healthy) {
|
|
|
|
|
//Poller Thread
|
|
|
|
|
if (onvif_event_listener || janus_enabled) {
|
|
|
|
|
|
|
|
|
|
if (!Poller) {
|
|
|
|
|
Poller = zm::make_unique<PollThread>(this);
|
|
|
|
@ -3177,7 +3184,7 @@ int Monitor::PrimeCapture() {
|
|
|
|
|
Poller->Start();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (decoding_enabled) {
|
|
|
|
|
if (!decoder_it) decoder_it = packetqueue.get_video_it(false);
|
|
|
|
|
if (!decoder) {
|
|
|
|
@ -3381,14 +3388,17 @@ size_t Monitor::WriteCallback(void *contents, size_t size, size_t nmemb, void *u
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Monitor::add_to_janus() {
|
|
|
|
|
//TODO clean this up, add error checking, etc
|
|
|
|
|
std::string response;
|
|
|
|
|
std::string endpoint = "127.0.0.1:8088/janus/";
|
|
|
|
|
std::string endpoint;
|
|
|
|
|
if ((config.janus_path != nullptr) && (config.janus_path[0] != '\0')) {
|
|
|
|
|
endpoint = config.janus_path;
|
|
|
|
|
} else {
|
|
|
|
|
endpoint = "127.0.0.1:8088/janus/";
|
|
|
|
|
}
|
|
|
|
|
std::string postData = "{\"janus\" : \"create\", \"transaction\" : \"randomString\"}";
|
|
|
|
|
std::string rtsp_username;
|
|
|
|
|
std::string rtsp_password;
|
|
|
|
|
std::string rtsp_path = "rtsp://";
|
|
|
|
|
std::string janus_id;
|
|
|
|
|
std::size_t pos;
|
|
|
|
|
std::size_t pos2;
|
|
|
|
|
CURLcode res;
|
|
|
|
@ -3409,44 +3419,15 @@ int Monitor::add_to_janus() {
|
|
|
|
|
rtsp_password = path.substr(pos+1, pos2 - pos - 1);
|
|
|
|
|
rtsp_path += path.substr(pos2 + 1);
|
|
|
|
|
|
|
|
|
|
//Start Janus API init. Need to get a session_id and handle_id
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK) {
|
|
|
|
|
Error("Failed to curl_easy_perform getting session/handle id");
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = response.find("\"id\": ");
|
|
|
|
|
if (pos == std::string::npos) return -1;
|
|
|
|
|
janus_id = response.substr(pos + 6, 16);
|
|
|
|
|
response = "";
|
|
|
|
|
endpoint += janus_id;
|
|
|
|
|
postData = "{\"janus\" : \"attach\", \"plugin\" : \"janus.plugin.streaming\", \"transaction\" : \"randomString\"}";
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL,endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK) {
|
|
|
|
|
Error("Failed to curl_easy_perform attaching");
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
pos = response.find("\"id\": ");
|
|
|
|
|
if (pos == std::string::npos) return -1;
|
|
|
|
|
std::string handle_id = response.substr(pos + 6, 16); //TODO: This is an assumption that the string is always 16
|
|
|
|
|
endpoint += "/";
|
|
|
|
|
endpoint += handle_id;
|
|
|
|
|
endpoint += janus_session;
|
|
|
|
|
|
|
|
|
|
//Assemble our actual request
|
|
|
|
|
postData = "{\"janus\" : \"message\", \"transaction\" : \"randomString\", \"body\" : {";
|
|
|
|
|
postData += "\"request\" : \"create\", \"admin_key\" : \"supersecret\", \"type\" : \"rtsp\", ";
|
|
|
|
|
postData += "\"url\" : \"";
|
|
|
|
|
postData += "\"request\" : \"create\", \"admin_key\" : \"";
|
|
|
|
|
postData += config.janus_secret;
|
|
|
|
|
postData += "\", \"type\" : \"rtsp\", ";
|
|
|
|
|
postData += "\"url\" : \"";
|
|
|
|
|
postData += rtsp_path;
|
|
|
|
|
postData += "\", \"rtsp_user\" : \"";
|
|
|
|
|
postData += rtsp_username;
|
|
|
|
@ -3467,52 +3448,39 @@ int Monitor::add_to_janus() {
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if ((response.find("error") != std::string::npos) && ((response.find("No such session") != std::string::npos) || (response.find("No such handle") != std::string::npos))) {
|
|
|
|
|
janus_session = "";
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -2;
|
|
|
|
|
}
|
|
|
|
|
//scan for missing session or handle id "No such session" "no such handle"
|
|
|
|
|
|
|
|
|
|
Debug(1,"Added stream to Janus: %s", response.c_str());
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int Monitor::remove_from_janus() {
|
|
|
|
|
//TODO clean this up, add error checking, etc
|
|
|
|
|
|
|
|
|
|
int Monitor::check_janus() {
|
|
|
|
|
std::string response;
|
|
|
|
|
std::string endpoint = "127.0.0.1:8088/janus/";
|
|
|
|
|
std::string postData = "{\"janus\" : \"create\", \"transaction\" : \"randomString\"}";
|
|
|
|
|
std::size_t pos;
|
|
|
|
|
std::string endpoint;
|
|
|
|
|
if ((config.janus_path != nullptr) && (config.janus_path[0] != '\0')) {
|
|
|
|
|
endpoint = config.janus_path;
|
|
|
|
|
} else {
|
|
|
|
|
endpoint = "127.0.0.1:8088/janus/";
|
|
|
|
|
}
|
|
|
|
|
std::string postData;
|
|
|
|
|
//std::size_t pos;
|
|
|
|
|
CURLcode res;
|
|
|
|
|
|
|
|
|
|
curl = curl_easy_init();
|
|
|
|
|
if(!curl) return -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Start Janus API init. Need to get a session_id and handle_id
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK) return -1;
|
|
|
|
|
|
|
|
|
|
pos = response.find("\"id\": ");
|
|
|
|
|
if (pos == std::string::npos) return -1;
|
|
|
|
|
std::string janus_id = response.substr(pos + 6, 16);
|
|
|
|
|
response = "";
|
|
|
|
|
endpoint += janus_id;
|
|
|
|
|
postData = "{\"janus\" : \"attach\", \"plugin\" : \"janus.plugin.streaming\", \"transaction\" : \"randomString\"}";
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL,endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK) return -1;
|
|
|
|
|
|
|
|
|
|
pos = response.find("\"id\": ");
|
|
|
|
|
if (pos == std::string::npos) return -1;
|
|
|
|
|
std::string handle_id = response.substr(pos + 6, 16);
|
|
|
|
|
endpoint += "/";
|
|
|
|
|
endpoint += handle_id;
|
|
|
|
|
endpoint += janus_session;
|
|
|
|
|
|
|
|
|
|
//Assemble our actual request
|
|
|
|
|
postData = "{\"janus\" : \"message\", \"transaction\" : \"randomString\", \"body\" : {";
|
|
|
|
|
postData += "\"request\" : \"destroy\", \"admin_key\" : \"supersecret\", \"id\" : ";
|
|
|
|
|
postData += "\"request\" : \"info\", \"id\" : ";
|
|
|
|
|
postData += std::to_string(id);
|
|
|
|
|
postData += "}}";
|
|
|
|
|
|
|
|
|
@ -3521,9 +3489,128 @@ int Monitor::remove_from_janus() {
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK) return -1;
|
|
|
|
|
if (res != CURLE_OK) { //may mean an error code thrown by Janus, because of a bad session
|
|
|
|
|
Warning("Attempted %s got %s", endpoint.c_str(), curl_easy_strerror(res));
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
janus_session = "";
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
Debug(1, "Queried for stream status: %s", response.c_str());
|
|
|
|
|
if ((response.find("error") != std::string::npos) && ((response.find("No such session") != std::string::npos) || (response.find("No such handle") != std::string::npos))) {
|
|
|
|
|
Warning("Janus Session timed out");
|
|
|
|
|
janus_session = "";
|
|
|
|
|
return -2;
|
|
|
|
|
} else if (response.find("No such mountpoint") != std::string::npos) {
|
|
|
|
|
Warning("Mountpoint Missing");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Monitor::remove_from_janus() {
|
|
|
|
|
std::string response;
|
|
|
|
|
std::string endpoint;
|
|
|
|
|
if ((config.janus_path != nullptr) && (config.janus_path[0] != '\0')) {
|
|
|
|
|
endpoint = config.janus_path;
|
|
|
|
|
} else {
|
|
|
|
|
endpoint = "127.0.0.1:8088/janus/";
|
|
|
|
|
}
|
|
|
|
|
std::string postData = "{\"janus\" : \"create\", \"transaction\" : \"randomString\"}";
|
|
|
|
|
//std::size_t pos;
|
|
|
|
|
CURLcode res;
|
|
|
|
|
|
|
|
|
|
curl = curl_easy_init();
|
|
|
|
|
if(!curl) return -1;
|
|
|
|
|
|
|
|
|
|
endpoint += "/";
|
|
|
|
|
endpoint += janus_session;
|
|
|
|
|
|
|
|
|
|
//Assemble our actual request
|
|
|
|
|
postData = "{\"janus\" : \"message\", \"transaction\" : \"randomString\", \"body\" : {";
|
|
|
|
|
postData += "\"request\" : \"destroy\", \"admin_key\" : \"";
|
|
|
|
|
postData += config.janus_secret;
|
|
|
|
|
postData += "\", \"id\" : ";
|
|
|
|
|
postData += std::to_string(id);
|
|
|
|
|
postData += "}}";
|
|
|
|
|
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL,endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK) {
|
|
|
|
|
Warning("Libcurl attempted %s got %s", endpoint.c_str(), curl_easy_strerror(res));
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Debug(1, "Removed stream from Janus: %s", response.c_str());
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Monitor::get_janus_session() {
|
|
|
|
|
std::string response;
|
|
|
|
|
std::string endpoint;
|
|
|
|
|
if ((config.janus_path != nullptr) && (config.janus_path[0] != '\0')) {
|
|
|
|
|
endpoint = config.janus_path;
|
|
|
|
|
} else {
|
|
|
|
|
endpoint = "127.0.0.1:8088/janus/";
|
|
|
|
|
}
|
|
|
|
|
std::string postData = "{\"janus\" : \"create\", \"transaction\" : \"randomString\"}";
|
|
|
|
|
std::size_t pos;
|
|
|
|
|
CURLcode res;
|
|
|
|
|
curl = curl_easy_init();
|
|
|
|
|
if(!curl) return -1;
|
|
|
|
|
|
|
|
|
|
//Start Janus API init. Need to get a session_id and handle_id
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK) {
|
|
|
|
|
Warning("Libcurl attempted %s got %s", endpoint.c_str(), curl_easy_strerror(res));
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = response.find("\"id\": ");
|
|
|
|
|
if (pos == std::string::npos)
|
|
|
|
|
{
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
janus_session = response.substr(pos + 6, 16);
|
|
|
|
|
|
|
|
|
|
response = "";
|
|
|
|
|
endpoint += "/";
|
|
|
|
|
endpoint += janus_session;
|
|
|
|
|
postData = "{\"janus\" : \"attach\", \"plugin\" : \"janus.plugin.streaming\", \"transaction\" : \"randomString\"}";
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL,endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
|
if (res != CURLE_OK)
|
|
|
|
|
{
|
|
|
|
|
Warning("Libcurl attempted %s got %s", endpoint.c_str(), curl_easy_strerror(res));
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = response.find("\"id\": ");
|
|
|
|
|
if (pos == std::string::npos)
|
|
|
|
|
{
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
janus_session += "/";
|
|
|
|
|
janus_session += response.substr(pos + 6, 16);
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
return 1;
|
|
|
|
|
} //get_janus_session
|
|
|
|
|