281 lines
6.3 KiB
C++
281 lines
6.3 KiB
C++
/*
|
|
; Project: Open Vehicle Monitor System
|
|
; Date: 14th March 2017
|
|
;
|
|
; Changes:
|
|
; 1.0 Initial release
|
|
;
|
|
; (C) 2011 Michael Stegen / Stegen Electronics
|
|
; (C) 2011-2017 Mark Webb-Johnson
|
|
; (C) 2011 Sonny Chen @ EPRO/DX
|
|
;
|
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
; of this software and associated documentation files (the "Software"), to deal
|
|
; in the Software without restriction, including without limitation the rights
|
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
; copies of the Software, and to permit persons to whom the Software is
|
|
; furnished to do so, subject to the following conditions:
|
|
;
|
|
; The above copyright notice and this permission notice shall be included in
|
|
; all copies or substantial portions of the Software.
|
|
;
|
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
; THE SOFTWARE.
|
|
*/
|
|
|
|
#include "ovms_log.h"
|
|
static const char *TAG = "http";
|
|
|
|
#include "ovms_http.h"
|
|
#include "ovms_config.h"
|
|
#include "metrics_standard.h"
|
|
|
|
OvmsHttpClient::OvmsHttpClient()
|
|
{
|
|
m_buf = NULL;
|
|
m_bodysize = 0;
|
|
m_responsecode = 0;
|
|
}
|
|
|
|
OvmsHttpClient::OvmsHttpClient(std::string url, const char* method)
|
|
{
|
|
m_buf = NULL;
|
|
Request(url, method);
|
|
}
|
|
|
|
OvmsHttpClient::~OvmsHttpClient()
|
|
{
|
|
if (m_buf)
|
|
{
|
|
delete m_buf;
|
|
m_buf = NULL;
|
|
}
|
|
}
|
|
|
|
bool OvmsHttpClient::Request(std::string url, const char* method)
|
|
{
|
|
m_bodysize = 0;
|
|
m_responsecode = 0;
|
|
|
|
// First, split URL into server and path components
|
|
if (url.compare(0, 7, "http://", 7) == 0)
|
|
{
|
|
url = url.substr(7);
|
|
}
|
|
else if (url.compare(0, 8, "https://", 8) == 0)
|
|
{
|
|
url = url.substr(8);
|
|
}
|
|
std::string server;
|
|
std::string path;
|
|
std::string service;
|
|
size_t delim = url.find('/');
|
|
if (delim==std::string::npos)
|
|
{
|
|
server = url;
|
|
path = std::string("");
|
|
}
|
|
else
|
|
{
|
|
server = url.substr(0,delim);
|
|
path = url.substr(delim);
|
|
}
|
|
delim = server.find(':');
|
|
if (delim==std::string::npos)
|
|
{
|
|
service = std::string("80");
|
|
}
|
|
else
|
|
{
|
|
service = server.substr(delim+1);
|
|
server = server.substr(0,delim);
|
|
}
|
|
|
|
Connect(server.c_str(), service.c_str());
|
|
if (!IsOpen())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Now, we need to send the HTTP request...
|
|
// ESP_LOGI(TAG, "Server is %s, path is %s",server.c_str(),path.c_str());
|
|
std::string req(method);
|
|
req.append(" ");
|
|
req.append(path);
|
|
req.append(" HTTP/1.0\r\nHost: ");
|
|
req.append(server);
|
|
req.append("\r\nUser-Agent: ");
|
|
req.append(get_user_agent());
|
|
req.append("\r\n\r\n");
|
|
if (Write(req.c_str(), req.length()) < 0)
|
|
{
|
|
ESP_LOGE(TAG, "Unable to write to server connection");
|
|
Disconnect();
|
|
return false;
|
|
}
|
|
|
|
m_buf = new OvmsBuffer(1024);
|
|
bool inheaders = true;
|
|
// ESP_LOGI(TAG,"Reading headers...");
|
|
while((inheaders)&&(m_buf->PollSocket(m_sock, 10000) >= 0))
|
|
{
|
|
// ESP_LOGI(TAG, "Now buffered %d bytes",m_buf->UsedSpace());
|
|
int k = m_buf->HasLine();
|
|
while ((inheaders)&&(k >= 0))
|
|
{
|
|
if (k == 0)
|
|
{
|
|
inheaders = 0;
|
|
}
|
|
else
|
|
{
|
|
// ESP_LOGI(TAG, "Got response %s",m_buf->ReadLine().c_str());
|
|
std::string header = m_buf->ReadLine();
|
|
if (strncasecmp(header.c_str(), "Content-Length:", 15) == 0)
|
|
{
|
|
m_bodysize = atoi(header.substr(15).c_str());
|
|
}
|
|
if (header.compare(0,5,"HTTP/") == 0)
|
|
{
|
|
size_t space = header.find(' ');
|
|
if (space!=std::string::npos)
|
|
{
|
|
m_responsecode = atoi(header.substr(space+1).c_str());
|
|
}
|
|
}
|
|
k = m_buf->HasLine();
|
|
}
|
|
}
|
|
}
|
|
if (inheaders)
|
|
{
|
|
ESP_LOGE(TAG, "Error: Premature end of server response");
|
|
Disconnect();
|
|
return false;
|
|
}
|
|
|
|
// Process the separator line
|
|
// m_buf->Diagnostics();
|
|
m_buf->ReadLine(); // Discard the empty header/body line
|
|
|
|
return true;
|
|
}
|
|
|
|
void OvmsHttpClient::Disconnect()
|
|
{
|
|
if (m_buf != NULL)
|
|
{
|
|
delete m_buf;
|
|
m_buf = NULL;
|
|
}
|
|
OvmsNetTcpConnection::Disconnect();
|
|
}
|
|
|
|
size_t OvmsHttpClient::BodyRead(void *buf, size_t nbyte)
|
|
{
|
|
// char *x = (char*)buf;
|
|
if ((m_buf == NULL)||(m_buf->UsedSpace() == 0))
|
|
{
|
|
size_t n = Read(buf,nbyte);
|
|
// ESP_EARLY_LOGI(TAG, "BodyRead got %d bytes direct (%02x %02x %02x %02x)",n,x[0],x[1],x[2],x[3]);
|
|
return n;
|
|
}
|
|
else
|
|
{
|
|
size_t n = m_buf->Pop(nbyte,(uint8_t*)buf);
|
|
// ESP_EARLY_LOGI(TAG, "Body Read got %d bytes from buf (%d left) (%02x %02x %02x %02x)",n,m_buf->UsedSpace(),x[0],x[1],x[2],x[3]);
|
|
if (m_buf->UsedSpace() == 0)
|
|
{
|
|
delete m_buf;
|
|
m_buf = NULL;
|
|
}
|
|
return n;
|
|
}
|
|
}
|
|
|
|
int OvmsHttpClient::BodyHasLine()
|
|
{
|
|
if (m_buf == NULL)
|
|
return -1;
|
|
|
|
if (m_buf->HasLine()<0)
|
|
{
|
|
m_buf->PollSocket(m_sock, 10000);
|
|
// m_buf->Diagnostics();
|
|
}
|
|
return m_buf->HasLine();
|
|
}
|
|
|
|
std::string OvmsHttpClient::BodyReadLine()
|
|
{
|
|
if (m_buf == NULL)
|
|
return std::string("");
|
|
|
|
if (m_buf->HasLine()<0)
|
|
{
|
|
m_buf->PollSocket(m_sock, 10000);
|
|
// m_buf->Diagnostics();
|
|
}
|
|
|
|
return m_buf->ReadLine();
|
|
}
|
|
|
|
size_t OvmsHttpClient::BodySize()
|
|
{
|
|
return m_bodysize;
|
|
}
|
|
|
|
int OvmsHttpClient::ResponseCode()
|
|
{
|
|
return m_responsecode;
|
|
}
|
|
|
|
std::string OvmsHttpClient::GetBodyAsString()
|
|
{
|
|
std::string body;
|
|
|
|
if (!IsOpen())
|
|
{
|
|
ESP_LOGE(TAG, "http request failed");
|
|
return body;
|
|
}
|
|
|
|
size_t expected = BodySize();
|
|
body.reserve(expected);
|
|
|
|
uint8_t rbuf[512];
|
|
size_t filesize = 0;
|
|
while (int k = BodyRead(rbuf,512))
|
|
{
|
|
filesize += k;
|
|
body.append((const char*)rbuf,k);
|
|
}
|
|
Disconnect();
|
|
|
|
if (filesize != expected)
|
|
{
|
|
ESP_LOGE(TAG, "Download file size (%d) does not match expected (%d)", filesize, expected);
|
|
body.empty();
|
|
}
|
|
|
|
Disconnect();
|
|
|
|
return body;
|
|
}
|
|
|
|
void OvmsHttpClient::Reset()
|
|
{
|
|
if (m_buf)
|
|
{
|
|
delete m_buf;
|
|
m_buf = NULL;
|
|
}
|
|
m_bodysize = 0;
|
|
m_responsecode = 0;
|
|
}
|