Statistics
| Branch: | Revision:

peerstreamer-src / peerstreamer-ng.c @ 92fe91e3

History | View | Annotate | Download (4.75 KB)

1
/*******************************************************************
2
* PeerStreamer-ng is a P2P video streaming application exposing a ReST
3
* interface.
4
* Copyright (C) 2017 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<signal.h>
21
#include<string.h>
22
#include<router.h>
23
#include<path_handlers.h>
24
#include<debug.h>
25
#include<task_manager.h>
26
#include<context.h>
27
#include<pschannel.h>
28
#include<periodic_task_intfs.h>
29
#include<pstreamer.h>
30
#include<ffmuxer.h>
31

    
32
#include<mongoose.h>
33

    
34

    
35
static uint8_t running = 1;
36

    
37
void sig_exit(int signo)
38
{
39
        running = 0;
40
}
41

    
42
void parse_args(struct context *c, int argc, char *const* argv)
43
{
44
        int o;
45

    
46
        while ((o = getopt (argc, argv, "vqp:c:s:")) != -1)
47
                switch (o) {
48
                        case 'p':
49
                                strncpy(c->http_port, optarg, 16);
50
                                break;
51
                        case 'c':
52
                                c->csvfile = strdup(optarg);
53
                                break;
54
                        case 's':
55
                                c->streamer_opts = strdup(optarg);
56
                                break;
57
                        case 'q':
58
                                set_debug(0);
59
                                break;
60
                        case 'v':
61
                                set_debug(2);
62
                                break;
63
                }
64
}
65

    
66
void mg_request_decode(char * buff, int buff_len, const struct http_message *hm)
67
{
68
        size_t i = 0;
69

    
70
        if (buff_len - i -2 > hm->method.len)
71
        {
72
                memmove(buff + i, hm->method.p, hm->method.len);
73
                i += hm->method.len;
74
        }
75
        buff[i++] = ' ';
76
        if (buff_len - i -2 > hm->uri.len)
77
        {
78
                memmove(buff + i, hm->uri.p, hm->uri.len);
79
                i += hm->uri.len;
80
        }
81
        buff[i++] = ' ';
82
        if (buff_len - i -1 > hm->query_string.len)
83
        {
84
                memmove(buff + i, hm->query_string.p, hm->query_string.len);
85
                i += hm->query_string.len;
86
        }
87
        buff[i] = '\0';
88
}
89

    
90
void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
91
{
92
        struct context *c = nc->user_data;
93
        struct http_message *hm;
94
        char buff[80];
95

    
96
        switch (ev) {
97
                case MG_EV_HTTP_REQUEST:
98
                        hm  = (struct http_message *) ev_data;
99
                        info("Received a request:\n");
100
                        mg_request_decode(buff, 80, hm);
101
                        info("\t%s\n", buff);
102
                        // Try to call a path handler. If it fails serve
103
                        // public contents
104
                        if(router_handle(c->router, nc, hm))
105
                                mg_serve_http(nc, hm, c->http_opts);
106
                        break;
107
                default:
108
                        break;
109
        }
110
}
111

    
112
void init(struct context *c, int argc, char **argv)
113
{
114
        strncpy(c->http_port, "3000", 16);
115
        signal(SIGINT, sig_exit);
116

    
117
        c->http_opts.enable_directory_listing = "no";
118
        c->http_opts.document_root = "Public/";
119
        c->http_opts.index_files = "index.html,player.html";
120
        c->csvfile = NULL;
121
        c->streamer_opts = NULL;
122
        set_debug(1);
123

    
124
        c->router = router_create(10);
125
        load_path_handlers(c->router);
126
        c->tm = task_manager_new();
127
        c->psm = pstreamer_manager_new(6001);
128

    
129
        c->mongoose_srv = (struct mg_mgr*) malloc(sizeof(struct mg_mgr));
130
        mg_mgr_init(c->mongoose_srv, c);
131

    
132
        parse_args(c, argc, argv);
133
        pstreamer_manager_set_streamer_options(c->psm, c->streamer_opts);
134
        c->pb = pschannel_bucket_new(c->csvfile);
135
        pschannel_bucket_insert(c->pb, "local_channel", "127.0.0.1", "6000", "300kbps", "127.0.0.1:3000/lchannel.sdp");
136
}
137

    
138
struct mg_mgr * launch_http_task(struct context *c)
139
{
140
        struct mg_connection *nc;
141

    
142
        nc = mg_bind(c->mongoose_srv, c->http_port, ev_handler);
143
        nc->user_data = c;
144
        if (nc == NULL) {
145
                fprintf(stderr, "Error starting server on port %s\n", c->http_port);
146
                exit(1);
147
        }
148
        mg_set_protocol_http_websocket(nc);
149
        task_manager_new_task(c->tm, mongoose_task_reinit, mongoose_task_callback, 1000, (void *)c->mongoose_srv->ifaces[MG_MAIN_IFACE]);
150

    
151
        return c->mongoose_srv;
152
}
153

    
154
void context_deinit(struct context *c)
155
{
156
        if (c->csvfile)
157
                free(c->csvfile);
158
        if (c->streamer_opts)
159
                free(c->streamer_opts);
160
        router_destroy(&(c->router));
161
        pstreamer_manager_destroy(&(c->psm));  // this must be destroyed before task managers!
162
        task_manager_destroy(&(c->tm));
163
        pschannel_bucket_destroy(&(c->pb));
164
        mg_mgr_free(c->mongoose_srv);
165
        free(c->mongoose_srv);
166
}
167

    
168
int main(int argc, char** argv)
169
{
170
        static struct context c;
171

    
172
        init(&c, argc, argv);
173

    
174

    
175
        info("Starting server on port %s\n", c.http_port);
176
        launch_http_task(&c);
177
        task_manager_new_task(c.tm, NULL, pschannel_csvfile_task_callback, 1000, (void *) c.pb);
178
        task_manager_new_task(c.tm, NULL, pstreamer_purge_task_callback, 5000, (void *) c.psm);
179
        ffmuxer_init();
180
        while (running)
181
                task_manager_poll(c.tm, 1000);
182

    
183
        info("\nExiting..\n");
184
        context_deinit(&c);
185
        ffmuxer_deinit();
186
        return 0;
187
}