GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/main.c Lines: 0 123 0.0 %
Date: 2020-12-10 21:44:00 Branches: 0 35 0.0 %

Line Branch Exec Source
1
#include <stdio.h> 				/* fprintf */
2
#include <stdlib.h>             /* NULL */
3
#include <getopt.h> 			/* getopt_long, struct option */
4
#include <string.h> 			/* strerror */
5
#include <errno.h> 			    /* errno */
6
7
#include "server.h"             /* server_start */
8
#include "config.h"             /* config_t, WSS_config_load(), WSS_config_free() */
9
#include "error.h"              /* wss_error_t */
10
#include "subprotocols.h"       /* wss_subprotocol_t */
11
#include "alloc.h"              /* WSS_malloc() */
12
#include "log.h"                /* WSS_log_*() */
13
#include "predict.h"
14
15
static void log_mutex(void *udata, int lock) {
16
    int err;
17
    pthread_mutex_t *l = (pthread_mutex_t *) udata;
18
    if (lock) {
19
        if ( unlikely((err = pthread_mutex_lock(l)) != 0) ) {
20
            WSS_log_error("Unable to lock log lock: %s", strerror(err));
21
        }
22
    } else {
23
        if ( unlikely((err = pthread_mutex_unlock(l)) != 0) ) {
24
            WSS_log_error("Unable to unlock log lock: %s", strerror(err));
25
        }
26
    }
27
}
28
29
static inline void wss_help(FILE *stream) {
30
    fprintf(
31
            stream,
32
            "Usage: ./WSServer [OPTIONS]\n\n"
33
            "OPTIONS:\n"
34
            "\t-h             | --help                 show server arguments\n"
35
            "\t-c CONFIG_PATH | --config CONFIG_PATH   provide JSON configuration file\n"
36
           );
37
}
38
39
int main(int argc, char *argv[]) {
40
    int err, res;
41
    wss_config_t config;
42
    FILE *file;
43
    pthread_mutex_t log_lock;
44
    char *echo = "subprotocols/echo/echo.so", *broadcast = "subprotocols/broadcast/broadcast.so";
45
46
#ifdef USE_RPMALLOC
47
    rpmalloc_initialize();
48
#endif
49
50
    static struct option long_options[] = {
51
        {"help"   	    , no_argument,       0, 'h'},
52
        {"config"       , required_argument, 0, 'c'},
53
        {0          	, 0                , 0,  0 }
54
    };
55
56
    // Default values
57
    config.subprotocols         = NULL;
58
    config.subprotocols_length  = 0;
59
    config.extensions           = NULL;
60
    config.extensions_length    = 0;
61
    config.favicon              = NULL;
62
    config.origins              = NULL;
63
    config.origins_length       = 0;
64
    config.hosts                = NULL;
65
    config.hosts_length         = 0;
66
    config.paths                = NULL;
67
    config.paths_length         = 0;
68
    config.queries              = NULL;
69
    config.queries_length       = 0;
70
    config.string               = NULL;
71
    config.data                 = NULL;
72
    config.length               = 0;
73
    config.port_http 	        = 80;
74
    config.port_https	        = 443;
75
#ifdef NDEBUG
76
    config.log 		            = WSS_LOG_INFO;
77
#else
78
    config.log 		            = WSS_LOG_TRACE;
79
#endif
80
    config.size_header          = 8192;
81
    config.size_payload         = 16777215;
82
    config.size_uri 	        = 8192;
83
    config.size_ringbuffer      = 128;
84
    config.size_buffer          = 32768;
85
    config.size_thread          = 2097152;
86
    config.size_frame           = 1048576;
87
    config.max_frames           = 1048576;
88
    config.pool_workers         = 4;
89
    config.pool_retries         = 5;
90
    config.timeout_pings        = 1;     // Times that a client will be pinged before timeout occurs
91
    config.timeout_poll         = -1;    // Infinite
92
    config.timeout_read         = 1000;  // 1 Second
93
    config.timeout_write        = 1000;  // 1 Second
94
    config.timeout_client       = 60000; // 1 Hour
95
    config.ssl_key              = NULL;
96
    config.ssl_cert             = NULL;
97
    config.ssl_dhparam          = NULL;
98
    config.ssl_ca_file          = NULL;
99
    config.ssl_ca_path          = NULL;
100
    config.ssl_cipher_list      = NULL;
101
    config.ssl_cipher_suites    = NULL;
102
    config.ssl_compression      = false;
103
    config.ssl_peer_cert        = false;
104
105
    if ( NULL == (file = fopen("log/WSServer.log", "a+")) ) {
106
        WSS_config_free(&config);
107
        fprintf(stderr, "%s\n", strerror(errno));
108
#ifdef USE_RPMALLOC
109
        rpmalloc_finalize();
110
#endif
111
        return EXIT_FAILURE;
112
    }
113
114
    // Set file to write log to
115
    log_set_fp(file);
116
117
    // Set log level to default value until configuration is loaded
118
    log_set_level(config.log);
119
120
    if ( unlikely((err = pthread_mutex_init(&log_lock, NULL)) != 0) ) {
121
        WSS_config_free(&config);
122
        WSS_log_error("Unable to initialize log lock: %s", strerror(err));
123
        fclose(file);
124
#ifdef USE_RPMALLOC
125
        rpmalloc_finalize();
126
#endif
127
        return EXIT_FAILURE;
128
    }
129
130
    // Set lock to use in interal lock function
131
    log_set_udata(&log_lock);
132
133
    // Set lock function for logging functions
134
    log_set_lock(log_mutex);
135
136
    while ( likely((err = getopt_long(argc, argv, "c:h", long_options, NULL)) != -1)) {
137
        switch (err) {
138
            case 'c':
139
                if ( unlikely(WSS_SUCCESS != WSS_config_load(&config, optarg)) ) {
140
                    WSS_config_free(&config);
141
142
                    if ( unlikely((err = pthread_mutex_destroy(&log_lock)) != 0) ) {
143
                        WSS_log_error("Unable to initialize log lock: %s", strerror(err));
144
                    }
145
146
                    fclose(file);
147
#ifdef USE_RPMALLOC
148
                    rpmalloc_finalize();
149
#endif
150
                    return EXIT_FAILURE;
151
                }
152
                break;
153
            case 'h':
154
                wss_help(stdout);
155
                WSS_config_free(&config);
156
                if ( unlikely((err = pthread_mutex_destroy(&log_lock)) != 0) ) {
157
                    WSS_log_error("Unable to initialize log lock: %s", strerror(err));
158
                    fclose(file);
159
#ifdef USE_RPMALLOC
160
                    rpmalloc_finalize();
161
#endif
162
                    return EXIT_FAILURE;
163
                }
164
                fclose(file);
165
#ifdef USE_RPMALLOC
166
                rpmalloc_finalize();
167
#endif
168
                return EXIT_SUCCESS;
169
            default:
170
                wss_help(stderr);
171
                WSS_config_free(&config);
172
                if ( unlikely((err = pthread_mutex_destroy(&log_lock)) != 0) ) {
173
                    WSS_log_error("Unable to initialize log lock: %s", strerror(err));
174
                }
175
                fclose(file);
176
#ifdef USE_RPMALLOC
177
                rpmalloc_finalize();
178
#endif
179
                return EXIT_FAILURE;
180
        }
181
    }
182
183
    // If in production mode do not print to stdout
184
#ifdef NDEBUG
185
    WSS_log_info("Log is in quiet mode");
186
    log_set_quiet(1);
187
#endif
188
189
    // Set log level to what what specified in the configuration
190
    log_set_level(config.log);
191
192
    // Setting echo and broadcast protocols as default if none was loaded
193
    if ( config.subprotocols_length == 0 && config.subprotocols == NULL) {
194
        if ( NULL != (config.subprotocols = WSS_calloc(2, sizeof(char *)))) {
195
            if ( NULL != (config.subprotocols_config = WSS_calloc(2, sizeof(char *)))) {
196
                config.subprotocols[0] = echo;
197
                config.subprotocols[1] = broadcast;
198
                config.subprotocols_config[0] = NULL;
199
                config.subprotocols_config[1] = NULL;
200
                config.subprotocols_length = 2;
201
            }
202
        }
203
    }
204
205
    res = WSS_server_start(&config);
206
207
    if ( unlikely((err = pthread_mutex_destroy(&log_lock)) != 0) ) {
208
        WSS_log_error("Unable to initialize log lock: %s", strerror(err));
209
        res = EXIT_FAILURE;
210
    }
211
212
    if ( unlikely(WSS_SUCCESS != WSS_config_free(&config)) ) {
213
        res = EXIT_FAILURE;
214
    }
215
216
    fclose(file);
217
218
#ifdef USE_RPMALLOC
219
    rpmalloc_finalize();
220
#endif
221
222
    return res;
223
}