Merge branch 'development' into LTS_development

# Conflicts:
#	lib/shared_memory.cpp
#	src/controller/controller.cpp
#	src/controller/controller_storage.h
#	src/output/output.cpp
This commit is contained in:
Thulinma 2016-09-15 16:17:06 +02:00
commit 1172768c34
20 changed files with 270 additions and 192 deletions

View file

@ -229,7 +229,7 @@ bool Util::Config::parseArgs(int & argc, char ** & argv) {
#endif
/*LTS-END*/
std::cout << "Built on " __DATE__ ", " __TIME__ << std::endl;
exit(1);
exit(0);
break;
default:
jsonForEach(vals, it) {

View file

@ -19,6 +19,12 @@
#define DTSC_ARR 0x0A
#define DTSC_CON 0xFF
//Increase this value every time the DTSH file format changes in an incompatible way
//Changelog:
// Version 0-2: Undocumented changes
// Version 3: switched to bigMeta-style by default, Parts layout switched from 3/2/4 to 3/3/3 bytes
#define DTSH_VERSION 3
namespace DTSC {
///\brief This enum holds all possible datatypes for DTSC packets.
@ -125,6 +131,7 @@ namespace DTSC {
int getDataLen() const;
int getPayloadLen() const;
JSON::Value toJSON() const;
std::string toSummary() const;
Scan getScan() const;
protected:
bool master;
@ -193,21 +200,22 @@ namespace DTSC {
///\brief Basic class for storage of data associated with single DTSC packets, a.k.a. parts.
class Part {
public:
long getSize();
void setSize(long newSize);
short getDuration();
void setDuration(short newDuration);
long getOffset();
void setOffset(long newOffset);
uint32_t getSize();
void setSize(uint32_t newSize);
uint32_t getDuration();
void setDuration(uint32_t newDuration);
uint32_t getOffset();
void setOffset(uint32_t newOffset);
char * getData();
void toPrettyString(std::ostream & str, int indent = 0);
private:
#define PACKED_PART_SIZE 9
///\brief Data storage for this Part.
///
/// - 3 bytes: MSB storage of the payload size of this packet in bytes.
/// - 2 bytes: MSB storage of the duration of this packet in milliseconds.
/// - 4 bytes: MSB storage of the presentation time offset of this packet in milliseconds.
char data[9];
/// - 3 bytes: MSB storage of the duration of this packet in milliseconds.
/// - 3 bytes: MSB storage of the presentation time offset of this packet in milliseconds.
char data[PACKED_PART_SIZE];
};
///\brief Basic class for storage of data associated with keyframes.
@ -228,7 +236,6 @@ namespace DTSC {
char * getData();
void toPrettyString(std::ostream & str, int indent = 0);
private:
#ifdef BIGMETA
#define PACKED_KEY_SIZE 25
///\brief Data storage for this Key.
///
@ -237,16 +244,6 @@ namespace DTSC {
/// - 4 bytes: MSB storage of the number of this keyframe.
/// - 2 bytes: MSB storage of the amount of parts in this keyframe.
/// - 8 bytes: MSB storage of the timestamp associated with this keyframe's first packet.
#else
#define PACKED_KEY_SIZE 16
///\brief Data storage for this Key.
///
/// - 5 bytes: MSB storage of the position of the first packet of this keyframe within the file.
/// - 3 bytes: MSB storage of the duration of this keyframe.
/// - 2 bytes: MSB storage of the number of this keyframe.
/// - 2 bytes: MSB storage of the amount of parts in this keyframe.
/// - 4 bytes: MSB storage of the timestamp associated with this keyframe's first packet.
#endif
char data[PACKED_KEY_SIZE];
};
@ -264,7 +261,6 @@ namespace DTSC {
char * getData();
void toPrettyString(std::ostream & str, int indent = 0);
private:
#ifdef BIGMETA
#define PACKED_FRAGMENT_SIZE 13
///\brief Data storage for this Fragment.
///
@ -272,15 +268,6 @@ namespace DTSC {
/// - 1 byte: length (amount of keyframes)
/// - 4 bytes: number of first keyframe in fragment
/// - 4 bytes: size of fragment in bytes
#else
#define PACKED_FRAGMENT_SIZE 11
///\brief Data storage for this Fragment.
///
/// - 4 bytes: duration (in milliseconds)
/// - 1 byte: length (amount of keyframes)
/// - 2 bytes: number of first keyframe in fragment
/// - 4 bytes: size of fragment in bytes
#endif
char data[PACKED_FRAGMENT_SIZE];
};
@ -362,12 +349,14 @@ namespace DTSC {
void writeTo(char * p);
JSON::Value toJSON();
void reset();
bool toFile(const std::string & fileName);
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
//members:
std::map<unsigned int, Track> tracks;
bool vod;
bool live;
bool merged;
uint16_t version;
long long int moreheader;
long long int bufferWindow;
};

View file

@ -4,6 +4,7 @@
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <fstream>
#define AUDIO_KEY_INTERVAL 5000 ///< This define controls the keyframe interval for non-video tracks, such as audio and metadata tracks.
@ -437,6 +438,18 @@ namespace DTSC {
return result;
}
std::string Packet::toSummary() const {
std::stringstream out;
char * res = 0;
unsigned int len = 0;
getString("data", res, len);
out << getTrackId() << "@" << getTime() << ": " << len << " bytes";
if (hasMember("keyframe")){
out << " (keyframe)";
}
return out.str();
}
/// Create an invalid DTSC::Scan object by default.
Scan::Scan() {
p = 0;
@ -870,33 +883,33 @@ namespace DTSC {
/*LTS-END*/
///\brief Returns the payloadsize of a part
long Part::getSize() {
uint32_t Part::getSize() {
return Bit::btoh24(data);
}
///\brief Sets the payloadsize of a part
void Part::setSize(long newSize) {
void Part::setSize(uint32_t newSize) {
Bit::htob24(data, newSize);
}
///\brief Retruns the duration of a part
short Part::getDuration() {
return Bit::btohs(data + 3);
///\brief Returns the duration of a part
uint32_t Part::getDuration() {
return Bit::btoh24(data + 3);
}
///\brief Sets the duration of a part
void Part::setDuration(short newDuration) {
Bit::htobs(data + 3, newDuration);
void Part::setDuration(uint32_t newDuration) {
Bit::htob24(data + 3, newDuration);
}
///\brief returns the offset of a part
long Part::getOffset() {
return Bit::btohl(data + 5);
uint32_t Part::getOffset() {
return Bit::btoh24(data + 6);
}
///\brief Sets the offset of a part
void Part::setOffset(long newOffset) {
Bit::htobl(data + 5, newOffset);
void Part::setOffset(uint32_t newOffset) {
Bit::htob24(data + 6, newOffset);
}
///\brief Returns the data of a part
@ -913,93 +926,49 @@ namespace DTSC {
///\brief Returns the byteposition of a keyframe
unsigned long long Key::getBpos() {
#ifdef BIGMETA
return Bit::btohll(data);
#else
return (((unsigned long long)data[0] << 32) | (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4]);
#endif
}
void Key::setBpos(unsigned long long newBpos) {
#ifdef BIGMETA
Bit::htobll(data, newBpos);
#else
data[4] = newBpos & 0xFF;
data[3] = (newBpos >> 8) & 0xFF;
data[2] = (newBpos >> 16) & 0xFF;
data[1] = (newBpos >> 24) & 0xFF;
data[0] = (newBpos >> 32) & 0xFF;
#endif
}
unsigned long Key::getLength() {
#ifdef BIGMETA
return Bit::btoh24(data+8);
#else
return Bit::btoh24(data+5);
#endif
}
void Key::setLength(unsigned long newLength) {
#ifdef BIGMETA
Bit::htob24(data+8, newLength);
#else
Bit::htob24(data+5, newLength);
#endif
}
///\brief Returns the number of a keyframe
unsigned long Key::getNumber() {
#ifdef BIGMETA
return Bit::btohl(data + 11);
#else
return Bit::btohs(data + 8);
#endif
}
///\brief Sets the number of a keyframe
void Key::setNumber(unsigned long newNumber) {
#ifdef BIGMETA
Bit::htobl(data + 11, newNumber);
#else
Bit::htobs(data + 8, newNumber);
#endif
}
///\brief Returns the number of parts of a keyframe
unsigned short Key::getParts() {
#ifdef BIGMETA
return Bit::btohs(data + 15);
#else
return Bit::btohs(data + 10);
#endif
}
///\brief Sets the number of parts of a keyframe
void Key::setParts(unsigned short newParts) {
#ifdef BIGMETA
Bit::htobs(data + 15, newParts);
#else
Bit::htobs(data + 10, newParts);
#endif
}
///\brief Returns the timestamp of a keyframe
unsigned long long Key::getTime() {
#ifdef BIGMETA
return Bit::btohll(data + 17);
#else
return Bit::btohl(data + 12);
#endif
}
///\brief Sets the timestamp of a keyframe
void Key::setTime(unsigned long long newTime) {
#ifdef BIGMETA
Bit::htobll(data + 17, newTime);
#else
Bit::htobl(data + 12, newTime);
#endif
}
///\brief Returns the data of this keyframe struct
@ -1036,38 +1005,22 @@ namespace DTSC {
///\brief Returns the number of the first keyframe in this fragment
unsigned long Fragment::getNumber() {
#ifdef BIGMETA
return Bit::btohl(data + 5);
#else
return Bit::btohs(data + 5);
#endif
}
///\brief Sets the number of the first keyframe in this fragment
void Fragment::setNumber(unsigned long newNumber) {
#ifdef BIGMETA
Bit::htobl(data + 5, newNumber);
#else
Bit::htobs(data + 5, newNumber);
#endif
}
///\brief Returns the size of a fragment
unsigned long Fragment::getSize() {
#ifdef BIGMETA
return Bit::btohl(data + 9);
#else
return Bit::btohl(data + 7);
#endif
}
///\brief Sets the size of a fragement
void Fragment::setSize(unsigned long newSize) {
#ifdef BIGMETA
Bit::htobl(data + 9, newSize);
#else
Bit::htobl(data + 7, newSize);
#endif
}
///\brief Returns thte data of this fragment structure
@ -1348,6 +1301,7 @@ namespace DTSC {
Meta::Meta() {
vod = false;
live = false;
version = DTSH_VERSION;
moreheader = 0;
merged = false;
bufferWindow = 0;
@ -1361,6 +1315,7 @@ namespace DTSC {
tracks.clear();
vod = source.getFlag("vod");
live = source.getFlag("live");
version = source.getInt("version");
merged = source.getFlag("merged");
bufferWindow = source.getInt("buffer_window");
moreheader = source.getInt("moreheader");
@ -1383,6 +1338,7 @@ namespace DTSC {
Meta::Meta(JSON::Value & meta) {
vod = meta.isMember("vod") && meta["vod"];
live = meta.isMember("live") && meta["live"];
version = meta.isMember("version") ? meta["version"].asInt() : 0;
merged = meta.isMember("merged") && meta["merged"];
bufferWindow = 0;
if (meta.isMember("buffer_window")) {
@ -1798,6 +1754,7 @@ namespace DTSC {
dataLen += it->second.getSendLen(skipDynamic);
}
}
if (version){dataLen += 17;}
return dataLen + 8; //add 8 bytes header
}
@ -1823,6 +1780,10 @@ namespace DTSC {
writePointer(p, "\000\006merged\001", 9);
writePointer(p, convertLongLong(1), 8);
}
if (version) {
writePointer(p, "\000\006version\001", 9);
writePointer(p, convertLongLong(version), 8);
}
if (bufferWindow) {
writePointer(p, "\000\015buffer_window\001", 16);
writePointer(p, convertLongLong(bufferWindow), 8);
@ -1856,6 +1817,10 @@ namespace DTSC {
conn.SendNow("\000\006merged\001", 9);
conn.SendNow(convertLongLong(1), 8);
}
if (version) {
conn.SendNow("\000\006version\001", 9);
conn.SendNow(convertLongLong(version), 8);
}
if (bufferWindow) {
conn.SendNow("\000\015buffer_window\001", 16);
conn.SendNow(convertLongLong(bufferWindow), 8);
@ -1948,10 +1913,20 @@ namespace DTSC {
if (bufferWindow) {
result["buffer_window"] = bufferWindow;
}
if (version) {
result["version"] = (long long)version;
}
result["moreheader"] = moreheader;
return result;
}
///\brief Writes metadata to a filename. Wipes existing contents, if any.
bool Meta::toFile(const std::string & fileName){
std::ofstream oFile(fileName.c_str());
oFile << toJSON().toNetPacked();
oFile.close();
}
///\brief Converts a meta object to a human readable string
///\param str The stringstream to append to
///\param indent the amount of indentation needed

View file

@ -17,17 +17,17 @@ namespace Util {
private:
static bool childRunning(pid_t p);
static tthread::mutex plistMutex;
static tthread::thread * reaper_thread;
static std::set<pid_t> plist; ///< Holds active process list.
static bool handler_set; ///< If true, the sigchld handler has been setup.
static bool thread_handler;///< True while thread handler should be running.
static void childsig_handler(int signum);
static void exit_handler();
static void runCmd(std::string & cmd);
static void setHandler();
static char* const* dequeToArgv(std::deque<std::string> & argDeq);
static void grim_reaper(void * n);
public:
static tthread::thread * reaper_thread;
static bool handler_set; ///< If true, the sigchld handler has been setup.
static void setHandler();
static std::string getOutputOf(char * const * argv);
static std::string getOutputOf(std::deque<std::string> & argDeq);
static pid_t StartPiped(char * const * argv, int * fdin, int * fdout, int * fderr);

View file

@ -537,9 +537,14 @@ bool RTMPStream::doHandshake() {
Secure::hmac_sha256bin(pTempBuffer, 1504, genuineFMSKey, 36, (char*)Server + serverDigestOffset);
//SECOND 1536 bytes for server response
char pTempHash[32];
Secure::hmac_sha256bin((char*)Client + keyChallengeIndex, 32, genuineFMSKey, 68, pTempHash);
Secure::hmac_sha256bin((char*)Server + 1536, 1536 - 32, pTempHash, 32, (char*)Server + 1536 * 2 - 32);
if (_validationScheme == 5 && Version == 3){
//copy exactly from client
memcpy(Server+1536, Client, 1536);
}else{
char pTempHash[32];
Secure::hmac_sha256bin((char*)Client + keyChallengeIndex, 32, genuineFMSKey, 68, pTempHash);
Secure::hmac_sha256bin((char*)Server + 1536, 1536 - 32, pTempHash, 32, (char*)Server + 1536 * 2 - 32);
}
Server[ -1] = Version;
RTMPStream::snd_cnt += 3073;

View file

@ -22,6 +22,11 @@
#endif
/// Forces a disconnect to all users.
static void killStatistics(char * data, size_t len, unsigned int id){
(*(data - 1)) = 60 | ((*(data - 1))&0x80);//Send disconnect message;
}
namespace IPC {
#if defined(__CYGWIN__) || defined(_WIN32)
@ -776,7 +781,6 @@ namespace IPC {
///\brief The deconstructor
sharedServer::~sharedServer() {
finishEach();
mySemaphore.close();
mySemaphore.unlink();
}
@ -833,21 +837,16 @@ namespace IPC {
return false;
}
///Disconnect all connected users
///Disconnect all connected users, waits at most 2.5 seconds until completed
void sharedServer::finishEach(){
if (!hasCounter){
return;
}
for (std::set<sharedPage>::iterator it = myPages.begin(); it != myPages.end(); it++) {
if (!it->mapped || !it->len) {
break;
}
unsigned int offset = 0;
while (offset + payLen + (hasCounter ? 1 : 0) <= it->len) {
it->mapped[offset] = 126;
offset += payLen + (hasCounter ? 1 : 0);
}
}
unsigned int c = 0;//to prevent eternal loops
do{
parseEach(killStatistics);
Util::wait(250);
}while(amount && c++ < 10);
}
///Returns a pointer to the data for the given index.
@ -917,17 +916,18 @@ namespace IPC {
if (*counter & 0x80){
connectedUsers++;
}
char countNum = (*counter) & 0x7F;
if (id >= amount) {
amount = id + 1;
VERYHIGH_MSG("Shared memory %s is now at count %u", baseName.c_str(), amount);
}
uint32_t tmpPID = *((uint32_t *)(it->mapped + 1 + offset + payLen - 4));
if (!Util::Procs::isRunning(tmpPID) && !(*counter == 126 || *counter == 127)){
if (!Util::Procs::isRunning(tmpPID) && !(countNum == 126 || countNum == 127)){
WARN_MSG("process disappeared, timing out. (pid %lu)", tmpPID);
*counter = 126; //if process is already dead, instant timeout.
*counter = 125 | (0x80 & (*counter)); //if process is already dead, instant timeout.
}
callback(it->mapped + offset + 1, payLen, id);
switch (*counter) {
switch (countNum) {
case 127:
HIGH_MSG("Client %u requested disconnect", id);
break;
@ -937,9 +937,9 @@ namespace IPC {
default:
#ifndef NOCRASHCHECK
if (tmpPID) {
if (*counter > 10 && *counter < 126) {
if (*counter < 30) {
if (*counter > 15) {
if (countNum > 10 && countNum < 60) {
if (countNum < 30) {
if (countNum > 15) {
WARN_MSG("Process %d is unresponsive", tmpPID);
}
Util::Procs::Stop(tmpPID); //soft kill
@ -948,11 +948,22 @@ namespace IPC {
Util::Procs::Murder(tmpPID); //improved kill
}
}
if (countNum > 70) {
if (countNum < 90) {
if (countNum > 75) {
WARN_MSG("Stopping process %d is unresponsive", tmpPID);
}
Util::Procs::Stop(tmpPID); //soft kill
} else {
ERROR_MSG("Killing unresponsive stopping process %d", tmpPID);
Util::Procs::Murder(tmpPID); //improved kill
}
}
}
#endif
break;
}
if (*counter == 127 || *counter == 126){
if (countNum == 127 || countNum == 126){
memset(it->mapped + offset + 1, 0, payLen);
it->mapped[offset] = 0;
} else {
@ -1153,7 +1164,7 @@ namespace IPC {
}
if (myPage.mapped) {
semGuard tmpGuard(&mySemaphore);
myPage.mapped[offsetOnPage] = 126;
myPage.mapped[offsetOnPage] = 126 | (countAsViewer?0x80:0);
HIGH_MSG("sharedClient finished ID %d", offsetOnPage/(payLen+1));
}
}
@ -1164,16 +1175,19 @@ namespace IPC {
DEBUG_MSG(DLVL_WARN, "Trying to keep-alive an element without counters");
return;
}
if ((myPage.mapped[offsetOnPage] & 0x7F) < 126) {
if (isAlive()){
myPage.mapped[offsetOnPage] = (countAsViewer ? 0x81 : 0x01);
}
}
bool sharedClient::isAlive() {
if (!hasCounter) {
return true;
return (myPage.mapped != 0);
}
return (myPage.mapped[offsetOnPage] & 0x7F) < 126;
if (myPage.mapped){
return (myPage.mapped[offsetOnPage] & 0x7F) < 60;
}
return false;
}
///\brief Get a pointer to the data of this client

View file

@ -186,6 +186,7 @@ namespace IPC {
///\brief The amount of connected clients
unsigned int amount;
unsigned int connectedUsers;
void finishEach();
private:
bool isInUse(unsigned int id);
void newPage();
@ -200,7 +201,6 @@ namespace IPC {
semaphore mySemaphore;
///\brief Whether the payload has a counter, if so, it is added in front of the payload
bool hasCounter;
void finishEach();
};
///\brief The client part of a server/client model for shared memory.