3
A brief file description
5
@section license License
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
15
http://www.apache.org/licenses/LICENSE-2.0
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.
24
/***************************************/
25
/****************************************************************************
27
* CliMain.cc - A simple client to communicate to local manager
30
****************************************************************************/
36
#include "I_Version.h"
37
#include "Tokenizer.h"
38
#include "TextBuffer.h"
40
#include "clientCLI.h"
47
/* initialize WINSOCK 2.0 */
48
WORD wVersionRequested;
52
wVersionRequested = MAKEWORD(2, 0);
53
err = WSAStartup(wVersionRequested, &wsaData);
58
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
68
static const char *programName;
70
static int interactiveMode;
71
static char readVar[255];
72
static char setVar[255];
73
static char varValue[255];
76
static int BounceCluster;
77
static int BounceLocal;
78
static int QueryDeadhosts;
80
static int ShutdownMgmtCluster;
81
static int ShutdownMgmtLocal;
82
static int ClearCluster;
84
static int timeout_arg;
87
handleArgInvocation(clientCLI * cli)
89
char bufToLm[1024]; // buffer to send request to Local Manager
90
textBuffer response(512); // textBuffer object to hold response
91
char *responseStr; // actual response string
92
ink_hrtime timeLeft = -1;
93
bool printResponse = false;
94
Tokenizer respTok(";");
95
const char *status = NULL;
96
const char *resp = NULL;
97
int bufRemaining = sizeof(bufToLm) - 1;
99
// Do we really need to memset this, shouldn't it be enough to just do *bufToLm=0; ? /leif
100
memset(bufToLm, '\0', 1024);
102
// Intialize request as non-interactive
103
ink_strncpy(bufToLm, "b ", bufRemaining);
106
// Following options must be sent over as their numeric
107
// equivalents that show up in the interactive menu
108
// this is ugly but makes the number of handled events smaller
109
// on the manager side
112
if (*readVar != '\0' || *setVar != '\0' || *varValue != '\0') {
113
fprintf(stderr, "%s: Invalid Argument Combination: Can not read or set values with re-read\n", programName);
114
cli->disconnectFromLM();
117
strncat(bufToLm, "3", bufRemaining); /* reread */
120
} else if (ShutdownMgmtCluster == 1) {
121
strncat(bufToLm, "9", bufRemaining); /* restart_cluster */
123
} else if (ShutdownMgmtLocal == 1) {
124
strncat(bufToLm, "8", bufRemaining); /* restart_local */
126
} else if (Shutdown == 1) {
127
strncat(bufToLm, "4", bufRemaining); /* shutdown */
129
} else if (BounceCluster == 1) {
130
strncat(bufToLm, "7", bufRemaining); /* bounce_cluster */
132
} else if (BounceLocal == 1) {
133
strncat(bufToLm, "6", bufRemaining); /* bounce_local */
135
} else if (Startup == 1) {
136
strncat(bufToLm, "5", bufRemaining); /* startup */
138
} else if (ClearCluster == 1) {
139
strncat(bufToLm, "10", bufRemaining); /* clear_cluster */
141
} else if (ClearNode == 1) {
142
strncat(bufToLm, "11", bufRemaining); /* clear_node */
144
} else if (QueryDeadhosts == 1) {
145
printResponse = true;
146
strncat(bufToLm, "query_deadhosts", bufRemaining);
148
} else if (*readVar != '\0') { // Handle a value read
149
if (*setVar != '\0' || *varValue != '\0') {
150
fprintf(stderr, "%s: Invalid Argument Combination: Can not read and set values at the same time\n", programName);
151
cli->disconnectFromLM();
154
printResponse = true;
155
strncat(bufToLm, "get ", bufRemaining);
157
strncat(bufToLm, readVar, bufRemaining);
158
bufRemaining -= strlen(readVar);
160
} else if (*setVar != '\0') { // Setting a variable
161
if (*varValue == '\0') {
162
fprintf(stderr, "%s: Set requires a -v argument\n", programName);
163
cli->disconnectFromLM();
166
strncat(bufToLm, "set ", bufRemaining);
168
strncat(bufToLm, setVar, bufRemaining);
169
bufRemaining -= strlen(setVar);
170
strncat(bufToLm, " ", bufRemaining);
172
strncat(bufToLm, varValue, bufRemaining);
173
bufRemaining -= strlen(varValue);
175
} else if (*varValue != '\0') { // We have a value but no variable to set
176
fprintf(stderr, "%s: Must specify variable to set with -s when using -v\n", programName);
177
cli->disconnectFromLM();
179
} else if (timeout_arg > 0) { //INKqa10515
180
timeLeft = timeout_arg * 1000;
182
fprintf(stderr, "%s: No arguments specified\n", programName);
183
cli->disconnectFromLM();
187
if (timeout_arg < 0) {
191
cli->sendCommand(bufToLm, &response, timeLeft);
192
responseStr = response.bufPtr();
194
// parse response request from server into 3 tokens:
195
// status, prompt and response
196
respTok.setMaxTokens(3); //<status>;<prompt>;<response>
197
respTok.Initialize(response.bufPtr(), COPY_TOKS);
201
if (status && *status == '1') { // OK
202
// Only print responses for read, ignore prompt
204
printf("%s\n", resp ? resp : "NULL");
205
} else if (responseStr && *responseStr == '0') { // Error, Always print out errors
206
fprintf(stderr, "%s: %s\n", programName, resp);
208
fprintf(stderr, "%s: Internal Error: Server Returned Invalid Reponse\n", programName);
209
cli->disconnectFromLM();
213
cli->disconnectFromLM();
214
} // end handleArgInvocation
217
runInteractive(clientCLI * cli)
219
char buf[512]; // holds request from interactive prompt
220
char sendbuf[512]; // holds request to send LM
221
textBuffer response(8192); // holds response from Local Manager
223
Tokenizer respTok(";");
224
const char *prompt = NULL;
225
const char *resp = NULL;
227
respTok.setMaxTokens(3); //<status>;<prompt>;<response>
229
// process input from command line
233
printf("%s", prompt);
238
// get input from command line
239
NOWARN_UNUSED_RETURN(fgets(buf, 512, stdin));
241
// check status of 'stdin' after reading
242
if (feof(stdin) != 0) {
243
fprintf(stderr, "%s: Detected EOF on input %s\n", programName, strerror(errno));
244
cli->disconnectFromLM();
246
} else if (ferror(stdin) != 0) {
247
fprintf(stderr, "%s: Error on reading user command: %s\n", programName, strerror(errno));
250
// continue on newline
251
if (strcmp(buf, "\n") == 0) {
255
if (timeout_arg > 0) {
256
timeLeft = timeout_arg * 1000;
261
// set interactive mode
262
ink_strncpy(sendbuf, "i ", sizeof(sendbuf));
263
strncat(sendbuf, buf, strlen(buf) - 1); // do not send newline
265
cli->sendCommand(sendbuf, &response, timeLeft);
268
if (strcasecmp("quit\n", buf) == 0 || strcasecmp("exit\n", buf) == 0) {
269
// Don't wait for response LM
270
cli->disconnectFromLM();
273
// parse response request from server into 3 tokens:
274
// status, prompt and response (but status is not used)
275
respTok.Initialize(response.bufPtr(), COPY_TOKS);
281
printf("%s\n", resp);
283
// reuse response buffer?
287
} // end runInteractive
289
AppVersionInfo appVersionInfo;
290
int version_flag = 0;
295
main(int argc, char **argv)
297
programName = argv[0];
309
ShutdownMgmtCluster = 0;
310
ShutdownMgmtLocal = 0;
315
// build the application information structure
316
appVersionInfo.setup(PACKAGE_NAME,"traffic_line", PACKAGE_VERSION, __DATE__,
317
__TIME__, BUILD_MACHINE, BUILD_PERSON, "");
319
// Before accessing file system initialize Layout engine
321
clientCLI *cli = new clientCLI();
323
/* Argument description table used to describe how to parse command line args, */
324
/* see 'ink_args.h' for meanings of the various fields */
325
ArgumentDescription argument_descriptions[] = {
327
/*{ "interactive", 'i', "Interactive Mode", "F", &interactiveMode, "CLI_INTERACTIVE", NULL}, */
329
{"query_deadhosts", 'q', "Query congested sites", "F", &QueryDeadhosts, NULL, NULL},
330
{"socket_path", 'p', "Socket Path", "S255", &cli->sockPath, "CLI_SOCKPATH", NULL},
332
{"cli_port", 'p', "Port Number", "I", &cli->cliPort, "CLI_PORT", NULL},
334
{"read_var", 'r', "Read Variable", "S255", &readVar, NULL, NULL},
335
{"set_var", 's', "Set Variable (requires -v option)", "S255", &setVar, NULL, NULL},
336
{"value", 'v', "Set Value (used with -s option)", "S255", &varValue, NULL, NULL},
337
{"help", 'h', "Help", NULL, NULL, NULL, usage},
338
{"reread_config", 'x', "Reread Config Files", "F", &reRead, NULL, NULL},
339
{"restart_cluster", 'M', "Restart traffic_manager (cluster wide)",
340
"F", &ShutdownMgmtCluster, NULL, NULL},
341
{"restart_local", 'L', "Restart traffic_manager (local node)",
342
"F", &ShutdownMgmtLocal, NULL, NULL},
343
{"shutdown", 'S', "Shutdown traffic_server (local node)", "F", &Shutdown, NULL, NULL},
344
{"startup", 'U', "Start traffic_server (local node)", "F", &Startup, NULL, NULL},
345
{"bounce_cluster", 'B', "Bounce traffic_server (cluster wide)", "F", &BounceCluster, NULL, NULL},
346
{"bounce_local", 'b', "Bounce local traffic_server", "F", &BounceLocal, NULL, NULL},
347
{"clear_cluster", 'C', "Clear Statistics (cluster wide)", "F", &ClearCluster, NULL, NULL},
348
{"clear_node", 'c', "Clear Statistics (local node)", "F", &ClearNode, NULL, NULL},
349
{"version", 'V', "Print Version Id", "T", &version_flag, NULL, NULL},
351
{ "timeout", 'T', "Request timeout (seconds)", "I", &timeout_arg, NULL, NULL} */
355
int n_argument_descriptions = SIZE(argument_descriptions);
358
// Process command line arguments and dump into variables
359
process_args(argument_descriptions, n_argument_descriptions, argv);
361
// check for the version number request
363
ink_fputln(stderr, appVersionInfo.FullVersionInfoStr);
368
if (initWinSock() == false) {
369
fprintf(stderr, "%s: unable to initialize winsock.\n", programName);
374
// Connect to Local Manager
376
if (cli->connectToLM() != clientCLI::err_none) {
377
char sock_path[PATH_NAME_MAX + 1];
379
Layout::relative_to(sock_path, sizeof(sock_path),
380
Layout::get()->runtimedir, clientCLI::defaultSockPath);
381
cli->setSockPath(sock_path);
382
if (cli->connectToLM() != clientCLI::err_none) {
383
fprintf(stderr, "%s: unable to connect to traffic_manager via %s\n", programName, cli->sockPath);
388
if (cli->connectToLM() != clientCLI::err_none) {
389
fprintf(stderr, "%s: unable to connect to traffic_manager via %s\n", programName, cli->sockPath);
394
// Interactive or batch mode
395
if (interactiveMode == 1) {
398
handleArgInvocation(cli);