LCOV - code coverage report
Current view: top level - src - libhttp.c (source / functions) Hit Total Coverage
Test: mkernel.info Lines: 81 105 77.1 %
Date: 2024-11-19 21:56:46 Functions: 7 7 100.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 21:50
      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             : #include "sclist.h"
      21             : 
      22             : #include <stdlib.h>
      23             : #include <stdio.h>
      24             : #include <string.h>
      25             : #include <assert.h>
      26             : 
      27             : typedef struct HTTPHeaders_s {
      28             :     char* name;
      29             :     char* value;
      30             : } HTTPHeaders_t;
      31             : 
      32             : typedef struct HTTP_s {
      33             :     sclist_t* headers;
      34             :     char* body;
      35             : } HTTP_t;
      36             : 
      37           3 : HTTP_t* HTTP_new() {
      38             :     HTTP_t* retval;
      39             : 
      40           3 :     if (NULL==(retval=malloc(sizeof(struct HTTP_s)))) {
      41           0 :         perror("HTTP_new");
      42           0 :         exit(EXIT_FAILURE);
      43             :     }
      44             : 
      45           3 :     retval->headers = sclist_new();
      46             : 
      47           3 :     if (NULL==(retval->body=malloc(1))) {
      48           0 :         perror("HTTP_new empty body allocation");
      49           0 :         exit(EXIT_FAILURE);
      50             :     };
      51           3 :     retval->body[0]=0;
      52             : 
      53           3 :     return retval;
      54             : }
      55             : 
      56           3 : void HTTP_addheader(HTTP_t* http, const char* name, const char* value) {
      57             :     HTTPHeaders_t* headers;
      58             : 
      59           3 :     assert(http);
      60           3 :     assert(http->headers);
      61           3 :     assert(http->body);
      62             : 
      63           3 :     if (NULL==(headers=malloc(sizeof(struct HTTPHeaders_s)))) {
      64           0 :         perror("HTTP_addheader");
      65           0 :         exit(EXIT_FAILURE);
      66             :     }
      67           3 :     if (NULL==(headers->name=malloc(strlen(name)+1))) {
      68           0 :         perror("HTTP_addheader name malloc");
      69           0 :         exit(EXIT_FAILURE);
      70             :     }
      71           3 :     strcpy(headers->name,name);
      72           3 :     if (NULL==(headers->value=malloc(strlen(value)+1))) {
      73           0 :         perror("HTTP_addheader value malloc");
      74           0 :         exit(EXIT_FAILURE);
      75             :     }
      76           3 :     strcpy(headers->value,value);
      77           3 :     sclist_addrecord(http->headers,headers);
      78           3 : }
      79             : 
      80           3 : char* HTTP_getheaders(const HTTP_t* http) {
      81           3 :     sclistrecord_t* current = NULL;
      82             :     char* retval;
      83             : 
      84           3 :     assert(http);
      85           3 :     assert(http->headers);
      86           3 :     assert(http->body);
      87             : 
      88           3 :     if (NULL==(retval=malloc(1))) {
      89           0 :         perror("HTTP_getheaders initial malloc");
      90           0 :         exit(EXIT_FAILURE);
      91             :     };
      92           3 :     retval[0]=0;
      93             : 
      94           3 :     current = sclist_firstrecord(http->headers);
      95           6 :     while (current) {
      96           3 :         HTTPHeaders_t* header=sclist_getvalue(current);
      97           3 :         if (header->name && header->value) {
      98             :             char* newretval;
      99           3 :             if (NULL==(newretval=realloc(retval,strlen(retval)+strlen(header->name)+2+strlen(header->value)+2+1))) {
     100           0 :                 perror("HTTP_getheaders inner loop");
     101           0 :                 exit(EXIT_FAILURE);
     102             :             }
     103           3 :             retval=newretval;
     104           3 :             strcat(retval,header->name);
     105           3 :             strcat(retval,": ");
     106           3 :             strcat(retval,header->value);
     107           3 :             strcat(retval,"\r\n");
     108             :         }
     109           3 :         current=sclist_nextrecord(current);
     110             :     }
     111           3 :     return retval;
     112             : }
     113             : 
     114           3 : void HTTP_del(HTTP_t* http) {
     115             :     sclistrecord_t* current;
     116             : 
     117           3 :     assert(http);
     118           3 :     assert(http->headers);
     119           3 :     assert(http->body);
     120             : 
     121           3 :     current = sclist_firstrecord(http->headers);
     122           6 :     while (current) {
     123           3 :         HTTPHeaders_t* header=sclist_getvalue(current);
     124           3 :         if (header->name)
     125           3 :             free(header->name);
     126           3 :         if (header->value)
     127           3 :             free(header->value);
     128           3 :         current = sclist_nextrecord(current);
     129             :     }
     130             : 
     131           3 :     free(http->body);
     132           3 :     free(http);
     133           3 : }
     134             : 
     135           3 : char* HTTP_getrequest(const HTTPMethod_t method, const char* uri, const HTTPVersion_t version) {
     136             :     char* retval;
     137             : 
     138           3 :     assert(method<=HTTPMETHOD_INVALID);
     139           3 :     assert(version<=HTTPVERSION_INVALID);
     140             : 
     141           3 :     if (NULL==(retval=malloc(7+1+strlen(uri)+1+8+1))) {
     142           0 :         perror("HTTP_getrequest");
     143           0 :         exit(EXIT_FAILURE);
     144             :     }
     145           3 :     retval[0]=0;
     146             : 
     147           3 :     switch(method) {
     148           3 :     case HTTPMETHOD_GET:
     149           3 :         strcat(retval, "GET");
     150           3 :         break;;
     151           0 :     case HTTPMETHOD_HEAD:
     152             :     case HTTPMETHOD_POST:
     153             :     case HTTPMETHOD_PUT:
     154             :     case HTTPMETHOD_DELETE:
     155             :     case HTTPMETHOD_CONNECT:
     156             :     case HTTPMETHOD_OPTIONS:
     157             :     case HTTPMETHOD_TRACE:
     158             :     case HTTPMETHOD_PATCH:
     159             :     case HTTPMETHOD_INVALID:
     160             :     default:
     161           0 :         fprintf(stderr,"HTTP method not supported\n");
     162           0 :         exit(EXIT_FAILURE);
     163             :         break;;
     164             :     }
     165           3 :     strcat(retval," ");
     166             : 
     167             :     /* NULL URI allowed, as an empty string */
     168           3 :     if (uri)
     169           3 :         strcat(retval, uri);
     170             : 
     171           3 :     strcat(retval," HTTP/");
     172           3 :     switch(version) {
     173           3 :     case HTTPVERSION_HTTP11:
     174             :     case HTTPVERSION_HTTP11b:
     175           3 :         strcat(retval, "1.1");
     176           3 :         break;;
     177           0 :     case HTTPVERSION_HTTP09:
     178             :     case HTTPVERSION_HTTP10:
     179             :     case HTTPVERSION_HTTP2:
     180             :     case HTTPVERSION_HTTP3:
     181             :     case HTTPVERSION_INVALID:
     182             :     default:
     183           0 :         fprintf(stderr,"HTTP version not supported\n");
     184           0 :         exit(EXIT_FAILURE);
     185             :         break;;
     186             :     }
     187           3 :     strcat(retval, "\r\n");
     188           3 :     return retval;
     189             : }
     190             : 
     191           3 : void HTTP_setbody(HTTP_t* http, const char* body) {
     192             :     char* newbody;
     193             : 
     194           3 :     assert(http);
     195           3 :     assert(http->body);
     196             : 
     197           3 :     if (NULL==(newbody=realloc(http->body,strlen(body)+1))) {
     198           0 :         perror("HTTP_setbody");
     199           0 :         exit(EXIT_FAILURE);
     200             :     }
     201             : 
     202           3 :     http->body = newbody;
     203           3 :     strcpy(http->body, body);
     204           3 : }
     205             : 
     206           3 : char* HTTP_getbody(HTTP_t* http) {
     207           3 :     assert(http);
     208           3 :     assert(http->body);
     209             : 
     210           3 :     return http->body;
     211             : }

Generated by: LCOV version 1.16