/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /***************************************************************************** Source UEprocess.c Version 0.1 Date 2012/02/27 Product NAS stack Subsystem UE NAS main process Author Frederic Maurel Description Implements the Non-Access Stratum protocol for Evolved Packet system (EPS) running at the User Equipment side. *****************************************************************************/ #include "commonDef.h" #include "nas_log.h" #include "nas_timer.h" #include "user_api.h" #include "network_api.h" #include "nas_user.h" #include "nas_network.h" #include "nas_parser.h" #include "user_defs.h" #include // exit #include // poll #include // memset #include // sigaction #include /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ /****************************************************************************/ /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ #define NAS_SLEEP_TIMEOUT 1000 /* 1 second */ static void *_nas_user_mngr(void *); static void *_nas_network_mngr(void *); static int _nas_set_signal_handler(int signal, void (handler)(int)); static void _nas_signal_handler(int signal); static void _nas_clean(user_api_id_t *user_api_id, int net_fd); uint8_t usim_test = 0; // FIXME user must be set up with right itti message instance // FIXME allocate user and initialize its fields nas_user_t *user = NULL; /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ /****************************************************************************/ int main(int argc, const char *argv[]) { // FIXME allocate and put it in user user_api_id_t *user_api_id = NULL; /* * Get the command line options */ if (nas_parser_get_options (argc, argv) != RETURNok) { nas_parser_print_usage (FIRMWARE_VERSION); exit (EXIT_FAILURE); } /* * Initialize logging trace utility */ nas_log_init (nas_parser_get_trace_level ()); const char *uhost = nas_parser_get_user_host (); const char *uport = nas_parser_get_user_port (); const char *devpath = nas_parser_get_device_path (); const char *devparams = nas_parser_get_device_params (); const char *nhost = nas_parser_get_network_host (); const char *nport = nas_parser_get_network_port (); LOG_TRACE (INFO, "UE-MAIN - %s -ueid %d -uhost %s -uport %s -nhost %s -nport %s -dev %s -params %s -trace 0x%x", argv[0], nas_parser_get_ueid (), uhost, uport, nhost, nport, devpath, devparams, nas_parser_get_trace_level ()); /* * Initialize the User interface */ if (user_api_initialize (user_api_id, uhost, uport, devpath, devparams) != RETURNok) { LOG_TRACE (ERROR, "UE-MAIN - user_api_initialize() failed"); exit (EXIT_FAILURE); } int user_fd = user_api_get_fd (user_api_id); /* * Initialize the Network interface */ if (network_api_initialize (nhost, nport) != RETURNok) { LOG_TRACE (ERROR, "UE-MAIN - network_api_initialize() failed"); user_api_close (user_api_id); exit (EXIT_FAILURE); } int network_fd = network_api_get_fd (); /* * Initialize the NAS contexts */ nas_user_initialize (user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); nas_network_initialize (); /* * Initialize NAS timer handlers */ nas_timer_init (); /* * Set up signal handlers */ (void) _nas_set_signal_handler (SIGINT, _nas_signal_handler); (void) _nas_set_signal_handler (SIGTERM, _nas_signal_handler); /* * Start thread use to manage the user connection endpoint */ pthread_t user_mngr; threadCreate (&user_mngr, , _nas_user_mngr, &user_fd, "UE-nas", -1, OAI_PRIORITY_RT_LOW) ; /* * Start thread use to manage the network connection endpoint */ pthread_t network_mngr; threadCreate (&network_mngr, _nas_network_mngr, &network_fd, "UE-nas-mgr", -1, OAI_PRIORITY_RT_LOW) ; /* * Suspend execution of the main process until all connection * endpoints are still active */ while ((user_fd != -1) && (network_fd != -1)) { poll (NULL, 0, NAS_SLEEP_TIMEOUT); user_fd = user_api_get_fd (user_api_id); network_fd = network_api_get_fd (); } /* Termination cleanup */ _nas_clean (user_api_id, network_fd); LOG_TRACE (WARNING, "UE-MAIN - NAS main process exited"); } /****************************************************************************/ /********************* L O C A L F U N C T I O N S *********************/ /****************************************************************************/ /**************************************************************************** ** ** ** Name: _nas_user_mngr() ** ** ** ** Description: Manages the connection endpoint use to communicate with ** ** the user application layer ** ** ** ** Inputs: fd: The descriptor of the user connection end-point ** ** Others: None ** ** ** ** Outputs: Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void *_nas_user_mngr(void *args) { LOG_FUNC_IN; pthread_setname_np( pthread_self(), "nas_user_mngr"); bool exit_loop = false; int *fd = (int *) args; LOG_TRACE (INFO, "UE-MAIN - User connection manager started (%d)", *fd); /* User receiving loop */ while (!exit_loop) { exit_loop = nas_user_receive_and_process(user, NULL); } /* Close the connection to the user application layer */ user_api_close (user->user_api_id); LOG_TRACE (WARNING, "UE-MAIN - " "The user connection endpoint manager exited"); LOG_FUNC_RETURN(NULL); } /**************************************************************************** ** ** ** Name: _nas_network_mngr() ** ** ** ** Description: Manages the connection endpoint use to communicate with ** ** the network sublayer ** ** ** ** Inputs: fd: The descriptor of the network connection endpoint ** ** Others: None ** ** ** ** Outputs: Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void *_nas_network_mngr(void *args) { LOG_FUNC_IN; int ret_code; int network_message_id; int bytes; int *fd = (int *) args; LOG_TRACE (INFO, "UE-MAIN - Network connection manager started (%d)", *fd); /* Network receiving loop */ while (true) { /* Read the network data message */ char _network_api_recv_buffer[NETWORK_API_RECV_BUFFER_SIZE] = {0}; bytes = network_api_read_data(*fd, _network_api_recv_buffer); if (bytes == RETURNerror) { /* Failed to read data from the network sublayer; * exit from the receiving loop */ LOG_TRACE (ERROR, "UE-MAIN - " "Failed to read data from the network sublayer"); break; } if (bytes == 0) { /* A signal was caught before any data were available */ continue; } /* Decode the network data message */ as_message_t _as_data = {}; network_message_id = network_api_decode_data(bytes, &_as_data); if (network_message_id == RETURNerror) { /* Failed to decode data read from the network sublayer */ continue; } /* Process the network data message */ ret_code = nas_network_process_data(user, network_message_id, &_as_data); if (ret_code != RETURNok) { /* The network data message has not been successfully * processed */ LOG_TRACE (WARNING, "UE-MAIN - " "The network procedure call 0x%x failed", network_message_id); } } /* Close the connection to the network sublayer */ network_api_close (*fd); LOG_TRACE (WARNING, "UE-MAIN - " "The network connection endpoint manager exited"); LOG_FUNC_RETURN(NULL); } /**************************************************************************** ** ** ** Name: _nas_set_signal_handler() ** ** ** ** Description: Set up a signal handler ** ** ** ** Inputs: signal: Signal number ** ** handler: Signal handler ** ** Others: None ** ** ** ** Outputs: Return: RETURNerror, RETURNok ** ** Others: None ** ** ** ***************************************************************************/ static int _nas_set_signal_handler(int signal, void (handler)(int)) { LOG_FUNC_IN; struct sigaction act; /* Initialize signal set */ (void) memset (&act, 0, sizeof(act)); (void) sigfillset (&act.sa_mask); (void) sigdelset (&act.sa_mask, SIGHUP); (void) sigdelset (&act.sa_mask, SIGINT); (void) sigdelset (&act.sa_mask, SIGTERM); (void) sigdelset (&act.sa_mask, SIGILL); (void) sigdelset (&act.sa_mask, SIGTRAP); (void) sigdelset (&act.sa_mask, SIGIOT); #ifndef LINUX (void) sigdelset (&act.sa_mask, SIGEMT); #endif (void) sigdelset (&act.sa_mask, SIGFPE); (void) sigdelset (&act.sa_mask, SIGBUS); (void) sigdelset (&act.sa_mask, SIGSEGV); (void) sigdelset (&act.sa_mask, SIGSYS); /* Initialize signal handler */ act.sa_handler = handler; if (sigaction (signal, &act, 0) < 0) { return RETURNerror; } LOG_TRACE (INFO, "UE-MAIN - Handler successfully set for signal %d", signal); LOG_FUNC_RETURN(RETURNok); } /**************************************************************************** ** ** ** Name: _nas_signal_handler() ** ** ** ** Description: Signal handler ** ** ** ** Inputs: signal: Signal number ** ** Others: None ** ** ** ** Outputs: Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void _nas_signal_handler(int signal) { LOG_FUNC_IN; LOG_TRACE (WARNING, "UE-MAIN - Signal %d received", signal); // FIXME acces to global _nas_clean (user->user_api_id, network_api_get_fd ()); exit (EXIT_SUCCESS); LOG_FUNC_OUT ; } /**************************************************************************** ** ** ** Name: _nas_clean() ** ** ** ** Description: Performs termination cleanup ** ** ** ** Inputs: usr_fd: User's connection file descriptor ** ** net_fd: Network's connection file descriptor ** ** Others: None ** ** ** ** Outputs: Return: None ** ** Others: None ** ** ** ***************************************************************************/ static void _nas_clean(user_api_id_t *user_api_id, int net_fd) { LOG_FUNC_IN; LOG_TRACE (INFO, "UE-MAIN - Perform EMM and ESM cleanup"); // FIXME nas_network_cleanup depends on nas_user_t // Why this program should interfere like that with oaisim ? //nas_network_cleanup (); LOG_TRACE (INFO, "UE-MAIN - " "Closing user connection %d and network connection %d", user_api_get_fd (user_api_id), net_fd); user_api_close (user_api_id); network_api_close (net_fd); LOG_FUNC_OUT ; }