- Fix: avoid infinite loop on mulitcast read thread if no data to read

Pre-ci test passed

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4000 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
Cedric Roux
2013-06-25 09:05:02 +00:00
commit 56c66c09aa
4111 changed files with 2133103 additions and 0 deletions
+348
View File
@@ -0,0 +1,348 @@
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file cli.c
* \brief oai main cli core
* \author Navid Nikaein
* \date 2011
* \version 0.1
* \warning This component can be runned only in user-space
* @ingroup util
*/
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <ctype.h>
#include "cli.h"
extern cli_config *cli_cfg;
command commands[] = {
{0, "help",NULL,com_help, NULL,"Display this text" },
{0, "?",NULL,com_help, NULL, "help at any point" },
{2, "prompt",NULL,prompt, prompt_usage,"Set/get cli prompt" },
{2, "info",NULL,info, NULL,"get software information" },
{1, "start",NULL,start, start_usage,"Start eNB/UE instance" },
{1, "set",NULL,set, set_usage,"set log for a give component" },
{0, "exit",NULL,com_exit, NULL,"Exit using OpenAir CLI Interface" },
{0, (char *)NULL,NULL, NULL,NULL, (char *)NULL }
};
static uid_t real_uid;
void priv_init(void) {
real_uid = getuid();
}
void priv_up(void) {
if (seteuid(0) != 0) {
printf("[CLI] Error setting uid to %d\n", real_uid);
}
}
void priv_down(void) {
if (seteuid(real_uid) != 0) {
printf("[CLI] Error setting uid to %d\n", 0);
}
}
int cli_start(void) {
priv_init();
priv_down();
putenv("REMADDR=");
// get username
if ((username = getlogin()) == NULL) {
username = getenv("USER");
}
set_permissions_map();
// set login info
cli_login(username, CLI_MAX_NODES, CLI_MAX_CMDS);
// send welcome msg to the client
sprintf(buffer, "%s", WELCOME_MSG);
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
printf(WELCOME_MSG);
printf("[CLI] started...\n");
sprintf(cli_cfg->prompt,"%s%c ", cli_prompt(), cli_cfg->promptchar);
send(cli_cfg->cfd,cli_cfg->prompt, strlen(cli_cfg->prompt), 0);
return 1;
}
int cli_loop(char * msg) {
char *s;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite(msg);
if (*s) {
//add_history(s);
execute_line(s);
}
send(cli_cfg->cfd, cli_cfg->prompt, strlen(cli_cfg->prompt), 0);
return 0;
}
/**
* The permissions map is a bit map which defines which modes are available
* to a user. The permissions groups map to linux groups in the following
* way: subtract 1000. The remainder is the bit number.
* Thus unix groups 1000, 1001, 1002 etc represent the permissions groups
* default, config and admin respectively.
*
*/
int set_permissions_map(void) {
gid_t group[10];
int n, i;
int perm_num;
// get the number of supplementary group IDs
n = getgroups(10, group);
// give show permissions even if user has none
map_permissions = ADMIN_PERMISSION;
for (i=0; i<n; i++) {
perm_num = group[i] - 1000;
if (perm_num < 0 || perm_num > 31) {
continue;
}
//map_permissions |= (1 << perm_num);
map_permissions |= ((1 << (perm_num+1)) - 1);
}
printf("[CLI] Permissions %04x for this session\n", map_permissions);
return 0;
}
int cli_login(const char *username, int maxnodes, int maxcmds) {
cli_set_prompt_char();
printf("[CLI] Client initialised\n");
// log the connection
// telnets use REMADDR
host = getenv("REMADDR");
if (host) {
snprintf(g_sid, MAX_SID, "%s#%s", username, host);
printf("[CLI] login via telnet by user %s from address %s\n", username, host);
} else {
host = getenv("SSH_CLIENT");
if (host) {
char *cp;
// format is <rem_addr> <rem_port> <local_port>
// replace first space with ':', second terminates the string
cp = strchr(host, ' ');
if (cp) {
*cp = ':';
}
cp = strchr(host, ' ');
if (cp) {
*cp = '\0';
}
snprintf(g_sid, MAX_SID, "%s$%s", username, host);
printf("[CLI] login via SSH by user %s from address %s", username, host);
} else {
host = getenv("HOST");
if (host) {
snprintf(g_sid, MAX_SID, "%s$%s", username, host);
printf("[CLI] by user %s from host %s", username, host);
} else {
printf("[CLI]Login by user %s from unknown destination\n", username);
}
}
}
//register an exit function
atexit(cli_finish);
return 0;
}
char *cli_prompt(void) {
static char promptstr[200];
promptstr[0]='\0';
snprintf(promptstr, 200,"%s@%s",username, cli_cfg->prompt);
return promptstr;
}
int cli_set_prompt_char(void) {
if (map_permissions & ADMIN_PERMISSION) {
cli_cfg->promptchar = '#';
} else if (map_permissions & CONFIG_PERMISSION) {
cli_cfg->promptchar = '%';
} else if (map_permissions & SHOW_PERMISSION) {
cli_cfg->promptchar = '$';
}
return 0;
}
void cli_finish(void) {
char *cp;
if ((cp = strchr(g_sid, '#'))) {
*cp = '\0';
printf("[CLI] logout via telnet by user %s from address %s\n", g_sid, cp+1);
} else if ((cp = strchr(g_sid, '$'))) {
*cp = '\0';
printf("[CLI] logout via SSH by user %s from address %s\n", g_sid, cp+1);
} else {
printf("[CLI] logout from %s\n", g_sid);
}
return;
}
/* Execute a command line. */
int execute_line (char *line) {
register int i;
command *command;
char *word;
/* Isolate the command word. */
i = 0;
while (line[i] && whitespace (line[i]))
i++;
word = line + i;
while (line[i] && !whitespace (line[i]))
i++;
if (line[i])
line[i++] = '\0';
command = find_command(word);
if (!command) {
sprintf(buffer, "%s: %s \n", word, NOCOMMAND_MSG);
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
printf("[CLI] commnad %s does not exist !\n", word);
return (-1);
}
/* Get argument to command, if any. */
while (whitespace (line[i]))
i++;
word = line + i;
/* Call the function. */
return ((*(command->func)) (word));
}
/* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
command * find_command (char *name) {
register int i;
for (i = 0; commands[i].name; i++){
if (strcmp (name, commands[i].name) == 0)
return (&commands[i]);
}
return ((command *)NULL);
}
/* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char * stripwhite (char *string) {
register char *s, *t;
for (s = string; whitespace (*s); s++)
;
if (*s == 0)
return (s);
t = s + strlen (s) - 1;
while (t > s && whitespace (*t))
t--;
*++t = '\0';
return s;
}
/* Generator function for command completion. STATE lets us know whether
to start from scratch; without any state (i.e. STATE == 0), then we
start at the top of the list. */
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
int com_help (char *arg) {
register int i;
int printed = 0;
for (i = 0; commands[i].name != NULL; i++){
// if (!*arg || (strcmp (arg, commands[i].name) == 0)){
sprintf (buffer,"%s\t\t<%s>\n", commands[i].name, commands[i].doc);
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
printed++;
// }
}
if (!printed) {
printf("No commands match `%s'. Possibilties are:\n", arg);
for (i = 0; commands[i].name; i++){
/* Print in six columns. */
if (printed == 6) {
printed = 0;
printf("\n");
}
printf("%s\t", commands[i].name);
printed++;
}
if (printed)
printf("\n");
}
return (0);
}
int whitespace (char c) {
return (isspace((int)c));
}
+159
View File
@@ -0,0 +1,159 @@
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file cli.h
* \brief cli interface header file
* \author Navid Nikaein
* \date 2011
* \version 0.1
* \warning This component can be runned only in the user-space
* @ingroup util
*/
#ifndef __CLI_H__
#define __CLI_H__
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
//#include <readline/readline.h>
//#include <readline/history.h>
typedef struct {
int port;
int sfd; //server fd
int cfd; // client fd
int enabled;
int debugfd; // debug state
int debug_paused;
char promptchar;
char prompt[200];
// char user_name[200];
int exit;
/*end*/
}cli_config;
typedef struct {
int group;
char *name; /* User printable name of the function. */
void *data;
int (*func)(char*);
int (*help)(char*);
char *doc; /* Documentation for this function. */
} command;
typedef void (* cli_handler_t)(const void * data, socklen_t len);
#define MAX_SOCK_BUFFER_SIZE 1500
char buffer[MAX_SOCK_BUFFER_SIZE];
/* The name of this program, as taken from argv[0]. */
char *progname;
/*username*/
const char *username;
const char *host;
/* When non-zero, this global means the user is done using this program. */
int done;
/// global permissions table
unsigned int map_permissions;
sigjmp_buf openair_jmp_buf;
/// maximum session ID length
#define MAX_SID 100
/// session id - sent in every message
char g_sid[MAX_SID];
#define WELCOME_MSG "\n\nWelcome to the Eurecom OpenAirInterface CLI \n\n"
#define NOCOMMAND_MSG "No such command for openair CLI Interface"
#define SHOW_PERMISSION (1 << 0)
#define CONFIG_PERMISSION (1 << 1)
#define ADMIN_PERMISSION (1 << 2)
#define OK 0
#define ERR -1
#define CLI_MAX_CMDS 200
#define CLI_MAX_NODES 10
/* The names of functions that actually do the manipulation. */
int com_help (), com_exit ();
int prompt(),prompt_usage(), info();
int start(), set();
int start_usage(), set_usage();
/* Forward declarations. */
char *stripwhite ();
command *find_command ();
void abandon_input(int);
char *command_generator ();
char **fileman_completion ();
int cli_login(const char *, int, int );
int cli_loop(char* msg);
int cli_set_prompt_char(void);
char *cli_prompt(void);
int openair_cli(void);
int valid_argument (char *caller, char *arg);
int cli_help(char *caller, char * arg);
void cli_init(void);
int cli_start(void);
void set_comp_debug(int);
int set_permissions_map(void);
int is_debugging(void);
int execute_line(char* line);
int whitespace (char c);
void cli_finish(void);
int token_argument(char *arg, char* optv[]);
int process_argument(int optc, char* optv[]);
#include "cli_if.h"
#endif
+301
View File
@@ -0,0 +1,301 @@
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file cli_cmd.c
* \brief oai cli commands
* \author Navid Nikaein
* \date 2011
* \version 0.1
* \warning This component can be runned only in user-space
* @ingroup util
*/
#include "cli.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "log.h"
#include "log_extern.h"
extern cli_config *cli_cfg;
#define NEXT_OPT do {optv++;optc--; } while (0)
#define CHECK_OPTC do { if(!optc) { \
if((optc - 1) == 1){ \
fprintf(stderr, "[CLI]Error parsing command line options!\n"); \
} else { \
optv--; \
fprintf(stderr, "[CLI]You must provide a parameter when using the %s switch!\n", *optv); \
} \
} } while (0)
mapping log_comp[] = {
{"phy", 2},
{"mac", 3},
{"emu", 4},
{"ocg", 5},
{"omg", 6},
{NULL, -1}
};
mapping log_level[] = {
{"error", 3},
{"warn", 4},
{"info", 6},
{"debug", 7},
{NULL, -1}
};
mapping log_flag[] = {
{"none", 0x0},
{"low", 0x04},
{"med", 0x34},
{"full", 0x74},
{NULL, -1}
};
/* ************************ CLI COMMANDS ************************** */
/* The user wishes to quit using this program. Just set DONE non-zero. */
int com_exit (char *arg) {
//set the xit value for the threads
cli_cfg->exit = 1;
cli_cfg->promptchar='\0';
cli_cfg->prompt[0]='\0';
snprintf(cli_cfg->prompt,200,"%s","oaicli");
close(cli_cfg->cfd);
return (0);
}
/* CLI error Function . */
void cli_error (char *caller) {
fprintf (stderr,"[CLI]an error running occured during the execution of %s function\n",
caller);
}
int prompt (char *arg) {
// char buf[200];
if (cli_help("prompt", arg) == OK)
return 0;
if (!arg || !*arg){ // no arg is provided, run get func
snprintf(buffer,200,"%s\n", cli_cfg->prompt);
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
// send(cli_cfg->cfd, cli_cfg->prompt, strlen(cli_cfg->prompt), 0);
}else {// set func
snprintf(cli_cfg->prompt,200,"%s",arg);
sprintf( cli_cfg->prompt,"%s%c ", cli_prompt(), cli_cfg->promptchar);
}
return (0);
}
int info (char *arg) {
sprintf(buffer, "CLI by user %s from host %s\n", username, host);
send(cli_cfg->cfd,buffer, strlen(buffer),0);
return 0;
}
int start (char *arg) {
// char buf[200];
char* optv[20];
int optc=0;
if (cli_help("start", arg) == OK)
return OK;
if (valid_argument ("start", arg) == ERR){
start_usage();
return ERR;
}
optc = token_argument(arg, optv);
process_argument(optc, optv);
return (0);
}
int set(char *arg){
char* optv[20];
int optc=0;
if (cli_help("set", arg) == OK)
return OK;
if (valid_argument ("set", arg) == ERR){
set_usage();
return ERR;
}
optc = token_argument(arg, optv);
process_argument(optc, optv);
return OK;
}
/* Return non-zero if ARG is a valid argument for CALLER, else print
an error message and return zero. */
int valid_argument (char *caller, char *arg) {
if (!arg || !*arg) {
snprintf(buffer,200,"%s: argument required\n", caller);
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
fprintf (stderr, "%s: argument required\n", caller);
return (ERR);
}
return (OK);
}
int cli_help(char *caller, char * arg) {
command *command;
if ((strcmp(arg, "-h") == 0 ) || (strcmp(arg, "?") == 0 ) || (strcmp(arg, "help") == 0 ) ||
(strcmp(arg, "-help") == 0 ) ||(strcmp(arg, "--help") == 0 )) {
command = find_command (caller); // we are sure that the command exists so no check is done
return ((*(command->help))(caller)); // return zero after calling help func
}
return ERR; // no help is requested bu the user
}
int token_argument(char *arg, char* optv[]) {
int tokc;
tokc = 0;
optv[tokc] = strtok(arg, " "); // get the first token
while (optv[tokc]!=NULL) {
tokc++;
optv[tokc] = strtok(NULL, " ");
}
return tokc;
}
int process_argument(int optc, char* optv[]) {
int index;
int state;
int comp=0, level=0, flag=0x34, interval=0;
while (optc > 0) {
/* add an RB */
if ((strcmp(*optv, "ue") == 0) || (strcmp(*optv, "UE") == 0) ) {
NEXT_OPT; CHECK_OPTC;
index = atoi (*optv);
if (optc > 0){
NEXT_OPT; CHECK_OPTC;
state = atoi (*optv);
printf("[CLI] UE %d state %d\n", index, state);
oai_emulation.info.cli_start_ue[index]=state;
}
else
return ERR;
}
if ((strcmp(*optv, "enb") == 0) || (strcmp(*optv, "eNB") == 0) ) {
NEXT_OPT; CHECK_OPTC;
index = atoi (*optv);
if (optc > 0) {
NEXT_OPT;CHECK_OPTC;
state = atoi (*optv);
printf("[CLI] eNB %d state %d\n", index, state);
oai_emulation.info.cli_start_enb[index]= state;
}
else
return ERR;
}
// fixme
if ((strcmp(*optv, "log") == 0) || (strcmp(*optv, "LOG") == 0) ) {
NEXT_OPT; CHECK_OPTC;
comp = map_str_to_int(log_comp, *optv);
NEXT_OPT;
if (optc > 0) {
CHECK_OPTC;
level = map_str_to_int(log_level, *optv);
}
else
return ERR;
NEXT_OPT;
if (optc > 0) {
CHECK_OPTC;
flag = map_str_to_int (log_flag, *optv);
}
NEXT_OPT;
if (optc > 0) {
CHECK_OPTC;
interval = atoi (*optv);
}
printf("[CLI] OMG set log for comp %d level %d flag 0x%x interval %d\n",
comp, level, flag, interval);
set_comp_log(comp, level, flag, interval);
}
NEXT_OPT;
}
return OK;
}
int prompt_usage(void) {
sprintf(buffer, "Usage: prompt [value]\n");
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
return 0;
}
int start_usage(void) {
sprintf(buffer, "Usage: start [enb|UE] [enb_index][0: stop, 1: start] \n");
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
sprintf(buffer, "Example to start enb 0: start enb 0 1 \n");
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
sprintf(buffer, "Example to stop ue &: start ue 1 0 \n");
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
return 0;
}
int set_usage(void) {
sprintf(buffer, "Usage: set log [comp] [level:debug,info,warn,error][flag:none,low,med,full][intervale: 1-100] \n");
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
sprintf(buffer, "Example 1: set log omg debug\n");
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
sprintf(buffer, "Example 1: set log omg info med 10\n");
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
return 0;
}
+79
View File
@@ -0,0 +1,79 @@
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file cli_if.h
* \brief cli interface
* \author Navid Nikaein
* \date 2011
* \version 0.1
* \warning This component can be runned only in the user-space
* @ingroup util
*/
#ifndef __CLI_IF_H__
# define __CLI_IF_H__
/*--- INCLUDES ---------------------------------------------------------------*/
# include "cli.h"
/*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
# ifdef COMPONENT_CLI
# ifdef COMPONENT_CLI_IF
# define private_cli_if(x) x
# define friend_cli_if(x) x
# define public_cli_if(x) x
# else
# define private_cli_if(x)
# define friend_cli_if(x) extern x
# define public_cli_if(x) extern x
# endif
# else
# define private_cli_if(x)
# define friend_cli_if(x)
# define public_cli_if(x) extern x
# endif
/** @defgroup _cli_if Interfaces of CLI
* @{*/
public_cli_if( void cli_init (void); )
public_cli_if( int cli_server_init(cli_handler_t handler); )
public_cli_if(void cli_server_cleanup(void);)
public_cli_if(void cli_server_recv(const void * data, socklen_t len);)
/* @}*/
#ifdef __cplusplus
}
#endif
#endif
+203
View File
@@ -0,0 +1,203 @@
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file cli_server.c
* \brief oai cli server side implementation
* \author Navid Nikaein
* \date 2011
* \version 0.1
* \warning This component can be runned only in user-space
* @ingroup util
*/
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/if.h>
#include <signal.h>
#include <stdlib.h>
#include "cli.h"
#include "UTIL/LOG/log.h"
#define MAX_NUM_CLIENTS 15
#define MAX_LINE 100
struct sockaddr_in saddr;
unsigned short server_port = 1352;
pthread_t cli_server_listener;
static void * cli_server_listen(void *arg);
cli_handler_t cli_server_handler= NULL;
cli_config *cli_cfg;
int cli_server_init(cli_handler_t handler) {
int one = 1;
cli_init();
cli_server_handler = handler;
if ((cli_cfg->sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return -1;
}
if (setsockopt(cli_cfg->sfd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one)) < 0) {
perror("setsockopt");
return -1;
}
LOG_I(CLI,"socket created %d\n", cli_cfg->sfd);
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(server_port);
if (bind(cli_cfg->sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
perror("bind");
return -1;
}
/* create telnet listener thread */
if (pthread_create(&cli_server_listener, NULL, cli_server_listen, NULL)) {
perror("thread");
return -1;
}
return 0;
}
static void * cli_server_listen(void *arg) {
struct sockaddr caddr;
socklen_t clen;
clen = sizeof(caddr);
printf("[CLI] server thread started\n");
// to be implemented
while (1){
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (listen(cli_cfg->sfd, MAX_NUM_CLIENTS) < 0) {
perror("listen");
exit(1);
}
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
printf("[CLI] server Started listening on %d\n", cli_cfg->sfd);
if ((cli_cfg->cfd = accept(cli_cfg->sfd, &caddr, &clen)) <0){
if (cli_cfg->cfd == EINTR )
continue;
else {
perror("error on accept\n");
exit(1);
}
}
printf("[CLI] server accepted the connection %d from a new client\n", cli_cfg->cfd);
cli_cfg->exit = 0;
cli_start(); // init
do {
clen = recv(cli_cfg->cfd, buffer, MAX_SOCK_BUFFER_SIZE, 0);
if (cli_server_handler)
cli_server_handler(buffer, clen);
}while (cli_cfg->exit == 0);
cli_finish();
}
pthread_exit(NULL);
}
void cli_server_recv(const void * data, socklen_t len) {
char * msg = (char*) data;
//reomve the newlines
msg[len]=0;
msg[len-1]=0;
msg[len-2]=0;
//Multiplex to the right handler if needed
cli_loop(msg);
//sprintf(buffer, "%s_ACK", msg);
//len = send(fd, buffer, strlen(buffer), 0);
}
void cli_server_cleanup(void){
/* if (unlink(telnet_server_socket) < 0) {
perror("");
}
*/
printf("[CLI] server pthread exit ! \n");
if (cli_cfg->exit) close(cli_cfg->cfd);// close the client first
pthread_exit(NULL);
pthread_cancel(cli_server_listener);
close(cli_cfg->sfd);
}
void cli_init (void) {
cli_cfg = calloc(1, sizeof(cli_config));
memset(cli_cfg, 0, sizeof(cli_config));
cli_cfg->exit = 0;
cli_cfg->port = 1352;
cli_cfg->promptchar='\0';
cli_cfg->prompt[0]='\0';
snprintf(cli_cfg->prompt,200,"%s","oaicli");
}
#ifdef STANDALONE
int main() {
printf("start \n");
cli_init();
//Main process of telnet server
if (cli_server_init(cli_server_recv) < 0) {
printf("server init failed \n");
exit(-1);
}
while (cli_cfg->exit ==0) {
}
printf("server init done 1 \n");
cli_server_cleanup();
//pthread_join(telnet_server_listener, NULL);
printf("server init done \n");
return 0;
}
#endif