Statistics
| Branch: | Revision:

peerstreamer-src / src / router.c @ 9eb656e7

History | View | Annotate | Download (3.14 KB)

1 9eb656e7 Luca Baldesi
/*******************************************************************
2
* PeerStreamer-ng is a P2P video streaming application exposing a ReST
3
* interface.
4
* Copyright (C) 2016 Luca Baldesi <luca.baldesi@unitn.it>
5
*
6
* This program is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Affero General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU Affero General Public License for more details.
15
*
16
* You should have received a copy of the GNU Affero General Public License
17
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*******************************************************************/
19
20
#include<regex.h>
21
22
#include "router.h"
23
24
#define HTTP_MAX_METHOD_LENGTH 10
25
26
struct route {
27
        char method[HTTP_MAX_METHOD_LENGTH];
28
        regex_t path;
29
        http_handle_t handler;
30
};
31
32
uint8_t route_init(struct route * r, const char * method, const char * regex, http_handle_t handler)
33
{
34
        uint8_t res = 0; 
35
36
        if(r && method && regex &&  handler)
37
        {
38
                 if (regcomp(&r->path, regex, REG_EXTENDED) == 0)
39
                {
40
                        strncpy(r->method, method, HTTP_MAX_METHOD_LENGTH);
41
                        r->method[HTTP_MAX_METHOD_LENGTH - 1] = '\0';
42
                        r->handler = handler;
43
                }
44
        } else
45
                res = 1;
46
        return res;
47
}
48
49
void route_deinit(struct route * r)
50
{
51
        regfree(&r->path);
52
}
53
54
struct router {
55
        struct route * routes;
56
        uint32_t route_num;
57
        uint32_t route_max;
58
};
59
60
void router_destroy(struct router ** r)
61
{
62
        uint32_t i;
63
64
        if(r && *r)
65
        {
66
                if((*r)->routes)
67
                {
68
                        for(i = 0; i < (*r)->route_num; i++)
69
                                route_deinit(&((*r)->routes[i]));
70
                        free((*r)->routes);
71
                }
72
                free(*r);
73
                *r = NULL;
74
        }
75
}
76
77
struct router * router_create(uint32_t size)
78
{
79
        struct router * r;
80
        r = malloc(sizeof(struct router));
81
        if (r)
82
        {
83
                r->route_num = 0;
84
                r->route_max = size;
85
                r->routes = malloc(sizeof(struct route) * r->route_max);
86
                if (!r->routes)
87
                        router_destroy(&r);
88
        }
89
        return r;
90
}
91
92
uint8_t router_add_route(struct router *r, const char * method, const char * regex, http_handle_t handler)
93
{
94
        uint8_t res = 0;
95
96
        if (r && r->route_num >= r->route_max)
97
        {
98
                r->route_max = r->route_max ? r->route_max * 2 : 2;
99
                r->routes = realloc(r->routes, sizeof(struct route) * r->route_max);
100
        }
101
102
        if (r && r->routes)
103
        {
104
                res = route_init(&(r->routes[r->route_num]), method, regex, handler);
105
                if(res == 0)
106
                        r->route_num++;
107
        }
108
        else
109
                res = 1;
110
111
        return res;
112
}
113
114
char * mg_str2str(const struct mg_str * s)
115
{
116
        char * p;
117
118
        p = malloc(s->len + 1);
119
        strncpy(p, s->p, s->len);
120
        p[s->len] = '\0';
121
        return p;
122
}
123
124
uint8_t router_handle(const struct router * r, struct mg_connection *nc, struct http_message *hm)
125
{
126
        uint32_t i = 0, res = 1;
127
        char * str;
128
129
        if(hm && r)
130
        {
131
                while (res && i < r->route_num)
132
                {
133
                        if(mg_vcmp(&hm->method, r->routes[i].method) == 0)
134
                        {
135
                                str = mg_str2str(&hm->uri);
136
                                if(regexec(&(r->routes[i].path), str, 0, NULL, 0) == 0)
137
                                {
138
                                        res = 0;
139
                                        r->routes[i].handler(nc, hm);
140
                                }
141
                                free(str);
142
                        }
143
                        i++;
144
                }
145
        }
146
        return res;
147
}