Search code examples
c++ccurlwsdllibcurl

"Failed writing body" CURLOPT_WRITEDATA


The below code is to get response from a server using wsdl, here the problem is curl returns response but am unable to print it.

Error:

Failed writing body Failed writing data

#include<stdio.h>
#include<string.h>
#include"../include/curl.h"

size_t write_data(void *ptr, size_t size, size_t count, void *stream)
{
      /* ptr - your string variable.
      stream - data chuck you received */

     printf("%.*s", size, (char*)stream);
}


int main()
{
    int res=0,i=0;
    char buffer[4098]="",buff[128]="",buf[256]="",buf7[30]="",buf6[30]="",buf5[30]="";
    char machineid[]="SUBANI";
    char filename1[50]="";
    int refno=0,paymode=0,taxtype=0;
    FILE *fbc;

    memset(filename1,0,sizeof(filename1));
    sprintf(filename1,"/mnt/jffs2/Response_Details1.xml");
    lk_dispclr();
    lk_disptext(1,0,(unsigned char *)"Sending Request",0);
    lk_disptext(2,0,(unsigned char *)"Please Wait",0);
    memset(buffer,0,sizeof(buffer));

    sprintf(buffer,"<?xml version=\"1.0\" encoding=\"utf-8\"?>\
                        <soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:log=\"http://wsdlclassess.application.sims.test.com\">\
                        <soap:Header>\
                        </soap:Header>\
                        <soap:Body>\
                        <log:loginMethod>\
                        <log:loginid>%s</log:loginid>\
                        <log:password>%s</log:password>\
                        </log:loginMethod>\
                        </soap:Body>\
                        </soap:Envelope>","raja","test");


    res=GET_FILE1(buffer,filename1);


    return 0;
}


int GET_FILE1(char *buffer,char *filename)
{
    CURL *curl;
    CURLcode res;
    struct curl_slist *headers = NULL;
    FILE *out_fd = (FILE *) 0;
    char errorbuf[300] = "",tmpbuff[128]="";
    char errmsg[256];
    int Timeout=120;   //Default timeout is = 2 mins
    int buffer_size = 0;
    char urlbuff[256]="";
    char mstr[10240];

    memset(urlbuff,0,sizeof(urlbuff));
        memset(tmpbuff,0,sizeof(tmpbuff));
    buffer_size = strlen(buffer);
         strcpy(tmpbuff,"http://10.10.1.111:8081/test_server/services/application?wsdl");
             tmpbuff[strlen(tmpbuff)]='\0';
    curl = curl_easy_init();
    if(curl)
    {
        out_fd = fopen (filename, "w");
        curl_easy_setopt(curl, CURLOPT_FILE, out_fd);
        printf("%s:Sign-In Request\n", __func__);
        headers = curl_slist_append(headers, "Content-type:application/soap+xml; charset=utf-8; action=\"http://wsdlclassess.application.sims.test.com/loginMethod\"");

        curl_easy_setopt(curl, CURLOPT_URL, tmpbuff);
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);

        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);

    curl_easy_setopt(curl, CURLOPT_WRITEDATA, mstr);


        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, buffer_size);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buffer);

        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, Timeout);
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER,errmsg);

        printf("The Server%s:Performing Transaction.....\n",__func__);
        res = curl_easy_perform(curl);
        printf("res=after culreasey perform%d\n",res);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        printf("\nerrorbuf:%s\n",errmsg);
        fclose(out_fd);
        if(CURLE_OK != res)
        {
            puts("error occured is\n" );
            //ppp_close();
            return -1;
        }
    }

    return 0;
}

Solution

  • The error is that you don't return the correct value from the function, in fact you don't return anything.

    Also, the data provided to the function is actually the first ptr argument.


    I agree that the documentation is not very clear, but it says:

    The size of the data pointed to by ptr is size multiplied with nmemb, it will not be zero terminated.

    The above line (emphasis mine) tells you that the data is in ptr which is the first argument in the function declaration provided in the documentation.

    The documentation also states:

    Return the number of bytes actually taken care of. If that amount differs from the amount passed to your function, it'll signal an error to the library. This will abort the transfer and return CURLE_WRITE_ERROR.

    You don't return a value from the function, and so you have undefined behavior with a seemingly random value being returned causing the whole operation to fail. To fix this you should return size * count.

    You also uses size to print the string, which is the size of the underlying type used (probably 1), your count variable is the number of characters read by CURL. To be fully working, without invoking more undefined behavior (since the data is not terminated) you should call printf like:

    printf("%*.*s", size * count, size * count, ptr);