renamed openair-cn to openair3
git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7886 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (c) 2015, EURECOM (www.eurecom.fr)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those
|
||||
* of the authors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
/*****************************************************************************
|
||||
|
||||
Source network_api.c
|
||||
|
||||
Version 0.1
|
||||
|
||||
Date 2012/03/01
|
||||
|
||||
Product NAS stack
|
||||
|
||||
Subsystem Application Programming Interface
|
||||
|
||||
Author Frederic Maurel
|
||||
|
||||
Description Implements the API used by the NAS layer to send/receive
|
||||
message to/from the network sublayer
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#include "network_api.h"
|
||||
#include "commonDef.h"
|
||||
#include "nas_log.h"
|
||||
#include "socket.h"
|
||||
|
||||
#include "as_message.h"
|
||||
|
||||
#include <string.h> // strerror, memset
|
||||
#include <netdb.h> // gai_strerror
|
||||
#include <errno.h> // errno
|
||||
#include <unistd.h> // gethostname
|
||||
|
||||
/****************************************************************************/
|
||||
/**************** 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 *******************/
|
||||
/****************************************************************************/
|
||||
|
||||
/* -------------------
|
||||
* Connection endpoint
|
||||
* -------------------
|
||||
* The connection endpoint is used to send/receive data to/from the
|
||||
* network sublayer. Its definition depends on the underlaying mechanism
|
||||
* chosen to communicate (network socket, I/O terminal device, async FIFO).
|
||||
* A connection endpoint is handled using an identifier, and functions
|
||||
* used to retreive the file descriptor actually allocated by the system,
|
||||
* to receive data, to send data, and to perform clean up when connection
|
||||
* is shut down.
|
||||
* Only one single end to end connection with the network sublayer is
|
||||
* managed at a time.
|
||||
*/
|
||||
static struct {
|
||||
/* Connection endpoint reference */
|
||||
void* endpoint;
|
||||
/* Connection endpoint handlers */
|
||||
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*);
|
||||
} _network_api_id;
|
||||
|
||||
#define NETWORK_API_OPEN(a, b, c) _network_api_id.open(a, b, c)
|
||||
#define NETWORK_API_GETFD() _network_api_id.getfd(_network_api_id.endpoint)
|
||||
#define NETWORK_API_RECV(a, b) _network_api_id.recv(_network_api_id.endpoint, a, b)
|
||||
#define NETWORK_API_SEND(a, b) _network_api_id.send(_network_api_id.endpoint, a, b)
|
||||
#define NETWORK_API_CLOSE() _network_api_id.close(_network_api_id.endpoint)
|
||||
|
||||
/*
|
||||
* The buffer used to receive data from the network sublayer
|
||||
*/
|
||||
#define NETWORK_API_RECV_BUFFER_SIZE 4096
|
||||
static char _network_api_recv_buffer[NETWORK_API_RECV_BUFFER_SIZE];
|
||||
|
||||
/*
|
||||
* The buffer used to send data to the network sublayer
|
||||
*/
|
||||
#define NETWORK_API_SEND_BUFFER_SIZE NETWORK_API_RECV_BUFFER_SIZE
|
||||
static char _network_api_send_buffer[NETWORK_API_SEND_BUFFER_SIZE];
|
||||
|
||||
/*
|
||||
* The decoded data received from the network sublayer
|
||||
*/
|
||||
static as_message_t _as_data = {}; /* Access Stratum message */
|
||||
|
||||
/****************************************************************************/
|
||||
/****************** E X P O R T E D F U N C T I O N S ******************/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_initialize() **
|
||||
** **
|
||||
** Description: Initializes the network API from which the NAS layer **
|
||||
** will send/receive messages to/from the network sublayer **
|
||||
** **
|
||||
** Inputs: host: The name of the host from which the net- **
|
||||
** work sublayer will connect **
|
||||
** port: The local port number **
|
||||
** Others: None **
|
||||
** **
|
||||
** Outputs: Return: RETURNerror, RETURNok **
|
||||
** Others: _network_api_id **
|
||||
** **
|
||||
***************************************************************************/
|
||||
int network_api_initialize(const char* host, const char* port)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
|
||||
/* Initialize network socket handlers */
|
||||
_network_api_id.open = socket_udp_open;
|
||||
_network_api_id.getfd = socket_get_fd;
|
||||
_network_api_id.recv = socket_recv;
|
||||
_network_api_id.send = socket_send;
|
||||
_network_api_id.close = socket_close;
|
||||
/* Initialize UDP communication channel with the network layer */
|
||||
#ifdef NAS_UE
|
||||
_network_api_id.endpoint = NETWORK_API_OPEN(SOCKET_CLIENT, host, port);
|
||||
#endif
|
||||
#ifdef NAS_MME
|
||||
_network_api_id.endpoint = NETWORK_API_OPEN(SOCKET_SERVER, NULL, port);
|
||||
#endif
|
||||
|
||||
if (_network_api_id.endpoint == NULL) {
|
||||
const char* error = ( (errno < 0) ?
|
||||
gai_strerror(errno) : strerror(errno) );
|
||||
LOG_TRACE(ERROR, "NET-API - Failed to open connection endpoint, %s",
|
||||
error);
|
||||
LOG_FUNC_RETURN (RETURNerror);
|
||||
}
|
||||
|
||||
gethostname(_network_api_send_buffer, NETWORK_API_SEND_BUFFER_SIZE);
|
||||
LOG_TRACE(INFO, "NET-API - Network's UDP socket %d is BOUND to %s/%s",
|
||||
network_api_get_fd(), _network_api_send_buffer, port);
|
||||
|
||||
LOG_FUNC_RETURN (RETURNok);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_get_fd() **
|
||||
** **
|
||||
** Description: Get the file descriptor of the connection endpoint used **
|
||||
** to send/receive messages to/from the network sublayer **
|
||||
** **
|
||||
** Inputs: None **
|
||||
** Others: _network_api_id **
|
||||
** **
|
||||
** Outputs: Return: The file descriptor of the connection end- **
|
||||
** point used by the network sublayer **
|
||||
** Others: None **
|
||||
** **
|
||||
***************************************************************************/
|
||||
int network_api_get_fd(void)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
LOG_FUNC_RETURN (NETWORK_API_GETFD());
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_get_data() **
|
||||
** **
|
||||
** Description: Get a generic pointer to the network data structure. **
|
||||
** Casting to the proper type is necessary before its usage. **
|
||||
** **
|
||||
** Inputs: None **
|
||||
** Others: _as_data **
|
||||
** **
|
||||
** Outputs: Return: A generic pointer to the network data **
|
||||
** structure **
|
||||
** Others: None **
|
||||
** **
|
||||
***************************************************************************/
|
||||
const void* network_api_get_data(void)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
LOG_FUNC_RETURN ((void*)(&_as_data));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_read_data() **
|
||||
** **
|
||||
** Description: Read data received from the network sublayer **
|
||||
** **
|
||||
** Inputs: fd: File descriptor of the connection endpoint **
|
||||
** from which data have been received **
|
||||
** Others: _network_api_id **
|
||||
** **
|
||||
** Outputs: Return: The number of bytes read when success; **
|
||||
** RETURNerror otherwise **
|
||||
** Others: _network_api_recv_buffer, _network_api_id **
|
||||
** **
|
||||
***************************************************************************/
|
||||
int network_api_read_data(int fd)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
|
||||
int rbytes;
|
||||
|
||||
/* Sanity check */
|
||||
int sfd = network_api_get_fd();
|
||||
|
||||
if (fd != sfd) {
|
||||
LOG_TRACE(ERROR, "NET-API - Endpoint %d is not the one created for communication with the network sublayer (%d)", fd, sfd);
|
||||
LOG_FUNC_RETURN (RETURNerror);
|
||||
}
|
||||
|
||||
memset(_network_api_recv_buffer, 0, NETWORK_API_RECV_BUFFER_SIZE);
|
||||
|
||||
/* Receive data from the network sublayer */
|
||||
rbytes = NETWORK_API_RECV(_network_api_recv_buffer,
|
||||
NETWORK_API_RECV_BUFFER_SIZE);
|
||||
|
||||
if (rbytes == RETURNerror) {
|
||||
LOG_TRACE(ERROR, "NET-API - recv() failed, %s", strerror(errno));
|
||||
LOG_FUNC_RETURN (RETURNerror);
|
||||
} else if (rbytes == 0) {
|
||||
LOG_TRACE(WARNING, "NET-API - A signal was caught");
|
||||
} else {
|
||||
LOG_TRACE(INFO, "NET-API - %d bytes received from the network "
|
||||
"sublayer", rbytes);
|
||||
LOG_DUMP(_network_api_recv_buffer, rbytes);
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN (rbytes);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_send_data() **
|
||||
** **
|
||||
** Description: Send data to the network sublayer **
|
||||
** **
|
||||
** Inputs: fd: File descriptor of the connection endpoint **
|
||||
** to which data have to be sent **
|
||||
** length: Number of bytes to send **
|
||||
** Others: _network_api_send_buffer, _network_api_id **
|
||||
** **
|
||||
** Outputs: Return: The number of bytes sent when success; **
|
||||
** RETURNerror otherwise **
|
||||
** Others: None **
|
||||
** **
|
||||
***************************************************************************/
|
||||
int network_api_send_data(int fd, int length)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
|
||||
int sbytes;
|
||||
|
||||
/* Sanity check */
|
||||
int sfd = network_api_get_fd();
|
||||
|
||||
if (fd != sfd) {
|
||||
LOG_TRACE(ERROR, "NET-API - Endpoint %d is not the one created for communication with the network sublayer (%d)", fd, sfd);
|
||||
LOG_FUNC_RETURN (RETURNerror);
|
||||
}
|
||||
|
||||
/* Send data to the network sublayer */
|
||||
sbytes = NETWORK_API_SEND(_network_api_send_buffer, length);
|
||||
|
||||
if (sbytes == RETURNerror) {
|
||||
LOG_TRACE(ERROR, "NET-API - send() failed, %s", strerror(errno));
|
||||
LOG_FUNC_RETURN (RETURNerror);
|
||||
} else if (sbytes == 0) {
|
||||
LOG_TRACE(WARNING, "NET-API - A signal was caught");
|
||||
} else {
|
||||
LOG_TRACE(INFO, "NET-API - %d bytes sent to the network sublayer",
|
||||
sbytes);
|
||||
LOG_DUMP(_network_api_send_buffer, sbytes);
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN (sbytes);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_close() **
|
||||
** **
|
||||
** Description: Clean the network API from which the NAS layer sent/recei-**
|
||||
** ved messages to/from the network sublayer **
|
||||
** **
|
||||
** Inputs: fd: File descriptor of the connection endpoint **
|
||||
** allocated by the system to communicate **
|
||||
** with the network sublayer **
|
||||
** Others: None **
|
||||
** **
|
||||
** Outputs: Return: None **
|
||||
** Others: _network_api_id **
|
||||
** **
|
||||
***************************************************************************/
|
||||
void network_api_close(int fd)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
|
||||
/* Sanity check */
|
||||
int sfd = network_api_get_fd();
|
||||
|
||||
if (fd != sfd) {
|
||||
LOG_TRACE(ERROR, "NET-API - Endpoint %d is not the one created for communication with the network sublayer (%d)", fd, sfd);
|
||||
LOG_FUNC_OUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cleanup the connection endpoint */
|
||||
NETWORK_API_CLOSE();
|
||||
_network_api_id.endpoint = NULL;
|
||||
|
||||
LOG_FUNC_OUT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_decode_data() **
|
||||
** **
|
||||
** Description: Decodes the message received from the network and fills **
|
||||
** the corresponding network data structure. **
|
||||
** **
|
||||
** Inputs: length: Number of bytes to decode **
|
||||
** Others: _network_api_recv_buffer **
|
||||
** **
|
||||
** Outputs: Return: The identifier of the received AS **
|
||||
** message when successfully decoded; **
|
||||
** RETURNerror otherwise **
|
||||
** Others: _as_data **
|
||||
** **
|
||||
***************************************************************************/
|
||||
int network_api_decode_data(int length)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
|
||||
/* Decode the Access Stratum message received from the network */
|
||||
int as_id = as_message_decode(_network_api_recv_buffer, &_as_data, length);
|
||||
|
||||
if (as_id != RETURNerror) {
|
||||
LOG_TRACE(INFO, "NET-API - AS message id=0x%x successfully decoded",
|
||||
as_id);
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN (as_id);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: network_api_encode_data() **
|
||||
** **
|
||||
** Description: Encodes Access Stratum message to be sent to the network **
|
||||
** **
|
||||
** Inputs data: Generic pointer to the AS data to encode **
|
||||
** Others: None **
|
||||
** **
|
||||
** Outputs: Return: The number of characters that have been **
|
||||
** successfully encoded; **
|
||||
** RETURNerror otherwise. **
|
||||
** Others: _network_api_send_buffer **
|
||||
** **
|
||||
***************************************************************************/
|
||||
int network_api_encode_data(void* data)
|
||||
{
|
||||
LOG_FUNC_IN;
|
||||
|
||||
/* Encode the Access Stratum message */
|
||||
int bytes = as_message_encode(_network_api_send_buffer,
|
||||
(as_message_t*)(data),
|
||||
NETWORK_API_SEND_BUFFER_SIZE);
|
||||
|
||||
if (bytes != RETURNerror) {
|
||||
LOG_TRACE(INFO, "NET-API - %d bytes encoded", bytes);
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN (bytes);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: as_message_send() **
|
||||
** **
|
||||
** Description: Service provided to the EPS Mobility Management protocol **
|
||||
** at the EMMAS Access Point (EMMAS-SAP) to send AS messages **
|
||||
** to the Access Stratum sublayer. **
|
||||
** **
|
||||
** Inputs: as_msg: The AS message to send **
|
||||
** Others: _network_api_send_buffer, _network_api_id **
|
||||
** **
|
||||
** Outputs: Return: The number of bytes sent when success; **
|
||||
** RETURNerror Otherwise **
|
||||
** Others: _network_api_send_buffer **
|
||||
** **
|
||||
***************************************************************************/
|
||||
int as_message_send(as_message_t* as_msg)
|
||||
{
|
||||
int bytes;
|
||||
LOG_FUNC_IN;
|
||||
|
||||
LOG_TRACE(INFO, "NET-API - Send message 0x%.4x to the Access Stratum "
|
||||
"layer", as_msg->msgID);
|
||||
|
||||
/* Encode the AS message */
|
||||
bytes = network_api_encode_data(as_msg);
|
||||
|
||||
if (bytes > 0) {
|
||||
/* Get the network file descriptor */
|
||||
int fd = network_api_get_fd();
|
||||
|
||||
if (fd != RETURNerror) {
|
||||
/* Send the AS message to the network */
|
||||
bytes = network_api_send_data(fd, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN (bytes);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/********************* L O C A L F U N C T I O N S *********************/
|
||||
/****************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user