OAI is riddled with boolean_t, FALSE, TRUE, etc. This makes no sense, as there is a standard bool type, and could lead to nasty bugs if a definition of a bool is non-standard (0 == false, true == !false). This commit removes all non-standard bools in the whole project.
317 lines
9.3 KiB
C
317 lines
9.3 KiB
C
/*
|
|
* 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
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
Eurecom OpenAirInterface 3
|
|
Copyright(c) 2012 Eurecom
|
|
|
|
Source user_simulator.c
|
|
|
|
Version 0.1
|
|
|
|
Date 2012/10/09
|
|
|
|
Product User simulator
|
|
|
|
Subsystem User simulator main process
|
|
|
|
Author Frederic Maurel
|
|
|
|
Description Implements the user simulator running at the user application
|
|
layer for NAS testing purpose.
|
|
|
|
*****************************************************************************/
|
|
|
|
#include "user_parser.h"
|
|
|
|
#include "include/commonDef.h"
|
|
#include "util/socket.h"
|
|
#include "util/device.h"
|
|
|
|
#include <stdio.h> // printf, perror
|
|
#include <errno.h> // errno
|
|
#include <netdb.h> // gai_strerror
|
|
#include <ctype.h> // isspace
|
|
#include <stdlib.h> // exit
|
|
#include <signal.h> // sigaction
|
|
#include <string.h> // memset
|
|
#include <pthread.h>
|
|
#include <poll.h>
|
|
|
|
/****************************************************************************/
|
|
/**************** 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 USER_SIMULATOR_BUFFER_SIZE 1024
|
|
|
|
/*
|
|
* String buffer used to send AT commands to the NAS sublayer
|
|
*/
|
|
static char _user_simulator_send_buffer [USER_SIMULATOR_BUFFER_SIZE];
|
|
|
|
/*
|
|
* String buffer used to receive responses from the NAS sublayer
|
|
*/
|
|
static char _user_simulator_recv_buffer [USER_SIMULATOR_BUFFER_SIZE];
|
|
|
|
/*
|
|
* The connection endpoint used for communication with the
|
|
* NAS sublayer (see src/api/user/user_api.c)
|
|
*/
|
|
static struct {
|
|
void* endpoint;
|
|
void* (*open) (int, const char*, const char*);
|
|
int (*getfd)(const void*);
|
|
ssize_t (*recv) (void*, char*, size_t);
|
|
ssize_t (*send) (const void*, const char*, size_t);
|
|
void (*close)(void*);
|
|
} _user_simulator_id;
|
|
//static socket_id_t * _user_simulator_sid;
|
|
|
|
#define USER_OPEN(a, b, c) _user_simulator_id.open(a, b, c)
|
|
#define USER_GETFD() _user_simulator_id.getfd(_user_simulator_id.endpoint)
|
|
#define USER_RECV(a, b) _user_simulator_id.recv(_user_simulator_id.endpoint, a, b)
|
|
#define USER_SEND(a, b) _user_simulator_id.send(_user_simulator_id.endpoint, a, b)
|
|
#define USER_CLOSE() _user_simulator_id.close(_user_simulator_id.endpoint)
|
|
|
|
static int _set_signal_handler(int signal, void (handler)(int));
|
|
static void _signal_handler(int signal_number);
|
|
static void* _receive_thread(void* arg);
|
|
|
|
/****************************************************************************/
|
|
/****************** E X P O R T E D F U N C T I O N S ******************/
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
int main (int argc, const char* argv[])
|
|
{
|
|
/*
|
|
* Get the command line options
|
|
*/
|
|
if ( user_parser_get_options(argc, argv) != RETURNok ) {
|
|
user_parser_print_usage();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
const char* host = user_parser_get_host();
|
|
const char* port = user_parser_get_port();
|
|
const char* devpath = user_parser_get_devpath();
|
|
const char* devattr = user_parser_get_devattr();
|
|
|
|
printf("%s -host %s -port %s -dev %s -params %s\n",
|
|
argv[0], host, port, devpath, devattr);
|
|
|
|
/*
|
|
* Initialize the communication channel to the NAS sublayer
|
|
*/
|
|
if (devpath) {
|
|
/* Initialize device handlers */
|
|
_user_simulator_id.open = device_open;
|
|
_user_simulator_id.getfd = device_get_fd;
|
|
_user_simulator_id.recv = device_read;
|
|
_user_simulator_id.send = device_write;
|
|
_user_simulator_id.close = device_close;
|
|
|
|
/* Initialize communication channel */
|
|
_user_simulator_id.endpoint = USER_OPEN(DEVICE, devpath, devattr);
|
|
|
|
if (_user_simulator_id.endpoint == NULL) {
|
|
perror("ERROR\t: Failed to open connection endpoint");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
printf("INFO\t: The User Simulator is now connected to %s (%d)\n",
|
|
devpath, (int)USER_GETFD());
|
|
} else {
|
|
/* Initialize network socket handlers */
|
|
_user_simulator_id.open = socket_udp_open;
|
|
_user_simulator_id.getfd = socket_get_fd;
|
|
_user_simulator_id.recv = socket_recv;
|
|
_user_simulator_id.send = socket_send;
|
|
_user_simulator_id.close = socket_close;
|
|
|
|
/* Initialize communication channel */
|
|
_user_simulator_id.endpoint = USER_OPEN(SOCKET_CLIENT, host, port);
|
|
|
|
if (_user_simulator_id.endpoint == NULL) {
|
|
const char* error = ( (errno < 0) ?
|
|
gai_strerror(errno) : strerror(errno) );
|
|
printf("ERROR\t: Failed to open connection endpoint: %s\n", error);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
printf("INFO\t: The User Simulator is now connected to %s/%s (%d)\n",
|
|
host, port, (int)USER_GETFD());
|
|
}
|
|
|
|
|
|
/*
|
|
* Set up signal handler
|
|
*/
|
|
(void) _set_signal_handler(SIGINT, _signal_handler);
|
|
(void) _set_signal_handler(SIGTERM, _signal_handler);
|
|
|
|
/*
|
|
* Create the receiving thread
|
|
*/
|
|
pthread_attr_t attr;
|
|
pthread_t thread_id;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
int rc = pthread_create (&thread_id, &attr, _receive_thread, NULL);
|
|
|
|
if (rc != 0) {
|
|
perror("ERROR\t: pthread_create() failed");
|
|
USER_CLOSE();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/*
|
|
* User simulator main loop
|
|
*/
|
|
while (true) {
|
|
char c;
|
|
int len;
|
|
|
|
/* Get the AT command */
|
|
printf("AT command (q to quit) > ");
|
|
c = getchar();
|
|
|
|
if (c == 'q') break;
|
|
|
|
if (c == '\n') continue;
|
|
|
|
len = 0;
|
|
|
|
while ( (len < USER_SIMULATOR_BUFFER_SIZE - 1) && (c != '\n') ) {
|
|
if (!isspace(c)) {
|
|
_user_simulator_send_buffer[len++] = c;
|
|
}
|
|
|
|
c = getchar();
|
|
}
|
|
|
|
_user_simulator_send_buffer[len++] = '\r';
|
|
_user_simulator_send_buffer[len] = '\0';
|
|
|
|
/* Send the AT command to the NAS sublayer */
|
|
int sbytes = USER_SEND(_user_simulator_send_buffer, len);
|
|
|
|
if (sbytes == RETURNerror) {
|
|
perror("ERROR\t: Failed to send data to the NAS sublayer");
|
|
break;
|
|
}
|
|
|
|
(void)poll(0, 0, 100);
|
|
}
|
|
|
|
/*
|
|
* Termination cleanup
|
|
*/
|
|
printf("INFO\t: Closing user endpoint descriptor %d\n", (int)USER_GETFD());
|
|
USER_CLOSE();
|
|
|
|
printf("INFO\t: User simulator exited\n");
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/********************* L O C A L F U N C T I O N S *********************/
|
|
/****************************************************************************/
|
|
|
|
/*
|
|
* Signal handler setup function
|
|
*/
|
|
static int _set_signal_handler(int signal, void (handler)(int))
|
|
{
|
|
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;
|
|
}
|
|
|
|
return RETURNok;
|
|
}
|
|
|
|
/*
|
|
* Signal handler
|
|
*/
|
|
static void _signal_handler(int signal_number)
|
|
{
|
|
printf("\nWARNING\t: Signal %d received\n", signal_number);
|
|
printf("INFO\t: Closing user socket %d\n", (int)USER_GETFD());
|
|
USER_CLOSE();
|
|
printf("INFO\t: User simulator exited\n");
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
/*
|
|
* Receiving thread
|
|
*/
|
|
static void* _receive_thread(void* arg)
|
|
{
|
|
while (true) {
|
|
/* Receive AT response from the NAS sublayer */
|
|
int rbytes = USER_RECV(_user_simulator_recv_buffer,
|
|
USER_SIMULATOR_BUFFER_SIZE);
|
|
|
|
if (rbytes != 0) {
|
|
if (rbytes == RETURNerror) {
|
|
perror("ERROR\t: Failed to receive data from the NAS sublayer");
|
|
break;
|
|
}
|
|
|
|
_user_simulator_recv_buffer[rbytes] = '\0';
|
|
|
|
/* Display AT response */
|
|
printf("%s\n", _user_simulator_recv_buffer);
|
|
}
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|