Statistics
| Branch: | Revision:

peerstreamer-src / peerstreamer-ng.c @ b87dc7a2

History | View | Annotate | Download (4.11 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

    
31
#include<mongoose.h>
32

    
33

    
34
static uint8_t running = 1;
35

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

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

    
45
        while ((o = getopt (argc, argv, "qp:")) != -1)
46
                switch (o) {
47
                        case 'p':
48
                                strncpy(c->http_port, optarg, 16);
49
                                break;
50
                        case 'q':
51
                                set_debug(0);
52
                                break;
53
                }
54
}
55

    
56
void mg_request_decode(char * buff, int buff_len, const struct http_message *hm)
57
{
58
        size_t i = 0;
59

    
60
        if (buff_len - i -2 > hm->method.len)
61
        {
62
                memmove(buff + i, hm->method.p, hm->method.len);
63
                i += hm->method.len;
64
        }
65
        buff[i++] = ' ';
66
        if (buff_len - i -2 > hm->uri.len)
67
        {
68
                memmove(buff + i, hm->uri.p, hm->uri.len);
69
                i += hm->uri.len;
70
        }
71
        buff[i++] = ' ';
72
        if (buff_len - i -1 > hm->query_string.len)
73
        {
74
                memmove(buff + i, hm->query_string.p, hm->query_string.len);
75
                i += hm->query_string.len;
76
        }
77
        buff[i] = '\0';
78
}
79

    
80
void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
81
{
82
        struct context *c = nc->user_data;
83
        struct http_message *hm;
84
        char buff[80];
85

    
86
        switch (ev) {
87
                case MG_EV_HTTP_REQUEST:
88
                        hm  = (struct http_message *) ev_data;
89
                        debug("Received a request:\n");
90
                        mg_request_decode(buff, 80, hm);
91
                        debug("\t%s\n", buff);
92
                        // Try to call a path handler. If it fails serve
93
                        // public contents
94
                        if(router_handle(c->router, nc, hm))
95
                                mg_serve_http(nc, hm, c->http_opts);
96
                        break;
97
                default:
98
                        break;
99
        }
100
}
101

    
102
void init(struct context *c, int argc, char **argv)
103
{
104
        strncpy(c->http_port, "3000", 16);
105
        signal(SIGINT, sig_exit);
106

    
107
        c->http_opts.enable_directory_listing = "no";
108
        c->http_opts.document_root = "Public/";
109
        c->http_opts.index_files = "index.html,player.html";
110
        set_debug(1);
111

    
112
        c->router = router_create(10);
113
        load_path_handlers(c->router);
114
        c->tm = task_manager_new();
115
        c->pb = pschannel_bucket_new();
116
        c->psm = pstreamer_manager_new(7000);
117
        pschannel_bucket_insert(c->pb, "local_channel", "127.0.0.1", "6000", "300kbps", "127.0.0.1:3000/lchannel.sdp");
118

    
119
        c->mongoose_srv = (struct mg_mgr*) malloc(sizeof(struct mg_mgr));
120
        mg_mgr_init(c->mongoose_srv, c);
121

    
122
        parse_args(c, argc, argv);
123
}
124

    
125
struct mg_mgr * launch_http_task(struct context *c)
126
{
127
        struct mg_connection *nc;
128

    
129
        nc = mg_bind(c->mongoose_srv, c->http_port, ev_handler);
130
        nc->user_data = c;
131
        if (nc == NULL) {
132
                fprintf(stderr, "Error starting server on port %s\n", c->http_port);
133
                exit(1);
134
        }
135
        mg_set_protocol_http_websocket(nc);
136
        task_manager_new_task(c->tm, mongoose_task_reinit, mongoose_task_callback, 1000, (void *)c->mongoose_srv->ifaces[MG_MAIN_IFACE]);
137

    
138
        return c->mongoose_srv;
139
}
140

    
141
void context_deinit(struct context *c)
142
{
143
        router_destroy(&(c->router));
144
        task_manager_destroy(&(c->tm));
145
        pschannel_bucket_destroy(&(c->pb));
146
        pstreamer_manager_destroy(&(c->psm));
147
        mg_mgr_free(c->mongoose_srv);
148
        free(c->mongoose_srv);
149
}
150

    
151
int main(int argc, char** argv)
152
{
153
        static struct context c;
154

    
155
        init(&c, argc, argv);
156

    
157

    
158
        debug("Starting server on port %s\n", c.http_port);
159
        launch_http_task(&c);
160
        while (running)
161
                task_manager_poll(c.tm, 1000);
162

    
163
        debug("\nExiting..\n");
164
        context_deinit(&c);
165
        return 0;
166
}