Разбор кода gSOAP для отправки запроса к веб-сервису

Для удобства сразу включим режим отладки:


Например, есть Proxy класс (тот в который включается #include "soapH.h").
Через экземпляр этого класса выполняется запрос к веб-сервису. Объявление метода для выполнения запроса выглядит в заголовочном файле примерно так:

virtual int myOperation(ns__myRequest  *ns__myRequest_
                      , ns__myResponse *ns__myResponse_) {
 return this->myOperation(NULL
                        , NULL
                        , ns__myRequest_
                        , ns__myResponse_);
}


Как видно этот метод является оберткой для другого метода, объявление которого в том же заголовочном файле выглядит следующим образом:

virtual int myOperation(const char *endpoint
                      , const char *soap_action
                      , ns__myRequest  *ns__myRequest_
                      , ns__myResponse *ns__myResponse_);

Далее рассмотрим уже определение этого метода в .cpp файле Proxy класса. Начальная часть метода:

int Proxy::myOperation(const char *endpoint
                     , const char *soap_action
                     , ns__myRequest  *ns__myRequest_
                     , ns__myResponse *ns__myResponse_)
{   struct soap *soap = this->soap; // [1]
    struct __ns__myOperation soap_tmp___ns__myOperation; // [2]
    if (endpoint) // [3]
        soap_endpoint = endpoint;
    if (soap_endpoint == NULL)
        soap_endpoint = "http://example.com:8080/web/service/";
    if (soap_action == NULL)
        soap_action = ""; // [8]
    soap_begin(soap); // [9]
    soap->encodingStyle = NULL;
    soap_tmp___ns__myOperation.ns__myRequest_ = ns__myRequest_; // [11]
    soap_serializeheader(soap); [12]
    soap_serialize___ns__myOperation(soap, &soap_tmp___ns__myOperation); // [13]
    if (soap_begin_count(soap)) // [14]
        return soap->error;
    if (soap->mode & SOAP_IO_LENGTH)
    {   if (soap_envelope_begin_out(soap)
         || soap_putheader(soap)
         || soap_body_begin_out(soap)
         || soap_put___ns__myOperation(soap, &soap_tmp___ns__myOperation, "-ns:myOperation", NULL)
         || soap_body_end_out(soap)
         || soap_envelope_end_out(soap))
             return soap->error;
    }

[1] Указатель на структуру типа soap, это структура является основной, далее большинство методов будут работать именно с ней.

[2] Создается экземпляр структуры __ns__myOperation, которая просто содержит в себе один указатель на ns__myRequest_ и всё. Назначение указателю происходит на [11].

[3-8] Инициализация точки назначения запросов soap_endpoint и переменной soap_action. Обратите внимание, что значения для этих переменных берутся из аргументов функции.

[9] Инициализация soap структуры (stdsoap2.cpp):

/******************************************************************************/
#ifndef PALM_2
SOAP_FMAC1
void
SOAP_FMAC2
soap_begin(struct soap *soap)
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
  if (!soap->keep_alive)
  { soap->buflen = 0;
    soap->bufidx = 0;
  }
  soap->null = 0;
  soap->position = 0;
  soap->encoding = 0;
  soap->mustUnderstand = 0;
  soap->mode = 0;
  soap->ns = 0;
  soap->part = SOAP_END;
  soap->event = 0;
  soap->evlev = 0;
  soap->alloced = 0;
  soap->count = 0;
  soap->length = 0;
  soap->cdata = 0;
  soap->error = SOAP_OK;
  soap->peeked = 0;
  soap->ahead = 0;
  soap->idnum = 0;
  soap->level = 0;
  soap->endpoint[0] = '\0';
  soap->encodingStyle = SOAP_STR_EOS;
#ifndef WITH_LEANER
  soap->dime.chunksize = 0;
  soap->dime.buflen = 0;
#endif
  soap_free_temp(soap);
}
#endif

/******************************************************************************/

[12-13] Сериализация заголовка и запроса.

Остальная часть метода:

    if (soap_end_count(soap)) // [26]
        return soap->error;
    if (soap_connect(soap, soap_url(soap, soap_endpoint, NULL), soap_action)
     || soap_envelope_begin_out(soap)
     || soap_putheader(soap)
     || soap_body_begin_out(soap)
     || soap_put___ns__myOperation(soap, &soap_tmp___ns__myOperation, "-ns:myOperation", NULL)
     || soap_body_end_out(soap)
     || soap_envelope_end_out(soap)
     || soap_end_send(soap)) // [27]
        return soap_closesock(soap);
    if (!ns__myResponse_)
        return soap_closesock(soap);
    ns__myResponse_->soap_default(soap);
    if (soap_begin_recv(soap)
     || soap_envelope_begin_in(soap)
     || soap_recv_header(soap)
     || soap_body_begin_in(soap))
        return soap_closesock(soap);
    ns__myResponse_->soap_get(soap, "ns:myResponse", "ns:myResponse");
    if (soap->error)
        return soap_recv_fault(soap, 0);
    if (soap_body_end_in(soap)
     || soap_envelope_end_in(soap)
     || soap_end_recv(soap))
        return soap_closesock(soap);
    return soap_closesock(soap);
}

[14-26] Подсчет разных величин.

[27]
-> В этом условии (имеется весь if) впервые устанавливается сетевое соединение через сокеты.
--> Отправка XML запроса по HTTP проходит в функции soap_end_send, до этого работа идет по TCP.
---> soap_end_send функция вызывает другую функцию soap_end_send_flush.
----> soap_end_send_flush функция вызывает первую встречу функцию soap_flush.
-----> soap_flush функция вызывает последнюю встречу функцию soap_flush_raw. Функция soap_flush_raw получает на вход аргументы: n - это размер запроса в байтах, s - HTTP-запрос.
------> soap_flush_raw вызывает soap->fsend(soap, s, n);

stdsoap2.cpp

--