Statistics
| Branch: | Revision:

peerstreamer-src / src / path_handlers.c @ 58fb2cdc

History | View | Annotate | Download (9.02 KB)

1
/*******************************************************************
2
* PeerStreamer-ng is a P2P video streaming application exposing a ReST
3
* interface.
4
* Copyright (C) 2015 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<stdint.h>
21
#include<pschannel.h>
22
#include<router.h>
23
#include<tokens.h>
24
#include<name_lengths.h>
25
#include<debug.h>
26
#include<pschannel.h>
27
#include<context.h>
28
#include<mongoose.h>
29
#include<streamer_creation_callback.h>
30

    
31
char * mg_uri_field(struct http_message *hm, uint8_t pos)
32
{
33
        char * uri;
34
        char ** tokens;
35
        uint32_t ntok;
36

    
37
        uri = malloc((hm->uri.len + 1) * sizeof(char));
38
        strncpy(uri, hm->uri.p, hm->uri.len);
39
        uri[hm->uri.len] = '\0';
40

    
41
        tokens = tokens_create(uri, '/', &ntok);
42
        
43
        strcpy(uri, tokens[pos]);
44
        tokens_destroy(&tokens, ntok);
45

    
46
        return uri;
47
}
48

    
49
void channel_index(struct mg_connection *nc, struct http_message *hm)
50
{
51
        char * channels;
52
        const struct context * c;
53

    
54
        c = (const struct context *) nc->user_data;
55

    
56
        info("GET request for channels\n");
57
        channels = pschannel_bucket_to_json(c->pb);
58
        debug("\t%s\n", channels);
59

    
60
        mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
61
        mg_printf_http_chunk(nc, "%s", channels);
62
        mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
63

    
64
        free(channels);
65
}
66

    
67
int8_t source_streamer_creation_handler(struct mg_connection *nc, const struct pschannel_bucket *psb, const struct pstreamer * ps, int8_t ret)
68
{
69
        char * json = NULL;
70
        int8_t res = -1;
71

    
72
        info("Inside source creation handler\n");
73
        if (ps)
74
                json = pstreamer_to_json(ps);
75

    
76
        if (ret == 0 && json)
77
        {
78
                mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
79
                mg_printf_http_chunk(nc, json);
80
                res = 0;
81
                info("Source room created and served\n");
82
        } else {
83
                mg_printf(nc, "%s", "HTTP/1.1 500 Internal server error\r\nTransfer-Encoding: chunked\r\n\r\n");
84
                // destroy ps?
85
                info("Stream room cannot be correctly created\n");
86
                if (ret)
87
                        debug(json);
88
                else
89
                        debug("PS does not exist");
90
        }
91
        if (json)
92
                free(json);
93
        mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
94

    
95
        return res;
96
}
97

    
98
int8_t streamer_creation_handler(struct mg_connection *nc, const struct pschannel_bucket *psb, const struct pstreamer * ps, int8_t ret)
99
{
100
        char * json = NULL;
101
        int8_t res = -1;
102
        const struct pschannel * ch = NULL;
103

    
104
        info("Inside creation handler\n");
105
        if (ps)
106
        {
107
                ch = pschannel_bucket_find(psb, pstreamer_source_ipaddr(ps), pstreamer_source_port(ps));
108
                json = pstreamer_to_json(ps);
109
                if (ch)
110
                        json[strlen(json)-1] = '\0';
111
        }
112

    
113
        if (ret == 0 && json)
114
        {
115
                mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
116
                mg_printf_http_chunk(nc, json);
117
                if (ch)
118
                        mg_printf_http_chunk(nc, ",\"name\":\"%s\"}", ch->name);
119
                res = 0;
120
                info("Stream created and served\n");
121
        } else {
122
                mg_printf(nc, "%s", "HTTP/1.1 500 Internal server error\r\nTransfer-Encoding: chunked\r\n\r\n");
123
                // destroy ps?
124
                info("Stream cannot be correctly served\n");
125
                if (ret)
126
                        debug(json);
127
                else
128
                        debug("PS does not exist");
129
        }
130
        if (json)
131
                free(json);
132
        mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
133

    
134
        return res;
135
}
136

    
137
void streamer_create(struct mg_connection *nc, struct http_message *hm)
138
{
139
        const struct context * c;
140
        char ipaddr[MAX_IPADDR_LENGTH];
141
        char rtp_dst_ip[MAX_IPADDR_LENGTH];
142
        char port[MAX_PORT_LENGTH];
143
        char * id;
144
        const struct pstreamer * ps = NULL;
145
        const struct pschannel * ch = NULL;
146

    
147
        c = (const struct context *) nc->user_data;
148
        mg_get_http_var(&hm->body, "ipaddr", ipaddr, MAX_IPADDR_LENGTH);
149
        mg_get_http_var(&hm->body, "port", port, MAX_PORT_LENGTH);
150

    
151
        id = mg_uri_field(hm, 1);
152
        mg_conn_addr_to_str(nc, rtp_dst_ip, MAX_IPADDR_LENGTH, MG_SOCK_STRINGIFY_IP|MG_SOCK_STRINGIFY_REMOTE);
153

    
154
        info("POST request for resource %s from %s\n", id, rtp_dst_ip);
155
        ch = pschannel_bucket_find(c->pb, ipaddr, port);
156

    
157
        if (ch)
158
        {
159
                debug("Channel: %s\n", ch->name);
160
                ps = pstreamer_manager_create_streamer(c->psm, ipaddr, port, id, rtp_dst_ip, streamer_creation_callback_new(nc, c->pb, streamer_creation_handler)); 
161
                if(ps)
162
                {
163
                        pstreamer_schedule_tasks((struct pstreamer*)ps, c->tm);
164
                        info("Streamer instance created\n");
165
                } else {
166
                        info("Streamer could not be launched\n");
167
                        mg_printf(nc, "%s", "HTTP/1.1 409 Conflict\r\nTransfer-Encoding: chunked\r\n\r\n");
168
                        mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
169
                }
170
        } else {
171
                info("No channel found for socket <%s:%s>\n", ipaddr, port);
172
                mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\nTransfer-Encoding: chunked\r\n\r\n");
173
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
174
        }
175

    
176
        free(id);
177
}
178

    
179
void streamer_update(struct mg_connection *nc, struct http_message *hm)
180
{
181
        char * id, * json;
182
        const struct pstreamer * ps;
183
        const struct context * c;
184

    
185
        c = (const struct context *) nc->user_data;
186
        id = mg_uri_field(hm, 1);
187

    
188
        ps = pstreamer_manager_get_streamer(c->psm, id);
189
        info("UPDATE request for resource %s\n", id);
190
        if (ps)
191
        {
192
                pstreamer_touch((struct pstreamer*) ps);
193
                info("\tInstance %s found and touched\n", id);
194
                json = pstreamer_to_json(ps);
195
                mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
196
                mg_printf_http_chunk(nc, "%s", json);
197
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
198
                free(json);
199
        } else {
200
                info("\tInstance %s not found\n", id);
201
                mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\nTransfer-Encoding: chunked\r\n\r\n");
202
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
203
        }
204

    
205
        free(id);
206
}
207

    
208
void source_index(struct mg_connection *nc, struct http_message *hm)
209
{
210
        char * channels;
211
        const struct context * c;
212

    
213
        c = (const struct context *) nc->user_data;
214

    
215
        info("GET request for source\n");
216
        channels = pstreamer_manager_sources_to_json(c->psm);
217
        debug("\t%s\n", channels);
218

    
219
        mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
220
        mg_printf_http_chunk(nc, "%s", channels);
221
        mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
222

    
223
        free(channels);
224
}
225

    
226
void source_streamer_create(struct mg_connection *nc, struct http_message *hm)
227
{
228
        const struct context * c;
229
        char rtp_source_ip[MAX_IPADDR_LENGTH];
230
        char * id;
231
        const struct pstreamer * ps = NULL;
232
        const struct pschannel * ch = NULL;
233

    
234
        c = (const struct context *) nc->user_data;
235

    
236
        id = mg_uri_field(hm, 1);
237
        mg_conn_addr_to_str(nc, rtp_source_ip, MAX_IPADDR_LENGTH, MG_SOCK_STRINGIFY_IP);
238

    
239
        info("POST request for source resource %s from %s\n", id, rtp_source_ip);
240

    
241
        ps = pstreamer_manager_create_source_streamer(c->psm, id, rtp_source_ip, streamer_creation_callback_new(nc, c->pb, source_streamer_creation_handler)); 
242
        if(ps)
243
        {
244
                pstreamer_schedule_tasks((struct pstreamer*)ps, c->tm);
245
                info("Source streamer instance created\n");
246
        } else {
247
                info("Source streamer could not be launched\n");
248
                mg_printf(nc, "%s", "HTTP/1.1 409 Conflict\r\nTransfer-Encoding: chunked\r\n\r\n");
249
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
250
        }
251

    
252
        free(id);
253
}
254

    
255
void source_streamer_update(struct mg_connection *nc, struct http_message *hm)
256
{
257
        char * id, * json;
258
        char janus_user_id[MAX_JANUS_USERID_LENGTH+1];
259
        const struct pstreamer * ps;
260
        const struct context * c;
261

    
262
        c = (const struct context *) nc->user_data;
263
        id = mg_uri_field(hm, 1);
264

    
265
        ps = pstreamer_manager_get_streamer(c->psm, id);
266
        janus_user_id[0] = '\0';
267
        info("UPDATE request for source resource %s\n", id);
268
        if (ps)
269
        {
270
                mg_get_http_var(&hm->body, "participant_id", janus_user_id, MAX_JANUS_USERID_LENGTH);
271

    
272
                if (strlen(janus_user_id) > 0)
273
                {
274
                        info("\tFound Participant ID: %s\n", janus_user_id);
275
                        pstreamer_source_touch(c->psm, (struct pstreamer*) ps, atoll(janus_user_id));
276
                } else
277
                        pstreamer_touch((struct pstreamer*) ps);
278

    
279
                info("\tSource instance %s found and touched\n", id);
280
                json = pstreamer_to_json(ps);
281
                mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
282
                mg_printf_http_chunk(nc, "%s", json);
283
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
284
                free(json);
285
        } else {
286
                info("\tInstance %s not found\n", id);
287
                mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\nTransfer-Encoding: chunked\r\n\r\n");
288
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
289
        }
290
        free(id);
291
}
292