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,
@ -226,70 +227,80 @@ static int ac_soapclient_send_http(struct ac_http_soap_request* httprequest, cha
return result; 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) { static int ac_soapclient_xml_io_read(void* ctx, char* buffer, int len) {
int result = -1; int result = -1;
char respbuffer[8192];
int respbufferlength = 0;
struct ac_http_soap_request* httprequest = (struct ac_http_soap_request*)ctx; struct ac_http_soap_request* httprequest = (struct ac_http_soap_request*)ctx;
if ((httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) || (httprequest->httpstate == HTTP_RESPONSE_HEADER)) { while ((httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) || (httprequest->httpstate == HTTP_RESPONSE_HEADER)) {
char respbuffer[8192]; /* Receive packet into temporaly buffer */
int respbufferlength = 0; 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 (;;) { /* Parse response code */
/* Receive packet into temporaly buffer */ temp = sscanf(respbuffer, "HTTP/1.1 %d %n", &httprequest->responsecode, &descpos);
if (capwap_socket_recv_timeout(httprequest->sock, &respbuffer[respbufferlength], 1, httprequest->responsetimeout) != 1) { if (temp != 1) {
httprequest->httpstate = HTTP_RESPONSE_ERROR; httprequest->httpstate = HTTP_RESPONSE_ERROR;
break; break;
} }
/* Update buffer size */ /* Parsing headers */
respbufferlength += 1; httprequest->httpstate = HTTP_RESPONSE_HEADER;
if (respbufferlength >= sizeof(respbuffer)) { } else if (httprequest->httpstate == HTTP_RESPONSE_HEADER) {
/* Buffer overflow */ char* value;
httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
}
/* Search line */ if (!respbufferlength) {
if ((respbufferlength > 1) && (respbuffer[respbufferlength - 2] == '\r') && (respbuffer[respbufferlength - 1] == '\n')) { if (httprequest->responsecode == HTTP_RESULT_CONTINUE) {
if (httprequest->httpstate == HTTP_RESPONSE_STATUS_CODE) { if (!httprequest->contentlength) {
int temp; httprequest->httpstate = HTTP_RESPONSE_STATUS_CODE;
int descpos; } else {
/* Parse response code */
respbuffer[respbufferlength - 2] = 0;
temp = sscanf(respbuffer, "HTTP/1.1 %d %n", &httprequest->responsecode, &descpos);
if ((temp != 1) || (httprequest->responsecode != 200)) {
httprequest->httpstate = HTTP_RESPONSE_ERROR; httprequest->httpstate = HTTP_RESPONSE_ERROR;
break;
} }
} else if (httprequest->contentxml && (httprequest->contentlength > 0)) {
/* Parsing headers */ httprequest->httpstate = HTTP_RESPONSE_BODY; /* Retrieve body */
respbufferlength = 0; } else {
httprequest->httpstate = HTTP_RESPONSE_HEADER; httprequest->httpstate = HTTP_RESPONSE_ERROR;
} else if (httprequest->httpstate == HTTP_RESPONSE_HEADER) { }
char* value; } else {
/* Separate key from value */
if (respbufferlength == 2) { value = strchr(respbuffer, ':');
if (httprequest->contentlength > 0) { if (!value) {
/* Retrieve body */ httprequest->httpstate = HTTP_RESPONSE_ERROR;
httprequest->httpstate = HTTP_RESPONSE_BODY; } else {
} 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;
}
/* */
*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;