cURL / Mailing Lists / curl-library / Single Mail

curl-library

dynamic memory allocation problems

From: Saidus Bounderra <bsaidus_at_gmail.com>
Date: Mon, 16 Aug 2010 09:09:04 +0100

Hello all ....
I'm trying to write a "windows dll" wich use the libcurl.lib . in this dll
there is functions that try to download file from internet using the multi
interface,
(i.e : One file will be downloaded using multiple easy handles each of them
will download a specified range ).
all works fine if i let the current downloading process finishes his work
...!!!! *BUT* if I interrupt the process for exemple in middle there is some
data
allocated by me dynamically that is not freed ... so my problem is ,IS
THERE ANY ONE CAN HELP ME TO RESOLVE THIS , or give me others ideas how
to proceed in others ways .. Thanks
here is the code :

I have commented the source in the function to understand the problem ....
Thanks ...

/////////////////////////////////////////////////////////////////////////////////////////////////
// Header File
///
/* --------------------------------------------------------- */
/*{ File : idsbscurl.h }*/
/*{ ============================ }*/
/*{ Interface for the DLL }*/
/*{ }*/
/*{ }*/
/*{ }*/
/*{ }*/
/*{ }*/
/*{ ids = internet download speeder }*/
/* ---------------------------------------------------------- */
#ifndef _IDSBSCURL_H
#define _IDSBSCURL_H

#ifdef IDSCBUILD
#define IDSEXTERN __declspec(dllexport)
#else
#define IDSEXTERN __declspec(dllimport)
#endif
/* Extern for C naming function dll */
#ifdef __cplusplus
extern "C" {
#endif // end cpp
/* ****************************************************************** */

typedef void * pvoid ;
/* ------------------------------------------------- */
/* Callback functions for Writing and Progression */
/* ------------------------------------------------- */
typedef int (*idsCbSplitAll)(pvoid Caller, double total, int chunk )
;
typedef int (*idsCbProgress)(pvoid Caller, double total , double dlnow,
                              double dlspeed, double gtime, int aHandle) ;

/* ------------------------------------------------- */
/* Auth Methodes */
/* ------------------------------------------------- *
#define IDSAUTH_NONE 0 /* nothing *
#define IDSAUTH_BASIC (1<<0) /* Basic (default)*
#define IDSAUTH_DIGEST (1<<1) /* Digest *
#define IDSAUTH_GSSNEGOTIATE (1<<2) /* GSS-Negotiate *
#define IDSAUTH_NTLM (1<<3) /* NTLM *
#define IDSAUTH_DIGEST_IE (1<<4) /* Digest with IE flavour*
#define IDSAUTH_ANY (~CURLAUTH_DIGEST_IE) /* all fine types
set*
#define IDSAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))*/
/* ------------------------------------------------- */
/* Enum for ThreadCount for the Curl handles */
/* ------------------------------------------------- */
/*typedef enum {
    thD2=2, thD4=4, thD6=6, thD8=8
} centhread;*/

/* ------------------------------------------------- */
/* Counter for the Curl handles */
/* ------------------------------------------------- */
struct curlcounter {
    pvoid cu ;
    unsigned int counter;
};

/* ------------------------------------------------- */
/* information about the remote file ressource */
/* ------------------------------------------------- */
struct infocurl{
    char *lc_name ;
    double lc_size ;
    char *lc_type ;
};
typedef struct infocurl TInfocurl ;
/* ------------------------------------------------- */
/* Proxy types */
/* ------------------------------------------------- */
typedef enum
{ pyHttp, //CURLPROXY_HTTP,
    pyHttp10, //CURLPROXY_HTTP_1_0,
    pySocks4, //CURLPROXY_SOCKS4,
    pySocks5, //CURLPROXY_SOCKS5,
    pySocks4A, //CURLPROXY_SOCKS4A ,
    pySocks5H, //CURLPROXY_SOCKS5_HOSTNAME
}proxy_type;

/* ------------------------------------------------- */
/* Authentification Procedures */
/* ------------------------------------------------- */
typedef enum
{
}auth_type ;
/* ------------------------------------------------- */
/* Global structure for the Download */
/* ------------------------------------------------- */
struct _idsFHttp
{
    /* general fields */
    char* url;
    char* lc_file;
    char* lc_folder;
    int port;
    char* username;
    char* password;
    int usehttpauth ; // 0 or 1 to enable http auth
    //long httpauth ;
    /* Proxy setting */
    char* proxy;
    char* pusername;
    char* ppassword;
    int pport ;
    int useproxyauth ; // 0 or 1 to enable http auth
    //long proxyauth ;
    proxy_type ptype; // proxy type
    char *BypassProxy; // adresse that not use proxy {CURLOPT_NOPROXY}
    /* -------------------*/
    /* Callback functions */
    idsCbSplitAll idsSplit;
    idsCbProgress idsPrgrs;

    /* Reserved for External use */
    pvoid caller ;
    /* thread specifique */
    int threadcount ;
    long int chunk;
    long int buffersz;
    /* Redirection */
    int followRedir ;
    int maxfollow ;
    /* Resuming */
    int EnableResume ; // 0 or 1

    /* Timing */
    int TimeOut ;
    /* MAx Connection */
    int MaxConnections ;

} ;
typedef struct _idsFHttp idsFHttp ;
typedef struct _idsFHttp* PidsFHttp ;

/* ------------------------------------------------- */
/* API Interface for downloading files from */
/* Http Server */
/* ------------------------------------------------- */
IDSEXTERN int idsbsGlobalInits_curl();
IDSEXTERN void idsbsGlobalClean_curl();
//IDSEXTERN int idsbsGetHttpFile_00 (const PidsFHttp p, centhread
nThreads) ;

//IDSEXTERN int idsbsGetHttpFile_01 (const PidsFHttp p) ;
//IDSEXTERN int idsbsGetHttpFile_02 (const PidsFHttp p) ;
//IDSEXTERN int idsbsGetHttpFile_04 (const PidsFHttp p) ;
/* ------------------------------------------------------
* Download the file in p->url in 6 threads
* -----------------------------------------------------*/
*IDSEXTERN int idsbsGetHttpFile_06 (const PidsFHttp p) ;*
//------------------------------------------------------
//IDSEXTERN int idsbsGetHttpFile_08 (const PidsFHttp p) ;
//IDSEXTERN int idsbsGetHttpFile_10 (const PidsFHttp p) ;
//IDSEXTERN int idsbsGetHttpFile_12 (const PidsFHttp p) ;
//IDSEXTERN int idsbsGetHttpFile_14 (const PidsFHttp p) ;
//IDSEXTERN int idsbsGetHttpFile_16 (const PidsFHttp p) ;

//IDSEXTERN int idsbsGetHttpFile_06er (const PidsFHttp p) ;
/* ------------------------------------------------- */
/* Usefull API for getting info and speed */
/* ........... */
/* ------------------------------------------------- */
//IDSEXTERN TInfocurl idsbsGetUrlInfos_00(const PidsFHttp p) ;
/* ****************************************************************** */
/* end of extern naming dll function */
#ifdef __cplusplus
} ;
#endif // end cpp
#endif // end of idsbscurl.h
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the source code for the function
// *IDSEXTERN int idsbsGetHttpFile_06 (const PidsFHttp p) ;*
//
//
/* --------------------------------------------------------- */
/*{ File : idsbsGetHttpFile_04.cpp }*/
/*{ ============================ }*/
/*{ Getting File From Http Server with 6 Connections }*/
/*{ }*/
/*{ }*/
/*{ }*/
/*{ }*/
/*{ }*/
/*{ }*/
/* ------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../inc/curl.h"
#include "idsbscurl.h"
#include "idsbs_helper.h"
#include "idsbshttpoptions.h"

// ---------------------------------------------
// this is the global variable to use in different
// functions in the following code
//

idsFHttp idsFile06 ; // Global Var

/* ------------------------------------------------- */
/* // Default Write Function */
/* ------------------------------------------------- */
static size_t DefWrtFunc06(char* Buffer, size_t nItems, size_t lItems, void
*stream )
{
    fwrite(Buffer,nItems,lItems,(FILE*)stream);
    return (nItems*lItems);
}

/* ------------------------------------------------- */
/* // Default Progress Function */
/* ------------------------------------------------- */
static int DefPrgressFunc06(void *clientp, double dltotal,double
dlnow,double ultotal,double ulnow )
{
    double speed = 0 ,
           dtime = 0 ;
    //void *nil = NULL ;
/*
    int t ;
    int *p ;

    p = &t ;
    *p = t
*/
    curlcounter *t = (curlcounter*)clientp;
    // Get Speed of download
    speed = idsbsGetSpeedDW((CURL*)t->cu);
    // Get Global Time
    dtime = idsbsGetGlobalTime((CURL*)t->cu);
    // Get thread Num
    unsigned int i = t->counter ; // Problem in getting the Num of the
Thread ... Resolved
    // Write a Callback Here for Progression and Speed
    if (idsFile06.idsPrgrs!=NULL)
    {idsFile06.idsPrgrs(idsFile06.caller,dltotal,dlnow,speed,dtime, i) ;}
    return 0 ;
}

/* ------------------------------------------------- */
/* // Adding Single Curl to MCurl */
/* ------------------------------------------------- */
static void bsInitCurlMulti06 (CURLM *cm, curlcounter *eh[], const PidsFHttp
P, FILE *fps[],
                        char Frange[][_MAX_PATH] ,int Counter)
{

    char Fname[_MAX_PATH] ;
    char* Lcname ;

    idsFile06 = *P;

    Lcname = P->lc_file ;
    sprintf(Fname,"%s%d",Lcname,Counter) ;

    if((fps[Counter] = fopen(Fname,"wb"))==NULL)
    { exit(-1); }

    //init the curl easy ...
    (CURL*)eh[Counter]->cu = curl_easy_init();
    eh[Counter]->counter = Counter ;

    // User Fill params
    curl_easy_setopt((CURL*)eh[Counter]->cu, CURLOPT_URL , P->url );
    curl_easy_setopt((CURL*)eh[Counter]->cu, CURLOPT_PORT , P->port
);
    // Fill the Ranges ...
    curl_easy_setopt((CURL*)eh[Counter]->cu, CURLOPT_RANGE ,
Frange[Counter] );
    // Write Functions
    curl_easy_setopt((CURL*)eh[Counter]->cu, CURLOPT_WRITEFUNCTION ,
DefWrtFunc06);
    curl_easy_setopt((CURL*)eh[Counter]->cu, CURLOPT_WRITEDATA ,
fps[Counter]);
    // Progress Function
    curl_easy_setopt((CURL*)eh[Counter]->cu, CURLOPT_NOPROGRESS,0);
    curl_easy_setopt((CURL*)eh[Counter]->cu, CURLOPT_PROGRESSFUNCTION,
DefPrgressFunc06);
    curl_easy_setopt((CURL*)eh[Counter]->cu,
CURLOPT_PROGRESSDATA,eh[Counter]) ;
    //curl_easy_setopt((CURL*)eh[Counter]->curl, CURLOPT_BUFFERSIZE,40960)
;

    // Other options will be done here ...
    // for Proxy and server Auth and Other
    //
// Set_CurlEParams ( P, (CURL*)eh[Counter]->cu);

    ///////////////////////////////////////////
    // Add easy handles to multi one
    curl_multi_add_handle(cm, (CURL*)eh[Counter]->cu);
    //return BSERROK ;
}

/* -------------------------------------------------- */
/* Getting File from Http Server with 6 Connections */
/* -------------------------------------------------- */
IDSEXTERN int idsbsGetHttpFile_06 (const PidsFHttp p)
{
    /* ------------------------------------------
    /
    / Get Content Length
    / Part the FileLength in a Ranges ..
    / Start the Process of Downloading
    /
    -------------------------------------------*/

    CURLM *cm ; // CurlM handle
    double resSize = 0 ; // File size
   // int Threads = 6 ; // Number of threads // <=> D4
    FILE *fpt[6] ; // File discriptors ..

    int running ; // track multi work ..
    int i = 0 ; // Counter

    //CURL *eh[D6] ; // easy handles ...
    curlcounter *eh[6];

    //curlcounter eh ;

    // -------------------------------------------------
    // Allocate memory for 6 structure type curlcounter
    // to this point there is no probleme
    // -------------------------------------------------
    int j = 0 ;
    for (j=0;j<6;j++) {
        eh[j] = (curlcounter*)malloc( sizeof(curlcounter)) ;
        if (eh[j]==NULL) { return -1 ;}
    }
    //
    // ----------------------------------------------------
    // Ranges to store the ranges for the 6 parts of files
    char Ranges[6][_MAX_PATH]; // for File partition

    idsFile06 = *p;
    // init the multi curl ....
    cm = curl_multi_init();
    // MAx Conenction
    Set_CurlMParams( p, cm);
    //
=================================================================================
    // Get Size of the File
    // idsbsGetFileLength ( p ) : Get the Countent Length for the file in
the server
    //
=================================================================================
    resSize = idsbsGetFileLength ( p ) ;

//==================================================================================
    // Parts file into sevral Chunks
    // idsbsThreadPartFile( FileSize, Ranges, 6) : Parts the size of the
file and fill
    // the Range Variable ...

//==================================================================================
    idsbsThreadPartFile( resSize, Ranges, 6) ;

    // Start the Job
    for (i=0;i<6;i++) { bsInitCurlMulti06(cm,eh ,p, fpt, Ranges, i) ; }

    // end the Job

// for (j=0;j<6;j++) {
// free(eh[j]);
// }

    // Start Transfer
    // if we let the transfer continue to its completion then it will be
fine
    // all allocated dynamically memory will be freed
    //
    //
    // but if we interrupt the transfer in ... for exemple in middle then
    // the allocated memory will not be cleaned (i.e: curlcounter *eh[6];)

    while(CURLM_CALL_MULTI_PERFORM ==
          curl_multi_perform(cm, &running)) ;

    while(running)
    {
        struct timeval timeout;
        int rc; /* select() return code */

        //CURLMsg *msg;
        //int Q ;

        fd_set fdread;
        fd_set fdwrite;
        fd_set fdexcep;
        int maxfd;

        FD_ZERO(&fdread);
        FD_ZERO(&fdwrite);
        FD_ZERO(&fdexcep);

        /* set a suitable timeout to play around with */
        timeout.tv_sec = 60;
        timeout.tv_usec = 0;

        /* get file descriptors from the transfers */
        curl_multi_fdset(cm, &fdread, &fdwrite, &fdexcep, &maxfd);

        /* In a real-world program you OF COURSE check the return code of
the
           function calls, *and* you make sure that maxfd is bigger than -1
so
           that the call to select() below makes sense! */

        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

        switch(rc)
        {
            case -1:/* select error */ running = 0;//printf("select()
returns error, this is badness\n");
              break;
            case 0:
            default:/* timeout or readable/writable sockets */
                    while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(cm,
&running));
              break;
        }
    }

    //
    // All this code will not be executed if we interrupt the work of the
    // the Libcurl
    // so Help me on How to do this .
    // IF THE USER DECIDE TO INTERRUPT THE WORK OF THE LIBRARY IN MIDDLE
    // HOW TO FREE ALL ALLOCATED MEMORY ..

//================================================================================

    // remove easy handle and Cleanup
    for(i=0;i<6;i++) {
        curl_multi_remove_handle(cm,(CURL*)eh[i]->cu);
        curl_easy_cleanup((CURL*)eh[i]->cu);
    }

//================================================================================
    // Close all Opened Files
    for(i=0;i<6;i++) { fclose(fpt[i]); }

//================================================================================
    // Clear the multi handle
    curl_multi_cleanup(cm) ;

//================================================================================
    // Splite all Files in One
    idsbsSplitFiles (p , fpt, 6/*, htp->Spt*/);

//================================================================================
    // delete parts
    idsbsDeleteFiles(p,6);

//================================================================================
    // Free allocated memory ..
    //
    //
    for (j=0;j<6;j++){
        free(eh[j]);
    }
    // REturn Value
    //return BSERROK ;

    return 0 ;
}

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2010-08-16