Added crappy "HiIpcam" IP cam support

This commit is contained in:
Thulinma 2018-01-11 15:00:24 +01:00
parent adf2d8f4f9
commit 0c6cd9bfc6
4 changed files with 65 additions and 16 deletions

View file

@ -38,15 +38,17 @@ HTTP::URL::URL(const std::string &url){
}else{ }else{
path = url.substr(first_slash); path = url.substr(first_slash);
} }
size_t hmark = path.find('#'); if (protocol != "rtsp"){
if (hmark != std::string::npos){ size_t hmark = path.find('#');
frag = Encodings::URL::decode(path.substr(hmark + 1)); if (hmark != std::string::npos){
path.erase(hmark); frag = Encodings::URL::decode(path.substr(hmark + 1));
} path.erase(hmark);
size_t qmark = path.find('?'); }
if (qmark != std::string::npos){ size_t qmark = path.find('?');
args = path.substr(qmark + 1); if (qmark != std::string::npos){
path.erase(qmark); args = path.substr(qmark + 1);
path.erase(qmark);
}
} }
if (path.size()){ if (path.size()){
if (path[0] == '/'){path.erase(0, 1);} if (path[0] == '/'){path.erase(0, 1);}
@ -172,7 +174,11 @@ std::string HTTP::URL::getUrl() const{
} }
if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;} if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;}
ret += "/"; ret += "/";
if (path.size()){ret += Encodings::URL::encode(path, "=");} if (protocol == "rtsp"){
if (path.size()){ret += Encodings::URL::encode(path, "=#?&");}
}else{
if (path.size()){ret += Encodings::URL::encode(path, "=");}
}
if (args.size()){ret += "?" + args;} if (args.size()){ret += "?" + args;}
if (frag.size()){ret += "#" + Encodings::URL::encode(frag, "=");} if (frag.size()){ret += "#" + Encodings::URL::encode(frag, "=");}
return ret; return ret;
@ -193,7 +199,11 @@ std::string HTTP::URL::getProxyUrl() const{
} }
if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;} if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;}
ret += "/"; ret += "/";
if (path.size()){ret += Encodings::URL::encode(path);} if (protocol == "rtsp"){
if (path.size()){ret += Encodings::URL::encode(path, "=#?&");}
}else{
if (path.size()){ret += Encodings::URL::encode(path, "=");}
}
if (args.size()){ret += "?" + args;} if (args.size()){ret += "?" + args;}
return ret; return ret;
} }
@ -216,7 +226,11 @@ std::string HTTP::URL::getBareUrl() const{
} }
if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;} if (port.size() && getPort() != getDefaultPort()){ret += ":" + port;}
ret += "/"; ret += "/";
if (path.size()){ret += Encodings::URL::encode(path);} if (protocol == "rtsp"){
if (path.size()){ret += Encodings::URL::encode(path, "=#?&");}
}else{
if (path.size()){ret += Encodings::URL::encode(path, "=");}
}
return ret; return ret;
} }
@ -399,8 +413,29 @@ std::string &HTTP::Parser::BuildRequest(){
/// Creates and sends a valid HTTP 1.0 or 1.1 request. /// Creates and sends a valid HTTP 1.0 or 1.1 request.
/// The request is build from internal variables set before this call is made. /// The request is build from internal variables set before this call is made.
/// To be precise, method, url, protocol, headers and body are used. /// To be precise, method, url, protocol, headers and body are used.
void HTTP::Parser::SendRequest(Socket::Connection &conn, const std::string &reqbody){ void HTTP::Parser::SendRequest(Socket::Connection &conn, const std::string &reqbody, bool allAtOnce){
/// \todo Include GET/POST variable parsing? /// \todo Include GET/POST variable parsing?
if (allAtOnce){
/// \TODO Make this less duplicated / more pretty.
std::map<std::string, std::string>::iterator it;
if (protocol.size() < 5 || protocol[4] != '/'){protocol = "HTTP/1.0";}
builder = method + " " + url + " " + protocol + "\r\n";
if (reqbody.size()){SetHeader("Content-Length", reqbody.length());}
for (it = headers.begin(); it != headers.end(); it++){
if ((*it).first != "" && (*it).second != ""){
builder += (*it).first + ": " + (*it).second + "\r\n";
}
}
builder += "\r\n";
if (reqbody.size()){
builder += reqbody;
}else{
builder += body;
}
conn.SendNow(builder);
return;
}
std::map<std::string, std::string>::iterator it; std::map<std::string, std::string>::iterator it;
if (protocol.size() < 5 || protocol[4] != '/'){protocol = "HTTP/1.0";} if (protocol.size() < 5 || protocol[4] != '/'){protocol = "HTTP/1.0";}
builder = method + " " + url + " " + protocol + "\r\n"; builder = method + " " + url + " " + protocol + "\r\n";
@ -801,6 +836,10 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer){
length = atoi(GetHeader("Content-Length").c_str()); length = atoi(GetHeader("Content-Length").c_str());
if (body.capacity() < length){body.reserve(length);} if (body.capacity() < length){body.reserve(length);}
} }
if (GetHeader("Content-length") != ""){
length = atoi(GetHeader("Content-length").c_str());
if (body.capacity() < length){body.reserve(length);}
}
if (GetHeader("Transfer-Encoding") == "chunked"){ if (GetHeader("Transfer-Encoding") == "chunked"){
getChunks = true; getChunks = true;
doingChunk = 0; doingChunk = 0;

View file

@ -36,7 +36,7 @@ namespace HTTP{
std::string &BuildRequest(); std::string &BuildRequest();
std::string &BuildResponse(); std::string &BuildResponse();
std::string &BuildResponse(std::string code, std::string message); std::string &BuildResponse(std::string code, std::string message);
void SendRequest(Socket::Connection &conn, const std::string &reqbody = ""); void SendRequest(Socket::Connection &conn, const std::string &reqbody = "", bool allAtOnce = false);
void SendResponse(std::string code, std::string message, Socket::Connection &conn); void SendResponse(std::string code, std::string message, Socket::Connection &conn);
void StartResponse(std::string code, std::string message, Parser &request, void StartResponse(std::string code, std::string message, Parser &request,
Socket::Connection &conn, bool bufferAllChunks = false); Socket::Connection &conn, bool bufferAllChunks = false);

View file

@ -341,6 +341,7 @@ namespace SDP{
} }
void State::parseSDP(const std::string &sdp){ void State::parseSDP(const std::string &sdp){
DONTEVEN_MSG("Parsing %llu-byte SDP", sdp.size());
std::stringstream ss(sdp); std::stringstream ss(sdp);
std::string to; std::string to;
uint64_t trackNo = 0; uint64_t trackNo = 0;
@ -349,6 +350,7 @@ namespace SDP{
while (std::getline(ss, to, '\n')){ while (std::getline(ss, to, '\n')){
if (!to.empty() && *to.rbegin() == '\r'){to.erase(to.size() - 1, 1);} if (!to.empty() && *to.rbegin() == '\r'){to.erase(to.size() - 1, 1);}
if (to.empty()){continue;} if (to.empty()){continue;}
DONTEVEN_MSG("Parsing SDP line: %s", to.c_str());
// All tracks start with a media line // All tracks start with a media line
if (to.substr(0, 2) == "m="){ if (to.substr(0, 2) == "m="){

View file

@ -98,7 +98,7 @@ namespace Mist{
sndH.SetHeader(it->first, it->second); sndH.SetHeader(it->first, it->second);
} }
} }
sndH.SendRequest(tcpCon); sndH.SendRequest(tcpCon, "", true);
} }
bool InputRTSP::checkArguments(){ bool InputRTSP::checkArguments(){
@ -129,6 +129,8 @@ namespace Mist{
void InputRTSP::parseStreamHeader(){ void InputRTSP::parseStreamHeader(){
std::map<std::string, std::string> extraHeaders; std::map<std::string, std::string> extraHeaders;
sendCommand("OPTIONS", url.getUrl(), "");
parsePacket();
extraHeaders["Accept"] = "application/sdp"; extraHeaders["Accept"] = "application/sdp";
sendCommand("DESCRIBE", url.getUrl(), "", &extraHeaders); sendCommand("DESCRIBE", url.getUrl(), "", &extraHeaders);
parsePacket(); parsePacket();
@ -215,7 +217,10 @@ namespace Mist{
if (recH.hasHeader("Content-Location")){ if (recH.hasHeader("Content-Location")){
url = HTTP::URL(recH.GetHeader("Content-Location")); url = HTTP::URL(recH.GetHeader("Content-Location"));
} }
if (recH.hasHeader("Content-Base")){url = HTTP::URL(recH.GetHeader("Content-Base"));} if (recH.hasHeader("Content-Base") && recH.GetHeader("Content-Base") != "" && recH.GetHeader("Content-Base") != url.getUrl()){
INFO_MSG("Changing base URL from %s to %s", url.getUrl().c_str(), recH.GetHeader("Content-Base").c_str());
url = HTTP::URL(recH.GetHeader("Content-Base"));
}
if (recH.hasHeader("Session")){ if (recH.hasHeader("Session")){
session = recH.GetHeader("Session"); session = recH.GetHeader("Session");
if (session.find(';') != std::string::npos){ if (session.find(';') != std::string::npos){
@ -224,12 +229,15 @@ namespace Mist{
} }
if (recH.hasHeader("Content-Type") && if (recH.hasHeader("Content-Type") &&
recH.GetHeader("Content-Type") == "application/sdp"){ recH.GetHeader("Content-Type") == "application/sdp"){
INFO_MSG("Received SDP");
seenSDP = true; seenSDP = true;
sdpState.parseSDP(recH.body); sdpState.parseSDP(recH.body);
recH.Clean(); recH.Clean();
INFO_MSG("SDP contained %llu tracks", myMeta.tracks.size());
return true; return true;
} }
if (recH.hasHeader("Transport")){ if (recH.hasHeader("Transport")){
INFO_MSG("Received setup response");
uint32_t trackNo = sdpState.parseSetup(recH, url.host, ""); uint32_t trackNo = sdpState.parseSetup(recH, url.host, "");
if (trackNo){ if (trackNo){
INFO_MSG("Parsed transport for track: %lu", trackNo); INFO_MSG("Parsed transport for track: %lu", trackNo);