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.
Interesting ! Would that shared data structure be a global variable ?
If so, could I make it unique so that we can create multiple instances
of that pd object ?
I will look at that object's code. Thanks !
Sorry for replying late... :)
--
Alexandre Quessy
http://alexandre.quessy.net
>
>
>
> 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 ====================
> t=0&ie
> 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@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@iem.at
>
http://lists.puredata.info/listinfo/pd-dev
>
>
> ------------------------------------------------------------------------
>
> News is what people want to keep hidden and everything else is publicity.
> - Bill Moyers
>
>