Statistics
| Branch: | Revision:

peerstreamer-src / src / path_handlers.c @ 92a361ca

History | View | Annotate | Download (5.58 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
void mg_connection_remote_ip(char * ip, const struct mg_connection *nc)
32
{
33
        const struct sockaddr_in *sender;
34
        sender = (struct sockaddr_in *)&(nc->sa);
35
        inet_ntop(AF_INET, &(sender->sin_addr), ip, MAX_IPADDR_LENGTH);
36
}
37

    
38
char * mg_uri_field(struct http_message *hm, uint8_t pos)
39
{
40
        char * uri;
41
        char ** tokens;
42
        uint32_t ntok;
43

    
44
        uri = malloc((hm->uri.len + 1) * sizeof(char));
45
        strncpy(uri, hm->uri.p, hm->uri.len);
46
        uri[hm->uri.len] = '\0';
47

    
48
        tokens = tokens_create(uri, '/', &ntok);
49
        
50
        strcpy(uri, tokens[pos]);
51
        tokens_destroy(&tokens, ntok);
52

    
53
        return uri;
54
}
55

    
56
void channel_index(struct mg_connection *nc, struct http_message *hm)
57
{
58
        char * channels;
59
        const struct context * c;
60

    
61
        c = (const struct context *) nc->user_data;
62

    
63
        info("GET request for channels\n");
64
        channels = pschannel_bucket_to_json(c->pb);
65
        debug("\t%s\n", channels);
66

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

    
71
        free(channels);
72
}
73

    
74
int8_t streamer_creation_handler(struct mg_connection *nc, const struct pschannel_bucket *psb, const struct pstreamer * ps, int8_t ret)
75
{
76
        char * json = NULL;
77
        int8_t res = -1;
78
        const struct pschannel * ch = NULL;
79

    
80
        info("Inside creation handler\n");
81
        if (ps)
82
        {
83
                ch = pschannel_bucket_find(psb, pstreamer_source_ipaddr(ps), pstreamer_source_port(ps));
84
                json = pstreamer_to_json(ps);
85
                if (ch)
86
                        json[strlen(json)-1] = '\0';
87
        }
88

    
89
        if (ret == 0 && json)
90
        {
91
                mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
92
                mg_printf_http_chunk(nc, json);
93
                if (ch)
94
                        mg_printf_http_chunk(nc, ",\"name\":\"%s\"}", ch->name);
95
                res = 0;
96
                info("Stream created and served\n");
97
        } else {
98
                mg_printf(nc, "%s", "HTTP/1.1 500 Internal server error\r\nTransfer-Encoding: chunked\r\n\r\n");
99
                // destroy ps?
100
                info("Stream cannot be correctly served\n");
101
                if (ret)
102
                        debug(json);
103
                else
104
                        debug("PS does not exist");
105
        }
106
        if (json)
107
                free(json);
108
        mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
109

    
110
        return res;
111
}
112

    
113
void streamer_create(struct mg_connection *nc, struct http_message *hm)
114
{
115
        const struct context * c;
116
        char ipaddr[MAX_IPADDR_LENGTH];
117
        char rtp_dst_ip[MAX_IPADDR_LENGTH];
118
        char port[MAX_PORT_LENGTH];
119
        char * id;
120
        const struct pstreamer * ps = NULL;
121
        const struct pschannel * ch = NULL;
122

    
123
        c = (const struct context *) nc->user_data;
124
        mg_get_http_var(&hm->body, "ipaddr", ipaddr, MAX_IPADDR_LENGTH);
125
        mg_get_http_var(&hm->body, "port", port, MAX_PORT_LENGTH);
126

    
127
        id = mg_uri_field(hm, 1);
128
        mg_connection_remote_ip(rtp_dst_ip, nc);
129

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

    
133
        if (ch)
134
        {
135
                debug("Channel: %s\n", ch->name);
136
                ps = pstreamer_manager_create_streamer(c->psm, ipaddr, port, id, rtp_dst_ip, streamer_creation_callback_new(nc, c->pb, streamer_creation_handler)); 
137
                if(ps)
138
                {
139
                        pstreamer_schedule_tasks((struct pstreamer*)ps, c->tm);
140
                        info("Streamer instance created\n");
141
                } else {
142
                        info("Streamer could not be launched\n");
143
                        mg_printf(nc, "%s", "HTTP/1.1 409 Conflict\r\nTransfer-Encoding: chunked\r\n\r\n");
144
                        mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
145
                }
146
        } else {
147
                info("No channel found for socket <%s:%s>\n", ipaddr, port);
148
                mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\nTransfer-Encoding: chunked\r\n\r\n");
149
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
150
        }
151

    
152
        free(id);
153
}
154

    
155
void streamer_update(struct mg_connection *nc, struct http_message *hm)
156
{
157
        char * id, * json;
158
        const struct pstreamer * ps;
159
        const struct context * c;
160

    
161
        c = (const struct context *) nc->user_data;
162
        id = mg_uri_field(hm, 1);
163

    
164
        ps = pstreamer_manager_get_streamer(c->psm, id);
165
        info("UPDATE request for resource %s\n", id);
166
        if (ps)
167
        {
168
                pstreamer_touch((struct pstreamer*) ps);
169
                info("\tInstance %s found and touched\n", id);
170
                json = pstreamer_to_json(ps);
171
                mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-type: application/json\r\n\r\n");
172
                mg_printf_http_chunk(nc, "%s", json);
173
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
174
                free(json);
175
        } else {
176
                info("\tInstance %s not found\n", id);
177
                mg_printf(nc, "%s", "HTTP/1.1 404 Not Found\r\nTransfer-Encoding: chunked\r\n\r\n");
178
                mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
179
        }
180

    
181
        free(id);
182
}