34#ifndef _POSIX_C_SOURCE
35#define _POSIX_C_SOURCE 200112L
40#if defined (CONSOLE_NETWORKING)
56 , help(
"help", help_command, this, &helpMark)
57 , helpMark(
"?", help_command, this)
58#if defined (CONSOLE_NETWORKING)
70 , help(
"help", help_command, this, &helpMark)
71 , helpMark(
"?", help_command, this)
72#if defined (CONSOLE_NETWORKING)
85#if OPENMRN_FEATURE_BSD_SOCKETS
86 fcntl(fd_in, F_SETFL,
fcntl(fd_in, F_GETFL, 0) | O_NONBLOCK);
88 new Session(
this, fd_in, fd_out);
101 current = current->
next;
105 current->
next =
new Command(name, callback, context);
113 fprintf(fp,
"%10s : print out this help menu\n",
"help | ?");
118 fprintf(fp,
"%10s : ", current->name);
119 const char *argv[2] = {current->name,
" "};
120 (*current->callback)(fp, 0, argv, NULL);
134 fprintf(fp,
"terminate the current login session, only\n%s"
135 "has an effect on socket based logins sessions\n",
154 while (current->
next)
156 current = current->
next;
175 if (current->
next == command)
182 current = current->
next;
186#if defined (CONSOLE_NETWORKING)
190Console::Listen::Listen(
Service *service,
int port)
227 result =
fcntl(fdListen, F_SETFL,
fcntl(0, F_GETFL, 0) | O_NONBLOCK);
243 int newfd =
::accept(fdListen, NULL, NULL);
253 return listen_and_call(&selectHelper, fdListen,
STATE(
accept));
264 , fp(fdopen(fd_out,
"w"))
265 , line((char*)malloc(64))
280 size_t count = (line_size - pos) - selectHelper.remaining_;
286#if OPENMRN_FEATURE_BSD_SOCKETS
287 if (S_ISSOCK(stat.st_mode))
290 return delete_this();
297 if (line[pos++] ==
'\n')
303 for (
size_t i = 0; i < pos; ++i)
317 args[argc] = &line[i];
325 if (command !=
nullptr)
327 command->flow->notify();
328 command->flow->argc = argc;
329 command->flow->argv = args;
331 return wait_and_call(
STATE(exit_interactive));
339 fprintf(fp,
"too many arguments\n");
346 return wait_and_call(
STATE(exit_interactive));
350 if (callback_result_process(status, args[0]) ==
false)
352 return delete_this();
362 if (pos >= line_size)
366 char *new_line = (
char*)malloc(line_size);
367 memcpy(new_line, line, pos);
373 return call_immediately(
STATE(entry));
384 for (
Command *current = &console->
help; current; current = current->next)
387 if (strcmp(current->name, argv[0]) == 0)
390 if (current->interactive)
393 return current->flow->callback(
this, fdIn, fp, argc, argv);
397 return (*current->callback)(fp, argc, argv, current->context);
413 return call_immediately(
STATE(entry));
415 HASSERT(callback_result_process(command->flow->status, command->name) ==
true);
422 return call_immediately(
STATE(entry));
436 fprintf(fp,
"invalid arguments\n");
442#if OPENMRN_FEATURE_BSD_SOCKETS
443 if (S_ISSOCK(stat.st_mode))
445 fprintf(fp,
"shutting down session\n");
449 fprintf(fp,
"session not a socket, "
450 "aborting session shutdown\n");
454 fprintf(fp,
"%s: command not found\n", name);
int fcntl(int fd, int cmd,...)
Manipulate a file descriptor.
int accept(int socket, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len)
Set the socket options.
int bind(int socket, const struct sockaddr *address, socklen_t address_len)
Bind a name to a socket.
int listen(int socket, int backlog)
Mark a connection-mode socket, specified by the socket argument, as accepting connections.
int socket(int domain, int type, int protocol)
Create an unbound socket in a communications domain.
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
~CommandFlow()
Destructor.
Command * command
Keep track of Command instance for destruction time.
virtual StateFlowBase::Action entry()=0
Entry point to command flow.
CommandFlow(Console *console, const char *name)
Constructor.
Console session metadata.
StateFlowBase::Action entry()
Entry point to the state machine.
StateFlowBase::Action exit_interactive()
Wait for completion of an interactive command in order to cleanup based on result.
void prompt(FILE *fp)
Print the standard prompt.
CommandStatus callback(int argc, const char *argv[])
Process a potential callback for a given command.
FILE * fp
file pointer of session
Session(Service *service, int fd_in, int fd_out)
Constructor.
StateFlowBase::Action process_read()
Process the incoming command line input.
bool callback_result_process(CommandStatus status, const char *name)
Process the result of the command callback.
This class provides a console available from stdin/stdout as well as via telnet.
Console(ExecutorBase *executor, uint16_t port)
Constructor.
void add_command(const char *name, Callback callback, void *context=NULL)
Add a new command to the console.
CommandStatus
Enumeration of recognized command callback results.
@ COMMAND_NOT_FOUND
Command not found.
@ COMMAND_ERROR
Command had some kind of error.
@ COMMAND_NEXT
Command waiting for input.
@ COMMAND_CLOSE
Command wants to close the session.
@ COMMAND_OK
Command executed successfully.
static CommandStatus help_command(FILE *fp, int argc, const char *argv[], void *context)
Print out the help menu by calling the in context helper function.
Command help
the "help" command instance
static CommandStatus quit_command(FILE *fp, int argc, const char *argv[], void *context)
Quit out of the current login session by calling the in context helper function.
Command helpMark
the help "?" command instance
static const size_t MAX_ARGS
Maximum number of supported arguments including the command itself.
void open_session(int fd_in, int fd_out)
Open and initialize a new session.
This class implements an execution of tasks pulled off an input queue.
Collection of related state machines that pend on incoming messages.
Return type for a state flow callback.
Base class for state machines.
void start_flow(Callback c)
Resets the flow to the specified state and starts it.
#define htons(x)
Converts a host endian short value to network endian.
#define INADDR_ANY
Listen on all network interfaces for incoming connections.
#define IPPROTO_TCP
TCP Raw Socket.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
#define SOCK_STREAM
TCP Socket.
#define SO_REUSEADDR
socket option to reuse address
#define SOL_SOCKET
socket option category
#define AF_INET
IPv4 Socket (UDP, TCP, etc...)
Console command metadata.
Command * next
next Command in list
Structure describing an Internet socket address.
#define TCP_NODELAY
don't delay send to coalesce packets