1

I am trying to make a http get request with my rasberry pi pico w using the IWip client libary, I was trying to have the TCPIPSERVER dns name as an attribute of the object but that wasnt working so I currently have it hard coded into the function, however if I uncomment the line with convert the TCPIPSERVER dns name from a string to a char* the http get request always has a timeout error. Below are the header file with the actual object and the main file that I am using

//$header$
//-------------------------------------------------------------------------------------------------------------
//                      ClsHTTPGet
//-------------------------------------------------------------------------------------------------------------
// FCC:     FLight Control Computer
//
// **legal**
// Author : "" Modified by Christopher Stevens 
// Created: 03/05/2023
/**
 * @brief This class provides an HTTP GET method to access data from a website
 * 
 * @note  Max buffer size is 2000 - If there is more data on the website than this memory could be overwritten
 */
//-------------------------------------------------------------------------------------------------------------



//#############################################################################################################
// Start Of Version History 
//#############################################################################################################



//-------------------------------------------------------------------------------------------------------------
#define Modified_Cls_HTTP_Get_Version_1 . 00
//03/05/2023
//-------------------------------------------------------------------------------------------------------------
/**
 * Inital Version 
*/
//-------------------------------------------------------------------------------------------------------------
#define Modified_Cls_HTTP_Get_Version_1 . 01
// 04/05/2023
//-------------------------------------------------------------------------------------------------------------
/**
 * @note added destructor method to class in order to free the allocated memory of the HTTPBuffer
*/
//-------------------------------------------------------------------------------------------------------------


//#############################################################################################################
// End Of Version History 
//#############################################################################################################



//-------------------------------------------------------------------------------------------------------------
#ifndef Modified_Cls_HTTP_Get
#define Modified_Cls_HTTP_Get

    #include <string>
    #include <stdio.h>
    #include <iostream>
    #include <cstring>
    #include "pico/stdlib.h"
    #include "pico/cyw43_arch.h"
    #include "lwip/apps/http_client.h"

//-------------------------------------------------------------------------------------------------------------
//      Class 1
//  ClsHTTPGet
// Allows the user to make a HTTP Get Request by calling the public method HTTP_Request
//-------------------------------------------------------------------------------------------------------------


    class ClsHTTPGet 
    {


//-------------------------------------------------------------------------------------------------------------
//      Public Function 1 
//  ClsHTTPGet
// Constructor method - used to declare and intiliase private attributes 
/**
 * @note - takes no parameters and returns no value (currently)
*/
//-------------------------------------------------------------------------------------------------------------
 


        public:
                ClsHTTPGet()
                {
                    bodyReceived = false;
                    std::strcpy(URL , "");
                    myHTTPPORT = 0;
                    //strcpy(myTCPIPSERVER , '\0');
                }



//-------------------------------------------------------------------------------------------------------------
//      Public Function 2
//  URLSetter
// used to set the URL for the specific object
/**
 * @param newURL - takes the new URL as a char* not string 
 * @note max size for URL 48 (maybe need to change)
*/
//-------------------------------------------------------------------------------------------------------------
        
        
                void URLSetter(char* newURL)
                {
                    std::strcpy(URL, newURL);
                }



//-------------------------------------------------------------------------------------------------------------
//      Public Function 3
//  MyTCPIPSEVERSetter
// used to Set the myTCPIPSEVER attribute for the specific object 
/**
 * @param newTCPIPSERVER - std::string containing new DNS name 
 * @note - no return value (void function)
*/
//-------------------------------------------------------------------------------------------------------------

            void MyTCPIPSERVERSetter(std::string newTCPIPSERVER)
            {
                myTCPIPSERVER = newTCPIPSERVER;
            }



//-------------------------------------------------------------------------------------------------------------
//      Public Function 4
//  MyTCPIPSEVERSetter
// used to Set the myTCPIPSEVER attribute for the specific object 
/**
 * @param newTCPIPSERVER - std::string containing new DNS name 
 * @note - no return value (void function)
*/
//-------------------------------------------------------------------------------------------------------------



            void MyHTTPPORTSetter(int newHTTPPORT)
            {
                myHTTPPORT = newHTTPPORT;
            }


//-------------------------------------------------------------------------------------------------------------
//      Public Function 5
//  HTTPBufferGetter
// used to get the HTTPBuffer for the specific object
/**
 * @return - HTTPBuffer as a char* not string
 * @note max size for HTTPBUffer is 2000
 * @note buffer is null-terminated 
*/
//-------------------------------------------------------------------------------------------------------------
        

                char* HTTPBufferGetter()
                {
                    return HTTPBuffer;
                }


//-------------------------------------------------------------------------------------------------------------
//      Public Function 6
//  HTTPRequest
// used to perform a HTTP Get request to the specific URL that is an attribute of the object
/**
 * @return - 0 if no error occured or 1 if a error occured 
 * @note - no parameters taken values can be changed through setter methods 
 * @note - max size for recieved data is 2000 
 * @note - can be slow so should be performed before performance-critical operation are needing to be executed
 * @note - this method will call private methods within the class in order to complete the HTTP Get Request 
*/
//-------------------------------------------------------------------------------------------------------------
            int HTTP_Request()
            {


                //printf("%s \n" , myTCPIPSERVER);
                printf("%d \n" , myHTTPPORT);
                printf("%s \n" , URL);
                httpc_connection_t settings;
                settings.result_fn = &result;
                settings.headers_done_fn = headers;

                char* CharMyTCPIPSERVER = new char[myTCPIPSERVER.length() + 1];
                //std::strncpy(CharMyTCPIPSERVER, myTCPIPSERVER.c_str() , 30); //######  breaks the code if enabled idk how or why
                //printf("%s \n" , CharMyTCPIPSERVER);
                char myTCPIPSEVER2[27] = "LAUNCHCONTROL.rocket.local";
                //if(CharMyTCPIPSERVER == myTCPIPSEVER2)
                //{
                //   printf("my mind is broken \n");
                //}
                err_t err = httpc_get_file_dns(
                        myTCPIPSEVER2,
                        myHTTPPORT,
                        URL,
                        &settings,
                        body,
                        this,
                        NULL
                );
                bodyReceived = false;
                printf("status %d \n", err);
                while (!bodyReceived) 
                {
                    sleep_ms(500);
                }
                sleep_ms(1000);
                free(CharMyTCPIPSERVER);
                return 0;
            }






//-------------------------------------------------------------------------------------------------------------
//      Public Method 7 
//   ~ClsHTTPGet
// used to destruct the object once used 
/**
 * @note - destructor for the class
 * @note - free the memory allocated for the HTTPBuffer 
*/
//-------------------------------------------------------------------------------------------------------------


            ~ClsHTTPGet()
            {
                free(HTTPBuffer);
            }


//-------------------------------------------------------------------------------------------------------------
// End Of Public Methods
//-------------------------------------------------------------------------------------------------------------



        private:

//-------------------------------------------------------------------------------------------------------------
//      Private Attributes
// HTTPBuffer - used to store the data recieved from the HTTP request
// bodyReceived - used by private methods to verify the data from the HTTP request has been recieved
// URL - the url that the HTTP request is made on
// myTCPIPSERVER - holds the DNS name for the TCP/IP Server request will be sent to
// myHTTPPORT - holds the port number http request will be made over 
//-------------------------------------------------------------------------------------------------------------


            char* HTTPBuffer = (char*) malloc(2000);
            bool bodyReceived;
            char URL[48];
            std::string myTCPIPSERVER = "LAUNCHCONTROL.rocket.local";
            int myHTTPPORT;

//-------------------------------------------------------------------------------------------------------------
//      Private Method 1 
//-------------------------------------------------------------------------------------------------------------

            static void result(void *arg, httpc_result_t httpc_result,
            u32_t rx_content_len, u32_t srv_res, err_t err)
            {
                printf(">>> result_fn >>>\n");
                printf("httpc_result: %s\n",
                        httpc_result == HTTPC_RESULT_OK              ? "HTTPC_RESULT_OK"
                    : httpc_result == HTTPC_RESULT_ERR_UNKNOWN     ? "HTTPC_RESULT_ERR_UNKNOWN"
                    : httpc_result == HTTPC_RESULT_ERR_CONNECT     ? "HTTPC_RESULT_ERR_CONNECT"
                    : httpc_result == HTTPC_RESULT_ERR_HOSTNAME    ? "HTTPC_RESULT_ERR_HOSTNAME"
                    : httpc_result == HTTPC_RESULT_ERR_CLOSED      ? "HTTPC_RESULT_ERR_CLOSED"
                    : httpc_result == HTTPC_RESULT_ERR_TIMEOUT     ? "HTTPC_RESULT_ERR_TIMEOUT"
                    : httpc_result == HTTPC_RESULT_ERR_SVR_RESP    ? "HTTPC_RESULT_ERR_SVR_RESP"
                    : httpc_result == HTTPC_RESULT_ERR_MEM         ? "HTTPC_RESULT_ERR_MEM"
                    : httpc_result == HTTPC_RESULT_LOCAL_ABORT     ? "HTTPC_RESULT_LOCAL_ABORT"
                    : httpc_result == HTTPC_RESULT_ERR_CONTENT_LEN ? "HTTPC_RESULT_ERR_CONTENT_LEN"
                    : "*UNKNOWN*");
                printf("received %ld bytes\n", rx_content_len);
                printf("server response: %ld\n", srv_res);
                printf("err: %d\n", err);
                printf("<<< result_fn <<<\n");
            }
//-------------------------------------------------------------------------------------------------------------
//      Private method 2 
//-------------------------------------------------------------------------------------------------------------

             static err_t headers(httpc_state_t *connection, void *arg,
                         struct pbuf *hdr, u16_t hdr_len, u32_t content_len)
            {
                printf("headers received\n");
                printf("content length=%d\n", content_len);
                printf("header length %d\n", hdr_len);
                pbuf_free(hdr);
                return ERR_OK;
            }

//-------------------------------------------------------------------------------------------------------------
//      Private method 3
//-------------------------------------------------------------------------------------------------------------

            static err_t body(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err)
            {
                ClsHTTPGet *self = (ClsHTTPGet *) arg;
                printf("The body is tot_len: %d\n", p->len);
                printf(">>> body >>>\n");
                pbuf_copy_partial(p, self->HTTPBuffer, p->tot_len, 0);
                printf("%s", self->HTTPBuffer);
                self->bodyReceived = true;
                printf("<<< body <<<\n");
                return ERR_OK;
            }

//-------------------------------------------------------------------------------------------------------------
//      End Of private methods
//-------------------------------------------------------------------------------------------------------------

    };

#endif


#include "ClsHTTPGet.h"
#include "WiFiConnect.h"
#include <iostream>
#include <cassert>
    int main(){
    stdio_init_all();
    sleep_ms(1000); // allow time to ensure usb or Uart conection established
    {
        if (ConnectWifi()){
            std::cout<< "sucessful connection \n";
        }
        else{
            std::cout << "error \n";
        }
    }
    {
        ClsHTTPGet InitalCommuication;
        {
            char URLForInitalCommunication[48] = "/CheckCommunication.php?MyStatus=ReadyToProceed"; // set the attributes of the object 
            InitalCommuication.URLSetter(URLForInitalCommunication);
            InitalCommuication.MyHTTPPORTSetter(HTTPPORT);
            InitalCommuication.MyTCPIPSERVERSetter(std::string(TCPIPSERVER)); // breaks it
        }

        InitalCommuication.HTTP_Request();
        printf("%s \n" , InitalCommuication.HTTPBufferGetter());
        const char expectedValue[7] = "Copy\r\n"; // what should be recieved from the HTTP Get request (note \r\n is from the http get request formatting rather htan the PhP itself)
        if (strcmp(expectedValue , InitalCommuication.HTTPBufferGetter() ) == 0){
            printf("\n done \n");

        }
        else{
            printf("failed \n");
        }
        InitalCommuication.~ClsHTTPGet(); // destruct the class as no longer neeed
        // better to call the destructor rather than reply on the compiler removing the object due to being outside the scope due to dynamic memory allocation
    }
    return 0;
}

I would expect the http get request to have the same outcome whether the line is uncommented or not (in the public function 6 )

Chris22
  • 21
  • 3
  • There is no `strcpy` (not even commented) in "public function 5". Please [edit] and clarify. – Jabberwocky May 05 '23 at 14:05
  • please show a [mre] – Alan Birtles May 05 '23 at 14:05
  • Do you mean the `//strcpy(myTCPIPSERVER , '\0');` in `ClsHTTPGet()`? There are two errors in this line: 1: `myTCPIPSERVER` is a `std::string` and you cannot use `std::strcpy` to copy into a `std::string`. 2: `'\0'` is a `char` but the second parameter of `strcpy` must be a `const char*`. For this reason alone your code cannot compile let alone run. What you need is `myTCPIPSERVER = ""` instead of `strcpy(myTCPIPSERVER , '\0')`, but probbaly `myTCPIPSERVER` is already an empty string beforehand (I'm not quite sure, because you didn't show the relevant code), and therefore it's not necessary. – Jabberwocky May 05 '23 at 14:12
  • OT: there are other problems too: For example all this `CharMyTCPIPSERVER` stuff looks utterly useless and over complicated, are you looking for [`std::string::c_str()`](https://cplusplus.com/reference/string/string/c_str/)? Also you cannot use `free` for memory allocated via `new`, you need to use `delete`. – Jabberwocky May 05 '23 at 14:20

0 Answers0