*** empty log message ***

svn path=/trunk/boinc/; revision=2166
This commit is contained in:
Karl Chen 2003-08-22 00:15:51 +00:00
parent 3e26f05319
commit 47c59c55a4
4 changed files with 115 additions and 63 deletions

View File

@ -5871,6 +5871,7 @@ Chrisz 2003/08/20
Karl 2003/08/20
- rewrote header parsing to be more robust:
- allow for header to not have to be a single TCP message
- parse line-by-line instead of full-header strstr for efficiency
- compare header names case insensitively
- test scripts

View File

@ -19,8 +19,6 @@
#include "windows_cpp.h"
#include <string.h>
#ifdef _WIN32
#include "winsock.h"
#endif
@ -41,11 +39,15 @@
#include "http.h"
#include <cstring>
#include <sstream>
#include <algorithm>
#define HTTP_BLOCKSIZE 16384
// Breaks a HTTP url down into its server and file path components
//
void parse_url(char* url, char* host, int &port, char* file) {
void parse_url(const char* url, char* host, int &port, char* file) {
char* p;
char buf[256];
@ -124,46 +126,85 @@ static void http_post_request_header(
);
}
// Parse an http reply header into the header struct
//
int read_http_reply_header(int socket, HTTP_REPLY_HEADER& header) {
int i, n;
char buf[1024], *p;
void HTTP_REPLY_HEADER::init()
{
status = 500;
content_length = 0;
redirect_location.erase();
recv_buf.erase();
}
void HTTP_REPLY_HEADER::parse()
{
ScopeMessages scope_messages(log_messages, ClientMessages::DEBUG_HTTP);
memset(buf, 0, sizeof(buf));
header.content_length = 0;
header.status = 404; // default to failure
for (i=0; i<1024; i++) {
n = recv(socket, buf+i, 1, 0);
if (strstr(buf, "\r\n\r\n") || strstr(buf, "\n\n")) {
// scope_messages.printf("read_http_reply_header(): reply header on socket %d:\n", socket);
scope_messages.printf_multiline(buf, "read_http_reply_header(): header: ");
p = strchr(buf, ' ');
if (p) {
header.status = atoi(p+1);
}
p = strstr(buf, "Content-Length: ");
if (p) {
header.content_length = atoi(p+strlen("Content-Length: "));
}
p = strstr(buf, "Location: ");
if (p) {
// TODO: Is there a better way to do this?
n = 0;
p += strlen( "Location: " );
istringstream h(recv_buf);
string line, w;
while (p[n] != '\n' && p[n] != '\r') {
header.redirect_location[n] = p[n];
n++;
}
header.redirect_location[n] = 0;
}
if (getline(h, line)) {
istringstream iline(line);
iline >> w;
if (!starts_with(w,"HTTP/")) {
scope_messages.printf("HTTP_REPLY_HEADER::parse(): not HTTP\n");
return;
}
iline >> status;
scope_messages.printf("HTTP_REPLY_HEADER::parse(): status=%d\n", status);
}
while (getline(h, line)) {
istringstream iline(line);
iline >> w;
downcase_string(w);
if (w == "content-length:") {
iline >> content_length;
scope_messages.printf("HTTP_REPLY_HEADER::parse(): content_length=%d\n", content_length);
} else if (w == "location:") {
iline >> redirect_location;
scope_messages.printf("HTTP_REPLY_HEADER::parse(): redirect_location=%s\n", redirect_location.c_str());
}
}
}
const unsigned int MAX_HEADER_SIZE = 1024;
// Parse an http reply header into the header struct
//
// Returns 1 if we are not done yet, 0 if done (header.status indicates
// success)
int HTTP_REPLY_HEADER::read_reply(int socket)
{
ScopeMessages scope_messages(log_messages, ClientMessages::DEBUG_HTTP);
while (recv_buf.size() < MAX_HEADER_SIZE) {
char c;
int n = recv(socket, &c, 1, 0);
if (n == -1 && errno == EAGAIN) {
scope_messages.printf("HTTP_REPLY_HEADER::read_reply(): recv() returned %d (EAGAIN)\n", n);
return 1;
}
if (n != 1) {
scope_messages.printf("HTTP_REPLY_HEADER::read_reply(): recv() returned %d\n", n);
break;
}
if (c == '\r') continue;
recv_buf += c;
if (ends_with(recv_buf, "\n\n")) {
scope_messages.printf_multiline(recv_buf.c_str(),
"HTTP_REPLY_HEADER::read_reply(): header: ");
parse();
return 0;
}
}
return 1;
// error occurred
scope_messages.printf("HTTP_REPLY_HEADER::read_reply(): returning error (recv_buf.size=%d)\n",
recv_buf.size());
return 0;
}
// Read the contents of the socket into buf
@ -200,7 +241,7 @@ HTTP_OP::~HTTP_OP() {
// Initialize HTTP HEAD operation
//
int HTTP_OP::init_head(char* url) {
int HTTP_OP::init_head(const char* url) {
char proxy_buf[256];
parse_url(url, hostname, port, filename);
NET_XFER::init(use_http_proxy?proxy_server_name:hostname, use_http_proxy?proxy_server_port:port, HTTP_BLOCKSIZE);
@ -217,7 +258,7 @@ int HTTP_OP::init_head(char* url) {
// Initialize HTTP GET operation
//
int HTTP_OP::init_get(char* url, char* out, bool del_old_file, double off) {
int HTTP_OP::init_get(const char* url, char* out, bool del_old_file, double off) {
char proxy_buf[256];
if (del_old_file) {
@ -243,7 +284,7 @@ int HTTP_OP::init_get(char* url, char* out, bool del_old_file, double off) {
// Initialize HTTP POST operation
//
int HTTP_OP::init_post(char* url, char* in, char* out) {
int HTTP_OP::init_post(const char* url, char* in, char* out) {
int retval;
double size;
char proxy_buf[256];
@ -274,7 +315,7 @@ int HTTP_OP::init_post(char* url, char* in, char* out) {
// Initialize HTTP POST operation
//
int HTTP_OP::init_post2(
char* url, char* r1, char* in, double offset
const char* url, char* r1, char* in, double offset
) {
int retval;
double size;
@ -379,6 +420,7 @@ bool HTTP_OP_SET::poll() {
break;
case HTTP_OP_GET:
case HTTP_OP_HEAD:
htp->hrh.init();
htp->http_op_state = HTTP_STATE_REPLY_HEADER;
htp->want_upload = false;
htp->want_download = true;
@ -417,6 +459,7 @@ bool HTTP_OP_SET::poll() {
if (htp->io_done) {
action = true;
scope_messages.printf("HTTP_OP_SET::poll(): finished sending request body\n");
htp->hrh.init();
htp->http_op_state = HTTP_STATE_REPLY_HEADER;
if (htp->file) {
fclose(htp->file);
@ -433,7 +476,10 @@ bool HTTP_OP_SET::poll() {
if (htp->io_ready) {
action = true;
scope_messages.printf("HTTP_OP_SET::poll(): got reply header; %p io_done %d\n", htp, htp->io_done);
read_http_reply_header(htp->socket, htp->hrh);
if (htp->hrh.read_reply(htp->socket)) {
// not done yet
break;
}
// TODO: handle all kinds of redirects here
@ -441,16 +487,16 @@ bool HTTP_OP_SET::poll() {
htp->close_socket();
switch (htp->http_op_type) {
case HTTP_OP_HEAD:
htp->init_head(htp->hrh.redirect_location);
htp->init_head(htp->hrh.redirect_location.c_str());
break;
case HTTP_OP_GET:
htp->init_get(htp->hrh.redirect_location, htp->outfile, false);
htp->init_get(htp->hrh.redirect_location.c_str(), htp->outfile, false);
break;
case HTTP_OP_POST:
htp->init_post(htp->hrh.redirect_location, htp->infile, htp->outfile);
htp->init_post(htp->hrh.redirect_location.c_str(), htp->infile, htp->outfile);
break;
case HTTP_OP_POST2:
htp->init_post2(htp->hrh.redirect_location, htp->req1, htp->infile, htp->file_offset);
htp->init_post2(htp->hrh.redirect_location.c_str(), htp->req1, htp->infile, htp->file_offset);
break;
}

View File

@ -2,18 +2,18 @@
// Version 1.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://boinc.berkeley.edu/license_1.0.txt
//
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is the Berkeley Open Infrastructure for Network Computing.
//
// under the License.
//
// The Original Code is the Berkeley Open Infrastructure for Network Computing.
//
// The Initial Developer of the Original Code is the SETI@home project.
// Portions created by the SETI@home project are Copyright (C) 2002
// University of California at Berkeley. All Rights Reserved.
//
// University of California at Berkeley. All Rights Reserved.
//
// Contributor(s):
//
@ -35,7 +35,12 @@
struct HTTP_REPLY_HEADER {
int status;
int content_length;
char redirect_location[256];
string redirect_location;
string recv_buf;
void init();
int read_reply(int socket);
void parse();
};
#define HTTP_OP_NONE 0
@ -70,11 +75,11 @@ public:
int proxy_server_port;
char proxy_server_name[256];
int init_head(char* url);
int init_get(char* url, char* outfile, bool del_old_file, double offset=0);
int init_post(char* url, char* infile, char* outfile);
int init_head(const char* url);
int init_get(const char* url, char* outfile, bool del_old_file, double offset=0);
int init_post(const char* url, char* infile, char* outfile);
int init_post2(
char* url, char* req1, char* infile, double offset
const char* url, char* req1, char* infile, double offset
);
bool http_op_done();
};
@ -101,7 +106,6 @@ public:
#define HTTP_STATE_REPLY_BODY 6
#define HTTP_STATE_DONE 7
extern int read_http_reply_header(int socket, HTTP_REPLY_HEADER&);
extern void parse_url(char* url, char* host, int &port, char* file);
extern void parse_url(const char* url, char* host, int &port, char* file);
#endif

View File

@ -30,10 +30,11 @@ class WorkUC(Work):
class ResultUC(Result):
def __init__(self):
self.stderr_out = MATCH_REGEXPS([ """<stderr_txt>
APP: upper_case: starting, argc \\d+
APP: upper_case: argv[[]0[]] is upper_case
APP: upper_case ending, wrote \\d+ chars"""])
self.stderr_out = MATCH_REGEXPS([
"<stderr_txt>\n" +
"APP: upper_case: starting, argc \\d+\n" +
"APP: upper_case: argv[[]0[]] is upper_case",
"APP: upper_case ending, wrote \\d+ chars"])
class ResultComputeErrorUC(ResultComputeError):
def __init__(self):