GCC Code Coverage Report


src/
File: src/service/service_com.c
Date: 2026-03-31 17:48:22
Lines:
113/137
82.5%
Functions:
9/9
100.0%
Branches:
70/104
67.3%

Line Branch Exec Source
1 #include <glib.h>
2 #include <inttypes.h>
3 #include <stdbool.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <gio/gio.h>
8 #include "service/service.h"
9 #include "service/service_internals.h"
10
11 static GSocket* s_socket;
12
13 /**
14 * @brief Attempt to connect to the service
15 *
16 * @param socket The socket to connect through
17 * @param error Error throws
18 * @return int error code
19 */
20 10 static void connect(GSocket* socket, GError** error) {
21 // Get the service port
22 10 int port = gittor_service_get_port(error);
23
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (error && *error) {
24 return;
25
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 } else if (port < 0) {
26 5 g_set_error(error, g_quark_from_static_string(__func__), 1,
27 "Error Connecting: service not found");
28 5 return;
29 }
30
31 GSocketAddress* address =
32 5 g_inet_socket_address_new_from_string("127.0.0.1", port);
33
34 // Multiple attempts to connect
35
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 for (int i = 0; i < 5; i++) {
36 5 g_clear_error(error);
37 5 g_socket_connect(socket, address, NULL, error);
38
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!*error) {
39 5 break;
40 }
41 g_usleep(100UL * 1000UL); // 100ms
42 }
43
44 5 g_object_unref(address);
45 5 return;
46 }
47
48 /**
49 * @brief Get the connection to the service
50 *
51 * @param auto_start Start the GitTor service if not running
52 * @param error Error throws
53 * @return GSocket* Connection to the service
54 */
55 13 static GSocket* get_connection(bool auto_start, GError** error) {
56 // Connection has already been established
57
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 if (s_socket != NULL) {
58 4 return s_socket;
59 }
60
61 9 s_socket = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
62 G_SOCKET_PROTOCOL_TCP, error);
63
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (error && *error) {
64 g_object_unref(s_socket);
65 s_socket = NULL;
66 return NULL;
67 }
68
69 // Attempt to connect
70 9 connect(s_socket, error);
71
72 // If connected, return
73
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
9 if (!*error) {
74 4 return s_socket;
75
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 } else if (!auto_start) {
76 4 g_object_unref(s_socket);
77 4 s_socket = NULL;
78 4 return NULL;
79 }
80
81 1 g_clear_error(error);
82
83 // Start the gittor service
84 1 gittor_service_run(true);
85 1 g_print("GitTor service started.\n");
86
87 // Attempt to connect a second time
88 1 connect(s_socket, error);
89
90 // If connection fails again, throw error
91
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (error && *error) {
92 g_object_unref(s_socket);
93 s_socket = NULL;
94 return NULL;
95 }
96
97 1 return s_socket;
98 }
99
100 2 extern packet_t* gittor_service_send(const packet_t* msg, GError** error) {
101
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (msg->type == END || msg->type == KILL) {
102 g_set_error(error, g_quark_from_static_string(__func__), 1,
103 "Error Sending Packet: cannot send control packets");
104 2 return NULL;
105 }
106
107 // Get connection to the service
108
1/1
✓ Branch 1 taken 2 times.
2 GSocket* socket = get_connection(true, error);
109
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (error && *error) {
110 return NULL;
111 }
112
113 // Send the header
114 2 header_t header = {.magic = MAGIC, .type = msg->type, .len = msg->len};
115
1/1
✓ Branch 1 taken 2 times.
2 g_socket_send(socket, (void*)&header, sizeof(header), NULL, error);
116
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (error && *error) {
117 return NULL;
118 }
119
120 // Send the data
121
1/1
✓ Branch 1 taken 2 times.
2 g_socket_send(socket, (void*)msg->data, msg->len, NULL, error);
122
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (error && *error) {
123 return NULL;
124 }
125
126 // Recieve the header
127
1/1
✓ Branch 1 taken 2 times.
2 g_socket_receive(socket, (void*)&header, sizeof(header), NULL, error);
128
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (error && *error) {
129 return NULL;
130 }
131
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (header.magic != MAGIC) {
133 g_set_error(error, g_quark_from_static_string(__func__), 2,
134 "Received Incorrect Header Signiture: got '%" PRIx64
135 "' expected '%" PRIx64 "'\n",
136 header.magic, MAGIC);
137 return NULL;
138 }
139
140 2 packet_t* resp = (packet_t*)malloc(sizeof(*resp));
141 2 resp->type = header.type;
142 2 resp->len = header.len;
143 2 resp->data = (void*)malloc(header.len);
144
145 // Recieve the data
146
1/1
✓ Branch 1 taken 2 times.
2 g_socket_receive(socket, resp->data, header.len, NULL, error);
147
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (error && *error) {
148 free(resp->data);
149 free(resp);
150 return NULL;
151 }
152
153 2 return resp;
154 }
155
156 3 extern int gittor_service_start() {
157 // Try to connect
158 3 GError* error = NULL;
159
1/1
✓ Branch 1 taken 3 times.
3 get_connection(false, &error);
160
161
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (error) {
162
1/1
✓ Branch 1 taken 2 times.
2 g_clear_error(&error);
163
1/1
✓ Branch 1 taken 2 times.
2 gittor_service_run(true);
164
1/1
✓ Branch 1 taken 2 times.
2 g_print("GitTor service started.\n");
165 } else {
166
1/1
✓ Branch 1 taken 1 times.
1 g_print("GitTor service already running.\n");
167 }
168
169 3 return 0;
170 }
171
172 5 extern int gittor_service_stop() {
173 // Try to connect
174 5 GError* error = NULL;
175
1/1
✓ Branch 1 taken 5 times.
5 GSocket* socket = get_connection(false, &error);
176
177
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (!error) {
178 // Kill the service
179 4 header_t header = {.magic = MAGIC, .type = KILL, .len = -1};
180
1/1
✓ Branch 1 taken 4 times.
4 g_socket_send(socket, (void*)&header, sizeof(header), NULL, NULL);
181
1/1
✓ Branch 1 taken 4 times.
4 g_object_unref(s_socket);
182 4 s_socket = NULL;
183
1/1
✓ Branch 1 taken 4 times.
4 g_print("GitTor service stopped.\n");
184 } else {
185
1/1
✓ Branch 1 taken 1 times.
1 g_clear_error(&error);
186
1/1
✓ Branch 1 taken 1 times.
1 g_print("GitTor service wasn't running.\n");
187 }
188
189
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (G_IS_OBJECT(s_socket)) {
190 g_object_unref(s_socket);
191 }
192 5 s_socket = NULL;
193
194 // While port is greater than 0, wait
195 5 int count = 0;
196
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 while (count < 20) {
197
1/1
✓ Branch 1 taken 9 times.
9 int port = gittor_service_get_port(&error);
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (error) {
199 g_clear_error(&error);
200 break;
201 }
202
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (port <= 0) {
203 5 break;
204 }
205
1/1
✓ Branch 1 taken 4 times.
4 g_usleep(100UL * 1000UL); // 100 ms
206 4 count++;
207 }
208
209 5 return 0;
210 }
211
212 2 extern int gittor_service_restart() {
213 2 gittor_service_stop();
214 2 gittor_service_start();
215 2 return 0;
216 }
217
218 2 extern void gittor_service_disconnect() {
219 // If already disconnected, skip
220
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (s_socket == NULL) {
221 1 return;
222 }
223
224 // Tell the service the connection is over
225 1 header_t header = {.magic = MAGIC, .type = END, .len = -1};
226
1/1
✓ Branch 1 taken 1 times.
1 g_socket_send(s_socket, (void*)&header, sizeof(header), NULL, NULL);
227
1/1
✓ Branch 1 taken 1 times.
1 g_object_unref(s_socket);
228 1 s_socket = NULL;
229 }
230
231 3 extern const char* gittor_service_status() {
232 static const char up[] = "up";
233 static const char down[] = "down";
234
235 // Try to connect
236 3 GError* error = NULL;
237
1/1
✓ Branch 1 taken 3 times.
3 get_connection(false, &error);
238
239
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (error) {
240
1/1
✓ Branch 1 taken 1 times.
1 g_clear_error(&error);
241 3 return down;
242 }
243
244 2 return up;
245 }
246
247 2 extern int gittor_service_ping() {
248 2 GError* error = NULL;
249 char ping[256];
250 2 packet_t msg = {.data = ping, .type = PING};
251
1/1
✓ Branch 1 taken 2 times.
2 msg.len = g_snprintf(ping, sizeof(ping) - 1, "pid: %d thread: %p", getpid(),
252
1/1
✓ Branch 1 taken 2 times.
2 (void*)g_thread_self()) +
253 1;
254
1/1
✓ Branch 1 taken 2 times.
2 packet_t* resp = gittor_service_send(&msg, &error);
255
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (error) {
257 free(resp);
258 g_printerr("Failed to ping service: %s\n", error->message);
259 g_clear_error(&error);
260 2 return 1;
261 }
262
263
1/1
✓ Branch 1 taken 2 times.
2 printf("[GitTor CLI] Recieved: '%s'\n", (char*)resp->data);
264 2 free(resp->data);
265 2 free(resp);
266 2 return 0;
267 }
268