improvements to http

This commit is contained in:
darkrose 2013-12-28 22:46:23 +10:00
parent d07aed423d
commit 1c5079daa7
4 changed files with 194 additions and 324 deletions

View File

@ -175,34 +175,12 @@ HTTPRemoteClient::~HTTPRemoteClient()
/* receive and handle data from a remote http client */
int HTTPRemoteClient::receive()
{
int r = fillBuffer();
if (!r)
return 0;
if (r<1)
return 1;
m_recv_headers.clear();
m_send_headers.clear();
int h = m_recv_headers.read(m_buff,r);
if (h == -1) {
int h = m_recv_headers.read(m_socket);
if (h == -1)
return 1;
}else if (h == -2) {
if (m_recv_headers.getUrl() == "")
return 1;
while (m_socket->WaitData(1000)) {
r = fillBuffer();
if (r<1)
return 1;
h = m_recv_headers.read(m_buff,r);
if (h > -1)
break;
if (h == -1)
return 1;
}
if (h < 0)
return 1;
}
if (m_recv_headers.getCookie() != "" && m_recv_headers.getHeader("User") != "") {
if (m_recv_headers.getCookie() == m_server->getPlayerCookie(m_recv_headers.getHeader("User"))) {
@ -222,56 +200,6 @@ int HTTPRemoteClient::receive()
return handleSpecial("404 Not Found");
}
/* read data from a remote http client */
int HTTPRemoteClient::read(char* buff, int size)
{
if (size > 2048) {
int r = 0;
int l;
int c = 2048;
int s = size;
while (fillBuffer()) {
c = 2048;
if (s<c)
c = s;
l = m_end-m_start;
if (l<c)
c = l;
if (c < 1)
break;
memcpy(buff+r,m_buff+m_start,c);
m_start += c;
r += c;
s -= c;
}
return r;
}
if (fillBuffer() < size)
return 0;
memcpy(buff,m_buff+m_start,size);
m_start+=size;
return size;
}
/* data read from remote http clients is buffered, fill the buffer */
int HTTPRemoteClient::fillBuffer()
{
int l = m_end-m_start;
if (l && m_start) {
memcpy(m_buff,m_buff+m_start,l);
m_start = 0;
m_end = l;
}
l = 2048-m_end;
if (!m_socket->WaitData(30))
return m_end;
return m_end+m_socket->Receive(m_buff+m_end,l);
}
/* handle /player/<name> url's */
int HTTPRemoteClient::handlePlayer()
{
@ -348,8 +276,7 @@ int HTTPRemoteClient::handlePlayer()
if (c > s)
c = s;
if (c) {
if (m_start == m_end)
m_socket->WaitData(60000);
//m_socket->WaitData(60000);
while ((l = read(buff,c)) > 0) {
s -= l;
t += l;
@ -733,34 +660,9 @@ void HTTPClient::step()
int r = 0;
int h = -1;
m_start = 0;
m_end = 0;
m_recv_headers.setResponse(0);
while (m_socket->WaitData(1000)) {
r = fillBuffer();
if (r<1) {
h = -1;
break;
}
h = m_recv_headers.read(m_buff,r);
if (h > -1)
break;
if (h == -1 || m_recv_headers.getResponse() == 500) {
#ifdef _WIN32
Sleep(1000);
#else
sleep(1);
#endif
r = 0;
h = -1;
break;
}
if (h == -2) {
m_start = 0;
m_end = 0;
}
}
if (h < 0) {
h = m_recv_headers.read(m_socket);
if (h == -1 || m_recv_headers.getResponse() == 500) {
delete m_socket;
m_req_mutex.Lock();
m_requests.push_back(q);
@ -768,8 +670,6 @@ void HTTPClient::step()
continue;
}
m_start += h;
r = m_recv_headers.getResponse();
if (q.post == "") {
@ -815,14 +715,7 @@ void HTTPClient::step()
if (c > s)
c = s;
if (c) {
if (m_start == m_end) {
m_socket->WaitData(60000);
#ifdef _WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
m_socket->WaitData(60000);
while ((l = read(buff,c)) > 0) {
s -= l;
c = fwrite(buff,1,l,f);
@ -997,57 +890,6 @@ bool HTTPClient::put(std::string &url, std::string &file)
return true;
}
/* read data from a remote http client */
int HTTPClient::read(char* buff, int size)
{
if (size > 2048) {
int r = 0;
int l;
int c = 2048;
int s = size;
while (fillBuffer()) {
c = 2048;
if (s<c)
c = s;
l = m_end-m_start;
if (l<c)
c = l;
if (c < 1)
break;
memcpy(buff+r,m_buff+m_start,c);
m_start += c;
r += c;
s -= c;
}
return r;
}
if (fillBuffer() < size)
return 0;
memcpy(buff,m_buff+m_start,size);
m_start+=size;
return size;
}
/* data read from remote http clients is buffered, fill the buffer */
int HTTPClient::fillBuffer()
{
int l = m_end-m_start;
if (l && m_start) {
memcpy(m_buff,m_buff+m_start,l);
m_start = 0;
m_end = l;
}
l = 2048-m_end;
if (!m_socket->WaitData(30))
return m_end;
m_end += m_socket->Receive(m_buff+m_end,l);
return m_end;
}
/* send http headers to the server */
void HTTPClient::sendHeaders()
{
@ -1083,131 +925,119 @@ void HTTPClient::sendHeaders()
*/
/* read in headers */
int HTTPRequestHeaders::read(char* buff, int length)
int HTTPRequestHeaders::read(TCPSocket *sock)
{
char nbuff[1024];
char vbuff[1024];
int n = 1;
int o = 0;
char lbuff[2048];
char* n;
char* v;
int i = 0;
int c = getUrl() == "" ? 0 : 1;
for (i=0; i<length; i++) {
if (buff[i] == '\r' || (!o && buff[i] == ' '))
continue;
if (buff[i] == '\n') {
if (!c) {
nbuff[o] = 0;
char* u = strchr(nbuff,' ');
if (!u)
return -1;
*u = 0;
setMethod(nbuff);
u++;
while (*u == ' ') {
u++;
}
char* p = strchr(u,' ');
if (!p)
return -1;
*p = 0;
p++;
while (*p == ' ') {
p++;
}
setUrl(u);
size_t current;
size_t next = -1;
std::string s(u);
do{
current = next + 1;
next = s.find_first_of("/", current);
if (s.substr(current, next-current) != "")
addUrl(s.substr(current, next-current));
} while (next != std::string::npos);
c++;
}else{
if (n)
return i+1;
vbuff[o] = 0;
if (!strcmp(nbuff,"Content-Length")) {
setLength(strtoul(vbuff,NULL,10));
}else if (!strcmp(nbuff,"Cookie") && !strncmp(vbuff,"MTID=",5)) {
setCookie(vbuff+5);
}else{
setHeader(nbuff,vbuff);
}
}
o = 0;
n = 1;
}else if (n && buff[i] == ':') {
nbuff[o] = 0;
o = 0;
n = 0;
}else if (n) {
nbuff[o++] = buff[i];
i = sock->ReceiveLine(lbuff,2048);
if (!i)
return -1;
n = lbuff;
lbuff[i] = 0;
printf("%s\n",n);
{
v = strchr(n,' ');
if (!v)
return -1;
*v = 0;
setMethod(n);
v++;
while (*v == ' ') {
v++;
}
n = v;
}
{
v = strchr(n,' ');
if (!v)
return -1;
*v = 0;
setUrl(n);
size_t current;
size_t next = -1;
std::string s(n);
do{
current = next + 1;
next = s.find_first_of("/", current);
if (s.substr(current, next-current) != "")
addUrl(s.substr(current, next-current));
} while (next != std::string::npos);
}
while ((i = sock->ReceiveLine(lbuff,2048))) {
n = lbuff;
v = strchr(lbuff,':');
if (!v)
return -1;
*v = 0;
v++;
while (*v && *v == ' ') {
v++;
}
if (!strcmp(n,"Content-Length")) {
setLength(strtoul(v,NULL,10));
}else if (!strcmp(n,"Cookie") && !strncmp(v,"MTID=",5)) {
setCookie(v+5);
}else{
vbuff[o++] = buff[i];
setHeader(n,v);
}
}
return -2;
return 0;
}
/* read in headers */
int HTTPResponseHeaders::read(char* buff, int length)
int HTTPResponseHeaders::read(TCPSocket *sock)
{
char nbuff[1024];
char vbuff[1024];
int n = 1;
int o = 0;
char lbuff[2048];
char* n;
char* v;
int i = 0;
int c = getResponse();
for (i=0; i<length; i++) {
if (buff[i] == '\r' || (!o && buff[i] == ' '))
continue;
if (buff[i] == '\n') {
if (!c) {
nbuff[o] = 0;
char* r = strchr(nbuff,' ');
if (!r)
return -1;
*r = 0;
r++;
while (*r == ' ') {
r++;
}
char* s = strchr(r,' ');
if (!s)
return -1;
*s = 0;
setResponse(strtol(r,NULL,10));
c++;
}else{
if (n)
return i+1;
vbuff[o] = 0;
if (!strcmp(nbuff,"Content-Length")) {
setLength(strtoul(vbuff,NULL,10));
}else if (!strcmp(nbuff,"SetCookie") && !strncmp(vbuff,"MTID=",5)) {
setCookie(vbuff+5);
}else{
setHeader(nbuff,vbuff);
}
}
o = 0;
n = 1;
}else if (n && buff[i] == ':') {
nbuff[o] = 0;
o = 0;
n = 0;
}else if (n) {
nbuff[o++] = buff[i];
i = sock->ReceiveLine(lbuff,2048);
if (!i)
return -1;
n = lbuff;
lbuff[i] = 0;
printf("%s\n",n);
{
v = strchr(n,' ');
if (!v)
return -1;
while (*v == ' ') {
v++;
}
n = v;
}
{
v = strchr(n,' ');
if (!v)
return -1;
*v = 0;
setResponse(strtol(n,NULL,10));
}
while ((i = sock->ReceiveLine(lbuff,2048))) {
n = lbuff;
v = strchr(n,':');
if (!v)
return -1;
*v = 0;
v++;
while (*v && *v == ' ') {
v++;
}
if (!strcmp(n,"Content-Length")) {
setLength(strtoul(v,NULL,10));
}else if (!strcmp(n,"SetCookie") && !strncmp(v,"MTID=",5)) {
setCookie(v+5);
}else{
vbuff[o++] = buff[i];
setHeader(n,v);
}
}
return -2;
return 0;
}

View File

@ -62,7 +62,7 @@ public:
m_url = std::string("");
m_url_split.clear();
}
virtual int read(char* buff, int length) = 0;
virtual int read(TCPSocket *sock) = 0;
u32 length() {return m_contentLength;}
std::string getCookie() {return m_cookie;}
std::string getUrl() {return m_url;}
@ -89,14 +89,14 @@ private:
class HTTPRequestHeaders : public HTTPHeaders
{
public:
virtual int read(char* buff, int length);
virtual int read(TCPSocket *sock);
private:
};
class HTTPResponseHeaders : public HTTPHeaders
{
public:
virtual int read(char* buff, int length);
virtual int read(TCPSocket *sock);
void setResponse(int r) {m_response = r;}
int getResponse() {return m_response;}
private:
@ -112,14 +112,12 @@ public:
{
m_socket = sock;
m_server = server;
m_start = 0;
m_end = 0;
}
~HTTPRemoteClient();
int receive();
private:
int read(char* buff, int size);
int fillBuffer();
int read(char* buff, int size) {return m_socket->Receive(buff,size);}
int readline(char* buff, int size) {return m_socket->ReceiveLine(buff,size);}
void sendHeaders();
int handlePlayer();
@ -137,9 +135,6 @@ private:
void sendFile(std::string &file);
void setResponse(const char* response) {std::string r(response); m_response = r;}
char m_buff[2048];
int m_start;
int m_end;
HTTPRequestHeaders m_recv_headers;
HTTPResponseHeaders m_send_headers;
std::string m_response;
@ -239,13 +234,10 @@ private:
bool get(std::string &url);
bool post(std::string &url, char* data);
bool put(std::string &url, std::string &file);
int read(char* buff, int size);
int fillBuffer();
int read(char* buff, int size) {return m_socket->Receive(buff,size);}
int readline(char* buff, int size) {return m_socket->ReceiveLine(buff,size);}
void sendHeaders();
char m_buff[2048];
int m_start;
int m_end;
Address m_address;
TCPSocket *m_socket;
HTTPResponseHeaders m_recv_headers;

View File

@ -352,6 +352,8 @@ TCPSocket::TCPSocket()
throw SocketException("Sockets not initialized");
m_handle = socket(AF_INET, SOCK_STREAM, 0);
m_bstart = 0;
m_bend = 0;
if (DP)
dstream<<DPS<<"TCPSocket("<<(int)m_handle<<")::TCPSocket()"<<std::endl;
@ -438,46 +440,86 @@ void TCPSocket::Send(const void *data, int size)
throw SendFailedException("Failed to send data");
}
/* data read from remote http clients is buffered, fill the buffer */
int TCPSocket::FillBuffer()
{
int r;
int l = m_bend-m_bstart;
if (!m_bstart && l == 2048)
return l;
if (l && m_bstart)
memcpy(m_buff,m_buff+m_bstart,l);
m_bstart = 0;
m_bend = l;
if (!WaitData(1000))
return m_bend;
r = (int)recv(m_handle,m_buff+l,2048-l,0);
if (r<0)
return m_bend;
m_bend = l+r;
return m_bend;
}
int TCPSocket::Receive(void *data, int size)
{
if (WaitData(m_timeout_ms) == false)
return -1;
sockaddr_in address;
socklen_t address_len = sizeof(address);
int received = recvfrom(
m_handle,
(char*)data,
size,
0,
(sockaddr*)&address,
&address_len
);
if (received < 0)
return -1;
unsigned int address_ip = ntohl(address.sin_addr.s_addr);
unsigned int address_port = ntohs(address.sin_port);
Address sender(address_ip, address_port);
if (DP) {
dstream<<DPS<<(int)m_handle<<" <- ";
dstream<<", size="<<received<<", data=";
for (int i=0; i<received && i<20; i++) {
if (i%2==0)
DEBUGPRINT(" ");
unsigned int a = ((const unsigned char*)data)[i];
DEBUGPRINT("%.2X", a);
if (size > 2048) {
unsigned char* buff = (unsigned char*)data;
int r = 0;
int l;
int c = 2048;
int s = size;
while (FillBuffer()) {
c = 2048;
if (s<c)
c = s;
l = m_bend-m_bstart;
if (l<c)
c = l;
if (c < 1)
break;
memcpy(buff+r,m_buff+m_bstart,c);
m_bstart += c;
r += c;
s -= c;
}
if (received>20)
dstream<<"...";
dstream<<std::endl;
return r;
}
return received;
if (FillBuffer() < size)
return 0;
memcpy(data,m_buff+m_bstart,size);
m_bstart+=size;
return size;
}
int TCPSocket::ReceiveLine(char* data, int size)
{
int i = 0;
for (; i<size; i++) {
if (m_bstart >= m_bend)
FillBuffer();
if (m_bstart >= m_bend)
break;
data[i] = m_buff[m_bstart++];
if (data[i] == '\r') {
i--;
}else if (data[i] == '\n') {
data[i] = 0;
break;
}else if (i > size-2) {
data[i+1] = 0;
break;
}
}
return i;
}
TCPSocket* TCPSocket::Accept()

View File

@ -133,14 +133,20 @@ public:
void Send(const void *data, int size);
// Returns -1 if there is no data
int Receive(void *data, int size);
int ReceiveLine(char* data, int size);
TCPSocket* Accept();
int GetHandle(); // For debugging purposes only
void setTimeoutMs(int timeout_ms);
// Returns true if there is data, false if timeout occurred
bool WaitData(int timeout_ms);
private:
int FillBuffer();
int m_handle;
int m_timeout_ms;
char m_buff[2048];
int m_bstart;
int m_bend;
};
#endif