Merge branch 'development' into LTS_development

# Conflicts:
#	src/input/input_buffer.cpp
This commit is contained in:
Thulinma 2016-02-12 16:18:54 +01:00
commit 53febd82d1
10 changed files with 91 additions and 36 deletions

View file

@ -329,6 +329,8 @@ namespace DTSC {
int width; int width;
int height; int height;
int fpks; int fpks;
private:
std::string cachedIdent;
}; };
///\brief Class for storage of meta data ///\brief Class for storage of meta data

View file

@ -1502,9 +1502,11 @@ namespace DTSC {
///\brief Returns a writable identifier for a track, to prevent overwrites on readout ///\brief Returns a writable identifier for a track, to prevent overwrites on readout
std::string Track::getWritableIdentifier() { std::string Track::getWritableIdentifier() {
if (cachedIdent.size()){return cachedIdent;}
std::stringstream result; std::stringstream result;
result << getIdentifier() << "_" << trackID; result << getIdentifier() << "_" << trackID;
return result.str(); cachedIdent = result.str();
return cachedIdent;
} }
///\brief Determines the "packed" size of a track ///\brief Determines the "packed" size of a track
@ -1545,8 +1547,9 @@ namespace DTSC {
///\brief Writes a track to a pointer ///\brief Writes a track to a pointer
void Track::writeTo(char *& p) { void Track::writeTo(char *& p) {
writePointer(p, convertShort(getWritableIdentifier().size()), 2); std::string trackIdent = getWritableIdentifier();
writePointer(p, getWritableIdentifier()); writePointer(p, convertShort(trackIdent.size()), 2);
writePointer(p, trackIdent);
writePointer(p, "\340", 1);//Begin track object writePointer(p, "\340", 1);//Begin track object
writePointer(p, "\000\011fragments\002", 12); writePointer(p, "\000\011fragments\002", 12);
writePointer(p, convertInt(fragments.size() * PACKED_FRAGMENT_SIZE), 4); writePointer(p, convertInt(fragments.size() * PACKED_FRAGMENT_SIZE), 4);

View file

@ -70,7 +70,7 @@ void Socket::Buffer::append(const char * newdata, const unsigned int newdatasize
} }
} }
if (i != j) { if (i != j) {
DONTEVEN_MSG("Adding a block of size %d", j-i); DONTEVEN_MSG("Adding a block of size %d", j - i);
data.push_front(std::string(newdata + i, (size_t)(j - i))); data.push_front(std::string(newdata + i, (size_t)(j - i)));
i = j; i = j;
} else { } else {
@ -294,7 +294,7 @@ void Socket::Connection::drop() {
/// Returns internal socket number. /// Returns internal socket number.
int Socket::Connection::getSocket() { int Socket::Connection::getSocket() {
if (sock != -1){ if (sock != -1) {
return sock; return sock;
} }
if (pipes[0] != -1) { if (pipes[0] != -1) {
@ -542,7 +542,7 @@ int Socket::Connection::iread(void * buffer, int len, int flags) {
r = recv(sock, buffer, len, flags); r = recv(sock, buffer, len, flags);
} else { } else {
r = recv(pipes[1], buffer, len, flags); r = recv(pipes[1], buffer, len, flags);
if (r < 0 && errno == ENOTSOCK){ if (r < 0 && errno == ENOTSOCK) {
r = read(pipes[1], buffer, len); r = read(pipes[1], buffer, len);
} }
} }
@ -606,14 +606,14 @@ bool Socket::Connection::iwrite(std::string & buffer) {
} //iwrite } //iwrite
/// Gets hostname for connection, if available. /// Gets hostname for connection, if available.
std::string Socket::Connection::getHost() { std::string Socket::Connection::getHost() const {
return remotehost; return remotehost;
} }
/// Gets hostname for connection, if available. /// Gets hostname for connection, if available.
/// Guaranteed to be either empty or 16 bytes long. /// Guaranteed to be either empty or 16 bytes long.
std::string Socket::Connection::getBinHost() { std::string Socket::Connection::getBinHost() {
if (remotehost.size()){ if (remotehost.size()) {
struct addrinfo * result, *rp, hints; struct addrinfo * result, *rp, hints;
memset(&hints, 0, sizeof(struct addrinfo)); memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
@ -630,16 +630,16 @@ std::string Socket::Connection::getBinHost() {
} }
char tmpBuffer[17] = "\000\000\000\000\000\000\000\000\000\000\377\377\000\000\000\000"; char tmpBuffer[17] = "\000\000\000\000\000\000\000\000\000\000\377\377\000\000\000\000";
for (rp = result; rp != NULL; rp = rp->ai_next) { for (rp = result; rp != NULL; rp = rp->ai_next) {
if (rp->ai_family == AF_INET){ if (rp->ai_family == AF_INET) {
memcpy(tmpBuffer + 12, &((sockaddr_in *)rp->ai_addr)->sin_addr.s_addr, 4); memcpy(tmpBuffer + 12, &((sockaddr_in *)rp->ai_addr)->sin_addr.s_addr, 4);
} }
if (rp->ai_family == AF_INET6){ if (rp->ai_family == AF_INET6) {
memcpy(tmpBuffer, ((sockaddr_in6 *)rp->ai_addr)->sin6_addr.s6_addr, 16); memcpy(tmpBuffer, ((sockaddr_in6 *)rp->ai_addr)->sin6_addr.s6_addr, 16);
} }
} }
freeaddrinfo(result); freeaddrinfo(result);
return std::string(tmpBuffer, 16); return std::string(tmpBuffer, 16);
}else{ } else {
return ""; return "";
} }
} }
@ -971,12 +971,18 @@ int Socket::Server::getSocket() {
/// If both fail, prints an DLVL_FAIL debug message. /// If both fail, prints an DLVL_FAIL debug message.
/// \param nonblock Whether the socket should be nonblocking. /// \param nonblock Whether the socket should be nonblocking.
Socket::UDPConnection::UDPConnection(bool nonblock) { Socket::UDPConnection::UDPConnection(bool nonblock) {
#ifdef __CYGWIN__
#warning UDP over IPv6 is currently disabled on windows
isIPv6 = false;
sock = socket(AF_INET, SOCK_DGRAM, 0);
#else
isIPv6 = true; isIPv6 = true;
sock = socket(AF_INET6, SOCK_DGRAM, 0); sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock == -1) { if (sock == -1) {
sock = socket(AF_INET, SOCK_DGRAM, 0); sock = socket(AF_INET, SOCK_DGRAM, 0);
isIPv6 = false; isIPv6 = false;
} }
#endif
if (sock == -1) { if (sock == -1) {
DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno));
} }
@ -995,18 +1001,18 @@ Socket::UDPConnection::UDPConnection(bool nonblock) {
/// Copies a UDP socket, re-allocating local copies of any needed structures. /// Copies a UDP socket, re-allocating local copies of any needed structures.
/// The data/data_size/data_len variables are *not* copied over. /// The data/data_size/data_len variables are *not* copied over.
Socket::UDPConnection::UDPConnection(const UDPConnection & o) { Socket::UDPConnection::UDPConnection(const UDPConnection & o) {
#ifdef __CYGWIN__
#warning UDP over IPv6 is currently disabled on windows
isIPv6 = false;
sock = socket(AF_INET, SOCK_DGRAM, 0);
#else
isIPv6 = true; isIPv6 = true;
sock = socket(AF_INET6, SOCK_DGRAM, 0); sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock == -1) { if (sock == -1) {
sock = socket(AF_INET, SOCK_DGRAM, 0); sock = socket(AF_INET, SOCK_DGRAM, 0);
isIPv6 = false; isIPv6 = false;
}else{
#ifdef __CYGWIN__
// Under windows, turn IPv6-only mode off.
int on = 0;
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
#endif
} }
#endif
if (sock == -1) { if (sock == -1) {
DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno));
} }
@ -1144,8 +1150,9 @@ void Socket::UDPConnection::SendNow(const char * sdata, size_t len) {
/// If that fails too, gives up and returns zero. /// If that fails too, gives up and returns zero.
/// Prints a debug message at DLVL_FAIL level if binding failed. /// Prints a debug message at DLVL_FAIL level if binding failed.
/// \return Actually bound port number, or zero on error. /// \return Actually bound port number, or zero on error.
int Socket::UDPConnection::bind(int port, std::string iface) { int Socket::UDPConnection::bind(int port, std::string iface, const std::string & multicastInterfaces) {
if (isIPv6){ int result = 0;
if (isIPv6) {
struct sockaddr_in6 s6; struct sockaddr_in6 s6;
memset(&s6, 0, sizeof(s6)); memset(&s6, 0, sizeof(s6));
s6.sin6_family = AF_INET6; s6.sin6_family = AF_INET6;
@ -1157,25 +1164,47 @@ int Socket::UDPConnection::bind(int port, std::string iface) {
s6.sin6_port = htons(port); s6.sin6_port = htons(port);
int r = ::bind(sock, (sockaddr *)&s6, sizeof(s6)); int r = ::bind(sock, (sockaddr *)&s6, sizeof(s6));
if (r == 0) { if (r == 0) {
return ntohs(s6.sin6_port); result = ntohs(s6.sin6_port);
} }
}else{ } else {
struct sockaddr_in s4; struct sockaddr_in s4;
memset(&s4, 0, sizeof(s4)); memset(&s4, 0, sizeof(s4));
s4.sin_family = AF_INET; s4.sin_family = AF_INET;
if (iface == "0.0.0.0" || iface.length() == 0) { if (iface == "0.0.0.0" || iface.length() == 0) {
s4.sin_addr.s_addr = INADDR_ANY; s4.sin_addr.s_addr = htonl(INADDR_ANY);
} else { } else {
inet_pton(AF_INET, iface.c_str(), &s4.sin_addr); inet_pton(AF_INET, iface.c_str(), &s4.sin_addr);
} }
s4.sin_port = htons(port); s4.sin_port = htons(port);
int r = ::bind(sock, (sockaddr *)&s4, sizeof(s4)); int r = ::bind(sock, (sockaddr *)&s4, sizeof(s4));
if (r == 0) { if (r == 0) {
return ntohs(s4.sin_port); result = ntohs(s4.sin_port);
} }
} }
DEBUG_MSG(DLVL_FAIL, "Could not bind %s UDP socket to port %d: %s", isIPv6?"IPv6":"IPv4", port, strerror(errno)); if (!result){
return 0; DEBUG_MSG(DLVL_FAIL, "Could not bind %s UDP socket to port %d: %s", isIPv6 ? "IPv6" : "IPv4", port, strerror(errno));
return 0;
}
//Detect multicast
if (iface.length() && ((atoi(iface.c_str()) & 0xE0) == 0xE0)){
if (!multicastInterfaces.length()){
WARN_MSG("Multicast IP given without any defined interfaces");
}else{
struct ip_mreq group;
inet_pton(AF_INET, iface.c_str(), &group.imr_multiaddr.s_addr);
size_t loc = 0;
while (loc != std::string::npos){
size_t nxtPos = multicastInterfaces.find(',', loc);
std::string curIface = multicastInterfaces.substr(loc, (nxtPos == std::string::npos ? nxtPos : nxtPos - loc));
inet_pton(AF_INET, curIface.c_str(), &group.imr_interface.s_addr);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) {
WARN_MSG("Unable to register for multicast on interface %s: %s", curIface.c_str() , strerror(errno));
}
loc = (nxtPos == std::string::npos ? nxtPos : nxtPos + 1);
}
}
}
return result;
} }
/// Attempt to receive a UDP packet. /// Attempt to receive a UDP packet.
@ -1183,9 +1212,15 @@ int Socket::UDPConnection::bind(int port, std::string iface) {
/// If a packet is received, it will be placed in the "data" member, with it's length in "data_len". /// If a packet is received, it will be placed in the "data" member, with it's length in "data_len".
/// \return True if a packet was received, false otherwise. /// \return True if a packet was received, false otherwise.
bool Socket::UDPConnection::Receive() { bool Socket::UDPConnection::Receive() {
#ifdef __CYGWIN__
if (data_size != SOCKETSIZE){
data = (char *)realloc(data, SOCKETSIZE);
data_size = SOCKETSIZE;
}
#endif
int r = recvfrom(sock, data, data_size, MSG_PEEK | MSG_TRUNC, 0, 0); int r = recvfrom(sock, data, data_size, MSG_PEEK | MSG_TRUNC, 0, 0);
if (r == -1){ if (r == -1) {
if (errno != EAGAIN){ if (errno != EAGAIN) {
INFO_MSG("Found an error: %d (%s)", errno, strerror(errno)); INFO_MSG("Found an error: %d (%s)", errno, strerror(errno));
} }
data_len = 0; data_len = 0;

View file

@ -71,7 +71,7 @@ namespace Socket {
void drop(); ///< Close connection without shutdown. void drop(); ///< Close connection without shutdown.
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false). void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false). bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
std::string getHost(); ///< Gets hostname for connection, if available. std::string getHost() const; ///< Gets hostname for connection, if available.
std::string getBinHost(); std::string getBinHost();
void setHost(std::string host); ///< Sets hostname for connection manually. void setHost(std::string host); ///< Sets hostname for connection manually.
int getSocket(); ///< Returns internal socket number. int getSocket(); ///< Returns internal socket number.
@ -137,7 +137,7 @@ namespace Socket {
UDPConnection(bool nonblock = false); UDPConnection(bool nonblock = false);
~UDPConnection(); ~UDPConnection();
int getSock(); int getSock();
int bind(int port, std::string iface = ""); int bind(int port, std::string iface = "", const std::string & multicastAddress = "");
void setBlocking(bool blocking); void setBlocking(bool blocking);
void SetDestination(std::string hostname, uint32_t port); void SetDestination(std::string hostname, uint32_t port);
void GetDestination(std::string & hostname, uint32_t & port); void GetDestination(std::string & hostname, uint32_t & port);

View file

@ -683,10 +683,11 @@ namespace Mist {
VERYHIGH_MSG("Updating meta for track %d", tNum); VERYHIGH_MSG("Updating meta for track %d", tNum);
//Store a reference for easier access //Store a reference for easier access
std::map<unsigned long, DTSCPageData> & locations = bufferLocations[tNum]; std::map<unsigned long, DTSCPageData> & locations = bufferLocations[tNum];
char * mappedPointer = metaPages[tNum].mapped;
//First detect all entries on metaPage //First detect all entries on metaPage
for (int i = 0; i < 8192; i += 8){ for (int i = 0; i < 8192; i += 8) {
int * tmpOffset = (int *)(metaPages[tNum].mapped + i); int * tmpOffset = (int *)(mappedPointer + i);
if (tmpOffset[0] == 0 && tmpOffset[1] == 0){ if (tmpOffset[0] == 0 && tmpOffset[1] == 0){
continue; continue;
} }

View file

@ -140,6 +140,14 @@ namespace Mist {
/*LTS-END*/ /*LTS-END*/
} }
std::string Output::getConnectedHost(){
return myConn.getHost();
}
std::string Output::getConnectedBinHost(){
return myConn.getBinHost();
}
/// Connects or reconnects to the stream. /// Connects or reconnects to the stream.
/// Assumes streamName class member has been set already. /// Assumes streamName class member has been set already.
/// Will start input if not currently active, calls onFail() if this does not succeed. /// Will start input if not currently active, calls onFail() if this does not succeed.
@ -1002,7 +1010,7 @@ namespace Mist {
IPC::statExchange tmpEx(statsPage.getData()); IPC::statExchange tmpEx(statsPage.getData());
tmpEx.now(now); tmpEx.now(now);
if (setHost){ if (setHost){
tmpEx.host(myConn.getBinHost()); tmpEx.host(getConnectedBinHost());
setHost = false; setHost = false;
} }
tmpEx.crc(crc); tmpEx.crc(crc);

View file

@ -95,6 +95,11 @@ namespace Mist {
bool sought;///<If a seek has been done, this is set to true. Used for seeking on prepareNext(). bool sought;///<If a seek has been done, this is set to true. Used for seeking on prepareNext().
bool completeKeyReadyTimeOut;//a bool to see if there has been a keyframe TimeOut for complete keys in Live bool completeKeyReadyTimeOut;//a bool to see if there has been a keyframe TimeOut for complete keys in Live
protected://these are to be messed with by child classes protected://these are to be messed with by child classes
virtual std::string getConnectedHost();
virtual std::string getConnectedBinHost();
IPC::sharedClient statsPage;///< Shared memory used for statistics reporting. IPC::sharedClient statsPage;///< Shared memory used for statistics reporting.
bool isBlocking;///< If true, indicates that myConn is blocking. bool isBlocking;///< If true, indicates that myConn is blocking.
unsigned int crc;///< Checksum, if any, for usage in the stats. unsigned int crc;///< Checksum, if any, for usage in the stats.

View file

@ -308,7 +308,7 @@ namespace Mist {
DEBUG_MSG(DLVL_HIGH, "Connector found: %s", connector.c_str()); DEBUG_MSG(DLVL_HIGH, "Connector found: %s", connector.c_str());
//build arguments for starting output process //build arguments for starting output process
std::string temphost=myConn.getHost(); std::string temphost=getConnectedHost();
std::string debuglevel = JSON::Value((long long)Util::Config::printDebugLevel).asString(); std::string debuglevel = JSON::Value((long long)Util::Config::printDebugLevel).asString();
std::string tmparg = Util::getMyPath() + std::string("MistOut") + connector; std::string tmparg = Util::getMyPath() + std::string("MistOut") + connector;

View file

@ -7,7 +7,7 @@
namespace Mist { namespace Mist {
OutHTTP::OutHTTP(Socket::Connection & conn) : HTTPOutput(conn){ OutHTTP::OutHTTP(Socket::Connection & conn) : HTTPOutput(conn){
if (myConn.getPureSocket() >= 0){ if (myConn.getPureSocket() >= 0){
std::string host = myConn.getHost(); std::string host = getConnectedHost();
dup2(myConn.getSocket(), STDIN_FILENO); dup2(myConn.getSocket(), STDIN_FILENO);
dup2(myConn.getSocket(), STDOUT_FILENO); dup2(myConn.getSocket(), STDOUT_FILENO);
myConn.drop(); myConn.drop();
@ -15,6 +15,7 @@ namespace Mist {
myConn.setHost(host); myConn.setHost(host);
} }
} }
OutHTTP::~OutHTTP() {} OutHTTP::~OutHTTP() {}
bool OutHTTP::listenMode(){ bool OutHTTP::listenMode(){

View file

@ -563,13 +563,13 @@ namespace Mist {
/*LTS-END*/ /*LTS-END*/
if (IP != ""){ if (IP != ""){
if (!myConn.isAddress(IP)){ if (!myConn.isAddress(IP)){
DEBUG_MSG(DLVL_FAIL, "Push from %s to %s rejected - source host not whitelisted", myConn.getHost().c_str(), streamName.c_str()); DEBUG_MSG(DLVL_FAIL, "Push from %s to %s rejected - source host not whitelisted", getConnectedHost().c_str(), streamName.c_str());
myConn.close(); myConn.close();
} }
} }
} }
}else{ }else{
DEBUG_MSG(DLVL_FAIL, "Push from %s rejected - stream '%s' not configured.", myConn.getHost().c_str(), streamName.c_str()); DEBUG_MSG(DLVL_FAIL, "Push from %s rejected - stream '%s' not configured.", getConnectedHost().c_str(), streamName.c_str());
myConn.close(); myConn.close();
} }
configLock.post(); configLock.post();