Improved the code and managed the message HTTP 100 Continue

This commit is contained in:
vemax78 2013-07-25 22:17:55 +02:00
parent 79c7412004
commit 429fce5420
2 changed files with 72 additions and 58 deletions

View File

@ -185,7 +185,7 @@ static int ac_soapclient_send_http(struct ac_http_soap_request* httprequest, cha
strftime(datetime, 32, "%a, %d %b %Y %T %z", &stm);
/* Calculate header length */
headerlength = 128 + length + strlen(httprequest->server->path) + strlen(httprequest->server->host) + strlen(datetime) + strlen((soapaction ? soapaction : ""));
headerlength = 150 + length + strlen(httprequest->server->path) + strlen(httprequest->server->host) + strlen(datetime) + strlen((soapaction ? soapaction : ""));
buffer = capwap_alloc(headerlength);
if (!buffer) {
capwap_outofmemory();
@ -200,6 +200,7 @@ static int ac_soapclient_send_http(struct ac_http_soap_request* httprequest, cha
"Content-Type: text/xml\r\n"
"Connection: Close\r\n"
"SoapAction: %s\r\n"
"Expect: 100-continue\r\n"
"\r\n"
"%s",
httprequest->server->path,
@ -226,70 +227,80 @@ static int ac_soapclient_send_http(struct ac_http_soap_request* httprequest, cha
return result;
}
/* */
static int ac_soapclient_http_readline(struct ac_http_soap_request* httprequest, char* buffer, int length) {
int result = -1;
int bufferpos = 0;
for (;;) {
/* Receive packet into temporaly buffer */
if (capwap_socket_recv_timeout(httprequest->sock, &buffer[bufferpos], 1, httprequest->responsetimeout) != 1) {
break; /* Connection error */
}
/* Update buffer size */
bufferpos += 1;
if (bufferpos >= length) {
break; /* Buffer overflow */
}
/* Search line */
if ((bufferpos > 1) && (buffer[bufferpos - 2] == '\r') && (buffer[bufferpos - 1] == '\n')) {
result = bufferpos - 2;
buffer[result] = 0;
break;
}
}
return result;
}
/* */
static int ac_soapclient_xml_io_read(void* ctx, char* buffer, int len) {
int result = -1;
char respbuffer[8192];
int respbufferlength = 0;
struct ac_http_soap_request* httprequest = (struct ac_http_soap_request*)ctx;
if ((httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) || (httprequest->httpstate == HTTP_RESPONSE_HEADER)) {
char respbuffer[8192];
int respbufferlength = 0;
while ((httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) || (httprequest->httpstate == HTTP_RESPONSE_HEADER)) {
/* Receive packet into temporaly buffer */
respbufferlength = ac_soapclient_http_readline(httprequest, respbuffer, sizeof(respbuffer));
if (respbufferlength == -1) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
} else if (httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) {
int temp;
int descpos;
for (;;) {
/* Receive packet into temporaly buffer */
if (capwap_socket_recv_timeout(httprequest->sock, &respbuffer[respbufferlength], 1, httprequest->responsetimeout) != 1) {
/* Parse response code */
temp = sscanf(respbuffer, "HTTP/1.1 %d %n", &httprequest->responsecode, &descpos);
if (temp != 1) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
/* Update buffer size */
respbufferlength += 1;
if (respbufferlength >= sizeof(respbuffer)) {
/* Buffer overflow */
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
/* Parsing headers */
httprequest->httpstate = HTTP_RESPONSE_HEADER;
} else if (httprequest->httpstate == HTTP_RESPONSE_HEADER) {
char* value;
/* Search line */
if ((respbufferlength > 1) && (respbuffer[respbufferlength - 2] == '\r') && (respbuffer[respbufferlength - 1] == '\n')) {
if (httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) {
int temp;
int descpos;
/* Parse response code */
respbuffer[respbufferlength - 2] = 0;
temp = sscanf(respbuffer, "HTTP/1.1 %d %n", &httprequest->responsecode, &descpos);
if ((temp != 1) || (httprequest->responsecode != 200)) {
if (!respbufferlength) {
if (httprequest->responsecode == HTTP_RESULT_CONTINUE) {
if (!httprequest->contentlength) {
httprequest->httpstate = HTTP_RESPONSE_STATUS_CODE;
} else {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
/* Parsing headers */
respbufferlength = 0;
httprequest->httpstate = HTTP_RESPONSE_HEADER;
} else if (httprequest->httpstate == HTTP_RESPONSE_HEADER) {
char* value;
if (respbufferlength == 2) {
if (httprequest->contentlength > 0) {
/* Retrieve body */
httprequest->httpstate = HTTP_RESPONSE_BODY;
} else {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
}
break;
}
/* Separate key from value */
respbuffer[respbufferlength - 2] = 0;
value = strchr(respbuffer, ':');
if (!value) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
/* */
} else if (httprequest->contentxml && (httprequest->contentlength > 0)) {
httprequest->httpstate = HTTP_RESPONSE_BODY; /* Retrieve body */
} else {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
}
} else {
/* Separate key from value */
value = strchr(respbuffer, ':');
if (!value) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
} else {
*value = 0;
value++;
while (*value == ' ') {
@ -301,7 +312,6 @@ static int ac_soapclient_xml_io_read(void* ctx, char* buffer, int len) {
httprequest->contentlength = atoi(value);
if (!httprequest->contentlength) {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
} else if (!strcmp(respbuffer, "Content-Type")) {
char* param;
@ -312,14 +322,12 @@ static int ac_soapclient_xml_io_read(void* ctx, char* buffer, int len) {
*param = 0;
}
if (strcmp(value, "text/xml")) {
if (!strcmp(value, "text/xml")) {
httprequest->contentxml = 1;
} else {
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
}
/* Next header */
respbufferlength = 0;
}
}
}
@ -638,6 +646,7 @@ struct ac_soap_response* ac_soapclient_recv_response(struct ac_http_soap_request
}
/* Parsing response */
response->responsecode = httprequest->responsecode;
response->xmlRoot = xmlDocGetRootElement(response->xmlDocument);
if (!response->xmlRoot) {
ac_soapclient_free_response(response);

View File

@ -11,6 +11,9 @@
#define SOAP_HTTP_PORT 80
#define SOAP_HTTPS_PORT 443
#define HTTP_RESULT_CONTINUE 100
#define HTTP_RESULT_OK 200
#define SOAP_PROTOCOL_REQUEST_TIMEOUT 10000
#define SOAP_PROTOCOL_RESPONSE_TIMEOUT 10000
@ -46,10 +49,12 @@ struct ac_http_soap_request {
int httpstate;
int responsecode;
int contentlength;
int contentxml;
};
/* */
struct ac_soap_response {
int responsecode;
xmlDocPtr xmlDocument;
xmlNodePtr xmlRoot;
xmlNodePtr xmlBody;