summaryrefslogtreecommitdiff
path: root/service/src/http_serv.c
blob: 1e4017cd90e06c835227c598dc533e44c4aca4c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <assert.h>
#include <rte_graph.h>
#include <rte_malloc.h>
#include <stdio.h>

#include <MESA_prof_load.h>
#include <cJSON.h>
#include <common.h>
#include <sc_common.h>
#include <sc_vdev.h>

#include <event2/buffer.h>
#include <event2/event.h>
#include <event2/http.h>

struct http_serv_main
{
    struct event_base * ev_base;
    struct evhttp * ev_http;
    pthread_t ev_dispatch_tid;
};

/* config example:
 * [:0]
 * name = olp0
 * type = niagara_3296
 * serial_number = 12345678abcdefgh
 *
 * [olp_channel:0]
 * device = olp0
 * state = 3
 * watchdog = 1
 * watchdog_kick_time_in_ms = 300
 * watchdog_timeout_in_ms = 600
 */

/* liveness probe callback */
static void http_serv_probe_cb(struct evhttp_request * req, void * arg)
{
    struct evbuffer * evb = evbuffer_new();
    if (!evb)
    {
        MR_ERROR("failed to create response buffer");
        return;
    }

    evbuffer_add_printf(evb, "Probe successfully, MRZCPD is running.");
    evhttp_send_reply(req, HTTP_OK, "OK", evb);
    evbuffer_free(evb);
}

/* event_base dispatch thread */
static void * http_serv_dispatch(void * arg)
{
    struct event_base * base = (struct event_base *)arg;
    event_base_dispatch(base);
    return NULL;
}

int http_serv_deinit(struct sc_main * sc_main)
{
    struct http_serv_main * ht_server_main = sc_main->ht_server_main;
    assert(ht_server_main != NULL);

    /* stop event_base dispatch thread */
    event_base_loopexit(ht_server_main->ev_base, NULL);
    pthread_join(ht_server_main->ev_dispatch_tid, NULL);

    /* release all ctx */
    evhttp_free(ht_server_main->ev_http);
    event_base_free(ht_server_main->ev_base);

    /* free http_serv_main */
    FREE(ht_server_main);
    return 0;
}

int http_serv_init(struct sc_main * sc_main)
{
    struct http_serv_main * http_server_main = ZMALLOC(sizeof(struct http_serv_main));
    MR_VERIFY_MALLOC(http_server_main);

    struct event_config * cfg = event_config_new();
    struct event_base * base = event_base_new_with_config(cfg);
    if (!base)
    {
        MR_ERROR("Couldn't create an event_base.");
        goto errout;
    }

    event_config_free(cfg);
    cfg = NULL;

    /* Create a new evhttp object to socket requests. */
    struct evhttp * http = evhttp_new(base);
    if (!http)
    {
        MR_ERROR("couldn't create evhttp. Exiting.\n");
        goto errout;
    }

    /* The /dump URI will dump all requests to stdout and say 200 ok. */
    evhttp_set_cb(http, "/probe", http_serv_probe_cb, (void *)http_server_main);

    /* Load the listen address and port */
    char str_listen_addr[INET6_ADDRSTRLEN] = {};
    MESA_load_profile_string_def(sc_main->local_cfgfile, "http_server", "listen_addr", str_listen_addr,
                                 sizeof(str_listen_addr), "::");

    unsigned int listen_port = 9086;
    MESA_load_profile_uint_def(sc_main->local_cfgfile, "http_server", "listen_port", &listen_port, 9086);

    struct evhttp_bound_socket * socket = evhttp_bind_socket_with_handle(http, str_listen_addr, listen_port);
    if (!socket)
    {
        MR_ERROR("couldn't bind to %s:%d.", str_listen_addr, listen_port);
        goto errout;
    }

    /* create a thread to do the event_base dispatch */
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, http_serv_dispatch, base);
    if (ret != 0)
    {
        MR_ERROR("failed to create thread for event_base dispatch: %s", strerror(ret));
        goto errout;
    }

    /* save the event_base, ev_http handles to http_serv_main */
    http_server_main->ev_base = base;
    http_server_main->ev_http = http;
    http_server_main->ev_dispatch_tid = tid;

    sc_main->ht_server_main = http_server_main;
    MR_INFO("HTTP Server is listening on %s:%u", str_listen_addr, listen_port);
    return 0;

errout:
    return -1;
}