cmultithreadingpthreadsmallocmongoose-web-server

malloc mongoose webserver http post body and pass it to thread


below is C snippet from mongoose webserver http event handler I am working on:

static void HttpEventHandler(struct mg_connection *nc, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_REQUEST) {
    struct http_message *hm = (struct http_message *) ev_data;
    if (mg_vcmp(&hm->method, "POST") == 0) {
        pthread_t thread_id;
        int rc;
        rc = pthread_create(&thread_id, NULL, thr_func, /* Here I want hm body to be passed after its malloced */);
        if (rc) { /* could not create thread */
            fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
            return EXIT_FAILURE;
        }
    }//if POST
    mg_printf(nc, "HTTP/1.1 200 OK\r\n");
    nc->flags |= MG_F_SEND_AND_CLOSE;
}

}

the http post message body, accessible as string using below syntax:

"%.*s", (int) hm->body.len,hm->body.p

I want code sample to malloc hm->body and pass it to the thread in snippet above, also it would be great to explain how to cast the passed void *. if its difficult then please malloc ev_data or hm.


Solution

  • You'd malloc() it as in:

        hm->body = malloc(sizeof *(hm->body));
        hm->body.p = "string"; 
        /* The above assigns a string literal. If you need to copy some
           user-defined string then you can instead do:
        hm->body = malloc(size); strcpy(hm->body.p, str); 
        where 'str' is the string you want copy and 'size' is the length of 'str'.
       */
        hm->body.len = strlen(hm->body);
    

    and then pass it to:

    rc = pthread_create(&thread_id, NULL, thr_func, hm->body);
    

    In thr_func() you would need to convert the argument to whatever the type of hm->body and then access it (because void * can't be dereferenced directly.). Something like:

    void *thr_func(void *arg)
    {
       struct mg_str *hm_body = arg;
       printf("str: %s, len: %zu\n", hm_body->p, hm_body->len);
       ...
    
       return NULL;
    }
    

    There's no need to cast anything to void*. The pthread_create() API expects a void * as the last argument and any data pointer can be directly assigned to void *. The same applies to struct http_message *hm = (struct http_message *) ev_data; statement as well. It can be just: struct http_message *hm = ev_data;.

    Depending how the "webserver" is implemented, you might need to take care of thread(s) completion as well.

    P.S: If you show the "hm" structure, it'll be much easier to explain things.