Statistics
| Branch: | Revision:

janus-gateway / utils.c @ b8237291

History | View | Annotate | Download (7.64 KB)

1
/*! \file    utils.c
2
 * \author   Lorenzo Miniero <lorenzo@meetecho.com>
3
 * \copyright GNU General Public License v3
4
 * \brief    Utilities and helpers
5
 * \details  Implementations of a few methods that may be of use here
6
 * and there in the code.
7
 * 
8
 * \ingroup core
9
 * \ref core
10
 */
11

    
12
#include <stdlib.h>
13
#include <string.h>
14
#include <sys/stat.h>
15
#include <errno.h>
16
#include <arpa/inet.h>
17
#include <sys/types.h>
18
#include <sys/socket.h>
19

    
20
#include "utils.h"
21
#include "debug.h"
22

    
23
#if __MACH__
24
#include "mach_gettime.h"
25
#endif
26

    
27
gint64 janus_get_monotonic_time(void) {
28
        struct timespec ts;
29
        clock_gettime (CLOCK_MONOTONIC, &ts);
30
        return (ts.tv_sec*G_GINT64_CONSTANT(1000000)) + (ts.tv_nsec/G_GINT64_CONSTANT(1000));
31
}
32

    
33
gint64 janus_get_real_time(void) {
34
        struct timespec ts;
35
        clock_gettime (CLOCK_REALTIME, &ts);
36
        return (ts.tv_sec*G_GINT64_CONSTANT(1000000)) + (ts.tv_nsec/G_GINT64_CONSTANT(1000));
37
}
38

    
39
gboolean janus_is_true(const char *value) {
40
        return value && (!strcasecmp(value, "yes") || !strcasecmp(value, "true") || !strcasecmp(value, "1"));
41
}
42

    
43
gboolean janus_strcmp_const_time(const void *str1, const void *str2) {
44
        if(str1 == NULL || str2 == NULL)
45
                return FALSE;
46
        const unsigned char *string1 = (const unsigned char *)str1;
47
        const unsigned char *string2 = (const unsigned char *)str2;
48
        size_t maxlen = strlen((char *)string1);
49
        if(strlen((char *)string2) > maxlen)
50
                maxlen = strlen((char *)string2);
51
        unsigned char *buf1 = g_malloc0(maxlen+1);
52
        memset(buf1, 0, maxlen);
53
        memcpy(buf1, string1, strlen(str1));
54
        unsigned char *buf2 = g_malloc0(maxlen+1);
55
        memset(buf2, 0, maxlen);
56
        memcpy(buf2, string2, strlen(str2));
57
        unsigned char result = 0;
58
        size_t i = 0;
59
        for (i = 0; i < maxlen; i++) {
60
                result |= buf1[i] ^ buf2[i];
61
        }
62
        g_free(buf1);
63
        buf1 = NULL;
64
        g_free(buf2);
65
        buf2 = NULL;
66
        return result == 0;
67
}
68

    
69
void janus_flags_reset(janus_flags *flags) {
70
        if(flags != NULL)
71
                *flags = 0;
72
}
73

    
74
void janus_flags_set(janus_flags *flags, uint32_t flag) {
75
        if(flags != NULL) {
76
                *flags |= flag;
77
        }
78
}
79

    
80
void janus_flags_clear(janus_flags *flags, uint32_t flag) {
81
        if(flags != NULL) {
82
                *flags &= ~(flag);
83
        }
84
}
85

    
86
gboolean janus_flags_is_set(janus_flags *flags, uint32_t flag) {
87
        if(flags != NULL) {
88
                uint32_t bit = *flags & flag;
89
                return (bit != 0);
90
        }
91
        return FALSE;
92
}
93

    
94
/* Easy way to replace multiple occurrences of a string with another: ALWAYS creates a NEW string */
95
char *janus_string_replace(char *message, const char *old_string, const char *new_string)
96
{
97
        if(!message || !old_string || !new_string)
98
                return NULL;
99

    
100
        if(!strstr(message, old_string)) {        /* Nothing to be done (old_string is not there) */
101
                return message;
102
        }
103
        if(!strcmp(old_string, new_string)) {        /* Nothing to be done (old_string=new_string) */
104
                return message;
105
        }
106
        if(strlen(old_string) == strlen(new_string)) {        /* Just overwrite */
107
                char *outgoing = message;
108
                char *pos = strstr(outgoing, old_string), *tmp = NULL;
109
                int i = 0;
110
                while(pos) {
111
                        i++;
112
                        memcpy(pos, new_string, strlen(new_string));
113
                        pos += strlen(old_string);
114
                        tmp = strstr(pos, old_string);
115
                        pos = tmp;
116
                }
117
                return outgoing;
118
        } else {        /* We need to resize */
119
                char *outgoing = g_strdup(message);
120
                g_free(message);
121
                if(outgoing == NULL) {
122
                        return NULL;
123
                }
124
                int diff = strlen(new_string) - strlen(old_string);
125
                /* Count occurrences */
126
                int counter = 0;
127
                char *pos = strstr(outgoing, old_string), *tmp = NULL;
128
                while(pos) {
129
                        counter++;
130
                        pos += strlen(old_string);
131
                        tmp = strstr(pos, old_string);
132
                        pos = tmp;
133
                }
134
                uint16_t old_stringlen = strlen(outgoing)+1, new_stringlen = old_stringlen + diff*counter;
135
                if(diff > 0) {        /* Resize now */
136
                        tmp = g_realloc(outgoing, new_stringlen);
137
                        if(!tmp) {
138
                                g_free(outgoing);
139
                                return NULL;
140
                        }
141
                        outgoing = tmp;
142
                }
143
                /* Replace string */
144
                pos = strstr(outgoing, old_string);
145
                while(pos) {
146
                        if(diff > 0) {        /* Move to the right (new_string is larger than old_string) */
147
                                uint16_t len = strlen(pos)+1;
148
                                memmove(pos + diff, pos, len);
149
                                memcpy(pos, new_string, strlen(new_string));
150
                                pos += strlen(new_string);
151
                                tmp = strstr(pos, old_string);
152
                        } else {        /* Move to the left (new_string is smaller than old_string) */
153
                                uint16_t len = strlen(pos - diff)+1;
154
                                memmove(pos, pos - diff, len);
155
                                memcpy(pos, new_string, strlen(new_string));
156
                                pos += strlen(old_string);
157
                                tmp = strstr(pos, old_string);
158
                        }
159
                        pos = tmp;
160
                }
161
                if(diff < 0) {        /* We skipped the resize previously (shrinking memory) */
162
                        tmp = g_realloc(outgoing, new_stringlen);
163
                        if(!tmp) {
164
                                g_free(outgoing);
165
                                return NULL;
166
                        }
167
                        outgoing = tmp;
168
                }
169
                outgoing[strlen(outgoing)] = '\0';
170
                return outgoing;
171
        }
172
}
173

    
174
int janus_mkdir(const char *dir, mode_t mode) {
175
        char tmp[256];
176
        char *p = NULL;
177
        size_t len;
178

    
179
        int res = 0;
180
        g_snprintf(tmp, sizeof(tmp), "%s", dir);
181
        len = strlen(tmp);
182
        if(tmp[len - 1] == '/')
183
                tmp[len - 1] = 0;
184
        for(p = tmp + 1; *p; p++) {
185
                if(*p == '/') {
186
                        *p = 0;
187
                        res = mkdir(tmp, mode);
188
                        if(res != 0 && errno != EEXIST) {
189
                                JANUS_LOG(LOG_ERR, "Error creating folder %s\n", tmp);
190
                                return res;
191
                        }
192
                        *p = '/';
193
                }
194
        }
195
        res = mkdir(tmp, mode);
196
        if(res != 0 && errno != EEXIST)
197
                return res;
198
        return 0;
199
}
200

    
201
int janus_get_opus_pt(const char *sdp) {
202
        if(!sdp)
203
                return -1;
204
        if(!strstr(sdp, "m=audio") || (!strstr(sdp, "opus/48000") && !strstr(sdp, "OPUS/48000")))
205
                return -2;
206
        const char *line = strstr(sdp, "m=audio");
207
        while(line) {
208
                char *next = strchr(line, '\n');
209
                if(next) {
210
                        *next = '\0';
211
                        JANUS_LOG(LOG_WARN, "%s\n", line);
212
                        if(strstr(line, "a=rtpmap") && strstr(line, "opus/48000")) {
213
                                /* Gotcha! */
214
                                JANUS_LOG(LOG_WARN, "opus/48000!\n");
215
                                int pt = 0;
216
                                if(sscanf(line, "a=rtpmap:%d opus/48000/2", &pt) == 1) {
217
                                        *next = '\n';
218
                                        return pt;
219
                                }
220
                        } else if(strstr(line, "a=rtpmap") && strstr(line, "OPUS/48000")) {
221
                                /* Gotcha! */
222
                                JANUS_LOG(LOG_WARN, "OPUS/48000!\n");
223
                                int pt = 0;
224
                                if(sscanf(line, "a=rtpmap:%d OPUS/48000/2", &pt) == 1) {
225
                                        *next = '\n';
226
                                        return pt;
227
                                }
228
                        }
229
                        *next = '\n';
230
                }
231
                line = next ? (next+1) : NULL;
232
        }
233
        return -3;
234
}
235

    
236
int janus_get_vp8_pt(const char *sdp) {
237
        if(!sdp)
238
                return -1;
239
        if(!strstr(sdp, "m=video") || (!strstr(sdp, "VP8/90000") && !strstr(sdp, "vp8/90000")))
240
                return -2;
241
        const char *line = strstr(sdp, "m=video");
242
        while(line) {
243
                char *next = strchr(line, '\n');
244
                if(next) {
245
                        *next = '\0';
246
                        if(strstr(line, "a=rtpmap") && strstr(line, "VP8/90000")) {
247
                                /* Gotcha! */
248
                                int pt = 0;
249
                                if(sscanf(line, "a=rtpmap:%d VP8/90000", &pt) == 1) {
250
                                        *next = '\n';
251
                                        return pt;
252
                                }
253
                        } else if(strstr(line, "a=rtpmap") && strstr(line, "vp8/90000")) {
254
                                /* Gotcha! */
255
                                int pt = 0;
256
                                if(sscanf(line, "a=rtpmap:%d vp8/90000", &pt) == 1) {
257
                                        *next = '\n';
258
                                        return pt;
259
                                }
260
                        }
261
                        *next = '\n';
262
                }
263
                line = next ? (next+1) : NULL;
264
        }
265
        return -3;
266
}
267

    
268
gboolean janus_is_ip_valid(const char *ip, int *family) {
269
        if(ip == NULL)
270
                return FALSE;
271

    
272
        struct sockaddr_in addr4;
273
        struct sockaddr_in6 addr6;
274

    
275
        if(inet_pton(AF_INET, ip, &addr4) > 0) {
276
                if(family != NULL)
277
                        *family = AF_INET;
278
                return TRUE;
279
        } else if(inet_pton(AF_INET6, ip, &addr6) > 0) {
280
                if(family != NULL)
281
                        *family = AF_INET6;
282
                return TRUE;
283
        } else {
284
                return FALSE;
285
        }
286
}
287

    
288
char *janus_address_to_ip(struct sockaddr *address) {
289
        if(address == NULL)
290
                return NULL;
291
        char addr_buf[INET6_ADDRSTRLEN];
292
        const char *addr = NULL;
293
        struct sockaddr_in *sin = NULL;
294
        struct sockaddr_in6 *sin6 = NULL;
295

    
296
        switch(address->sa_family) {
297
                case AF_INET:
298
                        sin = (struct sockaddr_in *)address;
299
                        addr = inet_ntop(AF_INET, &sin->sin_addr, addr_buf, INET_ADDRSTRLEN);
300
                        break;
301
                case AF_INET6:
302
                        sin6 = (struct sockaddr_in6 *)address;
303
                        addr = inet_ntop(AF_INET6, &sin6->sin6_addr, addr_buf, INET6_ADDRSTRLEN);
304
                        break;
305
                default:
306
                        /* Unknown family */
307
                        break;
308
        }
309
        return addr ? g_strdup(addr) : NULL;
310
}