Added crappy "HiIpcam" IP cam support
This commit is contained in:
parent
adf2d8f4f9
commit
0c6cd9bfc6
4 changed files with 65 additions and 16 deletions
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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="){
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue