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

View file

@ -9,40 +9,41 @@
namespace Secure { namespace Secure {
static unsigned char __gbv2keypub_der[] = {0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, static unsigned char __gbv2keypub_der[] = {0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe5, 0xd7, 0x9c, 0x7d, 0x73, 0xc6, 0xe6, 0xfb, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe5, 0xd7, 0x9c, 0x7d, 0x73, 0xc6, 0xe6, 0xfb,
0x35, 0x7e, 0xd7, 0x57, 0x99, 0x07, 0xdb, 0x99, 0x70, 0xc9, 0xd0, 0x3e, 0x53, 0x57, 0x3c, 0x1e, 0x55, 0xda, 0x0f, 0x69, 0xbf, 0x26, 0x79, 0xc7, 0x35, 0x7e, 0xd7, 0x57, 0x99, 0x07, 0xdb, 0x99, 0x70, 0xc9, 0xd0, 0x3e, 0x53, 0x57, 0x3c, 0x1e, 0x55, 0xda, 0x0f, 0x69, 0xbf, 0x26, 0x79, 0xc7,
0xb6, 0xdd, 0x8e, 0x83, 0x32, 0x65, 0x74, 0x0d, 0x74, 0x48, 0x42, 0x49, 0x22, 0x52, 0x58, 0x56, 0xc3, 0xe4, 0x49, 0x5d, 0xac, 0x6a, 0x94, 0xb1, 0xb6, 0xdd, 0x8e, 0x83, 0x32, 0x65, 0x74, 0x0d, 0x74, 0x48, 0x42, 0x49, 0x22, 0x52, 0x58, 0x56, 0xc3, 0xe4, 0x49, 0x5d, 0xac, 0x6a, 0x94, 0xb1,
0x64, 0x14, 0xbf, 0x4d, 0xd5, 0xd7, 0x3a, 0xca, 0x5c, 0x1e, 0x6f, 0x42, 0x30, 0xac, 0x29, 0xaa, 0xa0, 0x85, 0xd2, 0x16, 0xa2, 0x8e, 0x89, 0x12, 0x64, 0x14, 0xbf, 0x4d, 0xd5, 0xd7, 0x3a, 0xca, 0x5c, 0x1e, 0x6f, 0x42, 0x30, 0xac, 0x29, 0xaa, 0xa0, 0x85, 0xd2, 0x16, 0xa2, 0x8e, 0x89, 0x12,
0xc4, 0x92, 0x06, 0xea, 0xed, 0x48, 0xf6, 0xdb, 0xed, 0x4f, 0x62, 0x6c, 0xfa, 0xcf, 0xc2, 0xb9, 0x8d, 0x04, 0xb2, 0xba, 0x63, 0xc9, 0xcc, 0xee, 0xc4, 0x92, 0x06, 0xea, 0xed, 0x48, 0xf6, 0xdb, 0xed, 0x4f, 0x62, 0x6c, 0xfa, 0xcf, 0xc2, 0xb9, 0x8d, 0x04, 0xb2, 0xba, 0x63, 0xc9, 0xcc, 0xee,
0x23, 0x64, 0x46, 0x14, 0x12, 0xc8, 0x38, 0x67, 0x69, 0x6b, 0xaf, 0xd1, 0x7c, 0xb1, 0xb5, 0x79, 0xe4, 0x4e, 0x3a, 0xa7, 0xe8, 0x28, 0x89, 0x25, 0x23, 0x64, 0x46, 0x14, 0x12, 0xc8, 0x38, 0x67, 0x69, 0x6b, 0xaf, 0xd1, 0x7c, 0xb1, 0xb5, 0x79, 0xe4, 0x4e, 0x3a, 0xa7, 0xe8, 0x28, 0x89, 0x25,
0xc0, 0xd0, 0xd8, 0xc7, 0xd2, 0x26, 0xaa, 0xf5, 0xbf, 0x36, 0x55, 0x01, 0x89, 0x58, 0x1f, 0x1e, 0xf5, 0xa5, 0x42, 0x8f, 0x60, 0x2e, 0xc2, 0xd8, 0xc0, 0xd0, 0xd8, 0xc7, 0xd2, 0x26, 0xaa, 0xf5, 0xbf, 0x36, 0x55, 0x01, 0x89, 0x58, 0x1f, 0x1e, 0xf5, 0xa5, 0x42, 0x8f, 0x60, 0x2e, 0xc2, 0xd8,
0x21, 0x0b, 0x6c, 0x8d, 0xbb, 0x72, 0xf2, 0x19, 0x30, 0xe3, 0x4c, 0x3e, 0x80, 0xe7, 0xf2, 0xe3, 0x89, 0x4f, 0xd4, 0xee, 0x96, 0x3e, 0x4a, 0x9b, 0x21, 0x0b, 0x6c, 0x8d, 0xbb, 0x72, 0xf2, 0x19, 0x30, 0xe3, 0x4c, 0x3e, 0x80, 0xe7, 0xf2, 0xe3, 0x89, 0x4f, 0xd4, 0xee, 0x96, 0x3e, 0x4a, 0x9b,
0xe5, 0x16, 0x01, 0xf1, 0x98, 0xc9, 0x0b, 0xd6, 0xdf, 0x8a, 0x64, 0x47, 0xc4, 0x44, 0xcc, 0x92, 0x69, 0x28, 0xee, 0x7d, 0xac, 0xdc, 0x30, 0x56, 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, 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, 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 static unsigned int __gbv2keypub_der_len = 294; ///< Length of GBv2 public key data
/// Attempts to load the GBv2 public key. /// Attempts to load the GBv2 public key.
Auth::Auth(){ Auth::Auth() {
const unsigned char * key = __gbv2keypub_der; 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. /// Attempts to verify RSA signature using the public key.
/// Assumes basesign argument is base64 encoded RSA signature for data. /// Assumes basesign argument is base64 encoded RSA signature for data.
/// Returns true if the data could be verified, false otherwise. /// 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); 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 /// Wrapper function for openssl MD5 implementation
std::string md5(std::string input){ std::string md5(std::string input) {
char tmp[3]; char tmp[3];
std::string ret; std::string ret;
const unsigned char * res = MD5((const unsigned char*)input.c_str(), input.length(), 0); const unsigned char * res = MD5((const unsigned char *)input.c_str(), input.length(), 0);
for (int i = 0; i < 16; ++i){ for (int i = 0; i < 16; ++i) {
snprintf(tmp, 3, "%02x", res[i]); snprintf(tmp, 3, "%02x", res[i]);
ret += tmp; ret += tmp;
} }

View file

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

View file

@ -4,39 +4,39 @@
const std::string Base64::chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const std::string Base64::chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/// Helper for base64_decode function /// 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 == '/')); 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. /// 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. /// \param input Plaintext data to encode.
/// \returns Base64 encoded data. /// \returns Base64 encoded data.
std::string Base64::encode(std::string const input){ std::string Base64::encode(std::string const input) {
std::string ret; std::string ret;
unsigned int in_len = input.size(); unsigned int in_len = input.size();
char quad[4], triple[3]; char quad[4], triple[3];
unsigned int i, x, n = 3; unsigned int i, x, n = 3;
for (x = 0; x < in_len; x = x + 3){ for (x = 0; x < in_len; x = x + 3) {
if ((in_len - x) / 3 == 0){ if ((in_len - x) / 3 == 0) {
n = (in_len - x) % 3; n = (in_len - x) % 3;
} }
for (i = 0; i < 3; i++){ for (i = 0; i < 3; i++) {
triple[i] = '0'; triple[i] = '0';
} }
for (i = 0; i < n; i++){ for (i = 0; i < n; i++) {
triple[i] = input[x + i]; triple[i] = input[x + i];
} }
quad[0] = chars[(triple[0] & 0xFC) >> 2]; // FC = 11111100 quad[0] = chars[(triple[0] & 0xFC) >> 2]; // FC = 11111100
quad[1] = chars[((triple[0] & 0x03) << 4) | ((triple[1] & 0xF0) >> 4)]; // 03 = 11 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[2] = chars[((triple[1] & 0x0F) << 2) | ((triple[2] & 0xC0) >> 6)]; // 0F = 1111, C0=11110
quad[3] = chars[triple[2] & 0x3F]; // 3F = 111111 quad[3] = chars[triple[2] & 0x3F]; // 3F = 111111
if (n < 3){ if (n < 3) {
quad[3] = '='; quad[3] = '=';
} }
if (n < 2){ if (n < 2) {
quad[2] = '='; quad[2] = '=';
} }
for (i = 0; i < 4; i++){ for (i = 0; i < 4; i++) {
ret += quad[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. /// 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. /// \param encoded_string Base64 encoded data to decode.
/// \returns Plaintext decoded data. /// \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 in_len = encoded_string.size();
int i = 0; int i = 0;
int j = 0; int j = 0;
int in_ = 0; int in_ = 0;
unsigned char char_array_4[4], char_array_3[3]; unsigned char char_array_4[4], char_array_3[3];
std::string ret; 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_]; char_array_4[i++ ] = encoded_string[in_];
in_++; in_++;
if (i == 4){ if (i == 4) {
for (i = 0; i < 4; i++){ for (i = 0; i < 4; i++) {
char_array_4[i] = chars.find(char_array_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[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[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]; 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]; ret += char_array_3[i];
} }
i = 0; i = 0;
} }
} }
if (i){ if (i) {
for (j = i; j < 4; j++){ for (j = i; j < 4; j++) {
char_array_4[j] = 0; 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_4[j] = chars.find(char_array_4[j]);
} }
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);

View file

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

View file

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

View file

@ -14,7 +14,7 @@
namespace Util { namespace Util {
/// Deals with parsing configuration from commandline options. /// Deals with parsing configuration from commandline options.
class Config{ class Config {
private: private:
JSON::Value vals; ///< Holds all current config values JSON::Value vals; ///< Holds all current config values
int long_count; int long_count;
@ -49,7 +49,7 @@ namespace Util {
/// Gets all executables in getMyPath that start with "Mist". /// Gets all executables in getMyPath that start with "Mist".
void getMyExec(std::deque<std::string> & execs); void getMyExec(std::deque<std::string> & execs);
/// Will set the active user to the named username. /// Will set the active user to the named username.
void setUser(std::string user); void setUser(std::string user);

View file

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

View file

@ -4,9 +4,9 @@
#include "json.h" #include "json.h"
///\brief A typedef to simplify accessing all codecs ///\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 ///\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 ///\brief A namespace containing all functions for handling the conversion API
namespace Converter { namespace Converter {
@ -28,8 +28,8 @@ namespace Converter {
///\brief Holds a list of all current known codecs ///\brief Holds a list of all current known codecs
converterInfo allCodecs; converterInfo allCodecs;
///\brief Holds a list of all the current conversions ///\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 ///\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. // Defines to print debug messages.
#ifndef MIST_DEBUG #ifndef MIST_DEBUG
#define MIST_DEBUG 1 #define MIST_DEBUG 1
#define DLVL_NONE 0 // All debugging disabled. #define DLVL_NONE 0 // All debugging disabled.
#define DLVL_FAIL 1 // Only messages about failed operations. #define DLVL_FAIL 1 // Only messages about failed operations.
#define DLVL_ERROR 2 // Only messages about errors and failed operations. #define DLVL_ERROR 2 // Only messages about errors and failed operations.
#define DLVL_WARN 3 // Warnings, errors, and fail messages. #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_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_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_MEDIUM 5 // Slightly more than just development-level messages.
#define DLVL_HIGH 6 // Verbose debugging messages. #define DLVL_HIGH 6 // Verbose debugging messages.
#define DLVL_VERYHIGH 7 // Very verbose debugging messages. #define DLVL_VERYHIGH 7 // Very verbose debugging messages.
#define DLVL_EXTREME 8 // Everything is reported in extreme detail. #define DLVL_EXTREME 8 // Everything is reported in extreme detail.
#define DLVL_INSANE 9 // Everything is reported in insane detail. #define DLVL_INSANE 9 // Everything is reported in insane detail.
#define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones. #define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones.
#if DEBUG > -1 #if DEBUG > -1
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include "config.h" #include "config.h"
static const char* DBG_LVL_LIST[] = {"NONE","FAIL","ERROR","WARN","INFO","MEDIUM","HIGH","VERYHIGH","EXTREME","INSANE","DONTEVEN"}; 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 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
#define DEBUG_MSG(lvl, msg, ...) // Debugging disabled. #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
#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__)
#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 #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. unsigned int trackID;///< Stores the track the DTSC packet referenced by this structure is associated with.
}; };
enum packType{ enum packType {
DTSC_INVALID, DTSC_INVALID,
DTSC_HEAD, DTSC_HEAD,
DTSC_V1, DTSC_V1,
@ -67,26 +67,26 @@ namespace DTSC {
/// This class allows scanning through raw binary format DTSC data. /// This class allows scanning through raw binary format DTSC data.
/// It can be used as an iterator or as a direct accessor. /// It can be used as an iterator or as a direct accessor.
class Scan{ class Scan {
public: public:
Scan(); Scan();
Scan(char * pointer, size_t len); Scan(char * pointer, size_t len);
std::string toPrettyString(unsigned int indent = 0); std::string toPrettyString(unsigned int indent = 0);
Scan getMember(std::string indice); Scan getMember(std::string indice);
Scan getMember(const char * indice); Scan getMember(const char * indice);
Scan getMember(const char * indice, const unsigned int ind_len); Scan getMember(const char * indice, const unsigned int ind_len);
Scan getIndice(unsigned int num); Scan getIndice(unsigned int num);
char getType(); char getType();
bool asBool(); bool asBool();
long long asInt(); long long asInt();
std::string asString(); std::string asString();
void getString(char *& result, unsigned int & len); void getString(char *& result, unsigned int & len);
private: private:
char * p; char * p;
size_t len; size_t len;
}; };
/// DTSC::Packets can currently be three types: /// DTSC::Packets can currently be three types:
/// DTSC_HEAD packets are the "DTSC" header string, followed by 4 bytes len and packed content. /// DTSC_HEAD packets are the "DTSC" header string, followed by 4 bytes len and packed content.
/// DTSC_V1 packets are "DTPD", followed by 4 bytes len and packed content. /// DTSC_V1 packets are "DTPD", followed by 4 bytes len and packed content.
@ -125,7 +125,7 @@ namespace DTSC {
unsigned int bufferLen; unsigned int bufferLen;
unsigned int dataLen; unsigned int dataLen;
}; };
/// A simple structure used for ordering byte seek positions. /// A simple structure used for ordering byte seek positions.
struct livePos { struct livePos {
livePos() { livePos() {
@ -375,7 +375,7 @@ namespace DTSC {
private: private:
long int endPos; long int endPos;
void readHeader(int pos); void readHeader(int pos);
DTSC::Packet myPack; DTSC::Packet myPack;
JSON::Value metaStorage; JSON::Value metaStorage;
readOnlyMeta metadata; readOnlyMeta metadata;
std::map<int, std::string> trackMapping; std::map<int, std::string> trackMapping;

File diff suppressed because it is too large Load diff

View file

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

View file

@ -21,7 +21,7 @@
#include <errno.h> #include <errno.h>
namespace Filesystem { namespace Filesystem {
enum DIR_Permissions{ enum DIR_Permissions {
P_LIST = 0x01, //List P_LIST = 0x01, //List
P_RETR = 0x02, //Retrieve P_RETR = 0x02, //Retrieve
P_STOR = 0x04, //Store P_STOR = 0x04, //Store
@ -31,11 +31,11 @@ namespace Filesystem {
P_RMD = 0x40, //Remove directory P_RMD = 0x40, //Remove directory
}; };
enum DIR_Show{ enum DIR_Show {
S_NONE = 0x00, S_ACTIVE = 0x01, S_INACTIVE = 0x02, S_ALL = 0x03, S_NONE = 0x00, S_ACTIVE = 0x01, S_INACTIVE = 0x02, S_ALL = 0x03,
}; };
class Directory{ class Directory {
public: public:
Directory(std::string PathName = "", std::string BasePath = "."); Directory(std::string PathName = "", std::string BasePath = ".");
~Directory(); ~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". 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. /// This class is used to hold, work with and get information about a single FLV tag.
class Tag{ class Tag {
public: public:
int len; ///< Actual length of tag. int len; ///< Actual length of tag.
bool isKeyframe; ///< True if current tag is a video keyframe. bool isKeyframe; ///< True if current tag is a video keyframe.
@ -40,12 +40,12 @@ namespace FLV {
int offset(); int offset();
void offset(int o); void offset(int o);
Tag(); ///< Constructor for a new, empty, tag. Tag(); ///< Constructor for a new, empty, tag.
Tag(const Tag& O); ///< Copy constructor, copies the contents of an existing 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 & 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 RTMPStream::Chunk & O); ///<Copy constructor from a RTMP chunk.
~Tag(); ///< Generic destructor. ~Tag(); ///< Generic destructor.
//loader functions //loader functions
bool ChunkLoader(const RTMPStream::Chunk& O); bool ChunkLoader(const RTMPStream::Chunk & O);
bool DTSCLoader(DTSC::Stream & S); bool DTSCLoader(DTSC::Stream & S);
bool DTSCLoader(DTSC::Packet & packData, DTSC::Track & track); bool DTSCLoader(DTSC::Packet & packData, DTSC::Track & track);
bool DTSCVideoInit(DTSC::Track & video); bool DTSCVideoInit(DTSC::Track & video);

View file

@ -1,6 +1,6 @@
#include "ftp.h" #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; Conn = NewConnection;
MyPassivePort = 0; MyPassivePort = 0;
USER = ""; USER = "";
@ -23,545 +23,545 @@ FTP::User::User(Socket::Connection NewConnection, std::map<std::string, std::str
MyDir.SetVisibility("OnDemand", Filesystem::S_ACTIVE); MyDir.SetVisibility("OnDemand", Filesystem::S_ACTIVE);
JSON::Value MyConfig = JSON::fromFile("/tmp/mist/streamlist"); JSON::Value MyConfig = JSON::fromFile("/tmp/mist/streamlist");
for (JSON::ObjIter it = MyConfig["streams"].ObjBegin(); it != MyConfig["streams"].ObjEnd(); it++){ for (JSON::ObjIter it = MyConfig["streams"].ObjBegin(); it != MyConfig["streams"].ObjEnd(); it++) {
std::string ThisStream = ( *it).second["channel"]["URL"].toString(); std::string ThisStream = (*it).second["channel"]["URL"].toString();
ThisStream.erase(ThisStream.begin()); ThisStream.erase(ThisStream.begin());
ThisStream.erase(ThisStream.end() - 1); ThisStream.erase(ThisStream.end() - 1);
while (ThisStream.find('/') != std::string::npos){ while (ThisStream.find('/') != std::string::npos) {
ThisStream.erase(0, ThisStream.find('/') + 1); ThisStream.erase(0, ThisStream.find('/') + 1);
} }
ActiveStreams.push_back(ThisStream); 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; Commands ThisCmd = CMD_NOCMD;
if (Command.substr(0, 4) == "NOOP"){ if (Command.substr(0, 4) == "NOOP") {
ThisCmd = CMD_NOOP; ThisCmd = CMD_NOOP;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "USER"){ if (Command.substr(0, 4) == "USER") {
ThisCmd = CMD_USER; ThisCmd = CMD_USER;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "PASS"){ if (Command.substr(0, 4) == "PASS") {
ThisCmd = CMD_PASS; ThisCmd = CMD_PASS;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "QUIT"){ if (Command.substr(0, 4) == "QUIT") {
ThisCmd = CMD_QUIT; ThisCmd = CMD_QUIT;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "PORT"){ if (Command.substr(0, 4) == "PORT") {
ThisCmd = CMD_PORT; ThisCmd = CMD_PORT;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "RETR"){ if (Command.substr(0, 4) == "RETR") {
ThisCmd = CMD_RETR; ThisCmd = CMD_RETR;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "STOR"){ if (Command.substr(0, 4) == "STOR") {
ThisCmd = CMD_STOR; ThisCmd = CMD_STOR;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "TYPE"){ if (Command.substr(0, 4) == "TYPE") {
ThisCmd = CMD_TYPE; ThisCmd = CMD_TYPE;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "MODE"){ if (Command.substr(0, 4) == "MODE") {
ThisCmd = CMD_MODE; ThisCmd = CMD_MODE;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "STRU"){ if (Command.substr(0, 4) == "STRU") {
ThisCmd = CMD_STRU; ThisCmd = CMD_STRU;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "EPSV"){ if (Command.substr(0, 4) == "EPSV") {
ThisCmd = CMD_EPSV; ThisCmd = CMD_EPSV;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "PASV"){ if (Command.substr(0, 4) == "PASV") {
ThisCmd = CMD_PASV; ThisCmd = CMD_PASV;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "LIST"){ if (Command.substr(0, 4) == "LIST") {
ThisCmd = CMD_LIST; ThisCmd = CMD_LIST;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "CDUP"){ if (Command.substr(0, 4) == "CDUP") {
ThisCmd = CMD_CDUP; ThisCmd = CMD_CDUP;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "DELE"){ if (Command.substr(0, 4) == "DELE") {
ThisCmd = CMD_DELE; ThisCmd = CMD_DELE;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "RNFR"){ if (Command.substr(0, 4) == "RNFR") {
ThisCmd = CMD_RNFR; ThisCmd = CMD_RNFR;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 4) == "RNTO"){ if (Command.substr(0, 4) == "RNTO") {
ThisCmd = CMD_RNTO; ThisCmd = CMD_RNTO;
Command.erase(0, 5); Command.erase(0, 5);
} }
if (Command.substr(0, 3) == "PWD"){ if (Command.substr(0, 3) == "PWD") {
ThisCmd = CMD_PWD; ThisCmd = CMD_PWD;
Command.erase(0, 4); Command.erase(0, 4);
} }
if (Command.substr(0, 3) == "CWD"){ if (Command.substr(0, 3) == "CWD") {
ThisCmd = CMD_CWD; ThisCmd = CMD_CWD;
Command.erase(0, 4); Command.erase(0, 4);
} }
if (Command.substr(0, 3) == "RMD"){ if (Command.substr(0, 3) == "RMD") {
ThisCmd = CMD_RMD; ThisCmd = CMD_RMD;
Command.erase(0, 4); Command.erase(0, 4);
} }
if (Command.substr(0, 3) == "MKD"){ if (Command.substr(0, 3) == "MKD") {
ThisCmd = CMD_MKD; ThisCmd = CMD_MKD;
Command.erase(0, 4); Command.erase(0, 4);
} }
if (ThisCmd != CMD_RNTO){ if (ThisCmd != CMD_RNTO) {
RNFR = ""; RNFR = "";
} }
switch (ThisCmd){ switch (ThisCmd) {
case CMD_NOOP: { case CMD_NOOP: {
return 200; //Command okay. return 200; //Command okay.
break; break;
} }
case CMD_USER: { case CMD_USER: {
USER = "";
PASS = "";
if (Command == ""){
return 501;
} //Syntax error in parameters or arguments.
USER = Command;
return 331; //User name okay, need password.
break;
}
case CMD_PASS: {
if (USER == ""){
return 503;
} //Bad sequence of commands
if (Command == ""){
return 501;
} //Syntax error in parameters or arguments.
PASS = Command;
if ( !LoggedIn()){
USER = ""; USER = "";
PASS = ""; PASS = "";
return 530; //Not logged in. if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
USER = Command;
return 331; //User name okay, need password.
break;
}
case CMD_PASS: {
if (USER == "") {
return 503;
} //Bad sequence of commands
if (Command == "") {
return 501;
} //Syntax error in parameters or arguments.
PASS = Command;
if (!LoggedIn()) {
USER = "";
PASS = "";
return 530; //Not logged in.
}
return 230;
break;
} }
return 230;
break;
}
case CMD_LIST: { case CMD_LIST: {
Socket::Connection Connected = Passive.accept(); Socket::Connection Connected = Passive.accept();
if (Connected.connected()){ if (Connected.connected()) {
Conn.Send("125 Data connection already open; transfer starting.\n"); Conn.Send("125 Data connection already open; transfer starting.\n");
}else{ } else {
Conn.Send("150 File status okay; about to open data connection.\n"); Conn.Send("150 File status okay; about to open data connection.\n");
}
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string tmpstr = MyDir.LIST(ActiveStreams);
Connected.Send(tmpstr);
Connected.close();
return 226;
break;
} }
while ( !Connected.connected()){
Connected = Passive.accept();
}
std::string tmpstr = MyDir.LIST(ActiveStreams);
Connected.Send(tmpstr);
Connected.close();
return 226;
break;
}
case CMD_QUIT: { case CMD_QUIT: {
return 221; //Service closing control connection. Logged out if appropriate. return 221; //Service closing control connection. Logged out if appropriate.
break; break;
} }
case CMD_PORT: { case CMD_PORT: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
PORT = atoi(Command.c_str()); PORT = atoi(Command.c_str());
return 200; //Command okay. return 200; //Command okay.
break; break;
} }
case CMD_EPSV: { case CMD_EPSV: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
MyPassivePort = (rand() % 9999); MyPassivePort = (rand() % 9999);
Passive = Socket::Server(MyPassivePort, "0.0.0.0", true); Passive = Socket::Server(MyPassivePort, "0.0.0.0", true);
return 229; return 229;
break; break;
} }
case CMD_PASV: { case CMD_PASV: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
MyPassivePort = (rand() % 9999) + 49152; MyPassivePort = (rand() % 9999) + 49152;
Passive = Socket::Server(MyPassivePort, "0.0.0.0", true); Passive = Socket::Server(MyPassivePort, "0.0.0.0", true);
return 227; return 227;
break; break;
} }
case CMD_RETR: { case CMD_RETR: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_RETR)){ if (!MyDir.HasPermission(Filesystem::P_RETR)) {
return 550; return 550;
} //Access denied. } //Access denied.
Socket::Connection Connected = Passive.accept(); Socket::Connection Connected = Passive.accept();
if (Connected.connected()){ if (Connected.connected()) {
Conn.Send("125 Data connection already open; transfer starting.\n"); Conn.Send("125 Data connection already open; transfer starting.\n");
}else{ } else {
Conn.Send("150 File status okay; about to open data connection.\n"); Conn.Send("150 File status okay; about to open data connection.\n");
}
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string tmpstr = MyDir.RETR(Command);
Connected.Send(tmpstr);
Connected.close();
return 226;
break;
} }
while ( !Connected.connected()){
Connected = Passive.accept();
}
std::string tmpstr = MyDir.RETR(Command);
Connected.Send(tmpstr);
Connected.close();
return 226;
break;
}
case CMD_STOR: { case CMD_STOR: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_STOR)){ if (!MyDir.HasPermission(Filesystem::P_STOR)) {
return 550; return 550;
} //Access denied. } //Access denied.
Socket::Connection Connected = Passive.accept(); Socket::Connection Connected = Passive.accept();
if (Connected.connected()){ if (Connected.connected()) {
Conn.Send("125 Data connection already open; transfer starting.\n"); Conn.Send("125 Data connection already open; transfer starting.\n");
}else{ } else {
Conn.Send("150 File status okay; about to open data connection.\n"); Conn.Send("150 File status okay; about to open data connection.\n");
}
while (!Connected.connected()) {
Connected = Passive.accept();
}
std::string Buffer;
while (Connected.spool()) {
}
/// \todo Comment me back in. ^_^
//Buffer = Connected.Received();
MyDir.STOR(Command, Buffer);
return 250;
break;
} }
while ( !Connected.connected()){
Connected = Passive.accept();
}
std::string Buffer;
while (Connected.spool()){
}
/// \todo Comment me back in. ^_^
//Buffer = Connected.Received();
MyDir.STOR(Command, Buffer);
return 250;
break;
}
case CMD_TYPE: { case CMD_TYPE: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if (Command.size() != 1 && Command.size() != 3){ if (Command.size() != 1 && Command.size() != 3) {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
switch (Command[0]){ switch (Command[0]) {
case 'A': { case 'A': {
if (Command.size() > 1){ if (Command.size() > 1) {
if (Command[1] != ' '){ if (Command[1] != ' ') {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if (Command[2] != 'N'){ if (Command[2] != 'N') {
return 504; return 504;
} //Command not implemented for that parameter. } //Command not implemented for that parameter.
} }
TYPE = TYPE_ASCII_NONPRINT; TYPE = TYPE_ASCII_NONPRINT;
break; break;
} }
case 'I': { case 'I': {
if (Command.size() > 1){ if (Command.size() > 1) {
if (Command[1] != ' '){ if (Command[1] != ' ') {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if (Command[2] != 'N'){ if (Command[2] != 'N') {
return 504; return 504;
} //Command not implemented for that parameter. } //Command not implemented for that parameter.
} }
TYPE = TYPE_IMAGE_NONPRINT; TYPE = TYPE_IMAGE_NONPRINT;
break; break;
} }
default: { default: {
return 504; //Command not implemented for that parameter. return 504; //Command not implemented for that parameter.
break; break;
}
} }
return 200; //Command okay.
break;
} }
return 200; //Command okay.
break;
}
case CMD_MODE: { case CMD_MODE: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if (Command.size() != 1){ if (Command.size() != 1) {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if (Command[0] != 'S'){ if (Command[0] != 'S') {
return 504; return 504;
} //Command not implemented for that parameter. } //Command not implemented for that parameter.
MODE = MODE_STREAM; MODE = MODE_STREAM;
return 200; //Command okay. return 200; //Command okay.
break; break;
} }
case CMD_STRU: { case CMD_STRU: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if (Command.size() != 1){ if (Command.size() != 1) {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
switch (Command[0]){ switch (Command[0]) {
case 'F': { case 'F': {
STRU = STRU_FILE; STRU = STRU_FILE;
break; break;
} }
case 'R': { case 'R': {
STRU = STRU_RECORD; STRU = STRU_RECORD;
break; break;
} }
default: { default: {
return 504; //Command not implemented for that parameter. return 504; //Command not implemented for that parameter.
break; break;
}
} }
return 200; //Command okay.
break;
} }
return 200; //Command okay.
break;
}
case CMD_PWD: { case CMD_PWD: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 550; return 550;
} //Not logged in. } //Not logged in.
if (Command != ""){ if (Command != "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
return 2570; //257 -- 0 to indicate PWD over MKD return 2570; //257 -- 0 to indicate PWD over MKD
break; break;
} }
case CMD_CWD: { case CMD_CWD: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
Filesystem::Directory TmpDir = MyDir; Filesystem::Directory TmpDir = MyDir;
if (TmpDir.CWD(Command)){ if (TmpDir.CWD(Command)) {
if (TmpDir.IsDir()){ if (TmpDir.IsDir()) {
MyDir = TmpDir; MyDir = TmpDir;
return 250; return 250;
}
} }
return 550;
break;
} }
return 550;
break;
}
case CMD_CDUP: { case CMD_CDUP: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command != ""){ if (Command != "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
Filesystem::Directory TmpDir = MyDir; Filesystem::Directory TmpDir = MyDir;
if (TmpDir.CDUP()){ if (TmpDir.CDUP()) {
if (TmpDir.IsDir()){ if (TmpDir.IsDir()) {
MyDir = TmpDir; MyDir = TmpDir;
return 250; return 250;
}
} }
return 550;
break;
} }
return 550;
break;
}
case CMD_DELE: { case CMD_DELE: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if ( !MyDir.DELE(Command)){ if (!MyDir.DELE(Command)) {
return 550; return 550;
}
return 250;
break;
} }
return 250;
break;
}
case CMD_RMD: { case CMD_RMD: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_RMD)){ if (!MyDir.HasPermission(Filesystem::P_RMD)) {
return 550; return 550;
}
if (!MyDir.DELE(Command)) {
return 550;
}
return 250;
break;
} }
if ( !MyDir.DELE(Command)){
return 550;
}
return 250;
break;
}
case CMD_MKD: { case CMD_MKD: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if ( !MyDir.HasPermission(Filesystem::P_MKD)){ if (!MyDir.HasPermission(Filesystem::P_MKD)) {
return 550; return 550;
}
if (!MyDir.MKD(Command)) {
return 550;
}
return 2571;
break;
} }
if ( !MyDir.MKD(Command)){
return 550;
}
return 2571;
break;
}
case CMD_RNFR: { case CMD_RNFR: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
RNFR = Command; RNFR = Command;
return 350; //Awaiting further information return 350; //Awaiting further information
} }
case CMD_RNTO: { case CMD_RNTO: {
if ( !LoggedIn()){ if (!LoggedIn()) {
return 530; return 530;
} //Not logged in. } //Not logged in.
if (Command == ""){ if (Command == "") {
return 501; return 501;
} //Syntax error in parameters or arguments. } //Syntax error in parameters or arguments.
if (RNFR == ""){ if (RNFR == "") {
return 503; return 503;
} //Bad sequence of commands } //Bad sequence of commands
if ( !MyDir.Rename(RNFR, Command)){ if (!MyDir.Rename(RNFR, Command)) {
return 550; return 550;
}
return 250;
} }
return 250;
}
default: { default: {
return 502; //Command not implemented. return 502; //Command not implemented.
break; break;
} }
} }
} }
bool FTP::User::LoggedIn(){ bool FTP::User::LoggedIn() {
if (USER == "" || PASS == ""){ if (USER == "" || PASS == "") {
return false; return false;
} }
if ( !AllCredentials.size()){ if (!AllCredentials.size()) {
return true; return true;
} }
if ((AllCredentials.find(USER) != AllCredentials.end()) && AllCredentials[USER] == PASS){ if ((AllCredentials.find(USER) != AllCredentials.end()) && AllCredentials[USER] == PASS) {
return true; return true;
} }
return false; return false;
} }
std::string FTP::User::NumToMsg(int MsgNum){ std::string FTP::User::NumToMsg(int MsgNum) {
std::string Result; std::string Result;
switch (MsgNum){ switch (MsgNum) {
case 200: { case 200: {
Result = "200 Message okay.\n"; Result = "200 Message okay.\n";
break; break;
} }
case 221: { case 221: {
Result = "221 Service closing control connection. Logged out if appropriate.\n"; Result = "221 Service closing control connection. Logged out if appropriate.\n";
break; break;
} }
case 226: { case 226: {
Result = "226 Closing data connection.\n"; Result = "226 Closing data connection.\n";
break; break;
} }
case 227: { case 227: {
std::stringstream sstr; std::stringstream sstr;
sstr << "227 Entering passive mode (0,0,0,0,"; sstr << "227 Entering passive mode (0,0,0,0,";
sstr << (MyPassivePort >> 8) % 256; sstr << (MyPassivePort >> 8) % 256;
sstr << ","; sstr << ",";
sstr << MyPassivePort % 256; sstr << MyPassivePort % 256;
sstr << ").\n"; sstr << ").\n";
Result = sstr.str(); Result = sstr.str();
break; break;
} }
case 229: { case 229: {
std::stringstream sstr; std::stringstream sstr;
sstr << "229 Entering extended passive mode (|||"; sstr << "229 Entering extended passive mode (|||";
sstr << MyPassivePort; sstr << MyPassivePort;
sstr << "|).\n"; sstr << "|).\n";
Result = sstr.str(); Result = sstr.str();
break; break;
} }
case 230: { case 230: {
Result = "230 User logged in, proceed.\n"; Result = "230 User logged in, proceed.\n";
break; break;
} }
case 250: { case 250: {
Result = "250 Requested file action okay, completed.\n"; Result = "250 Requested file action okay, completed.\n";
break; break;
} }
case 2570: { //PWD case 2570: { //PWD
Result = "257 \"" + MyDir.PWD() + "\" selected as PWD\n"; Result = "257 \"" + MyDir.PWD() + "\" selected as PWD\n";
break; break;
} }
case 2571: { //MKD case 2571: { //MKD
Result = "257 \"" + MyDir.PWD() + "\" created\n"; Result = "257 \"" + MyDir.PWD() + "\" created\n";
break; break;
} }
case 331: { case 331: {
Result = "331 User name okay, need password.\n"; Result = "331 User name okay, need password.\n";
break; break;
} }
case 350: { case 350: {
Result = "350 Requested file action pending further information\n"; Result = "350 Requested file action pending further information\n";
break; break;
} }
case 501: { case 501: {
Result = "501 Syntax error in parameters or arguments.\n"; Result = "501 Syntax error in parameters or arguments.\n";
break; break;
} }
case 502: { case 502: {
Result = "502 Command not implemented.\n"; Result = "502 Command not implemented.\n";
break; break;
} }
case 503: { case 503: {
Result = "503 Bad sequence of commands.\n"; Result = "503 Bad sequence of commands.\n";
break; break;
} }
case 504: { case 504: {
Result = "504 Command not implemented for that parameter.\n"; Result = "504 Command not implemented for that parameter.\n";
break; break;
} }
case 530: { case 530: {
Result = "530 Not logged in.\n"; Result = "530 Not logged in.\n";
break; break;
} }
case 550: { case 550: {
Result = "550 Requested action not taken.\n"; Result = "550 Requested action not taken.\n";
break; break;
} }
default: { default: {
Result = "Error msg not implemented?\n"; Result = "Error msg not implemented?\n";
break; break;
} }
} }
return Result; return Result;
} }

View file

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

View file

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

View file

@ -11,7 +11,7 @@
/// Holds all HTTP processing related code. /// Holds all HTTP processing related code.
namespace HTTP { namespace HTTP {
/// Simple class for reading and writing HTTP 1.0 and 1.1. /// Simple class for reading and writing HTTP 1.0 and 1.1.
class Parser{ class Parser {
public: public:
Parser(); Parser();
bool Read(Socket::Connection & conn); 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 { namespace JSON {
/// Lists all types of JSON::Value. /// Lists all types of JSON::Value.
enum ValueType{ enum ValueType {
EMPTY, BOOL, INTEGER, STRING, ARRAY, OBJECT EMPTY, BOOL, INTEGER, STRING, ARRAY, OBJECT
}; };
@ -28,9 +28,9 @@ namespace JSON {
typedef std::deque<Value>::iterator ArrIter; typedef std::deque<Value>::iterator ArrIter;
typedef std::map<std::string, Value>::const_iterator ObjConstIter; typedef std::map<std::string, Value>::const_iterator ObjConstIter;
typedef std::deque<Value>::const_iterator ArrConstIter; 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. /// A JSON::Value is either a string or an integer, but may also be an object, array or null.
class Value{ class Value {
private: private:
ValueType myType; ValueType myType;
long long int intVal; long long int intVal;
@ -48,15 +48,15 @@ namespace JSON {
Value(long long int val); Value(long long int val);
Value(bool val); Value(bool val);
//comparison operators //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 //assignment operators
Value & operator=(const std::string &rhs); Value & operator=(const std::string & rhs);
Value & operator=(const char * rhs); Value & operator=(const char * rhs);
Value & operator=(const long long int &rhs); Value & operator=(const long long int & rhs);
Value & operator=(const int &rhs); Value & operator=(const int & rhs);
Value & operator=(const unsigned int &rhs); Value & operator=(const unsigned int & rhs);
Value & operator=(const bool &rhs); Value & operator=(const bool & rhs);
//converts to basic types //converts to basic types
operator long long int() const; operator long long int() const;
operator std::string() const; operator std::string() const;
@ -105,22 +105,22 @@ namespace JSON {
}; };
Value fromDTMI2(std::string & data); 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(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 fromString(std::string json);
Value fromFile(std::string filename); Value fromFile(std::string filename);
void fromDTMI2(std::string & data, Value & ret); 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(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> template <typename T>
std::string encodeVector(T begin, T end){ std::string encodeVector(T begin, T end) {
std::string result; std::string result;
for( T it = begin; it != end; it++){ for (T it = begin; it != end; it++) {
long long int tmp = (*it); long long int tmp = (*it);
while(tmp >= 0xFFFF){ while (tmp >= 0xFFFF) {
result += (char)0xFF; result += (char)0xFF;
result += (char)0xFF; result += (char)0xFF;
tmp -= 0xFFFF; tmp -= 0xFFFF;
@ -132,13 +132,13 @@ namespace JSON {
} }
template <typename T> template <typename T>
void decodeVector( std::string input, T & result ){ void decodeVector(std::string input, T & result) {
result.clear(); result.clear();
unsigned int tmp = 0; 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]; unsigned int curLen = (input[i] << 8) + input[i + 1];
tmp += curLen; tmp += curLen;
if (curLen != 0xFFFF){ if (curLen != 0xFFFF) {
result.push_back(tmp); result.push_back(tmp);
tmp = 0; tmp = 0;
} }
@ -146,11 +146,11 @@ namespace JSON {
} }
template <typename T> template <typename T>
std::string encodeVector4(T begin, T end){ std::string encodeVector4(T begin, T end) {
std::string result; std::string result;
for( T it = begin; it != end; it++){ for (T it = begin; it != end; it++) {
long long int tmp = (*it); long long int tmp = (*it);
while(tmp >= 0xFFFFFFFF){ while (tmp >= 0xFFFFFFFF) {
result += (char)0xFF; result += (char)0xFF;
result += (char)0xFF; result += (char)0xFF;
result += (char)0xFF; result += (char)0xFF;
@ -166,13 +166,13 @@ namespace JSON {
} }
template <typename T> template <typename T>
void decodeVector4( std::string input, T & result ){ void decodeVector4(std::string input, T & result) {
result.clear(); result.clear();
unsigned int tmp = 0; unsigned int tmp = 0;
for( int i = 0; i < input.size(); i += 4){ 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]); unsigned int curLen = (input[i] << 24) + (input[i + 1] << 16) + (input[i + 2] << 8) + (input[i + 3]);
tmp += curLen; tmp += curLen;
if (curLen != 0xFFFFFFFF){ if (curLen != 0xFFFFFFFF) {
result.push_back(tmp); result.push_back(tmp);
tmp = 0; 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 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 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. /// If managed, the pointer will be free'd upon destruction.
Box::Box(char * datapointer, bool manage){ Box::Box(char * datapointer, bool manage) {
data = datapointer; data = datapointer;
managed = manage; managed = manage;
payloadOffset = 8; payloadOffset = 8;
if (data == 0){ if (data == 0) {
clear(); clear();
}else{ } else {
data_size = ntohl(((int*)data)[0]); data_size = ntohl(((int *)data)[0]);
}
}
Box::Box(const Box & rs){
data = rs.data;
managed = false;
payloadOffset = rs.payloadOffset;
if (data == 0){
clear();
}else{
data_size = ntohl(((int*)data)[0]);
} }
} }
Box& Box::operator = (const Box & rs){ Box::Box(const Box & rs) {
data = rs.data;
managed = false;
payloadOffset = rs.payloadOffset;
if (data == 0) {
clear();
} else {
data_size = ntohl(((int *)data)[0]);
}
}
Box & Box::operator = (const Box & rs) {
clear(); clear();
data = rs.data; data = rs.data;
managed = false; managed = false;
payloadOffset = rs.payloadOffset; payloadOffset = rs.payloadOffset;
if (data == 0){ if (data == 0) {
clear(); clear();
}else{ } else {
data_size = ntohl(((int*)data)[0]); data_size = ntohl(((int *)data)[0]);
} }
return *this; return *this;
} }
/// If managed, this will free the data pointer. /// If managed, this will free the data pointer.
Box::~Box(){ Box::~Box() {
if (managed && data != 0){ if (managed && data != 0) {
free(data); free(data);
data = 0; data = 0;
} }
} }
/// Returns the values at byte positions 4 through 7. /// Returns the values at byte positions 4 through 7.
std::string Box::getType(){ std::string Box::getType() {
return std::string(data + 4, 4); 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. /// 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); return !memcmp(boxType, data + 4, 4);
} }
/// Reads the first 8 bytes and returns /// 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'}; char retVal[8] = {0, 0, 0, 0, 'e', 'r', 'r', 'o'};
long long unsigned int pos = ftell(newData); long long unsigned int pos = ftell(newData);
fread(retVal,8,1,newData); fread(retVal, 8, 1, newData);
fseek (newData,pos,SEEK_SET); fseek(newData, pos, SEEK_SET);
return std::string(retVal+4,4); return std::string(retVal + 4, 4);
} }
///\todo make good working calcBoxSize with size and payloadoffset calculation ///\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]); return (readVal[0] << 24) | (readVal[1] << 16) | (readVal[2] << 8) | (readVal[3]);
} }
bool skipBox(FILE * newData){ bool skipBox(FILE * newData) {
char readVal[16]; char readVal[16];
long long unsigned int pos = ftell(newData); long long unsigned int pos = ftell(newData);
if (fread(readVal,4,1,newData)){ if (fread(readVal, 4, 1, newData)) {
uint64_t size = calcBoxSize(readVal); uint64_t size = calcBoxSize(readVal);
if (size==1){ if (size == 1) {
if (fread(readVal+4,12,1,newData)){ if (fread(readVal + 4, 12, 1, newData)) {
size = 0 + ntohl(((int*)readVal)[2]); size = 0 + ntohl(((int *)readVal)[2]);
size <<= 32; size <<= 32;
size += ntohl(((int*)readVal)[3]); size += ntohl(((int *)readVal)[3]);
}else{ } else {
return false; return false;
} }
}else if (size==0){ } else if (size == 0) {
fseek(newData, 0, SEEK_END); fseek(newData, 0, SEEK_END);
} }
DEBUG_MSG(DLVL_DEVEL,"skipping size 0x%0.8X",size); DEBUG_MSG(DLVL_DEVEL, "skipping size 0x%0.8X", size);
if (fseek(newData, pos + size, SEEK_SET)==0){ if (fseek(newData, pos + size, SEEK_SET) == 0) {
return true; return true;
}else{ } else {
return false; return false;
} }
}else{ } else {
return false; return false;
} }
} }
bool Box::read(FILE* newData){ bool Box::read(FILE * newData) {
char readVal[16]; char readVal[16];
long long unsigned int pos = ftell(newData); long long unsigned int pos = ftell(newData);
if (fread(readVal,4,1,newData)){ if (fread(readVal, 4, 1, newData)) {
payloadOffset = 8; payloadOffset = 8;
uint64_t size = calcBoxSize(readVal); uint64_t size = calcBoxSize(readVal);
if (size==1){ if (size == 1) {
if (fread(readVal+4,12,1,newData)){ if (fread(readVal + 4, 12, 1, newData)) {
size = 0 + ntohl(((int*)readVal)[2]); size = 0 + ntohl(((int *)readVal)[2]);
size <<= 32; size <<= 32;
size += ntohl(((int*)readVal)[3]); size += ntohl(((int *)readVal)[3]);
payloadOffset = 16; payloadOffset = 16;
}else{ } else {
return false; return false;
} }
} }
fseek (newData,pos,SEEK_SET); fseek(newData, pos, SEEK_SET);
data = (char*)realloc(data, size); data = (char *)realloc(data, size);
data_size = size; data_size = size;
return (fread(data,size,1,newData) == 1); return (fread(data, size, 1, newData) == 1);
}else{ } else {
return false; return false;
} }
} }
/// Reads out a whole box (if possible) from newData, copying to the internal data storage and removing from the input string. /// 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. /// \returns True on success, false otherwise.
bool Box::read(std::string & newData){ bool Box::read(std::string & newData) {
if ( !managed){ if (!managed) {
return false; return false;
} }
if (newData.size() > 4){ if (newData.size() > 4) {
payloadOffset = 8; payloadOffset = 8;
uint64_t size = ntohl(((int*)newData.c_str())[0]); uint64_t size = ntohl(((int *)newData.c_str())[0]);
if (size == 1){ if (size == 1) {
if (newData.size() > 16){ if (newData.size() > 16) {
size = 0 + ntohl(((int*)newData.c_str())[2]); size = 0 + ntohl(((int *)newData.c_str())[2]);
size <<= 32; size <<= 32;
size += ntohl(((int*)newData.c_str())[3]); size += ntohl(((int *)newData.c_str())[3]);
payloadOffset = 16; payloadOffset = 16;
}else{ } else {
return false; return false;
} }
} }
if (newData.size() >= size){ if (newData.size() >= size) {
data = (char*)realloc(data, size); data = (char *)realloc(data, size);
data_size = size; data_size = size;
memcpy(data, newData.data(), size); memcpy(data, newData.data(), size);
newData.erase(0, size); newData.erase(0, size);
@ -168,207 +168,207 @@ namespace MP4 {
} }
/// Returns the total boxed size of this box, including the header. /// Returns the total boxed size of this box, including the header.
uint64_t Box::boxedSize(){ uint64_t Box::boxedSize() {
if (payloadOffset == 16){ if (payloadOffset == 16) {
return ((uint64_t)ntohl(((int*)data)[2]) << 32) + ntohl(((int*)data)[3]); 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. /// Retruns the size of the payload of thix box, excluding the header.
/// This value is defined as boxedSize() - 8. /// This value is defined as boxedSize() - 8.
uint64_t Box::payloadSize(){ uint64_t Box::payloadSize() {
return boxedSize() - payloadOffset; return boxedSize() - payloadOffset;
} }
/// Returns a copy of the data pointer. /// Returns a copy of the data pointer.
char * Box::asBox(){ char * Box::asBox() {
return data; return data;
} }
char * Box::payload(){ char * Box::payload() {
return data + payloadOffset; return data + payloadOffset;
} }
/// Makes this box managed if it wasn't already, resetting the internal storage to 8 bytes (the minimum). /// 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 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. /// If it was somehow impossible to allocate 8 bytes (should never happen), this will cause segfaults later.
void Box::clear(){ void Box::clear() {
if (data && managed){ if (data && managed) {
free(data); free(data);
} }
managed = true; managed = true;
payloadOffset = 8; payloadOffset = 8;
data = (char*)malloc(8); data = (char *)malloc(8);
if (data){ if (data) {
data_size = 8; data_size = 8;
((int*)data)[0] = htonl(data_size); ((int *)data)[0] = htonl(data_size);
}else{ } else {
data_size = 0; data_size = 0;
} }
} }
/// Attempts to typecast this Box to a more specific type and call the toPrettyString() function of that type. /// 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. /// If this failed, it will print out a message saying pretty-printing is not implemented for boxtype.
std::string Box::toPrettyString(uint32_t indent){ std::string Box::toPrettyString(uint32_t indent) {
switch (ntohl( *((int*)(data + 4)))){ //type is at this address switch (ntohl(*((int *)(data + 4)))) { //type is at this address
case 0x6D666864: case 0x6D666864:
return ((MFHD*)this)->toPrettyString(indent); return ((MFHD *)this)->toPrettyString(indent);
break; break;
case 0x6D6F6F66: case 0x6D6F6F66:
return ((MOOF*)this)->toPrettyString(indent); return ((MOOF *)this)->toPrettyString(indent);
break; break;
case 0x61627374: case 0x61627374:
return ((ABST*)this)->toPrettyString(indent); return ((ABST *)this)->toPrettyString(indent);
break; break;
case 0x61667274: case 0x61667274:
return ((AFRT*)this)->toPrettyString(indent); return ((AFRT *)this)->toPrettyString(indent);
break; break;
case 0x61667261: case 0x61667261:
return ((AFRA*)this)->toPrettyString(indent); return ((AFRA *)this)->toPrettyString(indent);
break; break;
case 0x61737274: case 0x61737274:
return ((ASRT*)this)->toPrettyString(indent); return ((ASRT *)this)->toPrettyString(indent);
break; break;
case 0x7472756E: case 0x7472756E:
return ((TRUN*)this)->toPrettyString(indent); return ((TRUN *)this)->toPrettyString(indent);
break; break;
case 0x74726166: case 0x74726166:
return ((TRAF*)this)->toPrettyString(indent); return ((TRAF *)this)->toPrettyString(indent);
break; break;
case 0x74666864: case 0x74666864:
return ((TFHD*)this)->toPrettyString(indent); return ((TFHD *)this)->toPrettyString(indent);
break; break;
case 0x61766343: case 0x61766343:
return ((AVCC*)this)->toPrettyString(indent); return ((AVCC *)this)->toPrettyString(indent);
break; break;
case 0x73647470: case 0x73647470:
return ((SDTP*)this)->toPrettyString(indent); return ((SDTP *)this)->toPrettyString(indent);
break; break;
case 0x66747970: case 0x66747970:
return ((FTYP*)this)->toPrettyString(indent); return ((FTYP *)this)->toPrettyString(indent);
break; break;
case 0x6D6F6F76: case 0x6D6F6F76:
return ((MOOV*)this)->toPrettyString(indent); return ((MOOV *)this)->toPrettyString(indent);
break; break;
case 0x6D766578: case 0x6D766578:
return ((MVEX*)this)->toPrettyString(indent); return ((MVEX *)this)->toPrettyString(indent);
break; break;
case 0x74726578: case 0x74726578:
return ((TREX*)this)->toPrettyString(indent); return ((TREX *)this)->toPrettyString(indent);
break; break;
case 0x6D667261: case 0x6D667261:
return ((MFRA*)this)->toPrettyString(indent); return ((MFRA *)this)->toPrettyString(indent);
break; break;
case 0x7472616B: case 0x7472616B:
return ((TRAK*)this)->toPrettyString(indent); return ((TRAK *)this)->toPrettyString(indent);
break; break;
case 0x6D646961: case 0x6D646961:
return ((MDIA*)this)->toPrettyString(indent); return ((MDIA *)this)->toPrettyString(indent);
break; break;
case 0x6D696E66: case 0x6D696E66:
return ((MINF*)this)->toPrettyString(indent); return ((MINF *)this)->toPrettyString(indent);
break; break;
case 0x64696E66: case 0x64696E66:
return ((DINF*)this)->toPrettyString(indent); return ((DINF *)this)->toPrettyString(indent);
break; break;
case 0x6D66726F: case 0x6D66726F:
return ((MFRO*)this)->toPrettyString(indent); return ((MFRO *)this)->toPrettyString(indent);
break; break;
case 0x68646C72: case 0x68646C72:
return ((HDLR*)this)->toPrettyString(indent); return ((HDLR *)this)->toPrettyString(indent);
break; break;
case 0x766D6864: case 0x766D6864:
return ((VMHD*)this)->toPrettyString(indent); return ((VMHD *)this)->toPrettyString(indent);
break; break;
case 0x736D6864: case 0x736D6864:
return ((SMHD*)this)->toPrettyString(indent); return ((SMHD *)this)->toPrettyString(indent);
break; break;
case 0x686D6864: case 0x686D6864:
return ((HMHD*)this)->toPrettyString(indent); return ((HMHD *)this)->toPrettyString(indent);
break; break;
case 0x6E6D6864: case 0x6E6D6864:
return ((NMHD*)this)->toPrettyString(indent); return ((NMHD *)this)->toPrettyString(indent);
break; break;
case 0x6D656864: case 0x6D656864:
return ((MEHD*)this)->toPrettyString(indent); return ((MEHD *)this)->toPrettyString(indent);
break; break;
case 0x7374626C: case 0x7374626C:
return ((STBL*)this)->toPrettyString(indent); return ((STBL *)this)->toPrettyString(indent);
break; break;
case 0x64726566: case 0x64726566:
return ((DREF*)this)->toPrettyString(indent); return ((DREF *)this)->toPrettyString(indent);
break; break;
case 0x75726C20: case 0x75726C20:
return ((URL*)this)->toPrettyString(indent); return ((URL *)this)->toPrettyString(indent);
break; break;
case 0x75726E20: case 0x75726E20:
return ((URN*)this)->toPrettyString(indent); return ((URN *)this)->toPrettyString(indent);
break; break;
case 0x6D766864: case 0x6D766864:
return ((MVHD*)this)->toPrettyString(indent); return ((MVHD *)this)->toPrettyString(indent);
break; break;
case 0x74667261: case 0x74667261:
return ((TFRA*)this)->toPrettyString(indent); return ((TFRA *)this)->toPrettyString(indent);
break; break;
case 0x746B6864: case 0x746B6864:
return ((TKHD*)this)->toPrettyString(indent); return ((TKHD *)this)->toPrettyString(indent);
break; break;
case 0x6D646864: case 0x6D646864:
return ((MDHD*)this)->toPrettyString(indent); return ((MDHD *)this)->toPrettyString(indent);
break; break;
case 0x73747473: case 0x73747473:
return ((STTS*)this)->toPrettyString(indent); return ((STTS *)this)->toPrettyString(indent);
break; break;
case 0x63747473: case 0x63747473:
return ((CTTS*)this)->toPrettyString(indent); return ((CTTS *)this)->toPrettyString(indent);
break; break;
case 0x73747363: case 0x73747363:
return ((STSC*)this)->toPrettyString(indent); return ((STSC *)this)->toPrettyString(indent);
break; break;
case 0x7374636F: case 0x7374636F:
return ((STCO*)this)->toPrettyString(indent); return ((STCO *)this)->toPrettyString(indent);
break; break;
case 0x7374737A: case 0x7374737A:
return ((STSZ*)this)->toPrettyString(indent); return ((STSZ *)this)->toPrettyString(indent);
break; break;
case 0x73747364: case 0x73747364:
return ((STSD*)this)->toPrettyString(indent); return ((STSD *)this)->toPrettyString(indent);
break; break;
case 0x6D703461://mp4a case 0x6D703461://mp4a
case 0x656E6361://enca case 0x656E6361://enca
return ((MP4A*)this)->toPrettyString(indent); return ((MP4A *)this)->toPrettyString(indent);
break; break;
case 0x61616320: case 0x61616320:
return ((AAC*)this)->toPrettyString(indent); return ((AAC *)this)->toPrettyString(indent);
break; break;
case 0x61766331: case 0x61766331:
return ((AVC1*)this)->toPrettyString(indent); return ((AVC1 *)this)->toPrettyString(indent);
break; break;
case 0x68323634://h264 case 0x68323634://h264
case 0x656E6376://encv case 0x656E6376://encv
return ((H264*)this)->toPrettyString(indent); return ((H264 *)this)->toPrettyString(indent);
break; break;
case 0x65647473: case 0x65647473:
return ((EDTS*)this)->toPrettyString(indent); return ((EDTS *)this)->toPrettyString(indent);
break; break;
case 0x73747373: case 0x73747373:
return ((STSS*)this)->toPrettyString(indent); return ((STSS *)this)->toPrettyString(indent);
break; break;
case 0x6D657461: case 0x6D657461:
return ((META*)this)->toPrettyString(indent); return ((META *)this)->toPrettyString(indent);
break; break;
case 0x656C7374: case 0x656C7374:
return ((ELST*)this)->toPrettyString(indent); return ((ELST *)this)->toPrettyString(indent);
break; break;
case 0x65736473: case 0x65736473:
return ((ESDS*)this)->toPrettyString(indent); return ((ESDS *)this)->toPrettyString(indent);
break; break;
case 0x75647461: case 0x75647461:
return ((UDTA*)this)->toPrettyString(indent); return ((UDTA *)this)->toPrettyString(indent);
break; break;
case 0x75756964: case 0x75756964:
return ((UUID*)this)->toPrettyString(indent); return ((UUID *)this)->toPrettyString(indent);
break; break;
default: default:
break; break;
@ -381,10 +381,10 @@ namespace MP4 {
/// Sets the 8 bits integer at the given index. /// Sets the 8 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed. /// Fails silently if resizing failed.
void Box::setInt8(char newData, size_t index){ void Box::setInt8(char newData, size_t index) {
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()) {
if ( !reserve(index, 0, 1)){ if (!reserve(index, 0, 1)) {
return; return;
} }
} }
@ -394,10 +394,10 @@ namespace MP4 {
/// Gets the 8 bits integer at the given index. /// Gets the 8 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
char Box::getInt8(size_t index){ char Box::getInt8(size_t index) {
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()) {
if ( !reserve(index, 0, 1)){ if (!reserve(index, 0, 1)) {
return 0; return 0;
} }
setInt8(0, index - payloadOffset); setInt8(0, index - payloadOffset);
@ -408,40 +408,40 @@ namespace MP4 {
/// Sets the 16 bits integer at the given index. /// Sets the 16 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed. /// Fails silently if resizing failed.
void Box::setInt16(short newData, size_t index){ void Box::setInt16(short newData, size_t index) {
index += payloadOffset; index += payloadOffset;
if (index + 1 >= boxedSize()){ if (index + 1 >= boxedSize()) {
if ( !reserve(index, 0, 2)){ if (!reserve(index, 0, 2)) {
return; return;
} }
} }
newData = htons(newData); newData = htons(newData);
memcpy(data + index, (char*) &newData, 2); memcpy(data + index, (char *) &newData, 2);
} }
/// Gets the 16 bits integer at the given index. /// Gets the 16 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
short Box::getInt16(size_t index){ short Box::getInt16(size_t index) {
index += payloadOffset; index += payloadOffset;
if (index + 1 >= boxedSize()){ if (index + 1 >= boxedSize()) {
if ( !reserve(index, 0, 2)){ if (!reserve(index, 0, 2)) {
return 0; return 0;
} }
setInt16(0, index - payloadOffset); setInt16(0, index - payloadOffset);
} }
short result; short result;
memcpy((char*) &result, data + index, 2); memcpy((char *) &result, data + index, 2);
return ntohs(result); return ntohs(result);
} }
/// Sets the 24 bits integer at the given index. /// Sets the 24 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed. /// 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; index += payloadOffset;
if (index + 2 >= boxedSize()){ if (index + 2 >= boxedSize()) {
if ( !reserve(index, 0, 3)){ if (!reserve(index, 0, 3)) {
return; return;
} }
} }
@ -453,10 +453,10 @@ namespace MP4 {
/// Gets the 24 bits integer at the given index. /// Gets the 24 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
uint32_t Box::getInt24(size_t index){ uint32_t Box::getInt24(size_t index) {
index += payloadOffset; index += payloadOffset;
if (index + 2 >= boxedSize()){ if (index + 2 >= boxedSize()) {
if ( !reserve(index, 0, 3)){ if (!reserve(index, 0, 3)) {
return 0; return 0;
} }
setInt24(0, index - payloadOffset); setInt24(0, index - payloadOffset);
@ -472,84 +472,84 @@ namespace MP4 {
/// Sets the 32 bits integer at the given index. /// Sets the 32 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed. /// 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; index += payloadOffset;
if (index + 3 >= boxedSize()){ if (index + 3 >= boxedSize()) {
if ( !reserve(index, 0, 4)){ if (!reserve(index, 0, 4)) {
return; return;
} }
} }
newData = htonl(newData); newData = htonl(newData);
memcpy(data + index, (char*) &newData, 4); memcpy(data + index, (char *) &newData, 4);
} }
/// Gets the 32 bits integer at the given index. /// Gets the 32 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
uint32_t Box::getInt32(size_t index){ uint32_t Box::getInt32(size_t index) {
index += payloadOffset; index += payloadOffset;
if (index + 3 >= boxedSize()){ if (index + 3 >= boxedSize()) {
if ( !reserve(index, 0, 4)){ if (!reserve(index, 0, 4)) {
return 0; return 0;
} }
setInt32(0, index - payloadOffset); setInt32(0, index - payloadOffset);
} }
uint32_t result; uint32_t result;
memcpy((char*) &result, data + index, 4); memcpy((char *) &result, data + index, 4);
return ntohl(result); return ntohl(result);
} }
/// Sets the 64 bits integer at the given index. /// Sets the 64 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Fails silently if resizing failed. /// 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; index += payloadOffset;
if (index + 7 >= boxedSize()){ if (index + 7 >= boxedSize()) {
if ( !reserve(index, 0, 8)){ if (!reserve(index, 0, 8)) {
return; return;
} }
} }
((int*)(data + index))[0] = htonl((int)(newData >> 32)); ((int *)(data + index))[0] = htonl((int)(newData >> 32));
((int*)(data + index))[1] = htonl((int)(newData & 0xFFFFFFFF)); ((int *)(data + index))[1] = htonl((int)(newData & 0xFFFFFFFF));
} }
/// Gets the 64 bits integer at the given index. /// Gets the 64 bits integer at the given index.
/// Attempts to resize the data pointer if the index is out of range. /// Attempts to resize the data pointer if the index is out of range.
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
uint64_t Box::getInt64(size_t index){ uint64_t Box::getInt64(size_t index) {
index += payloadOffset; index += payloadOffset;
if (index + 7 >= boxedSize()){ if (index + 7 >= boxedSize()) {
if ( !reserve(index, 0, 8)){ if (!reserve(index, 0, 8)) {
return 0; return 0;
} }
setInt64(0, index - payloadOffset); setInt64(0, index - payloadOffset);
} }
uint64_t result = ntohl(((int*)(data + index))[0]); uint64_t result = ntohl(((int *)(data + index))[0]);
result <<= 32; result <<= 32;
result += ntohl(((int*)(data + index))[1]); result += ntohl(((int *)(data + index))[1]);
return result; return result;
} }
/// Sets the NULL-terminated string at the given index. /// Sets the NULL-terminated string at the given index.
/// Will attempt to resize if the string doesn't fit. /// Will attempt to resize if the string doesn't fit.
/// Fails silently if resizing failed. /// Fails silently if resizing failed.
void Box::setString(std::string newData, size_t index){ void Box::setString(std::string newData, size_t index) {
setString((char*)newData.c_str(), newData.size(), index); setString((char *)newData.c_str(), newData.size(), index);
} }
/// Sets the NULL-terminated string at the given index. /// Sets the NULL-terminated string at the given index.
/// Will attempt to resize if the string doesn't fit. /// Will attempt to resize if the string doesn't fit.
/// Fails silently if resizing failed. /// 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; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()) {
if ( !reserve(index, 0, 1)){ if (!reserve(index, 0, 1)) {
return; return;
} }
data[index] = 0; data[index] = 0;
} }
if (getStringLen(index) != size){ if (getStringLen(index) != size) {
if ( !reserve(index, getStringLen(index) + 1, size + 1)){ if (!reserve(index, getStringLen(index) + 1, size + 1)) {
return; return;
} }
} }
@ -559,10 +559,10 @@ namespace MP4 {
/// Gets the NULL-terminated string at the given index. /// Gets the NULL-terminated string at the given index.
/// Will attempt to resize if the string is out of range. /// Will attempt to resize if the string is out of range.
/// Returns null if resizing failed. /// Returns null if resizing failed.
char * Box::getString(size_t index){ char * Box::getString(size_t index) {
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()) {
if ( !reserve(index, 0, 1)){ if (!reserve(index, 0, 1)) {
return 0; return 0;
} }
data[index] = 0; data[index] = 0;
@ -572,9 +572,9 @@ namespace MP4 {
/// Returns the length of the NULL-terminated string at the given index. /// Returns the length of the NULL-terminated string at the given index.
/// Returns 0 if out of range. /// Returns 0 if out of range.
size_t Box::getStringLen(size_t index){ size_t Box::getStringLen(size_t index) {
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()) {
return 0; return 0;
} }
return strlen(data + index); return strlen(data + index);
@ -584,12 +584,12 @@ namespace MP4 {
/// Do not store or copy this reference, for there will be raptors. /// Do not store or copy this reference, for there will be raptors.
/// Will attempt to resize if out of range. /// Will attempt to resize if out of range.
/// Returns an 8-byte error box if resizing failed. /// Returns an 8-byte error box if resizing failed.
Box & Box::getBox(size_t index){ Box & Box::getBox(size_t index) {
static Box retbox = Box((char*)"\000\000\000\010erro", false); static Box retbox = Box((char *)"\000\000\000\010erro", false);
index += payloadOffset; index += payloadOffset;
if (index + 8 > boxedSize()){ if (index + 8 > boxedSize()) {
if ( !reserve(index, 0, 8)){ if (!reserve(index, 0, 8)) {
retbox = Box((char*)"\000\000\000\010erro", false); retbox = Box((char *)"\000\000\000\010erro", false);
return retbox; return retbox;
} }
memcpy(data + index, "\000\000\000\010erro", 8); 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 the size of the box at the given position.
/// Returns undefined values if there is no box at the given position. /// Returns undefined values if there is no box at the given position.
/// Returns 0 if out of range. /// Returns 0 if out of range.
size_t Box::getBoxLen(size_t index){ size_t Box::getBoxLen(size_t index) {
if ((index + payloadOffset + 8) > boxedSize()){ if ((index + payloadOffset + 8) > boxedSize()) {
return 0; return 0;
} }
return getBox(index).boxedSize(); return getBox(index).boxedSize();
@ -610,10 +610,10 @@ namespace MP4 {
/// Replaces the existing box at the given index by the new box newEntry. /// 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. /// 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 oldlen = getBoxLen(index);
int newlen = newEntry.boxedSize(); int newlen = newEntry.boxedSize();
if (oldlen != newlen && !reserve(index + payloadOffset, oldlen, newlen)){ if (oldlen != newlen && !reserve(index + payloadOffset, oldlen, newlen)) {
return; return;
} }
memcpy(data + index + payloadOffset, newEntry.asBox(), newlen); 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. /// 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. /// This will move any existing data behind the currently reserved space to the proper location after reserving.
/// \returns True on success, false otherwise. /// \returns True on success, false otherwise.
bool Box::reserve(size_t position, size_t current, size_t wanted){ bool Box::reserve(size_t position, size_t current, size_t wanted) {
if (current == wanted){ if (current == wanted) {
return true; return true;
} }
if (position > boxedSize()){ if (position > boxedSize()) {
wanted += position - boxedSize(); wanted += position - boxedSize();
} }
if (current < wanted){ if (current < wanted) {
//make bigger //make bigger
if (boxedSize() + (wanted - current) > data_size){ if (boxedSize() + (wanted - current) > data_size) {
//realloc if managed, otherwise fail //realloc if managed, otherwise fail
if ( !managed){ if (!managed) {
return false; return false;
} }
void * ret = realloc(data, boxedSize() + (wanted - current)); void * ret = realloc(data, boxedSize() + (wanted - current));
if ( !ret){ if (!ret) {
return false; return false;
} }
data = (char*)ret; data = (char *)ret;
memset(data + boxedSize(), 0, wanted - current); //initialize to 0 memset(data + boxedSize(), 0, wanted - current); //initialize to 0
data_size = boxedSize() + (wanted - current); data_size = boxedSize() + (wanted - current);
} }
} }
//move data behind, if any //move data behind, if any
if (boxedSize() > (position + current)){ if (boxedSize() > (position + current)) {
memmove(data + position + wanted, data + position + current, boxedSize() - (position + current)); memmove(data + position + wanted, data + position + current, boxedSize() - (position + current));
} }
//calculate and set new size //calculate and set new size
if (payloadOffset != 16){ if (payloadOffset != 16) {
int newSize = boxedSize() + (wanted - current); int newSize = boxedSize() + (wanted - current);
((int*)data)[0] = htonl(newSize); ((int *)data)[0] = htonl(newSize);
} }
return true; return true;
} }
fullBox::fullBox(){ fullBox::fullBox() {
setVersion(0); setVersion(0);
} }
void fullBox::setVersion(char newVersion){ void fullBox::setVersion(char newVersion) {
setInt8(newVersion, 0); setInt8(newVersion, 0);
} }
char fullBox::getVersion(){ char fullBox::getVersion() {
return getInt8(0); return getInt8(0);
} }
void fullBox::setFlags(uint32_t newFlags){ void fullBox::setFlags(uint32_t newFlags) {
setInt24(newFlags, 1); setInt24(newFlags, 1);
} }
uint32_t fullBox::getFlags(){ uint32_t fullBox::getFlags() {
return getInt24(1); return getInt24(1);
} }
std::string fullBox::toPrettyString(uint32_t indent){ std::string fullBox::toPrettyString(uint32_t indent) {
std::stringstream r; std::stringstream r;
r << std::string(indent + 1, ' ') << "Version: " << (int)getVersion() << std::endl; r << std::string(indent + 1, ' ') << "Version: " << (int)getVersion() << std::endl;
r << std::string(indent + 1, ' ') << "Flags: " << getFlags() << std::endl; r << std::string(indent + 1, ' ') << "Flags: " << getFlags() << std::endl;
return r.str(); return r.str();
} }
containerBox::containerBox(){ containerBox::containerBox() {
} }
uint32_t containerBox::getContentCount(){ uint32_t containerBox::getContentCount() {
int res = 0; int res = 0;
unsigned int tempLoc = 0; unsigned int tempLoc = 0;
while (tempLoc < boxedSize() - 8){ while (tempLoc < boxedSize() - 8) {
res++; res++;
tempLoc += Box(getBox(tempLoc).asBox(), false).boxedSize(); tempLoc += Box(getBox(tempLoc).asBox(), false).boxedSize();
} }
return res; return res;
} }
void containerBox::setContent(Box & newContent, uint32_t no){ void containerBox::setContent(Box & newContent, uint32_t no) {
int tempLoc = 0; int tempLoc = 0;
unsigned int contentCount = getContentCount(); unsigned int contentCount = getContentCount();
for (unsigned int i = 0; i < no; i++){ for (unsigned int i = 0; i < no; i++) {
if (i < contentCount){ if (i < contentCount) {
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
}else{ } else {
if ( !reserve(tempLoc, 0, (no - contentCount) * 8)){ if (!reserve(tempLoc, 0, (no - contentCount) * 8)) {
return; return;
}; };
memset(data + tempLoc, 0, (no - contentCount) * 8); memset(data + tempLoc, 0, (no - contentCount) * 8);
@ -716,27 +716,27 @@ namespace MP4 {
setBox(newContent, tempLoc); setBox(newContent, tempLoc);
} }
Box & containerBox::getContent(uint32_t no){ Box & containerBox::getContent(uint32_t no) {
static Box ret = Box((char*)"\000\000\000\010erro", false); static Box ret = Box((char *)"\000\000\000\010erro", false);
if (no > getContentCount()){ if (no > getContentCount()) {
return ret; return ret;
} }
unsigned int i = 0; unsigned int i = 0;
int tempLoc = 0; int tempLoc = 0;
while (i < no){ while (i < no) {
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
i++; i++;
} }
return getBox(tempLoc); return getBox(tempLoc);
} }
std::string containerBox::toPrettyString(uint32_t indent){ std::string containerBox::toPrettyString(uint32_t indent) {
std::stringstream r; 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; Box curBox;
int tempLoc = 0; int tempLoc = 0;
int contentCount = getContentCount(); int contentCount = getContentCount();
for (int i = 0; i < contentCount; i++){ for (int i = 0; i < contentCount; i++) {
curBox = getContent(i); curBox = getContent(i);
r << curBox.toPrettyString(indent + 1); r << curBox.toPrettyString(indent + 1);
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
@ -744,24 +744,24 @@ namespace MP4 {
return r.str(); return r.str();
} }
uint32_t containerFullBox::getContentCount(){ uint32_t containerFullBox::getContentCount() {
int res = 0; int res = 0;
unsigned int tempLoc = 4; unsigned int tempLoc = 4;
while (tempLoc < boxedSize() - 8){ while (tempLoc < boxedSize() - 8) {
res++; res++;
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
} }
return res; return res;
} }
void containerFullBox::setContent(Box & newContent, uint32_t no){ void containerFullBox::setContent(Box & newContent, uint32_t no) {
int tempLoc = 4; int tempLoc = 4;
unsigned int contentCount = getContentCount(); unsigned int contentCount = getContentCount();
for (unsigned int i = 0; i < no; i++){ for (unsigned int i = 0; i < no; i++) {
if (i < contentCount){ if (i < contentCount) {
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
}else{ } else {
if ( !reserve(tempLoc, 0, (no - contentCount) * 8)){ if (!reserve(tempLoc, 0, (no - contentCount) * 8)) {
return; return;
}; };
memset(data + tempLoc, 0, (no - contentCount) * 8); memset(data + tempLoc, 0, (no - contentCount) * 8);
@ -771,29 +771,29 @@ namespace MP4 {
} }
setBox(newContent, tempLoc); setBox(newContent, tempLoc);
} }
Box & containerFullBox::getContent(uint32_t no){ Box & containerFullBox::getContent(uint32_t no) {
static Box ret = Box((char*)"\000\000\000\010erro", false); static Box ret = Box((char *)"\000\000\000\010erro", false);
if (no > getContentCount()){ if (no > getContentCount()) {
return ret; return ret;
} }
unsigned int i = 0; unsigned int i = 0;
int tempLoc = 4; int tempLoc = 4;
while (i < no){ while (i < no) {
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
i++; i++;
} }
return getBox(tempLoc); 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; std::stringstream r;
r << std::string(indent, ' ') << boxName <<" (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << boxName << " (" << boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent); r << fullBox::toPrettyString(indent);
Box curBox; Box curBox;
int tempLoc = 4; int tempLoc = 4;
int contentCount = getContentCount(); int contentCount = getContentCount();
for (int i = 0; i < contentCount; i++){ for (int i = 0; i < contentCount; i++) {
curBox = getContent(i); curBox = getContent(i);
r << curBox.toPrettyString(indent + 1); r << curBox.toPrettyString(indent + 1);
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);

View file

@ -18,16 +18,16 @@ namespace MP4 {
std::string readBoxType(FILE * newData); std::string readBoxType(FILE * newData);
bool skipBox(FILE * newData); bool skipBox(FILE * newData);
class Box{ class Box {
public: public:
Box(char * datapointer = 0, bool manage = true); Box(char * datapointer = 0, bool manage = true);
Box(const Box & rs); Box(const Box & rs);
Box& operator = (const Box & rs); Box & operator = (const Box & rs);
~Box(); ~Box();
std::string getType(); std::string getType();
bool isType(const char* boxType); bool isType(const char * boxType);
bool read(FILE* newData); bool read(FILE * newData);
bool read(std::string & newData); bool read(std::string & newData);
uint64_t boxedSize(); uint64_t boxedSize();
uint64_t payloadSize(); uint64_t payloadSize();
@ -49,7 +49,7 @@ namespace MP4 {
uint64_t getInt64(size_t index); uint64_t getInt64(size_t index);
//string functions //string functions
void setString(std::string newData, size_t index); 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); char * getString(size_t index);
size_t getStringLen(size_t index); size_t getStringLen(size_t index);
//box functions //box functions
@ -65,8 +65,8 @@ namespace MP4 {
unsigned int payloadOffset; ///<The offset of the payload with regards to the data unsigned int payloadOffset; ///<The offset of the payload with regards to the data
}; };
//Box Class //Box Class
class fullBox: public Box{ class fullBox: public Box {
public: public:
fullBox(); fullBox();
void setVersion(char newVersion); void setVersion(char newVersion);
@ -75,8 +75,8 @@ namespace MP4 {
uint32_t getFlags(); uint32_t getFlags();
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
class containerBox: public Box{ class containerBox: public Box {
public: public:
containerBox(); containerBox();
uint32_t getContentCount(); uint32_t getContentCount();
@ -84,8 +84,8 @@ namespace MP4 {
Box & getContent(uint32_t no); Box & getContent(uint32_t no);
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
class containerFullBox: public fullBox{ class containerFullBox: public fullBox {
public: public:
uint32_t getContentCount(); uint32_t getContentCount();
void setContent(Box & newContent, uint32_t no); void setContent(Box & newContent, uint32_t no);

File diff suppressed because it is too large Load diff

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

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

@ -134,10 +134,10 @@ namespace h264 {
//For calculating width //For calculating width
unsigned int widthInMbs = 0; unsigned int widthInMbs = 0;
unsigned int cropHorizontal = 0; unsigned int cropHorizontal = 0;
//For calculating height //For calculating height
bool mbsOnlyFlag = 0; bool mbsOnlyFlag = 0;
unsigned int heightInMapUnits = 0; unsigned int heightInMapUnits = 0;
unsigned int cropVertical = 0; unsigned int cropVertical = 0;
Utils::bitstream bs; Utils::bitstream bs;
@ -177,7 +177,7 @@ namespace h264 {
bs.skip(1); bs.skip(1);
//Stop skipping data and start doing usefull stuff //Stop skipping data and start doing usefull stuff
widthInMbs = bs.getUExpGolomb() + 1; widthInMbs = bs.getUExpGolomb() + 1;
heightInMapUnits = bs.getUExpGolomb() + 1; heightInMapUnits = bs.getUExpGolomb() + 1;
@ -197,7 +197,7 @@ namespace h264 {
//vuiParameters //vuiParameters
if (bs.get(1)) { if (bs.get(1)) {
//Skipping all the paramters we dont use //Skipping all the paramters we dont use
if (bs.get(1)){ if (bs.get(1)) {
if (bs.get(8) == 255) { if (bs.get(8) == 255) {
bs.skip(32); bs.skip(32);
} }

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

@ -1,17 +1,17 @@
#include <string> #include <string>
#include <cstdio> #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 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 width;
unsigned int height; unsigned int height;
double fps; double fps;
}; };
///Class for analyzing generic nal units ///Class for analyzing generic nal units
class NAL{ class NAL {
public: public:
NAL(); NAL();
NAL(std::string & InputData); NAL(std::string & InputData);
@ -25,21 +25,21 @@ namespace h264{
std::string MyData;///<The h264 nal unit data std::string MyData;///<The h264 nal unit data
}; };
//NAL class //NAL class
///Special instance of NAL class for analyzing SPS nal units ///Special instance of NAL class for analyzing SPS nal units
class SPS: public NAL{ class SPS: public NAL {
public: public:
SPS():NAL(){}; SPS(): NAL() {};
SPS(std::string & InputData, bool raw = false); SPS(std::string & InputData, bool raw = false);
SPSMeta getCharacteristics(); SPSMeta getCharacteristics();
void analyzeSPS(); void analyzeSPS();
}; };
///Special instance of NAL class for analyzing PPS nal units ///Special instance of NAL class for analyzing PPS nal units
class PPS: public NAL{ class PPS: public NAL {
public: public:
PPS():NAL(){}; PPS(): NAL() {};
PPS(std::string & InputData):NAL(InputData){}; PPS(std::string & InputData): NAL(InputData) {};
void analyzePPS(); void analyzePPS();
}; };
}//ns h264 }//ns h264

View file

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

View file

@ -8,15 +8,15 @@
#include "vorbis.h" #include "vorbis.h"
#include "json.h" #include "json.h"
namespace OGG{ namespace OGG {
enum HeaderType{ enum HeaderType {
Continued = 1, Continued = 1,
BeginOfStream = 2, BeginOfStream = 2,
EndOfStream = 4 EndOfStream = 4
}; };
class Page{ class Page {
public: public:
Page(); Page();
~Page(); ~Page();
@ -38,30 +38,30 @@ namespace OGG{
void setCRCChecksum(long unsigned int newVal); void setCRCChecksum(long unsigned int newVal);
char getPageSegments(); char getPageSegments();
inline void setPageSegments(char newVal); inline void setPageSegments(char newVal);
char* getSegmentTable(); char * getSegmentTable();
std::deque<unsigned int> & getSegmentTableDeque(); std::deque<unsigned int> & getSegmentTableDeque();
bool setSegmentTable(std::vector<unsigned int> layout); bool setSegmentTable(std::vector<unsigned int> layout);
void setSegmentTable(char* newVal, unsigned int length); void setSegmentTable(char * newVal, unsigned int length);
char* getPage();//returns complete page with header char * getPage(); //returns complete page with header
unsigned long int getPageSize(); unsigned long int getPageSize();
char* getFullPayload();//returns all segments in the page char * getFullPayload(); //returns all segments in the page
int getPayloadSize(); int getPayloadSize();
std::string toPrettyString(size_t indent = 0); std::string toPrettyString(size_t indent = 0);
void setInternalCodec(std::string myCodec); void setInternalCodec(std::string myCodec);
long unsigned int calcChecksum(); long unsigned int calcChecksum();
bool clear(); 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); void readDTSCVector(std::vector <JSON::Value> DTSCVec, unsigned int serial, unsigned int sequence);
private: private:
std::deque<unsigned int> segmentTableDeque; 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 datasize;//size of the allocated memory
unsigned int dataSum;//size of the total segments unsigned int dataSum;//size of the total segments
bool checkDataSize(unsigned int size); bool checkDataSize(unsigned int size);
std::string codec;//codec in the page std::string codec;//codec in the page
}; };
class headerPages{ class headerPages {
public: public:
void readDTSCHeader(DTSC::Meta & meta); void readDTSCHeader(DTSC::Meta & meta);
std::map <long long unsigned int, unsigned int> DTSCID2OGGSerial; 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; std::map<pid_t, Util::TerminationNotifier> Util::Procs::exitHandlers;
bool Util::Procs::handler_set = false; 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); pid_t ret = waitpid(p, 0, WNOHANG);
if (ret == p){return false;} if (ret == p) {
if (ret < 0 && errno == EINTR){ return false;
}
if (ret < 0 && errno == EINTR) {
return childRunning(p); return childRunning(p);
} }
if (kill(p, 0) == 0){return true;} if (kill(p, 0) == 0) {
return true;
}
return false; 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. /// 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 /// 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. /// 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; int waiting = 0;
std::map<pid_t, std::string> listcopy = plist; std::map<pid_t, std::string> listcopy = plist;
std::map<pid_t, std::string>::iterator it; 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 //wait up to 0.5 second for applications to shut down
while ( !listcopy.empty() && waiting <= 25){ while (!listcopy.empty() && waiting <= 25) {
for (it = listcopy.begin(); it != listcopy.end(); it++){ for (it = listcopy.begin(); it != listcopy.end(); it++) {
if ( !childRunning((*it).first)){ if (!childRunning((*it).first)) {
listcopy.erase(it); listcopy.erase(it);
break; break;
} }
if ( !listcopy.empty()){ if (!listcopy.empty()) {
Util::sleep(20); Util::sleep(20);
++waiting; ++waiting;
} }
} }
} }
if (listcopy.empty()){return;} if (listcopy.empty()) {
return;
}
DEBUG_MSG(DLVL_DEVEL, "Sending SIGINT to remaining %d children", (int)listcopy.size()); DEBUG_MSG(DLVL_DEVEL, "Sending SIGINT to remaining %d children", (int)listcopy.size());
//send sigint to all remaining //send sigint to all remaining
if ( !listcopy.empty()){ if (!listcopy.empty()) {
for (it = listcopy.begin(); it != listcopy.end(); it++){ for (it = listcopy.begin(); it != listcopy.end(); it++) {
DEBUG_MSG(DLVL_DEVEL, "SIGINT %d: %s", ( *it).first, ( *it).second.c_str()); DEBUG_MSG(DLVL_DEVEL, "SIGINT %d: %s", (*it).first, (*it).second.c_str());
kill(( *it).first, SIGINT); kill((*it).first, SIGINT);
} }
} }
DEBUG_MSG(DLVL_DEVEL, "Waiting up to 5 seconds for %d children to terminate.", (int)listcopy.size()); DEBUG_MSG(DLVL_DEVEL, "Waiting up to 5 seconds for %d children to terminate.", (int)listcopy.size());
waiting = 0; waiting = 0;
//wait up to 5 seconds for applications to shut down //wait up to 5 seconds for applications to shut down
while ( !listcopy.empty() && waiting <= 250){ while (!listcopy.empty() && waiting <= 250) {
for (it = listcopy.begin(); it != listcopy.end(); it++){ for (it = listcopy.begin(); it != listcopy.end(); it++) {
if ( !childRunning((*it).first)){ if (!childRunning((*it).first)) {
listcopy.erase(it); listcopy.erase(it);
break; break;
} }
if ( !listcopy.empty()){ if (!listcopy.empty()) {
Util::sleep(20); Util::sleep(20);
++waiting; ++waiting;
} }
} }
} }
if (listcopy.empty()){return;} if (listcopy.empty()) {
return;
}
DEBUG_MSG(DLVL_DEVEL, "Sending SIGKILL to remaining %d children", (int)listcopy.size()); DEBUG_MSG(DLVL_DEVEL, "Sending SIGKILL to remaining %d children", (int)listcopy.size());
//send sigkill to all remaining //send sigkill to all remaining
if ( !listcopy.empty()){ if (!listcopy.empty()) {
for (it = listcopy.begin(); it != listcopy.end(); it++){ for (it = listcopy.begin(); it != listcopy.end(); it++) {
DEBUG_MSG(DLVL_DEVEL, "SIGKILL %d: %s", ( *it).first, ( *it).second.c_str()); DEBUG_MSG(DLVL_DEVEL, "SIGKILL %d: %s", (*it).first, (*it).second.c_str());
kill(( *it).first, SIGKILL); kill((*it).first, SIGKILL);
} }
} }
DEBUG_MSG(DLVL_DEVEL, "Waiting up to a second for %d children to terminate.", (int)listcopy.size()); DEBUG_MSG(DLVL_DEVEL, "Waiting up to a second for %d children to terminate.", (int)listcopy.size());
waiting = 0; waiting = 0;
//wait up to 1 second for applications to shut down //wait up to 1 second for applications to shut down
while ( !listcopy.empty() && waiting <= 50){ while (!listcopy.empty() && waiting <= 50) {
for (it = listcopy.begin(); it != listcopy.end(); it++){ for (it = listcopy.begin(); it != listcopy.end(); it++) {
if ( !childRunning((*it).first)){ if (!childRunning((*it).first)) {
listcopy.erase(it); listcopy.erase(it);
break; break;
} }
if ( !listcopy.empty()){ if (!listcopy.empty()) {
Util::sleep(20); Util::sleep(20);
++waiting; ++waiting;
} }
} }
} }
if (listcopy.empty()){return;} if (listcopy.empty()) {
return;
}
DEBUG_MSG(DLVL_DEVEL, "Giving up with %d children left.", (int)listcopy.size()); DEBUG_MSG(DLVL_DEVEL, "Giving up with %d children left.", (int)listcopy.size());
} }
/// Sets up exit and childsig handlers. /// Sets up exit and childsig handlers.
/// Called by every Start* function. /// Called by every Start* function.
void Util::Procs::setHandler(){ void Util::Procs::setHandler() {
if ( !handler_set){ if (!handler_set) {
struct sigaction new_action; struct sigaction new_action;
new_action.sa_handler = childsig_handler; new_action.sa_handler = childsig_handler;
sigemptyset( &new_action.sa_mask); sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0; new_action.sa_flags = 0;
sigaction(SIGCHLD, &new_action, NULL); sigaction(SIGCHLD, &new_action, NULL);
atexit(exit_handler); atexit(exit_handler);
handler_set = true; handler_set = true;
}// else { }// else {
// DEBUG_MSG(DLVL_DEVEL, "not setting handler"); // DEBUG_MSG(DLVL_DEVEL, "not setting handler");
// } // }
} }
/// Used internally to capture child signals and update plist. /// Used internally to capture child signals and update plist.
void Util::Procs::childsig_handler(int signum){ void Util::Procs::childsig_handler(int signum) {
if (signum != SIGCHLD){ if (signum != SIGCHLD) {
DEBUG_MSG(DLVL_DEVEL, "signum != SIGCHLD"); DEBUG_MSG(DLVL_DEVEL, "signum != SIGCHLD");
return; return;
} }
int status; int status;
pid_t ret = -1; pid_t ret = -1;
while (ret != 0){ while (ret != 0) {
ret = waitpid( -1, &status, WNOHANG); ret = waitpid(-1, &status, WNOHANG);
if (ret <= 0){ //ignore, would block otherwise if (ret <= 0) { //ignore, would block otherwise
if (ret == 0 || errno != EINTR){ if (ret == 0 || errno != EINTR) {
return; return;
} }
continue; continue;
} }
int exitcode; int exitcode;
if (WIFEXITED(status)){ if (WIFEXITED(status)) {
exitcode = WEXITSTATUS(status); exitcode = WEXITSTATUS(status);
}else if (WIFSIGNALED(status)){ } else if (WIFSIGNALED(status)) {
exitcode = -WTERMSIG(status); exitcode = -WTERMSIG(status);
}else{// not possible } else { // not possible
return; return;
} }
@ -162,14 +174,14 @@ void Util::Procs::childsig_handler(int signum){
#endif #endif
plist.erase(ret); plist.erase(ret);
#if DEBUG >= DLVL_HIGH #if DEBUG >= DLVL_HIGH
if (!isActive(pname)){ if (!isActive(pname)) {
DEBUG_MSG(DLVL_HIGH, "Process %s fully terminated", pname.c_str()); DEBUG_MSG(DLVL_HIGH, "Process %s fully terminated", pname.c_str());
}else{ } else {
DEBUG_MSG(DLVL_HIGH, "Child process %d exited", ret); DEBUG_MSG(DLVL_HIGH, "Child process %d exited", ret);
} }
#endif #endif
if (exitHandlers.count(ret) > 0){ if (exitHandlers.count(ret) > 0) {
TerminationNotifier tn = exitHandlers[ret]; TerminationNotifier tn = exitHandlers[ret];
exitHandlers.erase(ret); exitHandlers.erase(ret);
tn(ret, exitcode); 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. /// 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; std::string ret;
int fin = 0, fout = -1, ferr = 0; int fin = 0, fout = -1, ferr = 0;
StartPiped("output_getter", argv, &fin, &fout, &ferr); 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"); FILE * outFile = fdopen(fout, "r");
char * fileBuf = 0; char * fileBuf = 0;
size_t fileBufLen = 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; ret += fileBuf;
} }
fclose(outFile); 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. /// 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; std::string ret;
int fin = 0, fout = -1, ferr = 0; int fin = 0, fout = -1, ferr = 0;
StartPiped("output_getter", cmd, &fin, &fout, &ferr); 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"); FILE * outFile = fdopen(fout, "r");
char * fileBuf = 0; char * fileBuf = 0;
size_t fileBufLen = 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; ret += fileBuf;
} }
free(fileBuf); free(fileBuf);
@ -217,21 +233,21 @@ std::string Util::Procs::getOutputOf(std::string cmd){
/// Replaces the current process - use after forking first! /// Replaces the current process - use after forking first!
/// This function will never return - it will either run the given /// This function will never return - it will either run the given
/// command or kill itself with return code 42. /// 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 //split cmd into arguments
//supports a maximum of 20 arguments //supports a maximum of 20 arguments
char * tmp = (char*)cmd.c_str(); char * tmp = (char *)cmd.c_str();
char * tmp2 = 0; char * tmp2 = 0;
char * args[21]; char * args[21];
int i = 0; int i = 0;
tmp2 = strtok(tmp, " "); tmp2 = strtok(tmp, " ");
args[0] = tmp2; args[0] = tmp2;
while (tmp2 != 0 && (i < 20)){ while (tmp2 != 0 && (i < 20)) {
tmp2 = strtok(0, " "); tmp2 = strtok(0, " ");
++i; ++i;
args[i] = tmp2; args[i] = tmp2;
} }
if (i == 20){ if (i == 20) {
args[20] = 0; args[20] = 0;
} }
//execute the command //execute the command
@ -244,19 +260,19 @@ void Util::Procs::runCmd(std::string & cmd){
/// \return 0 if process was not started, process PID otherwise. /// \return 0 if process was not started, process PID otherwise.
/// \arg name Name for this process - only used internally. /// \arg name Name for this process - only used internally.
/// \arg cmd Commandline for this process. /// \arg cmd Commandline for this process.
pid_t Util::Procs::Start(std::string name, std::string cmd){ pid_t Util::Procs::Start(std::string name, std::string cmd) {
if (isActive(name)){ if (isActive(name)) {
return getPid(name); return getPid(name);
} }
setHandler(); setHandler();
pid_t ret = fork(); pid_t ret = fork();
if (ret == 0){ if (ret == 0) {
runCmd(cmd); runCmd(cmd);
}else{ } else {
if (ret > 0){ if (ret > 0) {
DEBUG_MSG(DLVL_HIGH, "Process %s started, PID %d: %s", name.c_str(), ret, cmd.c_str()); 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)); 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started: fork() failed", name.c_str());
return 0; 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 name Name for this process - only used internally.
/// \arg cmd Commandline for sub (sending) process. /// \arg cmd Commandline for sub (sending) process.
/// \arg cmd2 Commandline for main (receiving) process. /// \arg cmd2 Commandline for main (receiving) process.
pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2) {
if (isActive(name)){ if (isActive(name)) {
return getPid(name); return getPid(name);
} }
setHandler(); setHandler();
int pfildes[2]; 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0; return 0;
} }
int devnull = open("/dev/null", O_RDWR); int devnull = open("/dev/null", O_RDWR);
pid_t ret = fork(); pid_t ret = fork();
if (ret == 0){ if (ret == 0) {
close(pfildes[0]); close(pfildes[0]);
dup2(pfildes[1], STDOUT_FILENO); dup2(pfildes[1], STDOUT_FILENO);
close(pfildes[1]); close(pfildes[1]);
dup2(devnull, STDIN_FILENO); dup2(devnull, STDIN_FILENO);
dup2(devnull, STDERR_FILENO); dup2(devnull, STDERR_FILENO);
runCmd(cmd); runCmd(cmd);
}else{ } else {
if (ret > 0){ if (ret > 0) {
plist.insert(std::pair<pid_t, std::string>(ret, name)); 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); 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(); pid_t ret2 = fork();
if (ret2 == 0){ if (ret2 == 0) {
close(pfildes[1]); close(pfildes[1]);
dup2(pfildes[0], STDIN_FILENO); dup2(pfildes[0], STDIN_FILENO);
close(pfildes[0]); close(pfildes[0]);
dup2(devnull, STDOUT_FILENO); dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO); dup2(devnull, STDERR_FILENO);
runCmd(cmd2); runCmd(cmd2);
}else{ } else {
if (ret2 > 0){ 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()); 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)); 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name); Stop(name);
close(pfildes[1]); 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 cmd Commandline for sub (sending) process.
/// \arg cmd2 Commandline for sub (middle) process. /// \arg cmd2 Commandline for sub (middle) process.
/// \arg cmd3 Commandline for main (receiving) 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){ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3) {
if (isActive(name)){ if (isActive(name)) {
return getPid(name); return getPid(name);
} }
setHandler(); setHandler();
int pfildes[2]; int pfildes[2];
int pfildes2[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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0; 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
return 0; return 0;
} }
int devnull = open("/dev/null", O_RDWR); int devnull = open("/dev/null", O_RDWR);
pid_t ret = fork(); pid_t ret = fork();
if (ret == 0){ if (ret == 0) {
close(pfildes[0]); close(pfildes[0]);
dup2(pfildes[1], STDOUT_FILENO); dup2(pfildes[1], STDOUT_FILENO);
close(pfildes[1]); 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[1]);
close(pfildes2[0]); close(pfildes2[0]);
runCmd(cmd); runCmd(cmd);
}else{ } else {
if (ret > 0){ if (ret > 0) {
plist.insert(std::pair<pid_t, std::string>(ret, name)); 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); 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(); pid_t ret2 = fork();
if (ret2 == 0){ if (ret2 == 0) {
close(pfildes[1]); close(pfildes[1]);
close(pfildes2[0]); close(pfildes2[0]);
dup2(pfildes[0], STDIN_FILENO); 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]); close(pfildes2[1]);
dup2(devnull, STDERR_FILENO); dup2(devnull, STDERR_FILENO);
runCmd(cmd2); runCmd(cmd2);
}else{ } else {
if (ret2 > 0){ 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()); 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)); 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name); Stop(name);
close(pfildes[1]); 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]); close(pfildes[0]);
pid_t ret3 = fork(); pid_t ret3 = fork();
if (ret3 == 0){ if (ret3 == 0) {
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); close(pfildes[0]);
close(pfildes2[1]); 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, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO); dup2(devnull, STDERR_FILENO);
runCmd(cmd3); runCmd(cmd3);
}else{ } else {
if (ret3 > 0){ 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()); 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)); 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()); DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
Stop(name); Stop(name);
close(pfildes[1]); 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 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 stdout.
/// \arg fdout Same as fdin, but for stderr. /// \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){ pid_t Util::Procs::StartPiped(std::string name, char * const * argv, int * fdin, int * fdout, int * fderr) {
if (isActive(name)){ if (isActive(name)) {
DEBUG_MSG(DLVL_WARN, "Process %s already active - skipping start", name.c_str()); DEBUG_MSG(DLVL_WARN, "Process %s already active - skipping start", name.c_str());
return getPid(name); return getPid(name);
} }
int pidtemp = StartPiped(argv, fdin, fdout, fderr); int pidtemp = StartPiped(argv, fdin, fdout, fderr);
if (pidtemp > 0 ) { if (pidtemp > 0) {
plist.insert(std::pair<pid_t, std::string>(pidtemp, name)); plist.insert(std::pair<pid_t, std::string>(pidtemp, name));
} }
return pidtemp; 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; pid_t pid;
int pipein[2], pipeout[2], pipeerr[2]; int pipein[2], pipeout[2], pipeerr[2];
//DEBUG_MSG(DLVL_DEVEL, "setHandler"); //DEBUG_MSG(DLVL_DEVEL, "setHandler");
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]); DEBUG_MSG(DLVL_ERROR, "Pipe in creation failed for process %s", argv[0]);
return 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]); DEBUG_MSG(DLVL_ERROR, "Pipe out creation failed for process %s", argv[0]);
if ( *fdin == -1){ if (*fdin == -1) {
close(pipein[0]); close(pipein[0]);
close(pipein[1]); close(pipein[1]);
} }
return 0; 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]); DEBUG_MSG(DLVL_ERROR, "Pipe err creation failed for process %s", argv[0]);
if ( *fdin == -1){ if (*fdin == -1) {
close(pipein[0]); close(pipein[0]);
close(pipein[1]); close(pipein[1]);
} }
if ( *fdout == -1){ if (*fdout == -1) {
close(pipeout[0]); close(pipeout[0]);
close(pipeout[1]); close(pipeout[1]);
} }
return 0; return 0;
} }
int devnull = -1; int devnull = -1;
if ( !fdin || !fdout || !fderr){ if (!fdin || !fdout || !fderr) {
devnull = open("/dev/null", O_RDWR); 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)); 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[0]);
close(pipein[1]); close(pipein[1]);
} }
if ( *fdout == -1){ if (*fdout == -1) {
close(pipeout[0]); close(pipeout[0]);
close(pipeout[1]); close(pipeout[1]);
} }
if ( *fderr == -1){ if (*fderr == -1) {
close(pipeerr[0]); close(pipeerr[0]);
close(pipeerr[1]); close(pipeerr[1]);
} }
@ -495,81 +511,81 @@ pid_t Util::Procs::StartPiped(char* const* argv, int * fdin, int * fdout, int *
} }
} }
pid = fork(); pid = fork();
if (pid == 0){ //child if (pid == 0) { //child
if ( !fdin){ if (!fdin) {
dup2(devnull, STDIN_FILENO); dup2(devnull, STDIN_FILENO);
}else if ( *fdin == -1){ } else if (*fdin == -1) {
close(pipein[1]); // close unused write end close(pipein[1]); // close unused write end
dup2(pipein[0], STDIN_FILENO); dup2(pipein[0], STDIN_FILENO);
close(pipein[0]); close(pipein[0]);
}else if ( *fdin != STDIN_FILENO){ } else if (*fdin != STDIN_FILENO) {
dup2( *fdin, STDIN_FILENO); dup2(*fdin, STDIN_FILENO);
} }
if ( !fdout){ if (!fdout) {
dup2(devnull, STDOUT_FILENO); dup2(devnull, STDOUT_FILENO);
}else if ( *fdout == -1){ } else if (*fdout == -1) {
close(pipeout[0]); // close unused read end close(pipeout[0]); // close unused read end
dup2(pipeout[1], STDOUT_FILENO); dup2(pipeout[1], STDOUT_FILENO);
close(pipeout[1]); close(pipeout[1]);
}else if ( *fdout != STDOUT_FILENO){ } else if (*fdout != STDOUT_FILENO) {
dup2( *fdout, STDOUT_FILENO); dup2(*fdout, STDOUT_FILENO);
} }
if ( !fderr){ if (!fderr) {
dup2(devnull, STDERR_FILENO); dup2(devnull, STDERR_FILENO);
}else if ( *fderr == -1){ } else if (*fderr == -1) {
close(pipeerr[0]); // close unused read end close(pipeerr[0]); // close unused read end
dup2(pipeerr[1], STDERR_FILENO); dup2(pipeerr[1], STDERR_FILENO);
close(pipeerr[1]); close(pipeerr[1]);
}else if ( *fderr != STDERR_FILENO){ } else if (*fderr != STDERR_FILENO) {
dup2( *fderr, STDERR_FILENO); dup2(*fderr, STDERR_FILENO);
} }
if( fdin && *fdin !=-1 && *fdin != STDIN_FILENO){ if (fdin && *fdin != -1 && *fdin != STDIN_FILENO) {
close( *fdin); close(*fdin);
} }
if( fdout && *fdout !=-1 && *fdout != STDOUT_FILENO){ if (fdout && *fdout != -1 && *fdout != STDOUT_FILENO) {
close( *fdout); close(*fdout);
} }
if( fderr && *fderr !=-1 && *fderr != STDERR_FILENO){ if (fderr && *fderr != -1 && *fderr != STDERR_FILENO) {
close( *fderr); close(*fderr);
} }
if (devnull != -1){ if (devnull != -1) {
close(devnull); close(devnull);
} }
execvp(argv[0], argv); execvp(argv[0], argv);
DEBUG_MSG(DLVL_ERROR, "execvp() failed for process %s", argv[0]); DEBUG_MSG(DLVL_ERROR, "execvp() failed for process %s", argv[0]);
exit(42); exit(42);
}else if (pid == -1){ } else if (pid == -1) {
DEBUG_MSG(DLVL_ERROR, "fork() for pipe failed for process %s", argv[0]); 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[0]);
close(pipein[1]); close(pipein[1]);
} }
if (fdout && *fdout == -1){ if (fdout && *fdout == -1) {
close(pipeout[0]); close(pipeout[0]);
close(pipeout[1]); close(pipeout[1]);
} }
if (fderr && *fderr == -1){ if (fderr && *fderr == -1) {
close(pipeerr[0]); close(pipeerr[0]);
close(pipeerr[1]); close(pipeerr[1]);
} }
if (devnull != -1){ if (devnull != -1) {
close(devnull); close(devnull);
} }
return 0; return 0;
}else{ //parent } else { //parent
DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d", argv[0], pid); DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d", argv[0], pid);
if (devnull != -1){ if (devnull != -1) {
close(devnull); close(devnull);
} }
if (fdin && *fdin == -1){ if (fdin && *fdin == -1) {
close(pipein[0]); // close unused end end close(pipein[0]); // close unused end end
*fdin = pipein[1]; *fdin = pipein[1];
} }
if (fdout && *fdout == -1){ if (fdout && *fdout == -1) {
close(pipeout[1]); // close unused write end close(pipeout[1]); // close unused write end
*fdout = pipeout[0]; *fdout = pipeout[0];
} }
if (fderr && *fderr == -1){ if (fderr && *fderr == -1) {
close(pipeerr[1]); // close unused write end close(pipeerr[1]); // close unused write end
*fderr = pipeerr[0]; *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 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 stdout.
/// \arg fdout Same as fdin, but for stderr. /// \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 * [] //Convert the given command to a char * []
char * tmp = (char*)cmd.c_str(); char * tmp = (char *)cmd.c_str();
char * tmp2 = 0; char * tmp2 = 0;
char * args[21]; char * args[21];
int i = 0; int i = 0;
tmp2 = strtok(tmp, " "); tmp2 = strtok(tmp, " ");
args[0] = tmp2; args[0] = tmp2;
while (tmp2 != 0 && (i < 20)){ while (tmp2 != 0 && (i < 20)) {
tmp2 = strtok(0, " "); tmp2 = strtok(0, " ");
++i; ++i;
args[i] = tmp2; args[i] = tmp2;
} }
if (i == 20){ if (i == 20) {
args[20] = 0; 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]; int pfildes[2];
if (pipe(pfildes) == -1){ if (pipe(pfildes) == -1) {
DEBUG_MSG(DLVL_ERROR, "Pipe creation failed for process %s", name.c_str()); DEBUG_MSG(DLVL_ERROR, "Pipe creation failed for process %s", name.c_str());
return 0; return 0;
} }
pid_t res1 = StartPiped(name, cmd1, fdin, &pfildes[1], fderr1); pid_t res1 = StartPiped(name, cmd1, fdin, &pfildes[1], fderr1);
if ( !res1){ if (!res1) {
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); close(pfildes[0]);
return 0; return 0;
} }
pid_t res2 = StartPiped(name+"receiving", cmd2, &pfildes[0], fdout, fderr2); pid_t res2 = StartPiped(name + "receiving", cmd2, &pfildes[0], fdout, fderr2);
if ( !res2){ if (!res2) {
Stop(res1); Stop(res1);
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); 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. /// Stops the named process, if running.
/// \arg name (Internal) name of process to stop /// \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; int max = 5;
while (isActive(name)){ while (isActive(name)) {
Stop(getPid(name)); Stop(getPid(name));
max--; max--;
if (max <= 0){ if (max <= 0) {
return; return;
} }
} }
@ -643,36 +659,36 @@ void Util::Procs::Stop(std::string name){
/// Stops the process with this pid, if running. /// Stops the process with this pid, if running.
/// \arg name The PID of the process to stop. /// \arg name The PID of the process to stop.
void Util::Procs::Stop(pid_t name){ void Util::Procs::Stop(pid_t name) {
if (isActive(name)){ if (isActive(name)) {
kill(name, SIGTERM); kill(name, SIGTERM);
} }
} }
/// (Attempts to) stop all running child processes. /// (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> listcopy = plist;
std::map<pid_t, std::string>::iterator it; std::map<pid_t, std::string>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++){ for (it = listcopy.begin(); it != listcopy.end(); it++) {
Stop(( *it).first); Stop((*it).first);
} }
} }
/// Returns the number of active child processes. /// Returns the number of active child processes.
int Util::Procs::Count(){ int Util::Procs::Count() {
return plist.size(); return plist.size();
} }
/// Returns true if a process by this name is currently active. /// 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> listcopy = plist;
std::map<pid_t, std::string>::iterator it; std::map<pid_t, std::string>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++){ for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (( *it).second == name){ if ((*it).second == name) {
if (childRunning(( *it).first)){ if (childRunning((*it).first)) {
return true; return true;
}else{ } else {
plist.erase(( *it).first); 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. /// 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); return (plist.count(name) == 1) && (kill(name, 0) == 0);
} }
/// Gets PID for this named process, if active. /// Gets PID for this named process, if active.
/// \return NULL if not active, process PID otherwise. /// \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; std::map<pid_t, std::string>::iterator it;
for (it = plist.begin(); it != plist.end(); it++){ for (it = plist.begin(); it != plist.end(); it++) {
if (( *it).second == name){ if ((*it).second == name) {
return ( *it).first; return (*it).first;
} }
} }
return 0; return 0;
@ -698,8 +714,8 @@ pid_t Util::Procs::getPid(std::string name){
/// Gets name for this process PID, if active. /// Gets name for this process PID, if active.
/// \return Empty string if not active, name otherwise. /// \return Empty string if not active, name otherwise.
std::string Util::Procs::getName(pid_t name){ std::string Util::Procs::getName(pid_t name) {
if (plist.count(name) == 1){ if (plist.count(name) == 1) {
return plist[name]; return plist[name];
} }
return ""; 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. /// Registers one notifier function for when a process indentified by PID terminates.
/// \return true if the notifier could be registered, false otherwise. /// \return true if the notifier could be registered, false otherwise.
bool Util::Procs::SetTerminationNotifier(pid_t pid, TerminationNotifier notifier){ bool Util::Procs::SetTerminationNotifier(pid_t pid, TerminationNotifier notifier) {
if (plist.find(pid) != plist.end()){ if (plist.find(pid) != plist.end()) {
exitHandlers[pid] = notifier; exitHandlers[pid] = notifier;
return true; return true;
} }

View file

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

View file

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

View file

@ -28,9 +28,9 @@ namespace RTMPStream {
extern unsigned int snd_cnt; ///< Counter for total data sent, in bytes. extern unsigned int snd_cnt; ///< Counter for total data sent, in bytes.
extern timeval lastrec; ///< Timestamp of last time data was received. extern timeval lastrec; ///< Timestamp of last time data was received.
/// Holds a single RTMP chunk, either send or receive direction. /// Holds a single RTMP chunk, either send or receive direction.
class Chunk{ class Chunk {
public: public:
unsigned char headertype; ///< For input chunks, the type of header. This is calculated automatically for output chunks. unsigned char headertype; ///< For input chunks, the type of header. This is calculated automatically for output chunks.
unsigned int cs_id; ///< ContentStream ID unsigned int cs_id; ///< ContentStream ID
@ -51,7 +51,7 @@ namespace RTMPStream {
extern std::map<unsigned int, Chunk> lastsend; extern std::map<unsigned int, Chunk> lastsend;
extern std::map<unsigned int, Chunk> lastrecv; extern std::map<unsigned int, Chunk> lastrecv;
std::string & SendChunk(unsigned int cs_id, unsigned char msg_type_id, unsigned int msg_stream_id, std::string data); std::string & SendChunk(unsigned int cs_id, unsigned char msg_type_id, unsigned int msg_stream_id, std::string data);
std::string & SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts); std::string & SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts);
std::string & SendMedia(FLV::Tag & tag); std::string & SendMedia(FLV::Tag & tag);

View file

@ -177,11 +177,11 @@ namespace IPC {
///\brief Unmaps a shared page if allowed ///\brief Unmaps a shared page if allowed
void sharedPage::unmap() { void sharedPage::unmap() {
if (mapped && len) { if (mapped && len) {
#ifdef __CYGWIN__ #ifdef __CYGWIN__
UnmapViewOfFile(mapped); UnmapViewOfFile(mapped);
#else #else
munmap(mapped, len); munmap(mapped, len);
#endif #endif
mapped = 0; mapped = 0;
len = 0; len = 0;
} }
@ -191,14 +191,14 @@ namespace IPC {
void sharedPage::close() { void sharedPage::close() {
unmap(); unmap();
if (handle > 0) { if (handle > 0) {
#ifdef __CYGWIN__ #ifdef __CYGWIN__
CloseHandle(handle); CloseHandle(handle);
#else #else
::close(handle); ::close(handle);
if (master && name != "") { if (master && name != "") {
shm_unlink(name.c_str()); shm_unlink(name.c_str());
} }
#endif #endif
handle = 0; handle = 0;
} }
} }
@ -247,69 +247,69 @@ namespace IPC {
master = master_; master = master_;
mapped = 0; mapped = 0;
if (name.size()) { if (name.size()) {
#ifdef __CYGWIN__ #ifdef __CYGWIN__
if (master){ if (master) {
handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, len, name.c_str()); handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, len, name.c_str());
}else{ } else {
int i = 0; int i = 0;
do { do {
if (i != 0){ if (i != 0) {
Util::sleep(1000); Util::sleep(1000);
}
handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name.c_str());
i++;
} 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));
return;
}
mapped = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (!mapped) {
return;
}
#else
handle = shm_open(name.c_str(), (master ? O_CREAT | O_EXCL : 0) | O_RDWR, ACCESSPERMS);
if (handle == -1) {
if (master) {
DEBUG_MSG(DLVL_HIGH, "Overwriting old page for %s", name.c_str());
handle = shm_open(name.c_str(), O_CREAT | O_RDWR, ACCESSPERMS);
} else {
int i = 0;
while (i < 10 && handle == -1 && autoBackoff) {
i++;
Util::sleep(1000);
handle = shm_open(name.c_str(), O_RDWR, ACCESSPERMS);
}
} }
} handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name.c_str());
if (handle == -1) { i++;
DEBUG_MSG(DLVL_FAIL, "shm_open for page %s failed: %s", name.c_str(), strerror(errno)); } while (i < 10 && !handle && autoBackoff);
return; }
} if (!handle) {
DEBUG_MSG(DLVL_FAIL, "%s for page %s failed: %s", (master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), strerror(errno));
return;
}
mapped = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (!mapped) {
return;
}
#else
handle = shm_open(name.c_str(), (master ? O_CREAT | O_EXCL : 0) | O_RDWR, ACCESSPERMS);
if (handle == -1) {
if (master) { if (master) {
if (ftruncate(handle, 0) < 0) { DEBUG_MSG(DLVL_HIGH, "Overwriting old page for %s", name.c_str());
DEBUG_MSG(DLVL_FAIL, "truncate to zero for page %s failed: %s", name.c_str(), strerror(errno)); handle = shm_open(name.c_str(), O_CREAT | O_RDWR, ACCESSPERMS);
return;
}
if (ftruncate(handle, len) < 0) {
DEBUG_MSG(DLVL_FAIL, "truncate to %lld for page %s failed: %s", len, name.c_str(), strerror(errno));
return;
}
} else { } else {
struct stat buffStats; int i = 0;
int xRes = fstat(handle, &buffStats); while (i < 10 && handle == -1 && autoBackoff) {
if (xRes < 0) { i++;
return; Util::sleep(1000);
handle = shm_open(name.c_str(), O_RDWR, ACCESSPERMS);
} }
len = buffStats.st_size;
} }
mapped = (char *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0); }
if (mapped == MAP_FAILED) { if (handle == -1) {
mapped = 0; DEBUG_MSG(DLVL_FAIL, "shm_open for page %s failed: %s", name.c_str(), strerror(errno));
return;
}
if (master) {
if (ftruncate(handle, 0) < 0) {
DEBUG_MSG(DLVL_FAIL, "truncate to zero for page %s failed: %s", name.c_str(), strerror(errno));
return; return;
} }
#endif if (ftruncate(handle, len) < 0) {
DEBUG_MSG(DLVL_FAIL, "truncate to %lld for page %s failed: %s", len, name.c_str(), strerror(errno));
return;
}
} else {
struct stat buffStats;
int xRes = fstat(handle, &buffStats);
if (xRes < 0) {
return;
}
len = buffStats.st_size;
}
mapped = (char *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);
if (mapped == MAP_FAILED) {
mapped = 0;
return;
}
#endif
} }
} }

View file

@ -11,7 +11,7 @@
#endif #endif
namespace IPC { namespace IPC {
///\brief A class used for the exchange of statistics over shared memory. ///\brief A class used for the exchange of statistics over shared memory.
class statExchange { class statExchange {
public: public:
@ -35,13 +35,13 @@ namespace IPC {
private: private:
///\brief The payload for the stat exchange ///\brief The payload for the stat exchange
/// - 8 byte - now (timestamp of last statistics) /// - 8 byte - now (timestamp of last statistics)
/// - 4 byte - time (duration of the current connection) /// - 4 byte - time (duration of the current connection)
/// - 4 byte - lastSecond (last second of content viewed) /// - 4 byte - lastSecond (last second of content viewed)
/// - 8 byte - down (Number of bytes received from peer) /// - 8 byte - down (Number of bytes received from peer)
/// - 8 byte - up (Number of bytes sent to peer) /// - 8 byte - up (Number of bytes sent to peer)
/// - 16 byte - host (ip address of the peer) /// - 16 byte - host (ip address of the peer)
/// - 20 byte - streamName (name of the stream peer is viewing) /// - 20 byte - streamName (name of the stream peer is viewing)
/// - 20 byte - connector (name of the connector the peer is using) /// - 20 byte - connector (name of the connector the peer is using)
char * data; char * data;
}; };
@ -80,7 +80,7 @@ namespace IPC {
#if !defined __APPLE__ #if !defined __APPLE__
///\brief A class for managing shared memory pages. ///\brief A class for managing shared memory pages.
class sharedPage{ class sharedPage {
public: public:
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true); sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage & rhs); sharedPage(const sharedPage & rhs);
@ -93,13 +93,13 @@ namespace IPC {
} }
void unmap(); void unmap();
void close(); void close();
#ifdef __CYGWIN__ #ifdef __CYGWIN__
///\brief The handle of the opened shared memory page ///\brief The handle of the opened shared memory page
HANDLE handle; HANDLE handle;
#else #else
///\brief The fd handle of the opened shared memory page ///\brief The fd handle of the opened shared memory page
int handle; int handle;
#endif #endif
///\brief The name of the opened shared memory page ///\brief The name of the opened shared memory page
std::string name; std::string name;
///\brief The size in bytes of the opened shared memory page ///\brief The size in bytes of the opened shared memory page
@ -118,7 +118,7 @@ namespace IPC {
#else #else
///\brief A class for managing shared files. ///\brief A class for managing shared files.
#endif #endif
class sharedFile{ class sharedFile {
public: public:
sharedFile(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true); sharedFile(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedFile(const sharedFile & rhs); sharedFile(const sharedFile & rhs);
@ -146,7 +146,7 @@ namespace IPC {
///\brief A class for handling shared memory pages. ///\brief A class for handling shared memory pages.
/// ///
///Uses shared files at its backbone, defined for portability ///Uses shared files at its backbone, defined for portability
class sharedPage: public sharedFile{ class sharedPage: public sharedFile {
public: public:
sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true); sharedPage(std::string name_ = "", unsigned int len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage & rhs); 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. ///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. ///If no such length can be allocated, the next page should be tried, and so on.
class sharedServer{ class sharedServer {
public: public:
sharedServer(); sharedServer();
sharedServer(std::string name, int len, bool withCounter = false); 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. ///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. ///If no such length can be allocated, the next page should be tried, and so on.
class sharedClient{ class sharedClient {
public: public:
sharedClient(); sharedClient();
sharedClient(const sharedClient & rhs); sharedClient(const sharedClient & rhs);

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,10 +25,10 @@ freely, subject to the following restrictions:
#include "tinythread.h" #include "tinythread.h"
#if defined(_TTHREAD_POSIX_) #if defined(_TTHREAD_POSIX_)
#include <unistd.h> #include <unistd.h>
#include <map> #include <map>
#elif defined(_TTHREAD_WIN32_) #elif defined(_TTHREAD_WIN32_)
#include <process.h> #include <process.h>
#endif #endif
@ -49,74 +49,69 @@ namespace tthread {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
#define _CONDITION_EVENT_ONE 0 #define _CONDITION_EVENT_ONE 0
#define _CONDITION_EVENT_ALL 1 #define _CONDITION_EVENT_ALL 1
#endif #endif
#if defined(_TTHREAD_WIN32_) #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_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL); mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL); InitializeCriticalSection(&mWaitersCountLock);
InitializeCriticalSection(&mWaitersCountLock); }
}
#endif #endif
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
condition_variable::~condition_variable() condition_variable::~condition_variable() {
{ CloseHandle(mEvents[_CONDITION_EVENT_ONE]);
CloseHandle(mEvents[_CONDITION_EVENT_ONE]); CloseHandle(mEvents[_CONDITION_EVENT_ALL]);
CloseHandle(mEvents[_CONDITION_EVENT_ALL]); DeleteCriticalSection(&mWaitersCountLock);
DeleteCriticalSection(&mWaitersCountLock); }
}
#endif #endif
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void condition_variable::_wait() void condition_variable::_wait() {
{ // Wait for either event to become signaled due to notify_one() or
// Wait for either event to become signaled due to notify_one() or // notify_all() being called
// notify_all() being called int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE);
int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE);
// Check if we are the last waiter // Check if we are the last waiter
EnterCriticalSection(&mWaitersCountLock); EnterCriticalSection(&mWaitersCountLock);
-- mWaitersCount; -- mWaitersCount;
bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
(mWaitersCount == 0); (mWaitersCount == 0);
LeaveCriticalSection(&mWaitersCountLock); LeaveCriticalSection(&mWaitersCountLock);
// If we are the last waiter to be notified to stop waiting, reset the event // If we are the last waiter to be notified to stop waiting, reset the event
if(lastWaiter) if (lastWaiter)
ResetEvent(mEvents[_CONDITION_EVENT_ALL]); ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
} }
#endif #endif
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void condition_variable::notify_one() void condition_variable::notify_one() {
{ // Are there any waiters?
// Are there any waiters? EnterCriticalSection(&mWaitersCountLock);
EnterCriticalSection(&mWaitersCountLock); bool haveWaiters = (mWaitersCount > 0);
bool haveWaiters = (mWaitersCount > 0); LeaveCriticalSection(&mWaitersCountLock);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal // If we have any waiting threads, send them a signal
if(haveWaiters) if (haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ONE]); SetEvent(mEvents[_CONDITION_EVENT_ONE]);
} }
#endif #endif
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void condition_variable::notify_all() void condition_variable::notify_all() {
{ // Are there any waiters?
// Are there any waiters? EnterCriticalSection(&mWaitersCountLock);
EnterCriticalSection(&mWaitersCountLock); bool haveWaiters = (mWaitersCount > 0);
bool haveWaiters = (mWaitersCount > 0); LeaveCriticalSection(&mWaitersCountLock);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal // If we have any waiting threads, send them a signal
if(haveWaiters) if (haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ALL]); SetEvent(mEvents[_CONDITION_EVENT_ALL]);
} }
#endif #endif
@ -128,17 +123,16 @@ void condition_variable::notify_all()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(_TTHREAD_POSIX_) #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 mutex idMapLock; static std::map<pthread_t, unsigned long int> idMap;
static std::map<pthread_t, unsigned long int> idMap; static unsigned long int idCount(1);
static unsigned long int idCount(1);
lock_guard<mutex> guard(idMapLock); lock_guard<mutex> guard(idMapLock);
if(idMap.find(aHandle) == idMap.end()) if (idMap.find(aHandle) == idMap.end())
idMap[aHandle] = idCount ++; idMap[aHandle] = idCount ++;
return thread::id(idMap[aHandle]); return thread::id(idMap[aHandle]);
} }
#endif // _TTHREAD_POSIX_ #endif // _TTHREAD_POSIX_
@ -147,165 +141,151 @@ static thread::id _pthread_t_to_ID(const pthread_t &aHandle)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/// Information to pass to the new thread (what to run). /// 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 (*mFunction)(void *); ///< Pointer to the function to be executed.
void * mArg; ///< Function argument for the thread function. void * mArg; ///< Function argument for the thread function.
thread * mThread; ///< Pointer to the thread object. thread * mThread; ///< Pointer to the thread object.
}; };
// Thread wrapper function. // Thread wrapper function.
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
unsigned WINAPI thread::wrapper_function(void * aArg) unsigned WINAPI thread::wrapper_function(void * aArg)
#elif defined(_TTHREAD_POSIX_) #elif defined(_TTHREAD_POSIX_)
void * thread::wrapper_function(void * aArg) void * thread::wrapper_function(void * aArg)
#endif #endif
{
// Get thread startup information
_thread_start_info * ti = (_thread_start_info *) aArg;
try
{ {
// Call the actual client thread function // Get thread startup information
ti->mFunction(ti->mArg); _thread_start_info * ti = (_thread_start_info *) aArg;
}
catch(...)
{
// Uncaught exceptions will terminate the application (default behavior
// according to C++11)
std::terminate();
}
// The thread is no longer executing try {
if (ti->mThread){ // Call the actual client thread function
lock_guard<mutex> guard(ti->mThread->mDataMutex); ti->mFunction(ti->mArg);
ti->mThread->mNotAThread = true; } catch (...) {
ti->mThread->ti_copy = 0; // Uncaught exceptions will terminate the application (default behavior
} // according to C++11)
std::terminate();
}
// The thread is responsible for freeing the startup information // The thread is no longer executing
delete ti; if (ti->mThread) {
lock_guard<mutex> guard(ti->mThread->mDataMutex);
ti->mThread->mNotAThread = true;
ti->mThread->ti_copy = 0;
}
return 0; // The thread is responsible for freeing the startup information
}
thread::thread(void (*aFunction)(void *), void * aArg)
{
// Serialize access to this thread structure
lock_guard<mutex> guard(mDataMutex);
// Fill out the thread startup information (passed to the thread wrapper,
// which will eventually free it)
_thread_start_info * ti = new _thread_start_info;
ti_copy = ti;
ti->mFunction = aFunction;
ti->mArg = aArg;
ti->mThread = this;
// The thread is now alive
mNotAThread = false;
// Create the thread
#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)
mHandle = 0;
#endif
// Did we fail to create the thread?
if(!mHandle)
{
mNotAThread = true;
ti_copy = 0;
delete ti; delete ti;
}
}
thread::~thread() return 0;
{
if (ti_copy){
((_thread_start_info *)ti_copy)->mThread = 0;
} }
if(joinable())
std::terminate();
}
void thread::join() thread::thread(void (*aFunction)(void *), void * aArg) {
{ // Serialize access to this thread structure
if(joinable()) lock_guard<mutex> guard(mDataMutex);
{
// Fill out the thread startup information (passed to the thread wrapper,
// which will eventually free it)
_thread_start_info * ti = new _thread_start_info;
ti_copy = ti;
ti->mFunction = aFunction;
ti->mArg = aArg;
ti->mThread = this;
// The thread is now alive
mNotAThread = false;
// Create the thread
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
WaitForSingleObject(mHandle, INFINITE); mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID);
CloseHandle(mHandle);
#elif defined(_TTHREAD_POSIX_) #elif defined(_TTHREAD_POSIX_)
pthread_join(mHandle, NULL); if (pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0)
mHandle = 0;
#endif
// Did we fail to create the thread?
if (!mHandle) {
mNotAThread = true;
ti_copy = 0;
delete ti;
}
}
thread::~thread() {
if (ti_copy) {
((_thread_start_info *)ti_copy)->mThread = 0;
}
if (joinable())
std::terminate();
}
void thread::join() {
if (joinable()) {
#if defined(_TTHREAD_WIN32_)
WaitForSingleObject(mHandle, INFINITE);
CloseHandle(mHandle);
#elif defined(_TTHREAD_POSIX_)
pthread_join(mHandle, NULL);
#endif
}
}
bool thread::joinable() const {
mDataMutex.lock();
bool result = !mNotAThread;
mDataMutex.unlock();
return result;
}
void thread::detach() {
mDataMutex.lock();
if (!mNotAThread) {
#if defined(_TTHREAD_WIN32_)
CloseHandle(mHandle);
#elif defined(_TTHREAD_POSIX_)
pthread_detach(mHandle);
#endif
mNotAThread = true;
}
mDataMutex.unlock();
}
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 #endif
} }
}
bool thread::joinable() const unsigned thread::hardware_concurrency() {
{
mDataMutex.lock();
bool result = !mNotAThread;
mDataMutex.unlock();
return result;
}
void thread::detach()
{
mDataMutex.lock();
if(!mNotAThread)
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
CloseHandle(mHandle); SYSTEM_INFO si;
#elif defined(_TTHREAD_POSIX_) GetSystemInfo(&si);
pthread_detach(mHandle); return (int) si.dwNumberOfProcessors;
#endif
mNotAThread = true;
}
mDataMutex.unlock();
}
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()
{
#if defined(_TTHREAD_WIN32_)
SYSTEM_INFO si;
GetSystemInfo(&si);
return (int) si.dwNumberOfProcessors;
#elif defined(_SC_NPROCESSORS_ONLN) #elif defined(_SC_NPROCESSORS_ONLN)
return (int) sysconf(_SC_NPROCESSORS_ONLN); return (int) sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_SC_NPROC_ONLN) #elif defined(_SC_NPROC_ONLN)
return (int) sysconf(_SC_NPROC_ONLN); return (int) sysconf(_SC_NPROC_ONLN);
#else #else
// The standard requires this function to return zero if the number of // The standard requires this function to return zero if the number of
// hardware cores could not be determined. // hardware cores could not be determined.
return 0; return 0;
#endif #endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// this_thread // this_thread
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
thread::id this_thread::get_id() thread::id this_thread::get_id() {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
return thread::id((unsigned long int) GetCurrentThreadId()); return thread::id((unsigned long int) GetCurrentThreadId());
#elif defined(_TTHREAD_POSIX_) #elif defined(_TTHREAD_POSIX_)
return _pthread_t_to_ID(pthread_self()); return _pthread_t_to_ID(pthread_self());
#endif #endif
} }
} }

View file

@ -57,30 +57,30 @@ freely, subject to the following restrictions:
// Which platform are we on? // Which platform are we on?
#if !defined(_TTHREAD_PLATFORM_DEFINED_) #if !defined(_TTHREAD_PLATFORM_DEFINED_)
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
#define _TTHREAD_WIN32_ #define _TTHREAD_WIN32_
#else #else
#define _TTHREAD_POSIX_ #define _TTHREAD_POSIX_
#endif #endif
#define _TTHREAD_PLATFORM_DEFINED_ #define _TTHREAD_PLATFORM_DEFINED_
#endif #endif
// Platform specific includes // Platform specific includes
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define __UNDEF_LEAN_AND_MEAN #define __UNDEF_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#ifdef __UNDEF_LEAN_AND_MEAN #ifdef __UNDEF_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN
#undef __UNDEF_LEAN_AND_MEAN #undef __UNDEF_LEAN_AND_MEAN
#endif #endif
#else #else
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
#include <sched.h> #include <sched.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
// Generic includes // Generic includes
@ -95,23 +95,23 @@ freely, subject to the following restrictions:
// Do we have a fully featured C++11 compiler? // Do we have a fully featured C++11 compiler?
#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L)) #if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L))
#define _TTHREAD_CPP11_ #define _TTHREAD_CPP11_
#endif #endif
// ...at least partial C++11? // ...at least partial C++11?
#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) #if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
#define _TTHREAD_CPP11_PARTIAL_ #define _TTHREAD_CPP11_PARTIAL_
#endif #endif
// Macro for disabling assignments of objects. // Macro for disabling assignments of objects.
#ifdef _TTHREAD_CPP11_PARTIAL_ #ifdef _TTHREAD_CPP11_PARTIAL_
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \ #define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&) = delete; \ name(const name&) = delete; \
name& operator=(const name&) = delete; name& operator=(const name&) = delete;
#else #else
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \ #define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&); \ name(const name&); \
name& operator=(const name&); name& operator=(const name&);
#endif #endif
/// @def thread_local /// @def thread_local
@ -136,11 +136,11 @@ freely, subject to the following restrictions:
/// @hideinitializer /// @hideinitializer
#if !defined(_TTHREAD_CPP11_) && !defined(thread_local) #if !defined(_TTHREAD_CPP11_) && !defined(thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define thread_local __thread #define thread_local __thread
#else #else
#define thread_local __declspec(thread) #define thread_local __declspec(thread)
#endif #endif
#endif #endif
@ -156,91 +156,86 @@ namespace tthread {
/// program may deadlock if the thread that owns a mutex object calls lock() /// program may deadlock if the thread that owns a mutex object calls lock()
/// on that object). /// on that object).
/// @see recursive_mutex /// @see recursive_mutex
class mutex { class mutex {
public: public:
/// Constructor. /// Constructor.
mutex() mutex()
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
: mAlreadyLocked(false) : mAlreadyLocked(false)
#endif #endif
{
#if defined(_TTHREAD_WIN32_)
InitializeCriticalSection(&mHandle);
#else
pthread_mutex_init(&mHandle, NULL);
#endif
}
/// Destructor.
~mutex()
{
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mHandle);
#else
pthread_mutex_destroy(&mHandle);
#endif
}
/// Lock the 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()
{
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mHandle);
while(mAlreadyLocked) Sleep(1000); // Simulate deadlock...
mAlreadyLocked = true;
#else
pthread_mutex_lock(&mHandle);
#endif
}
/// Try to lock the mutex.
/// The method will try to lock the mutex. If it fails, the function will
/// 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()
{
#if defined(_TTHREAD_WIN32_)
bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
if(ret && mAlreadyLocked)
{ {
LeaveCriticalSection(&mHandle); #if defined(_TTHREAD_WIN32_)
ret = false; InitializeCriticalSection(&mHandle);
#else
pthread_mutex_init(&mHandle, NULL);
#endif
} }
return ret;
#else
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
#endif
}
/// Unlock the mutex. /// Destructor.
/// If any threads are waiting for the lock on this mutex, one of them will ~mutex() {
/// be unblocked.
inline void unlock()
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
mAlreadyLocked = false; DeleteCriticalSection(&mHandle);
LeaveCriticalSection(&mHandle);
#else #else
pthread_mutex_unlock(&mHandle); pthread_mutex_destroy(&mHandle);
#endif #endif
} }
_TTHREAD_DISABLE_ASSIGNMENT(mutex) /// Lock the mutex.
/// The method will block the calling thread until a lock on the mutex can
private: /// be obtained. The mutex remains locked until @c unlock() is called.
/// @see lock_guard
inline void lock() {
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
CRITICAL_SECTION mHandle; EnterCriticalSection(&mHandle);
bool mAlreadyLocked; while (mAlreadyLocked) Sleep(1000); // Simulate deadlock...
mAlreadyLocked = true;
#else #else
pthread_mutex_t mHandle; pthread_mutex_lock(&mHandle);
#endif
}
/// Try to lock the mutex.
/// The method will try to lock the mutex. If it fails, the function will
/// 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() {
#if defined(_TTHREAD_WIN32_)
bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
if (ret && mAlreadyLocked) {
LeaveCriticalSection(&mHandle);
ret = false;
}
return ret;
#else
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
#endif
}
/// Unlock the mutex.
/// If any threads are waiting for the lock on this mutex, one of them will
/// be unblocked.
inline void unlock() {
#if defined(_TTHREAD_WIN32_)
mAlreadyLocked = false;
LeaveCriticalSection(&mHandle);
#else
pthread_mutex_unlock(&mHandle);
#endif
}
_TTHREAD_DISABLE_ASSIGNMENT(mutex)
private:
#if defined(_TTHREAD_WIN32_)
CRITICAL_SECTION mHandle;
bool mAlreadyLocked;
#else
pthread_mutex_t mHandle;
#endif #endif
friend class condition_variable; friend class condition_variable;
}; };
/// Recursive mutex class. /// Recursive mutex class.
/// This is a mutual exclusion object for synchronizing access to shared /// This is a mutual exclusion object for synchronizing access to shared
@ -248,81 +243,76 @@ class mutex {
/// may lock the mutex several times, as long as it unlocks the mutex the same /// may lock the mutex several times, as long as it unlocks the mutex the same
/// number of times). /// number of times).
/// @see mutex /// @see mutex
class recursive_mutex { class recursive_mutex {
public: public:
/// Constructor. /// Constructor.
recursive_mutex() recursive_mutex() {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
InitializeCriticalSection(&mHandle); InitializeCriticalSection(&mHandle);
#else #else
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mHandle, &attr); pthread_mutex_init(&mHandle, &attr);
#endif #endif
} }
/// Destructor. /// Destructor.
~recursive_mutex() ~recursive_mutex() {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mHandle); DeleteCriticalSection(&mHandle);
#else #else
pthread_mutex_destroy(&mHandle); pthread_mutex_destroy(&mHandle);
#endif #endif
} }
/// Lock the mutex. /// Lock the mutex.
/// The method will block the calling thread until a lock on the mutex can /// 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. /// be obtained. The mutex remains locked until @c unlock() is called.
/// @see lock_guard /// @see lock_guard
inline void lock() inline void lock() {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mHandle); EnterCriticalSection(&mHandle);
#else #else
pthread_mutex_lock(&mHandle); pthread_mutex_lock(&mHandle);
#endif #endif
} }
/// Try to lock the mutex. /// Try to lock the mutex.
/// The method will try to lock the mutex. If it fails, the function will /// The method will try to lock the mutex. If it fails, the function will
/// return immediately (non-blocking). /// return immediately (non-blocking).
/// @return @c true if the lock was acquired, or @c false if the lock could /// @return @c true if the lock was acquired, or @c false if the lock could
/// not be acquired. /// not be acquired.
inline bool try_lock() inline bool try_lock() {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
return TryEnterCriticalSection(&mHandle) ? true : false; return TryEnterCriticalSection(&mHandle) ? true : false;
#else #else
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false; return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
#endif #endif
} }
/// Unlock the mutex. /// Unlock the mutex.
/// If any threads are waiting for the lock on this mutex, one of them will /// If any threads are waiting for the lock on this mutex, one of them will
/// be unblocked. /// be unblocked.
inline void unlock() inline void unlock() {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
LeaveCriticalSection(&mHandle); LeaveCriticalSection(&mHandle);
#else #else
pthread_mutex_unlock(&mHandle); pthread_mutex_unlock(&mHandle);
#endif #endif
} }
_TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex) _TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex)
private: private:
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
CRITICAL_SECTION mHandle; CRITICAL_SECTION mHandle;
#else #else
pthread_mutex_t mHandle; pthread_mutex_t mHandle;
#endif #endif
friend class condition_variable; friend class condition_variable;
}; };
/// Lock guard class. /// Lock guard class.
/// The constructor locks the mutex, and the destructor unlocks the mutex, so /// The constructor locks the mutex, and the destructor unlocks the mutex, so
@ -339,30 +329,28 @@ class recursive_mutex {
/// } /// }
/// @endcode /// @endcode
template <class T> template <class T>
class lock_guard { class lock_guard {
public: public:
typedef T mutex_type; typedef T mutex_type;
lock_guard() : mMutex(0) {} lock_guard() : mMutex(0) {}
/// The constructor locks the mutex. /// The constructor locks the mutex.
explicit lock_guard(mutex_type &aMutex) explicit lock_guard(mutex_type & aMutex) {
{ mMutex = &aMutex;
mMutex = &aMutex; mMutex->lock();
mMutex->lock(); }
}
/// The destructor unlocks the mutex. /// The destructor unlocks the mutex.
~lock_guard() ~lock_guard() {
{ if (mMutex)
if(mMutex) mMutex->unlock();
mMutex->unlock(); }
}
private: private:
mutex_type * mMutex; mutex_type * mMutex;
}; };
/// Condition variable class. /// Condition variable class.
/// This is a signalling object for synchronizing the execution flow for /// This is a signalling object for synchronizing the execution flow for
@ -389,323 +377,308 @@ class lock_guard {
/// cond.notify_all(); /// cond.notify_all();
/// } /// }
/// @endcode /// @endcode
class condition_variable { class condition_variable {
public: public:
/// Constructor. /// Constructor.
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
condition_variable(); condition_variable();
#else #else
condition_variable() condition_variable() {
{ pthread_cond_init(&mHandle, NULL);
pthread_cond_init(&mHandle, NULL); }
}
#endif #endif
/// Destructor. /// Destructor.
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
~condition_variable(); ~condition_variable();
#else #else
~condition_variable() ~condition_variable() {
{ pthread_cond_destroy(&mHandle);
pthread_cond_destroy(&mHandle); }
}
#endif #endif
/// Wait for the condition. /// Wait for the condition.
/// The function will block the calling thread until the condition variable /// The function will block the calling thread until the condition variable
/// is woken by @c notify_one(), @c notify_all() or a spurious wake up. /// is woken by @c notify_one(), @c notify_all() or a spurious wake up.
/// @param[in] aMutex A mutex that will be unlocked when the wait operation /// @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. /// starts, an locked again as soon as the wait operation is finished.
template <class _mutexT> template <class _mutexT>
inline void wait(_mutexT &aMutex) inline void wait(_mutexT & aMutex) {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
// Increment number of waiters // Increment number of waiters
EnterCriticalSection(&mWaitersCountLock); EnterCriticalSection(&mWaitersCountLock);
++ mWaitersCount; ++ mWaitersCount;
LeaveCriticalSection(&mWaitersCountLock); LeaveCriticalSection(&mWaitersCountLock);
// Release the mutex while waiting for the condition (will decrease // Release the mutex while waiting for the condition (will decrease
// the number of waiters when done)... // the number of waiters when done)...
aMutex.unlock(); aMutex.unlock();
_wait(); _wait();
aMutex.lock(); aMutex.lock();
#else #else
pthread_cond_wait(&mHandle, &aMutex.mHandle); pthread_cond_wait(&mHandle, &aMutex.mHandle);
#endif #endif
} }
/// Notify one thread that is waiting for the condition. /// Notify one thread that is waiting for the condition.
/// If at least one thread is blocked waiting for this condition variable, /// If at least one thread is blocked waiting for this condition variable,
/// one will be woken up. /// one will be woken up.
/// @note Only threads that started waiting prior to this call will be /// @note Only threads that started waiting prior to this call will be
/// woken up. /// woken up.
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void notify_one(); void notify_one();
#else #else
inline void notify_one() inline void notify_one() {
{ pthread_cond_signal(&mHandle);
pthread_cond_signal(&mHandle); }
}
#endif #endif
/// Notify all threads that are waiting for the condition. /// Notify all threads that are waiting for the condition.
/// All threads that are blocked waiting for this condition variable will /// All threads that are blocked waiting for this condition variable will
/// be woken up. /// be woken up.
/// @note Only threads that started waiting prior to this call will be /// @note Only threads that started waiting prior to this call will be
/// woken up. /// woken up.
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void notify_all(); void notify_all();
#else #else
inline void notify_all() inline void notify_all() {
{ pthread_cond_broadcast(&mHandle);
pthread_cond_broadcast(&mHandle); }
}
#endif #endif
_TTHREAD_DISABLE_ASSIGNMENT(condition_variable) _TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
private: private:
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void _wait(); void _wait();
HANDLE mEvents[2]; ///< Signal and broadcast event HANDLEs. HANDLE mEvents[2]; ///< Signal and broadcast event HANDLEs.
unsigned int mWaitersCount; ///< Count of the number of waiters. unsigned int mWaitersCount; ///< Count of the number of waiters.
CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount. CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount.
#else #else
pthread_cond_t mHandle; pthread_cond_t mHandle;
#endif #endif
}; };
/// Thread class. /// Thread class.
class thread { class thread {
public: public:
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
typedef HANDLE native_handle_type; typedef HANDLE native_handle_type;
#else #else
typedef pthread_t native_handle_type; typedef pthread_t native_handle_type;
#endif #endif
class id; class id;
/// Default constructor. /// Default constructor.
/// Construct a @c thread object without an associated thread of execution /// Construct a @c thread object without an associated thread of execution
/// (i.e. non-joinable). /// (i.e. non-joinable).
thread() : mHandle(0), mNotAThread(true) thread() : mHandle(0), mNotAThread(true)
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
, mWin32ThreadID(0) , mWin32ThreadID(0)
#endif #endif
{} {}
/// Thread starting constructor. /// Thread starting constructor.
/// Construct a @c thread object with a new thread of execution. /// Construct a @c thread object with a new thread of execution.
/// @param[in] aFunction A function pointer to a function of type: /// @param[in] aFunction A function pointer to a function of type:
/// <tt>void fun(void * arg)</tt> /// <tt>void fun(void * arg)</tt>
/// @param[in] aArg Argument to the thread function. /// @param[in] aArg Argument to the thread function.
/// @note This constructor is not fully compatible with the standard C++ /// @note This constructor is not fully compatible with the standard C++
/// thread class. It is more similar to the pthread_create() (POSIX) and /// thread class. It is more similar to the pthread_create() (POSIX) and
/// CreateThread() (Windows) functions. /// CreateThread() (Windows) functions.
thread(void (*aFunction)(void *), void * aArg); thread(void (*aFunction)(void *), void * aArg);
/// Destructor. /// Destructor.
/// @note If the thread is joinable upon destruction, @c std::terminate() /// @note If the thread is joinable upon destruction, @c std::terminate()
/// will be called, which terminates the process. It is always wise to do /// will be called, which terminates the process. It is always wise to do
/// @c join() before deleting a thread object. /// @c join() before deleting a thread object.
~thread(); ~thread();
/// Wait for the thread to finish (join execution flows). /// Wait for the thread to finish (join execution flows).
/// After calling @c join(), the thread object is no longer associated with /// After calling @c join(), the thread object is no longer associated with
/// a thread of execution (i.e. it is not joinable, and you may not join /// a thread of execution (i.e. it is not joinable, and you may not join
/// with it nor detach from it). /// with it nor detach from it).
void join(); void join();
/// Check if the thread is joinable. /// Check if the thread is joinable.
/// A thread object is joinable if it has an associated thread of execution. /// A thread object is joinable if it has an associated thread of execution.
bool joinable() const; bool joinable() const;
/// Detach from the thread. /// Detach from the thread.
/// After calling @c detach(), the thread object is no longer assicated with /// After calling @c detach(), the thread object is no longer assicated with
/// a thread of execution (i.e. it is not joinable). The thread continues /// a thread of execution (i.e. it is not joinable). The thread continues
/// execution without the calling thread blocking, and when the thread /// execution without the calling thread blocking, and when the thread
/// ends execution, any owned resources are released. /// ends execution, any owned resources are released.
void detach(); void detach();
/// Return the thread ID of a thread object. /// Return the thread ID of a thread object.
id get_id() const; id get_id() const;
/// Get the native handle for this thread. /// Get the native handle for this thread.
/// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
/// is a @c pthread_t. /// is a @c pthread_t.
inline native_handle_type native_handle() inline native_handle_type native_handle() {
{ return mHandle;
return mHandle; }
}
/// Determine the number of threads which can possibly execute concurrently. /// Determine the number of threads which can possibly execute concurrently.
/// This function is useful for determining the optimal number of threads to /// This function is useful for determining the optimal number of threads to
/// use for a task. /// use for a task.
/// @return The number of hardware thread contexts in the system. /// @return The number of hardware thread contexts in the system.
/// @note If this value is not defined, the function returns zero (0). /// @note If this value is not defined, the function returns zero (0).
static unsigned hardware_concurrency(); static unsigned hardware_concurrency();
_TTHREAD_DISABLE_ASSIGNMENT(thread) _TTHREAD_DISABLE_ASSIGNMENT(thread)
private: private:
native_handle_type mHandle; ///< Thread handle. native_handle_type mHandle; ///< Thread handle.
mutable mutex mDataMutex; ///< Serializer for access to the thread private data. mutable mutex mDataMutex; ///< Serializer for access to the thread private data.
bool mNotAThread; ///< True if this object is not a thread of execution. bool mNotAThread; ///< True if this object is not a thread of execution.
void * ti_copy; void * ti_copy;
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex). unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
#endif #endif
// This is the internal thread wrapper function. // This is the internal thread wrapper function.
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
static unsigned WINAPI wrapper_function(void * aArg); static unsigned WINAPI wrapper_function(void * aArg);
#else #else
static void * wrapper_function(void * aArg); static void * wrapper_function(void * aArg);
#endif #endif
}; };
/// Thread ID. /// Thread ID.
/// The thread ID is a unique identifier for each thread. /// The thread ID is a unique identifier for each thread.
/// @see thread::get_id() /// @see thread::get_id()
class thread::id { class thread::id {
public: public:
/// Default constructor. /// Default constructor.
/// The default constructed ID is that of thread without a thread of /// The default constructed ID is that of thread without a thread of
/// execution. /// execution.
id() : mId(0) {}; id() : mId(0) {};
id(unsigned long int aId) : mId(aId) {}; 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;
mId = aId.mId; return *this;
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);
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);
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);
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);
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);
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);
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;
os << obj.mId; return os;
return os; }
}
private: private:
unsigned long int mId; unsigned long int mId;
}; };
// Related to <ratio> - minimal to be able to support chrono. // 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 /// Minimal implementation of the @c ratio class. This class provides enough
/// functionality to implement some basic @c chrono classes. /// 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); }
};
/// Minimal implementation of the @c chrono namespace.
/// The @c chrono namespace provides types for specifying time intervals.
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 {
private:
_Rep rep_;
public: public:
typedef _Rep rep; static double _as_double() {
typedef _Period period; return double(N) / double(D);
/// Construct a duration object with the given duration.
template <class _Rep2>
explicit duration(const _Rep2& r) : rep_(r) {};
/// Return the value of the duration object.
rep count() const
{
return rep_;
} }
}; };
// Standard duration types. /// Minimal implementation of the @c chrono namespace.
typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds. /// The @c chrono namespace provides types for specifying time intervals.
typedef duration<__intmax_t, ratio<1, 1000000> > microseconds; ///< Duration with the unit microseconds. namespace chrono {
typedef duration<__intmax_t, ratio<1, 1000> > milliseconds; ///< Duration with the unit milliseconds. /// Duration template class. This class provides enough functionality to
typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds. /// implement @c this_thread::sleep_for().
typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes. template <class _Rep, class _Period = ratio<1> > class duration {
typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours. private:
} _Rep rep_;
public:
typedef _Rep rep;
typedef _Period period;
/// Construct a duration object with the given duration.
template <class _Rep2>
explicit duration(const _Rep2 & r) : rep_(r) {};
/// Return the value of the duration object.
rep count() const {
return rep_;
}
};
// Standard duration types.
typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds.
typedef duration<__intmax_t, ratio<1, 1000000> > microseconds; ///< Duration with the unit microseconds.
typedef duration<__intmax_t, ratio<1, 1000> > milliseconds; ///< Duration with the unit milliseconds.
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 /// The namespace @c this_thread provides methods for dealing with the
/// calling thread. /// calling thread.
namespace this_thread { namespace this_thread {
/// Return the thread ID of the calling thread. /// Return the thread ID of the calling thread.
thread::id get_id(); thread::id get_id();
/// Yield execution to another thread. /// Yield execution to another thread.
/// Offers the operating system the opportunity to schedule another thread /// Offers the operating system the opportunity to schedule another thread
/// that is ready to run on the current processor. /// that is ready to run on the current processor.
inline void yield() inline void yield() {
{
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
Sleep(0); Sleep(0);
#else #else
sched_yield(); sched_yield();
#endif #endif
} }
/// Blocks the calling thread for a period of time. /// Blocks the calling thread for a period of time.
/// @param[in] aTime Minimum time to put the thread to sleep. /// @param[in] aTime Minimum time to put the thread to sleep.
/// Example usage: /// Example usage:
/// @code /// @code
/// // Sleep for 100 milliseconds /// // Sleep for 100 milliseconds
/// this_thread::sleep_for(chrono::milliseconds(100)); /// this_thread::sleep_for(chrono::milliseconds(100));
/// @endcode /// @endcode
/// @note Supported duration types are: nanoseconds, microseconds, /// @note Supported duration types are: nanoseconds, microseconds,
/// milliseconds, seconds, minutes and hours. /// 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_) #if defined(_TTHREAD_WIN32_)
Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5)); Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
#else #else
usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5)); usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
#endif #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. /// It fills the content with the next 188 bytes int he file.
/// \param Data The data to be read into the packet. /// \param Data The data to be read into the packet.
/// \return true if it was possible to read in a full packet, false otherwise. /// \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); strBuf.resize(188);
if (!fread((void*)strBuf.data(), 188, 1, data)){ if (!fread((void *)strBuf.data(), 188, 1, data)) {
return false; return false;
} }
return true; return true;
@ -577,12 +577,12 @@ namespace TS {
///Gets the payload of this packet, as a raw char array ///Gets the payload of this packet, as a raw char array
///\return The payload of this ts packet as a char pointer ///\return The payload of this ts packet as a char pointer
const char * Packet::getPayload() { 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 ///Gets the length of the payload for this apcket
///\return The amount of bytes payload in this packet ///\return The amount of bytes payload in this packet
int Packet::getPayloadLength(){ int Packet::getPayloadLength() {
return 184 - ((AdaptationField() > 1 ? AdaptationFieldLen() + 1 : 0)); return 184 - ((AdaptationField() > 1 ? AdaptationFieldLen() + 1 : 0));
} }

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

@ -162,13 +162,14 @@ namespace TS {
//0xF000 = reserved(3) = 7, network pid = 4096 //0xF000 = reserved(3) = 7, network pid = 4096
//0x2AB104B2 = CRC32 //0x2AB104B2 = CRC32
static char PAT[188] = {0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0xB0, 0x0D, 0x00, 0x01, 0xC1, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x2A, 0xB1, 0x04, static char PAT[188] = {0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0xB0, 0x0D, 0x00, 0x01, 0xC1, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x2A, 0xB1, 0x04,
0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 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, 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, 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. /// A standard Program Mapping Table, as generated by FFMPEG.
/// Contains both Audio and Video mappings, works also on video- or audio-only streams. /// Contains both Audio and Video mappings, works also on video- or audio-only streams.
@ -192,13 +193,14 @@ namespace TS {
//0xF000 = reserved(4) = 15, es_info_len = 0 //0xF000 = reserved(4) = 15, es_info_len = 0
//0x2F44B99B = CRC32 //0x2F44B99B = CRC32
static char PMT[188] = {0x47, 0x50, 0x00, 0x10, 0x00, 0x02, 0xB0, 0x17, 0x00, 0x01, 0xC1, 0x00, 0x00, 0xE1, 0x00, 0xF0, 0x00, 0x1B, 0xE1, 0x00, static char PMT[188] = {0x47, 0x50, 0x00, 0x10, 0x00, 0x02, 0xB0, 0x17, 0x00, 0x01, 0xC1, 0x00, 0x00, 0xE1, 0x00, 0xF0, 0x00, 0x1B, 0xE1, 0x00,
0xF0, 0x00, 0x0F, 0xE1, 0x01, 0xF0, 0x00, 0x2F, 0x44, 0xB9, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xE1, 0x01, 0xF0, 0x00, 0x2F, 0x44, 0xB9, 0x9B, 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, 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, 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 } //TS namespace

View file

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

View file

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