1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup test
36 * @ingroup test
37 * @brief skeleton file
38 *
39 * skeleton test program, will not be installed with a "make install"
40 *
41 * To create a new test based on the skeleton:
42 *
43 * _ copy the folder
44 * _ replace "skeleton" by the name of the test
45 * _ add the test to the top level Makefile.am and configure.ac
46 *
47 */
48
49 #include <dnscore/dnscore.h>
50 #include <dnscore/random.h>
51 #include <dnscore/message.h>
52 #include <dnscore/config_settings.h>
53 #include <dnscore/host_address.h>
54 #include <dnscore/format.h>
55 #include <dnscore/thread_pool.h>
56 #include <dnscore/buffer_output_stream.h>
57 #include <dnscore/logger_channel_stream.h>
58 #include <dnscore/file_output_stream.h>
59
60 #define HEAP_SIZE 0x40000000
61
62 static logger_handle *notify_log = LOGGER_HANDLE_SINK;
63
64 #define MODULE_MSG_HANDLE notify_log
65
help()66 static void help()
67 {
68 println("parameters: server-ip zone [count [loops]]");
69 flushout();
70 }
71
72 struct notify_send_args_s
73 {
74 host_address *ip;
75 int count;
76 int loops;
77 u8 zone[256];
78 };
79
notify_send(void * args_)80 static void *notify_send(void* args_)
81 {
82 struct notify_send_args_s *args = (struct notify_send_args_s*)args_;
83
84 ya_result ret;
85 random_ctx rndctx = random_init_auto();
86 message_data* mesg = message_new_instance();
87
88 s64 last = timeus();
89
90 s64 total_time = 0;
91 s64 max_time = 0;
92 s64 min_time = MAX_S64;
93 s64 faults = 0;
94 s64 delta;
95
96 for(int i = 0; i < args->loops; ++i)
97 {
98 u16 id = (u16)random_next(rndctx);
99 message_make_notify(mesg, id, args->zone, TYPE_SOA, CLASS_IN);
100
101 s64 now = timeus();
102
103 if(now - last > ONE_SECOND_US)
104 {
105 s64 next = last + ONE_SECOND_US;
106 last = next;
107 while(next < now)
108 {
109 last = next;
110 next += ONE_SECOND_US;
111 }
112
113 double mean_reply_time = total_time;
114 mean_reply_time /= (i + 1);
115 mean_reply_time /= ONE_SECOND_US_F;
116
117 double max_reply_time = max_time;
118 max_reply_time /= ONE_SECOND_US_F;
119 double min_reply_time = min_time;
120 min_reply_time /= ONE_SECOND_US_F;
121
122 log_info("notify %{dnsname} to %{hostaddr} %i/%i, %lli faults, mean reply time = %3.6fs [%3.6fs; %3.6fs]", args->zone, args->ip, i, args->loops, faults, mean_reply_time, min_reply_time, max_reply_time);
123 }
124
125 if(ISOK(ret = message_query_udp_with_timeout(mesg, args->ip, 600, 0)))
126 {
127 s64 reply = timeus();
128 delta = reply - now;
129
130 // message_print_format_dig(termout, message_get_buffer_const(mesg), message_get_size(mesg), 15, 0);
131 }
132 else
133 {
134 s64 reply = timeus();
135 delta = reply - now;
136 ++faults;
137
138 log_err("%{dnsname} network failed with: %r", args->zone, ret);
139 --i;
140 }
141
142 total_time += delta;
143 max_time = MAX(delta, max_time);
144 min_time = MIN(delta, min_time);
145
146 // message_reset_control(mesg);
147 }
148
149 message_free(mesg);
150
151 return NULL;
152 }
153
154 int
main(int argc,char * argv[])155 main(int argc, char *argv[])
156 {
157 ya_result ret;
158
159 struct notify_send_args_s args;
160
161 args.ip = NULL;
162 args.zone[0] = '\0';
163 args.count = 1;
164
165 /* initializes the core library */
166 dnscore_init();
167
168 if(argc < 3)
169 {
170 help();
171 return EXIT_FAILURE;
172 }
173
174 static const anytype defaults = {._8u8={CONFIG_HOST_LIST_FLAGS_DEFAULT,128,0,0,0,0,0,0}};
175
176 if(FAIL(ret = config_set_host_list(argv[1], &args.ip, defaults)))
177 {
178 formatln("%s is an invalid ip: %r", argv[1], ret);
179 help();
180 return EXIT_FAILURE;
181 }
182
183 if(args.ip->port == 0)
184 {
185 args.ip->port = NU16(53);
186 }
187
188 if(FAIL(ret = cstr_to_dnsname_with_check(args.zone, argv[2])))
189 {
190 formatln("%s is an invalid zone: %r", argv[2], ret);
191 help();
192 return EXIT_FAILURE;
193 }
194
195 if(argc >= 4)
196 {
197 args.count = atoi(argv[3]);
198 if(args.count < 0)
199 {
200 args.count = 1;
201 }
202 if(args.count > 255)
203 {
204 args.count = 255;
205 }
206 }
207
208 if(argc >= 5)
209 {
210 args.loops = atoi(argv[4]);
211 if(args.loops < 0)
212 {
213 args.loops = 1;
214 }
215 }
216
217 logger_init_ex(0x100000, HEAP_SIZE);
218 logger_start();
219
220 {
221 output_stream stdout_os;
222 logger_channel *stdout_channel;
223 static const char * const log_file_name = "/tmp/notify-test.log";
224
225 unlink(log_file_name);
226
227 fd_output_stream_attach(&stdout_os, dup_ex(1));
228 /*
229 ya_result ret;
230 if(FAIL(ret = file_output_stream_create(&stdout_os, log_file_name, 0644)))
231 {
232 formatln("failed to create %s: %r", log_file_name, ret);
233 exit(1);
234 }
235 */
236 buffer_output_stream_init(&stdout_os, &stdout_os, 65536);
237 stdout_channel = logger_channel_alloc();
238 logger_channel_stream_open(&stdout_os, FALSE, stdout_channel);
239 logger_channel_register("stdout", stdout_channel);
240 logger_handle_create("notify", ¬ify_log);
241
242 logger_handle_add_channel("notify", MSG_ALL_MASK, "stdout");
243
244 logger_flush();
245
246 sleep(1);
247 }
248
249
250 message_edns0_setmaxsize(4096);
251
252 struct thread_pool_s *tp = thread_pool_init_ex(args.count, args.count * 2, "notify");
253
254 // thread_pool_wait_all_running(tp);
255
256 if(tp != NULL)
257 {
258 for(int i = 0; i < args.count; ++i)
259 {
260 log_info("starting notify_send %i", i);
261 thread_pool_enqueue_call(tp, notify_send, &args, NULL, "notify");
262 }
263 }
264
265 thread_pool_destroy(tp);
266 tp = NULL;
267
268 flushout();
269 flusherr();
270 fflush(NULL);
271
272 dnscore_finalize();
273
274 return EXIT_SUCCESS;
275 }
276