Référence du fichier main.h

Aller au code source de ce fichier.

Structures de données

struct  StrExample
 Nouvelle structure interne contenant respectivement le pointeur de session de libcurl, le dernier message d'erreur, l'url d'origine et la machine Scol en cours. Plus de détails...

Fonctions

int sc_getFile (mmachine m)
 Récupère un fichier sur le net et l'enregistre localement.
int sc_newGetUrl (mmachine m)
 Code interne de la fonction Scol example_newUrl.

Variables

int ObjCurl

Documentation des fonctions

int sc_getFile ( mmachine  m  ) 

Récupère un fichier sur le net et l'enregistre localement.

Paramètres:
struct mmachine
Renvoie:
0

Code interne de la fonction Scol example_getFile

On récupère les valeurs des arguments passés à la fonction Scol grâce aux fonctions habituelles. On teste leur validité.

On code normalement la partie correspondante à la bibliothèque libcurl, comme si c'était un programme C quelconque (ce qui est d'ailleurs le cas !). On n'oublie pas de libérer les ressources précédemment allouées et on retourne 0 à la fonction Scol si tout est ok.

Notez qu'en cas d'erreurs sur les arguments, la fonctions Scol renverra d'autres valeurs :

1 - si le fichier distant ou local vaut nil; 2 - si la bibliothèque libcuel n'a pu s'initialiser correctement; 3 - si le fichier local n'a pu être ouvert en écriture.

Définition à la ligne 50 du fichier functions.c.

00051 {
00052     int murl, mlocalfile, len;
00053     char * url, * localfile, * err = NULL;
00054 
00055     CURL * hCurl;     /* handle */
00056     CURLcode rCurl; /* result */
00057     FILE * fp = NULL;
00058 
00059     MMechostr (MSKDEBUG, "sc_getFile : entering ...\n");
00060 
00061     mlocalfile = MTOP (MMpull (m));
00062     murl = MTOP (MMpull (m));
00063 
00064     if ((mlocalfile == NIL) || (murl == NIL))
00065     {
00066         MMechostr (MSKDEBUG, "sc_getFile error : url or localfile is nil\n");
00067         MMpush (m, ITOM (1));
00068         return 0;
00069     }
00070 
00071     hCurl = curl_easy_init();
00072     if (hCurl)    /* init ok */
00073     {
00074         len = sizeof (char) * (MMsizestr (m, mlocalfile));
00075         localfile = (char *) malloc (len+1);
00076         strncpy (localfile, MMstartstr (m, mlocalfile), len);
00077         localfile[len] = '\0';
00078 
00079         fp = fopen (localfile, "w");
00080         if (fp == NULL)
00081         {
00082             curl_easy_cleanup (hCurl);
00083             free (localfile); localfile = NULL;
00084             MMpush (m, ITOM (3));
00085             return 0;
00086         }
00087 
00088         err = (char *) malloc (sizeof (char) * (CURL_ERROR_SIZE +1));
00089         len = sizeof (char) * (MMsizestr (m, murl));
00090         url = (char *) malloc (len+1);
00091         strncpy (url, MMstartstr (m, murl), len);
00092         url[len] = '\0';
00093 
00094         curl_easy_setopt (hCurl, CURLOPT_URL, url);
00095         curl_easy_setopt (hCurl, CURLOPT_WRITEFUNCTION, fwrite);
00096         curl_easy_setopt (hCurl, CURLOPT_WRITEDATA, (FILE *) fp);
00097         curl_easy_setopt (hCurl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
00098         curl_easy_setopt (hCurl, CURLOPT_ERRORBUFFER, err);
00099         rCurl = curl_easy_perform (hCurl);
00100 
00101         MMechostr (MSKDEBUG, "sc_getFile : err = %s ...\n", err);
00102         curl_easy_cleanup (hCurl);
00103         fclose (fp);
00104 
00105         free (localfile); localfile = NULL;
00106         free (url); url = NULL;
00107         free (err); err = NULL;
00108 
00109         MMpush (m, ITOM (0));
00110         return 0;
00111     }
00112 
00113     MMpush (m, ITOM (2));
00114     return 0;
00115 }

int sc_newGetUrl ( mmachine  m  ) 

Code interne de la fonction Scol example_newUrl.

Paramètres:
struct mmachine
Renvoie:
0

Cette fonction propose d'envoyer une requête simple de type GET à un serveur et d'exécuter une fonction Scol spécifique (callback) à chaque réception de paquets en réponse à la requête.

Ce code présente :

  • la création d'objet de type Scol
  • la définition d'une fonction réflexe Scol

Pour créer un objet Scol, il est impératif de connaître le canal sur lequel le créer. D'autres paramètres peuvent être requis suivant les cas mais le canal est le seul requis dans tous les cas. Il n'y a aucun traitement à faire au sujet du canal, c'est transparent, le traitement est fait bien en profondeur, au niveau du kernel. Cependant, le canal doit être présent dans la pile, en position 0, lors de l'appel de la fonction de création. Ceci est impératif ! Le canal doit être à l'étage 0 de la pile ! Si ce n'est pas le cas, vous devez le déplacer.

Pour créer un objet Scol, il faut tout d'abord lui allouer de la mémoire (c'est le cas le plus fréquent (si ce n'est le seul dans une pratique usuelle) d'allocation directe de mémoire d'un objet de la VM). Ce sera fait avec MMalloc avec pour argument, la machine Scol courante, la taille à allouer et le type (tableau (TYPETAB) ou buffer (TYPEBUF)) :

 int objtab = MMalloc (m, sizeof (type), TYPEDEF);

Comme toute allocation, celle-ci doit être testée. On stocke alors le nouvel objet via la fonction MMstore : la machine Scol, le retour de MMalloc, un flag correspondant à l'objet et le pointeur système.

 MMstore (m, objtab, OBJ_HANDLE, (int) obj_handle);

Alors, il est possible d'inclure ledit objet dans la pile afin de le retourner à la fonction appelante de création, généralement via un \æ MMpush des plus classiques.

Enfin, création de l'objet du type Scol défini, via OBJcreate qui prend en arguments : la machine Scol, le type d'objet, l'objet système, le type del'objet parent (peut être NULL) et l'objet système du parent (peut être NULL).

Récapitulatif :

  • création de l'objet en C ou en C++ selon les cas
  • allocation de émmoire pour l'objet au sein de la VM (MMalloc)
  • stockage de l'objet (MMstore)
  • empilement pour le retour de la fonction Scol (MMpush)
  • creation de l'objet Scol (OBJcreate)

Pour ajouter une fonction réflexe à un objet Scol :

Il faut un objet valide (c'est une évidence mais il convient donc de tester sa validité !); et appeler la fonction OBJaddreflex. Celle-ci prend en argument :

  • la machine Scol en cours,
  • le type Scol de l'objet,
  • un flag spécifique à la callback

La fonction exemple demande une url en entrée et retourne un objet Scol de type ObjCurl en sortie. Entre temps, la fonction Scol aura également définie une callback qui sera exécutée à chaque paquet reçu. Son proptotype Scol : fun [Chn S S fun [ObjCurl u0 S I S S] u1 u0] ObjCurl

En entrée :

  • le canal
  • l'url
  • un paramètre non traité ici mais qui pourrait être un header pour la requête par exemple
  • une callback
  • un paramètre utilisateur utilisée dans la callback

En retour, un nouvel objet de type ObjCurl.

La callback, dont le type est (rappel) : fun [ObjCurl u0 S I S S] u1 est ainsi définie :

  • l'objet de type ObjCurl dont dépend la callback,
  • le paramètre utilisateur,
  • le paquet de données reçu,
  • la taille du paquet reçu,
  • l'url d'origine,
  • le message d'erreur éventuel de libcurl.

Définition à la ligne 325 du fichier functions.c.

00326 {
00327     int mchannel, murl;
00328     int curltab, sizetab, tmp_res, n;
00329     CURLcode rCurl;
00330     struct StrExample strEx;
00331 
00332     MMechostr (MSKDEBUG, "sc_newGetUrl : entering ...\n");
00333 
00334     memset (strEx.cerr, '\0', CURL_ERROR_SIZE);
00335 
00336     /* Récupération du canal dans lequel se déroule toute notre action ! */
00337     mchannel = MMget (m, 4);
00338     if (mchannel == NIL)
00339     {
00340         MMechostr (0, "sc_newGetUrl error : channel is nil\n");
00341         MMpull (m);
00342         MMpush (m, NIL);
00343         return 0;
00344     }
00345 
00346     /* Récupération de l'url distante */
00347     murl = MTOP (MMget (m, 3));
00348     if (murl == NIL)
00349     {
00350         MMechostr (0, "sc_newGetUrl error : url is nil\n");
00351         MMpull (m);
00352         MMpush (m, NIL);
00353         return 0;
00354     }
00355 
00356     /* On place le canal à l'étage 0 de la pile ! C'est IMPORTANT ! L'étage 0 (paramèter utilisateur
00357         de la callback) se retrouve en 4 on en aura besoin plus tard d'où la non-utilisation de MMset ... */
00358     INVERT (m, 0, 4);
00359 
00360     /* initialisation globale de la libcurl */
00361     if (curl_global_init (CURL_GLOBAL_ALL) != CURLE_OK)
00362     { /* échec de l'initialisation globale, on arrête tout */
00363         MMechostr (0, "sc_newGetUrl error : global init failed\n");
00364         MMpull (m);
00365         MMpush (m, NIL);
00366         return 0;
00367     }
00368 
00369     /* initialisation d'une session de la libcurl */
00370     strEx.hcurl = curl_easy_init();
00371     /* initialisation OK, on continue  */
00372     if (strEx.hcurl)
00373     {
00374         /* calcul de la taille nécessaire en mémoire pour l'objet concerné */
00375         sizetab = sizeof (strEx.hcurl) + 1;
00376         /* allocation de la mémoire de la taille précédemment retournée */
00377         curltab = MMmalloc (m, sizetab, TYPETAB);
00378         /* test du retour de l'allocation */
00379         if ((curltab == NIL))
00380         {
00381             MMechostr (0, "sc_newGetUrl error : insufficient memory\n");
00382             curl_easy_cleanup (strEx.hcurl);
00383             MMpull (m);
00384             MMpush (m, NIL);
00385             return 0;
00386         }
00387         /* stockage de l'objet dans l'espace mémoire alloué */
00388         MMstore (m, curltab, OBJCURL_HANDLE, (int) strEx.hcurl);
00389         /* empile de l'objet pour son utilisation en retour de la fonction Scol appelante */
00390         MMpush (m, PTOM (curltab));
00391         /* Création de l'objet Scol proprement dit
00392          après le MMpushprécédent, le canal se tretrouve donc en position 1 dans la pile, ce qui
00393          est ok pour l'appel de OBJcreate. Après, on aura plus besoin de connaître le canal
00394          et on pourra sacrifier l'étage 1 si besoin est */
00395         OBJcreate (m, ObjCurl, (int) strEx.hcurl, -1, -1);
00396 
00397         n = sizeof (char) * (MMsizestr (m, murl));
00398         strEx.url = (char *) malloc (n+1);
00399         strncpy (strEx.url, MMstartstr (m, murl), n);
00400         strEx.url[n] = '\0';
00401 
00402         strEx.m2m = m;
00403 
00404         /* on intervertit des étages dans la pile :
00405             l'objet session de libcurl passe à l'étage 2
00406             le paramètreutilisateur repasse en position 0, comme au départ */
00407         INVERT (m, 0, 2);   /* hCurl se retrouve en 2 */
00408         INVERT (m, 0, 4);   /* user param se retrouve en 0 */
00409         /* On ajoute la callback définie dans le package Scol */
00410         OBJaddreflex (m, ObjCurl, CURL_CB_GET);
00411 
00412         curl_easy_setopt (strEx.hcurl, CURLOPT_URL, strEx.url);
00413         curl_easy_setopt (strEx.hcurl, CURLOPT_ERRORBUFFER, strEx.cerr);
00414         curl_easy_setopt (strEx.hcurl, CURLOPT_WRITEDATA, &strEx);
00415         curl_easy_setopt (strEx.hcurl, CURLOPT_WRITEFUNCTION, sc_newUrlCB);
00416         curl_easy_setopt (strEx.hcurl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
00417 
00418         rCurl = curl_easy_perform (strEx.hcurl);
00419         sc_newUrlCBend (&strEx);
00420 
00421         curl_easy_cleanup (strEx.hcurl);
00422         curl_global_cleanup();
00423 
00424         free (strEx.url);
00425         /*free (strEx.cerr);*/
00426 
00427         return 0;
00428     }
00429 
00430     /* l'initialisation a échoué */
00431     MMechostr (0, "sc_newGetUrl error : easy init failed\n");
00432     curl_global_cleanup();
00433 
00434     MMpull (m);
00435     MMpush (m, NIL);
00436     return 0;
00437 }


Documentation des variables

int ObjCurl

Définition à la ligne 52 du fichier main.h.

Généré le Sat Nov 20 23:18:18 2010 pour example par  doxygen 1.6.3