Merge branch 'development' into LTS_development
This commit is contained in:
commit
28106cf396
5 changed files with 116 additions and 37 deletions
107
lib/json.cpp
107
lib/json.cpp
|
@ -162,9 +162,34 @@ static inline char hex2c(char c) {
|
||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string UTF8(uint32_t c){
|
||||||
|
std::string r;
|
||||||
|
if (c <= 0x7F){
|
||||||
|
r.append(1, c);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (c <= 0x7FF){
|
||||||
|
r.append(1, 0xC0 | (c >> 6));
|
||||||
|
r.append(1, 0x80 | (c & 0x3F));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (c <= 0x7FF){
|
||||||
|
r.append(1, 0xC0 | (c >> 12));
|
||||||
|
r.append(1, 0x80 | ((c >> 6) & 0x3F));
|
||||||
|
r.append(1, 0x80 | (c & 0x3F));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
r.append(1, 0xC0 | (c >> 18));
|
||||||
|
r.append(1, 0x80 | ((c >> 12) & 0x3F));
|
||||||
|
r.append(1, 0x80 | ((c >> 6) & 0x3F));
|
||||||
|
r.append(1, 0x80 | (c & 0x3F));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static std::string read_string(int separator, std::istream & fromstream) {
|
static std::string read_string(int separator, std::istream & fromstream) {
|
||||||
std::string out;
|
std::string out;
|
||||||
bool escaped = false;
|
bool escaped = false;
|
||||||
|
uint32_t fullChar = 0;
|
||||||
while (fromstream.good()) {
|
while (fromstream.good()) {
|
||||||
char c;
|
char c;
|
||||||
fromstream.get(c);
|
fromstream.get(c);
|
||||||
|
@ -173,6 +198,10 @@ static std::string read_string(int separator, std::istream & fromstream) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (escaped) {
|
if (escaped) {
|
||||||
|
if (fullChar && c != 'u'){
|
||||||
|
out += UTF8(fullChar >> 16);
|
||||||
|
fullChar = 0;
|
||||||
|
}
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
out += '\b';
|
out += '\b';
|
||||||
|
@ -189,15 +218,32 @@ static std::string read_string(int separator, std::istream & fromstream) {
|
||||||
case 't':
|
case 't':
|
||||||
out += '\t';
|
out += '\t';
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
char d1, d2;
|
||||||
|
fromstream.get(d1);
|
||||||
|
fromstream.get(d2);
|
||||||
|
out.append(1, (c2hex(d2) + (c2hex(d1) << 4)));
|
||||||
|
break;
|
||||||
case 'u': {
|
case 'u': {
|
||||||
char d1, d2, d3, d4;
|
char d1, d2, d3, d4;
|
||||||
fromstream.get(d1);
|
fromstream.get(d1);
|
||||||
fromstream.get(d2);
|
fromstream.get(d2);
|
||||||
fromstream.get(d3);
|
fromstream.get(d3);
|
||||||
fromstream.get(d4);
|
fromstream.get(d4);
|
||||||
out.append(1, (c2hex(d4) + (c2hex(d3) << 4)));
|
uint32_t tmpChar = (c2hex(d4) + (c2hex(d3) << 4) + (c2hex(d2) << 8) + (c2hex(d1) << 16));
|
||||||
//We ignore the upper two characters.
|
if (fullChar && (tmpChar < 0xDC00 || tmpChar > 0xDFFF)){
|
||||||
// + (c2hex(d2) << 8) + (c2hex(d1) << 16)
|
//not a low surrogate - handle high surrogate separately!
|
||||||
|
out += UTF8(fullChar >> 16);
|
||||||
|
fullChar = 0;
|
||||||
|
}
|
||||||
|
fullChar |= tmpChar;
|
||||||
|
if (fullChar >= 0xD800 && fullChar <= 0xDBFF){
|
||||||
|
//possibly high surrogate! Read next characters before handling...
|
||||||
|
fullChar <<= 16;//save as high surrogate
|
||||||
|
}else{
|
||||||
|
out += UTF8(fullChar);
|
||||||
|
fullChar = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -206,6 +252,10 @@ static std::string read_string(int separator, std::istream & fromstream) {
|
||||||
}
|
}
|
||||||
escaped = false;
|
escaped = false;
|
||||||
} else {
|
} else {
|
||||||
|
if (fullChar){
|
||||||
|
out += UTF8(fullChar >> 16);
|
||||||
|
fullChar = 0;
|
||||||
|
}
|
||||||
if (c == separator) {
|
if (c == separator) {
|
||||||
return out;
|
return out;
|
||||||
} else {
|
} else {
|
||||||
|
@ -213,13 +263,32 @@ static std::string read_string(int separator, std::istream & fromstream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fullChar){
|
||||||
|
out += UTF8(fullChar >> 16);
|
||||||
|
fullChar = 0;
|
||||||
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string UTF16(uint32_t c){
|
||||||
|
if (c > 0xFFFF){
|
||||||
|
c -= 0x010000;
|
||||||
|
return UTF16(0xD800 + ((c >> 10) & 0x3FF)) + UTF16(0xDC00 + (c & 0x3FF));
|
||||||
|
}else{
|
||||||
|
std::string ret = "\\u";
|
||||||
|
ret += hex2c((c >> 12) & 0xf);
|
||||||
|
ret += hex2c((c >> 8) & 0xf);
|
||||||
|
ret += hex2c((c >> 4) & 0xf);
|
||||||
|
ret += hex2c(c & 0xf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static std::string string_escape(const std::string val) {
|
static std::string string_escape(const std::string val) {
|
||||||
std::string out = "\"";
|
std::string out = "\"";
|
||||||
for (unsigned int i = 0; i < val.size(); ++i) {
|
for (unsigned int i = 0; i < val.size(); ++i) {
|
||||||
switch (val.data()[i]) {
|
const char & c = val.data()[i];
|
||||||
|
switch (c) {
|
||||||
case '"':
|
case '"':
|
||||||
out += "\\\"";
|
out += "\\\"";
|
||||||
break;
|
break;
|
||||||
|
@ -242,7 +311,35 @@ static std::string string_escape(const std::string val) {
|
||||||
out += "\\t";
|
out += "\\t";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (val.data()[i] < 32 || val.data()[i] > 126) {
|
if (c < 32 || c > 126) {
|
||||||
|
//we assume our data is UTF-8 encoded internally.
|
||||||
|
//JavaScript expects UTF-16, so if we recognize a valid UTF-8 sequence, we turn it into UTF-16 for JavaScript.
|
||||||
|
//Anything else is escaped as a single character UTF-16 escape.
|
||||||
|
if ((c & 0xC0) == 0xC0){
|
||||||
|
//possible UTF-8 sequence
|
||||||
|
//check for 2-byte sequence
|
||||||
|
if (((c & 0xE0) == 0XC0) && (i+1 < val.size()) && ((val.data()[i+1] & 0xC0) == 0x80)){
|
||||||
|
//valid 2-byte sequence
|
||||||
|
out += UTF16(((c & 0x1F) << 6) | (val.data()[i+1] & 0x3F));
|
||||||
|
i += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//check for 3-byte sequence
|
||||||
|
if (((c & 0xF0) == 0XE0) && (i+2 < val.size()) && ((val.data()[i+1] & 0xC0) == 0x80) && ((val.data()[i+2] & 0xC0) == 0x80)){
|
||||||
|
//valid 3-byte sequence
|
||||||
|
out += UTF16(((c & 0x1F) << 12) | ((val.data()[i+1] & 0x3F) << 6) | (val.data()[i+2] & 0x3F));
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//check for 4-byte sequence
|
||||||
|
if (((c & 0xF8) == 0XF0) && (i+3 < val.size()) && ((val.data()[i+1] & 0xC0) == 0x80) && ((val.data()[i+2] & 0xC0) == 0x80) && ((val.data()[i+3] & 0xC0) == 0x80)){
|
||||||
|
//valid 4-byte sequence
|
||||||
|
out += UTF16(((c & 0x1F) << 18) | ((val.data()[i+1] & 0x3F) << 12) | ((val.data()[i+2] & 0x3F) << 6) | (val.data()[i+3] & 0x3F));
|
||||||
|
i += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Anything else, we encode as a single UTF-16 character.
|
||||||
out += "\\u00";
|
out += "\\u00";
|
||||||
out += hex2c((val.data()[i] >> 4) & 0xf);
|
out += hex2c((val.data()[i] >> 4) & 0xf);
|
||||||
out += hex2c(val.data()[i] & 0xf);
|
out += hex2c(val.data()[i] & 0xf);
|
||||||
|
|
|
@ -237,6 +237,14 @@ void Socket::Connection::resetCounter(){
|
||||||
down = 0;
|
down = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Socket::Connection::addUp(const uint32_t i){
|
||||||
|
up += i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::Connection::addDown(const uint32_t i){
|
||||||
|
down += i;
|
||||||
|
}
|
||||||
|
|
||||||
/// Internally used call to make an file descriptor blocking or not.
|
/// Internally used call to make an file descriptor blocking or not.
|
||||||
void setFDBlocking(int FD, bool blocking){
|
void setFDBlocking(int FD, bool blocking){
|
||||||
int flags = fcntl(FD, F_GETFL, 0);
|
int flags = fcntl(FD, F_GETFL, 0);
|
||||||
|
|
|
@ -94,6 +94,8 @@ namespace Socket{
|
||||||
uint64_t dataUp(); ///< Returns total amount of bytes sent.
|
uint64_t dataUp(); ///< Returns total amount of bytes sent.
|
||||||
uint64_t dataDown(); ///< Returns total amount of bytes received.
|
uint64_t dataDown(); ///< Returns total amount of bytes received.
|
||||||
void resetCounter(); ///< Resets the up/down bytes counter to zero.
|
void resetCounter(); ///< Resets the up/down bytes counter to zero.
|
||||||
|
void addUp(const uint32_t i);
|
||||||
|
void addDown(const uint32_t i);
|
||||||
std::string getStats(std::string C); ///< Returns a std::string of stats, ended by a newline.
|
std::string getStats(std::string C); ///< Returns a std::string of stats, ended by a newline.
|
||||||
friend class Server;
|
friend class Server;
|
||||||
bool Error; ///< Set to true if a socket error happened.
|
bool Error; ///< Set to true if a socket error happened.
|
||||||
|
|
|
@ -459,39 +459,11 @@ namespace Mist{
|
||||||
selected << (*it);
|
selected << (*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEBUG_MSG(DLVL_MEDIUM, "Selected tracks: %s (%lu)", selected.str().c_str(), selectedTracks.size());
|
MEDIUM_MSG("Selected tracks: %s (%lu)", selected.str().c_str(), selectedTracks.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedTracks.size() == 0){
|
if (!selectedTracks.size() && myMeta.tracks.size()){
|
||||||
INSANE_MSG("We didn't find any tracks which that we can use. selectedTrack.size() is 0.");
|
WARN_MSG("No tracks selected (%u total) for stream %s!", myMeta.tracks.size(), streamName.c_str());
|
||||||
for (std::map<unsigned int,DTSC::Track>::iterator trit = myMeta.tracks.begin(); trit != myMeta.tracks.end(); trit++){
|
|
||||||
INSANE_MSG("Found track/codec: %s", trit->second.codec.c_str());
|
|
||||||
}
|
|
||||||
static std::string source;
|
|
||||||
if (!myMeta.tracks.size() && !source.size()){
|
|
||||||
IPC::sharedPage serverCfg(SHM_CONF, DEFAULT_CONF_PAGE_SIZE, false, false); ///< Contains server configuration and capabilities
|
|
||||||
IPC::semaphore configLock(SEM_CONF, O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
|
||||||
configLock.wait();
|
|
||||||
std::string smp = streamName.substr(0, streamName.find_first_of("+ "));
|
|
||||||
//check if smp (everything before + or space) exists
|
|
||||||
DTSC::Scan streamCfg = DTSC::Scan(serverCfg.mapped, serverCfg.len).getMember("streams").getMember(smp);
|
|
||||||
if (streamCfg){
|
|
||||||
source = streamCfg.getMember("source").asString();
|
|
||||||
}
|
|
||||||
configLock.post();
|
|
||||||
configLock.close();
|
|
||||||
}
|
|
||||||
if (!myMeta.tracks.size() && (source.find("dtsc://") == 0)){
|
|
||||||
//Wait 5 seconds and try again. Keep a counter, try at most 3 times
|
|
||||||
static int counter = 0;
|
|
||||||
if (counter++ < 10){
|
|
||||||
Util::wait(1000);
|
|
||||||
nProxy.userClient.keepAlive();
|
|
||||||
stats();
|
|
||||||
updateMeta();
|
|
||||||
selectDefaultTracks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Mist {
|
||||||
void parseChunk(Socket::Buffer & inputBuffer);
|
void parseChunk(Socket::Buffer & inputBuffer);
|
||||||
void parseAMFCommand(AMF::Object & amfData, int messageType, int streamId);
|
void parseAMFCommand(AMF::Object & amfData, int messageType, int streamId);
|
||||||
void sendCommand(AMF::Object & amfReply, int messageType, int streamId);
|
void sendCommand(AMF::Object & amfReply, int messageType, int streamId);
|
||||||
virtual std::string getStatsName();
|
std::string getStatsName();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue