Prettified error messages, first work on Util::Config server helpers.

This commit is contained in:
Thulinma 2014-01-22 23:47:59 +01:00
parent c6f63dfb95
commit 5c0f053006
25 changed files with 1254 additions and 327 deletions

View file

@ -13,7 +13,9 @@ endif
CPPFLAGS = -Wall -g -O2 -fPIC CPPFLAGS = -Wall -g -O2 -fPIC
override CPPFLAGS += -funsigned-char -DDEBUG="$(DEBUG)" -DPACKAGE_VERSION="\"$(PACKAGE_VERSION)\"" override CPPFLAGS += -funsigned-char -DDEBUG="$(DEBUG)" -DPACKAGE_VERSION="\"$(PACKAGE_VERSION)\""
LDLIBS = -lcrypto -lrt LDLIBS = -lcrypto
THREADLIB = -lpthread -lrt
LDLIBS = -lcrypto $(THREADLIB)
.DEFAULT_GOAL := all .DEFAULT_GOAL := all

3
README
View file

@ -6,6 +6,9 @@
| See COPYING file for full license | | See COPYING file for full license |
|_________________________________________________| |_________________________________________________|
NOTE: TinyThread++ is included also, but *not* copyright DDVTech BV.
License and author information for TinyThread++ can be found in the tinythread.h/cpp files.
The latest version of this code can always be found at: The latest version of this code can always be found at:
https://github.com/DDVTECH/mistlib https://github.com/DDVTECH/mistlib

View file

@ -2,8 +2,8 @@
/// Holds all code for the AMF namespace. /// Holds all code for the AMF namespace.
#include "amf.h" #include "amf.h"
#include "defines.h"
#include <sstream> #include <sstream>
#include <cstdio> //needed for stderr only
/// Returns the std::string Indice for the current object, if available. /// Returns the std::string Indice for the current object, if available.
/// Returns an empty string if no indice exists. /// Returns an empty string if no indice exists.
std::string AMF::Object::Indice(){ std::string AMF::Object::Indice(){
@ -124,9 +124,9 @@ AMF::Object::Object(std::string indice, AMF::obj0type setType){ //object type in
numval = 0; numval = 0;
} }
/// Prints the contents of this object to std::cerr. /// Return the contents as a human-readable string.
/// If this object contains other objects, it will call itself recursively /// If this object contains other objects, it will call itself recursively
/// and print all nested content in a nice human-readable format. /// and print all nested content as well.
std::string AMF::Object::Print(std::string indent){ std::string AMF::Object::Print(std::string indent){
std::stringstream st; std::stringstream st;
st << indent; st << indent;
@ -368,9 +368,6 @@ AMF::Object AMF::parseOne(const unsigned char *& data, unsigned int &len, unsign
unsigned int tmpi = 0; unsigned int tmpi = 0;
unsigned char tmpdbl[8]; unsigned char tmpdbl[8];
double *d; // hack to work around strict aliasing double *d; // hack to work around strict aliasing
#if DEBUG >= 10
fprintf(stderr, "Note: AMF type %hhx found. %i bytes left\n", data[i], len-i);
#endif
switch (data[i]){ switch (data[i]){
case AMF::AMF0_NUMBER: case AMF::AMF0_NUMBER:
tmpdbl[7] = data[i + 1]; tmpdbl[7] = data[i + 1];
@ -496,9 +493,7 @@ AMF::Object AMF::parseOne(const unsigned char *& data, unsigned int &len, unsign
} }
break; break;
} }
#if DEBUG >= 2 DEBUG_MSG(DLVL_ERROR, "Error: Unimplemented AMF type %hhx - returning.", data[i]);
fprintf(stderr, "Error: Unimplemented AMF type %hhx - returning.\n", data[i]);
#endif
return AMF::Object("error", AMF::AMF0_DDV_CONTAINER); return AMF::Object("error", AMF::AMF0_DDV_CONTAINER);
} //parseOne } //parseOne
@ -668,99 +663,101 @@ AMF::Object3::Object3(std::string indice, AMF::obj3type setType){ //object type
intval = 0; intval = 0;
} }
/// Prints the contents of this object to std::cerr. /// Return the contents as a human-readable string.
/// If this object contains other objects, it will call itself recursively /// If this object contains other objects, it will call itself recursively
/// and print all nested content in a nice human-readable format. /// and print all nested content as well.
void AMF::Object3::Print(std::string indent){ std::string AMF::Object3::Print(std::string indent){
std::cerr << indent; std::stringstream st;
st << indent;
// print my type // print my type
switch (myType){ switch (myType){
case AMF::AMF3_UNDEFINED: case AMF::AMF3_UNDEFINED:
std::cerr << "Undefined"; st << "Undefined";
break; break;
case AMF::AMF3_NULL: case AMF::AMF3_NULL:
std::cerr << "Null"; st << "Null";
break; break;
case AMF::AMF3_FALSE: case AMF::AMF3_FALSE:
std::cerr << "False"; st << "False";
break; break;
case AMF::AMF3_TRUE: case AMF::AMF3_TRUE:
std::cerr << "True"; st << "True";
break; break;
case AMF::AMF3_INTEGER: case AMF::AMF3_INTEGER:
std::cerr << "Integer"; st << "Integer";
break; break;
case AMF::AMF3_DOUBLE: case AMF::AMF3_DOUBLE:
std::cerr << "Double"; st << "Double";
break; break;
case AMF::AMF3_STRING: case AMF::AMF3_STRING:
std::cerr << "String"; st << "String";
break; break;
case AMF::AMF3_XMLDOC: case AMF::AMF3_XMLDOC:
std::cerr << "XML Doc"; st << "XML Doc";
break; break;
case AMF::AMF3_DATE: case AMF::AMF3_DATE:
std::cerr << "Date"; st << "Date";
break; break;
case AMF::AMF3_ARRAY: case AMF::AMF3_ARRAY:
std::cerr << "Array"; st << "Array";
break; break;
case AMF::AMF3_OBJECT: case AMF::AMF3_OBJECT:
std::cerr << "Object"; st << "Object";
break; break;
case AMF::AMF3_XML: case AMF::AMF3_XML:
std::cerr << "XML"; st << "XML";
break; break;
case AMF::AMF3_BYTES: case AMF::AMF3_BYTES:
std::cerr << "ByteArray"; st << "ByteArray";
break; break;
case AMF::AMF3_DDV_CONTAINER: case AMF::AMF3_DDV_CONTAINER:
std::cerr << "DDVTech Container"; st << "DDVTech Container";
break; break;
} }
// print my string indice, if available // print my string indice, if available
std::cerr << " " << myIndice << " "; st << " " << myIndice << " ";
// print my numeric or string contents // print my numeric or string contents
switch (myType){ switch (myType){
case AMF::AMF3_INTEGER: case AMF::AMF3_INTEGER:
std::cerr << intval; st << intval;
break; break;
case AMF::AMF3_DOUBLE: case AMF::AMF3_DOUBLE:
std::cerr << dblval; st << dblval;
break; break;
case AMF::AMF3_STRING: case AMF::AMF3_STRING:
case AMF::AMF3_XMLDOC: case AMF::AMF3_XMLDOC:
case AMF::AMF3_XML: case AMF::AMF3_XML:
case AMF::AMF3_BYTES: case AMF::AMF3_BYTES:
if (intval > 0){ if (intval > 0){
std::cerr << "REF" << intval; st << "REF" << intval;
}else{ }else{
std::cerr << strval; st << strval;
} }
break; break;
case AMF::AMF3_DATE: case AMF::AMF3_DATE:
if (intval > 0){ if (intval > 0){
std::cerr << "REF" << intval; st << "REF" << intval;
}else{ }else{
std::cerr << dblval; st << dblval;
} }
break; break;
case AMF::AMF3_ARRAY: case AMF::AMF3_ARRAY:
case AMF::AMF3_OBJECT: case AMF::AMF3_OBJECT:
if (intval > 0){ if (intval > 0){
std::cerr << "REF" << intval; st << "REF" << intval;
} }
break; break;
default: default:
break; //we don't care about the rest, and don't want a compiler warning... break; //we don't care about the rest, and don't want a compiler warning...
} }
std::cerr << std::endl; st << std::endl;
// if I hold other objects, print those too, recursively. // if I hold other objects, print those too, recursively.
if (contents.size() > 0){ if (contents.size() > 0){
for (std::vector<AMF::Object3>::iterator it = contents.begin(); it != contents.end(); it++){ for (std::vector<AMF::Object3>::iterator it = contents.begin(); it != contents.end(); it++){
it->Print(indent + " "); st << it->Print(indent + " ");
} }
} }
return st.str();
} //print } //print
/// Packs the AMF object to a std::string for transfer over the network. /// Packs the AMF object to a std::string for transfer over the network.
@ -784,9 +781,6 @@ AMF::Object3 AMF::parseOne3(const unsigned char *& data, unsigned int &len, unsi
unsigned int arrsize = 0; unsigned int arrsize = 0;
unsigned char tmpdbl[8]; unsigned char tmpdbl[8];
double *d; // hack to work around strict aliasing double *d; // hack to work around strict aliasing
#if DEBUG >= 10
fprintf(stderr, "Note: AMF3 type %hhx found. %i bytes left\n", data[i], len-i);
#endif
switch (data[i]){ switch (data[i]){
case AMF::AMF3_UNDEFINED: case AMF::AMF3_UNDEFINED:
case AMF::AMF3_NULL: case AMF::AMF3_NULL:
@ -1121,9 +1115,7 @@ AMF::Object3 AMF::parseOne3(const unsigned char *& data, unsigned int &len, unsi
} }
break; break;
} }
#if DEBUG >= 2 DEBUG_MSG(DLVL_ERROR, "Error: Unimplemented AMF3 type %hhx - returning.", data[i]);
fprintf(stderr, "Error: Unimplemented AMF3 type %hhx - returning.\n", data[i]);
#endif
return AMF::Object3("error", AMF::AMF3_DDV_CONTAINER); return AMF::Object3("error", AMF::AMF3_DDV_CONTAINER);
} //parseOne } //parseOne

View file

@ -108,7 +108,7 @@ namespace AMF {
Object3(std::string indice, double val, obj3type setType = AMF3_DOUBLE); Object3(std::string indice, double val, obj3type setType = AMF3_DOUBLE);
Object3(std::string indice, std::string val, obj3type setType = AMF3_STRING); Object3(std::string indice, std::string val, obj3type setType = AMF3_STRING);
Object3(std::string indice, obj3type setType = AMF3_OBJECT); Object3(std::string indice, obj3type setType = AMF3_OBJECT);
void Print(std::string indent = ""); std::string Print(std::string indent = "");
std::string Pack(); std::string Pack();
protected: protected:
std::string myIndice; ///< Holds this objects indice, if any. std::string myIndice; ///< Holds this objects indice, if any.

View file

@ -1,7 +1,7 @@
#include"bitstream.h" #include "bitstream.h"
#include<stdlib.h> #include "defines.h"
#include<string.h> #include <stdlib.h>
#include<iostream> #include <string.h>
namespace Utils{ namespace Utils{
bitstream::bitstream(){ bitstream::bitstream(){
@ -31,7 +31,6 @@ namespace Utils{
memcpy(data+dataSize, input, bytes); memcpy(data+dataSize, input, bytes);
dataSize += bytes; dataSize += bytes;
} }
//std::cout << std::hex << std::string(data, dataSize) << std::dec << std::endl;
} }
void bitstream::append(std::string input){ void bitstream::append(std::string input){
@ -45,11 +44,11 @@ namespace Utils{
long long unsigned int bitstream::peek(size_t count){ long long unsigned int bitstream::peek(size_t count){
if (count > 64){ if (count > 64){
std::cerr << "Utils::bitstream: Warning; Can not read "<< count <<" bits into a long long unsigned int!" << std::endl; 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()){
std::cerr << "Utils::bitstream: not enough bits left in stream. Left: " << size() << " requested: " << count << std::endl; DEBUG_MSG(DLVL_ERROR, "Not enough bits left in stream. Left: %d requested: %d", (int)size(), (int)count);
return 0; return 0;
} }
long long unsigned int retval = 0; long long unsigned int retval = 0;

View file

@ -2,6 +2,9 @@
/// Contains generic functions for managing configuration. /// Contains generic functions for managing configuration.
#include "config.h" #include "config.h"
#include "defines.h"
#include "timing.h"
#include "tinythread.h"
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
@ -22,7 +25,6 @@
#include <pwd.h> #include <pwd.h>
#include <getopt.h> #include <getopt.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <fstream> #include <fstream>
#include <dirent.h> //for getMyExec #include <dirent.h> //for getMyExec
@ -295,6 +297,46 @@ bool Util::Config::getBool(std::string optname){
return getOption(optname).asBool(); return getOption(optname).asBool();
} }
struct callbackData{
Socket::Connection * sock;
void (*cb)(Socket::Connection &);
};
static void callThreadCallback(void * cDataArg){
DEBUG_MSG(DLVL_INSANE, "Thread for %p started", cDataArg);
callbackData * cData = (callbackData*)cDataArg;
cData->cb(*(cData->sock));
cData->sock->close();
delete cData->sock;
delete cData;
DEBUG_MSG(DLVL_INSANE, "Thread for %p ended", cDataArg);
}
int Util::Config::serveThreadedSocket(void (*callback)(Socket::Connection &)){
Socket::Server server_socket = Socket::Server(getInteger("listen_port"), getString("listen_interface"), false);
if (!server_socket.connected()){return 1;}
DEBUG_MSG(DLVL_DEVEL, "Activating threaded server: %s", getString("cmd").c_str());
activate();
while (is_active && server_socket.connected()){
Socket::Connection S = server_socket.accept();
if (S.connected()){ //check if the new connection is valid
callbackData * cData = new callbackData;
cData->sock = new Socket::Connection(S);
cData->cb = callback;
//spawn a new thread for this connection
tthread::thread T(callThreadCallback, (void*)cData);
//detach it, no need to keep track of it anymore
T.detach();
}else{
Util::sleep(10); //sleep 10ms
}
}//main loop
server_socket.close();
DEBUG_MSG(DLVL_DEVEL, "Threaded server exiting: %s", getString("cmd").c_str());
return 0;
}
/// Activated the stored config. This will: /// Activated the stored config. This will:
/// - Drop permissions to the stored "username", if any. /// - Drop permissions to the stored "username", if any.
/// - Daemonize the process if "daemonize" exists and is true. /// - Daemonize the process if "daemonize" exists and is true.
@ -450,19 +492,13 @@ 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){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Error: could not setuid %s: could not get PID", username.c_str());
fprintf(stderr, "Error: could not setuid %s: could not get PID\n", username.c_str());
#endif
return; return;
}else{ }else{
if (setuid(user_info->pw_uid) != 0){ if (setuid(user_info->pw_uid) != 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Error: could not setuid %s: not allowed", username.c_str());
fprintf(stderr, "Error: could not setuid %s: not allowed\n", username.c_str());
#endif
}else{ }else{
#if DEBUG >= 3 DEBUG_MSG(DLVL_DEVEL, "Change user to %s", username.c_str());
fprintf(stderr, "Changed user to %s\n", username.c_str());
#endif
} }
} }
} }
@ -473,12 +509,8 @@ void Util::setUser(std::string username){
/// 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(){ void Util::Daemonize(){
#if DEBUG >= 3 DEBUG_MSG(DLVL_DEVEL, "Going into background mode...");
fprintf(stderr, "Going into background mode...\n");
#endif
if (daemon(1, 0) < 0){ if (daemon(1, 0) < 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Failed to daemonize: %s", strerror(errno));
fprintf(stderr, "Failed to daemonize: %s\n", strerror(errno));
#endif
} }
} }

View file

@ -33,6 +33,9 @@ namespace Util {
long long int getInteger(std::string optname); long long int getInteger(std::string optname);
bool getBool(std::string optname); bool getBool(std::string optname);
void activate(); void activate();
int serveThreadedSocket(void (*callback)(Socket::Connection & S));
int serveForkedSocket(void (*callback)(Socket::Connection & S));
int servePlainSocket(void (*callback)(Socket::Connection & S));
void addBasicConnectorOptions(JSON::Value & capabilities); void addBasicConnectorOptions(JSON::Value & capabilities);
void addConnectorOptions(int port, JSON::Value & capabilities); void addConnectorOptions(int port, JSON::Value & capabilities);
}; };

View file

@ -1,4 +1,3 @@
#include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <sys/types.h> #include <sys/types.h>
@ -69,7 +68,6 @@ namespace Converter {
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();
fprintf( stderr, "Querying %s\n", myPath.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;

18
lib/defines.h Normal file
View file

@ -0,0 +1,18 @@
// Defines to print debug messages.
#define DLVL_NONE 0 // All debugging disabled.
#define DLVL_FAIL 1 // Only messages about failed operations.
#define DLVL_ERROR 2 // Only messages about errors and failed operations.
#define DLVL_WARN 3 // Warnings, errors, and fail messages.
#define DLVL_DEVEL 4 // All of the above, plus status messages handy during development.
#define DLVL_MEDIUM 5 // Slightly more than just development-level messages.
#define DLVL_HIGH 6 // Verbose debugging messages.
#define DLVL_VERYHIGH 7 // Very verbose debugging messages.
#define DLVL_EXTREME 8 // Everything is reported in extreme detail.
#define DLVL_INSANE 9 // Everything is reported in insane detail.
#define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones.
#if DEBUG > 0
#include <stdio.h>
#define DEBUG_MSG(lvl, msg, ...) if (DEBUG >= lvl){fprintf(stderr, "[%s:%d] " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__);}
#else
#define DEBUG_MSG(lvl, msg, ...) // Debugging disabled.
#endif

View file

@ -2,6 +2,7 @@
/// Holds all code for DDVTECH Stream Container parsing/generation. /// Holds all code for DDVTECH Stream Container parsing/generation.
#include "dtsc.h" #include "dtsc.h"
#include "defines.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> //for memcmp #include <string.h> //for memcmp
#include <arpa/inet.h> //for htonl/ntohl #include <arpa/inet.h> //for htonl/ntohl
@ -87,9 +88,9 @@ bool DTSC::Stream::parsePacket(std::string & buffer){
syncing = false; syncing = false;
return true; return true;
} }
#if DEBUG >= 2 #if DEBUG >= DLVL_WARN
if (!syncing){ if (!syncing){
std::cerr << "Error: Invalid DTMI data detected - re-syncing" << std::endl; DEBUG_MSG(DLVL_WARN, "Invalid DTMI data detected - re-syncing");
syncing = true; syncing = true;
} }
#endif #endif
@ -155,9 +156,9 @@ bool DTSC::Stream::parsePacket(Socket::Buffer & buffer){
syncing = false; syncing = false;
return true; return true;
} }
#if DEBUG >= 2 #if DEBUG >= DLVL_WARN
if (!syncing){ if (!syncing){
std::cerr << "Error: Invalid DTMI data detected - syncing" << std::endl; DEBUG_MSG(DLVL_WARN, "Invalid DTMI data detected - syncing");
syncing = true; syncing = true;
} }
#endif #endif
@ -206,9 +207,7 @@ void DTSC::Stream::waitForMeta(Socket::Connection & sourceSocket){
if (Util::getMS() - start >= 5000){ if (Util::getMS() - start >= 5000){
sourceSocket.close(); sourceSocket.close();
//and optionally print a debug message that this happened //and optionally print a debug message that this happened
#if DEBUG >= 4 DEBUG_MSG(DLVL_DEVEL, "Timing out while waiting for metadata");
fprintf(stderr, "Timed out while waiting for metadata\n");
#endif
} }
} }
@ -283,7 +282,7 @@ void DTSC::Stream::addPacket(JSON::Value & newPack){
} }
/// Deletes a the first part of the buffer, updating the keyframes list and metadata as required. /// Deletes a the first part of the buffer, updating the keyframes list and metadata as required.
/// Will print a warning to std::cerr if a track has less than 2 keyframes left because of this. /// Will print a warning if a track has less than 2 keyframes left because of this.
void DTSC::Stream::cutOneBuffer(){ void DTSC::Stream::cutOneBuffer(){
int trid = buffers.begin()->first.trackID; int trid = buffers.begin()->first.trackID;
long long unsigned int delTime = buffers.begin()->first.seekTime; long long unsigned int delTime = buffers.begin()->first.seekTime;
@ -517,7 +516,7 @@ DTSC::File::File(std::string filename, bool create){
if (create){ if (create){
F = fopen(filename.c_str(), "w+b"); F = fopen(filename.c_str(), "w+b");
if(!F){ if(!F){
std::cerr << "Could not create file" << filename << ": " << strerror(errno) << std::endl; DEBUG_MSG(DLVL_ERROR, "Could not create file %s: %s", filename.c_str(), strerror(errno));
return; return;
} }
//write an empty header //write an empty header
@ -531,7 +530,7 @@ DTSC::File::File(std::string filename, bool create){
} }
created = create; created = create;
if ( !F){ if ( !F){
fprintf(stderr, "Could not open file %s\n", filename.c_str()); DEBUG_MSG(DLVL_ERROR, "Could not open file %s\n", filename.c_str());
return; return;
} }
fseek(F, 0, SEEK_END); fseek(F, 0, SEEK_END);
@ -561,7 +560,7 @@ DTSC::readOnlyMeta & DTSC::File::getMeta(){
/// Forces a write if force is set to true. /// Forces a write if force is set to true.
bool DTSC::File::writeHeader(std::string & header, bool force){ bool DTSC::File::writeHeader(std::string & header, bool force){
if (headerSize != header.size() && !force){ if (headerSize != header.size() && !force){
fprintf(stderr, "Could not overwrite header - not equal size\n"); DEBUG_MSG(DLVL_ERROR, "Could not overwrite header - not equal size");
return false; return false;
} }
headerSize = header.size(); headerSize = header.size();
@ -601,30 +600,28 @@ long long int DTSC::File::addHeader(std::string & header){
} }
/// Reads the header at the given file position. /// Reads the header at the given file position.
/// If the packet could not be read for any reason, the reason is printed to stderr. /// If the packet could not be read for any reason, the reason is printed.
/// Reading the header means the file position is moved to after the header. /// Reading the header means the file position is moved to after the header.
void DTSC::File::readHeader(int pos){ void DTSC::File::readHeader(int pos){
fseek(F, pos, SEEK_SET); fseek(F, pos, SEEK_SET);
if (fread(buffer, 4, 1, F) != 1){ if (fread(buffer, 4, 1, F) != 1){
if (feof(F)){ if (feof(F)){
#if DEBUG >= 4 DEBUG_MSG(DLVL_DEVEL, "End of file reached while reading header @ %d", pos);
fprintf(stderr, "End of file reached (H%i)\n", pos);
#endif
}else{ }else{
fprintf(stderr, "Could not read header (H%i)\n", pos); DEBUG_MSG(DLVL_ERROR, "Could not read header @ %d", pos);
} }
strbuffer = ""; strbuffer = "";
metadata = readOnlyMeta(); metadata = readOnlyMeta();
return; return;
} }
if (memcmp(buffer, DTSC::Magic_Header, 4) != 0){ if (memcmp(buffer, DTSC::Magic_Header, 4) != 0){
fprintf(stderr, "Invalid header - %.4s != %.4s (H%i)\n", buffer, DTSC::Magic_Header, pos); DEBUG_MSG(DLVL_ERROR, "Invalid header - %.4s != %.4s @ %i", buffer, DTSC::Magic_Header, pos);
strbuffer = ""; strbuffer = "";
metadata = readOnlyMeta(); metadata = readOnlyMeta();
return; return;
} }
if (fread(buffer, 4, 1, F) != 1){ if (fread(buffer, 4, 1, F) != 1){
fprintf(stderr, "Could not read size (H%i)\n", pos); DEBUG_MSG(DLVL_ERROR, "Could not read header size @ %i", pos);
strbuffer = ""; strbuffer = "";
metadata = readOnlyMeta(); metadata = readOnlyMeta();
return; return;
@ -634,7 +631,7 @@ void DTSC::File::readHeader(int pos){
strbuffer.resize(packSize); strbuffer.resize(packSize);
if (packSize){ if (packSize){
if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){ if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){
fprintf(stderr, "Could not read packet (H%i)\n", pos); DEBUG_MSG(DLVL_ERROR, "Could not read header packet @ %i", pos);
strbuffer = ""; strbuffer = "";
metadata = readOnlyMeta(); metadata = readOnlyMeta();
return; return;
@ -666,7 +663,7 @@ bool DTSC::File::reachedEOF(){
} }
/// Reads the packet available at the current file position. /// Reads the packet available at the current file position.
/// If the packet could not be read for any reason, the reason is printed to stderr. /// If the packet could not be read for any reason, the reason is printed.
/// Reading the packet means the file position is increased to the next packet. /// Reading the packet means the file position is increased to the next packet.
void DTSC::File::seekNext(){ void DTSC::File::seekNext(){
if ( !currentPositions.size()){ if ( !currentPositions.size()){
@ -689,11 +686,9 @@ void DTSC::File::seekNext(){
lastreadpos = ftell(F); lastreadpos = ftell(F);
if (fread(buffer, 4, 1, F) != 1){ if (fread(buffer, 4, 1, F) != 1){
if (feof(F)){ if (feof(F)){
#if DEBUG >= 4 DEBUG_MSG(DLVL_DEVEL, "End of file reached while seeking @ %i", (int)lastreadpos);
fprintf(stderr, "End of file reached.\n");
#endif
}else{ }else{
fprintf(stderr, "Could not read header\n"); DEBUG_MSG(DLVL_ERROR, "Could not seek to next @ %i", (int)lastreadpos);
} }
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
@ -712,13 +707,13 @@ void DTSC::File::seekNext(){
version = 2; version = 2;
} }
if (version == 0){ if (version == 0){
fprintf(stderr, "Invalid packet header @ %#x - %.4s != %.4s\n", (unsigned int)lastreadpos, buffer, DTSC::Magic_Packet2); DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x - %.4s != %.4s @ %d", (unsigned int)lastreadpos, buffer, DTSC::Magic_Packet2, (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;
} }
if (fread(buffer, 4, 1, F) != 1){ if (fread(buffer, 4, 1, F) != 1){
fprintf(stderr, "Could not read size\n"); DEBUG_MSG(DLVL_ERROR, "Could not read packet size @ %d", (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;
@ -727,7 +722,7 @@ void DTSC::File::seekNext(){
long packSize = ntohl(ubuffer[0]); long packSize = ntohl(ubuffer[0]);
strbuffer.resize(packSize); strbuffer.resize(packSize);
if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){ if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){
fprintf(stderr, "Could not read packet\n"); DEBUG_MSG(DLVL_ERROR, "Could not read packet @ %d", (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;
@ -782,11 +777,9 @@ void DTSC::File::parseNext(){
lastreadpos = ftell(F); lastreadpos = ftell(F);
if (fread(buffer, 4, 1, F) != 1){ if (fread(buffer, 4, 1, F) != 1){
if (feof(F)){ if (feof(F)){
#if DEBUG >= 4 DEBUG_MSG(DLVL_DEVEL, "End of file reached @ %d", (int)lastreadpos);
fprintf(stderr, "End of file reached.\n");
#endif
}else{ }else{
fprintf(stderr, "Could not read header\n"); DEBUG_MSG(DLVL_ERROR, "Could not read header @ %d", (int)lastreadpos);
} }
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
@ -798,7 +791,7 @@ void DTSC::File::parseNext(){
jsonbuffer = metadata.toJSON(); jsonbuffer = metadata.toJSON();
}else{ }else{
if (fread(buffer, 4, 1, F) != 1){ if (fread(buffer, 4, 1, F) != 1){
fprintf(stderr, "Could not read size\n"); DEBUG_MSG(DLVL_ERROR, "Could not read header size @ %d", (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;
@ -807,7 +800,7 @@ void DTSC::File::parseNext(){
long packSize = ntohl(ubuffer[0]); long packSize = ntohl(ubuffer[0]);
strbuffer.resize(packSize); strbuffer.resize(packSize);
if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){ if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){
fprintf(stderr, "Could not read packet\n"); DEBUG_MSG(DLVL_ERROR, "Could not read header @ %d", (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;
@ -824,13 +817,13 @@ void DTSC::File::parseNext(){
version = 2; version = 2;
} }
if (version == 0){ if (version == 0){
fprintf(stderr, "Invalid packet header @ %#x - %.4s != %.4s\n", (unsigned int)lastreadpos, buffer, DTSC::Magic_Packet2); DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x - %.4s != %.4s @ %d", (unsigned int)lastreadpos, buffer, DTSC::Magic_Packet2, (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;
} }
if (fread(buffer, 4, 1, F) != 1){ if (fread(buffer, 4, 1, F) != 1){
fprintf(stderr, "Could not read size\n"); DEBUG_MSG(DLVL_ERROR, "Could not read packet size @ %d", (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;
@ -839,7 +832,7 @@ void DTSC::File::parseNext(){
long packSize = ntohl(ubuffer[0]); long packSize = ntohl(ubuffer[0]);
strbuffer.resize(packSize); strbuffer.resize(packSize);
if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){ if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){
fprintf(stderr, "Could not read packet\n"); DEBUG_MSG(DLVL_ERROR, "Could not read packet @ %d", (int)lastreadpos);
strbuffer = ""; strbuffer = "";
jsonbuffer.null(); jsonbuffer.null();
return; return;

View file

@ -1,4 +1,5 @@
#include "dtsc.h" #include "dtsc.h"
#include "defines.h"
/// Retrieves a short in network order from the pointer p. /// Retrieves a short in network order from the pointer p.
static short btohs(char * p){ static short btohs(char * p){
@ -269,7 +270,7 @@ namespace DTSC {
void Track::update(JSON::Value & pack){ void Track::update(JSON::Value & pack){
if (pack["time"].asInt() < lastms){ if (pack["time"].asInt() < lastms){
std::cerr << "Received packets for track " << trackID << " in wrong order (" << pack["time"].asInt() << " < " << lastms << ") - ignoring!" << std::endl; DEBUG_MSG(DLVL_WARN, "Received packets for track %d in wrong order (%d < %d) - ignoring!", (int)trackID, (int)pack["time"].asInt(), (int)lastms);
return; return;
} }
Part newPart; Part newPart;

View file

@ -1,4 +1,5 @@
#include "filesystem.h" #include "filesystem.h"
#include "defines.h"
Filesystem::Directory::Directory(std::string PathName, std::string BasePath){ Filesystem::Directory::Directory(std::string PathName, std::string BasePath){
MyBase = BasePath; MyBase = BasePath;
@ -26,9 +27,7 @@ void Filesystem::Directory::FillEntries(){
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){
#if DEBUG >= 4 DEBUG_MSG(DLVL_DEVEL, "Skipping %s, reason %s", entry->d_name, strerror(errno));
fprintf(stderr, "\tSkipping %s\n\t\tReason: %s\n", entry->d_name, strerror(errno));
#endif
continue; continue;
} }
///Convert stat to string ///Convert stat to string
@ -38,8 +37,9 @@ void Filesystem::Directory::FillEntries(){
} }
void Filesystem::Directory::Print(){ void Filesystem::Directory::Print(){
/// \todo Remove? Libraries shouldn't print stuff.
if ( !ValidDir){ if ( !ValidDir){
printf("%s is not a valid directory\n", (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());
@ -74,9 +74,6 @@ std::string Filesystem::Directory::LIST(std::vector<std::string> ActiveStreams){
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());
fprintf(stderr, "%s active?: %d\n", ( *it).first.c_str(), Active);
fprintf(stderr, "\tMyPath: %s\n\tVisible: %d\n", MyPath.c_str(), MyVisible[MyPath]);
fprintf(stderr, "\t\tBitmask S_ACTIVE: %d\n\t\tBitmask S_INACTIVE: %d\n", MyVisible[MyPath] & S_ACTIVE, MyVisible[MyPath] & S_INACTIVE);
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';
@ -217,7 +214,6 @@ void Filesystem::Directory::STOR(std::string Path, std::string Data){
bool Filesystem::Directory::SimplifyPath(){ bool Filesystem::Directory::SimplifyPath(){
MyPath += "/"; MyPath += "/";
fprintf(stderr, "MyPath: %s\n", MyPath.c_str());
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++){
@ -258,7 +254,7 @@ bool Filesystem::Directory::DELE(std::string Path){
FileName = MyBase + MyPath + "/" + Path; FileName = MyBase + MyPath + "/" + Path;
} }
if (std::remove(FileName.c_str())){ if (std::remove(FileName.c_str())){
fprintf(stderr, "Removing file %s unsuccesfull\n", FileName.c_str()); DEBUG_MSG(DLVL_ERROR, "Removing file %s failed", FileName.c_str());
return false; return false;
} }
return true; return true;
@ -275,7 +271,7 @@ bool Filesystem::Directory::MKD(std::string Path){
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)){
fprintf(stderr, "Creating directory %s unsuccesfull\n", FileName.c_str()); DEBUG_MSG(DLVL_ERROR, "Creating directory %s failed", FileName.c_str());
return false; return false;
} }
MyVisible[FileName] = S_ALL; MyVisible[FileName] = S_ALL;
@ -298,7 +294,7 @@ bool Filesystem::Directory::Rename(std::string From, std::string To){
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())){
fprintf(stderr, "Renaming file %s to %s unsuccesfull\n", 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;
} }
return true; return true;

View file

@ -23,7 +23,6 @@ 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");
fprintf(stderr, "Streamamount: %d\n", MyConfig["streams"].size());
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());
@ -32,7 +31,6 @@ FTP::User::User(Socket::Connection NewConnection, std::map<std::string, std::str
ThisStream.erase(0, ThisStream.find('/') + 1); ThisStream.erase(0, ThisStream.find('/') + 1);
} }
ActiveStreams.push_back(ThisStream); ActiveStreams.push_back(ThisStream);
fprintf(stderr, "\t%s\n", ThisStream.c_str());
} }
} }
@ -160,7 +158,6 @@ int FTP::User::ParseCommand(std::string Command){
break; break;
} }
case CMD_LIST: { case CMD_LIST: {
std::cout << "Listening on :" << MyPassivePort << "\n";
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");
@ -170,7 +167,6 @@ int FTP::User::ParseCommand(std::string Command){
while ( !Connected.connected()){ while ( !Connected.connected()){
Connected = Passive.accept(); Connected = Passive.accept();
} }
fprintf(stderr, "Sending LIST information\n");
std::string tmpstr = MyDir.LIST(ActiveStreams); std::string tmpstr = MyDir.LIST(ActiveStreams);
Connected.Send(tmpstr); Connected.Send(tmpstr);
Connected.close(); Connected.close();
@ -197,7 +193,6 @@ int FTP::User::ParseCommand(std::string Command){
return 530; return 530;
} //Not logged in. } //Not logged in.
MyPassivePort = (rand() % 9999); MyPassivePort = (rand() % 9999);
std::cout << ":" << MyPassivePort << "\n";
Passive = Socket::Server(MyPassivePort, "0.0.0.0", true); Passive = Socket::Server(MyPassivePort, "0.0.0.0", true);
return 229; return 229;
break; break;
@ -207,7 +202,6 @@ int FTP::User::ParseCommand(std::string Command){
return 530; return 530;
} //Not logged in. } //Not logged in.
MyPassivePort = (rand() % 9999) + 49152; MyPassivePort = (rand() % 9999) + 49152;
std::cout << ":" << MyPassivePort << "\n";
Passive = Socket::Server(MyPassivePort, "0.0.0.0", true); Passive = Socket::Server(MyPassivePort, "0.0.0.0", true);
return 227; return 227;
break; break;
@ -222,7 +216,6 @@ int FTP::User::ParseCommand(std::string Command){
if ( !MyDir.HasPermission(Filesystem::P_RETR)){ if ( !MyDir.HasPermission(Filesystem::P_RETR)){
return 550; return 550;
} //Access denied. } //Access denied.
std::cout << "Listening on :" << MyPassivePort << "\n";
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");
@ -232,7 +225,6 @@ int FTP::User::ParseCommand(std::string Command){
while ( !Connected.connected()){ while ( !Connected.connected()){
Connected = Passive.accept(); Connected = Passive.accept();
} }
fprintf(stderr, "Sending RETR information\n");
std::string tmpstr = MyDir.RETR(Command); std::string tmpstr = MyDir.RETR(Command);
Connected.Send(tmpstr); Connected.Send(tmpstr);
Connected.close(); Connected.close();
@ -249,7 +241,6 @@ int FTP::User::ParseCommand(std::string Command){
if ( !MyDir.HasPermission(Filesystem::P_STOR)){ if ( !MyDir.HasPermission(Filesystem::P_STOR)){
return 550; return 550;
} //Access denied. } //Access denied.
std::cout << "Listening on :" << MyPassivePort << "\n";
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");
@ -259,7 +250,6 @@ int FTP::User::ParseCommand(std::string Command){
while ( !Connected.connected()){ while ( !Connected.connected()){
Connected = Passive.accept(); Connected = Passive.accept();
} }
fprintf(stderr, "Reading STOR information\n");
std::string Buffer; std::string Buffer;
while (Connected.spool()){ while (Connected.spool()){
} }

View file

@ -1,6 +1,7 @@
/// \file json.cpp Holds all JSON-related code. /// \file json.cpp Holds all JSON-related code.
#include "json.h" #include "json.h"
#include "defines.h"
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <stdlib.h> #include <stdlib.h>
@ -642,11 +643,11 @@ unsigned int JSON::Value::packedSize() const{
}//packedSize }//packedSize
/// Pre-packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header. /// Pre-packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header.
/// Non-object-types will print an error to stderr. /// Non-object-types will print an error.
/// The internal buffer is guaranteed to be up-to-date after this function is called. /// The internal buffer is guaranteed to be up-to-date after this function is called.
void JSON::Value::netPrepare(){ void JSON::Value::netPrepare(){
if (myType != OBJECT){ if (myType != OBJECT){
fprintf(stderr, "Error: Only objects may be NetPacked!\n"); DEBUG_MSG(DLVL_ERROR, "Only objects may be netpacked!");
return; return;
} }
std::string packed = toPacked(); std::string packed = toPacked();
@ -711,7 +712,7 @@ void JSON::Value::netPrepare(){
} }
/// Packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header. /// Packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header.
/// Non-object-types will print an error to stderr and return an empty string. /// Non-object-types will print an error and return an empty string.
/// This function returns a reference to an internal buffer where the prepared data is kept. /// This function returns a reference to an internal buffer where the prepared data is kept.
/// The internal buffer is *not* made stale if any changes occur inside the object - subsequent calls to toPacked() will clear the buffer, /// The internal buffer is *not* made stale if any changes occur inside the object - subsequent calls to toPacked() will clear the buffer,
/// calls to netPrepare will guarantee it is up-to-date. /// calls to netPrepare will guarantee it is up-to-date.
@ -719,7 +720,7 @@ std::string & JSON::Value::toNetPacked(){
static std::string emptystring; static std::string emptystring;
//check if this is legal //check if this is legal
if (myType != OBJECT){ if (myType != OBJECT){
fprintf(stderr, "Error: Only objects may be NetPacked!\n"); DEBUG_MSG(DLVL_ERROR, "Only objects may be netpacked!");
return emptystring; return emptystring;
} }
//if sneaky storage doesn't contain correct data, re-calculate it //if sneaky storage doesn't contain correct data, re-calculate it
@ -1018,9 +1019,6 @@ JSON::Value JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigne
/// \param i Current parsing position in the raw data (defaults to 0). /// \param i Current parsing position in the raw data (defaults to 0).
/// \param ret Will be set to JSON::Value, parsed from the raw data. /// \param ret Will be set to JSON::Value, parsed from the raw data.
void JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigned int &i, JSON::Value & ret){ void JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigned int &i, JSON::Value & ret){
#if DEBUG >= 10
fprintf(stderr, "Note: AMF type %hhx found. %i bytes left\n", data[i], len-i);
#endif
ret.null(); ret.null();
if (i >= len){ if (i >= len){
return; return;
@ -1087,9 +1085,7 @@ void JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigned int &
break; break;
} }
} }
#if DEBUG >= 2 DEBUG_MSG(DLVL_FAIL, "Unimplemented DTMI type %hhx, @ %i / %i - returning.\n", data[i], i, len);
fprintf(stderr, "Error: Unimplemented DTMI type %hhx, @ %i / %i - returning.\n", data[i], i, len);
#endif
i += 1; i += 1;
return; return;
} //fromOneDTMI } //fromOneDTMI

View file

@ -3,6 +3,7 @@
#include <arpa/inet.h> //for htonl and friends #include <arpa/inet.h> //for htonl and friends
#include "mp4.h" #include "mp4.h"
#include "json.h" #include "json.h"
#include "defines.h"
#define Int64 uint64_t #define Int64 uint64_t
@ -2286,7 +2287,7 @@ namespace MP4 {
void AVCC::setPayload(std::string newPayload){ void AVCC::setPayload(std::string newPayload){
if ( !reserve(0, payloadSize(), newPayload.size())){ if ( !reserve(0, payloadSize(), newPayload.size())){
std::cerr << "Cannot allocate enough memory for payload" << std::endl; DEBUG_MSG(DLVL_ERROR, "Cannot allocate enough memory for payload");
return; return;
} }
memcpy((char*)payload(), (char*)newPayload.c_str(), newPayload.size()); memcpy((char*)payload(), (char*)newPayload.c_str(), newPayload.size());

View file

@ -18,7 +18,6 @@ bool NAL_Unit::ReadData(std::string & InputData){
ShortAnnexB += (char)0x00; ShortAnnexB += (char)0x00;
ShortAnnexB += (char)0x00; ShortAnnexB += (char)0x00;
ShortAnnexB += (char)0x01; ShortAnnexB += (char)0x01;
// fprintf( stderr, "NAL_Unit::ReadData --- DataSize: %d\n", InputData.size() );
if (InputData.size() < 3){ if (InputData.size() < 3){
return false; return false;
} }

View file

@ -1,4 +1,5 @@
#include "ogg.h" #include "ogg.h"
#include "defines.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <sstream> #include <sstream>
@ -204,7 +205,7 @@ namespace OGG{
} }
static void STerrMSG(){ static void STerrMSG(){
std::cerr << "Segments too big, create a continue page" << std::endl; DEBUG_MSG(DLVL_ERROR, "Segment too big, create a continue page");
} }
/// \todo MAKE FIX HERE /// \todo MAKE FIX HERE
@ -486,10 +487,10 @@ namespace OGG{
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()){
std::cerr << "Granule inconcistency!! " << DTSCVec[0]["granule"].asInt() << " != " << DTSCVec[i]["granule"].asInt() << std::endl; 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()){
std::cerr << "Track ID inconcistency!! " << DTSCVec[0]["trackid"].asInt() << " != " <<DTSCVec[i]["trackid"].asInt() << std::endl; 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);

View file

@ -2,6 +2,7 @@
/// Contains generic functions for managing processes. /// Contains generic functions for managing processes.
#include "procs.h" #include "procs.h"
#include "defines.h"
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
@ -127,22 +128,19 @@ void Util::Procs::childsig_handler(int signum){
return; return;
} }
#if DEBUG >= 5 #if DEBUG >= DLVL_DEVEL
std::string pname = plist[ret]; std::string pname = plist[ret];
#endif #endif
plist.erase(ret); plist.erase(ret);
#if DEBUG >= 5 #if DEBUG >= DLVL_DEVEL
if (!isActive(pname)){ if (!isActive(pname)){
std::cerr << "Process " << pname << " fully terminated." << std::endl; DEBUG_MSG(DLVL_DEVEL, "Process %s fully terminated", pname.c_str());
} }
#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);
#if DEBUG >= 5
std::cerr << "Calling termination handler for " << pname << std::endl;
#endif
tn(ret, exitcode); tn(ret, exitcode);
} }
} }
@ -205,9 +203,7 @@ void Util::Procs::runCmd(std::string & cmd){
} }
//execute the command //execute the command
execvp(args[0], args); execvp(args[0], args);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Error running %s: %s", cmd.c_str(), strerror(errno));
std::cerr << "Error running \"" << cmd << "\": " << strerror(errno) << std::endl;
#endif
_exit(42); _exit(42);
} }
@ -225,14 +221,10 @@ pid_t Util::Procs::Start(std::string name, std::string cmd){
runCmd(cmd); runCmd(cmd);
}else{ }else{
if (ret > 0){ if (ret > 0){
#if DEBUG >= 5 DEBUG_MSG(DLVL_DEVEL, "Process %s started, PID %d: %s", name.c_str(), ret, cmd.c_str());
std::cerr << "Process " << name << " started, PID " << ret << ": " << cmd << std::endl;
#endif
plist.insert(std::pair<pid_t, std::string>(ret, name)); plist.insert(std::pair<pid_t, std::string>(ret, name));
}else{ }else{
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started: fork() failed", name.c_str());
std::cerr << "Process " << name << " could not be started. fork() failed." << std::endl;
#endif
return 0; return 0;
} }
} }
@ -251,9 +243,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
setHandler(); setHandler();
int pfildes[2]; int pfildes[2];
if (pipe(pfildes) == -1){ if (pipe(pfildes) == -1){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. Pipe creation failed." << std::endl;
#endif
return 0; return 0;
} }
@ -270,9 +260,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
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{
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. fork() failed." << std::endl;
#endif
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); close(pfildes[0]);
return 0; return 0;
@ -289,14 +277,10 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
runCmd(cmd2); runCmd(cmd2);
}else{ }else{
if (ret2 > 0){ if (ret2 > 0){
#if DEBUG >= 5 DEBUG_MSG(DLVL_DEVEL, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
std::cerr << "Process " << name << " started, PIDs (" << ret << ", " << ret2 << "): " << cmd << " | " << cmd2 << std::endl;
#endif
plist.insert(std::pair<pid_t, std::string>(ret2, name)); plist.insert(std::pair<pid_t, std::string>(ret2, name));
}else{ }else{
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. fork() failed." << std::endl;
#endif
Stop(name); Stop(name);
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); close(pfildes[0]);
@ -322,15 +306,11 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
int pfildes[2]; int pfildes[2];
int pfildes2[2]; int pfildes2[2];
if (pipe(pfildes) == -1){ if (pipe(pfildes) == -1){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. Pipe creation failed." << std::endl;
#endif
return 0; return 0;
} }
if (pipe(pfildes2) == -1){ if (pipe(pfildes2) == -1){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. Pipe creation failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. Pipe creation failed." << std::endl;
#endif
return 0; return 0;
} }
@ -349,9 +329,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
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{
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. fork() failed." << std::endl;
#endif
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); close(pfildes[0]);
close(pfildes2[1]); close(pfildes2[1]);
@ -372,14 +350,10 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
runCmd(cmd2); runCmd(cmd2);
}else{ }else{
if (ret2 > 0){ if (ret2 > 0){
#if DEBUG >= 5 DEBUG_MSG(DLVL_DEVEL, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
std::cerr << "Process " << name << " started, PIDs (" << ret << ", " << ret2 << "): " << cmd << " | " << cmd2 << std::endl;
#endif
plist.insert(std::pair<pid_t, std::string>(ret2, name)); plist.insert(std::pair<pid_t, std::string>(ret2, name));
}else{ }else{
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. fork() failed." << std::endl;
#endif
Stop(name); Stop(name);
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); close(pfildes[0]);
@ -403,14 +377,10 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
runCmd(cmd3); runCmd(cmd3);
}else{ }else{
if (ret3 > 0){ if (ret3 > 0){
#if DEBUG >= 5 DEBUG_MSG(DLVL_DEVEL, "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());
std::cerr << "Process " << name << " started, PIDs (" << ret << ", " << ret2 << ", " << ret3 << "): " << cmd << " | " << cmd2 << " | " << cmd3 << std::endl;
#endif
plist.insert(std::pair<pid_t, std::string>(ret3, name)); plist.insert(std::pair<pid_t, std::string>(ret3, name));
}else{ }else{
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
std::cerr << "Process " << name << " could not be started. fork() failed." << std::endl;
#endif
Stop(name); Stop(name);
close(pfildes[1]); close(pfildes[1]);
close(pfildes[0]); close(pfildes[0]);
@ -432,24 +402,18 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
/// \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)){
#if DEBUG >= 1 DEBUG_MSG(DLVL_WARN, "Process %s already active - skipping start", name.c_str());
std::cerr << name << " already active - skipping start" << std::endl;
#endif
return getPid(name); return getPid(name);
} }
pid_t pid; pid_t pid;
int pipein[2], pipeout[2], pipeerr[2]; int pipein[2], pipeout[2], pipeerr[2];
setHandler(); setHandler();
if (fdin && *fdin == -1 && pipe(pipein) < 0){ if (fdin && *fdin == -1 && pipe(pipein) < 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Pipe in creation failed for process %s", name.c_str());
std::cerr << "Pipe (in) creation failed for " << name << std::endl;
#endif
return 0; return 0;
} }
if (fdout && *fdout == -1 && pipe(pipeout) < 0){ if (fdout && *fdout == -1 && pipe(pipeout) < 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Pipe out creation failed for process %s", name.c_str());
std::cerr << "Pipe (out) creation failed for " << name << std::endl;
#endif
if ( *fdin == -1){ if ( *fdin == -1){
close(pipein[0]); close(pipein[0]);
close(pipein[1]); close(pipein[1]);
@ -457,9 +421,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i
return 0; return 0;
} }
if (fderr && *fderr == -1 && pipe(pipeerr) < 0){ if (fderr && *fderr == -1 && pipe(pipeerr) < 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Pipe err creation failed for process %s", name.c_str());
std::cerr << "Pipe (err) creation failed for " << name << std::endl;
#endif
if ( *fdin == -1){ if ( *fdin == -1){
close(pipein[0]); close(pipein[0]);
close(pipein[1]); close(pipein[1]);
@ -474,9 +436,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i
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){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Could not open /dev/null for process %s: %s", name.c_str(), strerror(errno));
std::cerr << "Could not open /dev/null for " << name << ": " << strerror(errno) << std::endl;
#endif
if ( *fdin == -1){ if ( *fdin == -1){
close(pipein[0]); close(pipein[0]);
close(pipein[1]); close(pipein[1]);
@ -528,14 +488,10 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i
close(devnull); close(devnull);
} }
execvp(argv[0], argv); execvp(argv[0], argv);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "execvp() failed for process %s", name.c_str());
perror("execvp failed");
#endif
exit(42); exit(42);
}else if (pid == -1){ }else if (pid == -1){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "fork() for pipe failed for process %s", name.c_str());
std::cerr << "Failed to fork for pipe: " << name << std::endl;
#endif
if (fdin && *fdin == -1){ if (fdin && *fdin == -1){
close(pipein[0]); close(pipein[0]);
close(pipein[1]); close(pipein[1]);
@ -553,14 +509,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i
} }
return 0; return 0;
}else{ //parent }else{ //parent
#if DEBUG >= 5 DEBUG_MSG(DLVL_DEVEL, "Piped process %s started, PID %d: %s", name.c_str(), pid, argv[0]);
std::cerr << "Piped process " << name << " started";
if (fdin ) std::cerr << " in=" << (*fdin == -1 ? pipein [1] : *fdin );
if (fdout) std::cerr << " out=" << (*fdout == -1 ? pipeout[0] : *fdout);
if (fderr) std::cerr << " err=" << (*fderr == -1 ? pipeerr[0] : *fderr);
if (devnull != -1) std::cerr << " null=" << devnull;
std::cerr << ", PID " << pid << ": " << argv[0] << std::endl;
#endif
if (devnull != -1){ if (devnull != -1){
close(devnull); close(devnull);
} }
@ -611,9 +560,7 @@ pid_t Util::Procs::StartPiped(std::string name, std::string cmd, int * fdin, int
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){
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Pipe creation failed for process %s", name.c_str());
std::cerr << "Process " << name << " could not be started. Pipe creation failed." << std::endl;
#endif
return 0; return 0;
} }
pid_t res1 = StartPiped(name, cmd1, fdin, &pfildes[1], fderr1); pid_t res1 = StartPiped(name, cmd1, fdin, &pfildes[1], fderr1);

View file

@ -2,6 +2,7 @@
/// Holds all code for the RTMPStream namespace. /// Holds all code for the RTMPStream namespace.
#include "rtmpchunks.h" #include "rtmpchunks.h"
#include "defines.h"
#include "flv_tag.h" #include "flv_tag.h"
#include "timing.h" #include "timing.h"
@ -261,9 +262,7 @@ bool ValidateClientScheme(uint8_t * pBuffer, uint8_t scheme){
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);
#if DEBUG >= 5 DEBUG_MSG(DLVL_MEDIUM, "Client scheme validation %hhi %s", scheme, result?"success":"failed");
fprintf(stderr, "Client scheme validation %hhi %s\n", scheme, result?"success":"failed");
#endif
delete[] pTempBuffer; delete[] pTempBuffer;
delete[] pTempHash; delete[] pTempHash;
return result; return result;
@ -556,7 +555,7 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
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 (prev.msg_type_id == 0){ if (prev.msg_type_id == 0){
fprintf(stderr, "Warning: Header type 0x40 with no valid previous chunk!\n"); 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;
@ -574,7 +573,7 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
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 (prev.msg_type_id == 0){ if (prev.msg_type_id == 0){
fprintf(stderr, "Warning: Header type 0x80 with no valid previous chunk!\n"); 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;
@ -589,7 +588,7 @@ bool RTMPStream::Chunk::Parse(std::string & indata){
break; break;
case 0xC0: case 0xC0:
if (prev.msg_type_id == 0){ if (prev.msg_type_id == 0){
fprintf(stderr, "Warning: Header type 0xC0 with no valid previous chunk!\n"); DEBUG_MSG(DLVL_WARN, "Warning: Header type 0xC0 with no valid previous chunk!");
} }
timestamp = prev.timestamp; timestamp = prev.timestamp;
len = prev.len; len = prev.len;
@ -704,7 +703,7 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
} //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){
fprintf(stderr, "Warning: Header type 0x40 with no valid previous chunk!\n"); 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;
@ -725,7 +724,7 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
} //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){
fprintf(stderr, "Warning: Header type 0x80 with no valid previous chunk!\n"); 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;
@ -740,7 +739,7 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer & buffer){
break; break;
case 0xC0: case 0xC0:
if (prev.msg_type_id == 0){ if (prev.msg_type_id == 0){
fprintf(stderr, "Warning: Header type 0xC0 with no valid previous chunk!\n"); DEBUG_MSG(DLVL_WARN, "Warning: Header type 0xC0 with no valid previous chunk!");
} }
timestamp = prev.timestamp; timestamp = prev.timestamp;
len = prev.len; len = prev.len;
@ -821,16 +820,12 @@ bool RTMPStream::doHandshake(){
} //"random" data } //"random" data
bool encrypted = (Version == 6); bool encrypted = (Version == 6);
#if DEBUG >= 8 DEBUG_MSG(DLVL_HIGH, "Handshake version is %hhi", Version);
fprintf(stderr, "Handshake version is %hhi\n", Version);
#endif
uint8_t _validationScheme = 5; uint8_t _validationScheme = 5;
if (ValidateClientScheme(Client, 0)) _validationScheme = 0; if (ValidateClientScheme(Client, 0)) _validationScheme = 0;
if (ValidateClientScheme(Client, 1)) _validationScheme = 1; if (ValidateClientScheme(Client, 1)) _validationScheme = 1;
#if DEBUG >= 8 DEBUG_MSG(DLVL_HIGH, "Handshake type is %hhi, encryption is %s", _validationScheme, encrypted?"on":"off");
fprintf(stderr, "Handshake type is %hhi, encryption is %s\n", _validationScheme, encrypted?"on":"off");
#endif
//FIRST 1536 bytes from server response //FIRST 1536 bytes from server response
//compute DH key position //compute DH key position

View file

@ -4,6 +4,7 @@
#include "socket.h" #include "socket.h"
#include "timing.h" #include "timing.h"
#include "defines.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <poll.h> #include <poll.h>
#include <netdb.h> #include <netdb.h>
@ -14,7 +15,6 @@
#endif #endif
#define BUFFER_BLOCKSIZE 4096 //set buffer blocksize to 4KiB #define BUFFER_BLOCKSIZE 4096 //set buffer blocksize to 4KiB
#include <iostream>//temporary for debugging
std::string uint2string(unsigned int i){ std::string uint2string(unsigned int i){
std::stringstream st; std::stringstream st;
@ -70,7 +70,7 @@ void Socket::Buffer::append(const char * newdata, const unsigned int newdatasize
} }
} }
if (data.size() > 5000){ if (data.size() > 5000){
std::cerr << "Warning: After " << newdatasize << " new bytes, buffer has " << data.size() << " parts!" << std::endl; DEBUG_MSG(DLVL_WARN, "Warning: After %d new bytes, buffer has %d parts!", newdatasize, (int)data.size());
} }
} }
@ -240,9 +240,7 @@ bool Socket::Connection::isBlocking(){
/// If the connection is already closed, nothing happens. /// If the connection is already closed, nothing happens.
void Socket::Connection::close(){ void Socket::Connection::close(){
if (connected()){ if (connected()){
#if DEBUG >= 6 DEBUG_MSG(DLVL_HIGH, "Socket %d closed", sock);
fprintf(stderr, "Socket closed.\n");
#endif
if (sock != -1){ if (sock != -1){
shutdown(sock, SHUT_RDWR); shutdown(sock, SHUT_RDWR);
errno = EINTR; errno = EINTR;
@ -285,9 +283,7 @@ Socket::Connection::Connection(std::string address, bool nonblock){
sock = socket(PF_UNIX, SOCK_STREAM, 0); sock = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock < 0){ if (sock < 0){
remotehost = strerror(errno); remotehost = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_FAIL, "Could not create socket! Error: %s", remotehost.c_str());
fprintf(stderr, "Could not create socket! Error: %s\n", remotehost.c_str());
#endif
return; return;
} }
Error = false; Error = false;
@ -307,9 +303,7 @@ Socket::Connection::Connection(std::string address, bool nonblock){
} }
}else{ }else{
remotehost = strerror(errno); remotehost = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_FAIL, "Could not connect to %s! Error: %s", address.c_str(), remotehost.c_str());
fprintf(stderr, "Could not connect to %s! Error: %s\n", address.c_str(), remotehost.c_str());
#endif
close(); close();
} }
} //Socket::Connection Unix Contructor } //Socket::Connection Unix Contructor
@ -340,9 +334,7 @@ Socket::Connection::Connection(std::string host, int port, bool nonblock){
hints.ai_next = NULL; hints.ai_next = NULL;
int s = getaddrinfo(host.c_str(), ss.str().c_str(), &hints, &result); int s = getaddrinfo(host.c_str(), ss.str().c_str(), &hints, &result);
if (s != 0){ if (s != 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_FAIL, "Could not connect to %s:%i! Error: %s", host.c_str(), port, gai_strerror(s));
fprintf(stderr, "Could not connect to %s:%i! Error: %s\n", host.c_str(), port, gai_strerror(s));
#endif
close(); close();
return; return;
} }
@ -362,9 +354,7 @@ Socket::Connection::Connection(std::string host, int port, bool nonblock){
freeaddrinfo(result); freeaddrinfo(result);
if (rp == 0){ if (rp == 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_FAIL, "Could not connect to %s! Error: %s", host.c_str(), remotehost.c_str());
fprintf(stderr, "Could not connect to %s! Error: %s\n", host.c_str(), remotehost.c_str());
#endif
close(); close();
}else{ }else{
if (nonblock){ if (nonblock){
@ -531,9 +521,7 @@ unsigned int Socket::Connection::iwrite(const void * buffer, int len){
if (errno != EPIPE){ if (errno != EPIPE){
Error = true; Error = true;
remotehost = strerror(errno); remotehost = strerror(errno);
#if DEBUG >= 2 DEBUG_MSG(DLVL_WARN, "Could not iwrite data! Error: %s\n", remotehost.c_str());
fprintf(stderr, "Could not iwrite data! Error: %s\n", remotehost.c_str());
#endif
} }
close(); close();
return 0; return 0;
@ -571,9 +559,7 @@ int Socket::Connection::iread(void * buffer, int len){
if (errno != EPIPE){ if (errno != EPIPE){
Error = true; Error = true;
remotehost = strerror(errno); remotehost = strerror(errno);
#if DEBUG >= 2 DEBUG_MSG(DLVL_WARN, "Could not iread data! Error: %s\n", remotehost.c_str());
fprintf(stderr, "Could not iread data! Error: %s\n", remotehost.c_str());
#endif
} }
close(); close();
return 0; return 0;
@ -661,7 +647,7 @@ Socket::Server::Server(){
/// \param nonblock (optional) Whether accept() calls will be nonblocking. Default is false (blocking). /// \param nonblock (optional) Whether accept() calls will be nonblocking. Default is false (blocking).
Socket::Server::Server(int port, std::string hostname, bool nonblock){ Socket::Server::Server(int port, std::string hostname, bool nonblock){
if ( !IPv6bind(port, hostname, nonblock) && !IPv4bind(port, hostname, nonblock)){ if ( !IPv6bind(port, hostname, nonblock) && !IPv4bind(port, hostname, nonblock)){
fprintf(stderr, "Could not create socket %s:%i! Error: %s\n", hostname.c_str(), port, errors.c_str()); DEBUG_MSG(DLVL_FAIL, "Could not create socket %s:%i! Error: %s", hostname.c_str(), port, errors.c_str());
sock = -1; sock = -1;
} }
} //Socket::Server TCP Constructor } //Socket::Server TCP Constructor
@ -675,9 +661,7 @@ bool Socket::Server::IPv6bind(int port, std::string hostname, bool nonblock){
sock = socket(AF_INET6, SOCK_STREAM, 0); sock = socket(AF_INET6, SOCK_STREAM, 0);
if (sock < 0){ if (sock < 0){
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Could not create IPv6 socket %s:%i! Error: %s", hostname.c_str(), port, errors.c_str());
fprintf(stderr, "Could not create IPv6 socket %s:%i! Error: %s\n", hostname.c_str(), port, errors.c_str());
#endif
return false; return false;
} }
int on = 1; int on = 1;
@ -699,23 +683,17 @@ bool Socket::Server::IPv6bind(int port, std::string hostname, bool nonblock){
if (ret == 0){ if (ret == 0){
ret = listen(sock, 100); //start listening, backlog of 100 allowed ret = listen(sock, 100); //start listening, backlog of 100 allowed
if (ret == 0){ if (ret == 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_DEVEL, "IPv6 socket success @ %s:%i\n", hostname.c_str(), port);
fprintf(stderr, "IPv6 socket success @ %s:%i\n", hostname.c_str(), port);
#endif
return true; return true;
}else{ }else{
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "IPv6 listen failed! Error: %s\n", errors.c_str());
fprintf(stderr, "IPv6 Listen failed! Error: %s\n", errors.c_str());
#endif
close(); close();
return false; return false;
} }
}else{ }else{
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "IPv6 Binding %s:%i failed (%s)\n", hostname.c_str(), port, errors.c_str());
fprintf(stderr, "IPv6 Binding %s:%i failed (%s)\n", hostname.c_str(), port, errors.c_str());
#endif
close(); close();
return false; return false;
} }
@ -730,9 +708,7 @@ bool Socket::Server::IPv4bind(int port, std::string hostname, bool nonblock){
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0){ if (sock < 0){
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Could not create IPv4 socket %s:%i! Error: %s", hostname.c_str(), port, errors.c_str());
fprintf(stderr, "Could not create IPv4 socket %s:%i! Error: %s\n", hostname.c_str(), port, errors.c_str());
#endif
return false; return false;
} }
int on = 1; int on = 1;
@ -754,23 +730,17 @@ bool Socket::Server::IPv4bind(int port, std::string hostname, bool nonblock){
if (ret == 0){ if (ret == 0){
ret = listen(sock, 100); //start listening, backlog of 100 allowed ret = listen(sock, 100); //start listening, backlog of 100 allowed
if (ret == 0){ if (ret == 0){
#if DEBUG >= 1 DEBUG_MSG(DLVL_DEVEL, "IPv4 socket success @ %s:%i\n", hostname.c_str(), port);
fprintf(stderr, "IPv4 socket success @ %s:%i\n", hostname.c_str(), port);
#endif
return true; return true;
}else{ }else{
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "IPv4 listen failed! Error: %s\n", errors.c_str());
fprintf(stderr, "IPv4 Listen failed! Error: %s\n", errors.c_str());
#endif
close(); close();
return false; return false;
} }
}else{ }else{
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "IPv4 Binding %s:%i failed (%s)\n", hostname.c_str(), port, errors.c_str());
fprintf(stderr, "IPv4 binding %s:%i failed (%s)\n", hostname.c_str(), port, errors.c_str());
#endif
close(); close();
return false; return false;
} }
@ -787,9 +757,7 @@ Socket::Server::Server(std::string address, bool nonblock){
sock = socket(AF_UNIX, SOCK_STREAM, 0); sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0){ if (sock < 0){
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Could not create unix socket %s! Error: %s", address.c_str(), errors.c_str());
fprintf(stderr, "Could not create socket! Error: %s\n", errors.c_str());
#endif
return; return;
} }
if (nonblock){ if (nonblock){
@ -807,17 +775,13 @@ Socket::Server::Server(std::string address, bool nonblock){
return; return;
}else{ }else{
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Unix listen failed! Error: %s\n", errors.c_str());
fprintf(stderr, "Listen failed! Error: %s\n", errors.c_str());
#endif
close(); close();
return; return;
} }
}else{ }else{
errors = strerror(errno); errors = strerror(errno);
#if DEBUG >= 1 DEBUG_MSG(DLVL_ERROR, "Unix Binding %s failed (%s)\n", address.c_str(), errors.c_str());
fprintf(stderr, "Binding failed! Error: %s\n", errors.c_str());
#endif
close(); close();
return; return;
} }
@ -845,29 +809,20 @@ Socket::Connection Socket::Server::accept(bool nonblock){
Socket::Connection tmp(r); Socket::Connection tmp(r);
if (r < 0){ if (r < 0){
if ((errno != EWOULDBLOCK) && (errno != EAGAIN) && (errno != EINTR)){ if ((errno != EWOULDBLOCK) && (errno != EAGAIN) && (errno != EINTR)){
#if DEBUG >= 1 DEBUG_MSG(DLVL_FAIL, "Error during accept - closing server socket %d.", sock);
fprintf(stderr, "Error during accept - closing server socket.\n");
#endif
close(); close();
} }
}else{ }else{
if (addrinfo.sin6_family == AF_INET6){ if (addrinfo.sin6_family == AF_INET6){
tmp.remotehost = inet_ntop(AF_INET6, &(addrinfo.sin6_addr), addrconv, INET6_ADDRSTRLEN); tmp.remotehost = inet_ntop(AF_INET6, &(addrinfo.sin6_addr), addrconv, INET6_ADDRSTRLEN);
#if DEBUG >= 6 DEBUG_MSG(DLVL_DEVEL, "IPv6 addr [%s]", tmp.remotehost.c_str());
fprintf(stderr,"IPv6 addr: %s\n", tmp.remotehost.c_str());
#endif
} }
if (addrinfo.sin6_family == AF_INET){ if (addrinfo.sin6_family == AF_INET){
tmp.remotehost = inet_ntop(AF_INET, &(((sockaddr_in*) &addrinfo)->sin_addr), addrconv, INET6_ADDRSTRLEN); tmp.remotehost = inet_ntop(AF_INET, &(((sockaddr_in*) &addrinfo)->sin_addr), addrconv, INET6_ADDRSTRLEN);
#if DEBUG >= 6 DEBUG_MSG(DLVL_DEVEL, "IPv4 addr [%s]", tmp.remotehost.c_str());
fprintf(stderr,"IPv4 addr: %s\n", tmp.remotehost.c_str());
#endif
} }
if (addrinfo.sin6_family == AF_UNIX){ if (addrinfo.sin6_family == AF_UNIX){
#if DEBUG >= 6 DEBUG_MSG(DLVL_DEVEL, "Unix addr [?]");
tmp.remotehost = ((sockaddr_un*)&addrinfo)->sun_path;
fprintf(stderr,"Unix socket, no address\n");
#endif
tmp.remotehost = "UNIX_SOCKET"; tmp.remotehost = "UNIX_SOCKET";
} }
} }
@ -893,9 +848,7 @@ bool Socket::Server::isBlocking(){
/// If the connection is already closed, nothing happens. /// If the connection is already closed, nothing happens.
void Socket::Server::close(){ void Socket::Server::close(){
if (connected()){ if (connected()){
#if DEBUG >= 6 DEBUG_MSG(DLVL_HIGH, "ServerSocket %d closed", sock);
fprintf(stderr, "ServerSocket closed.\n");
#endif
shutdown(sock, SHUT_RDWR); shutdown(sock, SHUT_RDWR);
errno = EINTR; errno = EINTR;
while (::close(sock) != 0 && errno == EINTR){ while (::close(sock) != 0 && errno == EINTR){

View file

@ -1,10 +1,6 @@
/// \file stream.cpp /// \file stream.cpp
/// Utilities for handling streams. /// Utilities for handling streams.
#if DEBUG >= 4
#include <iostream>
#endif
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
@ -14,6 +10,7 @@
#include "procs.h" #include "procs.h"
#include "config.h" #include "config.h"
#include "socket.h" #include "socket.h"
#include "defines.h"
std::string Util::getTmpFolder(){ std::string Util::getTmpFolder(){
std::string dir; std::string dir;
@ -83,20 +80,12 @@ Socket::Connection Util::Stream::getStream(std::string 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)){
if (ServConf["streams"][streamname]["source"].asString()[0] == '/'){ if (ServConf["streams"][streamname]["source"].asString()[0] == '/'){
#if DEBUG >= 5
std::cerr << "Opening VoD stream from file " << ServConf["streams"][streamname]["source"].asString() << std::endl;
#endif
return getVod(ServConf["streams"][streamname]["source"].asString(), streamname); return getVod(ServConf["streams"][streamname]["source"].asString(), streamname);
}else{ }else{
#if DEBUG >= 5
std::cerr << "Opening live stream " << streamname << std::endl;
#endif
return Socket::Connection(getTmpFolder() + "stream_" + streamname); return Socket::Connection(getTmpFolder() + "stream_" + streamname);
} }
} }
#if DEBUG >= 5 DEBUG_MSG(DLVL_ERROR, "Stream not found: %s", streamname.c_str());
std::cerr << "Could not open stream " << streamname << " - stream not found" << std::endl;
#endif
return Socket::Connection(); return Socket::Connection();
} }

303
lib/tinythread.cpp Normal file
View file

@ -0,0 +1,303 @@
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
Copyright (c) 2010-2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <exception>
#include "tinythread.h"
#if defined(_TTHREAD_POSIX_)
#include <unistd.h>
#include <map>
#elif defined(_TTHREAD_WIN32_)
#include <process.h>
#endif
namespace tthread {
//------------------------------------------------------------------------------
// condition_variable
//------------------------------------------------------------------------------
// NOTE 1: The Win32 implementation of the condition_variable class is based on
// the corresponding implementation in GLFW, which in turn is based on a
// description by Douglas C. Schmidt and Irfan Pyarali:
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
//
// NOTE 2: Windows Vista actually has native support for condition variables
// (InitializeConditionVariable, WakeConditionVariable, etc), but we want to
// be portable with pre-Vista Windows versions, so TinyThread++ does not use
// Vista condition variables.
//------------------------------------------------------------------------------
#if defined(_TTHREAD_WIN32_)
#define _CONDITION_EVENT_ONE 0
#define _CONDITION_EVENT_ALL 1
#endif
#if defined(_TTHREAD_WIN32_)
condition_variable::condition_variable() : mWaitersCount(0)
{
mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSection(&mWaitersCountLock);
}
#endif
#if defined(_TTHREAD_WIN32_)
condition_variable::~condition_variable()
{
CloseHandle(mEvents[_CONDITION_EVENT_ONE]);
CloseHandle(mEvents[_CONDITION_EVENT_ALL]);
DeleteCriticalSection(&mWaitersCountLock);
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::_wait()
{
// Wait for either event to become signaled due to notify_one() or
// notify_all() being called
int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE);
// Check if we are the last waiter
EnterCriticalSection(&mWaitersCountLock);
-- mWaitersCount;
bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
(mWaitersCount == 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we are the last waiter to be notified to stop waiting, reset the event
if(lastWaiter)
ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::notify_one()
{
// Are there any waiters?
EnterCriticalSection(&mWaitersCountLock);
bool haveWaiters = (mWaitersCount > 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal
if(haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ONE]);
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::notify_all()
{
// Are there any waiters?
EnterCriticalSection(&mWaitersCountLock);
bool haveWaiters = (mWaitersCount > 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal
if(haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ALL]);
}
#endif
//------------------------------------------------------------------------------
// POSIX pthread_t to unique thread::id mapping logic.
// Note: Here we use a global thread safe std::map to convert instances of
// pthread_t to small thread identifier numbers (unique within one process).
// This method should be portable across different POSIX implementations.
//------------------------------------------------------------------------------
#if defined(_TTHREAD_POSIX_)
static thread::id _pthread_t_to_ID(const pthread_t &aHandle)
{
static mutex idMapLock;
static std::map<pthread_t, unsigned long int> idMap;
static unsigned long int idCount(1);
lock_guard<mutex> guard(idMapLock);
if(idMap.find(aHandle) == idMap.end())
idMap[aHandle] = idCount ++;
return thread::id(idMap[aHandle]);
}
#endif // _TTHREAD_POSIX_
//------------------------------------------------------------------------------
// thread
//------------------------------------------------------------------------------
/// Information to pass to the new thread (what to run).
struct _thread_start_info {
void (*mFunction)(void *); ///< Pointer to the function to be executed.
void * mArg; ///< Function argument for the thread function.
thread * mThread; ///< Pointer to the thread object.
};
// Thread wrapper function.
#if defined(_TTHREAD_WIN32_)
unsigned WINAPI thread::wrapper_function(void * aArg)
#elif defined(_TTHREAD_POSIX_)
void * thread::wrapper_function(void * aArg)
#endif
{
// Get thread startup information
_thread_start_info * ti = (_thread_start_info *) aArg;
try
{
// Call the actual client thread function
ti->mFunction(ti->mArg);
}
catch(...)
{
// Uncaught exceptions will terminate the application (default behavior
// according to C++11)
std::terminate();
}
// The thread is no longer executing
lock_guard<mutex> guard(ti->mThread->mDataMutex);
ti->mThread->mNotAThread = true;
// The thread is responsible for freeing the startup information
delete ti;
return 0;
}
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->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;
delete ti;
}
}
thread::~thread()
{
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
}
unsigned thread::hardware_concurrency()
{
#if defined(_TTHREAD_WIN32_)
SYSTEM_INFO si;
GetSystemInfo(&si);
return (int) si.dwNumberOfProcessors;
#elif defined(_SC_NPROCESSORS_ONLN)
return (int) sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_SC_NPROC_ONLN)
return (int) sysconf(_SC_NPROC_ONLN);
#else
// The standard requires this function to return zero if the number of
// hardware cores could not be determined.
return 0;
#endif
}
//------------------------------------------------------------------------------
// this_thread
//------------------------------------------------------------------------------
thread::id this_thread::get_id()
{
#if defined(_TTHREAD_WIN32_)
return thread::id((unsigned long int) GetCurrentThreadId());
#elif defined(_TTHREAD_POSIX_)
return _pthread_t_to_ID(pthread_self());
#endif
}
}

714
lib/tinythread.h Normal file
View file

@ -0,0 +1,714 @@
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
Copyright (c) 2010-2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef _TINYTHREAD_H_
#define _TINYTHREAD_H_
/// @file
/// @mainpage TinyThread++ API Reference
///
/// @section intro_sec Introduction
/// TinyThread++ is a minimal, portable implementation of basic threading
/// classes for C++.
///
/// They closely mimic the functionality and naming of the C++11 standard, and
/// should be easily replaceable with the corresponding std:: variants.
///
/// @section port_sec Portability
/// The Win32 variant uses the native Win32 API for implementing the thread
/// classes, while for other systems, the POSIX threads API (pthread) is used.
///
/// @section class_sec Classes
/// In order to mimic the threading API of the C++11 standard, subsets of
/// several classes are provided. The fundamental classes are:
/// @li tthread::thread
/// @li tthread::mutex
/// @li tthread::recursive_mutex
/// @li tthread::condition_variable
/// @li tthread::lock_guard
/// @li tthread::fast_mutex
///
/// @section misc_sec Miscellaneous
/// The following special keywords are available: #thread_local.
///
/// For more detailed information (including additional classes), browse the
/// different sections of this documentation. A good place to start is:
/// tinythread.h.
// Which platform are we on?
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
#define _TTHREAD_WIN32_
#else
#define _TTHREAD_POSIX_
#endif
#define _TTHREAD_PLATFORM_DEFINED_
#endif
// Platform specific includes
#if defined(_TTHREAD_WIN32_)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define __UNDEF_LEAN_AND_MEAN
#endif
#include <windows.h>
#ifdef __UNDEF_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#undef __UNDEF_LEAN_AND_MEAN
#endif
#else
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#endif
// Generic includes
#include <ostream>
/// TinyThread++ version (major number).
#define TINYTHREAD_VERSION_MAJOR 1
/// TinyThread++ version (minor number).
#define TINYTHREAD_VERSION_MINOR 1
/// TinyThread++ version (full version).
#define TINYTHREAD_VERSION (TINYTHREAD_VERSION_MAJOR * 100 + TINYTHREAD_VERSION_MINOR)
// Do we have a fully featured C++11 compiler?
#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L))
#define _TTHREAD_CPP11_
#endif
// ...at least partial C++11?
#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
#define _TTHREAD_CPP11_PARTIAL_
#endif
// Macro for disabling assignments of objects.
#ifdef _TTHREAD_CPP11_PARTIAL_
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&) = delete; \
name& operator=(const name&) = delete;
#else
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&); \
name& operator=(const name&);
#endif
/// @def thread_local
/// Thread local storage keyword.
/// A variable that is declared with the @c thread_local keyword makes the
/// value of the variable local to each thread (known as thread-local storage,
/// or TLS). Example usage:
/// @code
/// // This variable is local to each thread.
/// thread_local int variable;
/// @endcode
/// @note The @c thread_local keyword is a macro that maps to the corresponding
/// compiler directive (e.g. @c __declspec(thread)). While the C++11 standard
/// allows for non-trivial types (e.g. classes with constructors and
/// destructors) to be declared with the @c thread_local keyword, most pre-C++11
/// compilers only allow for trivial types (e.g. @c int). So, to guarantee
/// portable code, only use trivial types for thread local storage.
/// @note This directive is currently not supported on Mac OS X (it will give
/// a compiler error), since compile-time TLS is not supported in the Mac OS X
/// executable format. Also, some older versions of MinGW (before GCC 4.x) do
/// not support this directive.
/// @hideinitializer
#if !defined(_TTHREAD_CPP11_) && !defined(thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define thread_local __thread
#else
#define thread_local __declspec(thread)
#endif
#endif
/// Main name space for TinyThread++.
/// This namespace is more or less equivalent to the @c std namespace for the
/// C++11 thread classes. For instance, the tthread::mutex class corresponds to
/// the std::mutex class.
namespace tthread {
/// Mutex class.
/// This is a mutual exclusion object for synchronizing access to shared
/// memory areas for several threads. The mutex is non-recursive (i.e. a
/// program may deadlock if the thread that owns a mutex object calls lock()
/// on that object).
/// @see recursive_mutex
class mutex {
public:
/// Constructor.
mutex()
#if defined(_TTHREAD_WIN32_)
: mAlreadyLocked(false)
#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);
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
friend class condition_variable;
};
/// Recursive mutex class.
/// This is a mutual exclusion object for synchronizing access to shared
/// memory areas for several threads. The mutex is recursive (i.e. a thread
/// may lock the mutex several times, as long as it unlocks the mutex the same
/// number of times).
/// @see mutex
class recursive_mutex {
public:
/// Constructor.
recursive_mutex()
{
#if defined(_TTHREAD_WIN32_)
InitializeCriticalSection(&mHandle);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mHandle, &attr);
#endif
}
/// Destructor.
~recursive_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);
#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_)
return TryEnterCriticalSection(&mHandle) ? true : false;
#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_)
LeaveCriticalSection(&mHandle);
#else
pthread_mutex_unlock(&mHandle);
#endif
}
_TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex)
private:
#if defined(_TTHREAD_WIN32_)
CRITICAL_SECTION mHandle;
#else
pthread_mutex_t mHandle;
#endif
friend class condition_variable;
};
/// Lock guard class.
/// The constructor locks the mutex, and the destructor unlocks the mutex, so
/// the mutex will automatically be unlocked when the lock guard goes out of
/// scope. Example usage:
/// @code
/// mutex m;
/// int counter;
///
/// void increment()
/// {
/// lock_guard<mutex> guard(m);
/// ++ counter;
/// }
/// @endcode
template <class T>
class lock_guard {
public:
typedef T mutex_type;
lock_guard() : mMutex(0) {}
/// The constructor locks the mutex.
explicit lock_guard(mutex_type &aMutex)
{
mMutex = &aMutex;
mMutex->lock();
}
/// The destructor unlocks the mutex.
~lock_guard()
{
if(mMutex)
mMutex->unlock();
}
private:
mutex_type * mMutex;
};
/// Condition variable class.
/// This is a signalling object for synchronizing the execution flow for
/// several threads. Example usage:
/// @code
/// // Shared data and associated mutex and condition variable objects
/// int count;
/// mutex m;
/// condition_variable cond;
///
/// // Wait for the counter to reach a certain number
/// void wait_counter(int targetCount)
/// {
/// lock_guard<mutex> guard(m);
/// while(count < targetCount)
/// cond.wait(m);
/// }
///
/// // Increment the counter, and notify waiting threads
/// void increment()
/// {
/// lock_guard<mutex> guard(m);
/// ++ count;
/// cond.notify_all();
/// }
/// @endcode
class condition_variable {
public:
/// Constructor.
#if defined(_TTHREAD_WIN32_)
condition_variable();
#else
condition_variable()
{
pthread_cond_init(&mHandle, NULL);
}
#endif
/// Destructor.
#if defined(_TTHREAD_WIN32_)
~condition_variable();
#else
~condition_variable()
{
pthread_cond_destroy(&mHandle);
}
#endif
/// Wait for the condition.
/// 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.
/// @param[in] aMutex A mutex that will be unlocked when the wait operation
/// starts, an locked again as soon as the wait operation is finished.
template <class _mutexT>
inline void wait(_mutexT &aMutex)
{
#if defined(_TTHREAD_WIN32_)
// Increment number of waiters
EnterCriticalSection(&mWaitersCountLock);
++ mWaitersCount;
LeaveCriticalSection(&mWaitersCountLock);
// Release the mutex while waiting for the condition (will decrease
// the number of waiters when done)...
aMutex.unlock();
_wait();
aMutex.lock();
#else
pthread_cond_wait(&mHandle, &aMutex.mHandle);
#endif
}
/// Notify one thread that is waiting for the condition.
/// If at least one thread is blocked waiting for this condition variable,
/// one will be woken up.
/// @note Only threads that started waiting prior to this call will be
/// woken up.
#if defined(_TTHREAD_WIN32_)
void notify_one();
#else
inline void notify_one()
{
pthread_cond_signal(&mHandle);
}
#endif
/// Notify all threads that are waiting for the condition.
/// All threads that are blocked waiting for this condition variable will
/// be woken up.
/// @note Only threads that started waiting prior to this call will be
/// woken up.
#if defined(_TTHREAD_WIN32_)
void notify_all();
#else
inline void notify_all()
{
pthread_cond_broadcast(&mHandle);
}
#endif
_TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
private:
#if defined(_TTHREAD_WIN32_)
void _wait();
HANDLE mEvents[2]; ///< Signal and broadcast event HANDLEs.
unsigned int mWaitersCount; ///< Count of the number of waiters.
CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount.
#else
pthread_cond_t mHandle;
#endif
};
/// Thread class.
class thread {
public:
#if defined(_TTHREAD_WIN32_)
typedef HANDLE native_handle_type;
#else
typedef pthread_t native_handle_type;
#endif
class id;
/// Default constructor.
/// Construct a @c thread object without an associated thread of execution
/// (i.e. non-joinable).
thread() : mHandle(0), mNotAThread(true)
#if defined(_TTHREAD_WIN32_)
, mWin32ThreadID(0)
#endif
{}
/// Thread starting constructor.
/// Construct a @c thread object with a new thread of execution.
/// @param[in] aFunction A function pointer to a function of type:
/// <tt>void fun(void * arg)</tt>
/// @param[in] aArg Argument to the thread function.
/// @note This constructor is not fully compatible with the standard C++
/// thread class. It is more similar to the pthread_create() (POSIX) and
/// CreateThread() (Windows) functions.
thread(void (*aFunction)(void *), void * aArg);
/// Destructor.
/// @note If the thread is joinable upon destruction, @c std::terminate()
/// will be called, which terminates the process. It is always wise to do
/// @c join() before deleting a thread object.
~thread();
/// Wait for the thread to finish (join execution flows).
/// 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
/// with it nor detach from it).
void join();
/// Check if the thread is joinable.
/// A thread object is joinable if it has an associated thread of execution.
bool joinable() const;
/// Detach from the thread.
/// 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
/// execution without the calling thread blocking, and when the thread
/// ends execution, any owned resources are released.
void detach();
/// Return the thread ID of a thread object.
id get_id() const;
/// Get the native handle for this thread.
/// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
/// is a @c pthread_t.
inline native_handle_type native_handle()
{
return mHandle;
}
/// Determine the number of threads which can possibly execute concurrently.
/// This function is useful for determining the optimal number of threads to
/// use for a task.
/// @return The number of hardware thread contexts in the system.
/// @note If this value is not defined, the function returns zero (0).
static unsigned hardware_concurrency();
_TTHREAD_DISABLE_ASSIGNMENT(thread)
private:
native_handle_type mHandle; ///< Thread handle.
mutable mutex mDataMutex; ///< Serializer for access to the thread private data.
bool mNotAThread; ///< True if this object is not a thread of execution.
#if defined(_TTHREAD_WIN32_)
unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
#endif
// This is the internal thread wrapper function.
#if defined(_TTHREAD_WIN32_)
static unsigned WINAPI wrapper_function(void * aArg);
#else
static void * wrapper_function(void * aArg);
#endif
};
/// Thread ID.
/// The thread ID is a unique identifier for each thread.
/// @see thread::get_id()
class thread::id {
public:
/// Default constructor.
/// The default constructed ID is that of thread without a thread of
/// execution.
id() : mId(0) {};
id(unsigned long int aId) : mId(aId) {};
id(const id& aId) : mId(aId.mId) {};
inline id & operator=(const id &aId)
{
mId = aId.mId;
return *this;
}
inline friend bool operator==(const id &aId1, const id &aId2)
{
return (aId1.mId == aId2.mId);
}
inline friend bool operator!=(const id &aId1, const id &aId2)
{
return (aId1.mId != aId2.mId);
}
inline friend bool operator<=(const id &aId1, const id &aId2)
{
return (aId1.mId <= aId2.mId);
}
inline friend bool operator<(const id &aId1, const id &aId2)
{
return (aId1.mId < aId2.mId);
}
inline friend bool operator>=(const id &aId1, const id &aId2)
{
return (aId1.mId >= aId2.mId);
}
inline friend bool operator>(const id &aId1, const id &aId2)
{
return (aId1.mId > aId2.mId);
}
inline friend std::ostream& operator <<(std::ostream &os, const id &obj)
{
os << obj.mId;
return os;
}
private:
unsigned long int mId;
};
// Related to <ratio> - minimal to be able to support chrono.
typedef long long __intmax_t;
/// Minimal implementation of the @c ratio class. This class provides enough
/// functionality to implement some basic @c chrono classes.
template <__intmax_t N, __intmax_t D = 1> class ratio {
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:
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
/// calling thread.
namespace this_thread {
/// Return the thread ID of the calling thread.
thread::id get_id();
/// Yield execution to another thread.
/// Offers the operating system the opportunity to schedule another thread
/// that is ready to run on the current processor.
inline void yield()
{
#if defined(_TTHREAD_WIN32_)
Sleep(0);
#else
sched_yield();
#endif
}
/// Blocks the calling thread for a period of time.
/// @param[in] aTime Minimum time to put the thread to sleep.
/// Example usage:
/// @code
/// // Sleep for 100 milliseconds
/// this_thread::sleep_for(chrono::milliseconds(100));
/// @endcode
/// @note Supported duration types are: nanoseconds, microseconds,
/// milliseconds, seconds, minutes and hours.
template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period>& aTime)
{
#if defined(_TTHREAD_WIN32_)
Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
#else
usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
#endif
}
}
}
// Define/macro cleanup
#undef _TTHREAD_DISABLE_ASSIGNMENT
#endif // _TINYTHREAD_H_

View file

@ -3,6 +3,7 @@
#include <sstream> #include <sstream>
#include "ts_packet.h" #include "ts_packet.h"
#include "defines.h"
#ifndef FILLER_DATA #ifndef FILLER_DATA
#define FILLER_DATA "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo vulputate urna eu commodo. Cras tempor velit nec nulla placerat volutpat. Proin eleifend blandit quam sit amet suscipit. Pellentesque vitae tristique lorem. Maecenas facilisis consequat neque, vitae iaculis eros vulputate ut. Suspendisse ut arcu non eros vestibulum pulvinar id sed erat. Nam dictum tellus vel tellus rhoncus ut mollis tellus fermentum. Fusce volutpat consectetur ante, in mollis nisi euismod vulputate. Curabitur vitae facilisis ligula. Sed sed gravida dolor. Integer eu eros a dolor lobortis ullamcorper. Mauris interdum elit non neque interdum dictum. Suspendisse imperdiet eros sed sapien cursus pulvinar. Vestibulum ut dolor lectus, id commodo elit. Cras convallis varius leo eu porta. Duis luctus sapien nec dui adipiscing quis interdum nunc congue. Morbi pharetra aliquet mauris vitae tristique. Etiam feugiat sapien quis augue elementum id ultricies magna vulputate. Phasellus luctus, leo id egestas consequat, eros tortor commodo neque, vitae hendrerit nunc sem ut odio." #define FILLER_DATA "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo vulputate urna eu commodo. Cras tempor velit nec nulla placerat volutpat. Proin eleifend blandit quam sit amet suscipit. Pellentesque vitae tristique lorem. Maecenas facilisis consequat neque, vitae iaculis eros vulputate ut. Suspendisse ut arcu non eros vestibulum pulvinar id sed erat. Nam dictum tellus vel tellus rhoncus ut mollis tellus fermentum. Fusce volutpat consectetur ante, in mollis nisi euismod vulputate. Curabitur vitae facilisis ligula. Sed sed gravida dolor. Integer eu eros a dolor lobortis ullamcorper. Mauris interdum elit non neque interdum dictum. Suspendisse imperdiet eros sed sapien cursus pulvinar. Vestibulum ut dolor lectus, id commodo elit. Cras convallis varius leo eu porta. Duis luctus sapien nec dui adipiscing quis interdum nunc congue. Morbi pharetra aliquet mauris vitae tristique. Etiam feugiat sapien quis augue elementum id ultricies magna vulputate. Phasellus luctus, leo id egestas consequat, eros tortor commodo neque, vitae hendrerit nunc sem ut odio."
@ -236,7 +237,7 @@ void TS::Packet::DefaultPMT(){
/// \return A string representation of the packet. /// \return A string representation of the packet.
const char* TS::Packet::ToString(){ const char* TS::Packet::ToString(){
if (strBuf.size() != 188){ if (strBuf.size() != 188){
std::cerr << "Error: Size invalid (" << strBuf.size() << ") Invalid data from this point on." << std::endl; DEBUG_MSG(DLVL_ERROR, "Size invalid (%i) - invalid data from this point on", (int)strBuf.size());
} }
return strBuf.c_str(); return strBuf.c_str();
} }

View file

@ -1,4 +1,5 @@
#include "vorbis.h" #include "vorbis.h"
#include "defines.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sstream> #include <sstream>
@ -236,7 +237,7 @@ namespace vorbis{
long long unsigned int floorType = stream.get(16); long long unsigned int floorType = stream.get(16);
switch(floorType){ switch(floorType){
case 0:{ case 0:{
std::cerr << "WARNING: FloorType 0 in vorbis setup header not tested!" << std::endl; 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
@ -339,7 +340,7 @@ namespace vorbis{
} }
char meh = stream.get(2); char meh = stream.get(2);
if (meh != 0){ if (meh != 0){
std::cerr << " Sanity Check ==0 : " << (int)meh << std::endl; DEBUG_MSG(DLVL_ERROR, "Sanity check ==0 : %i", (int)meh);
exit(0); exit(0);
} }
if (mappingSubmaps > 1){ if (mappingSubmaps > 1){