From 5e2b29466b497ab365f0dce64d7ebf29e4127395 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 7 Apr 2017 15:34:41 +0200 Subject: [PATCH 1/3] Fixes and improvements to generic push-input handling --- lib/dtscmeta.cpp | 1 + lib/h264.cpp | 2 ++ src/io.cpp | 5 ++--- src/output/output.cpp | 1 + src/output/output_rtmp.cpp | 1 - 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/dtscmeta.cpp b/lib/dtscmeta.cpp index 143455f4..67bc499d 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -1387,6 +1387,7 @@ namespace DTSC { } vod = (packBytePos > 0); live = !vod; + EXTREME_MSG("Updating meta with %lld@%lld+%lld", packTrack, packTime, packOffset); if (packTrack > 0 && tracks.count(packTrack)){ tracks[packTrack].update(packTime, packOffset, packDataSize, packBytePos, isKeyframe, packSendSize, segment_size); } diff --git a/lib/h264.cpp b/lib/h264.cpp index 1efa2cec..408a9900 100644 --- a/lib/h264.cpp +++ b/lib/h264.cpp @@ -213,6 +213,8 @@ namespace h264 { unsigned int timeScale = bs.get(32); result.fps = (double)timeScale / (2 * unitsInTick); bs.skip(1); + }else{ + result.fps = 0; } } diff --git a/src/io.cpp b/src/io.cpp index 4dff9e39..195060c2 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -305,9 +305,7 @@ namespace Mist { if (myMeta.live){ - //Update the metadata - DTSC::Packet updatePack(myPage.mapped + curOffset, size + 8, true); - myMeta.update(updatePack); + myMeta.update(pack); } //End of brain melt @@ -402,6 +400,7 @@ namespace Mist { myMeta.live = true; //Store the trackid for easier access unsigned long tid = packet.getTrackId(); + VERYHIGH_MSG("Buffering %s packet on track %lu: %llums, %db", myMeta.tracks[tid].codec.c_str(), tid, packet.getTime(), packet.getPayloadLen()); //Do nothing if the trackid is invalid if (!tid) { WARN_MSG("Packet without trackid!"); diff --git a/src/output/output.cpp b/src/output/output.cpp index 6ade1eaa..a923468a 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -198,6 +198,7 @@ namespace Mist{ if (nProxy.userClient.getData()){ nProxy.userClient.finish(); } + nProxy.streamName = streamName; char userPageName[NAME_BUFFER_SIZE]; snprintf(userPageName, NAME_BUFFER_SIZE, SHM_USERS, streamName.c_str()); unsigned int attempts = 0; diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp index bd6fc99b..69dbdebc 100644 --- a/src/output/output_rtmp.cpp +++ b/src/output/output_rtmp.cpp @@ -927,7 +927,6 @@ namespace Mist { snprintf(userPageName, NAME_BUFFER_SIZE, SHM_USERS, streamName.c_str()); nProxy.userClient = IPC::sharedClient(userPageName, PLAY_EX_SIZE, true); } - nProxy.streamName = streamName; bufferLivePacket(thisPacket); } break; From a82be2775ff4056d946943bf6194609a2c52cddf Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sat, 15 Apr 2017 14:00:04 +0200 Subject: [PATCH 2/3] Added local-only auto-authorize for API --- lib/socket.cpp | 43 ++++++++++++++++++++++++++----- lib/socket.h | 1 + src/controller/controller_api.cpp | 5 ++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/lib/socket.cpp b/lib/socket.cpp index ad70cb93..61ba79e4 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #define BUFFER_BLOCKSIZE 4096 // set buffer blocksize to 4KiB @@ -656,17 +657,17 @@ bool Socket::Connection::isAddress(std::string addr){ int s = getaddrinfo(addr.c_str(), 0, &hints, &result); if (s != 0){return false;} - char newaddr[INET_ADDRSTRLEN]; + char newaddr[INET6_ADDRSTRLEN]; newaddr[0] = 0; for (rp = result; rp != NULL; rp = rp->ai_next){ - if (rp->ai_family == AF_INET && inet_ntop(rp->ai_family, &(((sockaddr_in *)rp->ai_addr)->sin_addr), newaddr, INET_ADDRSTRLEN)){ - DEBUG_MSG(DLVL_DEVEL, "Comparing: '%s' to '%s'", remotehost.c_str(), newaddr); + if (rp->ai_family == AF_INET && inet_ntop(rp->ai_family, &(((sockaddr_in *)rp->ai_addr)->sin_addr), newaddr, INET6_ADDRSTRLEN)){ + INFO_MSG("Comparing '%s' to '%s'", remotehost.c_str(), newaddr); if (remotehost == newaddr){return true;} - DEBUG_MSG(DLVL_DEVEL, "Comparing: '%s' to '::ffff:%s'", remotehost.c_str(), newaddr); + INFO_MSG("Comparing '%s' to '::ffff:%s'", remotehost.c_str(), newaddr); if (remotehost == std::string("::ffff:") + newaddr){return true;} } - if (rp->ai_family == AF_INET6 && inet_ntop(rp->ai_family, &(((sockaddr_in6 *)rp->ai_addr)->sin6_addr), newaddr, INET_ADDRSTRLEN)){ - DEBUG_MSG(DLVL_DEVEL, "Comparing: '%s' to '%s'", remotehost.c_str(), newaddr); + if (rp->ai_family == AF_INET6 && inet_ntop(rp->ai_family, &(((sockaddr_in6 *)rp->ai_addr)->sin6_addr), newaddr, INET6_ADDRSTRLEN)){ + INFO_MSG("Comparing '%s' to '%s'", remotehost.c_str(), newaddr); if (remotehost == newaddr){return true;} } } @@ -674,6 +675,36 @@ bool Socket::Connection::isAddress(std::string addr){ return false; } +bool Socket::Connection::isLocal(){ + struct ifaddrs * ifAddrStruct=NULL; + struct ifaddrs * ifa=NULL; + void * tmpAddrPtr=NULL; + char addressBuffer[INET6_ADDRSTRLEN]; + + getifaddrs(&ifAddrStruct); + + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) { + continue; + } + if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4 + tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; + inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); + INFO_MSG("Comparing '%s' to '%s'", remotehost.c_str(), addressBuffer); + if (remotehost == addressBuffer){return true;} + INFO_MSG("Comparing '%s' to '::ffff:%s'", remotehost.c_str(), addressBuffer); + if (remotehost == std::string("::ffff:") + addressBuffer){return true;} + } else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6 + tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; + inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); + INFO_MSG("Comparing '%s' to '%s'", remotehost.c_str(), addressBuffer); + if (remotehost == addressBuffer){return true;} + } + } + if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct); + return false; +} + /// Create a new base Server. The socket is never connected, and a placeholder for later connections. Socket::Server::Server(){ sock = -1; diff --git a/lib/socket.h b/lib/socket.h index 0ebe0eb8..7704143d 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -82,6 +82,7 @@ namespace Socket{ std::string getError(); ///< Returns a string describing the last error that occured. bool connected() const; ///< Returns the connected-state for this socket. bool isAddress(std::string addr); + bool isLocal(); ///< Returns true if remote address is a local address. // buffered i/o methods bool spool(); ///< Updates the downbufferinternal variables. bool peek(); ///< Clears the downbuffer and fills it with peek diff --git a/src/controller/controller_api.cpp b/src/controller/controller_api.cpp index aef78505..e022f624 100644 --- a/src/controller/controller_api.cpp +++ b/src/controller/controller_api.cpp @@ -174,6 +174,11 @@ int Controller::handleAPIConnection(Socket::Connection & conn){ } {//lock the config mutex here - do not unlock until done processing tthread::lock_guard guard(configMutex); + //Are we local and not forwarded? Instant-authorized. + if (!authorized && !H.hasHeader("X-Real-IP") && conn.isLocal()){ + INFO_MSG("Local API access automatically authorized"); + authorized = true; + } //if already authorized, do not re-check for authorization if (authorized){ Response["authorize"]["status"] = "OK"; From a7718c78e94bf6674f6dd66996ee64ae1b836904 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sat, 15 Apr 2017 15:20:02 +0200 Subject: [PATCH 3/3] Made JSON::string_escape a public function --- lib/json.cpp | 18 ++++++++++++------ lib/json.h | 5 ++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/json.cpp b/lib/json.cpp index ce27de81..cc4f3ee6 100644 --- a/lib/json.cpp +++ b/lib/json.cpp @@ -284,7 +284,7 @@ static std::string UTF16(uint32_t c){ } } -static std::string string_escape(const std::string val) { +std::string JSON::string_escape(const std::string & val) { std::string out = "\""; for (unsigned int i = 0; i < val.size(); ++i) { const char & c = val.data()[i]; @@ -1059,7 +1059,7 @@ std::string JSON::Value::toString() const { break; } case STRING: { - return string_escape(strVal); + return JSON::string_escape(strVal); break; } case ARRAY: { @@ -1080,7 +1080,7 @@ std::string JSON::Value::toString() const { std::string tmp2 = "{"; if (objVal.size() > 0) { jsonForEachConst(*this, i){ - tmp2 += string_escape(i.key()) + ":"; + tmp2 += JSON::string_escape(i.key()) + ":"; tmp2 += i->toString(); if (i.num()+1 != objVal.size()) { tmp2 += ","; @@ -1114,7 +1114,7 @@ std::string JSON::Value::toPrettyString(int indentation) const { return "\"" + JSON::Value((long long int)strVal.size()).asString() + " bytes of data\""; } } - return string_escape(strVal); + return JSON::string_escape(strVal); break; } case ARRAY: { @@ -1141,7 +1141,7 @@ std::string JSON::Value::toPrettyString(int indentation) const { } std::string tmp2 = "{" + std::string((shortMode ? "" : "\n")); jsonForEachConst(*this, i){ - tmp2 += (shortMode ? std::string("") : std::string(indentation + 2, ' ')) + string_escape(i.key()) + ":"; + tmp2 += (shortMode ? std::string("") : std::string(indentation + 2, ' ')) + JSON::string_escape(i.key()) + ":"; tmp2 += i->toPrettyString(indentation + 2); if (i.num() + 1 != objVal.size()) { tmp2 += "," + std::string((shortMode ? " " : "\n")); @@ -1249,7 +1249,13 @@ unsigned int JSON::Value::size() const { } /// Converts a std::string to a JSON::Value. -JSON::Value JSON::fromString(std::string json) { +JSON::Value JSON::fromString(const char * data, const uint32_t data_len) { + const std::string str(data, data_len); + return JSON::fromString(str); +} + +/// Converts a std::string to a JSON::Value. +JSON::Value JSON::fromString(const std::string & json) { std::istringstream is(json); return JSON::Value(is); } diff --git a/lib/json.h b/lib/json.h index 37390033..d73360fb 100644 --- a/lib/json.h +++ b/lib/json.h @@ -16,6 +16,8 @@ namespace JSON { EMPTY, BOOL, INTEGER, STRING, ARRAY, OBJECT }; + /// JSON-string-escapes a value + std::string string_escape(const std::string & val); /// A JSON::Value is either a string or an integer, but may also be an object, array or null. class Value { @@ -91,7 +93,8 @@ namespace JSON { Value fromDTMI2(const unsigned char * data, unsigned int len, unsigned int & i); Value fromDTMI(std::string & data); Value fromDTMI(const unsigned char * data, unsigned int len, unsigned int & i); - Value fromString(std::string json); + Value fromString(const std::string & json); + Value fromString(const char * data, const uint32_t data_len); Value fromFile(std::string filename); void fromDTMI2(std::string & data, Value & ret); void fromDTMI2(const unsigned char * data, unsigned int len, unsigned int & i, Value & ret);