Such style. (Code style unification)

This commit is contained in:
Thulinma 2014-06-18 10:39:27 +02:00
parent 57bcd8f25c
commit 8c01ec8897
57 changed files with 6548 additions and 6437 deletions

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
namespace AMF {
/// Enumerates all possible AMF0 types, adding a special DDVTECH container type for ease of use.
enum obj0type{
enum obj0type {
AMF0_NUMBER = 0x00,
AMF0_BOOL = 0x01,
AMF0_STRING = 0x02,
@ -33,7 +33,7 @@ namespace AMF {
};
/// Enumerates all possible AMF3 types, adding a special DDVTECH container type for ease of use.
enum obj3type{
enum obj3type {
AMF3_UNDEFINED = 0x00,
AMF3_NULL = 0x01,
AMF3_FALSE = 0x02,
@ -52,7 +52,7 @@ namespace AMF {
/// Recursive class that holds AMF0 objects.
/// It supports all AMF0 types (defined in AMF::obj0type), adding support for a special DDVTECH container type.
class Object{
class Object {
public:
std::string Indice();
obj0type GetType();
@ -61,9 +61,9 @@ namespace AMF {
const char * Str();
int hasContent();
void addContent(AMF::Object c);
Object* getContentP(unsigned int i);
Object * getContentP(unsigned int i);
Object getContent(unsigned int i);
Object* getContentP(std::string s);
Object * getContentP(std::string s);
Object getContent(std::string s);
Object();
Object(std::string indice, double val, obj0type setType = AMF0_NUMBER);
@ -85,11 +85,11 @@ namespace AMF {
/// Parses a std::string to a valid AMF::Object.
Object parse(std::string data);
/// Parses a single AMF0 type - used recursively by the AMF::parse() functions.
Object parseOne(const unsigned char *& data, unsigned int &len, unsigned int &i, std::string name);
Object parseOne(const unsigned char *& data, unsigned int & len, unsigned int & i, std::string name);
/// Recursive class that holds AMF3 objects.
/// It supports all AMF3 types (defined in AMF::obj3type), adding support for a special DDVTECH container type.
class Object3{
class Object3 {
public:
std::string Indice();
obj3type GetType();
@ -99,9 +99,9 @@ namespace AMF {
const char * Str();
int hasContent();
void addContent(AMF::Object3 c);
Object3* getContentP(int i);
Object3 * getContentP(int i);
Object3 getContent(int i);
Object3* getContentP(std::string s);
Object3 * getContentP(std::string s);
Object3 getContent(std::string s);
Object3();
Object3(std::string indice, int val, obj3type setType = AMF3_INTEGER);
@ -125,6 +125,6 @@ namespace AMF {
/// Parses a std::string to a valid AMF::Object3.
Object3 parse3(std::string data);
/// Parses a single AMF3 type - used recursively by the AMF::parse3() functions.
Object3 parseOne3(const unsigned char *& data, unsigned int &len, unsigned int &i, std::string name);
Object3 parseOne3(const unsigned char *& data, unsigned int & len, unsigned int & i, std::string name);
} //AMF namespace

View file

@ -20,29 +20,30 @@ namespace Secure {
0xe5, 0x16, 0x01, 0xf1, 0x98, 0xc9, 0x0b, 0xd6, 0xdf, 0x8a, 0x64, 0x47, 0xc4, 0x44, 0xcc, 0x92, 0x69, 0x28, 0xee, 0x7d, 0xac, 0xdc, 0x30, 0x56,
0x3a, 0xe7, 0xbc, 0xba, 0x45, 0x16, 0x2c, 0x4c, 0x46, 0x6b, 0x2b, 0x20, 0xfb, 0x3d, 0x20, 0x35, 0xbb, 0x48, 0x49, 0x13, 0x65, 0xc9, 0x9a, 0x38,
0x10, 0x84, 0x1a, 0x8c, 0xc9, 0xd7, 0xde, 0x07, 0x10, 0x5a, 0xfb, 0xb4, 0x95, 0xae, 0x18, 0xf2, 0xe3, 0x15, 0xe8, 0xad, 0x7e, 0xe5, 0x3c, 0xa8,
0x47, 0x85, 0xd6, 0x1f, 0x54, 0xb5, 0xa3, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01}; ///< The GBv2 public key file.
0x47, 0x85, 0xd6, 0x1f, 0x54, 0xb5, 0xa3, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01
}; ///< The GBv2 public key file.
static unsigned int __gbv2keypub_der_len = 294; ///< Length of GBv2 public key data
/// Attempts to load the GBv2 public key.
Auth::Auth(){
Auth::Auth() {
const unsigned char * key = __gbv2keypub_der;
pubkey = (void*)d2i_RSAPublicKey(0, &key, __gbv2keypub_der_len);
pubkey = (void *)d2i_RSAPublicKey(0, &key, __gbv2keypub_der_len);
}
/// Attempts to verify RSA signature using the public key.
/// Assumes basesign argument is base64 encoded RSA signature for data.
/// Returns true if the data could be verified, false otherwise.
bool Auth::PubKey_Check(std::string & data, std::string basesign){
bool Auth::PubKey_Check(std::string & data, std::string basesign) {
std::string sign = Base64::decode(basesign);
return (RSA_verify(NID_md5, (unsigned char*)data.c_str(), data.size(), (unsigned char*)sign.c_str(), sign.size(), (RSA*)pubkey) == 1);
return (RSA_verify(NID_md5, (unsigned char *)data.c_str(), data.size(), (unsigned char *)sign.c_str(), sign.size(), (RSA *)pubkey) == 1);
}
/// Wrapper function for openssl MD5 implementation
std::string md5(std::string input){
std::string md5(std::string input) {
char tmp[3];
std::string ret;
const unsigned char * res = MD5((const unsigned char*)input.c_str(), input.length(), 0);
for (int i = 0; i < 16; ++i){
const unsigned char * res = MD5((const unsigned char *)input.c_str(), input.length(), 0);
for (int i = 0; i < 16; ++i) {
snprintf(tmp, 3, "%02x", res[i]);
ret += tmp;
}

View file

@ -2,7 +2,7 @@
#include <string>
namespace Secure {
class Auth{
class Auth {
private:
void * pubkey; ///< Holds the public key.
public:

View file

@ -4,39 +4,39 @@
const std::string Base64::chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/// Helper for base64_decode function
inline bool Base64::is_base64(unsigned char c){
inline bool Base64::is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
/// Used to base64 encode data. Input is the plaintext as std::string, output is the encoded data as std::string.
/// \param input Plaintext data to encode.
/// \returns Base64 encoded data.
std::string Base64::encode(std::string const input){
std::string Base64::encode(std::string const input) {
std::string ret;
unsigned int in_len = input.size();
char quad[4], triple[3];
unsigned int i, x, n = 3;
for (x = 0; x < in_len; x = x + 3){
if ((in_len - x) / 3 == 0){
for (x = 0; x < in_len; x = x + 3) {
if ((in_len - x) / 3 == 0) {
n = (in_len - x) % 3;
}
for (i = 0; i < 3; i++){
for (i = 0; i < 3; i++) {
triple[i] = '0';
}
for (i = 0; i < n; i++){
for (i = 0; i < n; i++) {
triple[i] = input[x + i];
}
quad[0] = chars[(triple[0] & 0xFC) >> 2]; // FC = 11111100
quad[1] = chars[((triple[0] & 0x03) << 4) | ((triple[1] & 0xF0) >> 4)]; // 03 = 11
quad[2] = chars[((triple[1] & 0x0F) << 2) | ((triple[2] & 0xC0) >> 6)]; // 0F = 1111, C0=11110
quad[3] = chars[triple[2] & 0x3F]; // 3F = 111111
if (n < 3){
if (n < 3) {
quad[3] = '=';
}
if (n < 2){
if (n < 2) {
quad[2] = '=';
}
for (i = 0; i < 4; i++){
for (i = 0; i < 4; i++) {
ret += quad[i];
}
}
@ -46,34 +46,34 @@ std::string Base64::encode(std::string const input){
/// Used to base64 decode data. Input is the encoded data as std::string, output is the plaintext data as std::string.
/// \param encoded_string Base64 encoded data to decode.
/// \returns Plaintext decoded data.
std::string Base64::decode(std::string const& encoded_string){
std::string Base64::decode(std::string const & encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])){
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++ ] = encoded_string[in_];
in_++;
if (i == 4){
for (i = 0; i < 4; i++){
if (i == 4) {
for (i = 0; i < 4; i++) {
char_array_4[i] = chars.find(char_array_4[i]);
}
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++){
for (i = 0; (i < 3); i++) {
ret += char_array_3[i];
}
i = 0;
}
}
if (i){
for (j = i; j < 4; j++){
if (i) {
for (j = i; j < 4; j++) {
char_array_4[j] = 0;
}
for (j = 0; j < 4; j++){
for (j = 0; j < 4; j++) {
char_array_4[j] = chars.find(char_array_4[j]);
}
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);

View file

@ -2,11 +2,11 @@
#include <string>
/// Holds base64 decoding and encoding functions.
class Base64{
class Base64 {
private:
static const std::string chars;
static inline bool is_base64(unsigned char c);
public:
static std::string encode(std::string const input);
static std::string decode(std::string const& encoded_string);
static std::string decode(std::string const & encoded_string);
};

View file

@ -3,51 +3,51 @@
#include <stdlib.h>
#include <string.h>
namespace Utils{
bitstream::bitstream(){
namespace Utils {
bitstream::bitstream() {
data = NULL;
offset = 0;
dataSize = 0;
bufferSize = 0;
}
bool bitstream::checkBufferSize(unsigned int size){
if (size > bufferSize){
void* temp = realloc(data, size);
if (temp){
data = (char*) temp;
bool bitstream::checkBufferSize(unsigned int size) {
if (size > bufferSize) {
void * temp = realloc(data, size);
if (temp) {
data = (char *) temp;
bufferSize = size;
return true;
}else{
} else {
return false;
}
}else{
} else {
return true;
}
}
void bitstream::append(char* input, size_t bytes){
if (checkBufferSize(dataSize+bytes)){
memcpy(data+dataSize, input, bytes);
void bitstream::append(char * input, size_t bytes) {
if (checkBufferSize(dataSize + bytes)) {
memcpy(data + dataSize, input, bytes);
dataSize += bytes;
}
}
void bitstream::append(std::string input){
append((char*)input.c_str(), input.size());
void bitstream::append(std::string input) {
append((char *)input.c_str(), input.size());
}
bool bitstream::peekOffset(size_t peekOffset){
bool bitstream::peekOffset(size_t peekOffset) {
peekOffset += offset;
return ((data[peekOffset >> 3]) >> (7 - (peekOffset & 7))) & 1;
}
long long unsigned int bitstream::peek(size_t count){
if (count > 64){
long long unsigned int bitstream::peek(size_t count) {
if (count > 64) {
DEBUG_MSG(DLVL_WARN, "Can not read %d bits into a long long unsigned int!", (int)count);
//return 0;
}
if (count > size()){
if (count > size()) {
DEBUG_MSG(DLVL_ERROR, "Not enough bits left in stream. Left: %d requested: %d", (int)size(), (int)count);
return 0;
}
@ -56,11 +56,11 @@ namespace Utils{
size_t readSize;
size_t readOff;
char readBuff;
while (curPlace < count){
readBuff = data[(int)((offset+curPlace)/8)];
while (curPlace < count) {
readBuff = data[(int)((offset + curPlace) / 8)];
readSize = 8;
readOff = (offset + curPlace) % 8; //the reading offset within the byte
if (readOff != 0){
if (readOff != 0) {
//if we start our read not on the start of a byte
//curplace and retval should both be 0
//this should be the first read that aligns reading to bytes, if we read over the end of read byte
@ -69,7 +69,7 @@ namespace Utils{
readBuff = readBuff & ((1 << readSize) - 1);//bitmasking
}
//up until here we assume we read to the end of the byte
if (count - curPlace < readSize){//if we do not read to the end of the byte
if (count - curPlace < readSize) { //if we do not read to the end of the byte
//we cut off the LSb off of the read buffer by bitshift
readSize = count - curPlace;
readBuff = readBuff >> (8 - readSize - readOff);
@ -80,98 +80,98 @@ namespace Utils{
return retval;
}
long long unsigned int bitstream::get(size_t count){
if(count <= size()){
long long unsigned int bitstream::get(size_t count) {
if (count <= size()) {
long long unsigned int retVal;
retVal = peek(count);
skip(count);
return retVal;
}else{
} else {
return 0;
}
}
void bitstream::skip(size_t count){
if(count <= size()){
void bitstream::skip(size_t count) {
if (count <= size()) {
offset += count;
}else{
offset = dataSize*8;
} else {
offset = dataSize * 8;
}
}
long long unsigned int bitstream::size(){
long long unsigned int bitstream::size() {
return (dataSize * 8) - offset;
}
void bitstream::clear(){
void bitstream::clear() {
dataSize = 0;
offset = 0;
}
void bitstream::flush(){
memmove(data, data + (offset/8), dataSize - (offset/8));
void bitstream::flush() {
memmove(data, data + (offset / 8), dataSize - (offset / 8));
dataSize -= offset / 8;
offset %= 8;
}
long long unsigned int bitstream::golombPeeker(){
for (size_t i = 0; i < 64 && i < size(); i++){
if (peekOffset(i)){
return peek((i * 2) + 1 );
long long unsigned int bitstream::golombPeeker() {
for (size_t i = 0; i < 64 && i < size(); i++) {
if (peekOffset(i)) {
return peek((i * 2) + 1);
}
}
return 0;
}
long long unsigned int bitstream::golombGetter(){
for (size_t i = 0; i < 64 && i < size(); i++){
if (peekOffset(i)){
long long unsigned int bitstream::golombGetter() {
for (size_t i = 0; i < 64 && i < size(); i++) {
if (peekOffset(i)) {
return get((i * 2) + 1);
}
}
return 0;
}
long long int bitstream::getExpGolomb(){
long long int bitstream::getExpGolomb() {
long long unsigned int temp = golombGetter();
return (temp >> 1) * (1 - ((temp & 1) << 1)); //Is actually return (temp / 2) * (1 - (temp & 1) * 2);
}
long long unsigned int bitstream::getUExpGolomb(){
long long unsigned int bitstream::getUExpGolomb() {
return golombGetter() - 1;
}
long long int bitstream::peekExpGolomb(){
long long int bitstream::peekExpGolomb() {
long long unsigned int temp = golombPeeker();
return (temp >> 1) * (1 - ((temp & 1) << 1)); //Is actually return (temp / 2) * (1 - (temp & 1) * 2);
}
long long unsigned int bitstream::peekUExpGolomb(){
long long unsigned int bitstream::peekUExpGolomb() {
return golombPeeker() - 1;
}
//Note: other bitstream here
bitstreamLSBF::bitstreamLSBF(){
bitstreamLSBF::bitstreamLSBF() {
readBufferOffset = 0;
readBuffer = 0;
}
void bitstreamLSBF::append (char* input, size_t bytes){
append(std::string(input,bytes));
void bitstreamLSBF::append(char * input, size_t bytes) {
append(std::string(input, bytes));
}
void bitstreamLSBF::append (std::string input){
void bitstreamLSBF::append(std::string input) {
data += input;
fixData();
}
long long unsigned int bitstreamLSBF::size(){
long long unsigned int bitstreamLSBF::size() {
return data.size() * 8 + readBufferOffset;
}
long long unsigned int bitstreamLSBF::get(size_t count){
if (count <= 32 && count <= readBufferOffset){
long long unsigned int bitstreamLSBF::get(size_t count) {
if (count <= 32 && count <= readBufferOffset) {
long long unsigned int retval = readBuffer & (((long long unsigned int)1 << count) - 1);
readBuffer = readBuffer >> count;
readBufferOffset -= count;
@ -181,29 +181,29 @@ namespace Utils{
return 42;
}
void bitstreamLSBF::skip(size_t count){
if (count <= 32 && count <= readBufferOffset){
void bitstreamLSBF::skip(size_t count) {
if (count <= 32 && count <= readBufferOffset) {
readBuffer = readBuffer >> count;
readBufferOffset -= count;
fixData();
}
}
long long unsigned int bitstreamLSBF::peek(size_t count){
if (count <= 32 && count <= readBufferOffset){
long long unsigned int bitstreamLSBF::peek(size_t count) {
if (count <= 32 && count <= readBufferOffset) {
return readBuffer & ((1 << count) - 1);
}
return 0;
}
void bitstreamLSBF::clear(){
void bitstreamLSBF::clear() {
data = "";
readBufferOffset = 0;
readBuffer = 0;
}
void bitstreamLSBF::fixData(){
while (readBufferOffset <= 32 && data.size() != 0){
void bitstreamLSBF::fixData() {
while (readBufferOffset <= 32 && data.size() != 0) {
//readBuffer = readBuffer & ((1 << readBufferOffset) - 1) | (data[0] << readBufferOffset);
readBuffer |= (((long long unsigned int)data[0]) << readBufferOffset);
data = data.substr(1);

View file

@ -1,19 +1,19 @@
#include<string>
namespace Utils{
class bitstream{
namespace Utils {
class bitstream {
public:
bitstream();
bitstream& operator<< (std::string input){
bitstream & operator<< (std::string input) {
append(input);
return *this;
};
bitstream& operator<< (char input){
bitstream & operator<< (char input) {
append(std::string(input, 1));
return *this;
};
void append (char* input, size_t bytes);
void append (std::string input);
void append(char * input, size_t bytes);
void append(std::string input);
long long unsigned int size();
void skip(size_t count);
long long unsigned int get(size_t count);
@ -29,21 +29,21 @@ namespace Utils{
bool checkBufferSize(unsigned int size);
long long unsigned int golombGetter();
long long unsigned int golombPeeker();
char* data;
char * data;
size_t offset;
size_t dataSize;
size_t bufferSize;
};
class bitstreamLSBF{
class bitstreamLSBF {
public:
bitstreamLSBF();
bitstreamLSBF& operator<< (std::string input){
bitstreamLSBF & operator<< (std::string input) {
append(input);
return *this;
};
void append (char* input, size_t bytes);
void append (std::string input);
void append(char * input, size_t bytes);
void append(std::string input);
long long unsigned int size();
void skip(size_t count);
long long unsigned int get(size_t count);

View file

@ -37,7 +37,7 @@ bool Util::Config::is_active = false;
unsigned int Util::Config::printDebugLevel = DEBUG;//
std::string Util::Config::libver = PACKAGE_VERSION;
Util::Config::Config(){
Util::Config::Config() {
//global options here
vals["debug"]["long"] = "debug";
vals["debug"]["short"] = "g";
@ -51,7 +51,7 @@ Util::Config::Config(){
}
/// Creates a new configuration manager.
Util::Config::Config(std::string cmd, std::string version){
Util::Config::Config(std::string cmd, std::string version) {
vals.null();
long_count = 2;
vals["cmd"]["value"].append(cmd);
@ -84,110 +84,110 @@ Util::Config::Config(std::string cmd, std::string version){
/// "help":"Blahblahblah" //The helptext for this option.
/// }
///\endcode
void Util::Config::addOption(std::string optname, JSON::Value option){
void Util::Config::addOption(std::string optname, JSON::Value option) {
vals[optname] = option;
if ( !vals[optname].isMember("value") && vals[optname].isMember("default")){
if (!vals[optname].isMember("value") && vals[optname].isMember("default")) {
vals[optname]["value"].append(vals[optname]["default"]);
vals[optname].removeMember("default");
}
long_count = 0;
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++){
if (it->second.isMember("long")){
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
if (it->second.isMember("long")) {
long_count++;
}
if (it->second.isMember("long_off")){
if (it->second.isMember("long_off")) {
long_count++;
}
}
}
/// Prints a usage message to the given output.
void Util::Config::printHelp(std::ostream & output){
void Util::Config::printHelp(std::ostream & output) {
unsigned int longest = 0;
std::map<long long int, std::string> args;
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++){
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
unsigned int current = 0;
if (it->second.isMember("long")){
if (it->second.isMember("long")) {
current += it->second["long"].asString().size() + 4;
}
if (it->second.isMember("short")){
if (it->second.isMember("short")) {
current += it->second["short"].asString().size() + 3;
}
if (current > longest){
if (current > longest) {
longest = current;
}
current = 0;
if (it->second.isMember("long_off")){
if (it->second.isMember("long_off")) {
current += it->second["long_off"].asString().size() + 4;
}
if (it->second.isMember("short_off")){
if (it->second.isMember("short_off")) {
current += it->second["short_off"].asString().size() + 3;
}
if (current > longest){
if (current > longest) {
longest = current;
}
if (it->second.isMember("arg_num")){
if (it->second.isMember("arg_num")) {
current = it->first.size() + 3;
if (current > longest){
if (current > longest) {
longest = current;
}
args[it->second["arg_num"].asInt()] = it->first;
}
}
output << "Usage: " << getString("cmd") << " [options]";
for (std::map<long long int, std::string>::iterator i = args.begin(); i != args.end(); i++){
if (vals[i->second].isMember("value") && vals[i->second]["value"].size()){
for (std::map<long long int, std::string>::iterator i = args.begin(); i != args.end(); i++) {
if (vals[i->second].isMember("value") && vals[i->second]["value"].size()) {
output << " [" << i->second << "]";
}else{
} else {
output << " " << i->second;
}
}
output << std::endl << std::endl;
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++){
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
std::string f;
if (it->second.isMember("long") || it->second.isMember("short")){
if (it->second.isMember("long") && it->second.isMember("short")){
if (it->second.isMember("long") || it->second.isMember("short")) {
if (it->second.isMember("long") && it->second.isMember("short")) {
f = "--" + it->second["long"].asString() + ", -" + it->second["short"].asString();
}else{
if (it->second.isMember("long")){
} else {
if (it->second.isMember("long")) {
f = "--" + it->second["long"].asString();
}
if (it->second.isMember("short")){
if (it->second.isMember("short")) {
f = "-" + it->second["short"].asString();
}
}
while (f.size() < longest){
while (f.size() < longest) {
f.append(" ");
}
if (it->second.isMember("arg")){
if (it->second.isMember("arg")) {
output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl;
}else{
} else {
output << f << it->second["help"].asString() << std::endl;
}
}
if (it->second.isMember("long_off") || it->second.isMember("short_off")){
if (it->second.isMember("long_off") && it->second.isMember("short_off")){
if (it->second.isMember("long_off") || it->second.isMember("short_off")) {
if (it->second.isMember("long_off") && it->second.isMember("short_off")) {
f = "--" + it->second["long_off"].asString() + ", -" + it->second["short_off"].asString();
}else{
if (it->second.isMember("long_off")){
} else {
if (it->second.isMember("long_off")) {
f = "--" + it->second["long_off"].asString();
}
if (it->second.isMember("short_off")){
if (it->second.isMember("short_off")) {
f = "-" + it->second["short_off"].asString();
}
}
while (f.size() < longest){
while (f.size() < longest) {
f.append(" ");
}
if (it->second.isMember("arg")){
if (it->second.isMember("arg")) {
output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl;
}else{
} else {
output << f << it->second["help"].asString() << std::endl;
}
}
if (it->second.isMember("arg_num")){
if (it->second.isMember("arg_num")) {
f = it->first;
while (f.size() < longest){
while (f.size() < longest) {
f.append(" ");
}
output << f << "(" << it->second["arg"].asString() << ") " << it->second["help"].asString() << std::endl;
@ -197,51 +197,51 @@ void Util::Config::printHelp(std::ostream & output){
/// Parses commandline arguments.
/// Calls exit if an unknown option is encountered, printing a help message.
bool Util::Config::parseArgs(int & argc, char ** & argv){
bool Util::Config::parseArgs(int & argc, char ** & argv) {
int opt = 0;
std::string shortopts;
struct option * longOpts = (struct option*)calloc(long_count + 1, sizeof(struct option));
struct option * longOpts = (struct option *)calloc(long_count + 1, sizeof(struct option));
int long_i = 0;
int arg_count = 0;
if (vals.size()){
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++){
if (it->second.isMember("short")){
if (vals.size()) {
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
if (it->second.isMember("short")) {
shortopts += it->second["short"].asString();
if (it->second.isMember("arg")){
if (it->second.isMember("arg")) {
shortopts += ":";
}
}
if (it->second.isMember("short_off")){
if (it->second.isMember("short_off")) {
shortopts += it->second["short_off"].asString();
if (it->second.isMember("arg")){
if (it->second.isMember("arg")) {
shortopts += ":";
}
}
if (it->second.isMember("long")){
if (it->second.isMember("long")) {
longOpts[long_i].name = it->second["long"].asString().c_str();
longOpts[long_i].val = it->second["short"].asString()[0];
if (it->second.isMember("arg")){
if (it->second.isMember("arg")) {
longOpts[long_i].has_arg = 1;
}
long_i++;
}
if (it->second.isMember("long_off")){
if (it->second.isMember("long_off")) {
longOpts[long_i].name = it->second["long_off"].asString().c_str();
longOpts[long_i].val = it->second["short_off"].asString()[0];
if (it->second.isMember("arg")){
if (it->second.isMember("arg")) {
longOpts[long_i].has_arg = 1;
}
long_i++;
}
if (it->second.isMember("arg_num") && !(it->second.isMember("value") && it->second["value"].size())){
if (it->second["arg_num"].asInt() > arg_count){
if (it->second.isMember("arg_num") && !(it->second.isMember("value") && it->second["value"].size())) {
if (it->second["arg_num"].asInt() > arg_count) {
arg_count = it->second["arg_num"].asInt();
}
}
}
}
while ((opt = getopt_long(argc, argv, shortopts.c_str(), longOpts, 0)) != -1){
switch (opt){
while ((opt = getopt_long(argc, argv, shortopts.c_str(), longOpts, 0)) != -1) {
switch (opt) {
case 'h':
case '?':
printHelp(std::cout);
@ -251,16 +251,16 @@ bool Util::Config::parseArgs(int & argc, char ** & argv){
exit(1);
break;
default:
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++){
if (it->second.isMember("short") && it->second["short"].asString()[0] == opt){
if (it->second.isMember("arg")){
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
if (it->second.isMember("short") && it->second["short"].asString()[0] == opt) {
if (it->second.isMember("arg")) {
it->second["value"].append((std::string)optarg);
}else{
} else {
it->second["value"].append((long long int)1);
}
break;
}
if (it->second.isMember("short_off") && it->second["short_off"].asString()[0] == opt){
if (it->second.isMember("short_off") && it->second["short_off"].asString()[0] == opt) {
it->second["value"].append((long long int)0);
}
}
@ -269,9 +269,9 @@ bool Util::Config::parseArgs(int & argc, char ** & argv){
} //commandline options parser
free(longOpts); //free the long options array
long_i = 1; //re-use long_i as an argument counter
while (optind < argc){ //parse all remaining options, ignoring anything unexpected.
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++){
if (it->second.isMember("arg_num") && it->second["arg_num"].asInt() == long_i){
while (optind < argc) { //parse all remaining options, ignoring anything unexpected.
for (JSON::ObjIter it = vals.ObjBegin(); it != vals.ObjEnd(); it++) {
if (it->second.isMember("arg_num") && it->second["arg_num"].asInt() == long_i) {
it->second["value"].append((std::string)argv[optind]);
break;
}
@ -279,7 +279,7 @@ bool Util::Config::parseArgs(int & argc, char ** & argv){
optind++;
long_i++;
}
if (long_i <= arg_count){
if (long_i <= arg_count) {
return false;
}
printDebugLevel = getInteger("debug");
@ -288,17 +288,17 @@ bool Util::Config::parseArgs(int & argc, char ** & argv){
/// Returns a reference to the current value of an option or default if none was set.
/// If the option does not exist, this exits the application with a return code of 37.
JSON::Value & Util::Config::getOption(std::string optname, bool asArray){
if ( !vals.isMember(optname)){
JSON::Value & Util::Config::getOption(std::string optname, bool asArray) {
if (!vals.isMember(optname)) {
std::cout << "Fatal error: a non-existent option '" << optname << "' was accessed." << std::endl;
exit(37);
}
if ( !vals[optname].isMember("value") || !vals[optname]["value"].isArray()){
if (!vals[optname].isMember("value") || !vals[optname]["value"].isArray()) {
vals[optname]["value"].append(JSON::Value());
}
if (asArray){
if (asArray) {
return vals[optname]["value"];
}else{
} else {
int n = vals[optname]["value"].size();
return vals[optname]["value"][n - 1];
}
@ -306,30 +306,30 @@ JSON::Value & Util::Config::getOption(std::string optname, bool asArray){
/// Returns the current value of an option or default if none was set as a string.
/// Calls getOption internally.
std::string Util::Config::getString(std::string optname){
std::string Util::Config::getString(std::string optname) {
return getOption(optname).asString();
}
/// Returns the current value of an option or default if none was set as a long long int.
/// Calls getOption internally.
long long int Util::Config::getInteger(std::string optname){
long long int Util::Config::getInteger(std::string optname) {
return getOption(optname).asInt();
}
/// Returns the current value of an option or default if none was set as a bool.
/// Calls getOption internally.
bool Util::Config::getBool(std::string optname){
bool Util::Config::getBool(std::string optname) {
return getOption(optname).asBool();
}
struct callbackData{
struct callbackData {
Socket::Connection * sock;
int (*cb)(Socket::Connection &);
};
static void callThreadCallback(void * cDataArg){
static void callThreadCallback(void * cDataArg) {
DEBUG_MSG(DLVL_INSANE, "Thread for %p started", cDataArg);
callbackData * cData = (callbackData*)cDataArg;
callbackData * cData = (callbackData *)cDataArg;
cData->cb(*(cData->sock));
cData->sock->close();
delete cData->sock;
@ -337,19 +337,19 @@ static void callThreadCallback(void * cDataArg){
DEBUG_MSG(DLVL_INSANE, "Thread for %p ended", cDataArg);
}
int Util::Config::threadServer(Socket::Server & server_socket, int (*callback)(Socket::Connection &)){
while (is_active && server_socket.connected()){
int Util::Config::threadServer(Socket::Server & server_socket, int (*callback)(Socket::Connection &)) {
while (is_active && server_socket.connected()) {
Socket::Connection S = server_socket.accept();
if (S.connected()){ //check if the new connection is valid
if (S.connected()) { //check if the new connection is valid
callbackData * cData = new callbackData;
cData->sock = new Socket::Connection(S);
cData->cb = callback;
//spawn a new thread for this connection
tthread::thread T(callThreadCallback, (void*)cData);
tthread::thread T(callThreadCallback, (void *)cData);
//detach it, no need to keep track of it anymore
T.detach();
DEBUG_MSG(DLVL_HIGH, "Spawned new thread for socket %i", S.getSocket());
}else{
} else {
Util::sleep(10); //sleep 10ms
}
}
@ -357,19 +357,19 @@ int Util::Config::threadServer(Socket::Server & server_socket, int (*callback)(S
return 0;
}
int Util::Config::forkServer(Socket::Server & server_socket, int (*callback)(Socket::Connection &)){
while (is_active && server_socket.connected()){
int Util::Config::forkServer(Socket::Server & server_socket, int (*callback)(Socket::Connection &)) {
while (is_active && server_socket.connected()) {
Socket::Connection S = server_socket.accept();
if (S.connected()){ //check if the new connection is valid
if (S.connected()) { //check if the new connection is valid
pid_t myid = fork();
if (myid == 0){ //if new child, start MAINHANDLER
if (myid == 0) { //if new child, start MAINHANDLER
server_socket.drop();
return callback(S);
}else{ //otherwise, do nothing or output debugging text
} else { //otherwise, do nothing or output debugging text
DEBUG_MSG(DLVL_HIGH, "Forked new process %i for socket %i", (int)myid, S.getSocket());
S.drop();
}
}else{
} else {
Util::sleep(10); //sleep 10ms
}
}
@ -377,15 +377,15 @@ int Util::Config::forkServer(Socket::Server & server_socket, int (*callback)(Soc
return 0;
}
int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)) {
Socket::Server server_socket;
if (vals.isMember("socket")){
if (vals.isMember("socket")) {
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
}
if (vals.isMember("listen_port") && vals.isMember("listen_interface")){
if (vals.isMember("listen_port") && vals.isMember("listen_interface")) {
server_socket = Socket::Server(getInteger("listen_port"), getString("listen_interface"), false);
}
if (!server_socket.connected()){
if (!server_socket.connected()) {
DEBUG_MSG(DLVL_DEVEL, "Failure to open socket");
return 1;
}
@ -394,15 +394,15 @@ int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
return threadServer(server_socket, callback);
}
int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection & S)){
int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection & S)) {
Socket::Server server_socket;
if (vals.isMember("socket")){
if (vals.isMember("socket")) {
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
}
if (vals.isMember("listen_port") && vals.isMember("listen_interface")){
if (vals.isMember("listen_port") && vals.isMember("listen_interface")) {
server_socket = Socket::Server(getInteger("listen_port"), getString("listen_interface"), false);
}
if (!server_socket.connected()){
if (!server_socket.connected()) {
DEBUG_MSG(DLVL_DEVEL, "Failure to open socket");
return 1;
}
@ -416,21 +416,21 @@ int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection & S)){
/// - Daemonize the process if "daemonize" exists and is true.
/// - Set is_active to true.
/// - Set up a signal handler to set is_active to false for the SIGINT, SIGHUP and SIGTERM signals.
void Util::Config::activate(){
if (vals.isMember("username")){
void Util::Config::activate() {
if (vals.isMember("username")) {
setUser(getString("username"));
}
if (vals.isMember("daemonize") && getBool("daemonize")){
if(vals.isMember("logfile") && getString("logfile") != ""){
if (vals.isMember("daemonize") && getBool("daemonize")) {
if (vals.isMember("logfile") && getString("logfile") != "") {
Daemonize(true);
}else{
} else {
Daemonize(false);
}
}
struct sigaction new_action;
struct sigaction cur_action;
new_action.sa_handler = signal_handler;
sigemptyset( &new_action.sa_mask);
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGINT, &new_action, NULL);
sigaction(SIGHUP, &new_action, NULL);
@ -438,7 +438,7 @@ void Util::Config::activate(){
sigaction(SIGPIPE, &new_action, NULL);
//check if a child signal handler isn't set already, if so, set it.
sigaction(SIGCHLD, 0, &cur_action);
if (cur_action.sa_handler == SIG_DFL || cur_action.sa_handler == SIG_IGN){
if (cur_action.sa_handler == SIG_DFL || cur_action.sa_handler == SIG_IGN) {
sigaction(SIGCHLD, &new_action, NULL);
}
is_active = true;
@ -447,19 +447,19 @@ void Util::Config::activate(){
/// Basic signal handler. Sets is_active to false if it receives
/// a SIGINT, SIGHUP or SIGTERM signal, reaps children for the SIGCHLD
/// signal, and ignores all other signals.
void Util::Config::signal_handler(int signum){
switch (signum){
void Util::Config::signal_handler(int signum) {
switch (signum) {
case SIGINT: //these three signals will set is_active to false.
case SIGHUP:
case SIGTERM:
is_active = false;
break;
case SIGCHLD:{ //when a child dies, reap it.
case SIGCHLD: { //when a child dies, reap it.
int status;
pid_t ret = -1;
while (ret != 0){
ret = waitpid( -1, &status, WNOHANG);
if (ret < 0 && errno != EINTR){
while (ret != 0) {
ret = waitpid(-1, &status, WNOHANG);
if (ret < 0 && errno != EINTR) {
break;
}
}
@ -472,7 +472,7 @@ void Util::Config::signal_handler(int signum){
/// Adds the default connector options. Also updates the capabilities structure with the default options.
/// Besides the options addBasicConnectorOptions adds, this function also adds port and interface options.
void Util::Config::addConnectorOptions(int port, JSON::Value & capabilities){
void Util::Config::addConnectorOptions(int port, JSON::Value & capabilities) {
JSON::Value option;
option.null();
option["long"] = "port";
@ -482,7 +482,7 @@ void Util::Config::addConnectorOptions(int port, JSON::Value & capabilities){
option["value"].append((long long)port);
addOption("listen_port", option);
capabilities["optional"]["port"]["name"] = "TCP port";
capabilities["optional"]["port"]["help"] = "TCP port to listen on - default if unprovided is "+option["value"][0u].asString();
capabilities["optional"]["port"]["help"] = "TCP port to listen on - default if unprovided is " + option["value"][0u].asString();
capabilities["optional"]["port"]["type"] = "uint";
capabilities["optional"]["port"]["option"] = "--port";
capabilities["optional"]["port"]["default"] = option["value"][0u];
@ -503,7 +503,7 @@ void Util::Config::addConnectorOptions(int port, JSON::Value & capabilities){
} //addConnectorOptions
/// Adds the default connector options. Also updates the capabilities structure with the default options.
void Util::Config::addBasicConnectorOptions(JSON::Value & capabilities){
void Util::Config::addBasicConnectorOptions(JSON::Value & capabilities) {
JSON::Value option;
option.null();
option["long"] = "username";
@ -518,7 +518,7 @@ void Util::Config::addBasicConnectorOptions(JSON::Value & capabilities){
capabilities["optional"]["username"]["type"] = "str";
if (capabilities.isMember("socket")){
if (capabilities.isMember("socket")) {
option.null();
option["arg"] = "string";
option["help"] = "Socket name that can be connected to for this connector.";
@ -546,29 +546,29 @@ void Util::Config::addBasicConnectorOptions(JSON::Value & capabilities){
/// Gets directory the current executable is stored in.
std::string Util::getMyPath(){
std::string Util::getMyPath() {
char mypath[500];
#ifdef __CYGWIN__
#ifdef __CYGWIN__
GetModuleFileName(0, mypath, 500);
#else
#ifdef __APPLE__
memset( mypath, 0, 500);
#else
#ifdef __APPLE__
memset(mypath, 0, 500);
unsigned int refSize = 500;
int ret = _NSGetExecutablePath(mypath,&refSize);
#else
int ret = _NSGetExecutablePath(mypath, &refSize);
#else
int ret = readlink("/proc/self/exe", mypath, 500);
if (ret != -1){
if (ret != -1) {
mypath[ret] = 0;
}else{
} else {
mypath[0] = 0;
}
#endif
#endif
#endif
#endif
std::string tPath = mypath;
size_t slash = tPath.rfind('/');
if (slash == std::string::npos){
if (slash == std::string::npos) {
slash = tPath.rfind('\\');
if (slash == std::string::npos){
if (slash == std::string::npos) {
return "";
}
}
@ -577,46 +577,48 @@ std::string Util::getMyPath(){
}
/// Gets all executables in getMyPath that start with "Mist".
void Util::getMyExec(std::deque<std::string> & execs){
void Util::getMyExec(std::deque<std::string> & execs) {
std::string path = Util::getMyPath();
#ifdef __CYGWIN__
#ifdef __CYGWIN__
path += "\\Mist*";
WIN32_FIND_DATA FindFileData;
HANDLE hdl = FindFirstFile(path.c_str(), &FindFileData);
while (hdl != INVALID_HANDLE_VALUE){
while (hdl != INVALID_HANDLE_VALUE) {
execs.push_back(FindFileData.cFileName);
if (!FindNextFile(hdl, &FindFileData)){
if (!FindNextFile(hdl, &FindFileData)) {
FindClose(hdl);
hdl = INVALID_HANDLE_VALUE;
}
}
#else
#else
DIR * d = opendir(path.c_str());
if (!d){return;}
struct dirent *dp;
if (!d) {
return;
}
struct dirent * dp;
do {
errno = 0;
if ((dp = readdir(d))){
if (strncmp(dp->d_name, "Mist", 4) == 0){
if ((dp = readdir(d))) {
if (strncmp(dp->d_name, "Mist", 4) == 0) {
execs.push_back(dp->d_name);
}
}
} while (dp != NULL);
closedir(d);
#endif
#endif
}
/// Sets the current process' running user
void Util::setUser(std::string username){
if (username != "root"){
void Util::setUser(std::string username) {
if (username != "root") {
struct passwd * user_info = getpwnam(username.c_str());
if ( !user_info){
if (!user_info) {
DEBUG_MSG(DLVL_ERROR, "Error: could not setuid %s: could not get PID", username.c_str());
return;
}else{
if (setuid(user_info->pw_uid) != 0){
} else {
if (setuid(user_info->pw_uid) != 0) {
DEBUG_MSG(DLVL_ERROR, "Error: could not setuid %s: not allowed", username.c_str());
}else{
} else {
DEBUG_MSG(DLVL_DEVEL, "Change user to %s", username.c_str());
}
}
@ -627,13 +629,13 @@ void Util::setUser(std::string username){
/// Works by calling daemon(1,0):
/// Does not change directory to root.
/// Does redirect output to /dev/null
void Util::Daemonize(bool notClose){
void Util::Daemonize(bool notClose) {
DEBUG_MSG(DLVL_DEVEL, "Going into background mode...");
int noClose = 0;
if(notClose){
if (notClose) {
noClose = 1;
}
if (daemon(1, noClose) < 0){
if (daemon(1, noClose) < 0) {
DEBUG_MSG(DLVL_ERROR, "Failed to daemonize: %s", strerror(errno));
}
}

View file

@ -14,7 +14,7 @@
namespace Util {
/// Deals with parsing configuration from commandline options.
class Config{
class Config {
private:
JSON::Value vals; ///< Holds all current config values
int long_count;

View file

@ -13,7 +13,7 @@
namespace Converter {
///\brief The base constructor
Converter::Converter(){
Converter::Converter() {
fillFFMpegEncoders();
}
@ -23,50 +23,52 @@ namespace Converter {
/// - AAC
/// - H264
/// - MP3
void Converter::fillFFMpegEncoders(){
std::vector<char*> cmd;
void Converter::fillFFMpegEncoders() {
std::vector<char *> cmd;
cmd.reserve(3);
cmd.push_back((char*)"ffmpeg");
cmd.push_back((char*)"-encoders");
cmd.push_back((char *)"ffmpeg");
cmd.push_back((char *)"-encoders");
cmd.push_back(NULL);
int outFD = -1;
Util::Procs::StartPiped("FFMpegInfo", &cmd[0], 0, &outFD, 0);
while( Util::Procs::isActive("FFMpegInfo")){ Util::sleep(100); }
FILE * outFile = fdopen( outFD, "r" );
while (Util::Procs::isActive("FFMpegInfo")) {
Util::sleep(100);
}
FILE * outFile = fdopen(outFD, "r");
char * fileBuf = 0;
size_t fileBufLen = 0;
while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
if (strstr(fileBuf, "aac") || strstr(fileBuf, "AAC")){
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)) {
if (strstr(fileBuf, "aac") || strstr(fileBuf, "AAC")) {
strtok(fileBuf, " \t");
allCodecs["ffmpeg"][strtok(NULL, " \t")] = "aac";
}
if (strstr(fileBuf, "h264") || strstr(fileBuf, "H264")){
if (strstr(fileBuf, "h264") || strstr(fileBuf, "H264")) {
strtok(fileBuf, " \t");
allCodecs["ffmpeg"][strtok(NULL, " \t")] = "h264";
}
if (strstr(fileBuf, "mp3") || strstr(fileBuf, "MP3")){
if (strstr(fileBuf, "mp3") || strstr(fileBuf, "MP3")) {
strtok(fileBuf, " \t");
allCodecs["ffmpeg"][strtok(NULL, " \t")] = "mp3";
}
}
fclose( outFile );
fclose(outFile);
}
///\brief A function to obtain all available codecs that have been obtained from the encoders.
///\return A reference to the allCodecs member.
converterInfo & Converter::getCodecs(){
converterInfo & Converter::getCodecs() {
return allCodecs;
}
///\brief A function to obtain the available encoders in JSON format.
///\return A JSON::Value containing all encoder:codec pairs.
JSON::Value Converter::getEncoders(){
JSON::Value Converter::getEncoders() {
JSON::Value result;
for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++){
for (codecInfo::iterator codIt = convIt->second.begin(); codIt != convIt->second.end(); codIt++){
if (codIt->second == "h264"){
for (converterInfo::iterator convIt = allCodecs.begin(); convIt != allCodecs.end(); convIt++) {
for (codecInfo::iterator codIt = convIt->second.begin(); codIt != convIt->second.end(); codIt++) {
if (codIt->second == "h264") {
result[convIt->first]["video"][codIt->first] = codIt->second;
}else{
} else {
result[convIt->first]["audio"][codIt->first] = codIt->second;
}
@ -78,26 +80,26 @@ namespace Converter {
///\brief Looks in a given path for all files that could be converted
///\param myPath The location to look at, this should be a folder.
///\return A JSON::Value containing all media files in the location, with their corresponding metadata values.
JSON::Value Converter::queryPath(std::string myPath){
JSON::Value Converter::queryPath(std::string myPath) {
char const * cmd[3] = {0, 0, 0};
std::string mistPath = Util::getMyPath() + "MistInfo";
cmd[0] = mistPath.c_str();
JSON::Value result;
DIR * Dirp = opendir(myPath.c_str());
struct stat StatBuf;
if (Dirp){
if (Dirp) {
dirent * entry;
while ((entry = readdir(Dirp))){
if (stat(std::string(myPath + "/" + entry->d_name).c_str(), &StatBuf) == -1){
while ((entry = readdir(Dirp))) {
if (stat(std::string(myPath + "/" + entry->d_name).c_str(), &StatBuf) == -1) {
continue;
}
if ((StatBuf.st_mode & S_IFREG) == 0){
if ((StatBuf.st_mode & S_IFREG) == 0) {
continue;
}
std::string fileName = entry->d_name;
std::string mijnPad = std::string(myPath + (myPath[myPath.size()-1] == '/' ? "" : "/") + entry->d_name);
std::string mijnPad = std::string(myPath + (myPath[myPath.size() - 1] == '/' ? "" : "/") + entry->d_name);
cmd[1] = mijnPad.c_str();
result[fileName] = JSON::fromString(Util::Procs::getOutputOf((char* const*)cmd));
result[fileName] = JSON::fromString(Util::Procs::getOutputOf((char * const *)cmd));
}
}
return result;
@ -118,11 +120,11 @@ namespace Converter {
/// - codec The codec to encode audio in, or copy to use the current codec
/// - samplerate The target samplerate for the audio, in hz
void Converter::startConversion(std::string name, JSON::Value parameters) {
if ( !parameters.isMember("input")){
if (!parameters.isMember("input")) {
statusHistory[name] = "No input file supplied";
return;
}
if ( !parameters.isMember("output")){
if (!parameters.isMember("output")) {
statusHistory[name] = "No output file supplied";
return;
}
@ -130,81 +132,81 @@ namespace Converter {
std::string outPath = parameters["output"].asString();
outPath = outPath.substr(0, outPath.rfind('/'));
int statRes = stat(outPath.c_str(), & statBuf);
if (statRes == -1 || !S_ISDIR(statBuf.st_mode)){
if (statRes == -1 || !S_ISDIR(statBuf.st_mode)) {
statusHistory[name] = "Output path is either non-existent, or not a path.";
return;
}
if ( !parameters.isMember("encoder")){
if (!parameters.isMember("encoder")) {
statusHistory[name] = "No encoder specified";
return;
}
if (allCodecs.find(parameters["encoder"]) == allCodecs.end()){
if (allCodecs.find(parameters["encoder"]) == allCodecs.end()) {
statusHistory[name] = "Can not find encoder " + parameters["encoder"].asString();
return;
}
if (parameters.isMember("video")){
if (parameters["video"].isMember("width") && !parameters["video"].isMember("height")){
if (parameters.isMember("video")) {
if (parameters["video"].isMember("width") && !parameters["video"].isMember("height")) {
statusHistory[name] = "No height parameter given";
return;
}
if (parameters["video"].isMember("height") && !parameters["video"].isMember("width")){
if (parameters["video"].isMember("height") && !parameters["video"].isMember("width")) {
statusHistory[name] = "No width parameter given";
return;
}
}
std::stringstream encoderCommand;
if (parameters["encoder"] == "ffmpeg"){
if (parameters["encoder"] == "ffmpeg") {
encoderCommand << "ffmpeg -i ";
encoderCommand << parameters["input"].asString() << " ";
if (parameters.isMember("video")){
if ( !parameters["video"].isMember("codec") || parameters["video"]["codec"] == "copy"){
if (parameters.isMember("video")) {
if (!parameters["video"].isMember("codec") || parameters["video"]["codec"] == "copy") {
encoderCommand << "-vcodec copy ";
}else{
} else {
codecInfo::iterator vidCodec = allCodecs["ffmpeg"].find(parameters["video"]["codec"]);
if (vidCodec == allCodecs["ffmpeg"].end()){
if (vidCodec == allCodecs["ffmpeg"].end()) {
statusHistory[name] = "Can not find video codec " + parameters["video"]["codec"].asString();
return;
}
encoderCommand << "-vcodec " << vidCodec->first << " ";
if (parameters["video"]["codec"].asString() == "h264"){
if (parameters["video"]["codec"].asString() == "h264") {
//Enforce baseline
encoderCommand << "-preset slow -profile:v baseline -level 30 ";
}
if (parameters["video"].isMember("fpks")){
if (parameters["video"].isMember("fpks")) {
encoderCommand << "-r " << parameters["video"]["fpks"].asInt() / 1000 << " ";
}
if (parameters["video"].isMember("width")){
if (parameters["video"].isMember("width")) {
encoderCommand << "-s " << parameters["video"]["width"].asInt() << "x" << parameters["video"]["height"].asInt() << " ";
}
///\todo Keyframe interval (different in older and newer versions of ffmpeg?)
}
}else{
} else {
encoderCommand << "-vn ";
}
if (parameters.isMember("audio")){
if ( !parameters["audio"].isMember("codec")){
if (parameters.isMember("audio")) {
if (!parameters["audio"].isMember("codec")) {
encoderCommand << "-acodec copy ";
}else{
} else {
codecInfo::iterator audCodec = allCodecs["ffmpeg"].find(parameters["audio"]["codec"]);
if (audCodec == allCodecs["ffmpeg"].end()){
if (audCodec == allCodecs["ffmpeg"].end()) {
statusHistory[name] = "Can not find audio codec " + parameters["audio"]["codec"].asString();
return;
}
if (audCodec->second == "aac"){
if (audCodec->second == "aac") {
encoderCommand << "-strict -2 ";
}
encoderCommand << "-acodec " << audCodec->first << " ";
if (parameters["audio"].isMember("samplerate")){
if (parameters["audio"].isMember("samplerate")) {
encoderCommand << "-ar " << parameters["audio"]["samplerate"].asInt() << " ";
}
}
}else{
} else {
encoderCommand << "-an ";
}
encoderCommand << "-f flv -";
}
int statusFD = -1;
Util::Procs::StartPiped2(name,encoderCommand.str(),Util::getMyPath() + "MistFLV2DTSC -o " + parameters["output"].asString(),0,0,&statusFD,0);
Util::Procs::StartPiped2(name, encoderCommand.str(), Util::getMyPath() + "MistFLV2DTSC -o " + parameters["output"].asString(), 0, 0, &statusFD, 0);
parameters["statusFD"] = statusFD;
allConversions[name] = parameters;
allConversions[name]["status"]["duration"] = "?";
@ -216,49 +218,49 @@ namespace Converter {
///\brief Updates the internal status of the converter class.
///
///Will check for each running conversion whether it is still running, and update its status accordingly
void Converter::updateStatus(){
if (allConversions.size()){
std::map<std::string,JSON::Value>::iterator cIt;
void Converter::updateStatus() {
if (allConversions.size()) {
std::map<std::string, JSON::Value>::iterator cIt;
bool hasChanged = true;
while (hasChanged && allConversions.size()){
while (hasChanged && allConversions.size()) {
hasChanged = false;
for (cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){
if (Util::Procs::isActive(cIt->first)){
for (cIt = allConversions.begin(); cIt != allConversions.end(); cIt++) {
if (Util::Procs::isActive(cIt->first)) {
int statusFD = dup(cIt->second["statusFD"].asInt());
fsync( statusFD );
FILE* statusFile = fdopen( statusFD, "r" );
fsync(statusFD);
FILE * statusFile = fdopen(statusFD, "r");
char * fileBuf = 0;
size_t fileBufLen = 0;
fseek(statusFile,0,SEEK_END);
fseek(statusFile, 0, SEEK_END);
std::string line;
int totalTime = 0;
do{
do {
getdelim(&fileBuf, &fileBufLen, '\r', statusFile);
line = fileBuf;
if (line.find("Duration") != std::string::npos){
if (line.find("Duration") != std::string::npos) {
int curOffset = line.find("Duration: ") + 10;
totalTime += atoi(line.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
totalTime += atoi(line.substr(curOffset+3, 2).c_str()) * 60 * 1000;
totalTime += atoi(line.substr(curOffset+6, 2).c_str()) *1000;
totalTime += atoi(line.substr(curOffset+9, 2).c_str()) * 10;
totalTime += atoi(line.substr(curOffset + 3, 2).c_str()) * 60 * 1000;
totalTime += atoi(line.substr(curOffset + 6, 2).c_str()) * 1000;
totalTime += atoi(line.substr(curOffset + 9, 2).c_str()) * 10;
cIt->second["duration"] = totalTime;
}
}while ( !feof(statusFile) && line.find("frame") != 0);//"frame" is the fist word on an actual status line of ffmpeg
if ( !feof(statusFile)){
cIt->second["status"] = parseFFMpegStatus( line );
} while (!feof(statusFile) && line.find("frame") != 0); //"frame" is the fist word on an actual status line of ffmpeg
if (!feof(statusFile)) {
cIt->second["status"] = parseFFMpegStatus(line);
cIt->second["status"]["duration"] = cIt->second["duration"];
cIt->second["status"]["progress"] = (cIt->second["status"]["time"].asInt() * 100) / cIt->second["duration"].asInt();
}else{
line.erase(line.end()-1);
line = line.substr( line.rfind("\n") + 1 );
} else {
line.erase(line.end() - 1);
line = line.substr(line.rfind("\n") + 1);
cIt->second["status"] = line;
}
free(fileBuf);
fclose(statusFile);
}else{
if (statusHistory.find( cIt->first ) == statusHistory.end()){
} else {
if (statusHistory.find(cIt->first) == statusHistory.end()) {
statusHistory[cIt->first] = "Conversion successful, running DTSCFix";
Util::Procs::Start(cIt->first+"DTSCFix",Util::getMyPath() + "MistDTSCFix " + cIt->second["output"].asString());
Util::Procs::Start(cIt->first + "DTSCFix", Util::getMyPath() + "MistDTSCFix " + cIt->second["output"].asString());
}
allConversions.erase(cIt);
hasChanged = true;
@ -267,11 +269,11 @@ namespace Converter {
}
}
}
if(statusHistory.size()){
std::map<std::string,std::string>::iterator sIt;
for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){
if (statusHistory[sIt->first].find("DTSCFix") != std::string::npos){
if (Util::Procs::isActive(sIt->first+"DTSCFIX")){
if (statusHistory.size()) {
std::map<std::string, std::string>::iterator sIt;
for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++) {
if (statusHistory[sIt->first].find("DTSCFix") != std::string::npos) {
if (Util::Procs::isActive(sIt->first + "DTSCFIX")) {
continue;
}
statusHistory[sIt->first] = "Conversion successful";
@ -285,34 +287,34 @@ namespace Converter {
///\return A JSON::Value with the following values set:
/// - frame The current last encoded frame
/// - time The current last encoded timestamp
JSON::Value Converter::parseFFMpegStatus(std::string statusLine){
JSON::Value Converter::parseFFMpegStatus(std::string statusLine) {
JSON::Value result;
int curOffset = statusLine.find("frame=") + 6;
result["frame"] = atoi(statusLine.substr(curOffset, statusLine.find("fps=") - curOffset).c_str() );
result["frame"] = atoi(statusLine.substr(curOffset, statusLine.find("fps=") - curOffset).c_str());
curOffset = statusLine.find("time=") + 5;
int myTime = 0;
myTime += atoi(statusLine.substr(curOffset, 2).c_str()) * 60 * 60 * 1000;
myTime += atoi(statusLine.substr(curOffset+3, 2).c_str()) * 60 * 1000;
myTime += atoi(statusLine.substr(curOffset+6, 2).c_str()) *1000;
myTime += atoi(statusLine.substr(curOffset+9, 2).c_str()) * 10;
myTime += atoi(statusLine.substr(curOffset + 3, 2).c_str()) * 60 * 1000;
myTime += atoi(statusLine.substr(curOffset + 6, 2).c_str()) * 1000;
myTime += atoi(statusLine.substr(curOffset + 9, 2).c_str()) * 10;
result["time"] = myTime;
return result;
}
///\brief Obtain the current internal status of the conversion class
///\return A JSON::Value with the status of each conversion
JSON::Value Converter::getStatus(){
JSON::Value Converter::getStatus() {
updateStatus();
JSON::Value result;
if (allConversions.size()){
for (std::map<std::string,JSON::Value>::iterator cIt = allConversions.begin(); cIt != allConversions.end(); cIt++){
if (allConversions.size()) {
for (std::map<std::string, JSON::Value>::iterator cIt = allConversions.begin(); cIt != allConversions.end(); cIt++) {
result[cIt->first] = cIt->second["status"];
result[cIt->first]["details"] = cIt->second;
}
}
if (statusHistory.size()){
std::map<std::string,std::string>::iterator sIt;
for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++){
if (statusHistory.size()) {
std::map<std::string, std::string>::iterator sIt;
for (sIt = statusHistory.begin(); sIt != statusHistory.end(); sIt++) {
result[sIt->first] = sIt->second;
}
}
@ -320,7 +322,7 @@ namespace Converter {
}
///\brief Clears the status history of all conversions
void Converter::clearStatus(){
void Converter::clearStatus() {
statusHistory.clear();
}
}

View file

@ -4,9 +4,9 @@
#include "json.h"
///\brief A typedef to simplify accessing all codecs
typedef std::map<std::string,std::string> codecInfo;
typedef std::map<std::string, std::string> codecInfo;
///\brief A typedef to simplify accessing all encoders
typedef std::map<std::string,codecInfo> converterInfo;
typedef std::map<std::string, codecInfo> converterInfo;
///\brief A namespace containing all functions for handling the conversion API
namespace Converter {
@ -28,8 +28,8 @@ namespace Converter {
///\brief Holds a list of all current known codecs
converterInfo allCodecs;
///\brief Holds a list of all the current conversions
std::map<std::string,JSON::Value> allConversions;
std::map<std::string, JSON::Value> allConversions;
///\brief Stores the status of all conversions, and the history
std::map<std::string,std::string> statusHistory;
std::map<std::string, std::string> statusHistory;
};
}

View file

@ -1,52 +1,52 @@
// Defines to print debug messages.
#ifndef MIST_DEBUG
#define MIST_DEBUG 1
#define DLVL_NONE 0 // All debugging disabled.
#define DLVL_FAIL 1 // Only messages about failed operations.
#define DLVL_ERROR 2 // Only messages about errors and failed operations.
#define DLVL_WARN 3 // Warnings, errors, and fail messages.
#define DLVL_DEVEL 4 // All of the above, plus status messages handy during development.
#define DLVL_INFO 4 // All of the above, plus status messages handy during development.
#define DLVL_MEDIUM 5 // Slightly more than just development-level messages.
#define DLVL_HIGH 6 // Verbose debugging messages.
#define DLVL_VERYHIGH 7 // Very verbose debugging messages.
#define DLVL_EXTREME 8 // Everything is reported in extreme detail.
#define DLVL_INSANE 9 // Everything is reported in insane detail.
#define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones.
#if DEBUG > -1
#define MIST_DEBUG 1
#define DLVL_NONE 0 // All debugging disabled.
#define DLVL_FAIL 1 // Only messages about failed operations.
#define DLVL_ERROR 2 // Only messages about errors and failed operations.
#define DLVL_WARN 3 // Warnings, errors, and fail messages.
#define DLVL_DEVEL 4 // All of the above, plus status messages handy during development.
#define DLVL_INFO 4 // All of the above, plus status messages handy during development.
#define DLVL_MEDIUM 5 // Slightly more than just development-level messages.
#define DLVL_HIGH 6 // Verbose debugging messages.
#define DLVL_VERYHIGH 7 // Very verbose debugging messages.
#define DLVL_EXTREME 8 // Everything is reported in extreme detail.
#define DLVL_INSANE 9 // Everything is reported in insane detail.
#define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones.
#if DEBUG > -1
#include <stdio.h>
#include <unistd.h>
#include "config.h"
static const char* DBG_LVL_LIST[] = {"NONE","FAIL","ERROR","WARN","INFO","MEDIUM","HIGH","VERYHIGH","EXTREME","INSANE","DONTEVEN"};
#include <stdio.h>
#include <unistd.h>
#include "config.h"
static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", "MEDIUM", "HIGH", "VERYHIGH", "EXTREME", "INSANE", "DONTEVEN"};
#if !defined(__APPLE__) && !defined(__MACH__) && defined(__GNUC__)
#include <errno.h>
extern char * program_invocation_short_name;
#if !defined(__APPLE__) && !defined(__MACH__) && defined(__GNUC__)
#include <errno.h>
extern char * program_invocation_short_name;
#if DEBUG >= DLVL_DEVEL
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|%s|%d|%s:%d|" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, getpid(), __FILE__, __LINE__, ##__VA_ARGS__);}
#else
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|%s|%d||" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, getpid(), ##__VA_ARGS__);}
#endif
#else
#if DEBUG >= DLVL_DEVEL
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s||%d|%s:%d|" msg "\n", DBG_LVL_LIST[lvl], getpid(), __FILE__, __LINE__, ##__VA_ARGS__);}
#else
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s||%d||" msg "\n", DBG_LVL_LIST[lvl], getpid(), ##__VA_ARGS__);}
#endif
#endif
#if DEBUG >= DLVL_DEVEL
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|%s|%d|%s:%d|" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, getpid(), __FILE__, __LINE__, ##__VA_ARGS__);}
#else
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|%s|%d||" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, getpid(), ##__VA_ARGS__);}
#endif
#else
#if DEBUG >= DLVL_DEVEL
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s||%d|%s:%d|" msg "\n", DBG_LVL_LIST[lvl], getpid(), __FILE__, __LINE__, ##__VA_ARGS__);}
#else
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s||%d||" msg "\n", DBG_LVL_LIST[lvl], getpid(), ##__VA_ARGS__);}
#endif
#endif
#else
#else
#define DEBUG_MSG(lvl, msg, ...) // Debugging disabled.
#endif
#define FAIL_MSG(msg, ...) DEBUG_MSG(DLVL_FAIL, msg, ##__VA_ARGS__)
#define ERROR_MSG(msg, ...) DEBUG_MSG(DLVL_ERROR, msg, ##__VA_ARGS__)
#define WARN_MSG(msg, ...) DEBUG_MSG(DLVL_WARN, msg, ##__VA_ARGS__)
#define DEVEL_MSG(msg, ...) DEBUG_MSG(DLVL_DEVEL, msg, ##__VA_ARGS__)
#define INFO_MSG(msg, ...) DEBUG_MSG(DLVL_DEVEL, msg, ##__VA_ARGS__)
#define DEBUG_MSG(lvl, msg, ...) // Debugging disabled.
#endif
#define FAIL_MSG(msg, ...) DEBUG_MSG(DLVL_FAIL, msg, ##__VA_ARGS__)
#define ERROR_MSG(msg, ...) DEBUG_MSG(DLVL_ERROR, msg, ##__VA_ARGS__)
#define WARN_MSG(msg, ...) DEBUG_MSG(DLVL_WARN, msg, ##__VA_ARGS__)
#define DEVEL_MSG(msg, ...) DEBUG_MSG(DLVL_DEVEL, msg, ##__VA_ARGS__)
#define INFO_MSG(msg, ...) DEBUG_MSG(DLVL_DEVEL, msg, ##__VA_ARGS__)
#endif

File diff suppressed because it is too large Load diff

View file

@ -58,7 +58,7 @@ namespace DTSC {
unsigned int trackID;///< Stores the track the DTSC packet referenced by this structure is associated with.
};
enum packType{
enum packType {
DTSC_INVALID,
DTSC_HEAD,
DTSC_V1,
@ -67,7 +67,7 @@ namespace DTSC {
/// This class allows scanning through raw binary format DTSC data.
/// It can be used as an iterator or as a direct accessor.
class Scan{
class Scan {
public:
Scan();
Scan(char * pointer, size_t len);

View file

@ -61,12 +61,12 @@ namespace DTSC {
/// Copier for packets, copies an existing packet with same noCopy flag as original.
/// If going from copy to noCopy, this will free the data pointer first.
void Packet::operator = (const Packet & rhs) {
if (master && !rhs.master){
if (master && !rhs.master) {
null();
}
if (rhs){
if (rhs) {
reInit(rhs.data, rhs.dataLen, !rhs.master);
}else{
} else {
null();
}
}
@ -82,7 +82,7 @@ namespace DTSC {
DEBUG_MSG(DLVL_DONTEVEN, "Datalen < 8");
return false;
}
if (version == DTSC_INVALID){
if (version == DTSC_INVALID) {
DEBUG_MSG(DLVL_DONTEVEN, "No valid version");
return false;
}
@ -95,14 +95,14 @@ namespace DTSC {
/// Returns the recognized packet type.
/// This type is set by reInit and all constructors, and then just referenced from there on.
packType Packet::getVersion() const{
packType Packet::getVersion() const {
return version;
}
/// Resets this packet back to the same state as if it had just been freshly constructed.
/// If needed, this frees the data pointer.
void Packet::null() {
if (master && data){
if (master && data) {
free(data);
}
master = false;
@ -132,12 +132,12 @@ namespace DTSC {
///\param len The length of the data pointed to by data_
///\param noCopy Determines whether to make a copy or not
void Packet::reInit(const char * data_, unsigned int len, bool noCopy) {
if (!data_){
if (!data_) {
DEBUG_MSG(DLVL_DEVEL, "ReInit received a null pointer with len %d, ignoring", len);
null();
return;
}
if (data_[0] != 'D' || data_[1] != 'T'){
if (data_[0] != 'D' || data_[1] != 'T') {
DEBUG_MSG(DLVL_HIGH, "ReInit received a pointer that didn't start with 'DT' - data corruption?");
null();
return;
@ -146,80 +146,80 @@ namespace DTSC {
len = ntohl(((int *)data_)[1]) + 8;
}
//clear any existing controlled contents
if (master && noCopy){
if (master && noCopy) {
null();
}
//set control flag to !noCopy
master = !noCopy;
//either copy the data, or only the pointer, depending on flag
if (noCopy){
data = (char*)data_;
}else{
if (noCopy) {
data = (char *)data_;
} else {
resize(len);
memcpy(data, data_, len);
}
//check header type and store packet length
dataLen = len;
version = DTSC_INVALID;
if (len > 3){
if (!memcmp(data, Magic_Packet2, 4)){
if (len > 3) {
if (!memcmp(data, Magic_Packet2, 4)) {
version = DTSC_V2;
}else{
if (!memcmp(data, Magic_Packet, 4)){
} else {
if (!memcmp(data, Magic_Packet, 4)) {
version = DTSC_V1;
}else{
if (!memcmp(data, Magic_Header, 4)){
} else {
if (!memcmp(data, Magic_Header, 4)) {
version = DTSC_HEAD;
}else{
} else {
DEBUG_MSG(DLVL_FAIL, "ReInit received a packet with invalid header");
return;
}
}
}
}else{
} else {
DEBUG_MSG(DLVL_FAIL, "ReInit received a packet with size < 4");
return;
}
}
/// Helper function for skipping over whole DTSC parts
static char * skipDTSC(char * p, char * max){
if (p+1 >= max || p[0] == 0x00){
static char * skipDTSC(char * p, char * max) {
if (p + 1 >= max || p[0] == 0x00) {
return 0;//out of packet! 1 == error
}
if (p[0] == DTSC_INT){
if (p[0] == DTSC_INT) {
//int, skip 9 bytes to next value
return p+9;
return p + 9;
}
if (p[0] == DTSC_STR){
if (p+4 >= max){
if (p[0] == DTSC_STR) {
if (p + 4 >= max) {
return 0;//out of packet!
}
return p + 5 + p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4];
}
if (p[0] == DTSC_OBJ || p[0] == DTSC_CON){
if (p[0] == DTSC_OBJ || p[0] == DTSC_CON) {
p++;
//object, scan contents
while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE)
if (p+2 >= max){
while (p[0] + p[1] != 0 && p < max) { //while not encountering 0x0000 (we assume 0x0000EE)
if (p + 2 >= max) {
return 0;//out of packet!
}
p += 2 + (p[0] * 256 + p[1]);//skip size
//otherwise, search through the contents, if needed, and continue
p = skipDTSC(p, max);
if (!p){
if (!p) {
return 0;
}
}
return p+3;
return p + 3;
}
if (p[0] == DTSC_ARR){
if (p[0] == DTSC_ARR) {
p++;
//array, scan contents
while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE)
while (p[0] + p[1] != 0 && p < max) { //while not encountering 0x0000 (we assume 0x0000EE)
//search through contents...
p = skipDTSC(p, max);
if (!p){
if (!p) {
return 0;
}
}
@ -232,28 +232,28 @@ namespace DTSC {
///\param identifier The name of the parameter
///\param result A location on which the string will be returned
///\param len An integer in which the length of the string will be returned
void Packet::getString(const char * identifier, char *& result, unsigned int & len) const{
void Packet::getString(const char * identifier, char *& result, unsigned int & len) const {
getScan().getMember(identifier).getString(result, len);
}
///\brief Retrieves a single parameter as a string
///\param identifier The name of the parameter
///\param result The string in which to store the result
void Packet::getString(const char * identifier, std::string & result) const{
void Packet::getString(const char * identifier, std::string & result) const {
result = getScan().getMember(identifier).asString();
}
///\brief Retrieves a single parameter as an integer
///\param identifier The name of the parameter
///\param result The result is stored in this integer
void Packet::getInt(const char * identifier, int & result) const{
void Packet::getInt(const char * identifier, int & result) const {
result = getScan().getMember(identifier).asInt();
}
///\brief Retrieves a single parameter as an integer
///\param identifier The name of the parameter
///\result The requested parameter as an integer
int Packet::getInt(const char * identifier) const{
int Packet::getInt(const char * identifier) const {
int result;
getInt(identifier, result);
return result;
@ -262,7 +262,7 @@ namespace DTSC {
///\brief Retrieves a single parameter as a boolean
///\param identifier The name of the parameter
///\param result The result is stored in this boolean
void Packet::getFlag(const char * identifier, bool & result) const{
void Packet::getFlag(const char * identifier, bool & result) const {
int result_;
getInt(identifier, result_);
result = (bool)result_;
@ -271,7 +271,7 @@ namespace DTSC {
///\brief Retrieves a single parameter as a boolean
///\param identifier The name of the parameter
///\result The requested parameter as a boolean
bool Packet::getFlag(const char * identifier) const{
bool Packet::getFlag(const char * identifier) const {
bool result;
getFlag(identifier, result);
return result;
@ -280,15 +280,17 @@ namespace DTSC {
///\brief Checks whether a parameter exists
///\param identifier The name of the parameter
///\result Whether the parameter exists or not
bool Packet::hasMember(const char * identifier) const{
bool Packet::hasMember(const char * identifier) const {
return getScan().getMember(identifier).getType() > 0;
}
///\brief Returns the timestamp of the packet.
///\return The timestamp of this packet.
long long unsigned int Packet::getTime() const{
if (version != DTSC_V2){
if (!data){return 0;}
long long unsigned int Packet::getTime() const {
if (version != DTSC_V2) {
if (!data) {
return 0;
}
return getInt("time");
}
return ((long long int)ntohl(((int *)(data + 12))[0]) << 32) | ntohl(((int *)(data + 12))[1]);
@ -296,8 +298,8 @@ namespace DTSC {
///\brief Returns the track id of the packet.
///\return The track id of this packet.
long int Packet::getTrackId() const{
if (version != DTSC_V2){
long int Packet::getTrackId() const {
if (version != DTSC_V2) {
return getInt("trackid");
}
return ntohl(((int *)data)[2]);
@ -305,84 +307,84 @@ namespace DTSC {
///\brief Returns a pointer to the payload of this packet.
///\return A pointer to the payload of this packet.
char * Packet::getData() const{
char * Packet::getData() const {
return data;
}
///\brief Returns the size of this packet.
///\return The size of this packet.
int Packet::getDataLen() const{
int Packet::getDataLen() const {
return dataLen;
}
///\brief Returns the size of the payload of this packet.
///\return The size of the payload of this packet.
int Packet::getPayloadLen() const{
if (version == DTSC_V2){
return dataLen-20;
}else{
return dataLen-8;
int Packet::getPayloadLen() const {
if (version == DTSC_V2) {
return dataLen - 20;
} else {
return dataLen - 8;
}
}
/// Returns a DTSC::Scan instance to the contents of this packet.
/// May return an invalid instance if this packet is invalid.
Scan Packet::getScan() const{
return Scan(data+(getDataLen()-getPayloadLen()), getPayloadLen());
Scan Packet::getScan() const {
return Scan(data + (getDataLen() - getPayloadLen()), getPayloadLen());
}
///\brief Converts the packet into a JSON value
///\return A JSON::Value representation of this packet.
JSON::Value Packet::toJSON() const{
JSON::Value Packet::toJSON() const {
JSON::Value result;
unsigned int i = 8;
if (getVersion() == DTSC_V1){
if (getVersion() == DTSC_V1) {
JSON::fromDTMI((const unsigned char *)data, dataLen, i, result);
}
if (getVersion() == DTSC_V2){
if (getVersion() == DTSC_V2) {
JSON::fromDTMI2((const unsigned char *)data, dataLen, i, result);
}
return result;
}
/// Create an invalid DTSC::Scan object by default.
Scan::Scan(){
Scan::Scan() {
p = 0;
len = 0;
}
/// Create a DTSC::Scan object from memory pointer.
Scan::Scan(char * pointer, size_t length){
Scan::Scan(char * pointer, size_t length) {
p = pointer;
len = length;
}
/// Returns an object representing the named indice of this object.
/// Returns an invalid object if this indice doesn't exist or this isn't an object type.
Scan Scan::getMember(std::string indice){
Scan Scan::getMember(std::string indice) {
return getMember(indice.data(), indice.size());
}
/// Returns an object representing the named indice of this object.
/// Returns an invalid object if this indice doesn't exist or this isn't an object type.
Scan Scan::getMember(const char * indice, const unsigned int ind_len){
if (getType() != DTSC_OBJ && getType() != DTSC_CON){
Scan Scan::getMember(const char * indice, const unsigned int ind_len) {
if (getType() != DTSC_OBJ && getType() != DTSC_CON) {
return Scan();
}
char * i = p+1;
char * i = p + 1;
//object, scan contents
while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE)
if (i+2 >= p+len){
while (i[0] + i[1] != 0 && i < p + len) { //while not encountering 0x0000 (we assume 0x0000EE)
if (i + 2 >= p + len) {
return Scan();//out of packet!
}
unsigned int strlen = i[0] * 256 + i[1];
i += 2;
if (ind_len == strlen && strncmp(indice, i, strlen) == 0){
return Scan(i+strlen, len-(i-p));
}else{
i = skipDTSC(i+strlen, p+len);
if (!i){
if (ind_len == strlen && strncmp(indice, i, strlen) == 0) {
return Scan(i + strlen, len - (i - p));
} else {
i = skipDTSC(i + strlen, p + len);
if (!i) {
return Scan();
}
}
@ -392,47 +394,47 @@ namespace DTSC {
/// Returns an object representing the named indice of this object.
/// Returns an invalid object if this indice doesn't exist or this isn't an object type.
Scan Scan::getMember(const char * indice){
Scan Scan::getMember(const char * indice) {
return getMember(indice, strlen(indice));
}
/// Returns an object representing the num-th indice of this array.
/// If not an array but an object, it returns the num-th member, instead.
/// Returns an invalid object if this indice doesn't exist or this isn't an array or object type.
Scan Scan::getIndice(unsigned int num){
if (getType() == DTSC_ARR){
char * i = p+1;
Scan Scan::getIndice(unsigned int num) {
if (getType() == DTSC_ARR) {
char * i = p + 1;
unsigned int arr_indice = 0;
//array, scan contents
while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE)
while (i[0] + i[1] != 0 && i < p + len) { //while not encountering 0x0000 (we assume 0x0000EE)
//search through contents...
if (arr_indice == num){
return Scan(i, len-(i-p));
}else{
if (arr_indice == num) {
return Scan(i, len - (i - p));
} else {
arr_indice++;
i = skipDTSC(i, p+len);
if (!i){
i = skipDTSC(i, p + len);
if (!i) {
return Scan();
}
}
}
}
if (getType() == DTSC_OBJ || getType() == DTSC_CON){
char * i = p+1;
if (getType() == DTSC_OBJ || getType() == DTSC_CON) {
char * i = p + 1;
unsigned int arr_indice = 0;
//object, scan contents
while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE)
if (i+2 >= p+len){
while (i[0] + i[1] != 0 && i < p + len) { //while not encountering 0x0000 (we assume 0x0000EE)
if (i + 2 >= p + len) {
return Scan();//out of packet!
}
unsigned int strlen = i[0] * 256 + i[1];
i += 2;
if (arr_indice == num){
return Scan(i+strlen, len-(i-p));
}else{
if (arr_indice == num) {
return Scan(i + strlen, len - (i - p));
} else {
arr_indice++;
i = skipDTSC(i+strlen, p+len);
if (!i){
i = skipDTSC(i + strlen, p + len);
if (!i) {
return Scan();
}
}
@ -442,8 +444,10 @@ namespace DTSC {
}
/// Returns the first byte of this DTSC value, or 0 on error.
char Scan::getType(){
if (!p){return 0;}
char Scan::getType() {
if (!p) {
return 0;
}
return p[0];
}
@ -452,8 +456,8 @@ namespace DTSC {
/// Strings are checked for non-zero length.
/// Objects and arrays are checked for content.
/// Returns false on error or in other cases.
bool Scan::asBool(){
switch (getType()){
bool Scan::asBool() {
switch (getType()) {
case DTSC_STR:
return (p[1] | p[2] | p[3] | p[4]);
case DTSC_INT:
@ -470,15 +474,17 @@ namespace DTSC {
/// Returns the long long value of this DTSC number value.
/// Will convert string values to numbers, taking octal and hexadecimal types into account.
/// Illegal or invalid values return 0.
long long Scan::asInt(){
switch (getType()){
long long Scan::asInt() {
switch (getType()) {
case DTSC_INT:
return ((long long int)p[1] << 56) | ((long long int)p[2] << 48) | ((long long int)p[3] << 40) | ((long long int)p[4] << 32) | ((long long int)p[5] << 24) | ((long long int)p[6] << 16) | ((long long int)p[7] << 8) | p[8];
case DTSC_STR:
char * str;
unsigned int strlen;
getString(str, strlen);
if (!strlen){return 0;}
if (!strlen) {
return 0;
}
return strtoll(str, 0, 0);
default:
return 0;
@ -488,7 +494,7 @@ namespace DTSC {
/// Returns the string value of this DTSC string value.
/// Uses getString internally, does no conversion.
/// Returns an empty string on error.
std::string Scan::asString(){
std::string Scan::asString() {
char * str;
unsigned int strlen;
getString(str, strlen);
@ -498,10 +504,10 @@ namespace DTSC {
/// Sets result to a pointer to the string, and strlen to the lenght of it.
/// Sets both to zero if this isn't a DTSC string value.
/// Attempts absolutely no conversion.
void Scan::getString(char *& result, unsigned int & strlen){
switch (getType()){
void Scan::getString(char *& result, unsigned int & strlen) {
switch (getType()) {
case DTSC_STR:
result = p+5;
result = p + 5;
strlen = p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4];
return;
default:
@ -512,18 +518,22 @@ namespace DTSC {
}
/// \todo Move this function to some generic area. Duplicate from json.cpp
static inline char hex2c(char c){
if (c < 10){return '0' + c;}
if (c < 16){return 'A' + (c - 10);}
static inline char hex2c(char c) {
if (c < 10) {
return '0' + c;
}
if (c < 16) {
return 'A' + (c - 10);
}
return '0';
}
/// \todo Move this function to some generic area. Duplicate from json.cpp
static std::string string_escape(const std::string val){
static std::string string_escape(const std::string val) {
std::stringstream out;
out << "\"";
for (unsigned int i = 0; i < val.size(); ++i){
switch (val.data()[i]){
for (unsigned int i = 0; i < val.size(); ++i) {
switch (val.data()[i]) {
case '"':
out << "\\\"";
break;
@ -546,11 +556,11 @@ namespace DTSC {
out << "\\t";
break;
default:
if (val.data()[i] < 32 || val.data()[i] > 126){
if (val.data()[i] < 32 || val.data()[i] > 126) {
out << "\\u00";
out << hex2c((val.data()[i] >> 4) & 0xf);
out << hex2c(val.data()[i] & 0xf);
}else{
} else {
out << val.data()[i];
}
break;
@ -560,40 +570,40 @@ namespace DTSC {
return out.str();
}
std::string Scan::toPrettyString(unsigned int indent){
switch (getType()){
case DTSC_STR:{
std::string Scan::toPrettyString(unsigned int indent) {
switch (getType()) {
case DTSC_STR: {
unsigned int strlen = p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4];
if (strlen > 250){
if (strlen > 250) {
std::stringstream ret;
ret << "\"" << strlen << " bytes of data\"";
return ret.str();
}
return string_escape(asString());
}
case DTSC_INT:{
case DTSC_INT: {
std::stringstream ret;
ret << asInt();
return ret.str();
}
case DTSC_OBJ:
case DTSC_CON:{
case DTSC_CON: {
std::stringstream ret;
ret << "{" << std::endl;
indent += 2;
char * i = p+1;
char * i = p + 1;
//object, scan contents
while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE)
if (i+2 >= p+len){
while (i[0] + i[1] != 0 && i < p + len) { //while not encountering 0x0000 (we assume 0x0000EE)
if (i + 2 >= p + len) {
indent -= 2;
ret << std::string((size_t)indent, ' ') << "} //walked out of object here";
return ret.str();
}
unsigned int strlen = i[0] * 256 + i[1];
i += 2;
ret << std::string((size_t)indent, ' ') << "\"" << std::string(i, strlen) << "\": " << Scan(i+strlen, len-(i-p)).toPrettyString(indent) << "," << std::endl;
i = skipDTSC(i+strlen, p+len);
if (!i){
ret << std::string((size_t)indent, ' ') << "\"" << std::string(i, strlen) << "\": " << Scan(i + strlen, len - (i - p)).toPrettyString(indent) << "," << std::endl;
i = skipDTSC(i + strlen, p + len);
if (!i) {
indent -= 2;
ret << std::string((size_t)indent, ' ') << "} //could not locate next object";
return ret.str();
@ -603,7 +613,7 @@ namespace DTSC {
ret << std::string((size_t)indent, ' ') << "}";
return ret.str();
}
case DTSC_ARR:{
case DTSC_ARR: {
std::stringstream ret;
ret << "[" << std::endl;
indent += 2;
@ -611,10 +621,10 @@ namespace DTSC {
unsigned int i = 0;
do {
tmpScan = getIndice(i++);
if (tmpScan.getType()){
if (tmpScan.getType()) {
ret << std::string((size_t)indent, ' ') << tmpScan.toPrettyString(indent) << "," << std::endl;
}
}while(tmpScan.getType());
} while (tmpScan.getType());
indent -= 2;
ret << std::string((size_t)indent, ' ') << "]";
return ret.str();
@ -666,7 +676,7 @@ namespace DTSC {
///\brief Converts a part to a human readable string
///\param str The stringstream to append to
///\param indent the amount of indentation needed
void Part::toPrettyString(std::ostream & str, int indent){
void Part::toPrettyString(std::ostream & str, int indent) {
str << std::string(indent, ' ') << "Part: Size(" << getSize() << "), Dur(" << getDuration() << "), Offset(" << getOffset() << ")" << std::endl;
}
@ -734,7 +744,7 @@ namespace DTSC {
///\brief Converts a keyframe to a human readable string
///\param str The stringstream to append to
///\param indent the amount of indentation needed
void Key::toPrettyString(std::ostream & str, int indent){
void Key::toPrettyString(std::ostream & str, int indent) {
str << std::string(indent, ' ') << "Key " << getNumber() << ": Pos(" << getBpos() << "), Dur(" << getLength() << "), Parts(" << getParts() << "), Time(" << getTime() << ")" << std::endl;
}
@ -786,7 +796,7 @@ namespace DTSC {
///\brief Converts a fragment to a human readable string
///\param str The stringstream to append to
///\param indent the amount of indentation needed
void Fragment::toPrettyString(std::ostream & str, int indent){
void Fragment::toPrettyString(std::ostream & str, int indent) {
str << std::string(indent, ' ') << "Fragment " << getNumber() << ": Dur(" << getDuration() << "), Len(" << (int)getLength() << "), Size(" << getSize() << ")" << std::endl;
}
@ -941,19 +951,19 @@ namespace DTSC {
///\brief Constructs a track from a JSON::Value
Track::Track(Scan & trackRef) {
if (trackRef.getMember("fragments").getType() == DTSC_STR){
if (trackRef.getMember("fragments").getType() == DTSC_STR) {
char * tmp = 0;
unsigned int tmplen = 0;
trackRef.getMember("fragments").getString(tmp, tmplen);
fragments = std::deque<Fragment>((Fragment *)tmp, ((Fragment *)tmp) + (tmplen / 11));
}
if (trackRef.getMember("keys").getType() == DTSC_STR){
if (trackRef.getMember("keys").getType() == DTSC_STR) {
char * tmp = 0;
unsigned int tmplen = 0;
trackRef.getMember("keys").getString(tmp, tmplen);
keys = std::deque<Key>((Key *)tmp, ((Key *)tmp) + (tmplen / 16));
}
if (trackRef.getMember("parts").getType() == DTSC_STR){
if (trackRef.getMember("parts").getType() == DTSC_STR) {
char * tmp = 0;
unsigned int tmplen = 0;
trackRef.getMember("parts").getString(tmp, tmplen);
@ -1187,19 +1197,19 @@ namespace DTSC {
///\param str The stringstream to append to
///\param indent the amount of indentation needed
///\param verbosity How verbose the output needs to be
void readOnlyTrack::toPrettyString(std::ostream & str, int indent, int verbosity){
void readOnlyTrack::toPrettyString(std::ostream & str, int indent, int verbosity) {
str << std::string(indent, ' ') << "Track " << getWritableIdentifier() << std::endl;
str << std::string(indent + 2, ' ') << "ID: " << trackID << std::endl;
str << std::string(indent + 2, ' ') << "Firstms: " << firstms << std::endl;
str << std::string(indent + 2, ' ') << "Lastms: " << lastms << std::endl;
str << std::string(indent + 2, ' ') << "Bps: " << bps << std::endl;
if (missedFrags){
if (missedFrags) {
str << std::string(indent + 2, ' ') << "missedFrags: " << missedFrags << std::endl;
}
str << std::string(indent + 2, ' ') << "Codec: " << codec << std::endl;
str << std::string(indent + 2, ' ') << "Type: " << type << std::endl;
str << std::string(indent + 2, ' ') << "Init: ";
for (unsigned int i = 0; i < init.size(); ++i){
for (unsigned int i = 0; i < init.size(); ++i) {
str << std::hex << std::setw(2) << std::setfill('0') << (int)init[i];
}
str << std::dec << std::endl;
@ -1217,20 +1227,20 @@ namespace DTSC {
str << std::string(indent + 2, ' ') << "CommentHeader: " << commentHeader << std::endl;
}
str << std::string(indent + 2, ' ') << "Fragments: " << fragLen << std::endl;
if (fragments && verbosity & 0x01){
for (unsigned int i = 0; i < fragLen; i++){
if (fragments && verbosity & 0x01) {
for (unsigned int i = 0; i < fragLen; i++) {
fragments[i].toPrettyString(str, indent + 4);
}
}
str << std::string(indent + 2, ' ') << "Keys: " << keyLen << std::endl;
if (keys && verbosity & 0x02) {
for (unsigned int i = 0; i < keyLen; i++){
for (unsigned int i = 0; i < keyLen; i++) {
keys[i].toPrettyString(str, indent + 4);
}
}
str << std::string(indent + 2, ' ') << "Parts: " << partLen << std::endl;
if (parts && verbosity & 0x04) {
for (unsigned int i = 0; i < partLen; i++){
for (unsigned int i = 0; i < partLen; i++) {
parts[i].toPrettyString(str, indent + 4);
}
}
@ -1257,11 +1267,11 @@ namespace DTSC {
moreheader = rhs.moreheader;
}
Meta::Meta(const DTSC::Packet & source){
Meta::Meta(const DTSC::Packet & source) {
reinit(source);
}
void Meta::reinit(const DTSC::Packet & source){
void Meta::reinit(const DTSC::Packet & source) {
tracks.clear();
vod = source.getFlag("vod");
live = source.getFlag("live");
@ -1271,16 +1281,16 @@ namespace DTSC {
Scan tmpTracks = source.getScan().getMember("tracks");
unsigned int num = 0;
Scan tmpTrack;
do{
do {
tmpTrack = tmpTracks.getIndice(num);
if (tmpTrack.asBool()){
if (tmpTrack.asBool()) {
int trackId = tmpTrack.getMember("trackid").asInt();
if (trackId){
if (trackId) {
tracks[trackId] = Track(tmpTrack);
}
num++;
}
}while(tmpTrack.asBool());
} while (tmpTrack.asBool());
}
///\brief Creates a meta object from a JSON::Value
@ -1326,19 +1336,19 @@ namespace DTSC {
///\param str The stringstream to append to
///\param indent the amount of indentation needed
///\param verbosity How verbose the output needs to be
void Track::toPrettyString(std::ostream & str, int indent, int verbosity){
void Track::toPrettyString(std::ostream & str, int indent, int verbosity) {
str << std::string(indent, ' ') << "Track " << getWritableIdentifier() << std::endl;
str << std::string(indent + 2, ' ') << "ID: " << trackID << std::endl;
str << std::string(indent + 2, ' ') << "Firstms: " << firstms << std::endl;
str << std::string(indent + 2, ' ') << "Lastms: " << lastms << std::endl;
str << std::string(indent + 2, ' ') << "Bps: " << bps << std::endl;
if (missedFrags){
if (missedFrags) {
str << std::string(indent + 2, ' ') << "missedFrags: " << missedFrags << std::endl;
}
str << std::string(indent + 2, ' ') << "Codec: " << codec << std::endl;
str << std::string(indent + 2, ' ') << "Type: " << type << std::endl;
str << std::string(indent + 2, ' ') << "Init: ";
for (unsigned int i = 0; i < init.size(); ++i){
for (unsigned int i = 0; i < init.size(); ++i) {
str << std::hex << std::setw(2) << std::setfill('0') << (int)init[i];
}
str << std::dec << std::endl;
@ -1356,20 +1366,20 @@ namespace DTSC {
str << std::string(indent + 2, ' ') << "CommentHeader: " << commentHeader << std::endl;
}
str << std::string(indent + 2, ' ') << "Fragments: " << fragments.size() << std::endl;
if (verbosity & 0x01){
for (unsigned int i = 0; i < fragments.size(); i++){
if (verbosity & 0x01) {
for (unsigned int i = 0; i < fragments.size(); i++) {
fragments[i].toPrettyString(str, indent + 4);
}
}
str << std::string(indent + 2, ' ') << "Keys: " << keys.size() << std::endl;
if (verbosity & 0x02) {
for (unsigned int i = 0; i < keys.size(); i++){
for (unsigned int i = 0; i < keys.size(); i++) {
keys[i].toPrettyString(str, indent + 4);
}
}
str << std::string(indent + 2, ' ') << "Parts: " << parts.size() << std::endl;
if (verbosity & 0x04) {
for (unsigned int i = 0; i < parts.size(); i++){
for (unsigned int i = 0; i < parts.size(); i++) {
parts[i].toPrettyString(str, indent + 4);
}
}
@ -1452,7 +1462,7 @@ namespace DTSC {
///\brief Writes a pointer to the specified destination
///
///Does a memcpy and increases the destination pointer accordingly
static void writePointer(char *& p, const char * src, unsigned int len){
static void writePointer(char *& p, const char * src, unsigned int len) {
memcpy(p, src, len);
p += len;
}
@ -1460,12 +1470,12 @@ namespace DTSC {
///\brief Writes a pointer to the specified destination
///
///Does a memcpy and increases the destination pointer accordingly
static void writePointer(char *& p, const std::string & src){
static void writePointer(char *& p, const std::string & src) {
writePointer(p, src.data(), src.size());
}
///\brief Writes a read-only track to a pointer
void readOnlyTrack::writeTo(char *& p){
void readOnlyTrack::writeTo(char *& p) {
std::string iden = getWritableIdentifier();
writePointer(p, convertShort(iden.size()), 2);
writePointer(p, iden);
@ -1588,7 +1598,7 @@ namespace DTSC {
}
///\brief Writes a track to a pointer
void Track::writeTo(char *& p){
void Track::writeTo(char *& p) {
writePointer(p, convertShort(getWritableIdentifier().size()), 2);
writePointer(p, getWritableIdentifier());
writePointer(p, "\340", 1);//Begin track object
@ -1722,16 +1732,16 @@ namespace DTSC {
}
///\brief Determines the "packed" size of a read-only meta object
unsigned int readOnlyMeta::getSendLen(){
unsigned int readOnlyMeta::getSendLen() {
unsigned int dataLen = 16 + (vod ? 14 : 0) + (live ? 15 : 0) + (merged ? 17 : 0) + (bufferWindow ? 24 : 0) + 21;
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
dataLen += it->second.getSendLen();
}
return dataLen+8;//add 8 bytes header length
return dataLen + 8; //add 8 bytes header length
}
///\brief Writes a read-only meta object to a pointer
void readOnlyMeta::writeTo(char * p){
void readOnlyMeta::writeTo(char * p) {
int dataLen = getSendLen() - 8;//strip 8 bytes header
writePointer(p, DTSC::Magic_Header, 4);
writePointer(p, convertInt(dataLen), 4);
@ -1763,7 +1773,7 @@ namespace DTSC {
///\brief Writes a read-only meta object to a socket
void readOnlyMeta::send(Socket::Connection & conn) {
int dataLen = getSendLen()-8;//strip 8 bytes header
int dataLen = getSendLen() - 8; //strip 8 bytes header
conn.SendNow(DTSC::Magic_Header, 4);
conn.SendNow(convertInt(dataLen), 4);
conn.SendNow("\340\000\006tracks\340", 10);
@ -1793,17 +1803,17 @@ namespace DTSC {
}
///\brief Determines the "packed" size of a meta object
unsigned int Meta::getSendLen(){
unsigned int Meta::getSendLen() {
unsigned int dataLen = 16 + (vod ? 14 : 0) + (live ? 15 : 0) + (merged ? 17 : 0) + (bufferWindow ? 24 : 0) + 21;
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
dataLen += it->second.getSendLen();
}
return dataLen+8;//add 8 bytes header
return dataLen + 8; //add 8 bytes header
}
///\brief Writes a meta object to a pointer
void Meta::writeTo(char * p){
int dataLen = getSendLen()-8;//strip 8 bytes header
void Meta::writeTo(char * p) {
int dataLen = getSendLen() - 8; //strip 8 bytes header
writePointer(p, DTSC::Magic_Header, 4);
writePointer(p, convertInt(dataLen), 4);
writePointer(p, "\340\000\006tracks\340", 10);
@ -1834,7 +1844,7 @@ namespace DTSC {
///\brief Writes a meta object to a socket
void Meta::send(Socket::Connection & conn) {
int dataLen = getSendLen()-8;//strip 8 bytes header
int dataLen = getSendLen() - 8; //strip 8 bytes header
conn.SendNow(DTSC::Magic_Header, 4);
conn.SendNow(convertInt(dataLen), 4);
conn.SendNow("\340\000\006tracks\340", 10);
@ -1974,7 +1984,7 @@ namespace DTSC {
///\param str The stringstream to append to
///\param indent the amount of indentation needed
///\param verbosity How verbose the output needs to be
void readOnlyMeta::toPrettyString(std::ostream & str, int indent, int verbosity){
void readOnlyMeta::toPrettyString(std::ostream & str, int indent, int verbosity) {
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
it->second.toPrettyString(str, indent, verbosity);
}
@ -1997,7 +2007,7 @@ namespace DTSC {
///\param str The stringstream to append to
///\param indent the amount of indentation needed
///\param verbosity How verbose the output needs to be
void Meta::toPrettyString(std::ostream & str, int indent, int verbosity){
void Meta::toPrettyString(std::ostream & str, int indent, int verbosity) {
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
it->second.toPrettyString(str, indent, verbosity);
}

View file

@ -1,32 +1,32 @@
#include "filesystem.h"
#include "defines.h"
Filesystem::Directory::Directory(std::string PathName, std::string BasePath){
Filesystem::Directory::Directory(std::string PathName, std::string BasePath) {
MyBase = BasePath;
if (PathName[0] == '/'){
if (PathName[0] == '/') {
PathName.erase(0, 1);
}
if (BasePath[BasePath.size() - 1] != '/'){
if (BasePath[BasePath.size() - 1] != '/') {
BasePath += "/";
}
MyPath = PathName;
FillEntries();
}
Filesystem::Directory::~Directory(){
Filesystem::Directory::~Directory() {
}
void Filesystem::Directory::FillEntries(){
void Filesystem::Directory::FillEntries() {
ValidDir = true;
struct stat StatBuf;
Entries.clear();
DIR * Dirp = opendir((MyBase + MyPath).c_str());
if ( !Dirp){
if (!Dirp) {
ValidDir = false;
}else{
} else {
dirent * entry;
while ((entry = readdir(Dirp))){
if (stat((MyBase + MyPath + "/" + entry->d_name).c_str(), &StatBuf) == -1){
while ((entry = readdir(Dirp))) {
if (stat((MyBase + MyPath + "/" + entry->d_name).c_str(), &StatBuf) == -1) {
DEBUG_MSG(DLVL_DEVEL, "Skipping %s, reason %s", entry->d_name, strerror(errno));
continue;
}
@ -36,173 +36,173 @@ void Filesystem::Directory::FillEntries(){
}
}
void Filesystem::Directory::Print(){
void Filesystem::Directory::Print() {
/// \todo Remove? Libraries shouldn't print stuff.
if ( !ValidDir){
if (!ValidDir) {
DEBUG_MSG(DLVL_ERROR, "%s is not a valid directory", (MyBase + MyPath).c_str());
return;
}
printf("%s:\n", (MyBase + MyPath).c_str());
for (std::map<std::string, struct stat>::iterator it = Entries.begin(); it != Entries.end(); it++){
printf("\t%s\n", ( *it).first.c_str());
for (std::map<std::string, struct stat>::iterator it = Entries.begin(); it != Entries.end(); it++) {
printf("\t%s\n", (*it).first.c_str());
}
printf("\n");
}
bool Filesystem::Directory::IsDir(){
bool Filesystem::Directory::IsDir() {
return ValidDir;
}
std::string Filesystem::Directory::PWD(){
std::string Filesystem::Directory::PWD() {
return "/" + MyPath;
}
std::string Filesystem::Directory::LIST(std::vector<std::string> ActiveStreams){
std::string Filesystem::Directory::LIST(std::vector<std::string> ActiveStreams) {
FillEntries();
int MyPermissions;
std::stringstream Converter;
passwd* pwd; //For Username
group* grp; //For Groupname
tm* tm; //For time localisation
passwd * pwd; //For Username
group * grp; //For Groupname
tm * tm; //For time localisation
char datestring[256]; //For time localisation
std::string MyLoc = MyBase + MyPath;
if (MyLoc[MyLoc.size() - 1] != '/'){
if (MyLoc[MyLoc.size() - 1] != '/') {
MyLoc += "/";
}
for (std::map<std::string, struct stat>::iterator it = Entries.begin(); it != Entries.end(); it++){
for (std::map<std::string, struct stat>::iterator it = Entries.begin(); it != Entries.end(); it++) {
bool Active = (std::find(ActiveStreams.begin(), ActiveStreams.end(), ( *it).first) != ActiveStreams.end());
if ((Active && (MyVisible[MyPath] & S_ACTIVE)) || (( !Active) && (MyVisible[MyPath] & S_INACTIVE)) || ((( *it).second.st_mode / 010000) == 4)){
if ((( *it).second.st_mode / 010000) == 4){
bool Active = (std::find(ActiveStreams.begin(), ActiveStreams.end(), (*it).first) != ActiveStreams.end());
if ((Active && (MyVisible[MyPath] & S_ACTIVE)) || ((!Active) && (MyVisible[MyPath] & S_INACTIVE)) || (((*it).second.st_mode / 010000) == 4)) {
if (((*it).second.st_mode / 010000) == 4) {
Converter << 'd';
}else{
} else {
Converter << '-';
}
MyPermissions = ((( *it).second.st_mode % 010000) / 0100);
if (MyPermissions & 4){
MyPermissions = (((*it).second.st_mode % 010000) / 0100);
if (MyPermissions & 4) {
Converter << 'r';
}else{
} else {
Converter << '-';
}
if (MyPermissions & 2){
if (MyPermissions & 2) {
Converter << 'w';
}else{
} else {
Converter << '-';
}
if (MyPermissions & 1){
if (MyPermissions & 1) {
Converter << 'x';
}else{
} else {
Converter << '-';
}
MyPermissions = ((( *it).second.st_mode % 0100) / 010);
if (MyPermissions & 4){
MyPermissions = (((*it).second.st_mode % 0100) / 010);
if (MyPermissions & 4) {
Converter << 'r';
}else{
} else {
Converter << '-';
}
if (MyPermissions & 2){
if (MyPermissions & 2) {
Converter << 'w';
}else{
} else {
Converter << '-';
}
if (MyPermissions & 1){
if (MyPermissions & 1) {
Converter << 'x';
}else{
} else {
Converter << '-';
}
MyPermissions = (( *it).second.st_mode % 010);
if (MyPermissions & 4){
MyPermissions = ((*it).second.st_mode % 010);
if (MyPermissions & 4) {
Converter << 'r';
}else{
} else {
Converter << '-';
}
if (MyPermissions & 2){
if (MyPermissions & 2) {
Converter << 'w';
}else{
} else {
Converter << '-';
}
if (MyPermissions & 1){
if (MyPermissions & 1) {
Converter << 'x';
}else{
} else {
Converter << '-';
}
Converter << ' ';
Converter << ( *it).second.st_nlink;
Converter << (*it).second.st_nlink;
Converter << ' ';
if ((pwd = getpwuid(( *it).second.st_uid))){
if ((pwd = getpwuid((*it).second.st_uid))) {
Converter << pwd->pw_name;
}else{
Converter << ( *it).second.st_uid;
} else {
Converter << (*it).second.st_uid;
}
Converter << ' ';
if ((grp = getgrgid(( *it).second.st_gid))){
if ((grp = getgrgid((*it).second.st_gid))) {
Converter << grp->gr_name;
}else{
Converter << ( *it).second.st_gid;
} else {
Converter << (*it).second.st_gid;
}
Converter << ' ';
Converter << ( *it).second.st_size;
Converter << (*it).second.st_size;
Converter << ' ';
tm = localtime( &(( *it).second.st_mtime));
tm = localtime(&((*it).second.st_mtime));
strftime(datestring, sizeof(datestring), "%b %d %H:%M", tm);
Converter << datestring;
Converter << ' ';
Converter << ( *it).first;
Converter << (*it).first;
Converter << '\n';
}
}
return Converter.str();
}
bool Filesystem::Directory::CWD(std::string Path){
if (Path[0] == '/'){
bool Filesystem::Directory::CWD(std::string Path) {
if (Path[0] == '/') {
Path.erase(0, 1);
MyPath = Path;
}else{
if (MyPath != ""){
} else {
if (MyPath != "") {
MyPath += "/";
}
MyPath += Path;
}
FillEntries();
printf("New Path: %s\n", MyPath.c_str());
if (MyPermissions.find(MyPath) != MyPermissions.end()){
if (MyPermissions.find(MyPath) != MyPermissions.end()) {
printf("\tPermissions: %d\n", MyPermissions[MyPath]);
}
return SimplifyPath();
}
bool Filesystem::Directory::CDUP(){
bool Filesystem::Directory::CDUP() {
return CWD("..");
}
std::string Filesystem::Directory::RETR(std::string Path){
std::string Filesystem::Directory::RETR(std::string Path) {
std::string Result;
std::string FileName;
if (Path[0] == '/'){
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
}else{
} else {
FileName = MyBase + MyPath + "/" + Path;
}
std::ifstream File;
File.open(FileName.c_str());
while (File.good()){
while (File.good()) {
Result += File.get();
}
File.close();
return Result;
}
void Filesystem::Directory::STOR(std::string Path, std::string Data){
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_STOR)){
void Filesystem::Directory::STOR(std::string Path, std::string Data) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_STOR)) {
std::string FileName;
if (Path[0] == '/'){
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
}else{
} else {
FileName = MyBase + MyPath + "/" + Path;
}
std::ofstream File;
@ -212,48 +212,48 @@ void Filesystem::Directory::STOR(std::string Path, std::string Data){
}
}
bool Filesystem::Directory::SimplifyPath(){
bool Filesystem::Directory::SimplifyPath() {
MyPath += "/";
std::vector<std::string> TempPath;
std::string TempString;
for (std::string::iterator it = MyPath.begin(); it != MyPath.end(); it++){
if (( *it) == '/'){
if (TempString == ".."){
if ( !TempPath.size()){
for (std::string::iterator it = MyPath.begin(); it != MyPath.end(); it++) {
if ((*it) == '/') {
if (TempString == "..") {
if (!TempPath.size()) {
return false;
}
TempPath.erase((TempPath.end() - 1));
}else if (TempString != "." && TempString != ""){
} else if (TempString != "." && TempString != "") {
TempPath.push_back(TempString);
}
TempString = "";
}else{
TempString += ( *it);
} else {
TempString += (*it);
}
}
MyPath = "";
for (std::vector<std::string>::iterator it = TempPath.begin(); it != TempPath.end(); it++){
MyPath += ( *it);
if (it != (TempPath.end() - 1)){
for (std::vector<std::string>::iterator it = TempPath.begin(); it != TempPath.end(); it++) {
MyPath += (*it);
if (it != (TempPath.end() - 1)) {
MyPath += "/";
}
}
if (MyVisible.find(MyPath) == MyVisible.end()){
if (MyVisible.find(MyPath) == MyVisible.end()) {
MyVisible[MyPath] = S_ALL;
}
return true;
}
bool Filesystem::Directory::DELE(std::string Path){
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_DELE)){
bool Filesystem::Directory::DELE(std::string Path) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_DELE)) {
std::string FileName;
if (Path[0] == '/'){
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
}else{
} else {
FileName = MyBase + MyPath + "/" + Path;
}
if (std::remove(FileName.c_str())){
if (std::remove(FileName.c_str())) {
DEBUG_MSG(DLVL_ERROR, "Removing file %s failed", FileName.c_str());
return false;
}
@ -262,15 +262,15 @@ bool Filesystem::Directory::DELE(std::string Path){
return false;
}
bool Filesystem::Directory::MKD(std::string Path){
bool Filesystem::Directory::MKD(std::string Path) {
std::string FileName;
if (Path[0] == '/'){
if (Path[0] == '/') {
Path.erase(0, 1);
FileName = MyBase + Path;
}else{
} else {
FileName = MyBase + MyPath + "/" + Path;
}
if (mkdir(FileName.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)){
if (mkdir(FileName.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
DEBUG_MSG(DLVL_ERROR, "Creating directory %s failed", FileName.c_str());
return false;
}
@ -278,22 +278,22 @@ bool Filesystem::Directory::MKD(std::string Path){
return true;
}
bool Filesystem::Directory::Rename(std::string From, std::string To){
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_RNFT)){
bool Filesystem::Directory::Rename(std::string From, std::string To) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & P_RNFT)) {
std::string FileFrom;
if (From[0] == '/'){
if (From[0] == '/') {
From.erase(0, 1);
FileFrom = MyBase + From;
}else{
} else {
FileFrom = MyBase + MyPath + "/" + From;
}
std::string FileTo;
if (To[0] == '/'){
if (To[0] == '/') {
FileTo = MyBase + To;
}else{
} else {
FileTo = MyBase + MyPath + "/" + To;
}
if (std::rename(FileFrom.c_str(), FileTo.c_str())){
if (std::rename(FileFrom.c_str(), FileTo.c_str())) {
DEBUG_MSG(DLVL_ERROR, "Renaming %s to %s failed", FileFrom.c_str(), FileTo.c_str());
return false;
}
@ -302,17 +302,17 @@ bool Filesystem::Directory::Rename(std::string From, std::string To){
return false;
}
void Filesystem::Directory::SetPermissions(std::string Path, char Permissions){
void Filesystem::Directory::SetPermissions(std::string Path, char Permissions) {
MyPermissions[Path] = Permissions;
}
bool Filesystem::Directory::HasPermission(char Permission){
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & Permission)){
bool Filesystem::Directory::HasPermission(char Permission) {
if (MyPermissions.find(MyPath) == MyPermissions.end() || (MyPermissions[MyPath] & Permission)) {
return true;
}
return false;
}
void Filesystem::Directory::SetVisibility(std::string Pathname, char Visible){
void Filesystem::Directory::SetVisibility(std::string Pathname, char Visible) {
MyVisible[Pathname] = Visible;
}

View file

@ -21,7 +21,7 @@
#include <errno.h>
namespace Filesystem {
enum DIR_Permissions{
enum DIR_Permissions {
P_LIST = 0x01, //List
P_RETR = 0x02, //Retrieve
P_STOR = 0x04, //Store
@ -31,11 +31,11 @@ namespace Filesystem {
P_RMD = 0x40, //Remove directory
};
enum DIR_Show{
enum DIR_Show {
S_NONE = 0x00, S_ACTIVE = 0x01, S_INACTIVE = 0x02, S_ALL = 0x03,
};
class Directory{
class Directory {
public:
Directory(std::string PathName = "", std::string BasePath = ".");
~Directory();

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ namespace FLV {
bool is_header(char * header); ///< Checks the first 3 bytes for the string "FLV".
/// This class is used to hold, work with and get information about a single FLV tag.
class Tag{
class Tag {
public:
int len; ///< Actual length of tag.
bool isKeyframe; ///< True if current tag is a video keyframe.
@ -40,12 +40,12 @@ namespace FLV {
int offset();
void offset(int o);
Tag(); ///< Constructor for a new, empty, tag.
Tag(const Tag& O); ///< Copy constructor, copies the contents of an existing tag.
Tag & operator=(const Tag& O); ///< Assignment operator - works exactly like the copy constructor.
Tag(const RTMPStream::Chunk& O); ///<Copy constructor from a RTMP chunk.
Tag(const Tag & O); ///< Copy constructor, copies the contents of an existing tag.
Tag & operator=(const Tag & O); ///< Assignment operator - works exactly like the copy constructor.
Tag(const RTMPStream::Chunk & O); ///<Copy constructor from a RTMP chunk.
~Tag(); ///< Generic destructor.
//loader functions
bool ChunkLoader(const RTMPStream::Chunk& O);
bool ChunkLoader(const RTMPStream::Chunk & O);
bool DTSCLoader(DTSC::Stream & S);
bool DTSCLoader(DTSC::Packet & packData, DTSC::Track & track);
bool DTSCVideoInit(DTSC::Track & video);

View file

@ -1,6 +1,6 @@
#include "ftp.h"
FTP::User::User(Socket::Connection NewConnection, std::map<std::string, std::string> Credentials){
FTP::User::User(Socket::Connection NewConnection, std::map<std::string, std::string> Credentials) {
Conn = NewConnection;
MyPassivePort = 0;
USER = "";
@ -23,110 +23,110 @@ FTP::User::User(Socket::Connection NewConnection, std::map<std::string, std::str
MyDir.SetVisibility("OnDemand", Filesystem::S_ACTIVE);
JSON::Value MyConfig = JSON::fromFile("/tmp/mist/streamlist");
for (JSON::ObjIter it = MyConfig["streams"].ObjBegin(); it != MyConfig["streams"].ObjEnd(); it++){
std::string ThisStream = ( *it).second["channel"]["URL"].toString();
for (JSON::ObjIter it = MyConfig["streams"].ObjBegin(); it != MyConfig["streams"].ObjEnd(); it++) {
std::string ThisStream = (*it).second["channel"]["URL"].toString();
ThisStream.erase(ThisStream.begin());
ThisStream.erase(ThisStream.end() - 1);
while (ThisStream.find('/') != std::string::npos){
while (ThisStream.find('/') != std::string::npos) {
ThisStream.erase(0, ThisStream.find('/') + 1);
}
ActiveStreams.push_back(ThisStream);
}
}
FTP::User::~User(){
FTP::User::~User() {
}
int FTP::User::ParseCommand(std::string Command){
int FTP::User::ParseCommand(std::string Command) {
Commands ThisCmd = CMD_NOCMD;
if (Command.substr(0, 4) == "NOOP"){
if (Command.substr(0, 4) == "NOOP") {
ThisCmd = CMD_NOOP;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "USER"){
if (Command.substr(0, 4) == "USER") {
ThisCmd = CMD_USER;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "PASS"){
if (Command.substr(0, 4) == "PASS") {
ThisCmd = CMD_PASS;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "QUIT"){
if (Command.substr(0, 4) == "QUIT") {
ThisCmd = CMD_QUIT;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "PORT"){
if (Command.substr(0, 4) == "PORT") {
ThisCmd = CMD_PORT;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "RETR"){
if (Command.substr(0, 4) == "RETR") {
ThisCmd = CMD_RETR;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "STOR"){
if (Command.substr(0, 4) == "STOR") {
ThisCmd = CMD_STOR;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "TYPE"){
if (Command.substr(0, 4) == "TYPE") {
ThisCmd = CMD_TYPE;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "MODE"){
if (Command.substr(0, 4) == "MODE") {
ThisCmd = CMD_MODE;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "STRU"){
if (Command.substr(0, 4) == "STRU") {
ThisCmd = CMD_STRU;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "EPSV"){
if (Command.substr(0, 4) == "EPSV") {
ThisCmd = CMD_EPSV;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "PASV"){
if (Command.substr(0, 4) == "PASV") {
ThisCmd = CMD_PASV;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "LIST"){
if (Command.substr(0, 4) == "LIST") {
ThisCmd = CMD_LIST;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "CDUP"){
if (Command.substr(0, 4) == "CDUP") {
ThisCmd = CMD_CDUP;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "DELE"){
if (Command.substr(0, 4) == "DELE") {
ThisCmd = CMD_DELE;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "RNFR"){
if (Command.substr(0, 4) == "RNFR") {
ThisCmd = CMD_RNFR;
Command.erase(0, 5);
}
if (Command.substr(0, 4) == "RNTO"){
if (Command.substr(0, 4) == "RNTO") {
ThisCmd = CMD_RNTO;
Command.erase(0, 5);
}
if (Command.substr(0, 3) == "PWD"){
if (Command.substr(0, 3) == "PWD") {
ThisCmd = CMD_PWD;
Command.erase(0, 4);
}
if (Command.substr(0, 3) == "CWD"){
if (Command.substr(0, 3) == "CWD") {
ThisCmd = CMD_CWD;
Command.erase(0, 4);
}
if (Command.substr(0, 3) == "RMD"){
if (Command.substr(0, 3) == "RMD") {
ThisCmd = CMD_RMD;
Command.erase(0, 4);
}
if (Command.substr(0, 3) == "MKD"){
if (Command.substr(0, 3) == "MKD") {
ThisCmd = CMD_MKD;
Command.erase(0, 4);
}
if (ThisCmd != CMD_RNTO){
if (ThisCmd != CMD_RNTO) {
RNFR = "";
}
switch (ThisCmd){
switch (ThisCmd) {
case CMD_NOOP: {
return 200; //Command okay.
break;
@ -134,7 +134,7 @@ int FTP::User::ParseCommand(std::string Command){
case CMD_USER: {
USER = "";
PASS = "";
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
USER = Command;
@ -142,14 +142,14 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_PASS: {
if (USER == ""){
if (USER == "") {
return 503;
} //Bad sequence of commands
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
PASS = Command;
if ( !LoggedIn()){
if (!LoggedIn()) {
USER = "";
PASS = "";
return 530; //Not logged in.
@ -159,12 +159,12 @@ int FTP::User::ParseCommand(std::string Command){
}
case CMD_LIST: {
Socket::Connection Connected = Passive.accept();
if (Connected.connected()){
if (Connected.connected()) {
Conn.Send("125 Data connection already open; transfer starting.\n");
}else{
} else {
Conn.Send("150 File status okay; about to open data connection.\n");
}
while ( !Connected.connected()){
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string tmpstr = MyDir.LIST(ActiveStreams);
@ -178,10 +178,10 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_PORT: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
PORT = atoi(Command.c_str());
@ -189,7 +189,7 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_EPSV: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
MyPassivePort = (rand() % 9999);
@ -198,7 +198,7 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_PASV: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
MyPassivePort = (rand() % 9999) + 49152;
@ -207,22 +207,22 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_RETR: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_RETR)){
if (!MyDir.HasPermission(Filesystem::P_RETR)) {
return 550;
} //Access denied.
Socket::Connection Connected = Passive.accept();
if (Connected.connected()){
if (Connected.connected()) {
Conn.Send("125 Data connection already open; transfer starting.\n");
}else{
} else {
Conn.Send("150 File status okay; about to open data connection.\n");
}
while ( !Connected.connected()){
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string tmpstr = MyDir.RETR(Command);
@ -232,26 +232,26 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_STOR: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_STOR)){
if (!MyDir.HasPermission(Filesystem::P_STOR)) {
return 550;
} //Access denied.
Socket::Connection Connected = Passive.accept();
if (Connected.connected()){
if (Connected.connected()) {
Conn.Send("125 Data connection already open; transfer starting.\n");
}else{
} else {
Conn.Send("150 File status okay; about to open data connection.\n");
}
while ( !Connected.connected()){
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string Buffer;
while (Connected.spool()){
while (Connected.spool()) {
}
/// \todo Comment me back in. ^_^
//Buffer = Connected.Received();
@ -260,22 +260,22 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_TYPE: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (Command.size() != 1 && Command.size() != 3){
if (Command.size() != 1 && Command.size() != 3) {
return 501;
} //Syntax error in parameters or arguments.
switch (Command[0]){
switch (Command[0]) {
case 'A': {
if (Command.size() > 1){
if (Command[1] != ' '){
if (Command.size() > 1) {
if (Command[1] != ' ') {
return 501;
} //Syntax error in parameters or arguments.
if (Command[2] != 'N'){
if (Command[2] != 'N') {
return 504;
} //Command not implemented for that parameter.
}
@ -283,11 +283,11 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case 'I': {
if (Command.size() > 1){
if (Command[1] != ' '){
if (Command.size() > 1) {
if (Command[1] != ' ') {
return 501;
} //Syntax error in parameters or arguments.
if (Command[2] != 'N'){
if (Command[2] != 'N') {
return 504;
} //Command not implemented for that parameter.
}
@ -303,16 +303,16 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_MODE: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (Command.size() != 1){
if (Command.size() != 1) {
return 501;
} //Syntax error in parameters or arguments.
if (Command[0] != 'S'){
if (Command[0] != 'S') {
return 504;
} //Command not implemented for that parameter.
MODE = MODE_STREAM;
@ -320,16 +320,16 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_STRU: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (Command.size() != 1){
if (Command.size() != 1) {
return 501;
} //Syntax error in parameters or arguments.
switch (Command[0]){
switch (Command[0]) {
case 'F': {
STRU = STRU_FILE;
break;
@ -347,22 +347,22 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_PWD: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 550;
} //Not logged in.
if (Command != ""){
if (Command != "") {
return 501;
} //Syntax error in parameters or arguments.
return 2570; //257 -- 0 to indicate PWD over MKD
break;
}
case CMD_CWD: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
Filesystem::Directory TmpDir = MyDir;
if (TmpDir.CWD(Command)){
if (TmpDir.IsDir()){
if (TmpDir.CWD(Command)) {
if (TmpDir.IsDir()) {
MyDir = TmpDir;
return 250;
}
@ -371,15 +371,15 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_CDUP: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command != ""){
if (Command != "") {
return 501;
} //Syntax error in parameters or arguments.
Filesystem::Directory TmpDir = MyDir;
if (TmpDir.CDUP()){
if (TmpDir.IsDir()){
if (TmpDir.CDUP()) {
if (TmpDir.IsDir()) {
MyDir = TmpDir;
return 250;
}
@ -388,71 +388,71 @@ int FTP::User::ParseCommand(std::string Command){
break;
}
case CMD_DELE: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if ( !MyDir.DELE(Command)){
if (!MyDir.DELE(Command)) {
return 550;
}
return 250;
break;
}
case CMD_RMD: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_RMD)){
if (!MyDir.HasPermission(Filesystem::P_RMD)) {
return 550;
}
if ( !MyDir.DELE(Command)){
if (!MyDir.DELE(Command)) {
return 550;
}
return 250;
break;
}
case CMD_MKD: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_MKD)){
if (!MyDir.HasPermission(Filesystem::P_MKD)) {
return 550;
}
if ( !MyDir.MKD(Command)){
if (!MyDir.MKD(Command)) {
return 550;
}
return 2571;
break;
}
case CMD_RNFR: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
RNFR = Command;
return 350; //Awaiting further information
}
case CMD_RNTO: {
if ( !LoggedIn()){
if (!LoggedIn()) {
return 530;
} //Not logged in.
if (Command == ""){
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
if (RNFR == ""){
if (RNFR == "") {
return 503;
} //Bad sequence of commands
if ( !MyDir.Rename(RNFR, Command)){
if (!MyDir.Rename(RNFR, Command)) {
return 550;
}
return 250;
@ -464,22 +464,22 @@ int FTP::User::ParseCommand(std::string Command){
}
}
bool FTP::User::LoggedIn(){
if (USER == "" || PASS == ""){
bool FTP::User::LoggedIn() {
if (USER == "" || PASS == "") {
return false;
}
if ( !AllCredentials.size()){
if (!AllCredentials.size()) {
return true;
}
if ((AllCredentials.find(USER) != AllCredentials.end()) && AllCredentials[USER] == PASS){
if ((AllCredentials.find(USER) != AllCredentials.end()) && AllCredentials[USER] == PASS) {
return true;
}
return false;
}
std::string FTP::User::NumToMsg(int MsgNum){
std::string FTP::User::NumToMsg(int MsgNum) {
std::string Result;
switch (MsgNum){
switch (MsgNum) {
case 200: {
Result = "200 Message okay.\n";
break;

View file

@ -14,22 +14,22 @@
namespace FTP {
static std::string FTPBasePath = "/tmp/mist/OnDemand/";
enum Mode{
enum Mode {
MODE_STREAM,
};
//FTP::Mode enumeration
enum Structure{
enum Structure {
STRU_FILE, STRU_RECORD,
};
//FTP::Structure enumeration
enum Type{
enum Type {
TYPE_ASCII_NONPRINT, TYPE_IMAGE_NONPRINT,
};
//FTP::Type enumeration
enum Commands{
enum Commands {
CMD_NOCMD,
CMD_NOOP,
CMD_USER,
@ -55,7 +55,7 @@ namespace FTP {
};
//FTP::Commands enumeration
class User{
class User {
public:
User(Socket::Connection NewConnection, std::map<std::string, std::string> Credentials);
~User();

View file

@ -6,13 +6,13 @@
/// This constructor creates an empty HTTP::Parser, ready for use for either reading or writing.
/// All this constructor does is call HTTP::Parser::Clean().
HTTP::Parser::Parser(){
HTTP::Parser::Parser() {
headerOnly = false;
Clean();
}
/// Completely re-initializes the HTTP::Parser, leaving it ready for either reading or writing usage.
void HTTP::Parser::Clean(){
void HTTP::Parser::Clean() {
seenHeaders = false;
seenReq = false;
getChunks = false;
@ -30,16 +30,16 @@ void HTTP::Parser::Clean(){
/// The request is build from internal variables set before this call is made.
/// To be precise, method, url, protocol, headers and body are used.
/// \return A string containing a valid HTTP 1.0 or 1.1 request, ready for sending.
std::string & HTTP::Parser::BuildRequest(){
std::string & HTTP::Parser::BuildRequest() {
/// \todo Include GET/POST variable parsing?
std::map<std::string, std::string>::iterator it;
if (protocol.size() < 5 || protocol[4] != '/'){
if (protocol.size() < 5 || protocol[4] != '/') {
protocol = "HTTP/1.0";
}
builder = method + " " + url + " " + protocol + "\r\n";
for (it = headers.begin(); it != headers.end(); it++){
if (( *it).first != "" && ( *it).second != ""){
builder += ( *it).first + ": " + ( *it).second + "\r\n";
for (it = headers.begin(); it != headers.end(); it++) {
if ((*it).first != "" && (*it).second != "") {
builder += (*it).first + ": " + (*it).second + "\r\n";
}
}
builder += "\r\n" + body;
@ -49,17 +49,17 @@ std::string & HTTP::Parser::BuildRequest(){
/// Creates and sends a valid HTTP 1.0 or 1.1 request.
/// The request is build from internal variables set before this call is made.
/// To be precise, method, url, protocol, headers and body are used.
void HTTP::Parser::SendRequest(Socket::Connection & conn){
void HTTP::Parser::SendRequest(Socket::Connection & conn) {
/// \todo Include GET/POST variable parsing?
std::map<std::string, std::string>::iterator it;
if (protocol.size() < 5 || protocol[4] != '/'){
if (protocol.size() < 5 || protocol[4] != '/') {
protocol = "HTTP/1.0";
}
builder = method + " " + url + " " + protocol + "\r\n";
conn.SendNow(builder);
for (it = headers.begin(); it != headers.end(); it++){
if (( *it).first != "" && ( *it).second != ""){
builder = ( *it).first + ": " + ( *it).second + "\r\n";
for (it = headers.begin(); it != headers.end(); it++) {
if ((*it).first != "" && (*it).second != "") {
builder = (*it).first + ": " + (*it).second + "\r\n";
conn.SendNow(builder);
}
}
@ -73,17 +73,17 @@ void HTTP::Parser::SendRequest(Socket::Connection & conn){
/// \param code The HTTP response code. Usually you want 200.
/// \param message The HTTP response message. Usually you want "OK".
/// \return A string containing a valid HTTP 1.0 or 1.1 response, ready for sending.
std::string & HTTP::Parser::BuildResponse(std::string code, std::string message){
std::string & HTTP::Parser::BuildResponse(std::string code, std::string message) {
/// \todo Include GET/POST variable parsing?
std::map<std::string, std::string>::iterator it;
if (protocol.size() < 5 || protocol[4] != '/'){
if (protocol.size() < 5 || protocol[4] != '/') {
protocol = "HTTP/1.0";
}
builder = protocol + " " + code + " " + message + "\r\n";
for (it = headers.begin(); it != headers.end(); it++){
if (( *it).first != "" && ( *it).second != ""){
if (( *it).first != "Content-Length" || ( *it).second != "0"){
builder += ( *it).first + ": " + ( *it).second + "\r\n";
for (it = headers.begin(); it != headers.end(); it++) {
if ((*it).first != "" && (*it).second != "") {
if ((*it).first != "Content-Length" || (*it).second != "0") {
builder += (*it).first + ": " + (*it).second + "\r\n";
}
}
}
@ -99,18 +99,18 @@ std::string & HTTP::Parser::BuildResponse(std::string code, std::string message)
/// \param code The HTTP response code. Usually you want 200.
/// \param message The HTTP response message. Usually you want "OK".
/// \param conn The Socket::Connection to send the response over.
void HTTP::Parser::SendResponse(std::string code, std::string message, Socket::Connection & conn){
void HTTP::Parser::SendResponse(std::string code, std::string message, Socket::Connection & conn) {
/// \todo Include GET/POST variable parsing?
std::map<std::string, std::string>::iterator it;
if (protocol.size() < 5 || protocol[4] != '/'){
if (protocol.size() < 5 || protocol[4] != '/') {
protocol = "HTTP/1.0";
}
builder = protocol + " " + code + " " + message + "\r\n";
conn.SendNow(builder);
for (it = headers.begin(); it != headers.end(); it++){
if (( *it).first != "" && ( *it).second != ""){
if (( *it).first != "Content-Length" || ( *it).second != "0"){
builder = ( *it).first + ": " + ( *it).second + "\r\n";
for (it = headers.begin(); it != headers.end(); it++) {
if ((*it).first != "" && (*it).second != "") {
if ((*it).first != "Content-Length" || (*it).second != "0") {
builder = (*it).first + ": " + (*it).second + "\r\n";
conn.SendNow(builder);
}
}
@ -126,12 +126,12 @@ void HTTP::Parser::SendResponse(std::string code, std::string message, Socket::C
/// \param message The HTTP response message. Usually you want "OK".
/// \param request The HTTP request to respond to.
/// \param conn The connection to send over.
void HTTP::Parser::StartResponse(std::string code, std::string message, HTTP::Parser & request, Socket::Connection & conn){
void HTTP::Parser::StartResponse(std::string code, std::string message, HTTP::Parser & request, Socket::Connection & conn) {
protocol = request.protocol;
body = "";
if (protocol == "HTTP/1.1"){
if (protocol == "HTTP/1.1") {
SetHeader("Transfer-Encoding", "chunked");
}else{
} else {
SetBody("");
}
SendResponse(code, message, conn);
@ -143,7 +143,7 @@ void HTTP::Parser::StartResponse(std::string code, std::string message, HTTP::Pa
/// This call simply calls StartResponse("200", "OK", request, conn)
/// \param request The HTTP request to respond to.
/// \param conn The connection to send over.
void HTTP::Parser::StartResponse(HTTP::Parser & request, Socket::Connection & conn){
void HTTP::Parser::StartResponse(HTTP::Parser & request, Socket::Connection & conn) {
StartResponse("200", "OK", request, conn);
}
@ -152,29 +152,29 @@ void HTTP::Parser::StartResponse(HTTP::Parser & request, Socket::Connection & co
/// - Retrieve all the body from the 'from' Socket::Connection.
/// - Forward those contents as-is to the 'to' Socket::Connection.
/// It blocks until completed or either of the connections reaches an error state.
void HTTP::Parser::Proxy(Socket::Connection & from, Socket::Connection & to){
void HTTP::Parser::Proxy(Socket::Connection & from, Socket::Connection & to) {
SendResponse(url, method, to);
if (getChunks){
if (getChunks) {
unsigned int proxyingChunk = 0;
while (to.connected() && from.connected()){
if ((from.Received().size() && (from.Received().size() > 1 || *(from.Received().get().rbegin()) == '\n')) || from.spool()){
if (proxyingChunk){
while (proxyingChunk && from.Received().size()){
while (to.connected() && from.connected()) {
if ((from.Received().size() && (from.Received().size() > 1 || *(from.Received().get().rbegin()) == '\n')) || from.spool()) {
if (proxyingChunk) {
while (proxyingChunk && from.Received().size()) {
unsigned int toappend = from.Received().get().size();
if (toappend > proxyingChunk){
if (toappend > proxyingChunk) {
toappend = proxyingChunk;
to.SendNow(from.Received().get().c_str(), toappend);
from.Received().get().erase(0, toappend);
}else{
} else {
to.SendNow(from.Received().get());
from.Received().get().clear();
}
proxyingChunk -= toappend;
}
}else{
} else {
//Make sure the received data ends in a newline (\n).
if ( *(from.Received().get().rbegin()) != '\n'){
if (from.Received().size() > 1){
if (*(from.Received().get().rbegin()) != '\n') {
if (from.Received().size() > 1) {
//make a copy of the first part
std::string tmp = from.Received().get();
//clear the first part, wiping it from the partlist
@ -182,10 +182,10 @@ void HTTP::Parser::Proxy(Socket::Connection & from, Socket::Connection & to){
from.Received().size();
//take the now first (was second) part, insert the stored part in front of it
from.Received().get().insert(0, tmp);
}else{
} else {
Util::sleep(100);
}
if ( *(from.Received().get().rbegin()) != '\n'){
if (*(from.Received().get().rbegin()) != '\n') {
continue;
}
}
@ -193,15 +193,15 @@ void HTTP::Parser::Proxy(Socket::Connection & from, Socket::Connection & to){
to.SendNow(from.Received().get());
std::string tmpA = from.Received().get().substr(0, from.Received().get().size() - 1);
while (tmpA.find('\r') != std::string::npos){
while (tmpA.find('\r') != std::string::npos) {
tmpA.erase(tmpA.find('\r'));
}
unsigned int chunkLen = 0;
if ( !tmpA.empty()){
for (unsigned int i = 0; i < tmpA.size(); ++i){
if (!tmpA.empty()) {
for (unsigned int i = 0; i < tmpA.size(); ++i) {
chunkLen = (chunkLen << 4) | unhex(tmpA[i]);
}
if (chunkLen == 0){
if (chunkLen == 0) {
getChunks = false;
to.SendNow("\r\n", 2);
return;
@ -210,24 +210,24 @@ void HTTP::Parser::Proxy(Socket::Connection & from, Socket::Connection & to){
}
from.Received().get().clear();
}
}else{
} else {
Util::sleep(100);
}
}
}else{
} else {
unsigned int bodyLen = length;
while (bodyLen > 0 && to.connected() && from.connected()){
if (from.Received().size() || from.spool()){
if (from.Received().get().size() <= bodyLen){
while (bodyLen > 0 && to.connected() && from.connected()) {
if (from.Received().size() || from.spool()) {
if (from.Received().get().size() <= bodyLen) {
to.SendNow(from.Received().get());
bodyLen -= from.Received().get().size();
from.Received().get().clear();
}else{
} else {
to.SendNow(from.Received().get().c_str(), bodyLen);
from.Received().get().erase(0, bodyLen);
bodyLen = 0;
}
}else{
} else {
Util::sleep(100);
}
}
@ -237,19 +237,19 @@ void HTTP::Parser::Proxy(Socket::Connection & from, Socket::Connection & to){
/// Trims any whitespace at the front or back of the string.
/// Used when getting/setting headers.
/// \param s The string to trim. The string itself will be changed, not returned.
void HTTP::Parser::Trim(std::string & s){
void HTTP::Parser::Trim(std::string & s) {
size_t startpos = s.find_first_not_of(" \t");
size_t endpos = s.find_last_not_of(" \t");
if ((std::string::npos == startpos) || (std::string::npos == endpos)){
if ((std::string::npos == startpos) || (std::string::npos == endpos)) {
s = "";
}else{
} else {
s = s.substr(startpos, endpos - startpos + 1);
}
}
/// Function that sets the body of a response or request, along with the correct Content-Length header.
/// \param s The string to set the body to.
void HTTP::Parser::SetBody(std::string s){
void HTTP::Parser::SetBody(std::string s) {
body = s;
SetHeader("Content-Length", s.length());
}
@ -257,39 +257,39 @@ void HTTP::Parser::SetBody(std::string s){
/// Function that sets the body of a response or request, along with the correct Content-Length header.
/// \param buffer The buffer data to set the body to.
/// \param len Length of the buffer data.
void HTTP::Parser::SetBody(char * buffer, int len){
void HTTP::Parser::SetBody(char * buffer, int len) {
body = "";
body.append(buffer, len);
SetHeader("Content-Length", len);
}
/// Returns header i, if set.
std::string HTTP::Parser::getUrl(){
if (url.find('?') != std::string::npos){
std::string HTTP::Parser::getUrl() {
if (url.find('?') != std::string::npos) {
return url.substr(0, url.find('?'));
}else{
} else {
return url;
}
}
/// Returns header i, if set.
std::string HTTP::Parser::GetHeader(std::string i){
std::string HTTP::Parser::GetHeader(std::string i) {
return headers[i];
}
/// Returns POST variable i, if set.
std::string HTTP::Parser::GetVar(std::string i){
std::string HTTP::Parser::GetVar(std::string i) {
return vars[i];
}
/// Sets header i to string value v.
void HTTP::Parser::SetHeader(std::string i, std::string v){
void HTTP::Parser::SetHeader(std::string i, std::string v) {
Trim(i);
Trim(v);
headers[i] = v;
}
/// Sets header i to integer value v.
void HTTP::Parser::SetHeader(std::string i, int v){
void HTTP::Parser::SetHeader(std::string i, int v) {
Trim(i);
char val[23]; //ints are never bigger than 22 chars as decimal
sprintf(val, "%i", v);
@ -297,11 +297,11 @@ void HTTP::Parser::SetHeader(std::string i, int v){
}
/// Sets POST variable i to string value v.
void HTTP::Parser::SetVar(std::string i, std::string v){
void HTTP::Parser::SetVar(std::string i, std::string v) {
Trim(i);
Trim(v);
//only set if there is actually a key
if ( !i.empty()){
if (!i.empty()) {
vars[i] = v;
}
}
@ -311,10 +311,10 @@ void HTTP::Parser::SetVar(std::string i, std::string v){
/// If not, as much as can be interpreted is removed and false returned.
/// \param conn The socket to read from.
/// \return True if a whole request or response was read, false otherwise.
bool HTTP::Parser::Read(Socket::Connection & conn){
bool HTTP::Parser::Read(Socket::Connection & conn) {
//Make sure the received data ends in a newline (\n).
while ((!seenHeaders || (getChunks && !doingChunk)) && *(conn.Received().get().rbegin()) != '\n'){
if (conn.Received().size() > 1){
while ((!seenHeaders || (getChunks && !doingChunk)) && *(conn.Received().get().rbegin()) != '\n') {
if (conn.Received().size() > 1) {
//make a copy of the first part
std::string tmp = conn.Received().get();
//clear the first part, wiping it from the partlist
@ -322,16 +322,16 @@ bool HTTP::Parser::Read(Socket::Connection & conn){
conn.Received().size();
//take the now first (was second) part, insert the stored part in front of it
conn.Received().get().insert(0, tmp);
}else{
} else {
return false;
}
}
//if a parse succeeds, simply return true
if (parse(conn.Received().get())){
if (parse(conn.Received().get())) {
return true;
}
//otherwise, if we have parts left, call ourselves recursively
if (conn.Received().size()){
if (conn.Received().size()) {
return Read(conn);
}
return false;
@ -342,7 +342,7 @@ bool HTTP::Parser::Read(Socket::Connection & conn){
/// If not, as much as can be interpreted is removed and false returned.
/// \param strbuf The buffer to read from.
/// \return True if a whole request or response was read, false otherwise.
bool HTTP::Parser::Read(std::string & strbuf){
bool HTTP::Parser::Read(std::string & strbuf) {
return parse(strbuf);
} //HTTPReader::Read
@ -351,74 +351,74 @@ bool HTTP::Parser::Read(std::string & strbuf){
/// from the data buffer.
/// \param HTTPbuffer The data buffer to read from.
/// \return True on success, false otherwise.
bool HTTP::Parser::parse(std::string & HTTPbuffer){
bool HTTP::Parser::parse(std::string & HTTPbuffer) {
size_t f;
std::string tmpA, tmpB, tmpC;
/// \todo Make this not resize HTTPbuffer in parts, but read all at once and then remove the entire request, like doxygen claims it does?
while ( !HTTPbuffer.empty()){
if ( !seenHeaders){
while (!HTTPbuffer.empty()) {
if (!seenHeaders) {
f = HTTPbuffer.find('\n');
if (f == std::string::npos) return false;
tmpA = HTTPbuffer.substr(0, f);
if (f + 1 == HTTPbuffer.size()){
if (f + 1 == HTTPbuffer.size()) {
HTTPbuffer.clear();
}else{
} else {
HTTPbuffer.erase(0, f + 1);
}
while (tmpA.find('\r') != std::string::npos){
while (tmpA.find('\r') != std::string::npos) {
tmpA.erase(tmpA.find('\r'));
}
if ( !seenReq){
if (!seenReq) {
seenReq = true;
f = tmpA.find(' ');
if (f != std::string::npos){
if (tmpA.substr(0, 4) == "HTTP"){
if (f != std::string::npos) {
if (tmpA.substr(0, 4) == "HTTP") {
protocol = tmpA.substr(0, f);
tmpA.erase(0, f + 1);
f = tmpA.find(' ');
if (f != std::string::npos){
if (f != std::string::npos) {
url = tmpA.substr(0, f);
tmpA.erase(0, f + 1);
method = tmpA;
if (url.find('?') != std::string::npos){
if (url.find('?') != std::string::npos) {
parseVars(url.substr(url.find('?') + 1)); //parse GET variables
}
}else{
} else {
seenReq = false;
}
}else{
} else {
method = tmpA.substr(0, f);
tmpA.erase(0, f + 1);
f = tmpA.find(' ');
if (f != std::string::npos){
if (f != std::string::npos) {
url = tmpA.substr(0, f);
tmpA.erase(0, f + 1);
protocol = tmpA;
if (url.find('?') != std::string::npos){
if (url.find('?') != std::string::npos) {
parseVars(url.substr(url.find('?') + 1)); //parse GET variables
}
}else{
} else {
seenReq = false;
}
}
}else{
} else {
seenReq = false;
}
}else{
if (tmpA.size() == 0){
} else {
if (tmpA.size() == 0) {
seenHeaders = true;
body.clear();
if (GetHeader("Content-Length") != ""){
if (GetHeader("Content-Length") != "") {
length = atoi(GetHeader("Content-Length").c_str());
if (body.capacity() < length){
if (body.capacity() < length) {
body.reserve(length);
}
}
if (GetHeader("Transfer-Encoding") == "chunked"){
if (GetHeader("Transfer-Encoding") == "chunked") {
getChunks = true;
doingChunk = 0;
}
}else{
} else {
f = tmpA.find(':');
if (f == std::string::npos) continue;
tmpB = tmpA.substr(0, f);
@ -427,61 +427,61 @@ bool HTTP::Parser::parse(std::string & HTTPbuffer){
}
}
}
if (seenHeaders){
if (length > 0){
if (headerOnly){
if (seenHeaders) {
if (length > 0) {
if (headerOnly) {
return true;
}
unsigned int toappend = length - body.length();
if (toappend > 0){
if (toappend > 0) {
body.append(HTTPbuffer, 0, toappend);
HTTPbuffer.erase(0, toappend);
}
if (length == body.length()){
if (length == body.length()) {
parseVars(body); //parse POST variables
return true;
}else{
} else {
return false;
}
}else{
if (getChunks){
if (headerOnly){
} else {
if (getChunks) {
if (headerOnly) {
return true;
}
if (doingChunk){
if (doingChunk) {
unsigned int toappend = HTTPbuffer.size();
if (toappend > doingChunk){
if (toappend > doingChunk) {
toappend = doingChunk;
}
body.append(HTTPbuffer, 0, toappend);
HTTPbuffer.erase(0, toappend);
doingChunk -= toappend;
}else{
} else {
f = HTTPbuffer.find('\n');
if (f == std::string::npos) return false;
tmpA = HTTPbuffer.substr(0, f);
while (tmpA.find('\r') != std::string::npos){
while (tmpA.find('\r') != std::string::npos) {
tmpA.erase(tmpA.find('\r'));
}
unsigned int chunkLen = 0;
if ( !tmpA.empty()){
for (unsigned int i = 0; i < tmpA.size(); ++i){
if (!tmpA.empty()) {
for (unsigned int i = 0; i < tmpA.size(); ++i) {
chunkLen = (chunkLen << 4) | unhex(tmpA[i]);
}
if (chunkLen == 0){
if (chunkLen == 0) {
getChunks = false;
return true;
}
doingChunk = chunkLen;
}
if (f + 1 == HTTPbuffer.size()){
if (f + 1 == HTTPbuffer.size()) {
HTTPbuffer.clear();
}else{
} else {
HTTPbuffer.erase(0, f + 1);
}
}
return false;
}else{
} else {
return true;
}
}
@ -492,28 +492,28 @@ bool HTTP::Parser::parse(std::string & HTTPbuffer){
/// Parses GET or POST-style variable data.
/// Saves to internal variable structure using HTTP::Parser::SetVar.
void HTTP::Parser::parseVars(std::string data){
void HTTP::Parser::parseVars(std::string data) {
std::string varname;
std::string varval;
// position where a part start (e.g. after &)
size_t pos = 0;
while (pos < data.length()){
while (pos < data.length()) {
size_t nextpos = data.find('&', pos);
if (nextpos == std::string::npos){
if (nextpos == std::string::npos) {
nextpos = data.length();
}
size_t eq_pos = data.find('=', pos);
if (eq_pos < nextpos){
if (eq_pos < nextpos) {
// there is a key and value
varname = data.substr(pos, eq_pos - pos);
varval = data.substr(eq_pos + 1, nextpos - eq_pos - 1);
}else{
} else {
// no value, only a key
varname = data.substr(pos, nextpos - pos);
varval.clear();
}
SetVar(urlunescape(varname), urlunescape(varval));
if (nextpos == std::string::npos){
if (nextpos == std::string::npos) {
// in case the string is gigantic
break;
}
@ -525,7 +525,7 @@ void HTTP::Parser::parseVars(std::string data){
/// Sends a string in chunked format if protocol is HTTP/1.1, sends as-is otherwise.
/// \param bodypart The data to send.
/// \param conn The connection to use for sending.
void HTTP::Parser::Chunkify(std::string & bodypart, Socket::Connection & conn){
void HTTP::Parser::Chunkify(std::string & bodypart, Socket::Connection & conn) {
Chunkify(bodypart.c_str(), bodypart.size(), conn);
}
@ -533,8 +533,8 @@ void HTTP::Parser::Chunkify(std::string & bodypart, Socket::Connection & conn){
/// \param data The data to send.
/// \param size The size of the data to send.
/// \param conn The connection to use for sending.
void HTTP::Parser::Chunkify(const char * data, unsigned int size, Socket::Connection & conn){
if (protocol == "HTTP/1.1"){
void HTTP::Parser::Chunkify(const char * data, unsigned int size, Socket::Connection & conn) {
if (protocol == "HTTP/1.1") {
char len[10];
int sizelen = snprintf(len, 10, "%x\r\n", size);
//prepend the chunk size and \r\n
@ -543,39 +543,39 @@ void HTTP::Parser::Chunkify(const char * data, unsigned int size, Socket::Connec
conn.SendNow(data, size);
//append \r\n
conn.SendNow("\r\n", 2);
if ( !size){
if (!size) {
//append \r\n again if this was the end of the file (required by chunked transfer encoding according to spec)
conn.SendNow("\r\n", 2);
}
}else{
} else {
//just send the chunk itself
conn.SendNow(data, size);
//close the connection if this was the end of the file
if ( !size){
if (!size) {
conn.close();
}
}
}
/// Unescapes URLencoded std::string data.
std::string HTTP::Parser::urlunescape(const std::string & in){
std::string HTTP::Parser::urlunescape(const std::string & in) {
std::string out;
for (unsigned int i = 0; i < in.length(); ++i){
if (in[i] == '%'){
for (unsigned int i = 0; i < in.length(); ++i) {
if (in[i] == '%') {
char tmp = 0;
++i;
if (i < in.length()){
if (i < in.length()) {
tmp = unhex(in[i]) << 4;
}
++i;
if (i < in.length()){
if (i < in.length()) {
tmp += unhex(in[i]);
}
out += tmp;
}else{
if (in[i] == '+'){
} else {
if (in[i] == '+') {
out += ' ';
}else{
} else {
out += in[i];
}
}
@ -585,19 +585,19 @@ std::string HTTP::Parser::urlunescape(const std::string & in){
/// Helper function for urlunescape.
/// Takes a single char input and outputs its integer hex value.
int HTTP::Parser::unhex(char c){
int HTTP::Parser::unhex(char c) {
return (c >= '0' && c <= '9' ? c - '0' : c >= 'A' && c <= 'F' ? c - 'A' + 10 : c - 'a' + 10);
}
/// URLencodes std::string data.
std::string HTTP::Parser::urlencode(const std::string &c){
std::string HTTP::Parser::urlencode(const std::string & c) {
std::string escaped = "";
int max = c.length();
for (int i = 0; i < max; i++){
for (int i = 0; i < max; i++) {
if (('0' <= c[i] && c[i] <= '9') || ('a' <= c[i] && c[i] <= 'z') || ('A' <= c[i] && c[i] <= 'Z')
|| (c[i] == '~' || c[i] == '!' || c[i] == '*' || c[i] == '(' || c[i] == ')' || c[i] == '\'')){
escaped.append( &c[i], 1);
}else{
|| (c[i] == '~' || c[i] == '!' || c[i] == '*' || c[i] == '(' || c[i] == ')' || c[i] == '\'')) {
escaped.append(&c[i], 1);
} else {
escaped.append("%");
escaped.append(hex(c[i]));
}
@ -607,7 +607,7 @@ std::string HTTP::Parser::urlencode(const std::string &c){
/// Helper function for urlescape.
/// Encodes a character as two hex digits.
std::string HTTP::Parser::hex(char dec){
std::string HTTP::Parser::hex(char dec) {
char dig1 = (dec & 0xF0) >> 4;
char dig2 = (dec & 0x0F);
if (dig1 <= 9) dig1 += 48;
@ -615,7 +615,7 @@ std::string HTTP::Parser::hex(char dec){
if (dig2 <= 9) dig2 += 48;
if (10 <= dig2 && dig2 <= 15) dig2 += 97 - 10;
std::string r;
r.append( &dig1, 1);
r.append( &dig2, 1);
r.append(&dig1, 1);
r.append(&dig2, 1);
return r;
}

View file

@ -11,7 +11,7 @@
/// Holds all HTTP processing related code.
namespace HTTP {
/// Simple class for reading and writing HTTP 1.0 and 1.1.
class Parser{
class Parser {
public:
Parser();
bool Read(Socket::Connection & conn);

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@ namespace DTSC {
namespace JSON {
/// Lists all types of JSON::Value.
enum ValueType{
enum ValueType {
EMPTY, BOOL, INTEGER, STRING, ARRAY, OBJECT
};
@ -30,7 +30,7 @@ namespace JSON {
typedef std::deque<Value>::const_iterator ArrConstIter;
/// A JSON::Value is either a string or an integer, but may also be an object, array or null.
class Value{
class Value {
private:
ValueType myType;
long long int intVal;
@ -48,15 +48,15 @@ namespace JSON {
Value(long long int val);
Value(bool val);
//comparison operators
bool operator==(const Value &rhs) const;
bool operator!=(const Value &rhs) const;
bool operator==(const Value & rhs) const;
bool operator!=(const Value & rhs) const;
//assignment operators
Value & operator=(const std::string &rhs);
Value & operator=(const std::string & rhs);
Value & operator=(const char * rhs);
Value & operator=(const long long int &rhs);
Value & operator=(const int &rhs);
Value & operator=(const unsigned int &rhs);
Value & operator=(const bool &rhs);
Value & operator=(const long long int & rhs);
Value & operator=(const int & rhs);
Value & operator=(const unsigned int & rhs);
Value & operator=(const bool & rhs);
//converts to basic types
operator long long int() const;
operator std::string() const;
@ -105,22 +105,22 @@ namespace JSON {
};
Value fromDTMI2(std::string & data);
Value fromDTMI2(const unsigned char * data, unsigned int len, unsigned int &i);
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 fromDTMI(const unsigned char * data, unsigned int len, unsigned int & i);
Value fromString(std::string json);
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);
void fromDTMI2(const unsigned char * data, unsigned int len, unsigned int & i, Value & ret);
void fromDTMI(std::string & data, Value & ret);
void fromDTMI(const unsigned char * data, unsigned int len, unsigned int &i, Value & ret);
void fromDTMI(const unsigned char * data, unsigned int len, unsigned int & i, Value & ret);
template <typename T>
std::string encodeVector(T begin, T end){
std::string encodeVector(T begin, T end) {
std::string result;
for( T it = begin; it != end; it++){
for (T it = begin; it != end; it++) {
long long int tmp = (*it);
while(tmp >= 0xFFFF){
while (tmp >= 0xFFFF) {
result += (char)0xFF;
result += (char)0xFF;
tmp -= 0xFFFF;
@ -132,13 +132,13 @@ namespace JSON {
}
template <typename T>
void decodeVector( std::string input, T & result ){
void decodeVector(std::string input, T & result) {
result.clear();
unsigned int tmp = 0;
for( int i = 0; i < input.size(); i += 2){
for (int i = 0; i < input.size(); i += 2) {
unsigned int curLen = (input[i] << 8) + input[i + 1];
tmp += curLen;
if (curLen != 0xFFFF){
if (curLen != 0xFFFF) {
result.push_back(tmp);
tmp = 0;
}
@ -146,11 +146,11 @@ namespace JSON {
}
template <typename T>
std::string encodeVector4(T begin, T end){
std::string encodeVector4(T begin, T end) {
std::string result;
for( T it = begin; it != end; it++){
for (T it = begin; it != end; it++) {
long long int tmp = (*it);
while(tmp >= 0xFFFFFFFF){
while (tmp >= 0xFFFFFFFF) {
result += (char)0xFF;
result += (char)0xFF;
result += (char)0xFF;
@ -166,13 +166,13 @@ namespace JSON {
}
template <typename T>
void decodeVector4( std::string input, T & result ){
void decodeVector4(std::string input, T & result) {
result.clear();
unsigned int tmp = 0;
for( int i = 0; i < input.size(); i += 4){
unsigned int curLen = (input[i] << 24) + (input[i+1] << 16) + (input[i+2] << 8) + (input[i+3]);
for (int i = 0; i < input.size(); i += 4) {
unsigned int curLen = (input[i] << 24) + (input[i + 1] << 16) + (input[i + 2] << 8) + (input[i + 3]);
tmp += curLen;
if (curLen != 0xFFFFFFFF){
if (curLen != 0xFFFFFFFF) {
result.push_back(tmp);
tmp = 0;
}

View file

@ -16,148 +16,148 @@ namespace MP4 {
/// If manage is set to true, the pointer will be realloc'ed when the box needs to be resized.
/// If the datapointer is NULL, manage is assumed to be true even if explicitly given as false.
/// If managed, the pointer will be free'd upon destruction.
Box::Box(char * datapointer, bool manage){
Box::Box(char * datapointer, bool manage) {
data = datapointer;
managed = manage;
payloadOffset = 8;
if (data == 0){
if (data == 0) {
clear();
}else{
data_size = ntohl(((int*)data)[0]);
} else {
data_size = ntohl(((int *)data)[0]);
}
}
Box::Box(const Box & rs){
Box::Box(const Box & rs) {
data = rs.data;
managed = false;
payloadOffset = rs.payloadOffset;
if (data == 0){
if (data == 0) {
clear();
}else{
data_size = ntohl(((int*)data)[0]);
} else {
data_size = ntohl(((int *)data)[0]);
}
}
Box& Box::operator = (const Box & rs){
Box & Box::operator = (const Box & rs) {
clear();
data = rs.data;
managed = false;
payloadOffset = rs.payloadOffset;
if (data == 0){
if (data == 0) {
clear();
}else{
data_size = ntohl(((int*)data)[0]);
} else {
data_size = ntohl(((int *)data)[0]);
}
return *this;
}
/// If managed, this will free the data pointer.
Box::~Box(){
if (managed && data != 0){
Box::~Box() {
if (managed && data != 0) {
free(data);
data = 0;
}
}
/// Returns the values at byte positions 4 through 7.
std::string Box::getType(){
std::string Box::getType() {
return std::string(data + 4, 4);
}
/// Returns true if the given 4-byte boxtype is equal to the values at byte positions 4 through 7.
bool Box::isType(const char* boxType){
bool Box::isType(const char * boxType) {
return !memcmp(boxType, data + 4, 4);
}
/// Reads the first 8 bytes and returns
std::string readBoxType(FILE * newData){
std::string readBoxType(FILE * newData) {
char retVal[8] = {0, 0, 0, 0, 'e', 'r', 'r', 'o'};
long long unsigned int pos = ftell(newData);
fread(retVal,8,1,newData);
fseek (newData,pos,SEEK_SET);
return std::string(retVal+4,4);
fread(retVal, 8, 1, newData);
fseek(newData, pos, SEEK_SET);
return std::string(retVal + 4, 4);
}
///\todo make good working calcBoxSize with size and payloadoffset calculation
unsigned long int calcBoxSize(char readVal[16]){
unsigned long int calcBoxSize(char readVal[16]) {
return (readVal[0] << 24) | (readVal[1] << 16) | (readVal[2] << 8) | (readVal[3]);
}
bool skipBox(FILE * newData){
bool skipBox(FILE * newData) {
char readVal[16];
long long unsigned int pos = ftell(newData);
if (fread(readVal,4,1,newData)){
if (fread(readVal, 4, 1, newData)) {
uint64_t size = calcBoxSize(readVal);
if (size==1){
if (fread(readVal+4,12,1,newData)){
size = 0 + ntohl(((int*)readVal)[2]);
if (size == 1) {
if (fread(readVal + 4, 12, 1, newData)) {
size = 0 + ntohl(((int *)readVal)[2]);
size <<= 32;
size += ntohl(((int*)readVal)[3]);
}else{
size += ntohl(((int *)readVal)[3]);
} else {
return false;
}
}else if (size==0){
} else if (size == 0) {
fseek(newData, 0, SEEK_END);
}
DEBUG_MSG(DLVL_DEVEL,"skipping size 0x%0.8X",size);
if (fseek(newData, pos + size, SEEK_SET)==0){
DEBUG_MSG(DLVL_DEVEL, "skipping size 0x%0.8X", size);
if (fseek(newData, pos + size, SEEK_SET) == 0) {
return true;
}else{
} else {
return false;
}
}else{
} else {
return false;
}
}
bool Box::read(FILE* newData){
bool Box::read(FILE * newData) {
char readVal[16];
long long unsigned int pos = ftell(newData);
if (fread(readVal,4,1,newData)){
if (fread(readVal, 4, 1, newData)) {
payloadOffset = 8;
uint64_t size = calcBoxSize(readVal);
if (size==1){
if (fread(readVal+4,12,1,newData)){
size = 0 + ntohl(((int*)readVal)[2]);
if (size == 1) {
if (fread(readVal + 4, 12, 1, newData)) {
size = 0 + ntohl(((int *)readVal)[2]);
size <<= 32;
size += ntohl(((int*)readVal)[3]);
size += ntohl(((int *)readVal)[3]);
payloadOffset = 16;
}else{
} else {
return false;
}
}
fseek (newData,pos,SEEK_SET);
data = (char*)realloc(data, size);
fseek(newData, pos, SEEK_SET);
data = (char *)realloc(data, size);
data_size = size;
return (fread(data,size,1,newData) == 1);
}else{
return (fread(data, size, 1, newData) == 1);
} else {
return false;
}
}
/// Reads out a whole box (if possible) from newData, copying to the internal data storage and removing from the input string.
/// \returns True on success, false otherwise.
bool Box::read(std::string & newData){
if ( !managed){
bool Box::read(std::string & newData) {
if (!managed) {
return false;
}
if (newData.size() > 4){
if (newData.size() > 4) {
payloadOffset = 8;
uint64_t size = ntohl(((int*)newData.c_str())[0]);
if (size == 1){
if (newData.size() > 16){
size = 0 + ntohl(((int*)newData.c_str())[2]);
uint64_t size = ntohl(((int *)newData.c_str())[0]);
if (size == 1) {
if (newData.size() > 16) {
size = 0 + ntohl(((int *)newData.c_str())[2]);
size <<= 32;
size += ntohl(((int*)newData.c_str())[3]);
size += ntohl(((int *)newData.c_str())[3]);
payloadOffset = 16;
}else{
} else {
return false;
}
}
if (newData.size() >= size){
data = (char*)realloc(data, size);
if (newData.size() >= size) {
data = (char *)realloc(data, size);
data_size = size;
memcpy(data, newData.data(), size);
newData.erase(0, size);
@ -168,207 +168,207 @@ namespace MP4 {
}
/// Returns the total boxed size of this box, including the header.
uint64_t Box::boxedSize(){
if (payloadOffset == 16){
return ((uint64_t)ntohl(((int*)data)[2]) << 32) + ntohl(((int*)data)[3]);
uint64_t Box::boxedSize() {
if (payloadOffset == 16) {
return ((uint64_t)ntohl(((int *)data)[2]) << 32) + ntohl(((int *)data)[3]);
}
return ntohl(((int*)data)[0]);
return ntohl(((int *)data)[0]);
}
/// Retruns the size of the payload of thix box, excluding the header.
/// This value is defined as boxedSize() - 8.
uint64_t Box::payloadSize(){
uint64_t Box::payloadSize() {
return boxedSize() - payloadOffset;
}
/// Returns a copy of the data pointer.
char * Box::asBox(){
char * Box::asBox() {
return data;
}
char * Box::payload(){
char * Box::payload() {
return data + payloadOffset;
}
/// Makes this box managed if it wasn't already, resetting the internal storage to 8 bytes (the minimum).
/// If this box wasn't managed, the original data is left intact - otherwise it is free'd.
/// If it was somehow impossible to allocate 8 bytes (should never happen), this will cause segfaults later.
void Box::clear(){
if (data && managed){
void Box::clear() {
if (data && managed) {
free(data);
}
managed = true;
payloadOffset = 8;
data = (char*)malloc(8);
if (data){
data = (char *)malloc(8);
if (data) {
data_size = 8;
((int*)data)[0] = htonl(data_size);
}else{
((int *)data)[0] = htonl(data_size);
} else {
data_size = 0;
}
}
/// Attempts to typecast this Box to a more specific type and call the toPrettyString() function of that type.
/// If this failed, it will print out a message saying pretty-printing is not implemented for boxtype.
std::string Box::toPrettyString(uint32_t indent){
switch (ntohl( *((int*)(data + 4)))){ //type is at this address
std::string Box::toPrettyString(uint32_t indent) {
switch (ntohl(*((int *)(data + 4)))) { //type is at this address
case 0x6D666864:
return ((MFHD*)this)->toPrettyString(indent);
return ((MFHD *)this)->toPrettyString(indent);
break;
case 0x6D6F6F66:
return ((MOOF*)this)->toPrettyString(indent);
return ((MOOF *)this)->toPrettyString(indent);
break;
case 0x61627374:
return ((ABST*)this)->toPrettyString(indent);
return ((ABST *)this)->toPrettyString(indent);
break;
case 0x61667274:
return ((AFRT*)this)->toPrettyString(indent);
return ((AFRT *)this)->toPrettyString(indent);
break;
case 0x61667261:
return ((AFRA*)this)->toPrettyString(indent);
return ((AFRA *)this)->toPrettyString(indent);
break;
case 0x61737274:
return ((ASRT*)this)->toPrettyString(indent);
return ((ASRT *)this)->toPrettyString(indent);
break;
case 0x7472756E:
return ((TRUN*)this)->toPrettyString(indent);
return ((TRUN *)this)->toPrettyString(indent);
break;
case 0x74726166:
return ((TRAF*)this)->toPrettyString(indent);
return ((TRAF *)this)->toPrettyString(indent);
break;
case 0x74666864:
return ((TFHD*)this)->toPrettyString(indent);
return ((TFHD *)this)->toPrettyString(indent);
break;
case 0x61766343:
return ((AVCC*)this)->toPrettyString(indent);
return ((AVCC *)this)->toPrettyString(indent);
break;
case 0x73647470:
return ((SDTP*)this)->toPrettyString(indent);
return ((SDTP *)this)->toPrettyString(indent);
break;
case 0x66747970:
return ((FTYP*)this)->toPrettyString(indent);
return ((FTYP *)this)->toPrettyString(indent);
break;
case 0x6D6F6F76:
return ((MOOV*)this)->toPrettyString(indent);
return ((MOOV *)this)->toPrettyString(indent);
break;
case 0x6D766578:
return ((MVEX*)this)->toPrettyString(indent);
return ((MVEX *)this)->toPrettyString(indent);
break;
case 0x74726578:
return ((TREX*)this)->toPrettyString(indent);
return ((TREX *)this)->toPrettyString(indent);
break;
case 0x6D667261:
return ((MFRA*)this)->toPrettyString(indent);
return ((MFRA *)this)->toPrettyString(indent);
break;
case 0x7472616B:
return ((TRAK*)this)->toPrettyString(indent);
return ((TRAK *)this)->toPrettyString(indent);
break;
case 0x6D646961:
return ((MDIA*)this)->toPrettyString(indent);
return ((MDIA *)this)->toPrettyString(indent);
break;
case 0x6D696E66:
return ((MINF*)this)->toPrettyString(indent);
return ((MINF *)this)->toPrettyString(indent);
break;
case 0x64696E66:
return ((DINF*)this)->toPrettyString(indent);
return ((DINF *)this)->toPrettyString(indent);
break;
case 0x6D66726F:
return ((MFRO*)this)->toPrettyString(indent);
return ((MFRO *)this)->toPrettyString(indent);
break;
case 0x68646C72:
return ((HDLR*)this)->toPrettyString(indent);
return ((HDLR *)this)->toPrettyString(indent);
break;
case 0x766D6864:
return ((VMHD*)this)->toPrettyString(indent);
return ((VMHD *)this)->toPrettyString(indent);
break;
case 0x736D6864:
return ((SMHD*)this)->toPrettyString(indent);
return ((SMHD *)this)->toPrettyString(indent);
break;
case 0x686D6864:
return ((HMHD*)this)->toPrettyString(indent);
return ((HMHD *)this)->toPrettyString(indent);
break;
case 0x6E6D6864:
return ((NMHD*)this)->toPrettyString(indent);
return ((NMHD *)this)->toPrettyString(indent);
break;
case 0x6D656864:
return ((MEHD*)this)->toPrettyString(indent);
return ((MEHD *)this)->toPrettyString(indent);
break;
case 0x7374626C:
return ((STBL*)this)->toPrettyString(indent);
return ((STBL *)this)->toPrettyString(indent);
break;
case 0x64726566:
return ((DREF*)this)->toPrettyString(indent);
return ((DREF *)this)->toPrettyString(indent);
break;
case 0x75726C20:
return ((URL*)this)->toPrettyString(indent);
return ((URL *)this)->toPrettyString(indent);
break;
case 0x75726E20:
return ((URN*)this)->toPrettyString(indent);
return ((URN *)this)->toPrettyString(indent);
break;
case 0x6D766864:
return ((MVHD*)this)->toPrettyString(indent);
return ((MVHD *)this)->toPrettyString(indent);
break;
case 0x74667261:
return ((TFRA*)this)->toPrettyString(indent);
return ((TFRA *)this)->toPrettyString(indent);
break;
case 0x746B6864:
return ((TKHD*)this)->toPrettyString(indent);
return ((TKHD *)this)->toPrettyString(indent);
break;
case 0x6D646864:
return ((MDHD*)this)->toPrettyString(indent);
return ((MDHD *)this)->toPrettyString(indent);
break;
case 0x73747473:
return ((STTS*)this)->toPrettyString(indent);
return ((STTS *)this)->toPrettyString(indent);
break;
case 0x63747473:
return ((CTTS*)this)->toPrettyString(indent);
return ((CTTS *)this)->toPrettyString(indent);
break;
case 0x73747363:
return ((STSC*)this)->toPrettyString(indent);
return ((STSC *)this)->toPrettyString(indent);
break;
case 0x7374636F:
return ((STCO*)this)->toPrettyString(indent);
return ((STCO *)this)->toPrettyString(indent);
break;
case 0x7374737A:
return ((STSZ*)this)->toPrettyString(indent);
return ((STSZ *)this)->toPrettyString(indent);
break;
case 0x73747364:
return ((STSD*)this)->toPrettyString(indent);
return ((STSD *)this)->toPrettyString(indent);
break;
case 0x6D703461://mp4a
case 0x656E6361://enca
return ((MP4A*)this)->toPrettyString(indent);
return ((MP4A *)this)->toPrettyString(indent);
break;
case 0x61616320:
return ((AAC*)this)->toPrettyString(indent);
return ((AAC *)this)->toPrettyString(indent);
break;
case 0x61766331:
return ((AVC1*)this)->toPrettyString(indent);
return ((AVC1 *)this)->toPrettyString(indent);
break;
case 0x68323634://h264
case 0x656E6376://encv
return ((H264*)this)->toPrettyString(indent);
return ((H264 *)this)->toPrettyString(indent);
break;
case 0x65647473:
return ((EDTS*)this)->toPrettyString(indent);
return ((EDTS *)this)->toPrettyString(indent);
break;
case 0x73747373:
return ((STSS*)this)->toPrettyString(indent);
return ((STSS *)this)->toPrettyString(indent);
break;
case 0x6D657461:
return ((META*)this)->toPrettyString(indent);
return ((META *)this)->toPrettyString(indent);
break;
case 0x656C7374:
return ((ELST*)this)->toPrettyString(indent);
return ((ELST *)this)->toPrettyString(indent);
break;
case 0x65736473:
return ((ESDS*)this)->toPrettyString(indent);
return ((ESDS *)this)->toPrettyString(indent);
break;
case 0x75647461:
return ((UDTA*)this)->toPrettyString(indent);
return ((UDTA *)this)->toPrettyString(indent);
break;
case 0x75756964:
return ((UUID*)this)->toPrettyString(indent);
return ((UUID *)this)->toPrettyString(indent);
break;
default:
break;
@ -381,10 +381,10 @@ namespace MP4 {
/// Sets the 8 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed.
void Box::setInt8(char newData, size_t index){
void Box::setInt8(char newData, size_t index) {
index += payloadOffset;
if (index >= boxedSize()){
if ( !reserve(index, 0, 1)){
if (index >= boxedSize()) {
if (!reserve(index, 0, 1)) {
return;
}
}
@ -394,10 +394,10 @@ namespace MP4 {
/// Gets the 8 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed.
char Box::getInt8(size_t index){
char Box::getInt8(size_t index) {
index += payloadOffset;
if (index >= boxedSize()){
if ( !reserve(index, 0, 1)){
if (index >= boxedSize()) {
if (!reserve(index, 0, 1)) {
return 0;
}
setInt8(0, index - payloadOffset);
@ -408,40 +408,40 @@ namespace MP4 {
/// Sets the 16 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed.
void Box::setInt16(short newData, size_t index){
void Box::setInt16(short newData, size_t index) {
index += payloadOffset;
if (index + 1 >= boxedSize()){
if ( !reserve(index, 0, 2)){
if (index + 1 >= boxedSize()) {
if (!reserve(index, 0, 2)) {
return;
}
}
newData = htons(newData);
memcpy(data + index, (char*) &newData, 2);
memcpy(data + index, (char *) &newData, 2);
}
/// Gets the 16 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed.
short Box::getInt16(size_t index){
short Box::getInt16(size_t index) {
index += payloadOffset;
if (index + 1 >= boxedSize()){
if ( !reserve(index, 0, 2)){
if (index + 1 >= boxedSize()) {
if (!reserve(index, 0, 2)) {
return 0;
}
setInt16(0, index - payloadOffset);
}
short result;
memcpy((char*) &result, data + index, 2);
memcpy((char *) &result, data + index, 2);
return ntohs(result);
}
/// Sets the 24 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed.
void Box::setInt24(uint32_t newData, size_t index){
void Box::setInt24(uint32_t newData, size_t index) {
index += payloadOffset;
if (index + 2 >= boxedSize()){
if ( !reserve(index, 0, 3)){
if (index + 2 >= boxedSize()) {
if (!reserve(index, 0, 3)) {
return;
}
}
@ -453,10 +453,10 @@ namespace MP4 {
/// Gets the 24 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed.
uint32_t Box::getInt24(size_t index){
uint32_t Box::getInt24(size_t index) {
index += payloadOffset;
if (index + 2 >= boxedSize()){
if ( !reserve(index, 0, 3)){
if (index + 2 >= boxedSize()) {
if (!reserve(index, 0, 3)) {
return 0;
}
setInt24(0, index - payloadOffset);
@ -472,84 +472,84 @@ namespace MP4 {
/// Sets the 32 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed.
void Box::setInt32(uint32_t newData, size_t index){
void Box::setInt32(uint32_t newData, size_t index) {
index += payloadOffset;
if (index + 3 >= boxedSize()){
if ( !reserve(index, 0, 4)){
if (index + 3 >= boxedSize()) {
if (!reserve(index, 0, 4)) {
return;
}
}
newData = htonl(newData);
memcpy(data + index, (char*) &newData, 4);
memcpy(data + index, (char *) &newData, 4);
}
/// Gets the 32 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed.
uint32_t Box::getInt32(size_t index){
uint32_t Box::getInt32(size_t index) {
index += payloadOffset;
if (index + 3 >= boxedSize()){
if ( !reserve(index, 0, 4)){
if (index + 3 >= boxedSize()) {
if (!reserve(index, 0, 4)) {
return 0;
}
setInt32(0, index - payloadOffset);
}
uint32_t result;
memcpy((char*) &result, data + index, 4);
memcpy((char *) &result, data + index, 4);
return ntohl(result);
}
/// Sets the 64 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed.
void Box::setInt64(uint64_t newData, size_t index){
void Box::setInt64(uint64_t newData, size_t index) {
index += payloadOffset;
if (index + 7 >= boxedSize()){
if ( !reserve(index, 0, 8)){
if (index + 7 >= boxedSize()) {
if (!reserve(index, 0, 8)) {
return;
}
}
((int*)(data + index))[0] = htonl((int)(newData >> 32));
((int*)(data + index))[1] = htonl((int)(newData & 0xFFFFFFFF));
((int *)(data + index))[0] = htonl((int)(newData >> 32));
((int *)(data + index))[1] = htonl((int)(newData & 0xFFFFFFFF));
}
/// Gets the 64 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed.
uint64_t Box::getInt64(size_t index){
uint64_t Box::getInt64(size_t index) {
index += payloadOffset;
if (index + 7 >= boxedSize()){
if ( !reserve(index, 0, 8)){
if (index + 7 >= boxedSize()) {
if (!reserve(index, 0, 8)) {
return 0;
}
setInt64(0, index - payloadOffset);
}
uint64_t result = ntohl(((int*)(data + index))[0]);
uint64_t result = ntohl(((int *)(data + index))[0]);
result <<= 32;
result += ntohl(((int*)(data + index))[1]);
result += ntohl(((int *)(data + index))[1]);
return result;
}
/// Sets the NULL-terminated string at the given index.
/// Will attempt to resize if the string doesn't fit.
/// Fails silently if resizing failed.
void Box::setString(std::string newData, size_t index){
setString((char*)newData.c_str(), newData.size(), index);
void Box::setString(std::string newData, size_t index) {
setString((char *)newData.c_str(), newData.size(), index);
}
/// Sets the NULL-terminated string at the given index.
/// Will attempt to resize if the string doesn't fit.
/// Fails silently if resizing failed.
void Box::setString(char* newData, size_t size, size_t index){
void Box::setString(char * newData, size_t size, size_t index) {
index += payloadOffset;
if (index >= boxedSize()){
if ( !reserve(index, 0, 1)){
if (index >= boxedSize()) {
if (!reserve(index, 0, 1)) {
return;
}
data[index] = 0;
}
if (getStringLen(index) != size){
if ( !reserve(index, getStringLen(index) + 1, size + 1)){
if (getStringLen(index) != size) {
if (!reserve(index, getStringLen(index) + 1, size + 1)) {
return;
}
}
@ -559,10 +559,10 @@ namespace MP4 {
/// Gets the NULL-terminated string at the given index.
/// Will attempt to resize if the string is out of range.
/// Returns null if resizing failed.
char * Box::getString(size_t index){
char * Box::getString(size_t index) {
index += payloadOffset;
if (index >= boxedSize()){
if ( !reserve(index, 0, 1)){
if (index >= boxedSize()) {
if (!reserve(index, 0, 1)) {
return 0;
}
data[index] = 0;
@ -572,9 +572,9 @@ namespace MP4 {
/// Returns the length of the NULL-terminated string at the given index.
/// Returns 0 if out of range.
size_t Box::getStringLen(size_t index){
size_t Box::getStringLen(size_t index) {
index += payloadOffset;
if (index >= boxedSize()){
if (index >= boxedSize()) {
return 0;
}
return strlen(data + index);
@ -584,12 +584,12 @@ namespace MP4 {
/// Do not store or copy this reference, for there will be raptors.
/// Will attempt to resize if out of range.
/// Returns an 8-byte error box if resizing failed.
Box & Box::getBox(size_t index){
static Box retbox = Box((char*)"\000\000\000\010erro", false);
Box & Box::getBox(size_t index) {
static Box retbox = Box((char *)"\000\000\000\010erro", false);
index += payloadOffset;
if (index + 8 > boxedSize()){
if ( !reserve(index, 0, 8)){
retbox = Box((char*)"\000\000\000\010erro", false);
if (index + 8 > boxedSize()) {
if (!reserve(index, 0, 8)) {
retbox = Box((char *)"\000\000\000\010erro", false);
return retbox;
}
memcpy(data + index, "\000\000\000\010erro", 8);
@ -601,8 +601,8 @@ namespace MP4 {
/// Returns the size of the box at the given position.
/// Returns undefined values if there is no box at the given position.
/// Returns 0 if out of range.
size_t Box::getBoxLen(size_t index){
if ((index + payloadOffset + 8) > boxedSize()){
size_t Box::getBoxLen(size_t index) {
if ((index + payloadOffset + 8) > boxedSize()) {
return 0;
}
return getBox(index).boxedSize();
@ -610,10 +610,10 @@ namespace MP4 {
/// Replaces the existing box at the given index by the new box newEntry.
/// Will resize if needed, will reserve new space if out of range.
void Box::setBox(Box & newEntry, size_t index){
void Box::setBox(Box & newEntry, size_t index) {
int oldlen = getBoxLen(index);
int newlen = newEntry.boxedSize();
if (oldlen != newlen && !reserve(index + payloadOffset, oldlen, newlen)){
if (oldlen != newlen && !reserve(index + payloadOffset, oldlen, newlen)) {
return;
}
memcpy(data + index + payloadOffset, newEntry.asBox(), newlen);
@ -622,90 +622,90 @@ namespace MP4 {
/// Attempts to reserve enough space for wanted bytes of data at given position, where current bytes of data is now reserved.
/// This will move any existing data behind the currently reserved space to the proper location after reserving.
/// \returns True on success, false otherwise.
bool Box::reserve(size_t position, size_t current, size_t wanted){
if (current == wanted){
bool Box::reserve(size_t position, size_t current, size_t wanted) {
if (current == wanted) {
return true;
}
if (position > boxedSize()){
if (position > boxedSize()) {
wanted += position - boxedSize();
}
if (current < wanted){
if (current < wanted) {
//make bigger
if (boxedSize() + (wanted - current) > data_size){
if (boxedSize() + (wanted - current) > data_size) {
//realloc if managed, otherwise fail
if ( !managed){
if (!managed) {
return false;
}
void * ret = realloc(data, boxedSize() + (wanted - current));
if ( !ret){
if (!ret) {
return false;
}
data = (char*)ret;
data = (char *)ret;
memset(data + boxedSize(), 0, wanted - current); //initialize to 0
data_size = boxedSize() + (wanted - current);
}
}
//move data behind, if any
if (boxedSize() > (position + current)){
if (boxedSize() > (position + current)) {
memmove(data + position + wanted, data + position + current, boxedSize() - (position + current));
}
//calculate and set new size
if (payloadOffset != 16){
if (payloadOffset != 16) {
int newSize = boxedSize() + (wanted - current);
((int*)data)[0] = htonl(newSize);
((int *)data)[0] = htonl(newSize);
}
return true;
}
fullBox::fullBox(){
fullBox::fullBox() {
setVersion(0);
}
void fullBox::setVersion(char newVersion){
void fullBox::setVersion(char newVersion) {
setInt8(newVersion, 0);
}
char fullBox::getVersion(){
char fullBox::getVersion() {
return getInt8(0);
}
void fullBox::setFlags(uint32_t newFlags){
void fullBox::setFlags(uint32_t newFlags) {
setInt24(newFlags, 1);
}
uint32_t fullBox::getFlags(){
uint32_t fullBox::getFlags() {
return getInt24(1);
}
std::string fullBox::toPrettyString(uint32_t indent){
std::string fullBox::toPrettyString(uint32_t indent) {
std::stringstream r;
r << std::string(indent + 1, ' ') << "Version: " << (int)getVersion() << std::endl;
r << std::string(indent + 1, ' ') << "Flags: " << getFlags() << std::endl;
return r.str();
}
containerBox::containerBox(){
containerBox::containerBox() {
}
uint32_t containerBox::getContentCount(){
uint32_t containerBox::getContentCount() {
int res = 0;
unsigned int tempLoc = 0;
while (tempLoc < boxedSize() - 8){
while (tempLoc < boxedSize() - 8) {
res++;
tempLoc += Box(getBox(tempLoc).asBox(), false).boxedSize();
}
return res;
}
void containerBox::setContent(Box & newContent, uint32_t no){
void containerBox::setContent(Box & newContent, uint32_t no) {
int tempLoc = 0;
unsigned int contentCount = getContentCount();
for (unsigned int i = 0; i < no; i++){
if (i < contentCount){
for (unsigned int i = 0; i < no; i++) {
if (i < contentCount) {
tempLoc += getBoxLen(tempLoc);
}else{
if ( !reserve(tempLoc, 0, (no - contentCount) * 8)){
} else {
if (!reserve(tempLoc, 0, (no - contentCount) * 8)) {
return;
};
memset(data + tempLoc, 0, (no - contentCount) * 8);
@ -716,27 +716,27 @@ namespace MP4 {
setBox(newContent, tempLoc);
}
Box & containerBox::getContent(uint32_t no){
static Box ret = Box((char*)"\000\000\000\010erro", false);
if (no > getContentCount()){
Box & containerBox::getContent(uint32_t no) {
static Box ret = Box((char *)"\000\000\000\010erro", false);
if (no > getContentCount()) {
return ret;
}
unsigned int i = 0;
int tempLoc = 0;
while (i < no){
while (i < no) {
tempLoc += getBoxLen(tempLoc);
i++;
}
return getBox(tempLoc);
}
std::string containerBox::toPrettyString(uint32_t indent){
std::string containerBox::toPrettyString(uint32_t indent) {
std::stringstream r;
r << std::string(indent, ' ') << "[" << getType() <<"] Container Box (" << boxedSize() << ")" << std::endl;
r << std::string(indent, ' ') << "[" << getType() << "] Container Box (" << boxedSize() << ")" << std::endl;
Box curBox;
int tempLoc = 0;
int contentCount = getContentCount();
for (int i = 0; i < contentCount; i++){
for (int i = 0; i < contentCount; i++) {
curBox = getContent(i);
r << curBox.toPrettyString(indent + 1);
tempLoc += getBoxLen(tempLoc);
@ -744,24 +744,24 @@ namespace MP4 {
return r.str();
}
uint32_t containerFullBox::getContentCount(){
uint32_t containerFullBox::getContentCount() {
int res = 0;
unsigned int tempLoc = 4;
while (tempLoc < boxedSize() - 8){
while (tempLoc < boxedSize() - 8) {
res++;
tempLoc += getBoxLen(tempLoc);
}
return res;
}
void containerFullBox::setContent(Box & newContent, uint32_t no){
void containerFullBox::setContent(Box & newContent, uint32_t no) {
int tempLoc = 4;
unsigned int contentCount = getContentCount();
for (unsigned int i = 0; i < no; i++){
if (i < contentCount){
for (unsigned int i = 0; i < no; i++) {
if (i < contentCount) {
tempLoc += getBoxLen(tempLoc);
}else{
if ( !reserve(tempLoc, 0, (no - contentCount) * 8)){
} else {
if (!reserve(tempLoc, 0, (no - contentCount) * 8)) {
return;
};
memset(data + tempLoc, 0, (no - contentCount) * 8);
@ -772,28 +772,28 @@ namespace MP4 {
setBox(newContent, tempLoc);
}
Box & containerFullBox::getContent(uint32_t no){
static Box ret = Box((char*)"\000\000\000\010erro", false);
if (no > getContentCount()){
Box & containerFullBox::getContent(uint32_t no) {
static Box ret = Box((char *)"\000\000\000\010erro", false);
if (no > getContentCount()) {
return ret;
}
unsigned int i = 0;
int tempLoc = 4;
while (i < no){
while (i < no) {
tempLoc += getBoxLen(tempLoc);
i++;
}
return getBox(tempLoc);
}
std::string containerFullBox::toPrettyCFBString(uint32_t indent, std::string boxName){
std::string containerFullBox::toPrettyCFBString(uint32_t indent, std::string boxName) {
std::stringstream r;
r << std::string(indent, ' ') << boxName <<" (" << boxedSize() << ")" << std::endl;
r << std::string(indent, ' ') << boxName << " (" << boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent);
Box curBox;
int tempLoc = 4;
int contentCount = getContentCount();
for (int i = 0; i < contentCount; i++){
for (int i = 0; i < contentCount; i++) {
curBox = getContent(i);
r << curBox.toPrettyString(indent + 1);
tempLoc += getBoxLen(tempLoc);

View file

@ -19,15 +19,15 @@ namespace MP4 {
bool skipBox(FILE * newData);
class Box{
class Box {
public:
Box(char * datapointer = 0, bool manage = true);
Box(const Box & rs);
Box& operator = (const Box & rs);
Box & operator = (const Box & rs);
~Box();
std::string getType();
bool isType(const char* boxType);
bool read(FILE* newData);
bool isType(const char * boxType);
bool read(FILE * newData);
bool read(std::string & newData);
uint64_t boxedSize();
uint64_t payloadSize();
@ -49,7 +49,7 @@ namespace MP4 {
uint64_t getInt64(size_t index);
//string functions
void setString(std::string newData, size_t index);
void setString(char* newData, size_t size, size_t index);
void setString(char * newData, size_t size, size_t index);
char * getString(size_t index);
size_t getStringLen(size_t index);
//box functions
@ -66,7 +66,7 @@ namespace MP4 {
};
//Box Class
class fullBox: public Box{
class fullBox: public Box {
public:
fullBox();
void setVersion(char newVersion);
@ -76,7 +76,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class containerBox: public Box{
class containerBox: public Box {
public:
containerBox();
uint32_t getContentCount();
@ -85,7 +85,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class containerFullBox: public fullBox{
class containerFullBox: public fullBox {
public:
uint32_t getContentCount();
void setContent(Box & newContent, uint32_t no);

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@
namespace MP4 {
//class Box;
struct afrt_runtable{
struct afrt_runtable {
uint32_t firstFragment;
uint64_t firstTimestamp;
uint32_t duration;
@ -14,7 +14,7 @@ namespace MP4 {
//fragmentRun
/// AFRT Box class
class AFRT: public Box{
class AFRT: public Box {
public:
AFRT();
void setVersion(char newVersion);
@ -33,13 +33,13 @@ namespace MP4 {
};
//AFRT Box
struct asrt_runtable{
struct asrt_runtable {
uint32_t firstSegment;
uint32_t fragmentsPerSegment;
};
/// ASRT Box class
class ASRT: public Box{
class ASRT: public Box {
public:
ASRT();
void setVersion(char newVersion);
@ -48,7 +48,7 @@ namespace MP4 {
uint32_t getUpdate();
uint32_t getQualityEntryCount();
void setQualityEntry(std::string & newQuality, uint32_t no);
const char* getQualityEntry(uint32_t no);
const char * getQualityEntry(uint32_t no);
uint32_t getSegmentRunEntryCount();
void setSegmentRun(uint32_t firstSegment, uint32_t fragmentsPerSegment, uint32_t no);
asrt_runtable getSegmentRun(uint32_t no);
@ -57,7 +57,7 @@ namespace MP4 {
//ASRT Box
/// ABST Box class
class ABST: public Box{
class ABST: public Box {
public:
ABST();
void setVersion(char newVersion);
@ -100,18 +100,18 @@ namespace MP4 {
};
//ABST Box
struct afraentry{
struct afraentry {
uint64_t time;
uint64_t offset;
};
struct globalafraentry{
struct globalafraentry {
uint64_t time;
uint32_t segment;
uint32_t fragment;
uint64_t afraoffset;
uint64_t offsetfromafra;
};
class AFRA: public Box{
class AFRA: public Box {
public:
AFRA();
void setVersion(uint32_t newVersion);

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
#include "mp4.h"
namespace MP4{
class MFHD: public Box{
namespace MP4 {
class MFHD: public Box {
public:
MFHD();
void setSequenceNumber(uint32_t newSequenceNumber);
@ -10,13 +10,13 @@ namespace MP4{
};
//MFHD Box
class MOOF: public containerBox{
class MOOF: public containerBox {
public:
MOOF();
};
//MOOF Box
class TRAF: public Box{
class TRAF: public Box {
public:
TRAF();
uint32_t getContentCount();
@ -26,13 +26,13 @@ namespace MP4{
};
//TRAF Box
struct trunSampleInformation{
struct trunSampleInformation {
uint32_t sampleDuration;
uint32_t sampleSize;
uint32_t sampleFlags;
uint32_t sampleOffset;
};
enum trunflags{
enum trunflags {
trundataOffset = 0x00000001,
trunfirstSampleFlags = 0x00000004,
trunsampleDuration = 0x00000100,
@ -40,7 +40,7 @@ namespace MP4{
trunsampleFlags = 0x00000400,
trunsampleOffsets = 0x00000800
};
enum sampleflags{
enum sampleflags {
noIPicture = 0x01000000,
isIPicture = 0x02000000,
noDisposable = 0x00400000,
@ -52,7 +52,7 @@ namespace MP4{
MUST_BE_PRESENT = 0x1
};
std::string prettySampleFlags(uint32_t flag);
class TRUN: public Box{
class TRUN: public Box {
public:
TRUN();
void setFlags(uint32_t newFlags);
@ -67,7 +67,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
enum tfhdflags{
enum tfhdflags {
tfhdBaseOffset = 0x000001,
tfhdSampleDesc = 0x000002,
tfhdSampleDura = 0x000008,
@ -75,7 +75,7 @@ namespace MP4{
tfhdSampleFlag = 0x000020,
tfhdNoDuration = 0x010000,
};
class TFHD: public Box{
class TFHD: public Box {
public:
TFHD();
void setFlags(uint32_t newFlags);
@ -96,7 +96,7 @@ namespace MP4{
};
class AVCC: public Box{
class AVCC: public Box {
public:
AVCC();
void setVersion(uint32_t newVersion);
@ -111,19 +111,19 @@ namespace MP4{
uint32_t getSPSNumber();
void setSPS(std::string newSPS);
uint32_t getSPSLen();
char* getSPS();
char * getSPS();
void setPPSNumber(uint32_t newPPSNumber);
uint32_t getPPSNumber();
void setPPS(std::string newPPS);
uint32_t getPPSLen();
char* getPPS();
char * getPPS();
std::string asAnnexB();
void setPayload(std::string newPayload);
std::string toPrettyString(uint32_t indent = 0);
};
///\todo : ESDS is filthy implemented, clean up when optimising
class ESDS: public fullBox{
class ESDS: public fullBox {
public:
ESDS();
ESDS(std::string init, uint32_t bps);
@ -181,7 +181,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class FTYP: public Box{
class FTYP: public Box {
public:
FTYP();
void setMajorBrand(const char * newMajorBrand);
@ -194,17 +194,17 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class MOOV: public containerBox{
class MOOV: public containerBox {
public:
MOOV();
};
class MVEX: public containerBox{
class MVEX: public containerBox {
public:
MVEX();
};
class TREX: public Box{
class TREX: public Box {
public:
TREX();
void setTrackID(uint32_t newTrackID);
@ -221,32 +221,32 @@ namespace MP4{
};
class MFRA: public containerBox{
class MFRA: public containerBox {
public:
MFRA();
};
class TRAK: public containerBox{
class TRAK: public containerBox {
public:
TRAK();
};
class MDIA: public containerBox{
class MDIA: public containerBox {
public:
MDIA();
};
class MINF: public containerBox{
class MINF: public containerBox {
public:
MINF();
};
class DINF: public containerBox{
class DINF: public containerBox {
public:
DINF();
};
class MFRO: public Box{
class MFRO: public Box {
public:
MFRO();
void setSize(uint32_t newSize);
@ -254,7 +254,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class HDLR: public Box{
class HDLR: public Box {
public:
HDLR(std::string & type, std::string name);
void setHandlerType(const char * newHandlerType);
@ -264,7 +264,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class VMHD: public fullBox{
class VMHD: public fullBox {
public:
VMHD();
void setGraphicsMode(uint16_t newGraphicsMode);
@ -275,7 +275,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class SMHD: public fullBox{
class SMHD: public fullBox {
public:
SMHD();
void setBalance(int16_t newBalance);
@ -283,7 +283,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class HMHD: public fullBox{
class HMHD: public fullBox {
public:
HMHD();
void setMaxPDUSize(uint16_t newMaxPDUSize);
@ -297,13 +297,13 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class NMHD: public fullBox{
class NMHD: public fullBox {
public:
NMHD();
std::string toPrettyString(uint32_t indent = 0);
};
class MEHD: public fullBox{
class MEHD: public fullBox {
public:
MEHD();
void setFragmentDuration(uint64_t newFragmentDuration);
@ -311,12 +311,12 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class STBL: public containerBox{
class STBL: public containerBox {
public:
STBL();
};
class URL: public fullBox{
class URL: public fullBox {
public:
URL();
void setLocation(std::string newLocation);
@ -324,7 +324,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class URN: public fullBox{
class URN: public fullBox {
public:
URN();
void setName(std::string newName);
@ -334,7 +334,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class DREF: public fullBox{
class DREF: public fullBox {
public:
DREF();
uint32_t getEntryCount();
@ -343,7 +343,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class MVHD: public fullBox{
class MVHD: public fullBox {
public:
MVHD(long long unsigned int duration);
void setCreationTime(uint64_t newCreationTime);
@ -366,7 +366,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
struct TFRAEntry{
struct TFRAEntry {
uint64_t time;
uint64_t moofOffset;
uint32_t trafNumber;
@ -374,7 +374,7 @@ namespace MP4{
uint32_t sampleNumber;
};
class TFRA: public fullBox{
class TFRA: public fullBox {
public:
TFRA();
void setTrackID(uint32_t newTrackID);
@ -393,7 +393,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class TKHD: public fullBox{
class TKHD: public fullBox {
public:
TKHD(uint32_t trackId, uint64_t duration, uint32_t width, uint32_t height);
void setCreationTime(uint64_t newCreationTime);
@ -423,7 +423,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class MDHD: public fullBox{
class MDHD: public fullBox {
public:
MDHD(uint64_t duration);
void setCreationTime(uint64_t newCreationTime);
@ -440,12 +440,12 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
struct STTSEntry{
struct STTSEntry {
uint32_t sampleCount;
uint32_t sampleDelta;
};
class STTS: public fullBox{
class STTS: public fullBox {
public:
STTS(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
@ -455,12 +455,12 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
struct CTTSEntry{
struct CTTSEntry {
uint32_t sampleCount;
uint32_t sampleOffset;
};
class CTTS: public fullBox{
class CTTS: public fullBox {
public:
CTTS();
void setEntryCount(uint32_t newEntryCount);
@ -470,13 +470,13 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
struct STSCEntry{
struct STSCEntry {
uint32_t firstChunk;
uint32_t samplesPerChunk;
uint32_t sampleDescriptionIndex;
};
class STSC: public fullBox{
class STSC: public fullBox {
public:
STSC(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
@ -486,7 +486,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class STCO: public fullBox{
class STCO: public fullBox {
public:
STCO(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
@ -496,7 +496,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class STSZ: public fullBox{
class STSZ: public fullBox {
public:
STSZ(char v = 1, uint32_t f = 0);
void setSampleSize(uint32_t newSampleSize);
@ -508,7 +508,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class SampleEntry: public Box{
class SampleEntry: public Box {
public:
SampleEntry();
void setDataReferenceIndex(uint16_t newDataReferenceIndex);
@ -516,7 +516,7 @@ namespace MP4{
std::string toPrettySampleString(uint32_t index);
};
class CLAP: public Box{//CleanApertureBox
class CLAP: public Box { //CleanApertureBox
public:
CLAP();
void setCleanApertureWidthN(uint32_t newVal);
@ -538,7 +538,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class PASP: public Box{ //PixelAspectRatioBox
class PASP: public Box { //PixelAspectRatioBox
public:
PASP();
void setHSpacing(uint32_t newVal);
@ -548,18 +548,18 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class VisualSampleEntry: public SampleEntry{
class VisualSampleEntry: public SampleEntry {
///\todo set default values
public:
VisualSampleEntry();
void setCodec(const char* newCodec);
void setCodec(const char * newCodec);
void setWidth(uint16_t newWidth);
uint16_t getWidth();
void setHeight(uint16_t newHeight);
uint16_t getHeight();
void setHorizResolution (uint32_t newHorizResolution);
void setHorizResolution(uint32_t newHorizResolution);
uint32_t getHorizResolution();
void setVertResolution (uint32_t newVertResolution);
void setVertResolution(uint32_t newVertResolution);
uint32_t getVertResolution();
void setFrameCount(uint16_t newFrameCount);
uint16_t getFrameCount();
@ -568,16 +568,16 @@ namespace MP4{
void setDepth(uint16_t newDepth);
uint16_t getDepth();
Box & getCLAP();
void setCLAP(Box& clap);
void setCLAP(Box & clap);
Box & getPASP();
std::string toPrettyVisualString(uint32_t index = 0, std::string = "");
};
class AudioSampleEntry: public SampleEntry{
class AudioSampleEntry: public SampleEntry {
public:
///\todo set default values
AudioSampleEntry();
void setCodec(const char* newCodec);
void setCodec(const char * newCodec);
void setChannelCount(uint16_t newChannelCount);
uint16_t getChannelCount();
void setSampleSize(uint16_t newSampleSize);
@ -587,56 +587,56 @@ namespace MP4{
void setSampleRate(uint32_t newSampleRate);
uint16_t toAACInit();
uint32_t getSampleRate();
void setCodecBox(Box& newBox);
void setCodecBox(Box & newBox);
Box & getCodecBox();
std::string toPrettyAudioString(uint32_t indent = 0, std::string name = "");
};
class MP4A: public AudioSampleEntry{
class MP4A: public AudioSampleEntry {
public:
MP4A();
std::string toPrettyString(uint32_t indent = 0);
};
class AAC: public AudioSampleEntry{
class AAC: public AudioSampleEntry {
public:
AAC();
std::string toPrettyString(uint32_t indent = 0);
};
class AVC1: public VisualSampleEntry{
class AVC1: public VisualSampleEntry {
public:
AVC1();
std::string toPrettyString(uint32_t indent = 0);
};
class H264: public VisualSampleEntry{
class H264: public VisualSampleEntry {
public:
H264();
std::string toPrettyString(uint32_t indent = 0);
};
class STSD: public fullBox{
class STSD: public fullBox {
public:
STSD(char v = 1, uint32_t f = 0);
void setEntryCount (uint32_t newEntryCount);
void setEntryCount(uint32_t newEntryCount);
uint32_t getEntryCount();
void setEntry(Box & newContent, uint32_t no);
Box & getEntry(uint32_t no);
std::string toPrettyString(uint32_t indent = 0);
};
class EDTS: public containerBox{
class EDTS: public containerBox {
public:
EDTS();
};
class UDTA: public containerBox{
class UDTA: public containerBox {
public:
UDTA();
};
class STSS: public fullBox{
class STSS: public fullBox {
public:
STSS(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newVal);
@ -646,13 +646,13 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class META: public containerFullBox{
class META: public containerFullBox {
public:
META();
std::string toPrettyString(uint32_t indent = 0);
};
class ELST: public fullBox{
class ELST: public fullBox {
public:
ELST();
void setSegmentDuration(uint64_t newVal);

View file

@ -1,8 +1,8 @@
#include "mp4_ms.h"
namespace MP4{
namespace MP4 {
static char c2hex(int c){
static char c2hex(int c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
@ -10,34 +10,34 @@ namespace MP4{
}
SDTP::SDTP(){
SDTP::SDTP() {
memcpy(data + 4, "sdtp", 4);
}
void SDTP::setVersion(uint32_t newVersion){
void SDTP::setVersion(uint32_t newVersion) {
setInt8(newVersion, 0);
}
uint32_t SDTP::getVersion(){
uint32_t SDTP::getVersion() {
return getInt8(0);
}
void SDTP::setValue(uint32_t newValue, size_t index){
void SDTP::setValue(uint32_t newValue, size_t index) {
setInt8(newValue, index);
}
uint32_t SDTP::getValue(size_t index){
uint32_t SDTP::getValue(size_t index) {
return getInt8(index);
}
std::string SDTP::toPrettyString(uint32_t indent){
std::string SDTP::toPrettyString(uint32_t indent) {
std::stringstream r;
r << std::string(indent, ' ') << "[sdtp] Sample Dependancy Type (" << boxedSize() << ")" << std::endl;
r << std::string(indent + 1, ' ') << "Samples: " << (boxedSize() - 12) << std::endl;
for (size_t i = 1; i <= boxedSize() - 12; ++i){
uint32_t val = getValue(i+3);
for (size_t i = 1; i <= boxedSize() - 12; ++i) {
uint32_t val = getValue(i + 3);
r << std::string(indent + 2, ' ') << "[" << i << "] = ";
switch (val & 3){
switch (val & 3) {
case 0:
r << " ";
break;
@ -51,7 +51,7 @@ namespace MP4{
r << "Error, ";
break;
}
switch (val & 12){
switch (val & 12) {
case 0:
r << " ";
break;
@ -65,7 +65,7 @@ namespace MP4{
r << "Error, ";
break;
}
switch (val & 48){
switch (val & 48) {
case 0:
r << " ";
break;
@ -84,48 +84,48 @@ namespace MP4{
return r.str();
}
UUID::UUID(){
UUID::UUID() {
memcpy(data + 4, "uuid", 4);
setInt64(0, 0);
setInt64(0, 8);
}
std::string UUID::getUUID(){
std::string UUID::getUUID() {
std::stringstream r;
r << std::hex;
for (int i = 0; i < 16; ++i){
if (i == 4 || i == 6 || i == 8 || i == 10){
for (int i = 0; i < 16; ++i) {
if (i == 4 || i == 6 || i == 8 || i == 10) {
r << "-";
}
r << std::setfill('0') << std::setw(2) << std::right << (int)(data[8+i]);
r << std::setfill('0') << std::setw(2) << std::right << (int)(data[8 + i]);
}
return r.str();
}
void UUID::setUUID(const std::string & uuid_string){
void UUID::setUUID(const std::string & uuid_string) {
//reset UUID to zero
for (int i = 0; i < 4; ++i){
((uint32_t*)(data+8))[i] = 0;
for (int i = 0; i < 4; ++i) {
((uint32_t *)(data + 8))[i] = 0;
}
//set the UUID from the string, char by char
int i = 0;
for (size_t j = 0; j < uuid_string.size(); ++j){
if (uuid_string[j] == '-'){
for (size_t j = 0; j < uuid_string.size(); ++j) {
if (uuid_string[j] == '-') {
continue;
}
data[8+i/2] |= (c2hex(uuid_string[j]) << ((~i & 1) << 2));
data[8 + i / 2] |= (c2hex(uuid_string[j]) << ((~i & 1) << 2));
++i;
}
}
void UUID::setUUID(const char * raw_uuid){
memcpy(data+8, raw_uuid, 16);
void UUID::setUUID(const char * raw_uuid) {
memcpy(data + 8, raw_uuid, 16);
}
std::string UUID::toPrettyString(uint32_t indent){
std::string UUID::toPrettyString(uint32_t indent) {
std::string UUID = getUUID();
if (UUID == "d4807ef2-ca39-4695-8e54-26cb9e46a79f"){
return ((UUID_TrackFragmentReference*)this)->toPrettyString(indent);
if (UUID == "d4807ef2-ca39-4695-8e54-26cb9e46a79f") {
return ((UUID_TrackFragmentReference *)this)->toPrettyString(indent);
}
std::stringstream r;
r << std::string(indent, ' ') << "[uuid] Extension box (" << boxedSize() << ")" << std::endl;
@ -134,73 +134,73 @@ namespace MP4{
return r.str();
}
UUID_TrackFragmentReference::UUID_TrackFragmentReference(){
UUID_TrackFragmentReference::UUID_TrackFragmentReference() {
setUUID((std::string)"d4807ef2-ca39-4695-8e54-26cb9e46a79f");
}
void UUID_TrackFragmentReference::setVersion(uint32_t newVersion){
void UUID_TrackFragmentReference::setVersion(uint32_t newVersion) {
setInt8(newVersion, 16);
}
uint32_t UUID_TrackFragmentReference::getVersion(){
uint32_t UUID_TrackFragmentReference::getVersion() {
return getInt8(16);
}
void UUID_TrackFragmentReference::setFlags(uint32_t newFlags){
void UUID_TrackFragmentReference::setFlags(uint32_t newFlags) {
setInt24(newFlags, 17);
}
uint32_t UUID_TrackFragmentReference::getFlags(){
uint32_t UUID_TrackFragmentReference::getFlags() {
return getInt24(17);
}
void UUID_TrackFragmentReference::setFragmentCount(uint32_t newCount){
void UUID_TrackFragmentReference::setFragmentCount(uint32_t newCount) {
setInt8(newCount, 20);
}
uint32_t UUID_TrackFragmentReference::getFragmentCount(){
uint32_t UUID_TrackFragmentReference::getFragmentCount() {
return getInt8(20);
}
void UUID_TrackFragmentReference::setTime(size_t num, uint64_t newTime){
if (getVersion() == 0){
setInt32(newTime, 21+(num*8));
}else{
setInt64(newTime, 21+(num*16));
void UUID_TrackFragmentReference::setTime(size_t num, uint64_t newTime) {
if (getVersion() == 0) {
setInt32(newTime, 21 + (num * 8));
} else {
setInt64(newTime, 21 + (num * 16));
}
}
uint64_t UUID_TrackFragmentReference::getTime(size_t num){
if (getVersion() == 0){
return getInt32(21+(num*8));
}else{
return getInt64(21+(num*16));
uint64_t UUID_TrackFragmentReference::getTime(size_t num) {
if (getVersion() == 0) {
return getInt32(21 + (num * 8));
} else {
return getInt64(21 + (num * 16));
}
}
void UUID_TrackFragmentReference::setDuration(size_t num, uint64_t newDuration){
if (getVersion() == 0){
setInt32(newDuration, 21+(num*8)+4);
}else{
setInt64(newDuration, 21+(num*16)+8);
void UUID_TrackFragmentReference::setDuration(size_t num, uint64_t newDuration) {
if (getVersion() == 0) {
setInt32(newDuration, 21 + (num * 8) + 4);
} else {
setInt64(newDuration, 21 + (num * 16) + 8);
}
}
uint64_t UUID_TrackFragmentReference::getDuration(size_t num){
if (getVersion() == 0){
return getInt32(21+(num*8)+4);
}else{
return getInt64(21+(num*16)+8);
uint64_t UUID_TrackFragmentReference::getDuration(size_t num) {
if (getVersion() == 0) {
return getInt32(21 + (num * 8) + 4);
} else {
return getInt64(21 + (num * 16) + 8);
}
}
std::string UUID_TrackFragmentReference::toPrettyString(uint32_t indent){
std::string UUID_TrackFragmentReference::toPrettyString(uint32_t indent) {
std::stringstream r;
r << std::string(indent, ' ') << "[d4807ef2-ca39-4695-8e54-26cb9e46a79f] Track Fragment Reference (" << boxedSize() << ")" << std::endl;
r << std::string(indent + 1, ' ') << "Version: " << getVersion() << std::endl;
r << std::string(indent + 1, ' ') << "Fragments: " << getFragmentCount() << std::endl;
int j = getFragmentCount();
for (int i = 0; i < j; ++i){
for (int i = 0; i < j; ++i) {
r << std::string(indent + 2, ' ') << "[" << i << "] Time = " << getTime(i) << ", Duration = " << getDuration(i) << std::endl;
}
return r.str();

View file

@ -1,8 +1,8 @@
#pragma once
#include "mp4.h"
namespace MP4{
class SDTP: public Box{
namespace MP4 {
class SDTP: public Box {
public:
SDTP();
void setVersion(uint32_t newVersion);
@ -12,7 +12,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class UUID: public Box{
class UUID: public Box {
public:
UUID();
std::string getUUID();
@ -21,7 +21,7 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class UUID_TrackFragmentReference: public UUID{
class UUID_TrackFragmentReference: public UUID {
public:
UUID_TrackFragmentReference();
void setVersion(uint32_t newVersion);

2
lib/nal.cpp Executable file → Normal file
View file

@ -197,7 +197,7 @@ namespace h264 {
//vuiParameters
if (bs.get(1)) {
//Skipping all the paramters we dont use
if (bs.get(1)){
if (bs.get(1)) {
if (bs.get(8) == 255) {
bs.skip(32);
}

16
lib/nal.h Executable file → Normal file
View file

@ -1,17 +1,17 @@
#include <string>
#include <cstdio>
namespace h264{
namespace h264 {
///Struct containing pre-calculated metadata of an SPS nal unit. Width and height in pixels, fps in Hz
struct SPSMeta{
struct SPSMeta {
unsigned int width;
unsigned int height;
double fps;
};
///Class for analyzing generic nal units
class NAL{
class NAL {
public:
NAL();
NAL(std::string & InputData);
@ -27,19 +27,19 @@ namespace h264{
//NAL class
///Special instance of NAL class for analyzing SPS nal units
class SPS: public NAL{
class SPS: public NAL {
public:
SPS():NAL(){};
SPS(): NAL() {};
SPS(std::string & InputData, bool raw = false);
SPSMeta getCharacteristics();
void analyzeSPS();
};
///Special instance of NAL class for analyzing PPS nal units
class PPS: public NAL{
class PPS: public NAL {
public:
PPS():NAL(){};
PPS(std::string & InputData):NAL(InputData){};
PPS(): NAL() {};
PPS(std::string & InputData): NAL(InputData) {};
void analyzePPS();
};
}//ns h264

View file

@ -5,87 +5,87 @@
#include <sstream>
#include <arpa/inet.h>
namespace OGG{
inline long long unsigned int get_64(char* data){
namespace OGG {
inline long long unsigned int get_64(char * data) {
long long unsigned int temp = 0;
for (int i = 7; i>= 0; --i){
for (int i = 7; i >= 0; --i) {
temp <<= 8;
temp += data[i];
}
return temp;
}
inline long unsigned int get_32(char* data){
inline long unsigned int get_32(char * data) {
long unsigned int temp = 0;
for (int i = 3; i>= 0; --i){
for (int i = 3; i >= 0; --i) {
temp <<= 8;
temp += data[i];
}
return temp;
}
inline void set_64(char* data, long unsigned int val){
for (int i = 0; i< 8; ++i){
inline void set_64(char * data, long unsigned int val) {
for (int i = 0; i < 8; ++i) {
data[i] = val & 0xFF;
val >>= 8;
}
}
inline void set_32(char* data, long unsigned int val){
for (int i = 0; i< 4; ++i){
inline void set_32(char * data, long unsigned int val) {
for (int i = 0; i < 4; ++i) {
data[i] = val & 0xFF;
val >>= 8;
}
}
Page::Page(){
Page::Page() {
data = NULL;
datasize = 0;
dataSum = 0;
}
Page::~Page(){
if (data){
Page::~Page() {
if (data) {
free(data);
}
}
bool Page::read(std::string & newData){
bool Page::read(std::string & newData) {
segmentTableDeque.clear();
//datasize = 0;
if (newData.size()<27){
if (newData.size() < 27) {
return false;
}
if (newData.substr(0, 4) != "OggS"){
if (newData.substr(0, 4) != "OggS") {
DEBUG_MSG(DLVL_FAIL, "Invalid Ogg page encountered - cannot continue");
return false;
}
dataSum = 0;
if (!checkDataSize(27)){
if (!checkDataSize(27)) {
return false;
}
memcpy(data, newData.c_str(), 27);//copying the header, always 27 bytes
if (newData.size() < 27u + getPageSegments()){//check input size
if (newData.size() < 27u + getPageSegments()) { //check input size
return false;
}
if(!checkDataSize(27 + getPageSegments())){//check if size available in memory
if (!checkDataSize(27 + getPageSegments())) { //check if size available in memory
return false;
}
memcpy(data + 27, newData.c_str() + 27, getPageSegments());
//copying the first part of the page into data, which tells the size of the page
for(unsigned int i = 0; i < getPageSegments(); i++){
for (unsigned int i = 0; i < getPageSegments(); i++) {
dataSum += getSegmentTable()[i];
}
if (newData.size() < 27 + getPageSegments() + dataSum){//check input size
if (newData.size() < 27 + getPageSegments() + dataSum) { //check input size
dataSum = 0;
return false;
}
if(!checkDataSize(27 + getPageSegments()+dataSum)){
if (!checkDataSize(27 + getPageSegments() + dataSum)) {
dataSum = 0;
return false;
}
@ -95,38 +95,38 @@ namespace OGG{
}
bool Page::read(FILE * inFile){
bool Page::read(FILE * inFile) {
segmentTableDeque.clear();
int oriPos = ftell(inFile);
dataSum = 0;
if (!checkDataSize(27)){
DEBUG_MSG(DLVL_WARN,"Unable to read a page: memory allocation");
if (!checkDataSize(27)) {
DEBUG_MSG(DLVL_WARN, "Unable to read a page: memory allocation");
return false;
}
if (!fread(data, 27, 1, inFile)){
DEBUG_MSG(DLVL_WARN,"Unable to read a page: fread");
if (!fread(data, 27, 1, inFile)) {
DEBUG_MSG(DLVL_WARN, "Unable to read a page: fread");
fseek(inFile, oriPos, SEEK_SET);
return false;
}
if(!checkDataSize(27 + getPageSegments())){
DEBUG_MSG(DLVL_WARN,"Unable to read a page: memory allocation1");
if (!checkDataSize(27 + getPageSegments())) {
DEBUG_MSG(DLVL_WARN, "Unable to read a page: memory allocation1");
return false;
}
if (!fread(data + 27, getPageSegments(), 1, inFile)){
DEBUG_MSG(DLVL_WARN,"Unable to read a page: fread1");
if (!fread(data + 27, getPageSegments(), 1, inFile)) {
DEBUG_MSG(DLVL_WARN, "Unable to read a page: fread1");
fseek(inFile, oriPos, SEEK_SET);
return false;
}
for (unsigned int i = 0; i < getPageSegments(); i++){
for (unsigned int i = 0; i < getPageSegments(); i++) {
dataSum += data[27 + i];
}
if (!checkDataSize(27 + getPageSegments() + dataSum)){
DEBUG_MSG(DLVL_WARN,"Unable to read a page: memory allocation2");
if (!checkDataSize(27 + getPageSegments() + dataSum)) {
DEBUG_MSG(DLVL_WARN, "Unable to read a page: memory allocation2");
dataSum = 0;
return false;
}
if ( !fread(data + 27 + getPageSegments(), dataSum, 1, inFile)){
DEBUG_MSG(DLVL_WARN,"Unable to read a page: fread2");
if (!fread(data + 27 + getPageSegments(), dataSum, 1, inFile)) {
DEBUG_MSG(DLVL_WARN, "Unable to read a page: fread2");
fseek(inFile, oriPos, SEEK_SET);
dataSum = 0;
return false;
@ -134,143 +134,143 @@ namespace OGG{
return true;
}
bool Page::getSegment(unsigned int index, char * ret, unsigned int & len){
if (index > segmentTableDeque.size()){
bool Page::getSegment(unsigned int index, char * ret, unsigned int & len) {
if (index > segmentTableDeque.size()) {
ret = NULL;
len = 0;
return false;
}
ret = getFullPayload();
for (unsigned int i = 0; i < index; i++){
for (unsigned int i = 0; i < index; i++) {
ret += segmentTableDeque[i];
}
len = segmentTableDeque[index];
return true;
}
void Page::setMagicNumber(){
if(checkDataSize(4)){
void Page::setMagicNumber() {
if (checkDataSize(4)) {
memcpy(data, "OggS", 4);
}
}
char Page::getVersion(){
char Page::getVersion() {
return data[4];
}
void Page::setVersion(char newVal){
if(checkDataSize(5)){
void Page::setVersion(char newVal) {
if (checkDataSize(5)) {
data[4] = newVal;
}
}
char Page::getHeaderType(){
char Page::getHeaderType() {
return data[5];
}
void Page::setHeaderType(char newVal){
if(checkDataSize(6)){
void Page::setHeaderType(char newVal) {
if (checkDataSize(6)) {
data[5] = newVal;
}
}
long long unsigned int Page::getGranulePosition(){
if(checkDataSize(14)){
long long unsigned int Page::getGranulePosition() {
if (checkDataSize(14)) {
//switching bit order upon return
//return ntohl(((long unsigned*)(data+6))[1]) & ((long long unsigned)((long long unsigned)ntohl(((long unsigned*)(data+6))[0]) << 32));
//long long unsigned int temp;
//temp = ((long unsigned int)(data+6)[0]);
//temp = temp << 32 + ((long unsigned int)(data+6)[1]);
return get_64(data+6);
return get_64(data + 6);
}
return 0;
}
void Page::setGranulePosition(long long unsigned int newVal){
if(checkDataSize(14)){
set_64(data+6, newVal);
void Page::setGranulePosition(long long unsigned int newVal) {
if (checkDataSize(14)) {
set_64(data + 6, newVal);
}
}
long unsigned int Page::getBitstreamSerialNumber(){
long unsigned int Page::getBitstreamSerialNumber() {
//return ntohl(((long unsigned int*)(data+14))[0]);
return get_32(data+14);
return get_32(data + 14);
}
void Page::setBitstreamSerialNumber(long unsigned int newVal){
if(checkDataSize(18)){
void Page::setBitstreamSerialNumber(long unsigned int newVal) {
if (checkDataSize(18)) {
//((long unsigned *)(data+14))[0] = htonl(newVal);
set_32(data+14, newVal);
set_32(data + 14, newVal);
}
}
long unsigned int Page::getPageSequenceNumber(){
return get_32(data+18);
long unsigned int Page::getPageSequenceNumber() {
return get_32(data + 18);
}
void Page::setPageSequenceNumber(long unsigned int newVal){
if(checkDataSize(22)){
void Page::setPageSequenceNumber(long unsigned int newVal) {
if (checkDataSize(22)) {
//((long unsigned *)(data+18))[0] = htonl(newVal);
set_32(data+18, newVal);
set_32(data + 18, newVal);
}
}
long unsigned int Page::getCRCChecksum(){
long unsigned int Page::getCRCChecksum() {
//return ntohl(((long unsigned int*)(data+22))[0]);
return get_32(data+22);
return get_32(data + 22);
}
void Page::setCRCChecksum(long unsigned int newVal){
if(checkDataSize(26)){
set_32(data+22,newVal);
void Page::setCRCChecksum(long unsigned int newVal) {
if (checkDataSize(26)) {
set_32(data + 22, newVal);
}
}
char Page::getPageSegments(){
char Page::getPageSegments() {
return data[26];
}
inline void Page::setPageSegments(char newVal){
if(checkDataSize(26)){
inline void Page::setPageSegments(char newVal) {
if (checkDataSize(26)) {
data[26] = newVal;
}
}
char* Page::getSegmentTable(){
return data+27;
char * Page::getSegmentTable() {
return data + 27;
}
std::deque<unsigned int> & Page::getSegmentTableDeque(){
if ( !segmentTableDeque.size()){
std::deque<unsigned int> & Page::getSegmentTableDeque() {
if (!segmentTableDeque.size()) {
unsigned int temp = 0;
for (unsigned int i = 0; i < getPageSegments(); i++){
for (unsigned int i = 0; i < getPageSegments(); i++) {
temp += getSegmentTable()[i];
if (getSegmentTable()[i] < 255){
if (getSegmentTable()[i] < 255) {
segmentTableDeque.push_back(temp);
temp = 0;
}
}
if (temp!=0){
if (temp != 0) {
segmentTableDeque.push_back(temp);
}
}
return segmentTableDeque;
}
static void STerrMSG(){
static void STerrMSG() {
DEBUG_MSG(DLVL_ERROR, "Segment too big, create a continue page");
}
bool Page::setSegmentTable(std::vector<unsigned int> layout){
dataSum=0;
for (unsigned int i = 0; i < layout.size(); i++){
bool Page::setSegmentTable(std::vector<unsigned int> layout) {
dataSum = 0;
for (unsigned int i = 0; i < layout.size(); i++) {
dataSum += layout[i];
}
unsigned int place = 0;
char table[256];
for (unsigned int i = 0; i < layout.size(); i++){
int amount = (layout[i]/255) + 1;
if (i == layout.size() - 1 && place + amount > (255 + (layout[i] % 255 == 0))){
for (unsigned int i = 0; i < layout.size(); i++) {
int amount = (layout[i] / 255) + 1;
if (i == layout.size() - 1 && place + amount > (255 + (layout[i] % 255 == 0))) {
STerrMSG();
return false;
}
@ -279,141 +279,140 @@ namespace OGG{
place += amount;
}
//Don't send element 256, even if it was filled.
if (place > 255){
if (place > 255) {
place = 255;
}
setPageSegments(place);
setSegmentTable(table,place);
setSegmentTable(table, place);
return true;
}
void Page::setSegmentTable(char* newVal, unsigned int length){
if(checkDataSize(27 + length)){
void Page::setSegmentTable(char * newVal, unsigned int length) {
if (checkDataSize(27 + length)) {
memcpy(data + 27, newVal, length);
}
}
unsigned long int Page::getPageSize(){
return 27 + getPageSegments()+dataSum;
unsigned long int Page::getPageSize() {
return 27 + getPageSegments() + dataSum;
}
char* Page::getPage(){
char * Page::getPage() {
return data;
}
char* Page::getFullPayload(){
char * Page::getFullPayload() {
return data + 27 + getPageSegments();
}
void Page::setInternalCodec(std::string myCodec){
void Page::setInternalCodec(std::string myCodec) {
codec = myCodec;
}
std::string Page::toPrettyString(size_t indent){
std::string Page::toPrettyString(size_t indent) {
std::stringstream r;
r << std::string(indent,' ') << "Ogg page (" << getPageSize() << ")" << std::endl;
r << std::string(indent + 2,' ') << "Version: " << (int)getVersion() << std::endl;
r << std::string(indent + 2,' ') << "Header type:";
if ( !getHeaderType()){
r << std::string(indent, ' ') << "Ogg page (" << getPageSize() << ")" << std::endl;
r << std::string(indent + 2, ' ') << "Version: " << (int)getVersion() << std::endl;
r << std::string(indent + 2, ' ') << "Header type:";
if (!getHeaderType()) {
r << " Normal";
}else{
if (getHeaderType() & Continued){
} else {
if (getHeaderType() & Continued) {
r << " Continued";
}
if (getHeaderType() & BeginOfStream){
if (getHeaderType() & BeginOfStream) {
r << " BeginOfStream";
}
if (getHeaderType() & EndOfStream){
if (getHeaderType() & EndOfStream) {
r << " EndOfStream";
}
}
r << " (" << (int)getHeaderType() << ")" << std::endl;
r << std::string(indent + 2,' ') << "Granule position: " << getGranulePosition() << std::endl;
r << std::string(indent + 2,' ') << "Bitstream number: " << getBitstreamSerialNumber() << std::endl;
r << std::string(indent + 2,' ') << "Sequence number: " << getPageSequenceNumber() << std::endl;
r << std::string(indent + 2,' ') << "Checksum: " << std::hex << getCRCChecksum() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "Granule position: " << getGranulePosition() << std::endl;
r << std::string(indent + 2, ' ') << "Bitstream number: " << getBitstreamSerialNumber() << std::endl;
r << std::string(indent + 2, ' ') << "Sequence number: " << getPageSequenceNumber() << std::endl;
r << std::string(indent + 2, ' ') << "Checksum: " << std::hex << getCRCChecksum() << std::dec << std::endl;
//r << " Calced Checksum: " << std::hex << calcChecksum() << std::dec << std::endl;
r << std::string(indent + 2,' ') << "Payloadsize: " << dataSum << std::endl;
r << std::string(indent + 2,' ') << (int)getPageSegments() << " segments:" << std::endl;
r << std::string(indent + 3,' ');
r << std::string(indent + 2, ' ') << "Payloadsize: " << dataSum << std::endl;
r << std::string(indent + 2, ' ') << (int)getPageSegments() << " segments:" << std::endl;
r << std::string(indent + 3, ' ');
std::deque<unsigned int> temp = getSegmentTableDeque();
for (std::deque<unsigned int>::iterator i = temp.begin(); i != temp.end(); i++){
for (std::deque<unsigned int>::iterator i = temp.begin(); i != temp.end(); i++) {
r << " " << (*i);
}
r << std::endl;
return r.str();
}
inline unsigned int crc32(unsigned int crc, const char *data, size_t len){
inline unsigned int crc32(unsigned int crc, const char * data, size_t len) {
static const unsigned int table[256] = {
0x00000000U,0x04C11DB7U,0x09823B6EU,0x0D4326D9U,
0x130476DCU,0x17C56B6BU,0x1A864DB2U,0x1E475005U,
0x2608EDB8U,0x22C9F00FU,0x2F8AD6D6U,0x2B4BCB61U,
0x350C9B64U,0x31CD86D3U,0x3C8EA00AU,0x384FBDBDU,
0x4C11DB70U,0x48D0C6C7U,0x4593E01EU,0x4152FDA9U,
0x5F15ADACU,0x5BD4B01BU,0x569796C2U,0x52568B75U,
0x6A1936C8U,0x6ED82B7FU,0x639B0DA6U,0x675A1011U,
0x791D4014U,0x7DDC5DA3U,0x709F7B7AU,0x745E66CDU,
0x9823B6E0U,0x9CE2AB57U,0x91A18D8EU,0x95609039U,
0x8B27C03CU,0x8FE6DD8BU,0x82A5FB52U,0x8664E6E5U,
0xBE2B5B58U,0xBAEA46EFU,0xB7A96036U,0xB3687D81U,
0xAD2F2D84U,0xA9EE3033U,0xA4AD16EAU,0xA06C0B5DU,
0xD4326D90U,0xD0F37027U,0xDDB056FEU,0xD9714B49U,
0xC7361B4CU,0xC3F706FBU,0xCEB42022U,0xCA753D95U,
0xF23A8028U,0xF6FB9D9FU,0xFBB8BB46U,0xFF79A6F1U,
0xE13EF6F4U,0xE5FFEB43U,0xE8BCCD9AU,0xEC7DD02DU,
0x34867077U,0x30476DC0U,0x3D044B19U,0x39C556AEU,
0x278206ABU,0x23431B1CU,0x2E003DC5U,0x2AC12072U,
0x128E9DCFU,0x164F8078U,0x1B0CA6A1U,0x1FCDBB16U,
0x018AEB13U,0x054BF6A4U,0x0808D07DU,0x0CC9CDCAU,
0x7897AB07U,0x7C56B6B0U,0x71159069U,0x75D48DDEU,
0x6B93DDDBU,0x6F52C06CU,0x6211E6B5U,0x66D0FB02U,
0x5E9F46BFU,0x5A5E5B08U,0x571D7DD1U,0x53DC6066U,
0x4D9B3063U,0x495A2DD4U,0x44190B0DU,0x40D816BAU,
0xACA5C697U,0xA864DB20U,0xA527FDF9U,0xA1E6E04EU,
0xBFA1B04BU,0xBB60ADFCU,0xB6238B25U,0xB2E29692U,
0x8AAD2B2FU,0x8E6C3698U,0x832F1041U,0x87EE0DF6U,
0x99A95DF3U,0x9D684044U,0x902B669DU,0x94EA7B2AU,
0xE0B41DE7U,0xE4750050U,0xE9362689U,0xEDF73B3EU,
0xF3B06B3BU,0xF771768CU,0xFA325055U,0xFEF34DE2U,
0xC6BCF05FU,0xC27DEDE8U,0xCF3ECB31U,0xCBFFD686U,
0xD5B88683U,0xD1799B34U,0xDC3ABDEDU,0xD8FBA05AU,
0x690CE0EEU,0x6DCDFD59U,0x608EDB80U,0x644FC637U,
0x7A089632U,0x7EC98B85U,0x738AAD5CU,0x774BB0EBU,
0x4F040D56U,0x4BC510E1U,0x46863638U,0x42472B8FU,
0x5C007B8AU,0x58C1663DU,0x558240E4U,0x51435D53U,
0x251D3B9EU,0x21DC2629U,0x2C9F00F0U,0x285E1D47U,
0x36194D42U,0x32D850F5U,0x3F9B762CU,0x3B5A6B9BU,
0x0315D626U,0x07D4CB91U,0x0A97ED48U,0x0E56F0FFU,
0x1011A0FAU,0x14D0BD4DU,0x19939B94U,0x1D528623U,
0xF12F560EU,0xF5EE4BB9U,0xF8AD6D60U,0xFC6C70D7U,
0xE22B20D2U,0xE6EA3D65U,0xEBA91BBCU,0xEF68060BU,
0xD727BBB6U,0xD3E6A601U,0xDEA580D8U,0xDA649D6FU,
0xC423CD6AU,0xC0E2D0DDU,0xCDA1F604U,0xC960EBB3U,
0xBD3E8D7EU,0xB9FF90C9U,0xB4BCB610U,0xB07DABA7U,
0xAE3AFBA2U,0xAAFBE615U,0xA7B8C0CCU,0xA379DD7BU,
0x9B3660C6U,0x9FF77D71U,0x92B45BA8U,0x9675461FU,
0x8832161AU,0x8CF30BADU,0x81B02D74U,0x857130C3U,
0x5D8A9099U,0x594B8D2EU,0x5408ABF7U,0x50C9B640U,
0x4E8EE645U,0x4A4FFBF2U,0x470CDD2BU,0x43CDC09CU,
0x7B827D21U,0x7F436096U,0x7200464FU,0x76C15BF8U,
0x68860BFDU,0x6C47164AU,0x61043093U,0x65C52D24U,
0x119B4BE9U,0x155A565EU,0x18197087U,0x1CD86D30U,
0x029F3D35U,0x065E2082U,0x0B1D065BU,0x0FDC1BECU,
0x3793A651U,0x3352BBE6U,0x3E119D3FU,0x3AD08088U,
0x2497D08DU,0x2056CD3AU,0x2D15EBE3U,0x29D4F654U,
0xC5A92679U,0xC1683BCEU,0xCC2B1D17U,0xC8EA00A0U,
0xD6AD50A5U,0xD26C4D12U,0xDF2F6BCBU,0xDBEE767CU,
0xE3A1CBC1U,0xE760D676U,0xEA23F0AFU,0xEEE2ED18U,
0xF0A5BD1DU,0xF464A0AAU,0xF9278673U,0xFDE69BC4U,
0x89B8FD09U,0x8D79E0BEU,0x803AC667U,0x84FBDBD0U,
0x9ABC8BD5U,0x9E7D9662U,0x933EB0BBU,0x97FFAD0CU,
0xAFB010B1U,0xAB710D06U,0xA6322BDFU,0xA2F33668U,
0xBCB4666DU,0xB8757BDAU,0xB5365D03U,0xB1F740B4U,
0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U,
0x130476DCU, 0x17C56B6BU, 0x1A864DB2U, 0x1E475005U,
0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U,
0x350C9B64U, 0x31CD86D3U, 0x3C8EA00AU, 0x384FBDBDU,
0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U,
0x5F15ADACU, 0x5BD4B01BU, 0x569796C2U, 0x52568B75U,
0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U,
0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU,
0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU, 0x95609039U,
0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U,
0xBE2B5B58U, 0xBAEA46EFU, 0xB7A96036U, 0xB3687D81U,
0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU,
0xD4326D90U, 0xD0F37027U, 0xDDB056FEU, 0xD9714B49U,
0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U,
0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U,
0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU, 0xEC7DD02DU,
0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU,
0x278206ABU, 0x23431B1CU, 0x2E003DC5U, 0x2AC12072U,
0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U,
0x018AEB13U, 0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU,
0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU,
0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U,
0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U, 0x53DC6066U,
0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU,
0xACA5C697U, 0xA864DB20U, 0xA527FDF9U, 0xA1E6E04EU,
0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U,
0x8AAD2B2FU, 0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U,
0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU,
0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU,
0xF3B06B3BU, 0xF771768CU, 0xFA325055U, 0xFEF34DE2U,
0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U,
0xD5B88683U, 0xD1799B34U, 0xDC3ABDEDU, 0xD8FBA05AU,
0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U,
0x7A089632U, 0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU,
0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU,
0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U,
0x251D3B9EU, 0x21DC2629U, 0x2C9F00F0U, 0x285E1D47U,
0x36194D42U, 0x32D850F5U, 0x3F9B762CU, 0x3B5A6B9BU,
0x0315D626U, 0x07D4CB91U, 0x0A97ED48U, 0x0E56F0FFU,
0x1011A0FAU, 0x14D0BD4DU, 0x19939B94U, 0x1D528623U,
0xF12F560EU, 0xF5EE4BB9U, 0xF8AD6D60U, 0xFC6C70D7U,
0xE22B20D2U, 0xE6EA3D65U, 0xEBA91BBCU, 0xEF68060BU,
0xD727BBB6U, 0xD3E6A601U, 0xDEA580D8U, 0xDA649D6FU,
0xC423CD6AU, 0xC0E2D0DDU, 0xCDA1F604U, 0xC960EBB3U,
0xBD3E8D7EU, 0xB9FF90C9U, 0xB4BCB610U, 0xB07DABA7U,
0xAE3AFBA2U, 0xAAFBE615U, 0xA7B8C0CCU, 0xA379DD7BU,
0x9B3660C6U, 0x9FF77D71U, 0x92B45BA8U, 0x9675461FU,
0x8832161AU, 0x8CF30BADU, 0x81B02D74U, 0x857130C3U,
0x5D8A9099U, 0x594B8D2EU, 0x5408ABF7U, 0x50C9B640U,
0x4E8EE645U, 0x4A4FFBF2U, 0x470CDD2BU, 0x43CDC09CU,
0x7B827D21U, 0x7F436096U, 0x7200464FU, 0x76C15BF8U,
0x68860BFDU, 0x6C47164AU, 0x61043093U, 0x65C52D24U,
0x119B4BE9U, 0x155A565EU, 0x18197087U, 0x1CD86D30U,
0x029F3D35U, 0x065E2082U, 0x0B1D065BU, 0x0FDC1BECU,
0x3793A651U, 0x3352BBE6U, 0x3E119D3FU, 0x3AD08088U,
0x2497D08DU, 0x2056CD3AU, 0x2D15EBE3U, 0x29D4F654U,
0xC5A92679U, 0xC1683BCEU, 0xCC2B1D17U, 0xC8EA00A0U,
0xD6AD50A5U, 0xD26C4D12U, 0xDF2F6BCBU, 0xDBEE767CU,
0xE3A1CBC1U, 0xE760D676U, 0xEA23F0AFU, 0xEEE2ED18U,
0xF0A5BD1DU, 0xF464A0AAU, 0xF9278673U, 0xFDE69BC4U,
0x89B8FD09U, 0x8D79E0BEU, 0x803AC667U, 0x84FBDBD0U,
0x9ABC8BD5U, 0x9E7D9662U, 0x933EB0BBU, 0x97FFAD0CU,
0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U,
0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U,
};
while (len > 0)
{
while (len > 0) {
crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
data++;
len--;
@ -421,39 +420,39 @@ namespace OGG{
return crc;
}
long unsigned int Page::calcChecksum(){
long unsigned int Page::calcChecksum() {
long unsigned int retVal = 0;
long unsigned int oldChecksum = getCRCChecksum();
setCRCChecksum (0);
setCRCChecksum(0);
retVal = crc32(0, data, getPageSize());
setCRCChecksum (oldChecksum);
setCRCChecksum(oldChecksum);
return retVal;
}
inline bool Page::checkDataSize(unsigned int size){
if (size > datasize){
void* tmp = realloc(data,size);
if (tmp){
data = (char*)tmp;
inline bool Page::checkDataSize(unsigned int size) {
if (size > datasize) {
void * tmp = realloc(data, size);
if (tmp) {
data = (char *)tmp;
datasize = size;
return true;
}else{
} else {
return false;
}
}else{
} else {
return true;
}
}
int Page::getPayloadSize(){
int Page::getPayloadSize() {
return dataSum;
}
bool Page::clear(){
if(!checkDataSize(27)){//check if size available in memory
bool Page::clear() {
if (!checkDataSize(27)) { //check if size available in memory
return false;
}
memset(data,0,27);
memset(data, 0, 27);
dataSum = 0;
codec = "";
setMagicNumber();
@ -461,30 +460,30 @@ namespace OGG{
return true;
}
bool Page::setPayload(char* newData, unsigned int length){
if(!checkDataSize(27 + getPageSegments() + length)){//check if size available in memory
bool Page::setPayload(char * newData, unsigned int length) {
if (!checkDataSize(27 + getPageSegments() + length)) { //check if size available in memory
return false;
}
memcpy(data + 27 + getPageSegments(), newData, length);
return true;
}
void Page::readDTSCVector(std::vector <JSON::Value> DTSCVec, unsigned int serial, unsigned int sequence){
void Page::readDTSCVector(std::vector <JSON::Value> DTSCVec, unsigned int serial, unsigned int sequence) {
clear();
setVersion();
if (DTSCVec[0]["OggCont"] ){//if it is a continue page, also for granule=0xFFFFFFFF
if (DTSCVec[0]["OggCont"]) {//if it is a continue page, also for granule=0xFFFFFFFF
setHeaderType(1);//headertype 1 = Continue Page
}else if (DTSCVec[0]["OggEOS"]){
} else if (DTSCVec[0]["OggEOS"]) {
setHeaderType(4);//headertype 4 = end of stream
}else{
} else {
setHeaderType(0);//headertype 0 = normal
}
setGranulePosition(DTSCVec[0]["granule"].asInt());
for (unsigned int i = 1; i < DTSCVec.size(); i++){
if (DTSCVec[0]["granule"].asInt() != DTSCVec[i]["granule"].asInt()){
for (unsigned int i = 1; i < DTSCVec.size(); i++) {
if (DTSCVec[0]["granule"].asInt() != DTSCVec[i]["granule"].asInt()) {
DEBUG_MSG(DLVL_WARN, "Granule inconcistency!! %u != %u", (unsigned int)DTSCVec[0]["granule"].asInt(), (unsigned int)DTSCVec[i]["granule"].asInt());
}
if (DTSCVec[0]["trackid"].asInt() != DTSCVec[i]["trackid"].asInt()){
if (DTSCVec[0]["trackid"].asInt() != DTSCVec[i]["trackid"].asInt()) {
DEBUG_MSG(DLVL_WARN, "Track ID inconcistency!! %u != %u", (unsigned int)DTSCVec[0]["trackid"].asInt(), (unsigned int)DTSCVec[i]["trackid"].asInt());
}
}
@ -494,37 +493,37 @@ namespace OGG{
std::vector<unsigned int> curSegTable;
std::string pageBuffer;
for (unsigned int i = 0; i < DTSCVec.size(); i++){
for (unsigned int i = 0; i < DTSCVec.size(); i++) {
curSegTable.push_back(DTSCVec[i]["data"].asString().size());
pageBuffer += DTSCVec[i]["data"].asString();
}
setSegmentTable(curSegTable);
setPayload((char*)pageBuffer.c_str(), pageBuffer.size());
setPayload((char *)pageBuffer.c_str(), pageBuffer.size());
setCRCChecksum(calcChecksum());
}
void headerPages::readDTSCHeader(DTSC::Meta & meta){
void headerPages::readDTSCHeader(DTSC::Meta & meta) {
//pages.clear();
parsedPages = "";
Page curOggPage;
srand (Util::getMS());//randomising with milliseconds from boot
srand(Util::getMS()); //randomising with milliseconds from boot
std::vector<unsigned int> curSegTable;
DTSCID2OGGSerial.clear();
DTSCID2seqNum.clear();
//Creating ID headers for theora and vorbis
for ( std::map<int,DTSC::Track>::iterator it = meta.tracks.begin(); it != meta.tracks.end(); it ++) {
for (std::map<int, DTSC::Track>::iterator it = meta.tracks.begin(); it != meta.tracks.end(); it ++) {
curOggPage.clear();
curOggPage.setVersion();
curOggPage.setHeaderType(2);//headertype 2 = Begin of Stream
curOggPage.setGranulePosition(0);
DTSCID2OGGSerial[it->second.trackID] = rand() % 0xFFFFFFFE +1; //initialising on a random not 0 number
DTSCID2OGGSerial[it->second.trackID] = rand() % 0xFFFFFFFE + 1; //initialising on a random not 0 number
curOggPage.setBitstreamSerialNumber(DTSCID2OGGSerial[it->second.trackID]);
DTSCID2seqNum[it->second.trackID] = 0;
curOggPage.setPageSequenceNumber(DTSCID2seqNum[it->second.trackID]++);
curSegTable.clear();
curSegTable.push_back(it->second.idHeader.size());
curOggPage.setSegmentTable(curSegTable);
curOggPage.setPayload((char*)it->second.idHeader.c_str(), it->second.idHeader.size());
curOggPage.setPayload((char *)it->second.idHeader.c_str(), it->second.idHeader.size());
curOggPage.setCRCChecksum(curOggPage.calcChecksum());
//std::cout << std::string(curOggPage.getPage(), curOggPage.getPageSize());
//pages.push_back(curOggPage);
@ -533,7 +532,7 @@ namespace OGG{
//Creating remaining headers for theora and vorbis
//for tracks in header
//create standard page with comment (empty) en setup header(init)
for ( std::map<int,DTSC::Track>::iterator it = meta.tracks.begin(); it != meta.tracks.end(); it ++) {
for (std::map<int, DTSC::Track>::iterator it = meta.tracks.begin(); it != meta.tracks.end(); it ++) {
curOggPage.clear();
curOggPage.setVersion();
curOggPage.setHeaderType(0);//headertype 0 = normal
@ -545,7 +544,7 @@ namespace OGG{
curSegTable.push_back(it->second.init.size());
curOggPage.setSegmentTable(curSegTable);
std::string fullHeader = it->second.commentHeader + it->second.init;
curOggPage.setPayload((char*)fullHeader.c_str(),fullHeader.size());
curOggPage.setPayload((char *)fullHeader.c_str(), fullHeader.size());
curOggPage.setCRCChecksum(curOggPage.calcChecksum());
//std::cout << std::string(curOggPage.getPage(), curOggPage.getPageSize());
//pages.push_back(curOggPage);

View file

@ -8,15 +8,15 @@
#include "vorbis.h"
#include "json.h"
namespace OGG{
namespace OGG {
enum HeaderType{
enum HeaderType {
Continued = 1,
BeginOfStream = 2,
EndOfStream = 4
};
class Page{
class Page {
public:
Page();
~Page();
@ -38,30 +38,30 @@ namespace OGG{
void setCRCChecksum(long unsigned int newVal);
char getPageSegments();
inline void setPageSegments(char newVal);
char* getSegmentTable();
char * getSegmentTable();
std::deque<unsigned int> & getSegmentTableDeque();
bool setSegmentTable(std::vector<unsigned int> layout);
void setSegmentTable(char* newVal, unsigned int length);
char* getPage();//returns complete page with header
void setSegmentTable(char * newVal, unsigned int length);
char * getPage(); //returns complete page with header
unsigned long int getPageSize();
char* getFullPayload();//returns all segments in the page
char * getFullPayload(); //returns all segments in the page
int getPayloadSize();
std::string toPrettyString(size_t indent = 0);
void setInternalCodec(std::string myCodec);
long unsigned int calcChecksum();
bool clear();
bool setPayload(char* newData, unsigned int length);
bool setPayload(char * newData, unsigned int length);
void readDTSCVector(std::vector <JSON::Value> DTSCVec, unsigned int serial, unsigned int sequence);
private:
std::deque<unsigned int> segmentTableDeque;
char* data;//pointer to the beginning of the Page data
char * data; //pointer to the beginning of the Page data
unsigned int datasize;//size of the allocated memory
unsigned int dataSum;//size of the total segments
bool checkDataSize(unsigned int size);
std::string codec;//codec in the page
};
class headerPages{
class headerPages {
public:
void readDTSCHeader(DTSC::Meta & meta);
std::map <long long unsigned int, unsigned int> DTSCID2OGGSerial;

View file

@ -25,13 +25,17 @@ std::map<pid_t, std::string> Util::Procs::plist;
std::map<pid_t, Util::TerminationNotifier> Util::Procs::exitHandlers;
bool Util::Procs::handler_set = false;
static bool childRunning(pid_t p){
static bool childRunning(pid_t p) {
pid_t ret = waitpid(p, 0, WNOHANG);
if (ret == p){return false;}
if (ret < 0 && errno == EINTR){
if (ret == p) {
return false;
}
if (ret < 0 && errno == EINTR) {
return childRunning(p);
}
if (kill(p, 0) == 0){return true;}
if (kill(p, 0) == 0) {
return true;
}
return false;
}
@ -39,121 +43,129 @@ static bool childRunning(pid_t p){
/// Waits up to 1 second, then sends SIGINT signal to all managed processes.
/// After that waits up to 5 seconds for children to exit, then sends SIGKILL to
/// all remaining children. Waits one more second for cleanup to finish, then exits.
void Util::Procs::exit_handler(){
void Util::Procs::exit_handler() {
int waiting = 0;
std::map<pid_t, std::string> listcopy = plist;
std::map<pid_t, std::string>::iterator it;
if (listcopy.empty()){return;}
if (listcopy.empty()) {
return;
}
//wait up to 0.5 second for applications to shut down
while ( !listcopy.empty() && waiting <= 25){
for (it = listcopy.begin(); it != listcopy.end(); it++){
if ( !childRunning((*it).first)){
while (!listcopy.empty() && waiting <= 25) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning((*it).first)) {
listcopy.erase(it);
break;
}
if ( !listcopy.empty()){
if (!listcopy.empty()) {
Util::sleep(20);
++waiting;
}
}
}
if (listcopy.empty()){return;}
if (listcopy.empty()) {
return;
}
DEBUG_MSG(DLVL_DEVEL, "Sending SIGINT to remaining %d children", (int)listcopy.size());
//send sigint to all remaining
if ( !listcopy.empty()){
for (it = listcopy.begin(); it != listcopy.end(); it++){
DEBUG_MSG(DLVL_DEVEL, "SIGINT %d: %s", ( *it).first, ( *it).second.c_str());
kill(( *it).first, SIGINT);
if (!listcopy.empty()) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
DEBUG_MSG(DLVL_DEVEL, "SIGINT %d: %s", (*it).first, (*it).second.c_str());
kill((*it).first, SIGINT);
}
}
DEBUG_MSG(DLVL_DEVEL, "Waiting up to 5 seconds for %d children to terminate.", (int)listcopy.size());
waiting = 0;
//wait up to 5 seconds for applications to shut down
while ( !listcopy.empty() && waiting <= 250){
for (it = listcopy.begin(); it != listcopy.end(); it++){
if ( !childRunning((*it).first)){
while (!listcopy.empty() && waiting <= 250) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning((*it).first)) {
listcopy.erase(it);
break;
}
if ( !listcopy.empty()){
if (!listcopy.empty()) {
Util::sleep(20);
++waiting;
}
}
}
if (listcopy.empty()){return;}
if (listcopy.empty()) {
return;
}
DEBUG_MSG(DLVL_DEVEL, "Sending SIGKILL to remaining %d children", (int)listcopy.size());
//send sigkill to all remaining
if ( !listcopy.empty()){
for (it = listcopy.begin(); it != listcopy.end(); it++){
DEBUG_MSG(DLVL_DEVEL, "SIGKILL %d: %s", ( *it).first, ( *it).second.c_str());
kill(( *it).first, SIGKILL);
if (!listcopy.empty()) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
DEBUG_MSG(DLVL_DEVEL, "SIGKILL %d: %s", (*it).first, (*it).second.c_str());
kill((*it).first, SIGKILL);
}
}
DEBUG_MSG(DLVL_DEVEL, "Waiting up to a second for %d children to terminate.", (int)listcopy.size());
waiting = 0;
//wait up to 1 second for applications to shut down
while ( !listcopy.empty() && waiting <= 50){
for (it = listcopy.begin(); it != listcopy.end(); it++){
if ( !childRunning((*it).first)){
while (!listcopy.empty() && waiting <= 50) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning((*it).first)) {
listcopy.erase(it);
break;
}
if ( !listcopy.empty()){
if (!listcopy.empty()) {
Util::sleep(20);
++waiting;
}
}
}
if (listcopy.empty()){return;}
if (listcopy.empty()) {
return;
}
DEBUG_MSG(DLVL_DEVEL, "Giving up with %d children left.", (int)listcopy.size());
}
/// Sets up exit and childsig handlers.
/// Called by every Start* function.
void Util::Procs::setHandler(){
if ( !handler_set){
void Util::Procs::setHandler() {
if (!handler_set) {
struct sigaction new_action;
new_action.sa_handler = childsig_handler;
sigemptyset( &new_action.sa_mask);
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGCHLD, &new_action, NULL);
atexit(exit_handler);
handler_set = true;
}// else {
// DEBUG_MSG(DLVL_DEVEL, "not setting handler");
// }
// }
}
/// Used internally to capture child signals and update plist.
void Util::Procs::childsig_handler(int signum){
if (signum != SIGCHLD){
void Util::Procs::childsig_handler(int signum) {
if (signum != SIGCHLD) {
DEBUG_MSG(DLVL_DEVEL, "signum != SIGCHLD");
return;
}
int status;
pid_t ret = -1;
while (ret != 0){
ret = waitpid( -1, &status, WNOHANG);
if (ret <= 0){ //ignore, would block otherwise
if (ret == 0 || errno != EINTR){
while (ret != 0) {
ret = waitpid(-1, &status, WNOHANG);
if (ret <= 0) { //ignore, would block otherwise
if (ret == 0 || errno != EINTR) {
return;
}
continue;
}
int exitcode;
if (WIFEXITED(status)){
if (WIFEXITED(status)) {
exitcode = WEXITSTATUS(status);
}else if (WIFSIGNALED(status)){
} else if (WIFSIGNALED(status)) {
exitcode = -WTERMSIG(status);
}else{// not possible
} else { // not possible
return;
}
@ -162,14 +174,14 @@ void Util::Procs::childsig_handler(int signum){
#endif
plist.erase(ret);
#if DEBUG >= DLVL_HIGH
if (!isActive(pname)){
if (!isActive(pname)) {
DEBUG_MSG(DLVL_HIGH, "Process %s fully terminated", pname.c_str());
}else{
} else {
DEBUG_MSG(DLVL_HIGH, "Child process %d exited", ret);
}
#endif
if (exitHandlers.count(ret) > 0){
if (exitHandlers.count(ret) > 0) {
TerminationNotifier tn = exitHandlers[ret];
exitHandlers.erase(ret);
tn(ret, exitcode);
@ -179,15 +191,17 @@ void Util::Procs::childsig_handler(int signum){
/// Runs the given command and returns the stdout output as a string.
std::string Util::Procs::getOutputOf(char* const* argv){
std::string Util::Procs::getOutputOf(char * const * argv) {
std::string ret;
int fin = 0, fout = -1, ferr = 0;
StartPiped("output_getter", argv, &fin, &fout, &ferr);
while (isActive("output_getter")){Util::sleep(100);}
while (isActive("output_getter")) {
Util::sleep(100);
}
FILE * outFile = fdopen(fout, "r");
char * fileBuf = 0;
size_t fileBufLen = 0;
while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)) {
ret += fileBuf;
}
fclose(outFile);
@ -196,15 +210,17 @@ std::string Util::Procs::getOutputOf(char* const* argv){
}
/// Runs the given command and returns the stdout output as a string.
std::string Util::Procs::getOutputOf(std::string cmd){
std::string Util::Procs::getOutputOf(std::string cmd) {
std::string ret;
int fin = 0, fout = -1, ferr = 0;
StartPiped("output_getter", cmd, &fin, &fout, &ferr);
while (isActive("output_getter")){Util::sleep(100);}
while (isActive("output_getter")) {
Util::sleep(100);
}
FILE * outFile = fdopen(fout, "r");
char * fileBuf = 0;
size_t fileBufLen = 0;
while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)) {
ret += fileBuf;
}
free(fileBuf);
@ -217,21 +233,21 @@ std::string Util::Procs::getOutputOf(std::string cmd){
/// Replaces the current process - use after forking first!
/// This function will never return - it will either run the given
/// command or kill itself with return code 42.
void Util::Procs::runCmd(std::string & cmd){
void Util::Procs::runCmd(std::string & cmd) {
//split cmd into arguments
//supports a maximum of 20 arguments
char * tmp = (char*)cmd.c_str();
char * tmp = (char *)cmd.c_str();
char * tmp2 = 0;
char * args[21];
int i = 0;
tmp2 = strtok(tmp, " ");
args[0] = tmp2;
while (tmp2 != 0 && (i < 20)){
while (tmp2 != 0 && (i < 20)) {
tmp2 = strtok(0, " ");
++i;
args[i] = tmp2;
}
if (i == 20){
if (i == 20) {
args[20] = 0;
}
//execute the command
@ -244,19 +260,19 @@ void Util::Procs::runCmd(std::string & cmd){
/// \return 0 if process was not started, process PID otherwise.
/// \arg name Name for this process - only used internally.
/// \arg cmd Commandline for this process.
pid_t Util::Procs::Start(std::string name, std::string cmd){
if (isActive(name)){
pid_t Util::Procs::Start(std::string name, std::string cmd) {
if (isActive(name)) {
return getPid(name);
}
setHandler();
pid_t ret = fork();
if (ret == 0){
if (ret == 0) {
runCmd(cmd);
}else{
if (ret > 0){
} else {
if (ret > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PID %d: %s", name.c_str(), ret, cmd.c_str());
plist.insert(std::pair<pid_t, std::string>(ret, name));
}else{
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started: fork() failed", name.c_str());
return 0;
}
@ -269,30 +285,30 @@ pid_t Util::Procs::Start(std::string name, std::string cmd){
/// \arg name Name for this process - only used internally.
/// \arg cmd Commandline for sub (sending) process.
/// \arg cmd2 Commandline for main (receiving) process.
pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
if (isActive(name)){
pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2) {
if (isActive(name)) {
return getPid(name);
}
setHandler();
int pfildes[2];
if (pipe(pfildes) == -1){
if (pipe(pfildes) == -1) {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0;
}
int devnull = open("/dev/null", O_RDWR);
pid_t ret = fork();
if (ret == 0){
if (ret == 0) {
close(pfildes[0]);
dup2(pfildes[1], STDOUT_FILENO);
close(pfildes[1]);
dup2(devnull, STDIN_FILENO);
dup2(devnull, STDERR_FILENO);
runCmd(cmd);
}else{
if (ret > 0){
} else {
if (ret > 0) {
plist.insert(std::pair<pid_t, std::string>(ret, name));
}else{
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
close(pfildes[1]);
close(pfildes[0]);
@ -301,18 +317,18 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
}
pid_t ret2 = fork();
if (ret2 == 0){
if (ret2 == 0) {
close(pfildes[1]);
dup2(pfildes[0], STDIN_FILENO);
close(pfildes[0]);
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
runCmd(cmd2);
}else{
if (ret2 > 0){
} else {
if (ret2 > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
plist.insert(std::pair<pid_t, std::string>(ret2, name));
}else{
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name);
close(pfildes[1]);
@ -331,25 +347,25 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
/// \arg cmd Commandline for sub (sending) process.
/// \arg cmd2 Commandline for sub (middle) process.
/// \arg cmd3 Commandline for main (receiving) process.
pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3){
if (isActive(name)){
pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3) {
if (isActive(name)) {
return getPid(name);
}
setHandler();
int pfildes[2];
int pfildes2[2];
if (pipe(pfildes) == -1){
if (pipe(pfildes) == -1) {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0;
}
if (pipe(pfildes2) == -1){
if (pipe(pfildes2) == -1) {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0;
}
int devnull = open("/dev/null", O_RDWR);
pid_t ret = fork();
if (ret == 0){
if (ret == 0) {
close(pfildes[0]);
dup2(pfildes[1], STDOUT_FILENO);
close(pfildes[1]);
@ -358,10 +374,10 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
close(pfildes2[1]);
close(pfildes2[0]);
runCmd(cmd);
}else{
if (ret > 0){
} else {
if (ret > 0) {
plist.insert(std::pair<pid_t, std::string>(ret, name));
}else{
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
close(pfildes[1]);
close(pfildes[0]);
@ -372,7 +388,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
}
pid_t ret2 = fork();
if (ret2 == 0){
if (ret2 == 0) {
close(pfildes[1]);
close(pfildes2[0]);
dup2(pfildes[0], STDIN_FILENO);
@ -381,11 +397,11 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
close(pfildes2[1]);
dup2(devnull, STDERR_FILENO);
runCmd(cmd2);
}else{
if (ret2 > 0){
} else {
if (ret2 > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
plist.insert(std::pair<pid_t, std::string>(ret2, name));
}else{
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name);
close(pfildes[1]);
@ -399,7 +415,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
close(pfildes[0]);
pid_t ret3 = fork();
if (ret3 == 0){
if (ret3 == 0) {
close(pfildes[1]);
close(pfildes[0]);
close(pfildes2[1]);
@ -408,11 +424,11 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
runCmd(cmd3);
}else{
if (ret3 > 0){
} else {
if (ret3 > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d, %d): %s | %s | %s", name.c_str(), ret, ret2, ret3, cmd.c_str(), cmd2.c_str(), cmd3.c_str());
plist.insert(std::pair<pid_t, std::string>(ret3, name));
}else{
} else {
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name);
close(pfildes[1]);
@ -433,61 +449,61 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
/// \arg fdin Standard input file descriptor. If null, /dev/null is assumed. Otherwise, if arg contains -1, a new fd is automatically allocated and written into this arg. Then the arg will be used as fd.
/// \arg fdout Same as fdin, but for stdout.
/// \arg fdout Same as fdin, but for stderr.
pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, int * fdout, int * fderr){
if (isActive(name)){
pid_t Util::Procs::StartPiped(std::string name, char * const * argv, int * fdin, int * fdout, int * fderr) {
if (isActive(name)) {
DEBUG_MSG(DLVL_WARN, "Process %s already active - skipping start", name.c_str());
return getPid(name);
}
int pidtemp = StartPiped(argv, fdin, fdout, fderr);
if (pidtemp > 0 ) {
if (pidtemp > 0) {
plist.insert(std::pair<pid_t, std::string>(pidtemp, name));
}
return pidtemp;
}
pid_t Util::Procs::StartPiped(char* const* argv, int * fdin, int * fdout, int * fderr){
pid_t Util::Procs::StartPiped(char * const * argv, int * fdin, int * fdout, int * fderr) {
pid_t pid;
int pipein[2], pipeout[2], pipeerr[2];
//DEBUG_MSG(DLVL_DEVEL, "setHandler");
setHandler();
if (fdin && *fdin == -1 && pipe(pipein) < 0){
if (fdin && *fdin == -1 && pipe(pipein) < 0) {
DEBUG_MSG(DLVL_ERROR, "Pipe in creation failed for process %s", argv[0]);
return 0;
}
if (fdout && *fdout == -1 && pipe(pipeout) < 0){
if (fdout && *fdout == -1 && pipe(pipeout) < 0) {
DEBUG_MSG(DLVL_ERROR, "Pipe out creation failed for process %s", argv[0]);
if ( *fdin == -1){
if (*fdin == -1) {
close(pipein[0]);
close(pipein[1]);
}
return 0;
}
if (fderr && *fderr == -1 && pipe(pipeerr) < 0){
if (fderr && *fderr == -1 && pipe(pipeerr) < 0) {
DEBUG_MSG(DLVL_ERROR, "Pipe err creation failed for process %s", argv[0]);
if ( *fdin == -1){
if (*fdin == -1) {
close(pipein[0]);
close(pipein[1]);
}
if ( *fdout == -1){
if (*fdout == -1) {
close(pipeout[0]);
close(pipeout[1]);
}
return 0;
}
int devnull = -1;
if ( !fdin || !fdout || !fderr){
if (!fdin || !fdout || !fderr) {
devnull = open("/dev/null", O_RDWR);
if (devnull == -1){
if (devnull == -1) {
DEBUG_MSG(DLVL_ERROR, "Could not open /dev/null for process %s: %s", argv[0], strerror(errno));
if ( *fdin == -1){
if (*fdin == -1) {
close(pipein[0]);
close(pipein[1]);
}
if ( *fdout == -1){
if (*fdout == -1) {
close(pipeout[0]);
close(pipeout[1]);
}
if ( *fderr == -1){
if (*fderr == -1) {
close(pipeerr[0]);
close(pipeerr[1]);
}
@ -495,81 +511,81 @@ pid_t Util::Procs::StartPiped(char* const* argv, int * fdin, int * fdout, int *
}
}
pid = fork();
if (pid == 0){ //child
if ( !fdin){
if (pid == 0) { //child
if (!fdin) {
dup2(devnull, STDIN_FILENO);
}else if ( *fdin == -1){
} else if (*fdin == -1) {
close(pipein[1]); // close unused write end
dup2(pipein[0], STDIN_FILENO);
close(pipein[0]);
}else if ( *fdin != STDIN_FILENO){
dup2( *fdin, STDIN_FILENO);
} else if (*fdin != STDIN_FILENO) {
dup2(*fdin, STDIN_FILENO);
}
if ( !fdout){
if (!fdout) {
dup2(devnull, STDOUT_FILENO);
}else if ( *fdout == -1){
} else if (*fdout == -1) {
close(pipeout[0]); // close unused read end
dup2(pipeout[1], STDOUT_FILENO);
close(pipeout[1]);
}else if ( *fdout != STDOUT_FILENO){
dup2( *fdout, STDOUT_FILENO);
} else if (*fdout != STDOUT_FILENO) {
dup2(*fdout, STDOUT_FILENO);
}
if ( !fderr){
if (!fderr) {
dup2(devnull, STDERR_FILENO);
}else if ( *fderr == -1){
} else if (*fderr == -1) {
close(pipeerr[0]); // close unused read end
dup2(pipeerr[1], STDERR_FILENO);
close(pipeerr[1]);
}else if ( *fderr != STDERR_FILENO){
dup2( *fderr, STDERR_FILENO);
} else if (*fderr != STDERR_FILENO) {
dup2(*fderr, STDERR_FILENO);
}
if( fdin && *fdin !=-1 && *fdin != STDIN_FILENO){
close( *fdin);
if (fdin && *fdin != -1 && *fdin != STDIN_FILENO) {
close(*fdin);
}
if( fdout && *fdout !=-1 && *fdout != STDOUT_FILENO){
close( *fdout);
if (fdout && *fdout != -1 && *fdout != STDOUT_FILENO) {
close(*fdout);
}
if( fderr && *fderr !=-1 && *fderr != STDERR_FILENO){
close( *fderr);
if (fderr && *fderr != -1 && *fderr != STDERR_FILENO) {
close(*fderr);
}
if (devnull != -1){
if (devnull != -1) {
close(devnull);
}
execvp(argv[0], argv);
DEBUG_MSG(DLVL_ERROR, "execvp() failed for process %s", argv[0]);
exit(42);
}else if (pid == -1){
} else if (pid == -1) {
DEBUG_MSG(DLVL_ERROR, "fork() for pipe failed for process %s", argv[0]);
if (fdin && *fdin == -1){
if (fdin && *fdin == -1) {
close(pipein[0]);
close(pipein[1]);
}
if (fdout && *fdout == -1){
if (fdout && *fdout == -1) {
close(pipeout[0]);
close(pipeout[1]);
}
if (fderr && *fderr == -1){
if (fderr && *fderr == -1) {
close(pipeerr[0]);
close(pipeerr[1]);
}
if (devnull != -1){
if (devnull != -1) {
close(devnull);
}
return 0;
}else{ //parent
} else { //parent
DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d", argv[0], pid);
if (devnull != -1){
if (devnull != -1) {
close(devnull);
}
if (fdin && *fdin == -1){
if (fdin && *fdin == -1) {
close(pipein[0]); // close unused end end
*fdin = pipein[1];
}
if (fdout && *fdout == -1){
if (fdout && *fdout == -1) {
close(pipeout[1]); // close unused write end
*fdout = pipeout[0];
}
if (fderr && *fderr == -1){
if (fderr && *fderr == -1) {
close(pipeerr[1]); // close unused write end
*fderr = pipeerr[0];
}
@ -584,40 +600,40 @@ pid_t Util::Procs::StartPiped(char* const* argv, int * fdin, int * fdout, int *
/// \arg fdin Standard input file descriptor. If null, /dev/null is assumed. Otherwise, if arg contains -1, a new fd is automatically allocated and written into this arg. Then the arg will be used as fd.
/// \arg fdout Same as fdin, but for stdout.
/// \arg fdout Same as fdin, but for stderr.
pid_t Util::Procs::StartPiped(std::string name, std::string cmd, int * fdin, int * fdout, int * fderr){
pid_t Util::Procs::StartPiped(std::string name, std::string cmd, int * fdin, int * fdout, int * fderr) {
//Convert the given command to a char * []
char * tmp = (char*)cmd.c_str();
char * tmp = (char *)cmd.c_str();
char * tmp2 = 0;
char * args[21];
int i = 0;
tmp2 = strtok(tmp, " ");
args[0] = tmp2;
while (tmp2 != 0 && (i < 20)){
while (tmp2 != 0 && (i < 20)) {
tmp2 = strtok(0, " ");
++i;
args[i] = tmp2;
}
if (i == 20){
if (i == 20) {
args[20] = 0;
}
return StartPiped(name,args,fdin,fdout,fderr);
return StartPiped(name, args, fdin, fdout, fderr);
}
pid_t Util::Procs::StartPiped2(std::string name, std::string cmd1, std::string cmd2, int * fdin, int * fdout, int * fderr1, int * fderr2){
pid_t Util::Procs::StartPiped2(std::string name, std::string cmd1, std::string cmd2, int * fdin, int * fdout, int * fderr1, int * fderr2) {
int pfildes[2];
if (pipe(pfildes) == -1){
if (pipe(pfildes) == -1) {
DEBUG_MSG(DLVL_ERROR, "Pipe creation failed for process %s", name.c_str());
return 0;
}
pid_t res1 = StartPiped(name, cmd1, fdin, &pfildes[1], fderr1);
if ( !res1){
if (!res1) {
close(pfildes[1]);
close(pfildes[0]);
return 0;
}
pid_t res2 = StartPiped(name+"receiving", cmd2, &pfildes[0], fdout, fderr2);
if ( !res2){
pid_t res2 = StartPiped(name + "receiving", cmd2, &pfildes[0], fdout, fderr2);
if (!res2) {
Stop(res1);
close(pfildes[1]);
close(pfildes[0]);
@ -630,12 +646,12 @@ pid_t Util::Procs::StartPiped2(std::string name, std::string cmd1, std::string c
}
/// Stops the named process, if running.
/// \arg name (Internal) name of process to stop
void Util::Procs::Stop(std::string name){
void Util::Procs::Stop(std::string name) {
int max = 5;
while (isActive(name)){
while (isActive(name)) {
Stop(getPid(name));
max--;
if (max <= 0){
if (max <= 0) {
return;
}
}
@ -643,36 +659,36 @@ void Util::Procs::Stop(std::string name){
/// Stops the process with this pid, if running.
/// \arg name The PID of the process to stop.
void Util::Procs::Stop(pid_t name){
if (isActive(name)){
void Util::Procs::Stop(pid_t name) {
if (isActive(name)) {
kill(name, SIGTERM);
}
}
/// (Attempts to) stop all running child processes.
void Util::Procs::StopAll(){
void Util::Procs::StopAll() {
std::map<pid_t, std::string> listcopy = plist;
std::map<pid_t, std::string>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++){
Stop(( *it).first);
for (it = listcopy.begin(); it != listcopy.end(); it++) {
Stop((*it).first);
}
}
/// Returns the number of active child processes.
int Util::Procs::Count(){
int Util::Procs::Count() {
return plist.size();
}
/// Returns true if a process by this name is currently active.
bool Util::Procs::isActive(std::string name){
bool Util::Procs::isActive(std::string name) {
std::map<pid_t, std::string> listcopy = plist;
std::map<pid_t, std::string>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++){
if (( *it).second == name){
if (childRunning(( *it).first)){
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if ((*it).second == name) {
if (childRunning((*it).first)) {
return true;
}else{
plist.erase(( *it).first);
} else {
plist.erase((*it).first);
}
}
}
@ -680,17 +696,17 @@ bool Util::Procs::isActive(std::string name){
}
/// Returns true if a process with this PID is currently active.
bool Util::Procs::isActive(pid_t name){
bool Util::Procs::isActive(pid_t name) {
return (plist.count(name) == 1) && (kill(name, 0) == 0);
}
/// Gets PID for this named process, if active.
/// \return NULL if not active, process PID otherwise.
pid_t Util::Procs::getPid(std::string name){
pid_t Util::Procs::getPid(std::string name) {
std::map<pid_t, std::string>::iterator it;
for (it = plist.begin(); it != plist.end(); it++){
if (( *it).second == name){
return ( *it).first;
for (it = plist.begin(); it != plist.end(); it++) {
if ((*it).second == name) {
return (*it).first;
}
}
return 0;
@ -698,8 +714,8 @@ pid_t Util::Procs::getPid(std::string name){
/// Gets name for this process PID, if active.
/// \return Empty string if not active, name otherwise.
std::string Util::Procs::getName(pid_t name){
if (plist.count(name) == 1){
std::string Util::Procs::getName(pid_t name) {
if (plist.count(name) == 1) {
return plist[name];
}
return "";
@ -707,8 +723,8 @@ std::string Util::Procs::getName(pid_t name){
/// Registers one notifier function for when a process indentified by PID terminates.
/// \return true if the notifier could be registered, false otherwise.
bool Util::Procs::SetTerminationNotifier(pid_t pid, TerminationNotifier notifier){
if (plist.find(pid) != plist.end()){
bool Util::Procs::SetTerminationNotifier(pid_t pid, TerminationNotifier notifier) {
if (plist.find(pid) != plist.end()) {
exitHandlers[pid] = notifier;
return true;
}

View file

@ -13,7 +13,7 @@ namespace Util {
typedef void (*TerminationNotifier)(pid_t pid, int exitCode);
/// Deals with spawning, monitoring and stopping child processes
class Procs{
class Procs {
private:
static std::map<pid_t, std::string> plist; ///< Holds active processes
static std::map<pid_t, TerminationNotifier> exitHandlers; ///< termination function, if any
@ -23,14 +23,14 @@ namespace Util {
static void runCmd(std::string & cmd);
static void setHandler();
public:
static std::string getOutputOf(char* const* argv);
static std::string getOutputOf(char * const * argv);
static std::string getOutputOf(std::string cmd);
static pid_t Start(std::string name, std::string cmd);
static pid_t Start(std::string name, std::string cmd, std::string cmd2);
static pid_t Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3);
static pid_t StartPiped(char* const* argv, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped(std::string name, char* const* argv, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped(char * const * argv, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped(std::string name, char * const * argv, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped(std::string name, std::string cmd, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped2(std::string name, std::string cmd1, std::string cmd2, int * fdin, int * fdout, int * fderr1, int * fderr2);

View file

@ -39,59 +39,61 @@ std::map<unsigned int, RTMPStream::Chunk> RTMPStream::lastrecv;
#include <openssl/hmac.h>
#define P1024 \
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
uint8_t genuineFMSKey[] = {0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x20,
0x4d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x53, 0x65, 0x72,
0x76, // Genuine Adobe Flash Media Server 001
0x65, 0x72, 0x20, 0x30, 0x30, 0x31, 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8, 0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57, 0x6e, 0xec,
0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae}; // 68
0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae
}; // 68
uint8_t genuineFPKey[] = {0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x20,
0x50, 0x6c, 0x61,
0x79, // Genuine Adobe Flash Player 001
0x65, 0x72, 0x20, 0x30, 0x30, 0x31, 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8, 0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57, 0x6e, 0xec,
0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae}; // 62
0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae
}; // 62
inline uint32_t GetDigestOffset(uint8_t *pBuffer, uint8_t scheme){
if (scheme == 0){
inline uint32_t GetDigestOffset(uint8_t * pBuffer, uint8_t scheme) {
if (scheme == 0) {
return ((pBuffer[8] + pBuffer[9] + pBuffer[10] + pBuffer[11]) % 728) + 12;
}else{
} else {
return ((pBuffer[772] + pBuffer[773] + pBuffer[774] + pBuffer[775]) % 728) + 776;
}
}
inline uint32_t GetDHOffset(uint8_t *pBuffer, uint8_t scheme){
if (scheme == 0){
inline uint32_t GetDHOffset(uint8_t * pBuffer, uint8_t scheme) {
if (scheme == 0) {
return ((pBuffer[1532] + pBuffer[1533] + pBuffer[1534] + pBuffer[1535]) % 632) + 772;
}else{
} else {
return ((pBuffer[768] + pBuffer[769] + pBuffer[770] + pBuffer[771]) % 632) + 8;
}
}
class DHWrapper{
class DHWrapper {
private:
int32_t _bitsCount;
DH *_pDH;
uint8_t *_pSharedKey;
DH * _pDH;
uint8_t * _pSharedKey;
int32_t _sharedKeyLength;
BIGNUM *_peerPublickey;
BIGNUM * _peerPublickey;
public:
DHWrapper(int32_t bitsCount);
virtual ~DHWrapper();
bool Initialize();
bool CopyPublicKey(uint8_t *pDst, int32_t dstLength);
bool CopyPrivateKey(uint8_t *pDst, int32_t dstLength);
bool CreateSharedKey(uint8_t *pPeerPublicKey, int32_t length);
bool CopySharedKey(uint8_t *pDst, int32_t dstLength);
bool CopyPublicKey(uint8_t * pDst, int32_t dstLength);
bool CopyPrivateKey(uint8_t * pDst, int32_t dstLength);
bool CreateSharedKey(uint8_t * pPeerPublicKey, int32_t length);
bool CopySharedKey(uint8_t * pDst, int32_t dstLength);
private:
void Cleanup();
bool CopyKey(BIGNUM *pNum, uint8_t *pDst, int32_t dstLength);
bool CopyKey(BIGNUM * pNum, uint8_t * pDst, int32_t dstLength);
};
DHWrapper::DHWrapper(int32_t bitsCount){
DHWrapper::DHWrapper(int32_t bitsCount) {
_bitsCount = bitsCount;
_pDH = 0;
_pSharedKey = 0;
@ -99,73 +101,73 @@ DHWrapper::DHWrapper(int32_t bitsCount){
_peerPublickey = 0;
}
DHWrapper::~DHWrapper(){
DHWrapper::~DHWrapper() {
Cleanup();
}
bool DHWrapper::Initialize(){
bool DHWrapper::Initialize() {
Cleanup();
_pDH = DH_new();
if ( !_pDH){
if (!_pDH) {
Cleanup();
return false;
}
_pDH->p = BN_new();
if ( !_pDH->p){
if (!_pDH->p) {
Cleanup();
return false;
}
_pDH->g = BN_new();
if ( !_pDH->g){
if (!_pDH->g) {
Cleanup();
return false;
}
if (BN_hex2bn( &_pDH->p, P1024) == 0){
if (BN_hex2bn(&_pDH->p, P1024) == 0) {
Cleanup();
return false;
}
if (BN_set_word(_pDH->g, 2) != 1){
if (BN_set_word(_pDH->g, 2) != 1) {
Cleanup();
return false;
}
_pDH->length = _bitsCount;
if (DH_generate_key(_pDH) != 1){
if (DH_generate_key(_pDH) != 1) {
Cleanup();
return false;
}
return true;
}
bool DHWrapper::CopyPublicKey(uint8_t *pDst, int32_t dstLength){
if ( !_pDH){
bool DHWrapper::CopyPublicKey(uint8_t * pDst, int32_t dstLength) {
if (!_pDH) {
return false;
}
return CopyKey(_pDH->pub_key, pDst, dstLength);
}
bool DHWrapper::CopyPrivateKey(uint8_t *pDst, int32_t dstLength){
if ( !_pDH){
bool DHWrapper::CopyPrivateKey(uint8_t * pDst, int32_t dstLength) {
if (!_pDH) {
return false;
}
return CopyKey(_pDH->priv_key, pDst, dstLength);
}
bool DHWrapper::CreateSharedKey(uint8_t *pPeerPublicKey, int32_t length){
if ( !_pDH){
bool DHWrapper::CreateSharedKey(uint8_t * pPeerPublicKey, int32_t length) {
if (!_pDH) {
return false;
}
if (_sharedKeyLength != 0 || _pSharedKey){
if (_sharedKeyLength != 0 || _pSharedKey) {
return false;
}
_sharedKeyLength = DH_size(_pDH);
if (_sharedKeyLength <= 0 || _sharedKeyLength > 1024){
if (_sharedKeyLength <= 0 || _sharedKeyLength > 1024) {
return false;
}
_pSharedKey = new uint8_t[_sharedKeyLength];
_peerPublickey = BN_bin2bn(pPeerPublicKey, length, 0);
if ( !_peerPublickey){
if (!_peerPublickey) {
return false;
}
@ -173,93 +175,93 @@ bool DHWrapper::CreateSharedKey(uint8_t *pPeerPublicKey, int32_t length){
return true;
}
bool DHWrapper::CopySharedKey(uint8_t *pDst, int32_t dstLength){
if ( !_pDH){
bool DHWrapper::CopySharedKey(uint8_t * pDst, int32_t dstLength) {
if (!_pDH) {
return false;
}
if (dstLength != _sharedKeyLength){
if (dstLength != _sharedKeyLength) {
return false;
}
memcpy(pDst, _pSharedKey, _sharedKeyLength);
return true;
}
void DHWrapper::Cleanup(){
if (_pDH){
if (_pDH->p){
void DHWrapper::Cleanup() {
if (_pDH) {
if (_pDH->p) {
BN_free(_pDH->p);
_pDH->p = 0;
}
if (_pDH->g){
if (_pDH->g) {
BN_free(_pDH->g);
_pDH->g = 0;
}
DH_free(_pDH);
_pDH = 0;
}
if (_pSharedKey){
if (_pSharedKey) {
delete[] _pSharedKey;
_pSharedKey = 0;
}
_sharedKeyLength = 0;
if (_peerPublickey){
if (_peerPublickey) {
BN_free(_peerPublickey);
_peerPublickey = 0;
}
}
bool DHWrapper::CopyKey(BIGNUM *pNum, uint8_t *pDst, int32_t dstLength){
bool DHWrapper::CopyKey(BIGNUM * pNum, uint8_t * pDst, int32_t dstLength) {
int32_t keySize = BN_num_bytes(pNum);
if ((keySize <= 0) || (dstLength <= 0) || (keySize > dstLength)){
if ((keySize <= 0) || (dstLength <= 0) || (keySize > dstLength)) {
return false;
}
if (BN_bn2bin(pNum, pDst) != keySize){
if (BN_bn2bin(pNum, pDst) != keySize) {
return false;
}
return true;
}
void InitRC4Encryption(uint8_t *secretKey, uint8_t *pubKeyIn, uint8_t *pubKeyOut, RC4_KEY *rc4keyIn, RC4_KEY *rc4keyOut){
void InitRC4Encryption(uint8_t * secretKey, uint8_t * pubKeyIn, uint8_t * pubKeyOut, RC4_KEY * rc4keyIn, RC4_KEY * rc4keyOut) {
uint8_t digest[SHA256_DIGEST_LENGTH];
unsigned int digestLen = 0;
HMAC_CTX ctx;
HMAC_CTX_init( &ctx);
HMAC_Init_ex( &ctx, secretKey, 128, EVP_sha256(), 0);
HMAC_Update( &ctx, pubKeyIn, 128);
HMAC_Final( &ctx, digest, &digestLen);
HMAC_CTX_cleanup( &ctx);
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, secretKey, 128, EVP_sha256(), 0);
HMAC_Update(&ctx, pubKeyIn, 128);
HMAC_Final(&ctx, digest, &digestLen);
HMAC_CTX_cleanup(&ctx);
RC4_set_key(rc4keyOut, 16, digest);
HMAC_CTX_init( &ctx);
HMAC_Init_ex( &ctx, secretKey, 128, EVP_sha256(), 0);
HMAC_Update( &ctx, pubKeyOut, 128);
HMAC_Final( &ctx, digest, &digestLen);
HMAC_CTX_cleanup( &ctx);
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, secretKey, 128, EVP_sha256(), 0);
HMAC_Update(&ctx, pubKeyOut, 128);
HMAC_Final(&ctx, digest, &digestLen);
HMAC_CTX_cleanup(&ctx);
RC4_set_key(rc4keyIn, 16, digest);
}
void HMACsha256(const void *pData, uint32_t dataLength, const void *pKey, uint32_t keyLength, void *pResult){
void HMACsha256(const void * pData, uint32_t dataLength, const void * pKey, uint32_t keyLength, void * pResult) {
unsigned int digestLen;
HMAC_CTX ctx;
HMAC_CTX_init( &ctx);
HMAC_Init_ex( &ctx, (unsigned char*)pKey, keyLength, EVP_sha256(), 0);
HMAC_Update( &ctx, (unsigned char *)pData, dataLength);
HMAC_Final( &ctx, (unsigned char *)pResult, &digestLen);
HMAC_CTX_cleanup( &ctx);
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, (unsigned char *)pKey, keyLength, EVP_sha256(), 0);
HMAC_Update(&ctx, (unsigned char *)pData, dataLength);
HMAC_Final(&ctx, (unsigned char *)pResult, &digestLen);
HMAC_CTX_cleanup(&ctx);
}
bool ValidateClientScheme(uint8_t * pBuffer, uint8_t scheme){
bool ValidateClientScheme(uint8_t * pBuffer, uint8_t scheme) {
uint32_t clientDigestOffset = GetDigestOffset(pBuffer, scheme);
uint8_t *pTempBuffer = new uint8_t[1536 - 32];
uint8_t * pTempBuffer = new uint8_t[1536 - 32];
memcpy(pTempBuffer, pBuffer, clientDigestOffset);
memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32, 1536 - clientDigestOffset - 32);
uint8_t *pTempHash = new uint8_t[512];
uint8_t * pTempHash = new uint8_t[512];
HMACsha256(pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash);
bool result = (memcmp(pBuffer + clientDigestOffset, pTempHash, 32) == 0);
DEBUG_MSG(DLVL_MEDIUM, "Client scheme validation %hhi %s", scheme, result?"success":"failed");
DEBUG_MSG(DLVL_MEDIUM, "Client scheme validation %hhi %s", scheme, result ? "success" : "failed");
delete[] pTempBuffer;
delete[] pTempHash;
return result;
@ -268,58 +270,58 @@ bool ValidateClientScheme(uint8_t * pBuffer, uint8_t scheme){
/// Packs up the chunk for sending over the network.
/// \warning Do not call if you are not actually sending the resulting data!
/// \returns A std::string ready to be sent.
std::string & RTMPStream::Chunk::Pack(){
std::string & RTMPStream::Chunk::Pack() {
static std::string output;
output.clear();
bool allow_short = lastsend.count(cs_id);
RTMPStream::Chunk prev = lastsend[cs_id];
unsigned int tmpi;
unsigned char chtype = 0x00;
if (allow_short && (prev.cs_id == cs_id)){
if (msg_stream_id == prev.msg_stream_id){
if (allow_short && (prev.cs_id == cs_id)) {
if (msg_stream_id == prev.msg_stream_id) {
chtype = 0x40; //do not send msg_stream_id
if (len == prev.len){
if (msg_type_id == prev.msg_type_id){
if (len == prev.len) {
if (msg_type_id == prev.msg_type_id) {
chtype = 0x80; //do not send len and msg_type_id
if (timestamp == prev.timestamp){
if (timestamp == prev.timestamp) {
chtype = 0xC0; //do not send timestamp
}
}
}
}
//override - we always sent type 0x00 if the timestamp has decreased since last chunk in this channel
if (timestamp < prev.timestamp){
if (timestamp < prev.timestamp) {
chtype = 0x00;
}
}
if (cs_id <= 63){
if (cs_id <= 63) {
output += (unsigned char)(chtype | cs_id);
}else{
if (cs_id <= 255 + 64){
} else {
if (cs_id <= 255 + 64) {
output += (unsigned char)(chtype | 0);
output += (unsigned char)(cs_id - 64);
}else{
} else {
output += (unsigned char)(chtype | 1);
output += (unsigned char)((cs_id - 64) % 256);
output += (unsigned char)((cs_id - 64) / 256);
}
}
unsigned int ntime = 0;
if (chtype != 0xC0){
if (chtype != 0xC0) {
//timestamp or timestamp diff
if (chtype == 0x00){
if (chtype == 0x00) {
tmpi = timestamp;
}else{
} else {
tmpi = timestamp - prev.timestamp;
}
if (tmpi >= 0x00ffffff){
if (tmpi >= 0x00ffffff) {
ntime = tmpi;
tmpi = 0x00ffffff;
}
output += (unsigned char)((tmpi >> 16) & 0xff);
output += (unsigned char)((tmpi >> 8) & 0xff);
output += (unsigned char)(tmpi & 0xff);
if (chtype != 0x80){
if (chtype != 0x80) {
//len
tmpi = len;
output += (unsigned char)((tmpi >> 16) & 0xff);
@ -327,7 +329,7 @@ std::string & RTMPStream::Chunk::Pack(){
output += (unsigned char)(tmpi & 0xff);
//msg type id
output += (unsigned char)msg_type_id;
if (chtype != 0x40){
if (chtype != 0x40) {
//msg stream id
output += (unsigned char)(msg_stream_id % 256);
output += (unsigned char)(msg_stream_id / 256);
@ -337,28 +339,28 @@ std::string & RTMPStream::Chunk::Pack(){
}
}
//support for 0x00ffffff timestamps
if (ntime){
if (ntime) {
output += (unsigned char)(ntime & 0xff);
output += (unsigned char)((ntime >> 8) & 0xff);
output += (unsigned char)((ntime >> 16) & 0xff);
output += (unsigned char)((ntime >> 24) & 0xff);
}
len_left = 0;
while (len_left < len){
while (len_left < len) {
tmpi = len - len_left;
if (tmpi > RTMPStream::chunk_snd_max){
if (tmpi > RTMPStream::chunk_snd_max) {
tmpi = RTMPStream::chunk_snd_max;
}
output.append(data, len_left, tmpi);
len_left += tmpi;
if (len_left < len){
if (cs_id <= 63){
if (len_left < len) {
if (cs_id <= 63) {
output += (unsigned char)(0xC0 + cs_id);
}else{
if (cs_id <= 255 + 64){
} else {
if (cs_id <= 255 + 64) {
output += (unsigned char)(0xC0);
output += (unsigned char)(cs_id - 64);
}else{
} else {
output += (unsigned char)(0xC1);
output += (unsigned char)((cs_id - 64) % 256);
output += (unsigned char)((cs_id - 64) / 256);
@ -372,7 +374,7 @@ std::string & RTMPStream::Chunk::Pack(){
} //SendChunk
/// Default constructor, creates an empty chunk with all values initialized to zero.
RTMPStream::Chunk::Chunk(){
RTMPStream::Chunk::Chunk() {
headertype = 0;
cs_id = 0;
timestamp = 0;
@ -385,7 +387,7 @@ RTMPStream::Chunk::Chunk(){
} //constructor
/// Packs up a chunk with the given arguments as properties.
std::string & RTMPStream::SendChunk(unsigned int cs_id, unsigned char msg_type_id, unsigned int msg_stream_id, std::string data){
std::string & RTMPStream::SendChunk(unsigned int cs_id, unsigned char msg_type_id, unsigned int msg_stream_id, std::string data) {
static RTMPStream::Chunk ch;
ch.cs_id = cs_id;
ch.timestamp = Util::getMS();
@ -403,7 +405,7 @@ std::string & RTMPStream::SendChunk(unsigned int cs_id, unsigned char msg_type_i
/// \param data Contents of the media data.
/// \param len Length of the media data, in bytes.
/// \param ts Timestamp of the media data, relative to current system time.
std::string & RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts){
std::string & RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts) {
static RTMPStream::Chunk ch;
ch.cs_id = msg_type_id + 42;
ch.timestamp = ts;
@ -412,13 +414,13 @@ std::string & RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char * d
ch.len_left = 0;
ch.msg_type_id = msg_type_id;
ch.msg_stream_id = 1;
ch.data = std::string((char*)data, (size_t)len);
ch.data = std::string((char *)data, (size_t)len);
return ch.Pack();
} //SendMedia
/// Packs up a chunk with media contents.
/// \param tag FLV::Tag with media to send.
std::string & RTMPStream::SendMedia(FLV::Tag & tag){
std::string & RTMPStream::SendMedia(FLV::Tag & tag) {
static RTMPStream::Chunk ch;
//Commented bit is more efficient and correct according to RTMP spec.
//Simply passing "4" is the only thing that actually plays correctly, though.
@ -435,7 +437,7 @@ std::string & RTMPStream::SendMedia(FLV::Tag & tag){
} //SendMedia
/// Packs up a chunk for a control message with 1 argument.
std::string & RTMPStream::SendCTL(unsigned char type, unsigned int data){
std::string & RTMPStream::SendCTL(unsigned char type, unsigned int data) {
static RTMPStream::Chunk ch;
ch.cs_id = 2;
ch.timestamp = Util::getMS();
@ -445,12 +447,12 @@ std::string & RTMPStream::SendCTL(unsigned char type, unsigned int data){
ch.msg_type_id = type;
ch.msg_stream_id = 0;
ch.data.resize(4);
*(int*)((char*)ch.data.c_str()) = htonl(data);
*(int *)((char *)ch.data.c_str()) = htonl(data);
return ch.Pack();
} //SendCTL
/// Packs up a chunk for a control message with 2 arguments.
std::string & RTMPStream::SendCTL(unsigned char type, unsigned int data, unsigned char data2){
std::string & RTMPStream::SendCTL(unsigned char type, unsigned int data, unsigned char data2) {
static RTMPStream::Chunk ch;
ch.cs_id = 2;
ch.timestamp = Util::getMS();
@ -460,13 +462,13 @@ std::string & RTMPStream::SendCTL(unsigned char type, unsigned int data, unsigne
ch.msg_type_id = type;
ch.msg_stream_id = 0;
ch.data.resize(5);
*(unsigned int*)((char*)ch.data.c_str()) = htonl(data);
*(unsigned int *)((char *)ch.data.c_str()) = htonl(data);
ch.data[4] = data2;
return ch.Pack();
} //SendCTL
/// Packs up a chunk for a user control message with 1 argument.
std::string & RTMPStream::SendUSR(unsigned char type, unsigned int data){
std::string & RTMPStream::SendUSR(unsigned char type, unsigned int data) {
static RTMPStream::Chunk ch;
ch.cs_id = 2;
ch.timestamp = Util::getMS();
@ -476,14 +478,14 @@ std::string & RTMPStream::SendUSR(unsigned char type, unsigned int data){
ch.msg_type_id = 4;
ch.msg_stream_id = 0;
ch.data.resize(6);
*(unsigned int*)(((char*)ch.data.c_str()) + 2) = htonl(data);
*(unsigned int *)(((char *)ch.data.c_str()) + 2) = htonl(data);
ch.data[0] = 0;
ch.data[1] = type;
return ch.Pack();
} //SendUSR
/// Packs up a chunk for a user control message with 2 arguments.
std::string & RTMPStream::SendUSR(unsigned char type, unsigned int data, unsigned int data2){
std::string & RTMPStream::SendUSR(unsigned char type, unsigned int data, unsigned int data2) {
static RTMPStream::Chunk ch;
ch.cs_id = 2;
ch.timestamp = Util::getMS();
@ -493,8 +495,8 @@ std::string & RTMPStream::SendUSR(unsigned char type, unsigned int data, unsigne
ch.msg_type_id = 4;
ch.msg_stream_id = 0;
ch.data.resize(10);
*(unsigned int*)(((char*)ch.data.c_str()) + 2) = htonl(data);
*(unsigned int*)(((char*)ch.data.c_str()) + 6) = htonl(data2);
*(unsigned int *)(((char *)ch.data.c_str()) + 2) = htonl(data);
*(unsigned int *)(((char *)ch.data.c_str()) + 6) = htonl(data2);
ch.data[0] = 0;
ch.data[1] = type;
return ch.Pack();
@ -508,14 +510,14 @@ std::string & RTMPStream::SendUSR(unsigned char type, unsigned int data, unsigne
/// \param indata The input string to parse and update.
/// \warning This function will destroy the current data in this chunk!
/// \returns True if a whole chunk could be read, false otherwise.
bool RTMPStream::Chunk::Parse(std::string & indata){
gettimeofday( &RTMPStream::lastrec, 0);
bool RTMPStream::Chunk::Parse(std::string & indata) {
gettimeofday(&RTMPStream::lastrec, 0);
unsigned int i = 0;
if (indata.size() < 1) return false; //need at least a byte
unsigned char chunktype = indata[i++ ];
//read the chunkstream ID properly
switch (chunktype & 0x3F){
switch (chunktype & 0x3F) {
case 0:
if (indata.size() < 2) return false; //need at least 2 bytes to continue
cs_id = indata[i++ ] + 64;
@ -535,7 +537,7 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
//process the rest of the header, for each chunk type
headertype = chunktype & 0xC0;
switch (headertype){
switch (headertype) {
case 0x00:
if (indata.size() < i + 11) return false; //can't read whole header
timestamp = indata[i++ ] * 256 * 256;
@ -553,13 +555,13 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
break;
case 0x40:
if (indata.size() < i + 7) return false; //can't read whole header
if (!allow_short){
if (!allow_short) {
DEBUG_MSG(DLVL_WARN, "Warning: Header type 0x40 with no valid previous chunk!");
}
timestamp = indata[i++ ] * 256 * 256;
timestamp += indata[i++ ] * 256;
timestamp += indata[i++ ];
if (timestamp != 0x00ffffff){
if (timestamp != 0x00ffffff) {
timestamp += prev.timestamp;
}
len = indata[i++ ] * 256 * 256;
@ -571,13 +573,13 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
break;
case 0x80:
if (indata.size() < i + 3) return false; //can't read whole header
if (!allow_short){
if (!allow_short) {
DEBUG_MSG(DLVL_WARN, "Warning: Header type 0x80 with no valid previous chunk!");
}
timestamp = indata[i++ ] * 256 * 256;
timestamp += indata[i++ ] * 256;
timestamp += indata[i++ ];
if (timestamp != 0x00ffffff){
if (timestamp != 0x00ffffff) {
timestamp += prev.timestamp;
}
len = prev.len;
@ -586,7 +588,7 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
msg_stream_id = prev.msg_stream_id;
break;
case 0xC0:
if (!allow_short){
if (!allow_short) {
DEBUG_MSG(DLVL_WARN, "Warning: Header type 0xC0 with no valid previous chunk!");
}
timestamp = prev.timestamp;
@ -597,18 +599,18 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
break;
}
//calculate chunk length, real length, and length left till complete
if (len_left > 0){
if (len_left > 0) {
real_len = len_left;
len_left -= real_len;
}else{
} else {
real_len = len;
}
if (real_len > RTMPStream::chunk_rec_max){
if (real_len > RTMPStream::chunk_rec_max) {
len_left += real_len - RTMPStream::chunk_rec_max;
real_len = RTMPStream::chunk_rec_max;
}
//read extended timestamp, if neccesary
if (timestamp == 0x00ffffff){
if (timestamp == 0x00ffffff) {
if (indata.size() < i + 4) return false; //can't read whole header
timestamp = indata[i++ ] * 256 * 256 * 256;
timestamp += indata[i++ ] * 256 * 256;
@ -617,10 +619,10 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
}
//read data if length > 0, and allocate it
if (real_len > 0){
if (prev.len_left > 0){
if (real_len > 0) {
if (prev.len_left > 0) {
data = prev.data;
}else{
} else {
data = "";
}
if (indata.size() < i + real_len) return false; //can't read all data (yet)
@ -628,12 +630,12 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
indata = indata.substr(i + real_len);
lastrecv[cs_id] = *this;
RTMPStream::rec_cnt += i + real_len;
if (len_left == 0){
if (len_left == 0) {
return true;
}else{
} else {
return Parse(indata);
}
}else{
} else {
data = "";
indata = indata.substr(i + real_len);
lastrecv[cs_id] = *this;
@ -650,17 +652,17 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
/// \param buffer The input to parse and update.
/// \warning This function will destroy the current data in this chunk!
/// \returns True if a whole chunk could be read, false otherwise.
bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
gettimeofday( &RTMPStream::lastrec, 0);
bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer) {
gettimeofday(&RTMPStream::lastrec, 0);
unsigned int i = 0;
if ( !buffer.available(3)){
if (!buffer.available(3)) {
return false;
} //we want at least 3 bytes
std::string indata = buffer.copy(3);
unsigned char chunktype = indata[i++ ];
//read the chunkstream ID properly
switch (chunktype & 0x3F){
switch (chunktype & 0x3F) {
case 0:
cs_id = indata[i++ ] + 64;
break;
@ -677,9 +679,9 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
//process the rest of the header, for each chunk type
headertype = chunktype & 0xC0;
switch (headertype){
switch (headertype) {
case 0x00:
if ( !buffer.available(i + 11)){
if (!buffer.available(i + 11)) {
return false;
} //can't read whole header
indata = buffer.copy(i + 11);
@ -697,17 +699,17 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
msg_stream_id += indata[i++ ] * 256 * 256 * 256;
break;
case 0x40:
if ( !buffer.available(i + 7)){
if (!buffer.available(i + 7)) {
return false;
} //can't read whole header
indata = buffer.copy(i + 7);
if (prev.msg_type_id == 0){
if (prev.msg_type_id == 0) {
DEBUG_MSG(DLVL_WARN, "Warning: Header type 0x40 with no valid previous chunk!");
}
timestamp = indata[i++ ] * 256 * 256;
timestamp += indata[i++ ] * 256;
timestamp += indata[i++ ];
if (timestamp != 0x00ffffff){
if (timestamp != 0x00ffffff) {
timestamp += prev.timestamp;
}
len = indata[i++ ] * 256 * 256;
@ -718,17 +720,17 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
msg_stream_id = prev.msg_stream_id;
break;
case 0x80:
if ( !buffer.available(i + 3)){
if (!buffer.available(i + 3)) {
return false;
} //can't read whole header
indata = buffer.copy(i + 3);
if (prev.msg_type_id == 0){
if (prev.msg_type_id == 0) {
DEBUG_MSG(DLVL_WARN, "Warning: Header type 0x80 with no valid previous chunk!");
}
timestamp = indata[i++ ] * 256 * 256;
timestamp += indata[i++ ] * 256;
timestamp += indata[i++ ];
if (timestamp != 0x00ffffff){
if (timestamp != 0x00ffffff) {
timestamp += prev.timestamp;
}
len = prev.len;
@ -737,7 +739,7 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
msg_stream_id = prev.msg_stream_id;
break;
case 0xC0:
if (prev.msg_type_id == 0){
if (prev.msg_type_id == 0) {
DEBUG_MSG(DLVL_WARN, "Warning: Header type 0xC0 with no valid previous chunk!");
}
timestamp = prev.timestamp;
@ -748,19 +750,19 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
break;
}
//calculate chunk length, real length, and length left till complete
if (len_left > 0){
if (len_left > 0) {
real_len = len_left;
len_left -= real_len;
}else{
} else {
real_len = len;
}
if (real_len > RTMPStream::chunk_rec_max){
if (real_len > RTMPStream::chunk_rec_max) {
len_left += real_len - RTMPStream::chunk_rec_max;
real_len = RTMPStream::chunk_rec_max;
}
//read extended timestamp, if neccesary
if (timestamp == 0x00ffffff){
if ( !buffer.available(i + 4)){
if (timestamp == 0x00ffffff) {
if (!buffer.available(i + 4)) {
return false;
} //can't read timestamp
indata = buffer.copy(i + 4);
@ -771,24 +773,24 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
}
//read data if length > 0, and allocate it
if (real_len > 0){
if ( !buffer.available(i + real_len)){
if (real_len > 0) {
if (!buffer.available(i + real_len)) {
return false;
} //can't read all data (yet)
buffer.remove(i); //remove the header
if (prev.len_left > 0){
if (prev.len_left > 0) {
data = prev.data + buffer.remove(real_len); //append the data and remove from buffer
}else{
} else {
data = buffer.remove(real_len); //append the data and remove from buffer
}
lastrecv[cs_id] = *this;
RTMPStream::rec_cnt += i + real_len;
if (len_left == 0){
if (len_left == 0) {
return true;
}else{
} else {
return Parse(buffer);
}
}else{
} else {
buffer.remove(i); //remove the header
data = "";
indata = indata.substr(i + real_len);
@ -802,10 +804,10 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
/// After calling this function, don't forget to read and ignore 1536 extra bytes,
/// these are the handshake response and not interesting for us because we don't do client
/// verification.
bool RTMPStream::doHandshake(){
bool RTMPStream::doHandshake() {
char Version;
//Read C0
if (handshake_in.size() < 1537){
if (handshake_in.size() < 1537) {
DEBUG_MSG(DLVL_FAIL, "Handshake wasn't filled properly (%lu/1537) - aborting!", handshake_in.size());
return false;
}
@ -816,9 +818,9 @@ bool RTMPStream::doHandshake(){
RTMPStream::rec_cnt += 1537;
//Build S1 Packet
*((uint32_t*)Server) = 0; //time zero
*(((uint32_t*)(Server + 4))) = htonl(0x01020304); //version 1 2 3 4
for (int i = 8; i < 3072; ++i){
*((uint32_t *)Server) = 0; //time zero
*(((uint32_t *)(Server + 4))) = htonl(0x01020304); //version 1 2 3 4
for (int i = 8; i < 3072; ++i) {
Server[i] = FILLER_DATA[i % sizeof(FILLER_DATA)];
} //"random" data
@ -828,7 +830,7 @@ bool RTMPStream::doHandshake(){
if (ValidateClientScheme(Client, 0)) _validationScheme = 0;
if (ValidateClientScheme(Client, 1)) _validationScheme = 1;
DEBUG_MSG(DLVL_HIGH, "Handshake type is %hhi, encryption is %s", _validationScheme, encrypted?"on":"off");
DEBUG_MSG(DLVL_HIGH, "Handshake type is %hhi, encryption is %s", _validationScheme, encrypted ? "on" : "off");
//FIRST 1536 bytes from server response
//compute DH key position
@ -837,34 +839,34 @@ bool RTMPStream::doHandshake(){
//generate DH key
DHWrapper dhWrapper(1024);
if ( !dhWrapper.Initialize()){
if (!dhWrapper.Initialize()) {
return false;
}
if ( !dhWrapper.CreateSharedKey(Client + clientDHOffset, 128)){
if (!dhWrapper.CreateSharedKey(Client + clientDHOffset, 128)) {
return false;
}
if ( !dhWrapper.CopyPublicKey(Server + serverDHOffset, 128)){
if (!dhWrapper.CopyPublicKey(Server + serverDHOffset, 128)) {
return false;
}
if (encrypted){
if (encrypted) {
uint8_t secretKey[128];
if ( !dhWrapper.CopySharedKey(secretKey, sizeof(secretKey))){
if (!dhWrapper.CopySharedKey(secretKey, sizeof(secretKey))) {
return false;
}
RC4_KEY _pKeyIn;
RC4_KEY _pKeyOut;
InitRC4Encryption(secretKey, (uint8_t*) &Client[clientDHOffset], (uint8_t*) &Server[serverDHOffset], &_pKeyIn, &_pKeyOut);
InitRC4Encryption(secretKey, (uint8_t *) &Client[clientDHOffset], (uint8_t *) &Server[serverDHOffset], &_pKeyIn, &_pKeyOut);
uint8_t data[1536];
RC4( &_pKeyIn, 1536, data, data);
RC4( &_pKeyOut, 1536, data, data);
RC4(&_pKeyIn, 1536, data, data);
RC4(&_pKeyOut, 1536, data, data);
}
//generate the digest
uint32_t serverDigestOffset = GetDigestOffset(Server, _validationScheme);
uint8_t *pTempBuffer = new uint8_t[1536 - 32];
uint8_t * pTempBuffer = new uint8_t[1536 - 32];
memcpy(pTempBuffer, Server, serverDigestOffset);
memcpy(pTempBuffer + serverDigestOffset, Server + serverDigestOffset + 32, 1536 - serverDigestOffset - 32);
uint8_t *pTempHash = new uint8_t[512];
uint8_t * pTempHash = new uint8_t[512];
HMACsha256(pTempBuffer, 1536 - 32, genuineFMSKey, 36, pTempHash);
memcpy(Server + serverDigestOffset, pTempHash, 32);
delete[] pTempBuffer;
@ -874,7 +876,7 @@ bool RTMPStream::doHandshake(){
uint32_t keyChallengeIndex = GetDigestOffset(Client, _validationScheme);
pTempHash = new uint8_t[512];
HMACsha256(Client + keyChallengeIndex, 32, genuineFMSKey, 68, pTempHash);
uint8_t *pLastHash = new uint8_t[512];
uint8_t * pLastHash = new uint8_t[512];
HMACsha256(Server + 1536, 1536 - 32, pTempHash, 32, pLastHash);
memcpy(Server + 1536 * 2 - 32, pLastHash, 32);
delete[] pTempHash;

View file

@ -30,7 +30,7 @@ namespace RTMPStream {
extern timeval lastrec; ///< Timestamp of last time data was received.
/// Holds a single RTMP chunk, either send or receive direction.
class Chunk{
class Chunk {
public:
unsigned char headertype; ///< For input chunks, the type of header. This is calculated automatically for output chunks.
unsigned int cs_id; ///< ContentStream ID

View file

@ -177,11 +177,11 @@ namespace IPC {
///\brief Unmaps a shared page if allowed
void sharedPage::unmap() {
if (mapped && len) {
#ifdef __CYGWIN__
#ifdef __CYGWIN__
UnmapViewOfFile(mapped);
#else
#else
munmap(mapped, len);
#endif
#endif
mapped = 0;
len = 0;
}
@ -191,14 +191,14 @@ namespace IPC {
void sharedPage::close() {
unmap();
if (handle > 0) {
#ifdef __CYGWIN__
#ifdef __CYGWIN__
CloseHandle(handle);
#else
#else
::close(handle);
if (master && name != "") {
shm_unlink(name.c_str());
}
#endif
#endif
handle = 0;
}
}
@ -247,18 +247,18 @@ namespace IPC {
master = master_;
mapped = 0;
if (name.size()) {
#ifdef __CYGWIN__
if (master){
#ifdef __CYGWIN__
if (master) {
handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, len, name.c_str());
}else{
} else {
int i = 0;
do {
if (i != 0){
if (i != 0) {
Util::sleep(1000);
}
handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name.c_str());
i++;
} while(i < 10 && !handle && autoBackoff);
} while (i < 10 && !handle && autoBackoff);
}
if (!handle) {
DEBUG_MSG(DLVL_FAIL, "%s for page %s failed: %s", (master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), strerror(errno));
@ -268,7 +268,7 @@ namespace IPC {
if (!mapped) {
return;
}
#else
#else
handle = shm_open(name.c_str(), (master ? O_CREAT | O_EXCL : 0) | O_RDWR, ACCESSPERMS);
if (handle == -1) {
if (master) {
@ -309,7 +309,7 @@ namespace IPC {
mapped = 0;
return;
}
#endif
#endif
}
}

View file

@ -80,7 +80,7 @@ namespace IPC {
#if !defined __APPLE__
///\brief A class for managing shared memory pages.
class sharedPage{
class sharedPage {
public:
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage & rhs);
@ -93,13 +93,13 @@ namespace IPC {
}
void unmap();
void close();
#ifdef __CYGWIN__
#ifdef __CYGWIN__
///\brief The handle of the opened shared memory page
HANDLE handle;
#else
#else
///\brief The fd handle of the opened shared memory page
int handle;
#endif
#endif
///\brief The name of the opened shared memory page
std::string name;
///\brief The size in bytes of the opened shared memory page
@ -118,7 +118,7 @@ namespace IPC {
#else
///\brief A class for managing shared files.
#endif
class sharedFile{
class sharedFile {
public:
sharedFile(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedFile(const sharedFile & rhs);
@ -146,7 +146,7 @@ namespace IPC {
///\brief A class for handling shared memory pages.
///
///Uses shared files at its backbone, defined for portability
class sharedPage: public sharedFile{
class sharedPage: public sharedFile {
public:
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage & rhs);
@ -163,7 +163,7 @@ namespace IPC {
///
///Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
///If no such length can be allocated, the next page should be tried, and so on.
class sharedServer{
class sharedServer {
public:
sharedServer();
sharedServer(std::string name, int len, bool withCounter = false);
@ -198,7 +198,7 @@ namespace IPC {
///
///Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
///If no such length can be allocated, the next page should be tried, and so on.
class sharedClient{
class sharedClient {
public:
sharedClient();
sharedClient(const sharedClient & rhs);

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ namespace Buffer {
namespace Socket {
/// A buffer made out of std::string objects that can be efficiently read from and written to.
class Buffer{
class Buffer {
private:
std::deque<std::string> data;
public:
@ -44,7 +44,7 @@ namespace Socket {
//Buffer
/// This class is for easy communicating through sockets, either TCP or Unix.
class Connection{
class Connection {
private:
int sock; ///< Internally saved socket number.
int pipes[2]; ///< Internally saved file descriptors for pipe socket simulation.
@ -98,13 +98,13 @@ namespace Socket {
bool Error; ///< Set to true if a socket error happened.
bool Blocking; ///< Set to true if a socket is currently or wants to be blocking.
//overloaded operators
bool operator==(const Connection &B) const;
bool operator!=(const Connection &B) const;
bool operator==(const Connection & B) const;
bool operator!=(const Connection & B) const;
operator bool() const;
};
/// This class is for easily setting up listening socket, either TCP or Unix.
class Server{
class Server {
private:
std::string errors; ///< Stores errors that may have occured.
int sock; ///< Internally saved socket number.
@ -123,7 +123,7 @@ namespace Socket {
int getSocket(); ///< Returns internal socket number.
};
class UDPConnection{
class UDPConnection {
private:
int sock; ///< Internally saved socket number.
std::string remotehost;///< Stores remote host address

View file

@ -14,29 +14,29 @@
#include "defines.h"
#include "shared_memory.h"
std::string Util::getTmpFolder(){
std::string Util::getTmpFolder() {
std::string dir;
char * tmp_char = 0;
if ( !tmp_char){
if (!tmp_char) {
tmp_char = getenv("TMP");
}
if ( !tmp_char){
if (!tmp_char) {
tmp_char = getenv("TEMP");
}
if ( !tmp_char){
if (!tmp_char) {
tmp_char = getenv("TMPDIR");
}
if (tmp_char){
if (tmp_char) {
dir = tmp_char;
dir += "/mist";
}else{
} else {
#if defined(_WIN32) || defined(_CYGWIN_)
dir = "C:/tmp/mist";
#else
dir = "/tmp/mist";
#endif
}
if (access(dir.c_str(), 0) != 0){
if (access(dir.c_str(), 0) != 0) {
mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); //attempt to create mist folder - ignore failures
}
return dir + "/";
@ -46,92 +46,92 @@ std::string Util::getTmpFolder(){
/// Filters the streamname, removing invalid characters and converting all
/// letters to lowercase. If a '?' character is found, everything following
/// that character is deleted. The original string is modified.
void Util::Stream::sanitizeName(std::string & streamname){
void Util::Stream::sanitizeName(std::string & streamname) {
//strip anything that isn't numbers, digits or underscores
for (std::string::iterator i = streamname.end() - 1; i >= streamname.begin(); --i){
if ( *i == '?'){
for (std::string::iterator i = streamname.end() - 1; i >= streamname.begin(); --i) {
if (*i == '?') {
streamname.erase(i, streamname.end());
break;
}
if ( !isalpha( *i) && !isdigit( *i) && *i != '_'){
if (!isalpha(*i) && !isdigit(*i) && *i != '_') {
streamname.erase(i);
}else{
*i = tolower( *i);
} else {
*i = tolower(*i);
}
}
}
bool Util::Stream::getLive(std::string streamname){
bool Util::Stream::getLive(std::string streamname) {
JSON::Value ServConf = JSON::fromFile(getTmpFolder() + "streamlist");
static unsigned long long counter = 0;
std::stringstream name;
name << "MistInBuffer " << (counter++);
std::string player_bin = Util::getMyPath() + "MistInBuffer";
DEBUG_MSG(DLVL_WARN, "Starting %s -p -s %s", player_bin.c_str(), streamname.c_str());
char* argv[15] = {(char*)player_bin.c_str(), (char*)"-p", (char*)"-s", (char*)streamname.c_str(), (char*)0};
char * argv[15] = {(char *)player_bin.c_str(), (char *)"-p", (char *)"-s", (char *)streamname.c_str(), (char *)0};
int argNum = 4;
if (ServConf["streams"][streamname].isMember("DVR")){
if (ServConf["streams"][streamname].isMember("DVR")) {
std::string bufferTime = ServConf["streams"][streamname]["DVR"].asString();
argv[argNum++] = (char*)"-b";
argv[argNum++] = (char*)bufferTime.c_str();
argv[argNum++] = (char*)0;
argv[argNum++] = (char *)"-b";
argv[argNum++] = (char *)bufferTime.c_str();
argv[argNum++] = (char *)0;
}
int pid = fork();
if (pid){
if (pid) {
execvp(argv[0], argv);
_exit(42);
}else if(pid == -1){
} else if (pid == -1) {
perror("Could not start vod");
}
return true;
}
/// Starts a process for a VoD stream.
bool Util::Stream::getVod(std::string filename, std::string streamname){
bool Util::Stream::getVod(std::string filename, std::string streamname) {
static unsigned long long counter = 0;
std::stringstream name;
name << "MistInDTSC " << (counter++);
std::string player_bin = Util::getMyPath() + "MistInDTSC";
if (filename.substr(filename.size()-5) == ".ismv"){
if (filename.substr(filename.size() - 5) == ".ismv") {
name.str("MistInISMV " + filename);
player_bin = Util::getMyPath() + "MistInISMV";
}
if (filename.substr(filename.size()-4) == ".flv"){
if (filename.substr(filename.size() - 4) == ".flv") {
name.str("MistInFLV " + filename);
player_bin = Util::getMyPath() + "MistInFLV";
}
INFO_MSG("Starting %s -p -s %s %s", player_bin.c_str(), streamname.c_str(), filename.c_str());
char* const argv[] = {(char*)player_bin.c_str(), (char*)"-p", (char*)"-s", (char*)streamname.c_str(), (char*)filename.c_str(), (char*)0};
char * const argv[] = {(char *)player_bin.c_str(), (char *)"-p", (char *)"-s", (char *)streamname.c_str(), (char *)filename.c_str(), (char *)0};
int pid = fork();
if (pid){
if (pid) {
execvp(argv[0], argv);
_exit(42);
}else if(pid == -1){
} else if (pid == -1) {
perror("Could not start vod");
}
return true;
}
/// Probe for available streams. Currently first VoD, then Live.
bool Util::Stream::getStream(std::string streamname){
bool Util::Stream::getStream(std::string streamname) {
sanitizeName(streamname);
JSON::Value ServConf = JSON::fromFile(getTmpFolder() + "streamlist");
if (ServConf["streams"].isMember(streamname)){
if (ServConf["streams"].isMember(streamname)) {
//check if the stream is already active, if yes, don't re-activate
IPC::semaphore playerLock(std::string("/lock_" + streamname).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 1);
if (!playerLock.tryWait()){
if (!playerLock.tryWait()) {
playerLock.close();
DEBUG_MSG(DLVL_MEDIUM, "Playerlock for %s already active - not re-activating stream", streamname.c_str());
return true;
}
playerLock.post();
playerLock.close();
if (ServConf["streams"][streamname]["source"].asString()[0] == '/'){
if (ServConf["streams"][streamname]["source"].asString()[0] == '/') {
DEBUG_MSG(DLVL_MEDIUM, "Activating VoD stream %s", streamname.c_str());
return getVod(ServConf["streams"][streamname]["source"].asString(), streamname);
}else{
} else {
DEBUG_MSG(DLVL_MEDIUM, "Activating live stream %s", streamname.c_str());
return getLive(streamname);
}
@ -144,7 +144,7 @@ bool Util::Stream::getStream(std::string streamname){
/// Filters the streamname, removing invalid characters and
/// converting all letters to lowercase.
/// If a '?' character is found, everything following that character is deleted.
Socket::Server Util::Stream::makeLive(std::string streamname){
Socket::Server Util::Stream::makeLive(std::string streamname) {
sanitizeName(streamname);
std::string loc = getTmpFolder() + "stream_" + streamname;
//create and return the Socket::Server

View file

@ -7,7 +7,7 @@
namespace Util {
std::string getTmpFolder();
class Stream{
class Stream {
public:
static void sanitizeName(std::string & streamname);
static bool getLive(std::string streamname);

View file

@ -4,93 +4,117 @@
#include <arpa/inet.h>
#include <sstream>
namespace theora{
bool header::checkDataSize(unsigned int size){
if (size > datasize){
void* tmp = realloc(data,size);
if (tmp){
data = (char*)tmp;
namespace theora {
bool header::checkDataSize(unsigned int size) {
if (size > datasize) {
void * tmp = realloc(data, size);
if (tmp) {
data = (char *)tmp;
datasize = size;
return true;
}else{
} else {
return false;
}
}else{
} else {
return true;
}
}
uint32_t header::getInt32(size_t index){
if (datasize >= (index + 3)){
uint32_t header::getInt32(size_t index) {
if (datasize >= (index + 3)) {
return (data[index] << 24) + (data[index + 1] << 16) + (data[index + 2] << 8) + data[index + 3];
}
return 0;
}
uint32_t header::getInt24(size_t index){
if (datasize >= (index + 2)){
uint32_t header::getInt24(size_t index) {
if (datasize >= (index + 2)) {
return 0 + (data[index] << 16) + (data[index + 1] << 8) + data[index + 2];
}
return 0;
}
uint16_t header::getInt16(size_t index){
if (datasize >= (index + 1)){
uint16_t header::getInt16(size_t index) {
if (datasize >= (index + 1)) {
return 0 + (data[index] << 8) + data[index + 1];
}
return 0;
}
uint32_t header::commentLen(size_t index){
if (datasize >= index + 3){
uint32_t header::commentLen(size_t index) {
if (datasize >= index + 3) {
return data[index] + (data[index + 1] << 8) + (data[index + 2] << 16) + (data[index + 3] << 24);
}
return 0;
}
header::header(){
header::header() {
data = NULL;
datasize = 0;
}
header::header(char * newData, unsigned int length){
header::header(char * newData, unsigned int length) {
data = NULL;
datasize = 0;
read(newData, length);
}
bool header::validateIdentificationHeader(){
if (datasize != 42){return false;}
if (getHeaderType() != 0){return false;}
if (getVMAJ() != 3){return false;}
if (getVMIN() != 2){return false;}
if (getFMBW() == 0){return false;}
if (getFMBH() == 0){return false;}
if ((short)getPICW() > getFMBW() * 16){return false;}
if ((short)getPICH() > getFMBH() * 16){return false;}
if ((short)getPICX() > (getFMBW() * 16) - (short)getPICW()){return false;}
if ((short)getPICY() > (getFMBH() * 16) - (short)getPICH()){return false;}
if (getFRN() == 0){return false;}
if (getFRD() == 0){return false;}
bool header::validateIdentificationHeader() {
if (datasize != 42) {
return false;
}
if (getHeaderType() != 0) {
return false;
}
if (getVMAJ() != 3) {
return false;
}
if (getVMIN() != 2) {
return false;
}
if (getFMBW() == 0) {
return false;
}
if (getFMBH() == 0) {
return false;
}
if ((short)getPICW() > getFMBW() * 16) {
return false;
}
if ((short)getPICH() > getFMBH() * 16) {
return false;
}
if ((short)getPICX() > (getFMBW() * 16) - (short)getPICW()) {
return false;
}
if ((short)getPICY() > (getFMBH() * 16) - (short)getPICH()) {
return false;
}
if (getFRN() == 0) {
return false;
}
if (getFRD() == 0) {
return false;
}
return true;
}
bool header::read(char* newData, unsigned int length){
if (length < 7){
bool header::read(char * newData, unsigned int length) {
if (length < 7) {
return false;
}
if (! (newData[0] & 0x80)){
if (!(newData[0] & 0x80)) {
return false;
}
if(memcmp(newData+1, "theora", 6)!=0){
if (memcmp(newData + 1, "theora", 6) != 0) {
return false;
}
if (checkDataSize(length)){
if (checkDataSize(length)) {
memcpy(data, newData, length);
}else{
} else {
return false;
}
switch(getHeaderType()){
switch (getHeaderType()) {
case 0:
return validateIdentificationHeader();
break;
@ -104,224 +128,272 @@ namespace theora{
return true;
}
int header::getHeaderType(){
int header::getHeaderType() {
return (data[0] & 0x7F);
}
char header::getVMAJ(){
if (getHeaderType() == 0){return data[7];}
char header::getVMAJ() {
if (getHeaderType() == 0) {
return data[7];
}
return 0;
}
char header::getVMIN(){
if (getHeaderType() == 0){return data[8];}
char header::getVMIN() {
if (getHeaderType() == 0) {
return data[8];
}
return 0;
}
char header::getVREV(){
if (getHeaderType() == 0){return data[9];}
char header::getVREV() {
if (getHeaderType() == 0) {
return data[9];
}
return 0;
}
short header::getFMBW(){
if (getHeaderType() == 0){return getInt16(10);}
short header::getFMBW() {
if (getHeaderType() == 0) {
return getInt16(10);
}
return 0;
}
short header::getFMBH(){
if (getHeaderType() == 0){return getInt16(12);}
short header::getFMBH() {
if (getHeaderType() == 0) {
return getInt16(12);
}
return 0;
}
char header::getPICX(){
if (getHeaderType() == 0){return data[20];}
char header::getPICX() {
if (getHeaderType() == 0) {
return data[20];
}
return 0;
}
char header::getPICY(){
if (getHeaderType() == 0){return data[21];}
char header::getPICY() {
if (getHeaderType() == 0) {
return data[21];
}
return 0;
}
char header::getKFGShift(){
if (getHeaderType() == 0){return (getInt16(40) >> 5) & 0x1F;}
char header::getKFGShift() {
if (getHeaderType() == 0) {
return (getInt16(40) >> 5) & 0x1F;
}
return 0;
}
long unsigned int header::getFRN(){
if (getHeaderType() == 0){return getInt32(22);}
long unsigned int header::getFRN() {
if (getHeaderType() == 0) {
return getInt32(22);
}
return 0;
}
long unsigned int header::getPICH(){
if (getHeaderType() == 0){return getInt24(17);}
long unsigned int header::getPICH() {
if (getHeaderType() == 0) {
return getInt24(17);
}
return 0;
}
long unsigned int header::getPICW(){
if (getHeaderType() == 0){return getInt24(14);}
long unsigned int header::getPICW() {
if (getHeaderType() == 0) {
return getInt24(14);
}
return 0;
}
long unsigned int header::getFRD(){
if (getHeaderType() == 0){return getInt32(26);}
long unsigned int header::getFRD() {
if (getHeaderType() == 0) {
return getInt32(26);
}
return 0;
}
long unsigned int header::getPARN(){
if (getHeaderType() == 0){return getInt24(30);}
long unsigned int header::getPARN() {
if (getHeaderType() == 0) {
return getInt24(30);
}
return 0;
}
long unsigned int header::getPARD(){
if (getHeaderType() == 0){return getInt24(33);}
long unsigned int header::getPARD() {
if (getHeaderType() == 0) {
return getInt24(33);
}
return 0;
}
char header::getCS(){
if (getHeaderType() == 0){return data[36];}
char header::getCS() {
if (getHeaderType() == 0) {
return data[36];
}
return 0;
}
long unsigned int header::getNOMBR(){
if (getHeaderType() == 0){return getInt24(37);}
long unsigned int header::getNOMBR() {
if (getHeaderType() == 0) {
return getInt24(37);
}
return 0;
}
char header::getQUAL(){
if (getHeaderType() == 0){return (data[40] >> 3) & 0x1F;}
char header::getQUAL() {
if (getHeaderType() == 0) {
return (data[40] >> 3) & 0x1F;
}
return 0;
}
char header::getPF(){
if (getHeaderType() == 0){return (data[41] >> 3) & 0x03;}
char header::getPF() {
if (getHeaderType() == 0) {
return (data[41] >> 3) & 0x03;
}
return 0;
}
std::string header::getVendor(){
if (getHeaderType() != 1){return "";}
std::string header::getVendor() {
if (getHeaderType() != 1) {
return "";
}
return std::string(data + 11, commentLen(7));
}
long unsigned int header::getNComments(){
if (getHeaderType() != 1){return 0;}
long unsigned int header::getNComments() {
if (getHeaderType() != 1) {
return 0;
}
int offset = 11 + commentLen(7);
return commentLen(offset);
}
char header::getLFLIMS(size_t index){
if (getHeaderType() != 2){return 0;}
if (index >= 64){return 0;}
char header::getLFLIMS(size_t index) {
if (getHeaderType() != 2) {
return 0;
}
if (index >= 64) {
return 0;
}
char NBITS = (data[0] >> 5) & 0x07;
return NBITS;
}
std::string header::getUserComment(size_t index){
if (index >= getNComments()){return "";}
std::string header::getUserComment(size_t index) {
if (index >= getNComments()) {
return "";
}
int offset = 11 + commentLen(7) + 4;
for (size_t i = 0; i < index; i++){
for (size_t i = 0; i < index; i++) {
offset += 4 + commentLen(offset);
}
return std::string(data + offset + 4,commentLen(offset));
return std::string(data + offset + 4, commentLen(offset));
}
std::string header::toPrettyString(size_t indent){
std::string header::toPrettyString(size_t indent) {
std::stringstream result;
result << std::string(indent,' ') << "Theora header" << std::endl;
result << std::string(indent+2,' ') << "HeaderType: " << getHeaderType() << std::endl;
switch (getHeaderType()){
result << std::string(indent, ' ') << "Theora header" << std::endl;
result << std::string(indent + 2, ' ') << "HeaderType: " << getHeaderType() << std::endl;
switch (getHeaderType()) {
case 0:
result << std::string(indent+2,' ') << "VMAJ: " << (int)getVMAJ() << std::endl;
result << std::string(indent+2,' ') << "VMIN: " << (int)getVMIN() << std::endl;
result << std::string(indent+2,' ') << "VREV: " << (int)getVREV() << std::endl;
result << std::string(indent+2,' ') << "FMBW: " << getFMBW() << std::endl;
result << std::string(indent+2,' ') << "FMBH: " << getFMBH() << std::endl;
result << std::string(indent+2,' ') << "PICH: " << getPICH() << std::endl;
result << std::string(indent+2,' ') << "PICW: " << getPICW() << std::endl;
result << std::string(indent+2,' ') << "PICX: " << (int)getPICX() << std::endl;
result << std::string(indent+2,' ') << "PICY: " << (int)getPICY() << std::endl;
result << std::string(indent+2,' ') << "FRN: " << getFRN() << std::endl;
result << std::string(indent+2,' ') << "FRD: " << getFRD() << std::endl;
result << std::string(indent+2,' ') << "PARN: " << getPARN() << std::endl;
result << std::string(indent+2,' ') << "PARD: " << getPARD() << std::endl;
result << std::string(indent+2,' ') << "CS: " << (int)getCS() << std::endl;
result << std::string(indent+2,' ') << "NOMBR: " << getNOMBR() << std::endl;
result << std::string(indent+2,' ') << "QUAL: " << (int)getQUAL() << std::endl;
result << std::string(indent+2,' ') << "KFGShift: " << (int)getKFGShift() << std::endl;
result << std::string(indent + 2, ' ') << "VMAJ: " << (int)getVMAJ() << std::endl;
result << std::string(indent + 2, ' ') << "VMIN: " << (int)getVMIN() << std::endl;
result << std::string(indent + 2, ' ') << "VREV: " << (int)getVREV() << std::endl;
result << std::string(indent + 2, ' ') << "FMBW: " << getFMBW() << std::endl;
result << std::string(indent + 2, ' ') << "FMBH: " << getFMBH() << std::endl;
result << std::string(indent + 2, ' ') << "PICH: " << getPICH() << std::endl;
result << std::string(indent + 2, ' ') << "PICW: " << getPICW() << std::endl;
result << std::string(indent + 2, ' ') << "PICX: " << (int)getPICX() << std::endl;
result << std::string(indent + 2, ' ') << "PICY: " << (int)getPICY() << std::endl;
result << std::string(indent + 2, ' ') << "FRN: " << getFRN() << std::endl;
result << std::string(indent + 2, ' ') << "FRD: " << getFRD() << std::endl;
result << std::string(indent + 2, ' ') << "PARN: " << getPARN() << std::endl;
result << std::string(indent + 2, ' ') << "PARD: " << getPARD() << std::endl;
result << std::string(indent + 2, ' ') << "CS: " << (int)getCS() << std::endl;
result << std::string(indent + 2, ' ') << "NOMBR: " << getNOMBR() << std::endl;
result << std::string(indent + 2, ' ') << "QUAL: " << (int)getQUAL() << std::endl;
result << std::string(indent + 2, ' ') << "KFGShift: " << (int)getKFGShift() << std::endl;
break;
case 1:
result << std::string(indent+2,' ') << "Vendor: " << getVendor() << std::endl;
result << std::string(indent+2,' ') << "User Comments (" << getNComments() << "):" << std::endl;
for (long unsigned int i = 0; i < getNComments(); i++){
result << std::string(indent+4,' ') << "[" << i << "] " << getUserComment(i) << std::endl;
result << std::string(indent + 2, ' ') << "Vendor: " << getVendor() << std::endl;
result << std::string(indent + 2, ' ') << "User Comments (" << getNComments() << "):" << std::endl;
for (long unsigned int i = 0; i < getNComments(); i++) {
result << std::string(indent + 4, ' ') << "[" << i << "] " << getUserComment(i) << std::endl;
}
break;
case 2:
result << std::string(indent+2,' ') << "NBITS: " << (int)getLFLIMS(0) << std::endl;
result << std::string(indent + 2, ' ') << "NBITS: " << (int)getLFLIMS(0) << std::endl;
}
return result.str();
}
frame::frame(){
frame::frame() {
data = NULL;
datasize = 0;
}
bool frame::checkDataSize(unsigned int size){
if (size > datasize){
void* tmp = realloc(data,size);
if (tmp){
data = (char*)tmp;
bool frame::checkDataSize(unsigned int size) {
if (size > datasize) {
void * tmp = realloc(data, size);
if (tmp) {
data = (char *)tmp;
datasize = size;
return true;
}else{
} else {
return false;
}
}else{
} else {
return true;
}
}
bool frame::read(char* newData, unsigned int length){
if (length < 7){
bool frame::read(char * newData, unsigned int length) {
if (length < 7) {
return false;
}
if ((newData[0] & 0x80)){
if ((newData[0] & 0x80)) {
return false;
}
if (checkDataSize(length)){
if (checkDataSize(length)) {
memcpy(data, newData, length);
}else{
} else {
return false;
}
return true;
}
char frame::getFTYPE(){
char frame::getFTYPE() {
return (data[0] >> 6) & 0x01;
}
char frame::getNQIS(){
char frame::getNQIS() {
return 0;
}
char frame::getQIS(size_t index){
if (index >= 3){return 0;}
char frame::getQIS(size_t index) {
if (index >= 3) {
return 0;
}
return 0;
}
long long unsigned int header::parseGranuleUpper(long long unsigned int granPos){
long long unsigned int header::parseGranuleUpper(long long unsigned int granPos) {
return granPos >> getKFGShift();
}
long long unsigned int header::parseGranuleLower(long long unsigned int granPos){
long long unsigned int header::parseGranuleLower(long long unsigned int granPos) {
return (granPos & ((1 << getKFGShift()) - 1));
}
std::string frame::toPrettyString(size_t indent){
std::string frame::toPrettyString(size_t indent) {
std::stringstream result;
result << std::string(indent,' ') << "Theora Frame" << std::endl;
result << std::string(indent+2,' ') << "FType: " << (int)getFTYPE() << std::endl;
result << std::string(indent, ' ') << "Theora Frame" << std::endl;
result << std::string(indent + 2, ' ') << "FType: " << (int)getFTYPE() << std::endl;
return result.str();
}
}

View file

@ -3,12 +3,12 @@
#include<stdint.h>
#include<string>
namespace theora{
class header{
namespace theora {
class header {
public:
header();
header(char* newData, unsigned int length);
bool read(char* newData, unsigned int length);
header(char * newData, unsigned int length);
bool read(char * newData, unsigned int length);
int getHeaderType();
char getVMAJ();
char getVMIN();
@ -41,16 +41,16 @@ namespace theora{
uint16_t getInt16(size_t index);
uint32_t commentLen(size_t index);
private:
char* data;
char * data;
unsigned int datasize;
bool checkDataSize(unsigned int size);
bool validateIdentificationHeader();
};
class frame{
class frame {
public:
frame();
bool read(char* newData, unsigned int length);
bool read(char * newData, unsigned int length);
char getFTYPE();
char getNQIS();
char getQIS(size_t index);

View file

@ -11,7 +11,7 @@
#include <mach/mach.h>
#define CLOCK_REALTIME CALENDAR_CLOCK
#define CLOCK_MONOTONIC SYSTEM_CLOCK
void clock_gettime(int ign, struct timespec * ts){
void clock_gettime(int ign, struct timespec * ts) {
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), ign, &cclock);
@ -23,53 +23,53 @@ void clock_gettime(int ign, struct timespec * ts){
#endif
/// Sleeps for the indicated amount of milliseconds or longer.
void Util::sleep(int ms){
if (ms < 0){
void Util::sleep(int ms) {
if (ms < 0) {
return;
}
if (ms > 100000){
if (ms > 100000) {
ms = 100000;
}
struct timespec T;
T.tv_sec = ms / 1000;
T.tv_nsec = 1000000 * (ms % 1000);
nanosleep( &T, 0);
nanosleep(&T, 0);
}
long long Util::getNTP(){
long long Util::getNTP() {
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return ((((long long int)t.tv_sec) + 2208988800) << 32) + (t.tv_nsec*4.2949);
return ((((long long int)t.tv_sec) + 2208988800) << 32) + (t.tv_nsec * 4.2949);
}
/// Gets the current time in milliseconds.
long long int Util::getMS(){
long long int Util::getMS() {
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return ((long long int)t.tv_sec) * 1000 + t.tv_nsec / 1000000;
}
long long int Util::bootSecs(){
long long int Util::bootSecs() {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return t.tv_sec;
}
/// Gets the current time in microseconds.
long long unsigned int Util::getMicros(){
long long unsigned int Util::getMicros() {
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return ((long long unsigned int)t.tv_sec) * 1000000 + t.tv_nsec / 1000;
}
/// Gets the time difference in microseconds.
long long unsigned int Util::getMicros(long long unsigned int previous){
long long unsigned int Util::getMicros(long long unsigned int previous) {
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return ((long long unsigned int)t.tv_sec) * 1000000 + t.tv_nsec / 1000 - previous;
}
/// Gets the amount of seconds since 01/01/1970.
long long int Util::epoch(){
long long int Util::epoch() {
return time(0);
}

View file

@ -25,10 +25,10 @@ freely, subject to the following restrictions:
#include "tinythread.h"
#if defined(_TTHREAD_POSIX_)
#include <unistd.h>
#include <map>
#include <unistd.h>
#include <map>
#elif defined(_TTHREAD_WIN32_)
#include <process.h>
#include <process.h>
#endif
@ -49,31 +49,28 @@ namespace tthread {
//------------------------------------------------------------------------------
#if defined(_TTHREAD_WIN32_)
#define _CONDITION_EVENT_ONE 0
#define _CONDITION_EVENT_ALL 1
#define _CONDITION_EVENT_ONE 0
#define _CONDITION_EVENT_ALL 1
#endif
#if defined(_TTHREAD_WIN32_)
condition_variable::condition_variable() : mWaitersCount(0)
{
condition_variable::condition_variable() : mWaitersCount(0) {
mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSection(&mWaitersCountLock);
}
}
#endif
#if defined(_TTHREAD_WIN32_)
condition_variable::~condition_variable()
{
condition_variable::~condition_variable() {
CloseHandle(mEvents[_CONDITION_EVENT_ONE]);
CloseHandle(mEvents[_CONDITION_EVENT_ALL]);
DeleteCriticalSection(&mWaitersCountLock);
}
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::_wait()
{
void condition_variable::_wait() {
// Wait for either event to become signaled due to notify_one() or
// notify_all() being called
int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE);
@ -86,37 +83,35 @@ void condition_variable::_wait()
LeaveCriticalSection(&mWaitersCountLock);
// If we are the last waiter to be notified to stop waiting, reset the event
if(lastWaiter)
if (lastWaiter)
ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
}
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::notify_one()
{
void condition_variable::notify_one() {
// Are there any waiters?
EnterCriticalSection(&mWaitersCountLock);
bool haveWaiters = (mWaitersCount > 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal
if(haveWaiters)
if (haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ONE]);
}
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::notify_all()
{
void condition_variable::notify_all() {
// Are there any waiters?
EnterCriticalSection(&mWaitersCountLock);
bool haveWaiters = (mWaitersCount > 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal
if(haveWaiters)
if (haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ALL]);
}
}
#endif
@ -128,17 +123,16 @@ void condition_variable::notify_all()
//------------------------------------------------------------------------------
#if defined(_TTHREAD_POSIX_)
static thread::id _pthread_t_to_ID(const pthread_t &aHandle)
{
static thread::id _pthread_t_to_ID(const pthread_t & aHandle) {
static mutex idMapLock;
static std::map<pthread_t, unsigned long int> idMap;
static unsigned long int idCount(1);
lock_guard<mutex> guard(idMapLock);
if(idMap.find(aHandle) == idMap.end())
if (idMap.find(aHandle) == idMap.end())
idMap[aHandle] = idCount ++;
return thread::id(idMap[aHandle]);
}
}
#endif // _TTHREAD_POSIX_
@ -147,36 +141,33 @@ static thread::id _pthread_t_to_ID(const pthread_t &aHandle)
//------------------------------------------------------------------------------
/// Information to pass to the new thread (what to run).
struct _thread_start_info {
struct _thread_start_info {
void (*mFunction)(void *); ///< Pointer to the function to be executed.
void * mArg; ///< Function argument for the thread function.
thread * mThread; ///< Pointer to the thread object.
};
};
// Thread wrapper function.
#if defined(_TTHREAD_WIN32_)
unsigned WINAPI thread::wrapper_function(void * aArg)
unsigned WINAPI thread::wrapper_function(void * aArg)
#elif defined(_TTHREAD_POSIX_)
void * thread::wrapper_function(void * aArg)
void * thread::wrapper_function(void * aArg)
#endif
{
{
// Get thread startup information
_thread_start_info * ti = (_thread_start_info *) aArg;
try
{
try {
// Call the actual client thread function
ti->mFunction(ti->mArg);
}
catch(...)
{
} catch (...) {
// Uncaught exceptions will terminate the application (default behavior
// according to C++11)
std::terminate();
}
// The thread is no longer executing
if (ti->mThread){
if (ti->mThread) {
lock_guard<mutex> guard(ti->mThread->mDataMutex);
ti->mThread->mNotAThread = true;
ti->mThread->ti_copy = 0;
@ -186,10 +177,9 @@ void * thread::wrapper_function(void * aArg)
delete ti;
return 0;
}
}
thread::thread(void (*aFunction)(void *), void * aArg)
{
thread::thread(void (*aFunction)(void *), void * aArg) {
// Serialize access to this thread structure
lock_guard<mutex> guard(mDataMutex);
@ -208,32 +198,28 @@ thread::thread(void (*aFunction)(void *), void * aArg)
#if defined(_TTHREAD_WIN32_)
mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID);
#elif defined(_TTHREAD_POSIX_)
if(pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0)
if (pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0)
mHandle = 0;
#endif
// Did we fail to create the thread?
if(!mHandle)
{
if (!mHandle) {
mNotAThread = true;
ti_copy = 0;
delete ti;
}
}
}
thread::~thread()
{
if (ti_copy){
thread::~thread() {
if (ti_copy) {
((_thread_start_info *)ti_copy)->mThread = 0;
}
if(joinable())
if (joinable())
std::terminate();
}
}
void thread::join()
{
if(joinable())
{
void thread::join() {
if (joinable()) {
#if defined(_TTHREAD_WIN32_)
WaitForSingleObject(mHandle, INFINITE);
CloseHandle(mHandle);
@ -241,21 +227,18 @@ void thread::join()
pthread_join(mHandle, NULL);
#endif
}
}
}
bool thread::joinable() const
{
bool thread::joinable() const {
mDataMutex.lock();
bool result = !mNotAThread;
mDataMutex.unlock();
return result;
}
}
void thread::detach()
{
void thread::detach() {
mDataMutex.lock();
if(!mNotAThread)
{
if (!mNotAThread) {
#if defined(_TTHREAD_WIN32_)
CloseHandle(mHandle);
#elif defined(_TTHREAD_POSIX_)
@ -264,21 +247,19 @@ void thread::detach()
mNotAThread = true;
}
mDataMutex.unlock();
}
}
thread::id thread::get_id() const
{
if(!joinable())
thread::id thread::get_id() const {
if (!joinable())
return id();
#if defined(_TTHREAD_WIN32_)
return id((unsigned long int) mWin32ThreadID);
#elif defined(_TTHREAD_POSIX_)
return _pthread_t_to_ID(mHandle);
#endif
}
}
unsigned thread::hardware_concurrency()
{
unsigned thread::hardware_concurrency() {
#if defined(_TTHREAD_WIN32_)
SYSTEM_INFO si;
GetSystemInfo(&si);
@ -292,20 +273,19 @@ unsigned thread::hardware_concurrency()
// hardware cores could not be determined.
return 0;
#endif
}
}
//------------------------------------------------------------------------------
// this_thread
//------------------------------------------------------------------------------
thread::id this_thread::get_id()
{
thread::id this_thread::get_id() {
#if defined(_TTHREAD_WIN32_)
return thread::id((unsigned long int) GetCurrentThreadId());
#elif defined(_TTHREAD_POSIX_)
return _pthread_t_to_ID(pthread_self());
#endif
}
}
}

View file

@ -57,30 +57,30 @@ freely, subject to the following restrictions:
// Which platform are we on?
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
#define _TTHREAD_WIN32_
#else
#define _TTHREAD_POSIX_
#endif
#define _TTHREAD_PLATFORM_DEFINED_
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
#define _TTHREAD_WIN32_
#else
#define _TTHREAD_POSIX_
#endif
#define _TTHREAD_PLATFORM_DEFINED_
#endif
// Platform specific includes
#if defined(_TTHREAD_WIN32_)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define __UNDEF_LEAN_AND_MEAN
#endif
#include <windows.h>
#ifdef __UNDEF_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#undef __UNDEF_LEAN_AND_MEAN
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define __UNDEF_LEAN_AND_MEAN
#endif
#include <windows.h>
#ifdef __UNDEF_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#undef __UNDEF_LEAN_AND_MEAN
#endif
#else
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#endif
// Generic includes
@ -95,21 +95,21 @@ freely, subject to the following restrictions:
// Do we have a fully featured C++11 compiler?
#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L))
#define _TTHREAD_CPP11_
#define _TTHREAD_CPP11_
#endif
// ...at least partial C++11?
#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
#define _TTHREAD_CPP11_PARTIAL_
#define _TTHREAD_CPP11_PARTIAL_
#endif
// Macro for disabling assignments of objects.
#ifdef _TTHREAD_CPP11_PARTIAL_
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&) = delete; \
name& operator=(const name&) = delete;
#else
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&); \
name& operator=(const name&);
#endif
@ -136,11 +136,11 @@ freely, subject to the following restrictions:
/// @hideinitializer
#if !defined(_TTHREAD_CPP11_) && !defined(thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define thread_local __thread
#else
#define thread_local __declspec(thread)
#endif
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define thread_local __thread
#else
#define thread_local __declspec(thread)
#endif
#endif
@ -156,7 +156,7 @@ namespace tthread {
/// program may deadlock if the thread that owns a mutex object calls lock()
/// on that object).
/// @see recursive_mutex
class mutex {
class mutex {
public:
/// Constructor.
mutex()
@ -172,8 +172,7 @@ class mutex {
}
/// Destructor.
~mutex()
{
~mutex() {
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mHandle);
#else
@ -185,11 +184,10 @@ class mutex {
/// The method will block the calling thread until a lock on the mutex can
/// be obtained. The mutex remains locked until @c unlock() is called.
/// @see lock_guard
inline void lock()
{
inline void lock() {
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mHandle);
while(mAlreadyLocked) Sleep(1000); // Simulate deadlock...
while (mAlreadyLocked) Sleep(1000); // Simulate deadlock...
mAlreadyLocked = true;
#else
pthread_mutex_lock(&mHandle);
@ -201,12 +199,10 @@ class mutex {
/// return immediately (non-blocking).
/// @return @c true if the lock was acquired, or @c false if the lock could
/// not be acquired.
inline bool try_lock()
{
inline bool try_lock() {
#if defined(_TTHREAD_WIN32_)
bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
if(ret && mAlreadyLocked)
{
if (ret && mAlreadyLocked) {
LeaveCriticalSection(&mHandle);
ret = false;
}
@ -219,8 +215,7 @@ class mutex {
/// Unlock the mutex.
/// If any threads are waiting for the lock on this mutex, one of them will
/// be unblocked.
inline void unlock()
{
inline void unlock() {
#if defined(_TTHREAD_WIN32_)
mAlreadyLocked = false;
LeaveCriticalSection(&mHandle);
@ -240,7 +235,7 @@ class mutex {
#endif
friend class condition_variable;
};
};
/// Recursive mutex class.
/// This is a mutual exclusion object for synchronizing access to shared
@ -248,11 +243,10 @@ class mutex {
/// may lock the mutex several times, as long as it unlocks the mutex the same
/// number of times).
/// @see mutex
class recursive_mutex {
class recursive_mutex {
public:
/// Constructor.
recursive_mutex()
{
recursive_mutex() {
#if defined(_TTHREAD_WIN32_)
InitializeCriticalSection(&mHandle);
#else
@ -264,8 +258,7 @@ class recursive_mutex {
}
/// Destructor.
~recursive_mutex()
{
~recursive_mutex() {
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mHandle);
#else
@ -277,8 +270,7 @@ class recursive_mutex {
/// The method will block the calling thread until a lock on the mutex can
/// be obtained. The mutex remains locked until @c unlock() is called.
/// @see lock_guard
inline void lock()
{
inline void lock() {
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mHandle);
#else
@ -291,8 +283,7 @@ class recursive_mutex {
/// return immediately (non-blocking).
/// @return @c true if the lock was acquired, or @c false if the lock could
/// not be acquired.
inline bool try_lock()
{
inline bool try_lock() {
#if defined(_TTHREAD_WIN32_)
return TryEnterCriticalSection(&mHandle) ? true : false;
#else
@ -303,8 +294,7 @@ class recursive_mutex {
/// Unlock the mutex.
/// If any threads are waiting for the lock on this mutex, one of them will
/// be unblocked.
inline void unlock()
{
inline void unlock() {
#if defined(_TTHREAD_WIN32_)
LeaveCriticalSection(&mHandle);
#else
@ -322,7 +312,7 @@ class recursive_mutex {
#endif
friend class condition_variable;
};
};
/// Lock guard class.
/// The constructor locks the mutex, and the destructor unlocks the mutex, so
@ -339,30 +329,28 @@ class recursive_mutex {
/// }
/// @endcode
template <class T>
class lock_guard {
template <class T>
class lock_guard {
public:
typedef T mutex_type;
lock_guard() : mMutex(0) {}
/// The constructor locks the mutex.
explicit lock_guard(mutex_type &aMutex)
{
explicit lock_guard(mutex_type & aMutex) {
mMutex = &aMutex;
mMutex->lock();
}
/// The destructor unlocks the mutex.
~lock_guard()
{
if(mMutex)
~lock_guard() {
if (mMutex)
mMutex->unlock();
}
private:
mutex_type * mMutex;
};
};
/// Condition variable class.
/// This is a signalling object for synchronizing the execution flow for
@ -389,14 +377,13 @@ class lock_guard {
/// cond.notify_all();
/// }
/// @endcode
class condition_variable {
class condition_variable {
public:
/// Constructor.
#if defined(_TTHREAD_WIN32_)
condition_variable();
#else
condition_variable()
{
condition_variable() {
pthread_cond_init(&mHandle, NULL);
}
#endif
@ -405,8 +392,7 @@ class condition_variable {
#if defined(_TTHREAD_WIN32_)
~condition_variable();
#else
~condition_variable()
{
~condition_variable() {
pthread_cond_destroy(&mHandle);
}
#endif
@ -417,8 +403,7 @@ class condition_variable {
/// @param[in] aMutex A mutex that will be unlocked when the wait operation
/// starts, an locked again as soon as the wait operation is finished.
template <class _mutexT>
inline void wait(_mutexT &aMutex)
{
inline void wait(_mutexT & aMutex) {
#if defined(_TTHREAD_WIN32_)
// Increment number of waiters
EnterCriticalSection(&mWaitersCountLock);
@ -443,8 +428,7 @@ class condition_variable {
#if defined(_TTHREAD_WIN32_)
void notify_one();
#else
inline void notify_one()
{
inline void notify_one() {
pthread_cond_signal(&mHandle);
}
#endif
@ -457,8 +441,7 @@ class condition_variable {
#if defined(_TTHREAD_WIN32_)
void notify_all();
#else
inline void notify_all()
{
inline void notify_all() {
pthread_cond_broadcast(&mHandle);
}
#endif
@ -474,11 +457,11 @@ class condition_variable {
#else
pthread_cond_t mHandle;
#endif
};
};
/// Thread class.
class thread {
class thread {
public:
#if defined(_TTHREAD_WIN32_)
typedef HANDLE native_handle_type;
@ -536,8 +519,7 @@ class thread {
/// Get the native handle for this thread.
/// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
/// is a @c pthread_t.
inline native_handle_type native_handle()
{
inline native_handle_type native_handle() {
return mHandle;
}
@ -565,12 +547,12 @@ class thread {
#else
static void * wrapper_function(void * aArg);
#endif
};
};
/// Thread ID.
/// The thread ID is a unique identifier for each thread.
/// @see thread::get_id()
class thread::id {
class thread::id {
public:
/// Default constructor.
/// The default constructed ID is that of thread without a thread of
@ -579,68 +561,62 @@ class thread::id {
id(unsigned long int aId) : mId(aId) {};
id(const id& aId) : mId(aId.mId) {};
id(const id & aId) : mId(aId.mId) {};
inline id & operator=(const id &aId)
{
inline id & operator=(const id & aId) {
mId = aId.mId;
return *this;
}
inline friend bool operator==(const id &aId1, const id &aId2)
{
inline friend bool operator==(const id & aId1, const id & aId2) {
return (aId1.mId == aId2.mId);
}
inline friend bool operator!=(const id &aId1, const id &aId2)
{
inline friend bool operator!=(const id & aId1, const id & aId2) {
return (aId1.mId != aId2.mId);
}
inline friend bool operator<=(const id &aId1, const id &aId2)
{
inline friend bool operator<=(const id & aId1, const id & aId2) {
return (aId1.mId <= aId2.mId);
}
inline friend bool operator<(const id &aId1, const id &aId2)
{
inline friend bool operator<(const id & aId1, const id & aId2) {
return (aId1.mId < aId2.mId);
}
inline friend bool operator>=(const id &aId1, const id &aId2)
{
inline friend bool operator>=(const id & aId1, const id & aId2) {
return (aId1.mId >= aId2.mId);
}
inline friend bool operator>(const id &aId1, const id &aId2)
{
inline friend bool operator>(const id & aId1, const id & aId2) {
return (aId1.mId > aId2.mId);
}
inline friend std::ostream& operator <<(std::ostream &os, const id &obj)
{
inline friend std::ostream & operator <<(std::ostream & os, const id & obj) {
os << obj.mId;
return os;
}
private:
unsigned long int mId;
};
};
// Related to <ratio> - minimal to be able to support chrono.
typedef long long __intmax_t;
typedef long long __intmax_t;
/// Minimal implementation of the @c ratio class. This class provides enough
/// functionality to implement some basic @c chrono classes.
template <__intmax_t N, __intmax_t D = 1> class ratio {
template <__intmax_t N, __intmax_t D = 1> class ratio {
public:
static double _as_double() { return double(N) / double(D); }
};
static double _as_double() {
return double(N) / double(D);
}
};
/// Minimal implementation of the @c chrono namespace.
/// The @c chrono namespace provides types for specifying time intervals.
namespace chrono {
namespace chrono {
/// Duration template class. This class provides enough functionality to
/// implement @c this_thread::sleep_for().
template <class _Rep, class _Period = ratio<1> > class duration {
@ -652,11 +628,10 @@ namespace chrono {
/// Construct a duration object with the given duration.
template <class _Rep2>
explicit duration(const _Rep2& r) : rep_(r) {};
explicit duration(const _Rep2 & r) : rep_(r) {};
/// Return the value of the duration object.
rep count() const
{
rep count() const {
return rep_;
}
};
@ -668,19 +643,18 @@ namespace chrono {
typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds.
typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes.
typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours.
}
}
/// The namespace @c this_thread provides methods for dealing with the
/// calling thread.
namespace this_thread {
namespace this_thread {
/// Return the thread ID of the calling thread.
thread::id get_id();
/// Yield execution to another thread.
/// Offers the operating system the opportunity to schedule another thread
/// that is ready to run on the current processor.
inline void yield()
{
inline void yield() {
#if defined(_TTHREAD_WIN32_)
Sleep(0);
#else
@ -697,15 +671,14 @@ namespace this_thread {
/// @endcode
/// @note Supported duration types are: nanoseconds, microseconds,
/// milliseconds, seconds, minutes and hours.
template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period>& aTime)
{
template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period> & aTime) {
#if defined(_TTHREAD_WIN32_)
Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
#else
usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
#endif
}
}
}
}

8
lib/ts_packet.cpp Executable file → Normal file
View file

@ -36,9 +36,9 @@ namespace TS {
/// It fills the content with the next 188 bytes int he file.
/// \param Data The data to be read into the packet.
/// \return true if it was possible to read in a full packet, false otherwise.
bool Packet::FromFile(FILE * data){
bool Packet::FromFile(FILE * data) {
strBuf.resize(188);
if (!fread((void*)strBuf.data(), 188, 1, data)){
if (!fread((void *)strBuf.data(), 188, 1, data)) {
return false;
}
return true;
@ -577,12 +577,12 @@ namespace TS {
///Gets the payload of this packet, as a raw char array
///\return The payload of this ts packet as a char pointer
const char * Packet::getPayload() {
return strBuf.data() + (4 + (AdaptationField( ) > 1 ? AdaptationFieldLen() + 1 : 0));
return strBuf.data() + (4 + (AdaptationField() > 1 ? AdaptationFieldLen() + 1 : 0));
}
///Gets the length of the payload for this apcket
///\return The amount of bytes payload in this packet
int Packet::getPayloadLength(){
int Packet::getPayloadLength() {
return 184 - ((AdaptationField() > 1 ? AdaptationFieldLen() + 1 : 0));
}

6
lib/ts_packet.h Executable file → Normal file
View file

@ -168,7 +168,8 @@ namespace TS {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
/// A standard Program Mapping Table, as generated by FFMPEG.
/// Contains both Audio and Video mappings, works also on video- or audio-only streams.
@ -198,7 +199,8 @@ namespace TS {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
} //TS namespace

View file

@ -10,143 +10,143 @@
#include <cstdio>
#include <iostream>
namespace vorbis{
long long unsigned int reverseByte16(long long unsigned int input){
namespace vorbis {
long long unsigned int reverseByte16(long long unsigned int input) {
return ((input & 0xFF00) >> 8) | ((input & 0xFF) << 8);
}
long long unsigned int reverseByte24(long long unsigned int input){
return ((input & 0xFF0000) >> 16)| (input & 0xFF00) | ((input & 0xFF) << 16);
long long unsigned int reverseByte24(long long unsigned int input) {
return ((input & 0xFF0000) >> 16) | (input & 0xFF00) | ((input & 0xFF) << 16);
}
long long unsigned int reverseByte32(long long unsigned int input){
return ((input & 0xFF000000) >> 24)| ((input & 0xFF0000) >> 8) | ((input & 0xFF00) << 8) | ((input & 0xFF) << 24);
long long unsigned int reverseByte32(long long unsigned int input) {
return ((input & 0xFF000000) >> 24) | ((input & 0xFF0000) >> 8) | ((input & 0xFF00) << 8) | ((input & 0xFF) << 24);
}
header::header(){
header::header() {
data = NULL;
datasize = 0;
}
header::header(char * newData, unsigned int length){
header::header(char * newData, unsigned int length) {
data = NULL;
datasize = 0;
read(newData, length);
}
int header::getHeaderType(){
int header::getHeaderType() {
return (int)(data[0]);
}
long unsigned int header::getVorbisVersion(){
if (getHeaderType() == 1){
long unsigned int header::getVorbisVersion() {
if (getHeaderType() == 1) {
return getInt32(7);
}else{
} else {
return 0;
}
}
char header::getAudioChannels(){
if (getHeaderType() == 1){
char header::getAudioChannels() {
if (getHeaderType() == 1) {
return data[11];
}else{
} else {
return 0;
}
}
long unsigned int header::getAudioSampleRate(){
if (getHeaderType() == 1){
long unsigned int header::getAudioSampleRate() {
if (getHeaderType() == 1) {
return ntohl(getInt32(12));
}else{
} else {
return 0;
}
}
long unsigned int header::getBitrateMaximum(){
if (getHeaderType() == 1){
long unsigned int header::getBitrateMaximum() {
if (getHeaderType() == 1) {
return getInt32(16);
}else{
} else {
return 0;
}
}
long unsigned int header::getBitrateNominal(){
if (getHeaderType() == 1){
long unsigned int header::getBitrateNominal() {
if (getHeaderType() == 1) {
return getInt32(20);
}else{
} else {
return 0;
}
}
long unsigned int header::getBitrateMinimum(){
if (getHeaderType() == 1){
long unsigned int header::getBitrateMinimum() {
if (getHeaderType() == 1) {
return getInt32(24);
}else{
} else {
return 0;
}
}
char header::getBlockSize0(){
if (getHeaderType() == 1){
char header::getBlockSize0() {
if (getHeaderType() == 1) {
return data[28] & 0x0F;
}else{
} else {
return 0;
}
}
char header::getBlockSize1(){
if (getHeaderType() == 1){
return (data[28]>>4) & 0x0F;
}else{
char header::getBlockSize1() {
if (getHeaderType() == 1) {
return (data[28] >> 4) & 0x0F;
} else {
return 0;
}
}
char header::getFramingFlag(){
if (getHeaderType() == 1){
char header::getFramingFlag() {
if (getHeaderType() == 1) {
return data[29];
}else{
} else {
return 0;
}
}
bool header::checkDataSize(unsigned int size){
if (size > datasize){
void* tmp = realloc(data,size);
if (tmp){
data = (char*)tmp;
bool header::checkDataSize(unsigned int size) {
if (size > datasize) {
void * tmp = realloc(data, size);
if (tmp) {
data = (char *)tmp;
datasize = size;
return true;
}else{
} else {
return false;
}
}else{
} else {
return true;
}
}
bool header::validate(){
switch(getHeaderType()){
bool header::validate() {
switch (getHeaderType()) {
case 1://ID header
if (datasize!=30){
if (datasize != 30) {
return false;
}
if (getVorbisVersion()!=0){
if (getVorbisVersion() != 0) {
return false;
}
if (getAudioChannels()<=0){
if (getAudioChannels() <= 0) {
return false;
};
if (getAudioSampleRate()<=0) {
if (getAudioSampleRate() <= 0) {
return false;
}
if (getBlockSize0()>getBlockSize1()){
if (getBlockSize0() > getBlockSize1()) {
return false;
};
if (getFramingFlag()!=1){
if (getFramingFlag() != 1) {
return false;
};
break;
@ -161,73 +161,73 @@ namespace vorbis{
return true;
}
bool header::read(char* newData, unsigned int length){
if (length < 7){
bool header::read(char * newData, unsigned int length) {
if (length < 7) {
return false;
}
if(memcmp(newData+1, "vorbis", 6)!=0){
if (memcmp(newData + 1, "vorbis", 6) != 0) {
return false;
}
if (checkDataSize(length)){
if (checkDataSize(length)) {
memcpy(data, newData, length);
}else{
} else {
return false;
}
return true;
}
std::deque<mode> header::readModeDeque(char audioChannels){
std::deque<mode> header::readModeDeque(char audioChannels) {
Utils::bitstreamLSBF stream;
stream.append(data,datasize);
stream.append(data, datasize);
stream.skip(28); //skipping common header part
stream.skip(28); //skipping common header part
char codebook_count = stream.get(8) + 1;
for (int i = 0; i < codebook_count; i++){
for (int i = 0; i < codebook_count; i++) {
long long unsigned int CMN = stream.get(24);
if (CMN != 0x564342){
DEBUG_MSG(DLVL_WARN,"Is dit het? VCB != %c%c%c", (char)(CMN >> 16), (char)(CMN >> 8), (char)CMN);
if (CMN != 0x564342) {
DEBUG_MSG(DLVL_WARN, "Is dit het? VCB != %c%c%c", (char)(CMN >> 16), (char)(CMN >> 8), (char)CMN);
exit(1);
}
unsigned short codebook_dimensions = stream.get(16);
unsigned int codebook_entries = stream.get(24);
bool orderedFlag = stream.get(1);
if (!orderedFlag){
if (!orderedFlag) {
bool sparseFlag = stream.get(1);
if (sparseFlag){//sparse flag
if (sparseFlag) { //sparse flag
//sparse handling
for (unsigned int o = 0; o < codebook_entries; o++){
if (stream.get(1)){
for (unsigned int o = 0; o < codebook_entries; o++) {
if (stream.get(1)) {
stream.skip(5);
}
}
}else{
for (unsigned int o = 0; o < codebook_entries; o++){
} else {
for (unsigned int o = 0; o < codebook_entries; o++) {
stream.skip(5);
}
}
}else{
} else {
//ordered handling
stream.skip(5);
for (unsigned int o = 0; o < codebook_entries; o++){
int readnow = (std::log(codebook_entries-o))/(std::log(2))+1;
o+=stream.get(readnow);
for (unsigned int o = 0; o < codebook_entries; o++) {
int readnow = (std::log(codebook_entries - o)) / (std::log(2)) + 1;
o += stream.get(readnow);
}
}
char codebook_lookup_type = stream.get(4);
if (codebook_lookup_type != 0){
if (codebook_lookup_type != 0) {
stream.skip(32);
stream.skip(32);
char codebook_value_bits = stream.get(4) + 1;
stream.skip(1);
unsigned int codebook_lookup_value;
if (codebook_lookup_type == 1){
codebook_lookup_value = std::pow(codebook_entries, (1.0/codebook_dimensions));
}else{
if (codebook_lookup_type == 1) {
codebook_lookup_value = std::pow(codebook_entries, (1.0 / codebook_dimensions));
} else {
codebook_lookup_value = codebook_entries * codebook_dimensions;
}
for (unsigned int i = 0; i < codebook_lookup_value; i++){
for (unsigned int i = 0; i < codebook_lookup_value; i++) {
stream.skip(codebook_value_bits);
}
}
@ -235,44 +235,44 @@ namespace vorbis{
//end of codebooks
//time domain transforms
long long unsigned int TDT = stream.get(6) + 1;
for (unsigned int i = 0; i < TDT; i++){
for (unsigned int i = 0; i < TDT; i++) {
stream.skip(16);
}
//Floors
long long unsigned int floors = stream.get(6) + 1;
for (unsigned int i = 0; i < floors; i++){
for (unsigned int i = 0; i < floors; i++) {
long long unsigned int floorType = stream.get(16);
switch(floorType){
case 0:{
switch (floorType) {
case 0: {
DEBUG_MSG(DLVL_WARN, "FloorType 0 in vorbis setup header not tested!");
stream.skip(8);//order
stream.skip(16);//rate
stream.skip(16);//bark_map_size
stream.skip(6);//amplitude bits
stream.skip(8);//amplitude offset
long long unsigned int numberOfBooks = stream.get(4)+1;
for (unsigned int o = 0; o < numberOfBooks; o++){
long long unsigned int numberOfBooks = stream.get(4) + 1;
for (unsigned int o = 0; o < numberOfBooks; o++) {
stream.skip(8);//book list array
}
break;
}
case 1:{
case 1: {
long long unsigned int floorPartitions = stream.get(5);
long long int max = -1;
std::deque<int> partition_class;
for (unsigned int o = 0; o < floorPartitions; o++){
for (unsigned int o = 0; o < floorPartitions; o++) {
long long int temp = stream.get(4);
partition_class.push_back(temp);
if (temp>max) max = temp;
if (temp > max) max = temp;
}
std::deque<int> class_dimensions;
for (int o = 0; o <= max; o++){
class_dimensions.push_back(stream.get(3)+1);//class dimensions PUT IN ARRAY!
for (int o = 0; o <= max; o++) {
class_dimensions.push_back(stream.get(3) + 1); //class dimensions PUT IN ARRAY!
int class_subclass = stream.get(2);
if (class_subclass !=0){
if (class_subclass != 0) {
stream.skip(8);//class_master_books
}
for (int p = 0; p < (1<<class_subclass); p++){
for (int p = 0; p < (1 << class_subclass); p++) {
stream.skip(8);
}
}
@ -280,9 +280,9 @@ namespace vorbis{
int rangebits = stream.get(4);//rangebits
long long unsigned int count = 0;
long long unsigned int skipper = 0;
for (unsigned int o = 0; o < floorPartitions; o++){
for (unsigned int o = 0; o < floorPartitions; o++) {
count += class_dimensions[(partition_class[o])];
while (skipper < count){
while (skipper < count) {
stream.skip(rangebits);
skipper ++;
}
@ -296,79 +296,79 @@ namespace vorbis{
//Residues
long long unsigned int residues = stream.get(6) + 1;
for(unsigned int i = 0; i < residues; i++){
for (unsigned int i = 0; i < residues; i++) {
std::deque<char> residueCascade;
long long unsigned int residueType = stream.get(16);
if(residueType<=2){
if (residueType <= 2) {
stream.skip(24);//residue begin
stream.skip(24);//residue end
stream.skip(24);//residue partition size
long long unsigned int residueClass = stream.get(6)+1;//residue classifications
long long unsigned int residueClass = stream.get(6) + 1; //residue classifications
stream.skip(8);//residue classbook
for (unsigned int o = 0; o < residueClass; o++){
for (unsigned int o = 0; o < residueClass; o++) {
char temp = stream.get(3);//low bits
bool bitFlag = stream.get(1);
if (bitFlag){
if (bitFlag) {
temp += stream.get(5) << 3;
}
residueCascade.push_back(temp);
}
for (unsigned int o = 0; o < residueClass; o++){
for (unsigned int p = 0; p < 7; p++){
if (((residueCascade[o] >> p) & 1) == 1){
for (unsigned int o = 0; o < residueClass; o++) {
for (unsigned int p = 0; p < 7; p++) {
if (((residueCascade[o] >> p) & 1) == 1) {
stream.skip(8);
}else{
} else {
}
}
}
}else{
} else {
exit(0);
}
}
//Mappings
long long unsigned int mappings = stream.get(6) + 1;
for(unsigned int i = 0; i < mappings; i++){
for (unsigned int i = 0; i < mappings; i++) {
long long unsigned int mapType = stream.get(16);
if (mapType == 0){
if (mapType == 0) {
char mappingSubmaps = 1;
if (stream.get(1)==1){
if (stream.get(1) == 1) {
mappingSubmaps = stream.get(4);//vorbis mapping submaps
}
long long unsigned int coupling_steps = 0;
if (stream.get(1)==1){
coupling_steps = stream.get(8)+1;
for (unsigned int o = 0; o<coupling_steps; o++){
int temp = (std::log((audioChannels-o)-1))/(std::log(2)) + 1;
if (temp>0){
if (stream.get(1) == 1) {
coupling_steps = stream.get(8) + 1;
for (unsigned int o = 0; o < coupling_steps; o++) {
int temp = (std::log((audioChannels - o) - 1)) / (std::log(2)) + 1;
if (temp > 0) {
stream.skip(temp);//mapping magnitude
stream.skip(temp);//mapping angle
}
}
}
char meh = stream.get(2);
if (meh != 0){
if (meh != 0) {
DEBUG_MSG(DLVL_ERROR, "Sanity check ==0 : %i", (int)meh);
exit(0);
}
if (mappingSubmaps > 1){
for (int o = 0; o < audioChannels; o++){
if (mappingSubmaps > 1) {
for (int o = 0; o < audioChannels; o++) {
stream.skip(4);
}
}
for (int o = 0; o < mappingSubmaps; o++){
for (int o = 0; o < mappingSubmaps; o++) {
stream.skip(8);//placeholder
stream.skip(8);//vorbis Mapping subfloor
stream.skip(8);//vorbis mapping submap residue
}
}else{
} else {
exit(0);
}
}
//Modes
long long unsigned int modes = stream.get(6) + 1;
std::deque<mode> retVal;
for (unsigned int i = 0; i < modes; i++){
for (unsigned int i = 0; i < modes; i++) {
mode temp;
temp.blockFlag = stream.get(1);
temp.windowType = stream.get(16);
@ -380,46 +380,46 @@ namespace vorbis{
return retVal;
}
uint32_t header::getInt32(size_t index){
if (datasize >= (index + 3)){
uint32_t header::getInt32(size_t index) {
if (datasize >= (index + 3)) {
return (data[index] << 24) + (data[index + 1] << 16) + (data[index + 2] << 8) + data[index + 3];
}
return 0;
}
uint32_t header::getInt24(size_t index){
if (datasize >= (index + 2)){
uint32_t header::getInt24(size_t index) {
if (datasize >= (index + 2)) {
return 0 + (data[index] << 16) + (data[index + 1] << 8) + data[index + 2];
}
return 0;
}
uint16_t header::getInt16(size_t index){
if (datasize >= (index + 1)){
uint16_t header::getInt16(size_t index) {
if (datasize >= (index + 1)) {
return 0 + (data[index] << 8) + data[index + 1];
}
return 0;
}
std::string header::toPrettyString(size_t indent){
std::string header::toPrettyString(size_t indent) {
std::stringstream r;
r << std::string(indent+1,' ') << "Vorbis Header" << std::endl;
r << std::string(indent+2,' ') << "Magic Number: " << std::string(data + 1,6) << std::endl;
r << std::string(indent+2,' ') << "Header Type: " << getHeaderType() << std::endl;
if (getHeaderType() == 1){
r << std::string(indent+2,' ') << "ID Header" << std::endl;
r << std::string(indent+2,' ') << "VorbisVersion: " << getVorbisVersion() << std::endl;
r << std::string(indent+2,' ') << "AudioChannels: " << (int)getAudioChannels() << std::endl;
r << std::string(indent+2,' ') << "BitrateMaximum: " << std::hex << getBitrateMaximum() << std::dec << std::endl;
r << std::string(indent+2,' ') << "BitrateNominal: " << std::hex << getBitrateNominal() << std::dec << std::endl;
r << std::string(indent+2,' ') << "BitrateMinimum: " << std::hex << getBitrateMinimum() << std::dec << std::endl;
r << std::string(indent+2,' ') << "BlockSize0: " << (int)getBlockSize0() << std::endl;
r << std::string(indent+2,' ') << "BlockSize1: " << (int)getBlockSize1() << std::endl;
r << std::string(indent+2,' ') << "FramingFlag: " << (int)getFramingFlag() << std::endl;
} else if (getHeaderType() == 3){
r << std::string(indent+2,' ') << "Comment Header" << std::endl;
} else if (getHeaderType() == 5){
r << std::string(indent+2,' ') << "Setup Header" << std::endl;
r << std::string(indent + 1, ' ') << "Vorbis Header" << std::endl;
r << std::string(indent + 2, ' ') << "Magic Number: " << std::string(data + 1, 6) << std::endl;
r << std::string(indent + 2, ' ') << "Header Type: " << getHeaderType() << std::endl;
if (getHeaderType() == 1) {
r << std::string(indent + 2, ' ') << "ID Header" << std::endl;
r << std::string(indent + 2, ' ') << "VorbisVersion: " << getVorbisVersion() << std::endl;
r << std::string(indent + 2, ' ') << "AudioChannels: " << (int)getAudioChannels() << std::endl;
r << std::string(indent + 2, ' ') << "BitrateMaximum: " << std::hex << getBitrateMaximum() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "BitrateNominal: " << std::hex << getBitrateNominal() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "BitrateMinimum: " << std::hex << getBitrateMinimum() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "BlockSize0: " << (int)getBlockSize0() << std::endl;
r << std::string(indent + 2, ' ') << "BlockSize1: " << (int)getBlockSize1() << std::endl;
r << std::string(indent + 2, ' ') << "FramingFlag: " << (int)getFramingFlag() << std::endl;
} else if (getHeaderType() == 3) {
r << std::string(indent + 2, ' ') << "Comment Header" << std::endl;
} else if (getHeaderType() == 5) {
r << std::string(indent + 2, ' ') << "Setup Header" << std::endl;
}
return r.str();
}

View file

@ -5,23 +5,23 @@
#include <string>
#include <deque>
namespace vorbis{
struct mode{
namespace vorbis {
struct mode {
bool blockFlag;
unsigned short windowType;
unsigned short transformType;
char mapping;
};
inline unsigned int ilog(unsigned int input){
return (std::log(input))/(std::log(2))+1;
inline unsigned int ilog(unsigned int input) {
return (std::log(input)) / (std::log(2)) + 1;
}
class header{
class header {
public:
header();
header(char* newData, unsigned int length);
bool read(char* newData, unsigned int length);
header(char * newData, unsigned int length);
bool read(char * newData, unsigned int length);
int getHeaderType();
long unsigned int getVorbisVersion();
char getAudioChannels();
@ -40,7 +40,7 @@ namespace vorbis{
uint16_t getInt16(size_t index);
private:
std::deque<mode> modes;
char* data;
char * data;
unsigned int datasize;
bool checkDataSize(unsigned int size);
bool validate();