1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 /*****************************************************************************
25 * Filename: APITestCliRemote.cc
26 * Purpose: An interactive cli to test remote mgmt API; UNIT TEST for mgmtAPI
27 * Created: lant
28 *
29 ***************************************************************************/
30
31 /***************************************************************************
32 * Possible Commands:
33 ***************************************************************************
34 * Control Operations:
35 * -------------------
36 * state: returns ON (proxy is on) or OFF (proxy is off)
37 * start:<tsArgs> - turns Proxy on, the tsArgs is optional;
38 * it can either be "hostdb" or "all",
39 * eg. start, start:hostdb, start:all
40 * stop: turns Proxy off
41 * restart: restarts Traffic Manager (Traffic Cop must be running)
42 *
43 * File operations:
44 * ---------------
45 * read_file: reads hosting.config file
46 * proxy.config.xxx (a records.config variable): returns value of that record
47 * records: tests get/set/get a record of each different type
48 * (int, float, counter, string)
49 * err_recs: stress test record get/set functions by purposely entering
50 * invalid record names and/or values
51 * get_mlt: tests TSRecordGetMlt
52 * set_mlt: tests TSRecordSetMlt
53 *
54 * read_url: tests TSReadFromUrl works by retrieving two valid urls
55 * test_url: tests robustness of TSReadFromUrl using invalid urls
56 *
57 * Event Operations:
58 * ----------------
59 * active_events: lists the names of all currently active events
60 * MGMT_ALARM_xxx (event_name specified in CoreAPIShared.h or Alarms.h):
61 * resolves the specified event
62 * register: registers a generic callback (=eventCallbackFn) which
63 * prints out the event name whenever an event is signalled
64 * unregister: unregisters the generic callback function eventCallbackFn
65 *
66 * Diags
67 * ----
68 * diags - uses STATUS, NOTE, FATAL, ERROR diags
69 *
70 * Statistics
71 * ----------
72 * set_stats - sets dummy values for selected group of NODE, PROCESS
73 * records
74 * print_stats - prints the values for the same selected group of records
75 * reset_stats - resets all statistics to default values
76 */
77
78 #include "tscore/ink_config.h"
79 #include "tscore/ink_defs.h"
80 #include "tscore/ink_memory.h"
81 #include <cstdlib>
82 #include <cstring>
83 #include <cstdio>
84 #include <strings.h>
85 #include "tscore/ink_string.h"
86
87 #include "mgmtapi.h"
88
89 // refer to test_records() function
90 #define TEST_STRING 1
91 #define TEST_FLOAT 1
92 #define TEST_INT 1
93 #define TEST_COUNTER 1
94 #define TEST_REC_SET 1
95 #define TEST_REC_GET 0
96 #define TEST_REC_GET_2 0
97
98 #define SET_INT 0
99
100 /***************************************************************************
101 * Printing Helper Functions
102 ***************************************************************************/
103
104 /* ------------------------------------------------------------------------
105 * print_err
106 * ------------------------------------------------------------------------
107 * used to print the error description associated with the TSMgmtError err
108 */
109 void
print_err(const char * module,TSMgmtError err)110 print_err(const char *module, TSMgmtError err)
111 {
112 char *err_msg;
113
114 err_msg = TSGetErrorMessage(err);
115 printf("(%s) ERROR: %s\n", module, err_msg);
116
117 if (err_msg) {
118 TSfree(err_msg);
119 }
120 }
121
122 /*-------------------------------------------------------------
123 * print_string_list
124 *-------------------------------------------------------------*/
125 void
print_string_list(TSStringList list)126 print_string_list(TSStringList list)
127 {
128 int i, count, buf_pos = 0;
129 char buf[1000];
130
131 if (!list) {
132 return;
133 }
134 count = TSStringListLen(list);
135 for (i = 0; i < count; i++) {
136 char *str = TSStringListDequeue(list);
137 snprintf(buf + buf_pos, sizeof(buf) - buf_pos, "%s,", str);
138 buf_pos = strlen(buf);
139 TSStringListEnqueue(list, str);
140 }
141 printf("%s \n", buf);
142 }
143
144 /*-------------------------------------------------------------
145 * print_int_list
146 *-------------------------------------------------------------*/
147 void
print_int_list(TSIntList list)148 print_int_list(TSIntList list)
149 {
150 int i, count, buf_pos = 0;
151 char buf[1000];
152
153 count = TSIntListLen(list);
154 for (i = 0; i < count; i++) {
155 int *elem = TSIntListDequeue(list);
156 snprintf(buf + buf_pos, sizeof(buf) - buf_pos, "%d:", *elem);
157 buf_pos = strlen(buf);
158 TSIntListEnqueue(list, elem);
159 }
160 printf("Int List: %s \n", buf);
161 }
162
163 /***************************************************************************
164 * Control Testing
165 ***************************************************************************/
166 void
print_proxy_state()167 print_proxy_state()
168 {
169 TSProxyStateT state = TSProxyStateGet();
170
171 switch (state) {
172 case TS_PROXY_ON:
173 printf("Proxy State = ON\n");
174 break;
175 case TS_PROXY_OFF:
176 printf("Proxy State = OFF\n");
177 break;
178 default:
179 printf("ERROR: Proxy State Undefined!\n");
180 break;
181 }
182 }
183
184 // starts Traffic Server (turns proxy on)
185 void
start_TS(char * tsArgs)186 start_TS(char *tsArgs)
187 {
188 TSMgmtError ret;
189 TSCacheClearT clear = TS_CACHE_CLEAR_NONE;
190 char *args;
191
192 strtok(tsArgs, ":");
193 args = strtok(nullptr, ":");
194 if (args) {
195 if (strcmp(args, "all\n") == 0) {
196 clear = TS_CACHE_CLEAR_CACHE;
197 } else if (strcmp(args, "hostdb\n") == 0) {
198 clear = TS_CACHE_CLEAR_HOSTDB;
199 }
200 } else {
201 clear = TS_CACHE_CLEAR_NONE;
202 }
203
204 printf("STARTING PROXY with cache: %d\n", clear);
205 if ((ret = TSProxyStateSet(TS_PROXY_ON, clear)) != TS_ERR_OKAY) {
206 printf("[TSProxyStateSet] turn on FAILED\n");
207 }
208 print_err("start_TS", ret);
209 }
210
211 // stops Traffic Server (turns proxy off)
212 void
stop_TS()213 stop_TS()
214 {
215 TSMgmtError ret;
216
217 printf("STOPPING PROXY\n");
218 if ((ret = TSProxyStateSet(TS_PROXY_OFF, TS_CACHE_CLEAR_NONE)) != TS_ERR_OKAY) {
219 printf("[TSProxyStateSet] turn off FAILED\n");
220 }
221 print_err("stop_TS", ret);
222 }
223
224 // restarts Traffic Manager (Traffic Cop must be running)
225 void
restart()226 restart()
227 {
228 TSMgmtError ret;
229
230 printf("RESTART\n");
231 if ((ret = TSRestart(true)) != TS_ERR_OKAY) {
232 printf("[TSRestart] FAILED\n");
233 }
234
235 print_err("restart", ret);
236 }
237
238 // rereads all the configuration files
239 void
reconfigure()240 reconfigure()
241 {
242 TSMgmtError ret;
243
244 printf("RECONFIGURE\n");
245 if ((ret = TSReconfigure()) != TS_ERR_OKAY) {
246 printf("[TSReconfigure] FAILED\n");
247 }
248
249 print_err("reconfigure", ret);
250 }
251
252 /* ------------------------------------------------------------------------
253 * test_action_need
254 * ------------------------------------------------------------------------
255 * tests if correct action need is returned when requested record is set
256 */
257 void
test_action_need()258 test_action_need()
259 {
260 TSActionNeedT action;
261
262 // RU_NULL record
263 TSRecordSetString("proxy.config.proxy_name", "proxy_dorky", &action);
264 printf("[TSRecordSetString] proxy.config.proxy_name \n\tAction Should: [%d]\n\tAction is : [%d]\n", TS_ACTION_UNDEFINED,
265 action);
266 }
267
268 /* Bouncer the traffic_server process(es) */
269 void
bounce()270 bounce()
271 {
272 TSMgmtError ret;
273
274 printf("BOUNCER\n");
275 if ((ret = TSBounce(true)) != TS_ERR_OKAY) {
276 printf("[TSBounce] FAILED\n");
277 }
278
279 print_err("bounce", ret);
280 }
281
282 /***************************************************************************
283 * Record Testing
284 ***************************************************************************/
285
286 /* ------------------------------------------------------------------------
287 * test_error_records
288 * ------------------------------------------------------------------------
289 * stress test error handling by purposely being dumb; send requests to
290 * get invalid record names
291 */
292 void
test_error_records()293 test_error_records()
294 {
295 TSInt port1, new_port = 8080;
296 TSActionNeedT action;
297 TSMgmtError ret;
298 TSCounter ctr1;
299
300 printf("\n");
301 // test get integer
302 fprintf(stderr, "Test invalid record names\n");
303
304 ret = TSRecordGetInt("proy.config.cop.core_signal", &port1);
305 if (ret != TS_ERR_OKAY) {
306 print_err("TSRecordGetInt", ret);
307 } else {
308 printf("[TSRecordGetInt] proxy.config.cop.core_signal=%" PRId64 " \n", port1);
309 }
310
311 // test set integer
312 ret = TSRecordSetInt("proy.config.cop.core_signal", new_port, &action);
313 print_err("TSRecordSetInt", ret);
314
315 printf("\n");
316 if (TSRecordGetCounter("proxy.press.socks.connections_successful", &ctr1) != TS_ERR_OKAY) {
317 printf("TSRecordGetCounter FAILED!\n");
318 } else {
319 printf("[TSRecordGetCounter]proxy.process.socks.connections_successful=%" PRId64 " \n", ctr1);
320 }
321 }
322
323 /* ------------------------------------------------------------------------
324 * test_records
325 * ------------------------------------------------------------------------
326 * stress test record functionality by getting and setting different
327 * records types; use the #defines defined above to determine which
328 * type of tests you'd like turned on/off
329 */
330 void
test_records()331 test_records()
332 {
333 TSActionNeedT action;
334 char *rec_value;
335 char new_str[] = "new_record_value";
336 TSInt port1, port2, new_port = 52432;
337 TSCounter ctr1, ctr2, new_ctr = 6666;
338 TSMgmtError err;
339
340 /********************* START TEST SECTION *****************/
341 printf("\n\n");
342
343 #if SET_INT
344 // test set integer
345 if (TSRecordSetInt("proxy.config.cop.core_signal", new_port, &action) != TS_ERR_OKAY)
346 printf("TSRecordSetInt FAILED!\n");
347 else
348 printf("[TSRecordSetInt] proxy.config.cop.core_signal=%" PRId64 " \n", new_port);
349 #endif
350
351 #if TEST_REC_GET
352 TSRecordEle *rec_ele;
353 // retrieve a string value record using generic RecordGet
354 rec_ele = TSRecordEleCreate();
355 if (TSRecordGet("proxy.config.http.cache.vary_default_other", rec_ele) != TS_ERR_OKAY)
356 printf("TSRecordGet FAILED!\n");
357 else
358 printf("[TSRecordGet] proxy.config.http.cache.vary_default_other=%s\n", rec_ele->string_val);
359
360 TSRecordEleDestroy(rec_ele);
361 printf("\n\n");
362 #endif
363
364 #if TEST_REC_GET_2
365 // retrieve a string value record using generic RecordGet
366 rec_ele = TSRecordEleCreate();
367 if (TSRecordGet("proxy.config.proxy_name", rec_ele) != TS_ERR_OKAY)
368 printf("TSRecordGet FAILED!\n");
369 else
370 printf("[TSRecordGet] proxy.config.proxy_name=%s\n", rec_ele->string_val);
371
372 TSRecordEleDestroy(rec_ele);
373 printf("\n\n");
374 #endif
375
376 #if TEST_STRING
377 // retrieve an string value record using GetString
378 err = TSRecordGetString("proxy.config.proxy_name", &rec_value);
379 if (err != TS_ERR_OKAY) {
380 print_err("TSRecordGetString", err);
381 } else {
382 printf("[TSRecordGetString] proxy.config.proxy_name=%s\n", rec_value);
383 }
384 TSfree(rec_value);
385 rec_value = nullptr;
386
387 // test RecordSet
388 err = TSRecordSetString("proxy.config.proxy_name", (TSString)new_str, &action);
389 if (err != TS_ERR_OKAY) {
390 print_err("TSRecordSetString", err);
391 } else {
392 printf("[TSRecordSetString] proxy.config.proxy_name=%s\n", new_str);
393 }
394
395 // get
396 err = TSRecordGetString("proxy.config.proxy_name", &rec_value);
397 if (err != TS_ERR_OKAY) {
398 print_err("TSRecordGetString", err);
399 } else {
400 printf("[TSRecordGetString] proxy.config.proxy_name=%s\n", rec_value);
401 }
402 printf("\n");
403 TSfree(rec_value);
404 #endif
405
406 #if TEST_INT
407 printf("\n");
408 // test get integer
409 if (TSRecordGetInt("proxy.config.cop.core_signal", &port1) != TS_ERR_OKAY) {
410 printf("TSRecordGetInt FAILED!\n");
411 } else {
412 printf("[TSRecordGetInt] proxy.config.cop.core_signal=%" PRId64 " \n", port1);
413 }
414
415 // test set integer
416 if (TSRecordSetInt("proxy.config.cop.core_signal", new_port, &action) != TS_ERR_OKAY) {
417 printf("TSRecordSetInt FAILED!\n");
418 } else {
419 printf("[TSRecordSetInt] proxy.config.cop.core_signal=%" PRId64 " \n", new_port);
420 }
421
422 if (TSRecordGetInt("proxy.config.cop.core_signal", &port2) != TS_ERR_OKAY) {
423 printf("TSRecordGetInt FAILED!\n");
424 } else {
425 printf("[TSRecordGetInt] proxy.config.cop.core_signal=%" PRId64 " \n", port2);
426 }
427 printf("\n");
428 #endif
429
430 #if TEST_COUNTER
431 printf("\n");
432
433 if (TSRecordGetCounter("proxy.process.socks.connections_successful", &ctr1) != TS_ERR_OKAY) {
434 printf("TSRecordGetCounter FAILED!\n");
435 } else {
436 printf("[TSRecordGetCounter]proxy.process.socks.connections_successful=%" PRId64 " \n", ctr1);
437 }
438
439 if (TSRecordSetCounter("proxy.process.socks.connections_successful", new_ctr, &action) != TS_ERR_OKAY) {
440 printf("TSRecordSetCounter FAILED!\n");
441 } else {
442 printf("[TSRecordSetCounter] proxy.process.socks.connections_successful=%" PRId64 " \n", new_ctr);
443 }
444
445 if (TSRecordGetCounter("proxy.process.socks.connections_successful", &ctr2) != TS_ERR_OKAY) {
446 printf("TSRecordGetCounter FAILED!\n");
447 } else {
448 printf("[TSRecordGetCounter]proxy.process.socks.connections_successful=%" PRId64 " \n", ctr2);
449 }
450 printf("\n");
451 #endif
452 }
453
454 // retrieves the value of the "proxy.config.xxx" record requested at input
455 void
test_rec_get(char * rec_name)456 test_rec_get(char *rec_name)
457 {
458 TSRecordEle *rec_ele;
459 TSMgmtError ret;
460 char *name;
461
462 name = ats_strdup(rec_name);
463 printf("[test_rec_get] Get Record: %s\n", name);
464
465 // retrieve a string value record using generic RecordGet
466 rec_ele = TSRecordEleCreate();
467 if ((ret = TSRecordGet(name, rec_ele)) != TS_ERR_OKAY) {
468 printf("TSRecordGet FAILED!\n");
469 } else {
470 switch (rec_ele->rec_type) {
471 case TS_REC_INT:
472 printf("[TSRecordGet] %s=%" PRId64 "\n", name, rec_ele->valueT.int_val);
473 break;
474 case TS_REC_COUNTER:
475 printf("[TSRecordGet] %s=%" PRId64 "\n", name, rec_ele->valueT.counter_val);
476 break;
477 case TS_REC_FLOAT:
478 printf("[TSRecordGet] %s=%f\n", name, rec_ele->valueT.float_val);
479 break;
480 case TS_REC_STRING:
481 printf("[TSRecordGet] %s=%s\n", name, rec_ele->valueT.string_val);
482 break;
483 default:
484 // Handled here:
485 // TS_REC_UNDEFINED
486 break;
487 }
488 }
489
490 print_err("TSRecordGet", ret);
491
492 TSRecordEleDestroy(rec_ele);
493 TSfree(name);
494 }
495
496 /* ------------------------------------------------------------------------
497 * test_record_get_mlt
498 * ------------------------------------------------------------------------
499 * Creates a list of record names to retrieve, and then batch request to
500 * get list of records
501 */
502 void
test_record_get_mlt()503 test_record_get_mlt()
504 {
505 TSStringList name_list;
506 TSList rec_list;
507 int i, num;
508 char *v1, *v2, *v3, *v6, *v7;
509 TSMgmtError ret;
510
511 name_list = TSStringListCreate();
512 rec_list = TSListCreate();
513
514 const size_t v1_size = (sizeof(char) * (strlen("proxy.config.proxy_name") + 1));
515 v1 = static_cast<char *>(TSmalloc(v1_size));
516 ink_strlcpy(v1, "proxy.config.proxy_name", v1_size);
517 const size_t v2_size = (sizeof(char) * (strlen("proxy.config.bin_path") + 1));
518 v2 = static_cast<char *>(TSmalloc(v2_size));
519 ink_strlcpy(v2, "proxy.config.bin_path", v2_size);
520 const size_t v3_size = (sizeof(char) * (strlen("proxy.config.manager_binary") + 1));
521 v3 = static_cast<char *>(TSmalloc(v3_size));
522 ink_strlcpy(v3, "proxy.config.manager_binary", v3_size);
523 const size_t v6_size = (sizeof(char) * (strlen("proxy.config.env_prep") + 1));
524 v6 = static_cast<char *>(TSmalloc(v6_size));
525 ink_strlcpy(v6, "proxy.config.env_prep", v6_size);
526 const size_t v7_size = (sizeof(char) * (strlen("proxy.config.cop.core_signal") + 1));
527 v7 = static_cast<char *>(TSmalloc(v7_size));
528 ink_strlcpy(v7, "proxy.config.cop.core_signal", v7_size);
529
530 // add the names to the get_list
531 TSStringListEnqueue(name_list, v1);
532 TSStringListEnqueue(name_list, v2);
533 TSStringListEnqueue(name_list, v3);
534 TSStringListEnqueue(name_list, v6);
535 TSStringListEnqueue(name_list, v7);
536
537 num = TSStringListLen(name_list);
538 printf("Num Records to Get: %d\n", num);
539 ret = TSRecordGetMlt(name_list, rec_list);
540 // free the string list
541 TSStringListDestroy(name_list);
542 if (ret != TS_ERR_OKAY) {
543 print_err("TSStringListDestroy", ret);
544 }
545
546 for (i = 0; i < num; i++) {
547 TSRecordEle *rec_ele = static_cast<TSRecordEle *>(TSListDequeue(rec_list));
548 if (!rec_ele) {
549 printf("ERROR\n");
550 break;
551 }
552 printf("Record: %s = ", rec_ele->rec_name);
553 switch (rec_ele->rec_type) {
554 case TS_REC_INT:
555 printf("%" PRId64 "\n", rec_ele->valueT.int_val);
556 break;
557 case TS_REC_COUNTER:
558 printf("%" PRId64 "\n", rec_ele->valueT.counter_val);
559 break;
560 case TS_REC_FLOAT:
561 printf("%f\n", rec_ele->valueT.float_val);
562 break;
563 case TS_REC_STRING:
564 printf("%s\n", rec_ele->valueT.string_val);
565 break;
566 default:
567 // Handled here:
568 // TS_REC_UNDEFINED
569 break;
570 }
571 TSRecordEleDestroy(rec_ele);
572 }
573
574 TSListDestroy(rec_list); // must dequeue and free each string individually
575
576 return;
577 }
578
579 /* ------------------------------------------------------------------------
580 * test_record_set_mlt
581 * ------------------------------------------------------------------------
582 * Creates a list of TSRecordEle's, and then batch request to set records
583 * Also checks to make sure correct action_need type is set.
584 */
585 void
test_record_set_mlt()586 test_record_set_mlt()
587 {
588 TSList list;
589 TSRecordEle *ele1, *ele2;
590 TSActionNeedT action = TS_ACTION_UNDEFINED;
591 TSMgmtError err;
592
593 list = TSListCreate();
594
595 ele1 = TSRecordEleCreate(); // TS_TYPE_UNDEFINED action
596 ele1->rec_name = TSstrdup("proxy.config.cli_binary");
597 ele1->rec_type = TS_REC_STRING;
598 ele1->valueT.string_val = TSstrdup(ele1->rec_name);
599
600 ele2 = TSRecordEleCreate(); // undefined action
601 ele2->rec_name = TSstrdup("proxy.config.cop.core_signal");
602 ele2->rec_type = TS_REC_INT;
603 ele2->valueT.int_val = -4;
604
605 TSListEnqueue(list, ele1);
606 TSListEnqueue(list, ele2);
607
608 err = TSRecordSetMlt(list, &action);
609 print_err("TSRecordSetMlt", err);
610 fprintf(stderr, "[TSRecordSetMlt] Action Required: %d\n", action);
611
612 // cleanup: need to iterate through list and delete each ele
613 int count = TSListLen(list);
614 for (int i = 0; i < count; i++) {
615 TSRecordEle *ele = static_cast<TSRecordEle *>(TSListDequeue(list));
616 TSRecordEleDestroy(ele);
617 }
618 TSListDestroy(list);
619 }
620
621 /***************************************************************************
622 * File I/O Testing
623 ***************************************************************************/
624
625 // if valid==true, then use a valid url to read
626 void
test_read_url(bool valid)627 test_read_url(bool valid)
628 {
629 char *header = nullptr;
630 int headerSize;
631 char *body = nullptr;
632 int bodySize;
633 TSMgmtError err;
634
635 if (!valid) {
636 // first try
637
638 err = TSReadFromUrlEx("hsdfasdf.com:80/index.html", &header, &headerSize, &body, &bodySize, 50000);
639 if (err != TS_ERR_OKAY) {
640 print_err("TSReadFromUrlEx", err);
641 } else {
642 printf("--------------------------------------------------------------\n");
643 // printf("The header...\n%s\n%d\n", *header, *headerSize);
644 printf("--------------------------------------------------------------\n");
645 printf("The body...\n%s\n%d\n", body, bodySize);
646 }
647 if (body) {
648 TSfree(body);
649 }
650 if (header) {
651 TSfree(header);
652 }
653
654 err = TSReadFromUrlEx("http://sadfasdfi.com:80/", &header, &headerSize, &body, &bodySize, 50000);
655 if (err != TS_ERR_OKAY) {
656 print_err("TSReadFromUrlEx", err);
657 } else {
658 printf("---------------------------------------------------------------\n");
659 printf("The header...\n%s\n%d\n", header, headerSize);
660 printf("-------------------------------------------------------------\n");
661 printf("The body...\n%s\n%d\n", body, bodySize);
662 }
663 if (header) {
664 TSfree(header);
665 }
666 if (body) {
667 TSfree(body);
668 }
669
670 } else { // use valid urls
671 err = TSReadFromUrlEx("lakota.example.com:80/", &header, &headerSize, &body, &bodySize, 50000);
672
673 if (err != TS_ERR_OKAY) {
674 print_err("TSReadFromUrlEx", err);
675 } else {
676 printf("---------------------------------------------------------------\n");
677 printf("The header...\n%s\n%d\n", header, headerSize);
678 printf("-------------------------------------------------------------\n");
679 printf("The body...\n%s\n%d\n", body, bodySize);
680 }
681 if (header) {
682 TSfree(header);
683 }
684 if (body) {
685 TSfree(body);
686 }
687
688 // read second url
689 err = TSReadFromUrlEx("http://www.apache.org:80/index.html", &header, &headerSize, &body, &bodySize, 50000);
690 if (err != TS_ERR_OKAY) {
691 print_err("TSReadFromUrlEx", err);
692 } else {
693 printf("---------------------------------------------------------------\n");
694 printf("The header...\n%s\n%d\n", header, headerSize);
695 printf("-------------------------------------------------------------\n");
696 printf("The body...\n%s\n%d\n", body, bodySize);
697 }
698 if (header) {
699 TSfree(header);
700 }
701 if (body) {
702 TSfree(body);
703 }
704 }
705 }
706
707 /***************************************************************************
708 * Events Testing
709 ***************************************************************************/
710 /* ------------------------------------------------------------------------
711 * print_active_events
712 * ------------------------------------------------------------------------
713 * retrieves a list of all active events and prints out each event name,
714 * one event per line
715 */
716 void
print_active_events()717 print_active_events()
718 {
719 TSList events;
720 TSMgmtError ret;
721 int count, i;
722 char *name;
723
724 printf("[print_active_events]\n");
725
726 events = TSListCreate();
727 ret = TSActiveEventGetMlt(events);
728 if (ret != TS_ERR_OKAY) {
729 print_err("TSActiveEventGetMlt", ret);
730 goto END;
731 } else { // successful get
732 count = TSListLen(events);
733 for (i = 0; i < count; i++) {
734 name = static_cast<char *>(TSListDequeue(events));
735 printf("\t%s\n", name);
736 TSfree(name);
737 }
738 }
739
740 END:
741 TSListDestroy(events);
742 return;
743 }
744
745 /* ------------------------------------------------------------------------
746 * check_active
747 * ------------------------------------------------------------------------
748 * returns true if the event named event_name is currently active (unresolved)
749 * returns false otherwise
750 */
751 bool
check_active(char * event_name)752 check_active(char *event_name)
753 {
754 bool active;
755 TSMgmtError ret;
756
757 ret = TSEventIsActive(event_name, &active);
758 print_err("TSEventIsActive", ret);
759
760 if (active) {
761 printf("%s is ACTIVE\n", event_name);
762 } else {
763 printf("%s is NOT-ACTIVE\n", event_name);
764 }
765
766 return active;
767 }
768
769 /* ------------------------------------------------------------------------
770 * try_resolve
771 * ------------------------------------------------------------------------
772 * checks if the event_name is still unresolved; if it is, it then
773 * resolves it, and checks the status of the event again to make sure
774 * the event was actually resolved
775 *
776 * NOTE: all the special string manipulation is needed because the CLI
777 * appends extra newline character to end of the user input; normally
778 * do not have to do all this special string manipulation
779 */
780 void
try_resolve(char * event_name)781 try_resolve(char *event_name)
782 {
783 TSMgmtError ret;
784 char *name;
785
786 name = TSstrdup(event_name);
787 printf("[try_resolve] Resolving event: %s\n", name);
788
789 if (check_active(name)) { // resolve events
790 ret = TSEventResolve(name);
791 print_err("TSEventResolve", ret);
792 check_active(name); // should be non-active now
793 }
794
795 TSfree(name);
796 }
797
798 /* ------------------------------------------------------------------------
799 * eventCallbackFn
800 * ------------------------------------------------------------------------
801 * the callback function; when called, it just prints out the name
802 * of the event that was signalled
803 */
804 void
eventCallbackFn(char * name,char * msg,int,void *)805 eventCallbackFn(char *name, char *msg, int /* pri ATS_UNUSED */, void * /* data ATS_UNUSED */)
806 {
807 printf("[eventCallbackFn] EVENT: %s, %s\n", name, msg);
808 return;
809 }
810
811 /* ------------------------------------------------------------------------
812 * register_event_callback
813 * ------------------------------------------------------------------------
814 * registers the eventCallbackFn above for all events; this just means
815 * that for any event that's signalled, the callback fn will also be called
816 */
817 void
register_event_callback()818 register_event_callback()
819 {
820 TSMgmtError err;
821
822 printf("\n[register_event_callback] \n");
823 err = TSEventSignalCbRegister(nullptr, eventCallbackFn, nullptr);
824 print_err("TSEventSignalCbRegister", err);
825 }
826
827 /* ------------------------------------------------------------------------
828 * unregister_event_callback
829 * ------------------------------------------------------------------------
830 * unregisters the eventCallbackFn above for all events; this just means
831 * that it will remove this eventCallbackFn entirely so that for any
832 * event called, the eventCallbackFn will NOT be called
833 */
834 void
unregister_event_callback()835 unregister_event_callback()
836 {
837 TSMgmtError err;
838
839 printf("\n[unregister_event_callback]\n");
840 err = TSEventSignalCbUnregister(nullptr, eventCallbackFn);
841 print_err("TSEventSignalCbUnregister", err);
842 }
843
844 /***************************************************************************
845 * Statistics
846 ***************************************************************************/
847
848 // generate dummy values for statistics
849 void
set_stats()850 set_stats()
851 {
852 TSActionNeedT action;
853
854 fprintf(stderr, "[set_stats] Set Dummy Stat Values\n");
855
856 TSRecordSetInt("proxy.process.http.user_agent_response_document_total_size", 100, &action);
857 TSRecordSetInt("proxy.process.http.user_agent_response_header_total_size", 100, &action);
858 TSRecordSetInt("proxy.process.http.current_client_connections", 100, &action);
859 TSRecordSetInt("proxy.process.http.current_client_transactions", 100, &action);
860 TSRecordSetInt("proxy.process.http.origin_server_response_document_total_size", 100, &action);
861 TSRecordSetInt("proxy.process.http.origin_server_response_header_total_size", 100, &action);
862 TSRecordSetInt("proxy.process.http.current_server_connections", 100, &action);
863 TSRecordSetInt("proxy.process.http.current_server_transactions", 100, &action);
864
865 TSRecordSetInt("proxy.node.proxy_running", 110, &action);
866 TSRecordSetInt("proxy.node.proxy_running", 110, &action);
867 }
868
869 void
print_stats()870 print_stats()
871 {
872 TSInt i1, i2, i3, i4, i5, i6, i7, i8;
873
874 fprintf(stderr, "[print_stats]\n");
875
876 TSRecordGetInt("proxy.process.http.user_agent_response_document_total_size", &i1);
877 TSRecordGetInt("proxy.process.http.user_agent_response_header_total_size", &i2);
878 TSRecordGetInt("proxy.process.http.current_client_connections", &i3);
879 TSRecordGetInt("proxy.process.http.current_client_transactions", &i4);
880 TSRecordGetInt("proxy.process.http.origin_server_response_document_total_size", &i5);
881 TSRecordGetInt("proxy.process.http.origin_server_response_header_total_size", &i6);
882 TSRecordGetInt("proxy.process.http.current_server_connections", &i7);
883 TSRecordGetInt("proxy.process.http.current_server_transactions", &i8);
884
885 fprintf(stderr, "%" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 "\n", i1,
886 i2, i3, i4, i5, i6, i7, i8);
887
888 TSRecordGetInt("proxy.node.proxy_running", &i4);
889 TSRecordGetInt("proxy.node.proxy_running", &i6);
890
891 fprintf(stderr, "%" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 "\n", i1, i7, i2, i3, i4,
892 i5, i6);
893
894 fprintf(stderr, "PROCESS stats: \n");
895 fprintf(stderr, "%" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 "\n", i1, i2, i3, i4);
896 }
897
898 void
reset_stats()899 reset_stats()
900 {
901 TSMgmtError err = TSStatsReset(nullptr);
902 print_err("TSStatsReset", err);
903 return;
904 }
905
906 void
sync_test()907 sync_test()
908 {
909 TSActionNeedT action;
910
911 TSRecordSetString("proxy.config.proxy_name", "dorkface", &action);
912 printf("[TSRecordSetString] proxy.config.proxy_name \n\tAction Should: [%d]\n\tAction is : [%d]\n", TS_ACTION_UNDEFINED,
913 action);
914
915 TSMgmtError ret;
916 if ((ret = TSProxyStateSet(TS_PROXY_OFF, TS_CACHE_CLEAR_NONE)) != TS_ERR_OKAY) {
917 printf("[TSProxyStateSet] turn off FAILED\n");
918 }
919 print_err("stop_TS", ret);
920 }
921
922 /* ########################################################################*/
923 /* ------------------------------------------------------------------------
924 * runInteractive
925 * ------------------------------------------------------------------------
926 * the loop that processes the commands inputted by user
927 */
928 static void
runInteractive()929 runInteractive()
930 {
931 char buf[512]; // holds request from interactive prompt
932
933 // process input from command line
934 while (true) {
935 // Display a prompt
936 printf("api_cli-> ");
937
938 // get input from command line
939 ATS_UNUSED_RETURN(fgets(buf, 512, stdin));
940
941 // check status of 'stdin' after reading
942 if (feof(stdin) != 0) {
943 printf("EXIT api_cli_remote\n");
944 return;
945 } else if (ferror(stdin) != 0) {
946 printf("EXIT api_cli_remote\n");
947 return;
948 }
949 // continue on newline
950 if (strcmp(buf, "\n") == 0) {
951 continue;
952 }
953 // exiting/quitting?
954 if (strcasecmp("quit\n", buf) == 0 || strcasecmp("exit\n", buf) == 0) {
955 // Don't wait for response LM
956 // exit(0);
957 return;
958 }
959 // check what operation user typed in
960 if (strstr(buf, "state")) {
961 print_proxy_state();
962 } else if (strncmp(buf, "start", 5) == 0) {
963 start_TS(buf);
964 } else if (strstr(buf, "stop")) {
965 stop_TS();
966 } else if (strstr(buf, "restart")) {
967 restart();
968 } else if (strstr(buf, "reconfig")) {
969 reconfigure();
970 } else if (strstr(buf, "records")) {
971 test_records();
972 } else if (strstr(buf, "err_recs")) {
973 test_error_records();
974 } else if (strstr(buf, "get_mlt")) {
975 test_record_get_mlt();
976 } else if (strstr(buf, "set_mlt")) {
977 test_record_set_mlt();
978 } else if (strstr(buf, "proxy.")) {
979 test_rec_get(buf);
980 } else if (strstr(buf, "active_events")) {
981 print_active_events();
982 } else if (strstr(buf, "MGMT_ALARM_")) {
983 try_resolve(buf);
984 } else if (strncmp(buf, "register", 8) == 0) {
985 register_event_callback();
986 } else if (strstr(buf, "unregister")) {
987 unregister_event_callback();
988 } else if (strstr(buf, "read_url")) {
989 test_read_url(true);
990 } else if (strstr(buf, "test_url")) {
991 test_read_url(false);
992 } else if (strstr(buf, "reset_stats")) {
993 reset_stats();
994 } else if (strstr(buf, "set_stats")) {
995 set_stats();
996 } else if (strstr(buf, "print_stats")) {
997 print_stats();
998 } else {
999 sync_test();
1000 }
1001
1002 } // end while(1)
1003
1004 } // end runInteractive
1005
1006 /* ------------------------------------------------------------------------
1007 * main
1008 * ------------------------------------------------------------------------
1009 * Main entry point which connects the client to the API, does any
1010 * clean up on exit, and gets the interactive command-line running
1011 */
1012 int
main(int,char **)1013 main(int /* argc ATS_UNUSED */, char ** /* argv ATS_UNUSED */)
1014 {
1015 TSMgmtError ret;
1016
1017 if ((ret = TSInit(nullptr, TS_MGMT_OPT_DEFAULTS)) == TS_ERR_OKAY) {
1018 runInteractive();
1019 TSTerminate();
1020 printf("END REMOTE API TEST\n");
1021 } else {
1022 print_err("main", ret);
1023 }
1024
1025 return 0;
1026 } // end main()
1027