[PD-dev] HTTP requests external : cURL threads ?

Alexandre Quessy listes at sourcelibre.com
Mon Jun 19 18:18:08 CEST 2006


Hi,

I am working on a simple external to do HTTP requests from PD. The idea is
to implement a simple way to send and receive simple data to a web server.
This is intended to work together with a set of classes that will interpret
the GET variables as key and values pairs where the values can be similar to
FUDI protocol messages. The web page would then answer with a FUDI message
or so. I don't use Python because I want it to be very fast, totally
portable and easy to install. (I also agree with Hans regarding small tools
to make a constellation of low level objects)

Here are my bugs : perhaps I am not very good yet with strings in C, but I
have several errors when I try to execute this code from within PD as an
external. Well, when I get malloc errors, it must be only about memory size
arithmetics, but when it gets into segmentation faults, I was just wondering
if it could be because cURL starts a new thread. I think that thread are not
much appropriate in PD's context. Do you think this is the problem, or I am
just still a bit bad with memory maths ?

Also, if you have ideas about this external, please don't hesitate. I think
I will rename it to http, as it is not intended in downloading whole files,
but just for simple HTTP requests.

See below for the current code, the makefile and one of the errors it
creates.

Alexandre Quessy
http://alexandre.quessy.net

============================= error when using it ====================

pd wget-help.pd
STACK_END old=0xbf9e5ffc; new=0xbf9efffc
PDP: pure data packet
PDP: version 0.12.4
* About to connect() to alexandre.quessy.net port 80
*   Trying 64.15.134.165... * connected
* Connected to alexandre.quessy.net (64.15.134.165) port 80
> GET /pd/curlme.php?asd=qwe+123 HTTP/1.1
User-Agent: Pure Data
Host: alexandre.quessy.net
Accept: */*

< HTTP/1.1 200 OK
< Date: Mon, 19 Jun 2006 16:03:44 GMT
< Server: Apache
< X-Powered-By: PHP/4.3.10-16
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html
* Closing connection #0
socket receive error: Connection reset by peer (104)
Erreur de segmentation

================== makefile ====================================

all: wget.pd_linux
    @echo "making wget"

wget.pd_linux: wget.c
    gcc -DPD -O2 -funroll-loops -fomit-frame-pointer \
      -Wall -W -Wshadow -Wstrict-prototypes \
      -Wno-unused -Wno-parentheses -Wno-switch -o wget.o -c wget.c
    ld -export_dynamic -shared -o wget.pd_linux wget.o -lcurl -lc -lm
    strip --strip-unneeded wget.pd_linux
    rm wget.o



================== code : wget.c ================================

/**
 * [wget] is a Pure Data object for simple HTTP requests.
 *
 * @url http://alexandre.quessy.net/
 * @author Alexandre Quessy <alexandre at quessy.net>
 * @license GNU General Public License 2006
 */
#define PDWGET_VERSION "0.1.0"

/* PD includes */
#include "m_pd.h"

/* cURL and standard C libraries */
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>

/* Download callback function prototype */
size_t wget_callBack(void *ptr, size_t size, size_t nmemb, void *x);

/**
 * variables of the pd object
 */
typedef struct wget {
  t_object x_ob; /* The instance. Contains inlets and outlets */
  t_outlet *x_outlet0; /* result string */
  t_outlet *x_outlet1; /* HTTP error codes */
} t_wget;



/**
 * HTTP request.
 */
void wget_request(t_wget *x, t_symbol *s, int argc, t_atom *argv) {
    post("wget : called request.");
    //curl_global_init(CURL_GLOBAL_NOTHING);//CURL_GLOBAL_ALL

    //t_symbol *sym_tmp = atom_getsymbol(&argv[0]);
    if (argc < 1) {
        post("wget : Error : needs arguments.");
    } else {
    t_symbol *sym_tmp = atom_getsymbolarg(0, argc, argv);
        char *url = sym_tmp->s_name;

    post("wget : requesting : %s", url);

    /* cURL context */
    CURL *pContext = curl_easy_init();
    if (pContext == NULL) {
        post("wget : Error :  Null cURL handle.");
    } else {
        /* cURL options */
        CURLcode pCode = curl_easy_setopt(pContext, CURLOPT_URL, url);
        curl_easy_setopt(pContext, CURLOPT_WRITEFUNCTION, wget_callBack,
(void *) x);
        curl_easy_setopt(pContext, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(pContext, CURLOPT_HEADER, 0);
        curl_easy_setopt(pContext, CURLOPT_NOPROGRESS, 1);
        curl_easy_setopt(pContext, CURLOPT_USERAGENT, "Pure Data");
        curl_easy_setopt(pContext, CURLOPT_NOSIGNAL, 1);
        curl_easy_setopt(pContext, CURLOPT_TIMEOUT, (long) 5);

        /* cURL performing */
        post("wget : Performing the request.");
        const CURLcode result = curl_easy_perform(pContext);
        if(CURLE_OK != result) {
            post("wget : Error from cURL: %s", curl_easy_strerror(result));
        } else {

            /* HTTP code */
            long lHttpCode;
            curl_easy_getinfo(pContext, CURLINFO_RESPONSE_CODE, &lHttpCode);
            post("wget : HTTP response code: %ld ", lHttpCode);
            //outlet_float(x->x_outlet1, (float) lHttpCode);
        }
    }

    post("[wget] cleaning up...");
    /* cURL cleanup */
    curl_easy_cleanup(pContext);
    post("[wget] Local cleaned up.");
    //curl_global_cleanup();
    post("[wget] Global cleaned up.");
    //outlet_list(x->x_outlet0, gensym("A_FLOAT"), numCols+1, &atoms); //
&atoms ??
    } // else
}

/**
 * The representation of the class in PD.
 */
t_class *wget_class;

/**
 * constructor
 */
void *wget_new(t_symbol *selector, int argc, t_atom *argv) {
    post("wget : creating a new object.");
    t_wget *x = (t_wget *) pd_new(wget_class);
    x->x_outlet0 = outlet_new(&x->x_ob, gensym("list"));
    x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));
    return (void *)x;
}

/**
 * setup
 */
void wget_setup(void) {
    curl_global_init(CURL_GLOBAL_NOTHING);
    wget_class = class_new(gensym("wget"), (t_newmethod) wget_new, 0,
sizeof(t_wget), 0, A_GIMME, 0);
    class_addmethod(wget_class, (t_method)wget_request, gensym("request"),
A_GIMME, 0);

    post("----------------------------------------------------");
    post(" [wget] %s (c) GPL Copyleft 2006 Alexandre Quessy",
PDWGET_VERSION);
    post(" Simple HTTP requests for Pure Data.");
    post("----------------------------------------------------");
}

/**
 * Callback implementation
 */
size_t wget_callBack(void *ptr, size_t size, size_t nmemb, void *x) {
    size_t totalSize = nmemb * size;
    char *dest = malloc(totalSize + 1); //(sizeof(char))
    strcpy(dest, (char *) ptr);
    post("[wget] : Getting data.");
    dest[totalSize] = '\0';
    post("result :");
    post("===============================");
    post("%s", dest);
    post("===============================");

    //outlet_symbol(((t_wget *)x)->x_outlet0, gensym(dest));
    //free(dest);
    return(totalSize);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puredata.info/pipermail/pd-dev/attachments/20060619/4221738b/attachment.htm>


More information about the Pd-dev mailing list