Ntk-console: Stop using fixed buffer width.

* Detect end of string in console and act on that.
* Open console connection on startup
* Terminate console connection on exit
This commit is contained in:
Alexander von Gluck IV 2014-09-14 09:50:08 -05:00
parent 3a842c2d4c
commit bc3f496788
3 changed files with 247 additions and 259 deletions

View File

@ -1,29 +1,11 @@
#include "Netsukuku-Console.h" #include "Netsukuku-Console.h"
#include <unistd.h>
char response[BUFFER_LENGTH]; char response[BUFFER_LENGTH];
void usage();
void clean_up();
typedef enum {
COMMAND_HELP = 0x100,
COMMAND_UPTIME,
COMMAND_KILL,
COMMAND_VERSION,
COMMAND_INETCONN,
COMMAND_CURIFS,
COMMAND_CURIFSCT,
COMMAND_CURQSPNID,
COMMAND_CURIP,
COMMAND_CURNODE,
COMMAND_IFS,
COMMAND_IFSCT,
COMMAND_QUIT,
COMMAND_CONSUPTIME,
} command_t;
const struct supported_commands { const struct supported_commands {
command_t id; command_t id;
@ -69,21 +51,28 @@ command_parse(char *request)
} }
void static int
response_cleanup(char response[BUFFER_LENGTH]) request_receive(int sock, char message[], int max)
{ {
char remove = 'a'; int total = 0;
const int bsize = 1024;
char* c; char buffer[bsize+1];
char* pPosition; int read = bsize;
while((pPosition = strchr(response, 'a')) != NULL) {
if ((c = index(response, remove)) != NULL) { message[0] = 0; // initialize for strcat()
size_t len_left = sizeof(response) - (c+1-response);
memmove(c, c+1, len_left); while(read == bsize) {
} read = recv(sock, buffer, bsize, 0);
if(read < 0)
return -1; // error, bail out
total += read;
if(total > max)
return -2; // overflow
buffer[read] = 0;
strcat(message, buffer);
} }
printf("Sent and received Successfully!\n The Response was: %s", response); return total;
} }
@ -91,37 +80,28 @@ response_cleanup(char response[BUFFER_LENGTH])
void void
ntkd_request(char *request) ntkd_request(char *request)
{ {
rc = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); if (sockfd <= 0) {
if (rc < 0) { perror("ntkd connection closed unexpectedly!\n");
perror("connect() failed");
exit(-1); exit(-1);
} }
int request_length = strlen(request); int request_length = strlen(request) - 1;
memset(request, 'a', BUFFER_LENGTH - request_length); request[request_length] = '\0';
rc = send(sockfd, request, sizeof(request), 0);
printf("request: '%s'\n", request);
rc = send(sockfd, request, request_length, 0);
if (rc < 0) { if (rc < 0) {
perror("send() failed"); perror("send() failed");
exit(-1); exit(-1);
} }
bytesReceived = 0; request_receive(sockfd, response, BUFFER_LENGTH);
while (bytesReceived < BUFFER_LENGTH) { if (rc < 0) {
rc = recv(sockfd, & response[bytesReceived], perror("recv() failed");
BUFFER_LENGTH - bytesReceived, 0);
if (rc < 0) {
perror("recv() failed");
exit(-1);
}
else if (rc == 0) {
printf("The server closed the connection\n");
exit(-1); exit(-1);
} }
/* Increment the number of bytes that have been received so far */ printf("%s\n", response);
bytesReceived += rc;
}
response_cleanup(response);
} }
@ -137,6 +117,28 @@ opensocket(void)
memset(&serveraddr, 0, sizeof(serveraddr)); memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sun_family = AF_UNIX; serveraddr.sun_family = AF_UNIX;
strcpy(serveraddr.sun_path, SERVER_PATH); strcpy(serveraddr.sun_path, SERVER_PATH);
rc = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (rc < 0) {
perror("connect() failed");
exit(-1);
}
printf("ntkd console connection opened successfully.\n");
}
void
closesocket(void)
{
const int optVal = 1;
const socklen_t optLen = sizeof(optVal);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen);
if (sockfd >= 0)
close(sockfd);
printf("ntkd console connection closed.\n");
} }
@ -175,10 +177,10 @@ console_uptime(void)
} }
int static void
millisleep(unsigned ms) millisleep(unsigned ms)
{ {
return usleep(1000 * ms); usleep(1000 * ms);
} }
@ -189,7 +191,7 @@ console(char* request)
switch (commandID) { switch (commandID) {
case COMMAND_QUIT: case COMMAND_QUIT:
clean_up(); closesocket();
exit(0); exit(0);
case COMMAND_UPTIME: case COMMAND_UPTIME:
case COMMAND_INETCONN: case COMMAND_INETCONN:
@ -211,6 +213,7 @@ console(char* request)
console_uptime(); console_uptime();
break; break;
case COMMAND_KILL: case COMMAND_KILL:
closesocket();
system("ntkd -k"); system("ntkd -k");
break; break;
case COMMAND_HELP: case COMMAND_HELP:
@ -234,61 +237,28 @@ main(void)
uptime_month = timeinfo->tm_mon; uptime_month = timeinfo->tm_mon;
uptime_year = timeinfo->tm_year; uptime_year = timeinfo->tm_year;
opensocket();
printf("This is the Netsukuku Console, Please type 'help' for more information.\n"); printf("This is the Netsukuku Console, Please type 'help' for more information.\n");
char* request = (char*)malloc(BUFFER_LENGTH); char* request = (char*)malloc(BUFFER_LENGTH);
opensocket();
do { do {
printf("\n>"); printf("\n> ");
fgets(request, 16, stdin); fgets(request, 16, stdin);
fflush(stdin); fflush(stdin);
console(request); console(request);
} while(FALSE); memset(request, 0, BUFFER_LENGTH);
} while(TRUE);
closesocket();
clean_up(); clean_up();
return 0; return 0;
} }
void usage(void) { void usage(void) {
printf("Usage:\n");
printf("Usage\n" for (int i = 0; i < sizeof(kSupportedCommands)
" uptime Returns the time when ntkd finished the hooking,\n" / sizeof(kSupportedCommands[0]); i++) {
" to get the the actual uptime just do)\n" printf(" %16s - %s\n", kSupportedCommands[i].command, kSupportedCommands[i].help);
" time(0)-me.uptime \n" }
" help Shows this\n"
" kill Kills the running instance of netsukuku with SIGINT\n\n"
" version Shows the running version of the ntk-console, and ntkd.\n"
" inet_connected If it is 1, Ntkd is connected to the Internet\n"
" \n"
" cur_ifs Lists all of the interfaces in cur_ifs\n"
" cur_ifs_n Lists the number of interfaces present in `cur_ifs'\n"
" cur_qspn_id The current qspn_id we are processing. "
" It is cur_qspn_id[levels] big\n"
" cur_ip Current IP address\n"
" \n"
" cur_node Current Node\n"
" ifs Lists all of the interfaces in server_opt.ifs\n"
" ifs_n Lists the number of interfaces present in server_opt.ifs\n"
" quit Exits this program\n"
" console_uptime Gets the uptime of this console\n");
}
void clean_up(void)
{
const int optVal = 1;
const socklen_t optLen = sizeof(optVal);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen);
setsockopt(sockfd1, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen);
if (sockfd != -1)
close(sockfd);
if (sockfd1 != -1)
close(sockfd1);
unlink(SERVER_PATH);
} }

View File

@ -12,10 +12,34 @@
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#define SERVER_PATH "/tmp/ntk-console"
#define BUFFER_LENGTH 250 #define SERVER_PATH "/tmp/ntk-console"
#define VERSION_STR "0.0.2" #define BUFFER_LENGTH 250
#define FALSE 0 #define VERSION_STR "0.0.2"
#ifndef TRUE
#define FALSE 0
#define TRUE 1
#endif
typedef enum {
COMMAND_HELP = 0x100,
COMMAND_UPTIME,
COMMAND_KILL,
COMMAND_VERSION,
COMMAND_INETCONN,
COMMAND_CURIFS,
COMMAND_CURIFSCT,
COMMAND_CURQSPNID,
COMMAND_CURIP,
COMMAND_CURNODE,
COMMAND_IFS,
COMMAND_IFSCT,
COMMAND_QUIT,
COMMAND_CONSUPTIME,
} command_t;
int sockfd = -1, sockfd1 = -1; int sockfd = -1, sockfd1 = -1;
struct sockaddr_un serveraddr; struct sockaddr_un serveraddr;
@ -33,4 +57,11 @@ int uptime_year;
int i; int i;
#endif /*NETSUKUKUCONSOLE_H*/ void usage();
void clean_up();
void opensocket();
void closesocket();
#endif /*NETSUKUKUCONSOLE_H*/

View File

@ -9,9 +9,10 @@
/* Constants used for the console bindings. */ /* Constants used for the console bindings. */
#define SERVER_PATH "/tmp/ntk-console" #define SERVER_PATH "/tmp/ntk-console"
#define REQUEST_LENGTH 250 #define REQUEST_LENGTH 250
#define FALSE 0 #define FALSE 0
#define TRUE 1
/* Variable and structure defintions, sockfd refers to socket file descriptor /* Variable and structure defintions, sockfd refers to socket file descriptor
* length refers to the required length of the requests that will be sent. * length refers to the required length of the requests that will be sent.
@ -28,181 +29,167 @@ int rc, length;
* unlinks the server path, etc. */ * unlinks the server path, etc. */
void clean_up(void) { void clean_up(void) {
const int optVal = 1; const int optVal = 1;
const socklen_t optLen = sizeof(optVal); const socklen_t optLen = sizeof(optVal);
setsockopt(sockfd_1, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen); setsockopt(sockfd_1, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen);
setsockopt(sockfd_2, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen); setsockopt(sockfd_2, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen);
if (sockfd_1 != -1) if (sockfd_1 != -1)
close(sockfd_1); close(sockfd_1);
if (sockfd_2 != -1) if (sockfd_2 != -1)
close(sockfd_2); close(sockfd_2);
unlink(SERVER_PATH); unlink(SERVER_PATH);
} }
/* Creates an AF_UNIX socket and binds it to a local address. */ /* Creates an AF_UNIX socket and binds it to a local address. */
void opensocket(void) { void opensocket(void) {
int stop_trying; int stop_trying;
sockfd_1 = socket(AF_UNIX, SOCK_STREAM, 0); sockfd_1 = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd_1 < 0) { if (sockfd_1 < 0) {
perror("socket creation failed"); perror("socket creation failed");
exit(-1); exit(-1);
} }
memset(&serveraddr, 0, sizeof(serveraddr)); memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sun_family = AF_UNIX; serveraddr.sun_family = AF_UNIX;
strcpy(serveraddr.sun_path, SERVER_PATH); strcpy(serveraddr.sun_path, SERVER_PATH);
rc = bind(sockfd_1, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr)); rc = bind(sockfd_1, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr));
if (rc < 0) { if (rc < 0) {
perror("bind() failed"); perror("bind() failed");
clean_up(); clean_up();
if(stop_trying >= 2) { if(stop_trying >= 2) {
perror("bind() failed"); perror("bind() failed");
clean_up(); clean_up();
opensocket(); opensocket();
exit(-1); exit(-1);
} }
stop_trying++; stop_trying++;
opensocket(); opensocket();
} }
} }
/* Sends a parsed response to the ntk console client. */ /* Sends a parsed response to the ntk console client. */
void send_response(char response[REQUEST_LENGTH], ...) { void
int response_length; send_response(char response[REQUEST_LENGTH], ...)
{
response_length = (int)strlen(response); int response_length = (int)strlen(response);
memset(response, 'a', REQUEST_LENGTH - response_length); rc = send(sockfd_2, response, sizeof(response), 0);
rc = send(sockfd_2, response, sizeof(response), 0); if (rc < 0){
if (rc < 0){ perror("send() failed");
perror("send() failed"); exit(-1);
exit(-1); }
}
} }
void request_cleanup(char unprocessed_request[REQUEST_LENGTH]) {
char remove = 'a';
char* c;
int x;
char* pPosition;
while(pPosition = strchr(unprocessed_request, 'a') != NULL) {
if ((c = index(unprocessed_request, remove)) != NULL) {
size_t len_left = sizeof(unprocessed_request) - (c+1-unprocessed_request);
memmove(c, c+1, len_left);
}
}
printf("Cleaned Request is: %s", unprocessed_request);
request_processing(unprocessed_request);
}
/* Parses the received request from the ntk console client /* Parses the received request from the ntk console client
* to data from ntkd structures such as: me * to data from ntkd structures such as: me
* into a response for the ntk console client. */ * into a response for the ntk console client. */
int request_processing(char unprocessed_request[REQUEST_LENGTH]) { int
request_processing(char unprocessed_request[REQUEST_LENGTH])
if(strncmp(unprocessed_request,"uptime", (int)strlen(unprocessed_request)) == 0) {
send_response((char)time(0)-me.uptime); if(strncmp(unprocessed_request,"uptime", (int)strlen(unprocessed_request)) == 0)
send_response((char)time(0)-me.uptime);
else if(strncmp(unprocessed_request,"version", (int)strlen(unprocessed_request)) == 0)
send_response(VERSION_STR); else if(strncmp(unprocessed_request,"version", (int)strlen(unprocessed_request)) == 0)
send_response(VERSION_STR);
else if(strncmp(unprocessed_request,"inet_connected", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.inet_connected); else if(strncmp(unprocessed_request,"inet_connected", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.inet_connected);
else if(strncmp(unprocessed_request,"cur_ifs", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_ifs); else if(strncmp(unprocessed_request,"cur_ifs", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_ifs);
else if(strncmp(unprocessed_request,"cur_ifs_n", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_ifs_n); else if(strncmp(unprocessed_request,"cur_ifs_n", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_ifs_n);
else if(strncmp(unprocessed_request,"cur_qspn_id", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_qspn_id); else if(strncmp(unprocessed_request,"cur_qspn_id", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_qspn_id);
else if(strncmp(unprocessed_request,"cur_ip", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_ip.data); else if(strncmp(unprocessed_request,"cur_ip", (int)strlen(unprocessed_request)) == 0)
send_response((char)me.cur_ip.data);
/*else if(strncmp(unprocessed_request,"cur_node", (int)strlen(unprocessed_request)) == 0)
send_response(me.cur_node); /*else if(strncmp(unprocessed_request,"cur_node", (int)strlen(unprocessed_request)) == 0)
send_response(me.cur_node);
else if(strncmp(unprocessed_request,"ifs", (int)strlen(unprocessed_request)) == 0)
return 0; else if(strncmp(unprocessed_request,"ifs", (int)strlen(unprocessed_request)) == 0)
return 0;
else if(strncmp(unprocessed_request,"ifs_n", (int)strlen(unprocessed_request)) == 0)
return 0;*/ else if(strncmp(unprocessed_request,"ifs_n", (int)strlen(unprocessed_request)) == 0)
send_response(unprocessed_request, " Is invalid or yet to be implemented."); return 0;*/
return -1; send_response(unprocessed_request, " Is invalid or yet to be implemented.");
return -1;
} }
/* Receives a request of 250 bytes from the ntk console client.
* listen and accept are also in a while loop to allow for different
* start times between the ntk console bindings and the ntk console client,
* As well as restarting of the ntk console client. */
void ntkd_request(void) {
char request[REQUEST_LENGTH];
do {
rc = listen(sockfd_1, 10);
if (rc< 0) {
perror("listen() failed");
exit(-1);
}
printf("Ready for client connect().\n"); static int
request_receive(int sock, char message[], int max)
sockfd_2 = accept(sockfd_1, NULL, NULL); {
if (sockfd_2 < 0) { int total = 0;
perror("accept() failed"); const int bsize = 1024;
exit(-1); char buffer[bsize+1];
} int read = bsize;
length = REQUEST_LENGTH; message[0] = 0; // initialize for strcat()
rc = setsockopt(sockfd_2, SOL_SOCKET, SO_RCVLOWAT,
(char *)&length, sizeof(length)); while(read == bsize) {
if (rc < 0) { read = recv(sock, buffer, bsize, 0);
perror("setsockopt(SO_RCVLOWAT) failed"); if(read < 0)
exit(-1); return -1; // error, bail out
} total += read;
if(total > max)
rc = recv(sockfd_2, request, sizeof(request), 0); return -2; // overflow
if (rc < 0) { buffer[read] = 0;
perror("recv() failed"); strcat(message, buffer);
exit(-1); }
}
return total;
printf("%d bytes of data were received\n", rc); }
if (rc == 0 || rc < sizeof(request)) {
printf("The console client closed the connection before all of the\n"); void ntkd_request(void) {
printf("data was sent\n"); char request[REQUEST_LENGTH];
exit(-1);
} rc = listen(sockfd_1, 10);
if (rc< 0) {
request_cleanup(request); perror("listen() failed");
} while(FALSE); exit(-1);
}
clean_up();
printf("Ready for client connect().\n");
do {
sockfd_2 = accept(sockfd_1, NULL, NULL);
if (sockfd_2 < 0) {
perror("accept() failed");
exit(-1);
}
rc = request_receive(sockfd_2, request, REQUEST_LENGTH);
if (rc < 0) {
perror("recv() failed");
exit(-1);
}
printf("%d bytes of data were received\n", rc);
request_processing(request);
} while(TRUE);
clean_up();
} }
void console_recv_send(void) { void console_recv_send(void) {
opensocket(); opensocket();
ntkd_request(); ntkd_request();
} }