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

View File

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