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

Hans-Christoph Steiner hans at eds.org
Thu Jun 22 22:15:48 CEST 2006


Sounds like a nifty object,  but why not aim on making it as flexible  
as possible?  It shouldn't be too hard to make it do everything that  
libcurl lets you do.  One simple thing, for example, is making it  
possible to set the CURLOPTS_* via Pd messages so people can make  
their own HTTP headers.

As for crashes, since libcurl wants to use a call back function, you  
will need have a separate thread, AFAIK.  That separate thread could  
just wait for libcurl to call the callback, then write data to a data  
structure.  The Pd object would then just check the data structure  
for the status of things.  externals/olafmatt/hidin is a example of  
how to do the threading, even tho its Windows only object, the  
threading method will be the same.

.hc


On Jun 19, 2006, at 9:18 AM, Alexandre Quessy wrote:

> 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);
> }
>
>
>
>
>
> _______________________________________________
> PD-dev mailing list
> PD-dev at iem.at
> http://lists.puredata.info/listinfo/pd-dev


------------------------------------------------------------------------

News is what people want to keep hidden and everything else is  
publicity.          - Bill Moyers


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puredata.info/pipermail/pd-dev/attachments/20060622/1922b44c/attachment.htm>


More information about the Pd-dev mailing list