LCOV - code coverage report
Current view: top level - src - libhttp.c (source / functions) Hit Total Coverage
Test: mkernel.info Lines: 0 106 0.0 %
Date: 2024-11-19 20:30:41 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /**
       2             :  *    @file  libhttp.c
       3             :  *   @brief  HTTP parsing and building library
       4             :  *
       5             :  *  @author  François Cerbelle (Fanfan), francois@cerbelle.net
       6             :  *
       7             :  *  @internal
       8             :  *       Created:  15/11/2024
       9             :  *      Revision:  none
      10             :  * Last modified:  2024-11-19 20:24
      11             :  *      Compiler:  gcc
      12             :  *  Organization:  Cerbelle.net
      13             :  *     Copyright:  Copyright (c) 2024, François Cerbelle
      14             :  *
      15             :  *  This source code is released for free distribution under the terms of the
      16             :  *  GNU General Public License as published by the Free Software Foundation.
      17             :  */
      18             : 
      19             : #include "libhttp.h"
      20             : 
      21             : #include <stdlib.h>
      22             : #include <stdio.h>
      23             : #include <string.h>
      24             : #include <assert.h>
      25             : 
      26             : typedef enum HTTPVersion_e {
      27             :     HTTPVERSION_HTTP09,
      28             :     HTTPVERSION_HTTP10,
      29             :     HTTPVERSION_HTTP11,
      30             :     HTTPVERSION_HTTP11b,
      31             :     HTTPVERSION_HTTP2,
      32             :     HTTPVERSION_HTTP3,
      33             :     HTTPVERSION_INVALID
      34             : } HTTPVersion_t;
      35             : 
      36             : typedef enum HTTPMethod_e {
      37             :     HTTPMETHOD_GET,
      38             :     HTTPMETHOD_HEAD,
      39             :     HTTPMETHOD_POST,
      40             :     HTTPMETHOD_PUT,
      41             :     HTTPMETHOD_DELETE,
      42             :     HTTPMETHOD_CONNECT,
      43             :     HTTPMETHOD_OPTIONS,
      44             :     HTTPMETHOD_TRACE,
      45             :     HTTPMETHOD_PATCH,
      46             :     HTTPMETHOD_INVALID
      47             : } HTTPMethod_t;
      48             : 
      49             : typedef struct HTTPHeaders_s {
      50             :     struct HTTPHeaders_s* next;
      51             :     char* name;
      52             :     char* value;
      53             : } HTTPHeaders_t;
      54             : 
      55             : typedef struct HTTP_s {
      56             :     HTTPHeaders_t* headers;
      57             :     char* body;
      58             : } HTTP_t;
      59             : 
      60           0 : HTTP_t* HTTP_new() {
      61             :     HTTP_t* retval;
      62             : 
      63           0 :     if (NULL==(retval=malloc(sizeof(struct HTTP_s)))) {
      64           0 :         perror("HTTP_new");
      65           0 :         exit(EXIT_FAILURE);
      66             :     }
      67             : 
      68           0 :     if (NULL==(retval->headers=malloc(sizeof(struct HTTPHeaders_s)))) {
      69           0 :         perror("HTTP_new headers initialization");
      70           0 :         exit(EXIT_FAILURE);
      71             :     }
      72           0 :     retval->headers->next = NULL;
      73           0 :     retval->headers->name = NULL;
      74           0 :     retval->headers->value = NULL;
      75             : 
      76           0 :     if (NULL==(retval->body=malloc(1))) {
      77           0 :         perror("HTTP_new empty body allocation");
      78           0 :         exit(EXIT_FAILURE);
      79             :     };
      80           0 :     retval->body[0]=0;
      81             : 
      82           0 :     return retval;
      83             : }
      84             : 
      85           0 : void HTTP_addheader(HTTP_t* http, const char* name, const char* value) {
      86             :     HTTPHeaders_t* headers;
      87             : 
      88           0 :     assert(http);
      89           0 :     assert(http->headers);
      90           0 :     assert(http->body);
      91             : 
      92           0 :     if (NULL==(headers=malloc(sizeof(struct HTTPHeaders_s)))) {
      93           0 :         perror("HTTP_addheader");
      94           0 :         exit(EXIT_FAILURE);
      95             :     }
      96           0 :     if (NULL==(headers->name=malloc(strlen(name)+1))) {
      97           0 :         perror("HTTP_addheader name malloc");
      98           0 :         exit(EXIT_FAILURE);
      99             :     }
     100           0 :     strcpy(headers->name,name);
     101           0 :     if (NULL==(headers->value=malloc(strlen(value)+1))) {
     102           0 :         perror("HTTP_addheader value malloc");
     103           0 :         exit(EXIT_FAILURE);
     104             :     }
     105           0 :     strcpy(headers->value,value);
     106           0 :     headers->next = http->headers;
     107           0 :     http->headers = headers;
     108           0 : }
     109             : 
     110           0 : char* HTTP_getheaders(const HTTP_t* http) {
     111             :     HTTPHeaders_t* headers;
     112             :     char* retval;
     113             : 
     114           0 :     assert(http);
     115           0 :     assert(http->headers);
     116           0 :     assert(http->body);
     117             : 
     118           0 :     if (NULL==(retval=malloc(1))) {
     119           0 :         perror("HTTP_getheaders initial malloc");
     120           0 :         exit(EXIT_FAILURE);
     121             :     };
     122           0 :     retval[0]=0;
     123           0 :     for (headers=http->headers; headers; headers=headers->next) {
     124           0 :         if (headers->name && headers->value) {
     125             :             char* newretval;
     126           0 :             if (NULL==(newretval=realloc(retval,strlen(retval)+strlen(headers->name)+2+strlen(headers->value)+2+1))) {
     127           0 :                 perror("HTTP_getheaders inner loop");
     128           0 :                 exit(EXIT_FAILURE);
     129             :             }
     130           0 :             retval=newretval;
     131           0 :             strcat(retval,headers->name);
     132           0 :             strcat(retval,": ");
     133           0 :             strcat(retval,headers->value);
     134           0 :             strcat(retval,"\r\n");
     135             :         }
     136             :     }
     137           0 :     return retval;
     138             : }
     139             : 
     140           0 : void HTTP_del(HTTP_t* http) {
     141             :     HTTPHeaders_t* headers_it;
     142           0 :     assert(http);
     143           0 :     assert(http->headers);
     144           0 :     assert(http->body);
     145             : 
     146           0 :     while (NULL!=(headers_it=http->headers)) {
     147           0 :         http->headers=http->headers->next;
     148           0 :         if (headers_it->name)
     149           0 :             free(headers_it->name);
     150           0 :         if (headers_it->value)
     151           0 :             free(headers_it->value);
     152           0 :         free(headers_it);
     153             :     }
     154           0 :     free(http->body);
     155           0 :     free(http);
     156           0 : }
     157             : 
     158           0 : char* HTTP_getrequest(const HTTPMethod_t method, const char* uri, const HTTPVersion_t version) {
     159             :     char* retval;
     160             : 
     161           0 :     assert(method<=HTTPMETHOD_INVALID);
     162           0 :     assert(version<=HTTPVERSION_INVALID);
     163             : 
     164           0 :     if (NULL==(retval=malloc(7+1+strlen(uri)+1+8+1))) {
     165           0 :         perror("HTTP_getrequest");
     166           0 :         exit(EXIT_FAILURE);
     167             :     }
     168           0 :     retval[0]=0;
     169             : 
     170           0 :     switch(method) {
     171           0 :     case HTTPMETHOD_GET:
     172           0 :         strcat(retval, "GET");
     173           0 :         break;;
     174           0 :     case HTTPMETHOD_HEAD:
     175             :     case HTTPMETHOD_POST:
     176             :     case HTTPMETHOD_PUT:
     177             :     case HTTPMETHOD_DELETE:
     178             :     case HTTPMETHOD_CONNECT:
     179             :     case HTTPMETHOD_OPTIONS:
     180             :     case HTTPMETHOD_TRACE:
     181             :     case HTTPMETHOD_PATCH:
     182             :     case HTTPMETHOD_INVALID:
     183             :     default:
     184           0 :         fprintf(stderr,"HTTP method not supported\n");
     185           0 :         exit(EXIT_FAILURE);
     186             :         break;;
     187             :     }
     188           0 :     strcat(retval," ");
     189             : 
     190             :     /* NULL URI allowed, as an empty string */
     191           0 :     if (uri)
     192           0 :         strcat(retval, uri);
     193             : 
     194           0 :     strcat(retval," HTTP/");
     195           0 :     switch(version) {
     196           0 :     case HTTPVERSION_HTTP11:
     197             :     case HTTPVERSION_HTTP11b:
     198           0 :         strcat(retval, "1.1");
     199           0 :         break;;
     200           0 :     case HTTPVERSION_HTTP09:
     201             :     case HTTPVERSION_HTTP10:
     202             :     case HTTPVERSION_HTTP2:
     203             :     case HTTPVERSION_HTTP3:
     204             :     case HTTPVERSION_INVALID:
     205             :     default:
     206           0 :         fprintf(stderr,"HTTP version not supported\n");
     207           0 :         exit(EXIT_FAILURE);
     208             :         break;;
     209             :     }
     210           0 :     strcat(retval, "\r\n");
     211           0 :     return retval;
     212             : }
     213             : 
     214           0 : void HTTP_setbody(HTTP_t* http, const char* body) {
     215             :     char* newbody;
     216             : 
     217           0 :     assert(http);
     218           0 :     assert(http->body);
     219             : 
     220           0 :     if (NULL==(newbody=realloc(http->body,strlen(body)+1))) {
     221           0 :         perror("HTTP_setbody");
     222           0 :         exit(EXIT_FAILURE);
     223             :     }
     224             : 
     225           0 :     http->body = newbody;
     226           0 :     strcpy(http->body, body);
     227           0 : }
     228             : 
     229           0 : char* HTTP_getbody(HTTP_t* http) {
     230           0 :     assert(http);
     231           0 :     assert(http->body);
     232             : 
     233           0 :     return http->body;
     234             : }

Generated by: LCOV version 1.16