diff --git a/lib/dtscmeta.cpp b/lib/dtscmeta.cpp index 89f3645c..752c57d1 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -1457,6 +1457,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, ivec); } diff --git a/lib/h264.cpp b/lib/h264.cpp index 91203890..e949424f 100644 --- a/lib/h264.cpp +++ b/lib/h264.cpp @@ -155,6 +155,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/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); 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 06ca6d2d..54fe491f 100644 --- a/src/controller/controller_api.cpp +++ b/src/controller/controller_api.cpp @@ -196,6 +196,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"; diff --git a/src/io.cpp b/src/io.cpp index b0f0fd96..0ec5c77a 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -370,9 +370,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 @@ -467,6 +465,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 f5e9e365..f5911be2 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -328,6 +328,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 2c4d4802..563044e9 100644 --- a/src/output/output_rtmp.cpp +++ b/src/output/output_rtmp.cpp @@ -1119,7 +1119,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;