From 429fce54204bb3faddb4043551ddbf6262f9eaa9 Mon Sep 17 00:00:00 2001 From: vemax78 Date: Thu, 25 Jul 2013 22:17:55 +0200 Subject: [PATCH] Improved the code and managed the message HTTP 100 Continue --- src/ac/ac_soap.c | 125 +++++++++++++++++++++++++---------------------- src/ac/ac_soap.h | 5 ++ 2 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/ac/ac_soap.c b/src/ac/ac_soap.c index a9df576..8ce73aa 100644 --- a/src/ac/ac_soap.c +++ b/src/ac/ac_soap.c @@ -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); diff --git a/src/ac/ac_soap.h b/src/ac/ac_soap.h index c641142..1b5360f 100644 --- a/src/ac/ac_soap.h +++ b/src/ac/ac_soap.h @@ -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;