Skip to content

Commit fcbaf3d

Browse files
committed
Add structured JSON event stream and exit codes
New --json-events flag emits JSON on stderr for GUI integration. exit_codes.h defines specific codes for each failure type.
1 parent 7930195 commit fcbaf3d

3 files changed

Lines changed: 194 additions & 0 deletions

File tree

src/event.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright (c) 2015 Adrien Vergé
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "event.h"
19+
20+
#include <pthread.h>
21+
22+
#include <stdarg.h>
23+
#include <stdint.h>
24+
#include <stdio.h>
25+
#include <string.h>
26+
#include <time.h>
27+
28+
static int events_enabled;
29+
static int64_t seq_counter;
30+
static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER;
31+
32+
void event_init(int enabled)
33+
{
34+
events_enabled = enabled;
35+
}
36+
37+
void event_emit(const char *type, const char *json_fields_fmt, ...)
38+
{
39+
va_list ap;
40+
char fields_buf[2048];
41+
42+
if (!events_enabled)
43+
return;
44+
45+
pthread_mutex_lock(&event_mutex);
46+
47+
fprintf(stderr, "{\"event\":\"%s\",\"ts\":%lld,\"seq\":%lld",
48+
type, (long long)time(NULL), (long long)seq_counter++);
49+
50+
if (json_fields_fmt && json_fields_fmt[0] != '\0') {
51+
va_start(ap, json_fields_fmt);
52+
vsnprintf(fields_buf, sizeof(fields_buf), json_fields_fmt, ap);
53+
va_end(ap);
54+
fprintf(stderr, ",%s", fields_buf);
55+
}
56+
57+
fprintf(stderr, "}\n");
58+
fflush(stderr);
59+
60+
pthread_mutex_unlock(&event_mutex);
61+
}
62+
63+
char *json_escape(char *buf, size_t buf_size, const char *input)
64+
{
65+
size_t i = 0;
66+
size_t o = 0;
67+
68+
if (!buf || buf_size == 0)
69+
return buf;
70+
71+
/* Reserve space for NUL terminator */
72+
buf_size--;
73+
74+
if (!input) {
75+
buf[0] = '\0';
76+
return buf;
77+
}
78+
79+
while (input[i] != '\0' && o < buf_size) {
80+
unsigned char c = (unsigned char)input[i];
81+
82+
if (c == '"') {
83+
if (o + 2 > buf_size)
84+
break;
85+
buf[o++] = '\\';
86+
buf[o++] = '"';
87+
} else if (c == '\\') {
88+
if (o + 2 > buf_size)
89+
break;
90+
buf[o++] = '\\';
91+
buf[o++] = '\\';
92+
} else if (c == '\n') {
93+
if (o + 2 > buf_size)
94+
break;
95+
buf[o++] = '\\';
96+
buf[o++] = 'n';
97+
} else if (c == '\r') {
98+
if (o + 2 > buf_size)
99+
break;
100+
buf[o++] = '\\';
101+
buf[o++] = 'r';
102+
} else if (c == '\t') {
103+
if (o + 2 > buf_size)
104+
break;
105+
buf[o++] = '\\';
106+
buf[o++] = 't';
107+
} else if (c < 0x20) {
108+
if (o + 6 > buf_size)
109+
break;
110+
snprintf(buf + o, 7, "\\u%04x", c);
111+
o += 6;
112+
} else {
113+
buf[o++] = c;
114+
}
115+
i++;
116+
}
117+
118+
buf[o] = '\0';
119+
return buf;
120+
}

src/event.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2015 Adrien Vergé
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#ifndef OPENFORTIVPN_EVENT_H
19+
#define OPENFORTIVPN_EVENT_H
20+
21+
#include <stddef.h>
22+
23+
/* Initialize the event system. enabled=1 turns on JSON output to stderr. */
24+
void event_init(int enabled);
25+
26+
/* Emit a JSON event line to stderr. fmt contains key:value pairs in JSON. */
27+
void event_emit(const char *type, const char *json_fields_fmt, ...);
28+
29+
/*
30+
* Helper: escape a string for JSON (handles quotes, backslashes, control chars).
31+
* Writes to buf, returns buf. Truncates if output exceeds buf_size.
32+
*/
33+
char *json_escape(char *buf, size_t buf_size, const char *input);
34+
35+
#endif /* OPENFORTIVPN_EVENT_H */

src/exit_codes.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2015 Adrien Vergé
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#ifndef OPENFORTIVPN_EXIT_CODES_H
19+
#define OPENFORTIVPN_EXIT_CODES_H
20+
21+
enum ofv_exit_code {
22+
OFV_EXIT_OK = 0,
23+
OFV_EXIT_GENERIC = 1, /* legacy fallback */
24+
OFV_EXIT_DNS_FAILED = 10,
25+
OFV_EXIT_TCP_FAILED = 11,
26+
OFV_EXIT_TLS_FAILED = 12,
27+
OFV_EXIT_CERT_FAILED = 13,
28+
OFV_EXIT_AUTH_FAILED = 20,
29+
OFV_EXIT_OTP_MISSING = 21,
30+
OFV_EXIT_SAML_FAILED = 22,
31+
OFV_EXIT_ALLOC_DENIED = 23,
32+
OFV_EXIT_CONFIG_FAILED = 30,
33+
OFV_EXIT_ADAPTER_FAILED = 40,
34+
OFV_EXIT_TUNNEL_FAILED = 41,
35+
OFV_EXIT_PERMISSION = 50,
36+
OFV_EXIT_SIGNAL = 60
37+
};
38+
39+
#endif /* OPENFORTIVPN_EXIT_CODES_H */

0 commit comments

Comments
 (0)