GCC Code Coverage Report


Directory: src/
File: src/backend/modules/pacrunner-duktape.c
Date: 2023-01-04 17:35:37
Exec Total Coverage
Lines: 29 78 37.2%
Branches: 9 29 31.0%

Line Branch Exec Source
1 /* pacrunner-duktape.c
2 *
3 * Copyright 2022 Jan-Michael Brummer
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * SPDX-License-Identifier: LGPL-2.1-or-later
20 */
21
22 #include <unistd.h>
23 #ifdef __WIN32__
24 #include <ws2tcpip.h>
25 #else
26 #include <netdb.h>
27 #endif
28 #include <glib-object.h>
29
30 #include "pacrunner-duktape.h"
31 #include "pacutils.h"
32 #include "px-module.h"
33 #include "px-pacrunner-module.h"
34
35 #include "duktape.h"
36
37 struct _PxDuktapeModule {
38 GObject parent_instance;
39 duk_context *ctx;
40 };
41
42 static void module_interface_init (gpointer g_iface,
43 gpointer data);
44
45
6/7
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 18 times.
48 G_DEFINE_TYPE_WITH_CODE (PxDuktapeModule, px_duktape_module,
46 PX_TYPE_MODULE,
47 G_IMPLEMENT_INTERFACE (PX_TYPE_PACRUNNER_MODULE, module_interface_init);
48 );
49
50 static duk_ret_t
51 dns_resolve (duk_context *ctx)
52 {
53 const char *hostname = NULL;
54 struct addrinfo *info;
55 char tmp[INET6_ADDRSTRLEN + 1];
56
57 if (duk_get_top (ctx) != 1) {
58 /* Invalid number of arguments */
59 return 0;
60 }
61
62 /* We do not need to free the string - It's managed by Duktape. */
63 hostname = duk_get_string (ctx, 0);
64 if (!hostname)
65 return 0;
66
67 /* Look it up */
68 if (getaddrinfo (hostname, NULL, NULL, &info))
69 return 0;
70
71 /* Try for IPv4 */
72 if (getnameinfo (info->ai_addr,
73 info->ai_addrlen,
74 tmp,
75 INET6_ADDRSTRLEN + 1,
76 NULL,
77 0,
78 NI_NUMERICHOST)) {
79 freeaddrinfo (info);
80 duk_push_null (ctx);
81 return 1;
82 }
83 freeaddrinfo (info);
84
85 /* Create the return value */
86 duk_push_string (ctx, tmp);
87
88 return 1;
89 }
90
91 static duk_ret_t
92 my_ip_address (duk_context *ctx)
93 {
94 char hostname[1024];
95
96 hostname[sizeof (hostname) - 1] = '\0';
97
98 if (!gethostname (hostname, sizeof (hostname) - 1)) {
99 duk_push_string (ctx, hostname);
100 return dns_resolve (ctx);
101 }
102
103 return duk_error (ctx, DUK_ERR_ERROR, "Unable to find hostname!");
104 }
105
106 static void
107 10 px_duktape_module_init (PxDuktapeModule *self)
108 {
109 10 self->ctx = duk_create_heap_default ();
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!self->ctx)
111 return;
112
113 10 duk_push_c_function (self->ctx, dns_resolve, 1);
114 10 duk_put_global_string (self->ctx, "dnsResolve");
115
116 10 duk_push_c_function (self->ctx, my_ip_address, 1);
117 10 duk_put_global_string (self->ctx, "myIpAddress");
118
119 10 duk_push_string (self->ctx, JAVASCRIPT_ROUTINES);
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (duk_peval_noresult (self->ctx))
121 goto error;
122
123 10 return;
124
125 error:
126 duk_destroy_heap (self->ctx);
127 }
128
129 static void
130 10 px_duktape_dispose (GObject *object)
131 {
132 10 PxDuktapeModule *self = PX_DUKTAPE_MODULE (object);
133
134
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 g_clear_pointer (&self->ctx, duk_destroy_heap);
135
136 10 G_OBJECT_CLASS (px_duktape_module_parent_class)->dispose (object);
137 10 }
138
139
140 static void
141 2 px_duktape_module_class_init (PxDuktapeModuleClass *klass)
142 {
143 2 GObjectClass *object_class = G_OBJECT_CLASS (klass);
144
145 /* object_class->constructed = px_duktape_constructed; */
146 2 object_class->dispose = px_duktape_dispose;
147 2 }
148
149 void
150 px_duktape_set_pac (PxModule *px_module,
151 const char *pac)
152 {
153 PxDuktapeModule *self = PX_DUKTAPE_MODULE (px_module);
154
155 duk_push_string (self->ctx, pac);
156
157 if (duk_peval_noresult (self->ctx)) {
158 return;
159 }
160 }
161
162 char *
163 px_duktape_run (PxModule *px_module,
164 GUri *uri)
165 {
166 PxDuktapeModule *self = PX_DUKTAPE_MODULE (px_module);
167 duk_int_t result;
168
169 g_print ("%s: ENTER\n", __FUNCTION__);
170
171 duk_get_global_string (self->ctx, "FindProxyForURL");
172 duk_push_string (self->ctx, g_uri_to_string (uri));
173 duk_push_string (self->ctx, g_uri_get_host (uri));
174 result = duk_pcall (self->ctx, 2);
175
176 if (result == 0) {
177 const char *proxy = duk_get_string (self->ctx, 0);
178 char *proxy_string;
179
180 if (!proxy) {
181 duk_pop (self->ctx);
182 return g_strdup ("");
183 }
184
185 proxy_string = g_strdup (proxy);
186
187 duk_pop (self->ctx);
188
189 return proxy_string;
190 }
191
192 duk_pop (self->ctx);
193 return g_strdup ("");
194 }
195
196 static void
197 2 module_interface_init (gpointer g_iface,
198 gpointer data)
199 {
200 2 PxPacrunnerModuleInterface *iface = g_iface;
201
202 2 iface->name = "Duktape";
203 2 iface->version = 1;
204
205 2 iface->set_pac = px_duktape_set_pac;
206 2 iface->run = px_duktape_run;
207 2 }
208
209 PxModule *
210 10 px_module_create (void)
211 {
212 10 return g_object_new (PX_TYPE_DUKTAPE_MODULE, NULL);
213 }
214