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:
gauthier
2015-10-06 16:53:42 +00:00
parent c7518ecf42
commit 7b5431a62c
705 changed files with 206 additions and 208 deletions
+28
View File
@@ -0,0 +1,28 @@
/*
* 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.
*/
+43
View File
@@ -0,0 +1,43 @@
ifndef PROJDIR
PROJDIR = $(PWD)/../..
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
INCLUDES = -I. -I$(INCDIR)
TARGET = $(LIBUTIL)
TARGETS = $(TARGET).a $(TARGET).so
all: $(TARGETS)
%.o: %.c Makefile
@echo Compiling $<
@$(CC) $(CFLAGS) -c $< -o $@
$(TARGET).a: $(OBJS)
@$(RM) $@
@$(AR) $(ARFLAGS) $@ $(OBJS)
@echo Replacing $@ to $(LIBDIR)
@$(RM) $(LIBDIR)/$@
@$(CP) $@ $(LIBDIR)
$(TARGET).so: $(OBJS)
@$(LD) -G -o $@ $(OBJS)
@echo Replacing $@ to $(LIBDIR)
@$(RM) $(LIBDIR)/$@
@$(CP) $@ $(LIBDIR)
clean:
$(RM) $(OBJS) *.bak *~
veryclean: clean
$(RM) $(TARGETS)
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
+132
View File
@@ -0,0 +1,132 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "TLVEncoder.h"
#include "TLVDecoder.h"
#include "OctetString.h"
#define DUMP_OUTPUT_SIZE 1024
static char _dump_output[DUMP_OUTPUT_SIZE];
OctetString* dup_octet_string(OctetString *octetstring)
{
OctetString *os_p = NULL;
if (octetstring) {
os_p = calloc(1,sizeof(OctetString));
os_p->length = octetstring->length;
os_p->value = malloc(octetstring->length+1);
memcpy(os_p->value, octetstring->value, octetstring->length);
os_p->value[octetstring->length] = '\0';
}
return os_p;
}
void free_octet_string(OctetString *octetstring)
{
if (octetstring) {
if (octetstring->value) free(octetstring->value);
octetstring->value = NULL;
octetstring->length = 0;
free(octetstring);
}
}
int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t buflen)
{
if (octetstring != NULL) {
if ((octetstring->value != NULL) && (octetstring->length > 0)) {
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, octetstring->length, buflen);
memcpy((void*)buffer, (void*)octetstring->value, octetstring->length);
return octetstring->length;
} else {
return 0;
}
} else {
return 0;
}
}
int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buffer, uint32_t buflen)
{
if (buflen < pdulen)
return -1;
if ((octetstring != NULL) && (buffer!= NULL)) {
octetstring->length = pdulen;
octetstring->value = malloc(sizeof(uint8_t) * (pdulen+1));
memcpy((void*)octetstring->value, (void*)buffer, pdulen);
octetstring->value[pdulen] = '\0';
return octetstring->length;
} else {
return -1;
}
}
char* dump_octet_string_xml( const OctetString * const octetstring)
{
int i;
int remaining_size = DUMP_OUTPUT_SIZE;
int size = 0;
int size_print = 0;
size_print = snprintf(_dump_output, remaining_size, "<Length>%u</Length>\n\t<values>", octetstring->length);
size += size_print;
remaining_size -= size_print;
for (i = 0; i < octetstring->length; i++) {
size_print = snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]);
size += size_print;
remaining_size -= size_print;
}
size_print = snprintf(&_dump_output[size], remaining_size, "</values>\n");
return _dump_output;
}
char* dump_octet_string( const OctetString * const octetstring)
{
int i;
int remaining_size = DUMP_OUTPUT_SIZE;
int size = 0;
int size_print = 0;
for (i = 0; i < octetstring->length; i++) {
size_print = snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]);
size += size_print;
remaining_size -= size_print;
}
return _dump_output;
}
+77
View File
@@ -0,0 +1,77 @@
/*
* 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.
*/
#include <stdint.h>
#include <assert.h>
#ifndef OCTET_STRING_H_
#define OCTET_STRING_H_
typedef struct OctetString_tag {
uint32_t length;
uint8_t *value;
} OctetString;
#define FREE_OCTET_STRING(oCTETsTRING) \
do { \
if ((oCTETsTRING).value != NULL) { \
free((oCTETsTRING).value); \
(oCTETsTRING).value = NULL; \
} \
(oCTETsTRING).length = 0; \
} while (0);
#define DUP_OCTET_STRING(oCTETsTRINGoRIG,oCTETsTRINGcOPY) \
do { \
if ((oCTETsTRINGoRIG).value == NULL) { \
(oCTETsTRINGcOPY).length = 0; \
(oCTETsTRINGcOPY).value = NULL; \
break; \
} \
(oCTETsTRINGcOPY).length = (oCTETsTRINGoRIG).length; \
(oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length+1); \
(oCTETsTRINGcOPY).value[(oCTETsTRINGoRIG).length] = '\0'; \
memcpy((oCTETsTRINGcOPY).value, \
(oCTETsTRINGoRIG).value, \
(oCTETsTRINGoRIG).length); \
} while (0);
OctetString* dup_octet_string(OctetString*octetstring);
void free_octet_string(OctetString *octetstring);
int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t len);
int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buffer, uint32_t buflen);
char* dump_octet_string_xml(const OctetString * const octetstring);
char* dump_octet_string(const OctetString * const octetstring);
#endif /* OCTET_STRING_H_ */
+57
View File
@@ -0,0 +1,57 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "TLVDecoder.h"
int errorCodeDecoder = 0;
const char *errorCodeStringDecoder[] = {
"No error",
"Buffer NULL",
"Buffer too short",
"Unexpected IEI",
"Mandatory field not present",
"Wrong message type",
"EXT value doesn't match",
"Protocol not supported",
};
void tlv_decode_perror(void)
{
if (errorCodeDecoder >= 0)
// No error or TLV_DECODE_ERR_OK
return;
printf("TLV decoder error: (%d, %s)\n", errorCodeDecoder, errorCodeStringDecoder[errorCodeDecoder * -1]);
}
+141
View File
@@ -0,0 +1,141 @@
/*
* 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.
*/
#ifndef TLV_DECODER_H_
#define TLV_DECODER_H_
#include <arpa/inet.h> // ntohl, ntohs
#include "nas_log.h"
#ifndef NAS_DEBUG
# define NAS_DEBUG 1
#endif
#define DECODE_U8(bUFFER, vALUE, sIZE) \
vALUE = *(uint8_t*)(bUFFER); \
sIZE += sizeof(uint8_t)
#define DECODE_U16(bUFFER, vALUE, sIZE) \
vALUE = ntohs(*(uint16_t*)(bUFFER)); \
sIZE += sizeof(uint16_t)
#define DECODE_U24(bUFFER, vALUE, sIZE) \
vALUE = ntohl(*(uint32_t*)(bUFFER)) >> 8; \
sIZE += sizeof(uint8_t) + sizeof(uint16_t)
#define DECODE_U32(bUFFER, vALUE, sIZE) \
vALUE = ntohl(*(uint32_t*)(bUFFER)); \
sIZE += sizeof(uint32_t)
#if (BYTE_ORDER == LITTLE_ENDIAN)
# define DECODE_LENGTH_U16(bUFFER, vALUE, sIZE) \
vALUE = ((*(bUFFER)) << 8) | (*((bUFFER) + 1)); \
sIZE += sizeof(uint16_t)
#else
# define DECODE_LENGTH_U16(bUFFER, vALUE, sIZE) \
vALUE = (*(bUFFER)) | (*((bUFFER) + 1) << 8); \
sIZE += sizeof(uint16_t)
#endif
#define IES_DECODE_U8(bUFFER, dECODED, vALUE) \
DECODE_U8(bUFFER + dECODED, vALUE, dECODED)
#define IES_DECODE_U16(bUFFER, dECODED, vALUE) \
DECODE_U16(bUFFER + dECODED, vALUE, dECODED)
#define IES_DECODE_U24(bUFFER, dECODED, vALUE) \
DECODE_U24(bUFFER + dECODED, vALUE, dECODED)
#define IES_DECODE_U32(bUFFER, dECODED, vALUE) \
DECODE_U32(bUFFER + dECODED, vALUE, dECODED)
typedef enum {
TLV_DECODE_ERROR_OK = 0,
TLV_DECODE_UNEXPECTED_IEI = -1,
TLV_DECODE_MANDATORY_FIELD_NOT_PRESENT = -2,
TLV_DECODE_VALUE_DOESNT_MATCH = -3,
/* Fatal errors - received message should not be processed */
TLV_DECODE_WRONG_MESSAGE_TYPE = -10,
TLV_DECODE_PROTOCOL_NOT_SUPPORTED = -11,
TLV_DECODE_BUFFER_TOO_SHORT = -12,
TLV_DECODE_BUFFER_NULL = -13,
TLV_DECODE_MAC_MISMATCH = -14,
} tlv_decoder_error_code;
/* Defines error code limit below which received message should be discarded
* because it cannot be further processed */
#define TLV_DECODE_FATAL_ERROR (TLV_DECODE_VALUE_DOESNT_MATCH)
extern int errorCodeDecoder;
void tlv_decode_perror(void);
#define CHECK_PDU_POINTER_AND_LENGTH_DECODER(bUFFER, mINIMUMlENGTH, lENGTH) \
if (bUFFER == NULL) \
{ \
printf("(%s:%d) Got NULL pointer for the payload\n", \
__FILE__, __LINE__); \
errorCodeDecoder = TLV_DECODE_BUFFER_NULL; \
LOG_FUNC_RETURN(TLV_DECODE_BUFFER_NULL); \
} \
if (lENGTH < mINIMUMlENGTH) \
{ \
printf("(%s:%d) Expecting at least %d bytes, got %d\n", \
__FILE__, __LINE__, mINIMUMlENGTH, lENGTH); \
errorCodeDecoder = TLV_DECODE_BUFFER_TOO_SHORT; \
LOG_FUNC_RETURN(TLV_DECODE_BUFFER_TOO_SHORT); \
}
#define CHECK_LENGTH_DECODER(bUFFERlENGTH, lENGTH) \
if (bUFFERlENGTH < lENGTH) \
{ \
errorCodeDecoder = TLV_DECODE_BUFFER_TOO_SHORT; \
LOG_FUNC_RETURN(TLV_DECODE_BUFFER_TOO_SHORT); \
}
#define CHECK_MESSAGE_TYPE(mESSAGE_tYPE, bUFFER) \
{ \
if (mESSAGE_tYPE != bUFFER) \
{ \
errorCodeDecoder = TLV_DECODE_WRONG_MESSAGE_TYPE; \
LOG_FUNC_RETURN(errorCodeDecoder); \
} \
}
#define CHECK_IEI_DECODER(iEI, bUFFER) \
if(iEI != bUFFER) \
{ \
printf("IEI is different than the one expected." \
"(Got: 0x%x, expecting: 0x%x)\n", bUFFER, iEI); \
errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI; \
LOG_FUNC_RETURN(TLV_DECODE_UNEXPECTED_IEI); \
}
#endif /* define (TLV_DECODER_H_) */
+54
View File
@@ -0,0 +1,54 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "TLVEncoder.h"
int errorCodeEncoder = 0;
const char *errorCodeStringEncoder[] = {
"No error",
"Buffer NULL",
"Buffer too short",
"Octet string too long for IEI",
"Wrong message type",
"Protocol not supported",
};
void tlv_encode_perror(void)
{
if (errorCodeEncoder >= 0)
// No error or TLV_DECODE_ERR_OK
return;
printf("error: (%d, %s)\n", errorCodeEncoder, errorCodeStringEncoder[errorCodeEncoder * -1]);
}
+105
View File
@@ -0,0 +1,105 @@
/*
* 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.
*/
#ifndef TLV_ENCODER_H_
#define TLV_ENCODER_H_
#include <arpa/inet.h> // htonl, htons
#define ENCODE_U8(buffer, value, size) \
*(uint8_t*)(buffer) = value; \
size += sizeof(uint8_t)
#define ENCODE_U16(buffer, value, size) \
*(uint16_t*)(buffer) = htons(value); \
size += sizeof(uint16_t)
#define ENCODE_U24(buffer, value, size) \
*(uint32_t*)(buffer) = htonl(value); \
size += sizeof(uint8_t) + sizeof(uint16_t)
#define ENCODE_U32(buffer, value, size) \
*(uint32_t*)(buffer) = htonl(value); \
size += sizeof(uint32_t)
#define IES_ENCODE_U8(buffer, encoded, value) \
ENCODE_U8(buffer + encoded, value, encoded)
#define IES_ENCODE_U16(buffer, encoded, value) \
ENCODE_U16(buffer + encoded, value, encoded)
#define IES_ENCODE_U24(buffer, encoded, value) \
ENCODE_U24(buffer + encoded, value, encoded)
#define IES_ENCODE_U32(buffer, encoded, value) \
ENCODE_U32(buffer + encoded, value, encoded)
typedef enum {
TLV_ENCODE_ERROR_OK = 0,
TLV_ENCODE_VALUE_DOESNT_MATCH = -1,
/* Fatal errors - message should not be sent */
TLV_ENCODE_OCTET_STRING_TOO_LONG_FOR_IEI = -10,
TLV_ENCODE_WRONG_MESSAGE_TYPE = -11,
TLV_ENCODE_PROTOCOL_NOT_SUPPORTED = -12,
TLV_ENCODE_BUFFER_TOO_SHORT = -13,
TLV_ENCODE_BUFFER_NULL = -14,
} tlv_encoder_error_code;
/* Defines error code limit below which message should be sent because
* it cannot be further processed */
#define TLV_ENCODE_FATAL_ERROR (TLV_ENCODE_VALUE_DOESNT_MATCH)
extern int errorCodeEncoder;
void tlv_encode_perror(void);
#define CHECK_PDU_POINTER_AND_LENGTH_ENCODER(bUFFER, mINIMUMlENGTH, lENGTH) \
if (bUFFER == NULL) \
{ \
printf("Got NULL pointer for the payload\n"); \
errorCodeEncoder = TLV_ENCODE_BUFFER_NULL; \
return TLV_ENCODE_BUFFER_NULL; \
} \
if (lENGTH < mINIMUMlENGTH) \
{ \
printf("(%s:%d) Expecting at least %d bytes, got %d\n", \
__FILE__, __LINE__, mINIMUMlENGTH, lENGTH); \
errorCodeEncoder = TLV_ENCODE_BUFFER_TOO_SHORT; \
return TLV_ENCODE_BUFFER_TOO_SHORT; \
}
#define CHECK_PDU_POINTER_ENCODER(bUFFER) \
if (bUFFER == NULL) \
{ \
printf("Got NULL pointer for the payload\n"); \
errorCodeEncoder = TLV_ENCODE_BUFFER_NULL; \
return TLV_ENCODE_BUFFER_NULL; \
}
#endif /* define (TLV_ENCODER_H_) */
+271
View File
@@ -0,0 +1,271 @@
/*
* 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 device.c
Version 0.1
Date 2012/11/29
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Implements Linux/UNIX I/O device handlers
*****************************************************************************/
#include "device.h"
#include "commonDef.h"
#include <stdio.h> // fflush
#include <stdlib.h> // malloc, free
#include <string.h> // strncpy
#include <unistd.h> // read, write, close
#include <sys/stat.h>
#include <fcntl.h> // open
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/
/* Function used to configure TTY I/O terminal attributes */
extern int stty_set(int fd, const char *params);
/****************************************************************************/
/******************* L O C A L D E F I N I T I O N S *******************/
/****************************************************************************/
/* ------------------------
* Identifier of the device
* ------------------------
* A device is defined with a pathname and attribute parameters.
* A file descriptor is created to handle the setup of the device
* attributes.
*/
struct device_id_s {
#define DEVICE_PATHNAME_SIZE 32
char pathname[DEVICE_PATHNAME_SIZE+1]; /* device pathname */
int fd; /* device file descriptor */
};
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: device_open() **
** **
** Description: Open a device to get a file descriptor for use with read **
** and write I/O operations **
** **
** Inputs: devpath: Device path name **
** params: Device parameters **
** Others: None **
** **
** Outputs: None **
** Return: A pointer to the device identifier alloca- **
** ted for I/O operations. NULL if the device **
** has not been successfully opened. **
** Others: None **
** **
***************************************************************************/
void* device_open(int type, const char* devpath, const char* params)
{
int fd;
/* Parameters sanity check */
if (devpath == NULL) {
return NULL;
}
if (type != DEVICE) {
return NULL;
}
/* Open the device for I/O operations */
fd = open(devpath, O_RDWR);
if (fd < 0) {
return NULL;
}
/* The device has been successfully opened */
device_id_t * devid = (device_id_t *)malloc(sizeof(struct device_id_s));
if (devid != NULL) {
strncpy(devid->pathname, devpath, DEVICE_PATHNAME_SIZE);
devid->fd = fd;
if (params != NULL) {
/* Set TTY parameters */
if (stty_set(fd, params) != RETURNok) {
device_close(devid);
devid = NULL;
}
}
}
return devid;
}
/****************************************************************************
** **
** Name: device_close() **
** **
** Description: Close the specified device and frees memory space alloca- **
** ted to handle access to the device **
** **
** Inputs: None **
** Others: None **
** **
** Outputs: id: The identifier of the device **
** Return: None **
** Others: None **
** **
***************************************************************************/
void device_close(void* id)
{
if (id) {
close( ((device_id_t*)id)->fd );
free(id);
}
}
/****************************************************************************
** **
** Name: device_read() **
** **
** Description: Read data from the given I/O device into the input buffer **
** of specified length **
** **
** Inputs: id: The identifier of the device **
** len: The number of bytes to read **
** Others: None **
** **
** Outputs: buffer: The input buffer **
** Return: The number of bytes read when success; **
** RETURNerror otherwise. **
** Others: None **
** **
***************************************************************************/
ssize_t device_read(void* id, char* buffer, size_t len)
{
const device_id_t* devid = (device_id_t*)(id);
#if 0
ssize_t rbytes = read(devid->fd, buffer, len);
if (rbytes < 0) {
return RETURNerror;
}
#endif
//#if 0
ssize_t rbytes = 0;
do {
ssize_t size = read(devid->fd, buffer + rbytes, len - rbytes);
if (size < 0) {
return RETURNerror;
}
rbytes += size;
} while ( (buffer[rbytes-1] != '\r') && (buffer[rbytes-1] != '\n')
&& (buffer[rbytes-1] != '\0') );
//#endif
return rbytes;
}
/****************************************************************************
** **
** Name: device_write() **
** **
** Description: Write data to the given I/O device from the output buffer **
** of specified length **
** **
** Inputs: id: The identifier of the device **
** buffer: The output buffer **
** len: The number of bytes to write **
** Others: None **
** **
** Outputs: None **
** Return: The number of bytes written when success; **
** RETURNerror otherwise. **
** Others: None **
** **
***************************************************************************/
ssize_t device_write(const void* id, const char* buffer, size_t len)
{
const device_id_t* devid = (device_id_t*)(id);
ssize_t sbytes = write(devid->fd, buffer, len);
fflush(NULL);
if (sbytes != len) {
return RETURNerror;
}
return sbytes;
}
/****************************************************************************
** **
** Name: device_get_fd() **
** **
** Description: Get the value of the file descriptor created to handle **
** the device with the given identifier **
** **
** Inputs: id: The identifier of the device **
** Others: None **
** **
** Outputs: None **
** Return: The file descriptor of the device **
** Others: None **
** **
***************************************************************************/
int device_get_fd(const void* id)
{
if (id) {
return ((device_id_t*)id)->fd;
}
return RETURNerror;
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
+80
View File
@@ -0,0 +1,80 @@
/*
* 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 device.h
Version 0.1
Date 2012/11/29
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Implements Linux/UNIX I/O device handlers
*****************************************************************************/
#ifndef __DEVICE_H__
#define __DEVICE_H__
#include <sys/types.h>
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/* Type of the connection endpoint */
#define DEVICE 3
/* Hidden structure that handles device data */
typedef struct device_id_s device_id_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
void* device_open(int type, const char* devname, const char* params);
int device_get_fd(const void* id);
ssize_t device_read(void* id, char* buffer, size_t length);
ssize_t device_write(const void* id, const char* buffer, size_t length);
void device_close(void* id);
#endif /* __DEVICE_H__*/
+191
View File
@@ -0,0 +1,191 @@
/*
* 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 memory.c
Version 0.1
Date 2012/10/09
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Memory access utilities
*****************************************************************************/
#include "memory.h"
#include "commonDef.h"
#include "nas_log.h"
#include <stdio.h> // fopen, fread, fclose
#include <stdlib.h> // getenv, malloc, free
#include <string.h> // strlen
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: memory_get_path() **
** **
** Description: Gets the absolute path of the file where non-volatile **
** data are located **
** **
** Inputs: dirname: The directory where data file is located **
** filename: The name of the data file **
** Others: None **
** **
** Outputs: None **
** Return: The absolute path of the non-volatile data **
** file. The returned value is a dynamically **
** allocated octet string that needs to be **
** freed after usage. **
** Others: None **
** **
***************************************************************************/
char* memory_get_path(const char* dirname, const char* filename)
{
/* Get non-volatile data directory */
const char* path = getenv(dirname);
if (path == NULL) {
path = getenv(DEFAULT_NAS_PATH);
}
if (path == NULL) {
LOG_TRACE(WARNING, "MEMORY - %s and %s environment variables are not defined trying local directory", dirname, DEFAULT_NAS_PATH);
path = ".";
}
/* Append non-volatile data file name */
size_t size = strlen(path) + strlen(filename) + 1;
char* data_filename = (char*)malloc(size+1);
if (data_filename != NULL) {
if (size != sprintf(data_filename, "%s/%s", path, filename)) {
free(data_filename);
return NULL;
}
}
return data_filename;
}
/****************************************************************************
** **
** Name: memory_read() **
** **
** Description: Reads data from a non-volatile data file **
** **
** Inputs: datafile: The absolute path to the data file **
** size: The size of the data to read **
** Others: None **
** **
** Outputs: data: Pointer to the data read **
** Return: RETURNerror, RETURNok **
** Others: None **
** **
***************************************************************************/
int memory_read(const char* datafile, void* data, size_t size)
{
int rc = RETURNerror;
/* Open the data file for reading operation */
FILE* fp = fopen(datafile, "rb");
if (fp != NULL) {
/* Read data */
size_t n = fread(data, size, 1, fp);
if (n == 1) {
rc = RETURNok;
}
/* Close the data file */
fclose(fp);
}
return (rc);
}
/****************************************************************************
** **
** Name: memory_write() **
** **
** Description: Writes data to a non-volatile data file **
** **
** Inputs: datafile: The absolute path to the data file **
** data: Pointer to the data to write **
** size: The size of the data to write **
** Others: None **
** **
** Outputs: None **
** Return: RETURNerror, RETURNok **
** Others: None **
** **
***************************************************************************/
int memory_write(const char* datafile, const void* data, size_t size)
{
int rc = RETURNerror;
/* Open the data file for writing operation */
FILE* fp = fopen(datafile, "wb");
if (fp != NULL) {
/* Write data */
size_t n = fwrite(data, size, 1, fp);
if (n == 1) {
rc = RETURNok;
}
/* Close the data file */
fclose(fp);
}
return (rc);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
+72
View File
@@ -0,0 +1,72 @@
/*
* 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 memory.h
Version 0.1
Date 2012/10/09
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Memory access utilities
*****************************************************************************/
#ifndef __MEMORY_H__
#define __MEMORY_H__
#include <stddef.h> // size_t
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
char* memory_get_path(const char* dirname, const char* filename);
int memory_read(const char* datafile, void* data, size_t size);
int memory_write(const char* datafile, const void* data, size_t size);
#endif /* __MEMORY_H__*/
+280
View File
@@ -0,0 +1,280 @@
/*
* 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 nas_log.c
Version 0.1
Date 2012/02/28
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Usefull logging functions
*****************************************************************************/
#include "nas_log.h"
#if defined(NAS_BUILT_IN_UE) && defined(NAS_UE)
int nas_log_func_indent;
#else
#include <stdio.h> // stderr, sprintf, fprintf, vfprintf
#include <stdarg.h> // va_list, va_start, va_end
#include <string.h> // strlen
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/
/* ANSI escape codes for colored display */
#define LOG_BLACK "\033[30m"
#define LOG_RED "\033[31m"
#define LOG_GREEN "\033[32m"
#define LOG_YELLOW "\033[33m"
#define LOG_BLUE "\033[34m"
#define LOG_MAGENTA "\033[35m"
#define LOG_CYAN "\033[36m"
#define LOG_WHITE "\033[37m"
#define LOG_END "\033[0m"
#define LOG_AUTO LOG_END
/****************************************************************************/
/******************* L O C A L D E F I N I T I O N S *******************/
/****************************************************************************/
/* ------------------------
* Internal logging context
* ------------------------
* Internal logging context consists on:
* - The file name and the line number from where the data have been
* logged. These information are gathered into a string that will
* be displayed as a prefix of the logging trace with the format
* filename[line]
* - The severity level filter
* - The indentation level to convey FUNC logging traces
* - The data definition of each logging trace level: name and mask
* (the mask is used against the severity level filter to enable
* or disable specific logging traces)
*/
typedef struct {
#define LOG_PREFIX_SIZE 118
char prefix[LOG_PREFIX_SIZE];
unsigned char filter;
int indent;
const struct {
char* name;
unsigned char mask;
char* color;
} level[];
} log_context_t;
/*
* Definition of the logging context
*/
static log_context_t _log_context = {
"", /* prefix */
0x00, /* filter */
0, /* indent */
{
{ "DEBUG", NAS_LOG_DEBUG, LOG_GREEN }, /* DEBUG */
{ "INFO", NAS_LOG_INFO, LOG_AUTO }, /* INFO */
{ "WARNING", NAS_LOG_WARNING, LOG_BLUE }, /* WARNING */
{ "ERROR", NAS_LOG_ERROR, LOG_RED }, /* ERROR */
{ "", NAS_LOG_FUNC, LOG_AUTO }, /* FUNC_IN */
{ "", NAS_LOG_FUNC, LOG_AUTO }, /* FUNC_OUT */
} /* level[] */
};
/* Maximum number of bytes into a line of dump logging data */
#define LOG_DUMP_LINE_SIZE 16
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: log_init() **
** **
** Description: Initializes internal logging data **
** **
** Inputs: filter: Value of the severity level that will be **
** used as a filter to enable or disable **
** specific logging traces **
** Others: None **
** **
** Outputs: Return: None **
** Others: None **
** **
***************************************************************************/
void nas_log_init(char filter)
{
_log_context.filter = filter;
}
/****************************************************************************
** **
** Name: log_data() **
** **
** Description: Defines internal logging data **
** **
** Inputs: filename: Name of the file from where the data have **
** been logged **
** line: Number of the line in the file **
** Others: None **
** **
** Outputs: Return: None **
** Others: None **
** **
***************************************************************************/
void log_data(const char* filename, int line)
{
int len = strlen(filename) + 2 + 1; //2:[], 1:/0
if (line > 9999) len+=5;
else if (line > 999) len+=4;
else if (line > 99) len+=3;
else if (line > 9) len+=2;
else len+=1;
if (len > LOG_PREFIX_SIZE) {
snprintf(_log_context.prefix, LOG_PREFIX_SIZE, "%s:%d", &filename[len - LOG_PREFIX_SIZE], line);
} else {
snprintf(_log_context.prefix, LOG_PREFIX_SIZE, "%s:%d", filename, line);
}
}
/****************************************************************************
** **
** Name: log_trace() **
** **
** Description: Displays logging data **
** **
** Inputs: severity: Severity level of the logging data **
** data: Formated logging data to display **
** Others: None **
** **
** Outputs: Return: None **
** Others: None **
** **
***************************************************************************/
void log_trace(log_severity_t severity, const char* data, ...)
{
int i;
/* Sanity check */
if (severity > LOG_SEVERITY_MAX) return;
/* Display only authorized logging traces */
if (_log_context.level[severity].mask & _log_context.filter) {
va_list argp;
/*
* First, display internal logging data (logging trace prefix: file
* name and line number from where the data have been logged) and
* the severity level.
*/
fprintf(stderr, "%s%-120.118s%-10s", _log_context.level[severity].color,
_log_context.prefix, _log_context.level[severity].name);
{
/* Next, perform indentation for FUNC logging trace */
if (severity == FUNC_OUT) {
_log_context.indent--;
}
for (i=0; i<_log_context.indent; i++) {
fprintf(stderr, " ");
}
if (severity == FUNC_IN) {
_log_context.indent++;
}
}
/* Finally, display logging data */
va_start(argp, data);
vfprintf(stderr, data, argp);
/* Terminate with line feed character */
fprintf(stderr, "%s\n", LOG_END);
va_end(argp);
}
}
/****************************************************************************
** **
** Name: log_dump() **
** **
** Description: Dump logging data **
** **
** Inputs: data: Logging data to dump **
** len: Number of bytes to be dumped **
** Others: None **
** **
** Outputs: Return: None **
** Others: None **
** **
***************************************************************************/
void log_dump(const char* data, int len)
{
int i;
/* Display only authorized logging traces */
if ( (len > 0) && (NAS_LOG_HEX & _log_context.filter) ) {
int bytes = 0;
fprintf(stderr, "\n\t");
for (i=0; i < len; i++) {
fprintf(stderr, "%.2hx ", (const unsigned char) data[i]);
/* Add new line when the number of displayed bytes exceeds
* the line's size */
if ( ++bytes > (LOG_DUMP_LINE_SIZE - 1) ) {
bytes = 0;
fprintf(stderr, "\n\t");
}
}
if (bytes % LOG_DUMP_LINE_SIZE) {
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
fflush(stderr);
}
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
#endif
+166
View File
@@ -0,0 +1,166 @@
/*
* 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 nas_log.h
Version 0.1
Date 2012/02/28
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Usefull logging functions
*****************************************************************************/
#ifndef __NAS_LOG_H__
#define __NAS_LOG_H__
#if defined(NAS_BUILT_IN_UE) && defined(NAS_UE)
# include "UTIL/LOG/log.h"
# undef LOG_TRACE
#endif
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/* -----------------------
* Logging severity levels
* -----------------------
* OFF : Disables logging trace utilities.
* DEBUG : Only used for debug purpose. Should be removed from the code.
* INFO : Informational trace
* WARNING : The program displays the warning message and doesn't stop.
* ERROR : The program displays the error message and usually exits or
* runs appropriate procedure.
* FUNC : Prints trace when entering/leaving to/from function. Usefull
* to display the function's calling tree information at runtime.
* ON : Enables logging traces excepted FUNC.
* ALL : Turns on ALL logging traces.
*/
#define NAS_LOG_OFF 0x00 /* No trace */
#define NAS_LOG_DEBUG 0x01 /* Debug trace */
#define NAS_LOG_INFO 0x02 /* Informational trace */
#define NAS_LOG_WARNING 0x04 /* Warning trace */
#define NAS_LOG_ERROR 0x08 /* Error trace */
#define NAS_LOG_FUNC 0x10 /* Entering/Leaving function trace */
#define NAS_LOG_HEX 0x20 /* Dump trace */
#define NAS_LOG_ON 0x0F /* All traces excepted FUNC and HEX */
#define NAS_LOG_ALL 0xFF /* All traces */
/* Logging severity type */
typedef enum {
DEBUG,
INFO,
WARNING,
ERROR,
FUNC_IN,
FUNC_OUT,
LOG_SEVERITY_MAX
} log_severity_t;
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
#if defined(NAS_BUILT_IN_UE) && defined(NAS_UE)
# define LOG_TRACE(s, x, args...) \
do { \
switch (s) { \
case ERROR: LOG_E(NAS, " %s:%d " x "\n", __FILE__, __LINE__, ##args); break; \
case WARNING: LOG_W(NAS, " %s:%d " x "\n", __FILE__, __LINE__, ##args); break; \
case INFO: LOG_I(NAS, " %s:%d " x "\n", __FILE__, __LINE__, ##args); break; \
default: LOG_D(NAS, " %s:%d " x "\n", __FILE__, __LINE__, ##args); break; \
} \
} while (0)
# define LOG_DUMP(dATA, lEN) \
do { \
char buffer[3*lEN + 1]; \
int i; \
for (i = 0; i < lEN; i++) \
sprintf (&buffer[3*i], "%02x ", dATA[i]); \
LOG_D(NAS, " Dump %d: %s\n", lEN, buffer); \
} while (0)
# define LOG_FUNC_IN \
do { \
LOG_D(NAS, " %s:%d %*sEntering %s()\n", __FILE__, __LINE__, nas_log_func_indent, "", __FUNCTION__); \
nas_log_func_indent += 2; \
} while (0)
# define LOG_FUNC_OUT \
do { \
nas_log_func_indent -= 2; \
LOG_D(NAS, " %s:%d %*sLeaving %s()\n", __FILE__, __LINE__, nas_log_func_indent, "", __FUNCTION__); \
} while (0)
# define LOG_FUNC_RETURN(rETURNcODE) \
do { \
nas_log_func_indent -= 2; \
LOG_D(NAS, " %s:%d %*sLeaving %s(rc = %ld)\n", __FILE__, __LINE__, nas_log_func_indent, "", \
__FUNCTION__, (long) rETURNcODE); \
return (rETURNcODE); \
} while (0)
extern int nas_log_func_indent;
#else
# define LOG_TRACE log_data(__FILE__, __LINE__); log_trace
# define LOG_DUMP(a, b) log_dump((a),(b));
# define LOG_FUNC_IN LOG_TRACE(FUNC_IN, "Entering %s()", __FUNCTION__)
# define LOG_FUNC_OUT LOG_TRACE(FUNC_OUT, "Leaving %s()", __FUNCTION__)
# define LOG_FUNC_RETURN(rETURNcODE) \
do { \
LOG_TRACE(FUNC_OUT, "Leaving %s(rc = %ld)", __FUNCTION__, \
(long) rETURNcODE); \
return (rETURNcODE); \
} while(0)
void nas_log_init(char filter);
void log_data(const char* filename, int line);
void log_trace(log_severity_t severity, const char* data, ...);
void log_dump(const char* data, int len);
#endif
#endif /* __NAS_LOG_H__*/
+881
View File
@@ -0,0 +1,881 @@
/*
* 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 nas_timer.c
Version 0.1
Date 2012/10/09
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Timer utilities
*****************************************************************************/
#include <pthread.h>
#include <assert.h>
#include <stdint.h>
#include <string.h> // memset
#include <stdlib.h> // malloc, free
#include <sys/time.h> // setitimer
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
# include "timer.h"
#else
# include <signal.h>
# include <time.h> // clock_gettime
#endif
#include "nas_timer.h"
#include "commonDef.h"
#include "msc.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 *******************/
/****************************************************************************/
/* Structure of an interval timer entry
* ------------------------------------
* The callback function is scheduled to be executed upon expiration of
* the timer that has been previously setup to the initial interval time
* value when the timer entry was allocated.
*/
typedef struct {
#if defined(ENABLE_ITTI)
long timer_id; /* Timer id returned by the timer API from ITTI */
#else
pthread_t pid; /* Thread identifier of the callback */
#endif
struct timeval itv; /* Initial interval timer value */
struct timeval tv; /* Interval timer value */
nas_timer_callback_t cb; /* Callback executed at timer expiration */
void *args; /* Callback argument parameters */
} nas_timer_entry_t;
/* Structure of a timer queue - list of active interval timer entries
* ------------------------------------------------------------------
* At any time, the first entry of the queue is always associated to the
* first timer that will come to expire. Upon timer expiration, the first
* entry is removed from the queue and freed.
*/
typedef struct _nas_timer_queue_t {
int id; /* Identifier of the current timer entry */
nas_timer_entry_t *entry; /* The current timer entry */
struct _nas_timer_queue_t *prev;/* The previous timer entry in the queue */
struct _nas_timer_queue_t *next;/* The next timer entry in the queue */
} timer_queue_t;
/* Structure of a timer database
* -----------------------------
* The timer database is managed to provide unique identifier to timer at
* startup and to maintain an ordered queue of active timer entries.
*/
typedef struct {
int timer_id; /* Identifier of the first available timer entry */
#define TIMER_DATABASE_SIZE 256
timer_queue_t tq[TIMER_DATABASE_SIZE];
timer_queue_t *head;/* Pointer to the first timer entry to be fired */
#if !defined(ENABLE_ITTI)
pthread_mutex_t mutex;
#endif
} nas_timer_database_t;
/*
* The timer database
*/
static nas_timer_database_t _nas_timer_db = {
0,
{},
NULL
#if !defined(ENABLE_ITTI)
, PTHREAD_MUTEX_INITIALIZER
#endif
};
#if defined(ENABLE_ITTI)
#define nas_timer_lock_db()
#define nas_timer_unlock_db()
#else
#define nas_timer_lock_db() pthread_mutex_lock(&_nas_timer_db.mutex)
#define nas_timer_unlock_db() pthread_mutex_unlock(&_nas_timer_db.mutex)
#endif
/*
* The handler executed whenever the system timer expires
*/
#if !defined(ENABLE_ITTI)
static void _nas_timer_handler(int signal);
#endif
/*
* -----------------------------------------------------------------------------
* Functions used to manage the timer database
* -----------------------------------------------------------------------------
*/
static void _nas_timer_db_init(void);
static int _nas_timer_db_get_id(void);
static int _nas_timer_db_is_active(int id);
static nas_timer_entry_t *_nas_timer_db_create_entry(long sec,
nas_timer_callback_t cb, void *args);
static void _nas_timer_db_delete_entry(int id);
static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t *te);
static int _nas_timer_db_insert(timer_queue_t *entry);
static nas_timer_entry_t *_nas_timer_db_remove_entry(int id);
static int _nas_timer_db_remove(timer_queue_t *entry);
/*
* -----------------------------------------------------------------------------
* Operator functions for timeval structures
* -----------------------------------------------------------------------------
*/
static int _nas_timer_cmp(const struct timeval *a, const struct timeval *b);
static void _nas_timer_add(const struct timeval *a, const struct timeval *b,
struct timeval *result);
static int _nas_timer_sub(const struct timeval *a, const struct timeval *b,
struct timeval *result);
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: timer_init() **
** **
** Description: Initializes internal data used to manage timers **
** **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _nas_timer_db **
** **
***************************************************************************/
int nas_timer_init(void)
{
/* Initialize the timer database */
_nas_timer_db_init();
#if !defined(ENABLE_ITTI)
/* Setup the timer database handler */
struct sigaction act;
(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);
act.sa_handler = _nas_timer_handler;
if ( sigaction (SIGALRM, &act, 0) < 0 ) {
return (RETURNerror);
}
#endif
return (RETURNok);
}
/****************************************************************************
** **
** Name: timer_start() **
** **
** Description: Schedules the execution of the given callback function **
** upon expiration of the specified time interval **
** **
** Inputs: sec: The value of the time interval in seconds **
** cb: Function executed upon timer expiration **
** args: Callback argument parameters **
** Others: None **
** **
** Outputs: None **
** Return: The timer identifier when successfully **
** started; NAS_TIMER_INACTIVE_ID otherwise. **
** Others: None **
** **
***************************************************************************/
int nas_timer_start(long sec, nas_timer_callback_t cb, void *args)
{
int id;
nas_timer_entry_t *te;
#if defined(ENABLE_ITTI)
int ret;
long timer_id;
#endif
/* Do not start null timer */
if (sec == 0) {
return (NAS_TIMER_INACTIVE_ID);
}
/* Get an identifier for the new timer entry */
id = _nas_timer_db_get_id();
if (id < 0) {
/* No available timer entry found */
return (NAS_TIMER_INACTIVE_ID);
}
/* Create a new timer entry */
te = _nas_timer_db_create_entry(sec, cb, args);
if (te == NULL) {
return (NAS_TIMER_INACTIVE_ID);
}
/* Insert the new entry into the timer queue */
_nas_timer_db_insert_entry(id, te);
#if defined(ENABLE_ITTI)
# if defined(NAS_MME)
ret = timer_setup(sec, 0, TASK_NAS_MME, INSTANCE_DEFAULT, TIMER_PERIODIC, args, &timer_id);
# else
ret = timer_setup(sec, 0, TASK_NAS_UE, INSTANCE_DEFAULT, TIMER_PERIODIC, args, &timer_id);
# endif
if (ret == -1) {
return NAS_TIMER_INACTIVE_ID;
}
te->timer_id = timer_id;
#endif
return (id);
}
/****************************************************************************
** **
** Name: timer_stop() **
** **
** Description: Stop the timer with the specified identifier **
** **
** Inputs: id: The identifier of the timer to be stopped **
** Others: None **
** **
** Outputs: None **
** Return: NAS_TIMER_INACTIVE_ID when successfully stop- **
** ped; The timer identifier otherwise. **
** Others: None **
** **
***************************************************************************/
int nas_timer_stop(int id)
{
/* Check if the timer entry is active */
if (_nas_timer_db_is_active(id)) {
nas_timer_entry_t *entry;
/* Remove the entry from the timer queue */
entry = _nas_timer_db_remove_entry(id);
#if defined(ENABLE_ITTI)
timer_remove(entry->timer_id);
#else
(void)entry;
#endif
/* Delete the timer entry */
_nas_timer_db_delete_entry(id);
return (NAS_TIMER_INACTIVE_ID);
}
return (id);
}
/****************************************************************************
** **
** Name: timer_restart() **
** **
** Description: Restart the timer with the specified identifier. The ti- **
** mer is scheduled to expire after the same period of time **
** and will execute the callback function that has been set **
** when it was started. **
** **
** Inputs: id: The identifier of the timer to be started **
** again **
** Others: None **
** **
** Outputs: None **
** Return: The timer identifier when successfully **
** re-started; NAS_TIMER_INACTIVE_ID otherwise. **
** Others: None **
** **
***************************************************************************/
int nas_timer_restart(int id)
{
/* Check if the timer entry is active */
if (_nas_timer_db_is_active(id)) {
/* Remove the entry from the timer queue */
nas_timer_entry_t *te = _nas_timer_db_remove_entry(id);
/* Initialize its interval timer value */
te->tv = te->itv;
/* Insert again the entry into the timer queue */
_nas_timer_db_insert_entry(id, te);
return (id);
}
return (NAS_TIMER_INACTIVE_ID);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/****************************************************************************
** **
** Name: _nas_timer_handler() **
** **
** Description: The timer handler is executed whenever the system deli- **
** vers signal SIGALARM. It starts execution of the callback **
** function of the first entry within the queue of active **
** timer entries. The entry is not removed from the queue of **
** active timer entries and shall be explicitly removed when **
** the timer expires. **
** **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _nas_timer_db **
** **
***************************************************************************/
#if defined(ENABLE_ITTI)
void nas_timer_handle_signal_expiry(long timer_id, void *arg_p)
{
/* Get the timer entry for which the system timer expired */
nas_timer_entry_t *te = _nas_timer_db.head->entry;
te->cb(te->args);
}
#else
static void _nas_timer_handler(int signal)
{
/* At least one timer has been started */
assert( (_nas_timer_db.head != NULL) && (_nas_timer_db.head->entry != NULL) );
/* Get the timer entry for which the system timer expired */
nas_timer_entry_t *te = _nas_timer_db.head->entry;
/* Execute the callback function */
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
int rc = pthread_create (&te->pid, &attr, te->cb, te->args);
pthread_attr_destroy(&attr);
/* Wait for the thread to terminate before releasing the timer entry */
if (rc == 0) {
void *result = NULL;
(void) pthread_join(te->pid, &result);
/* TODO: Check returned result ??? */
if (result) {
free(result);
}
}
}
#endif
/*
* -----------------------------------------------------------------------------
* Functions used to manage the timer database
* -----------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _nas_timer_db_init() **
** **
** Description: Initializes the timer database **
** **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _nas_timer_db **
** **
***************************************************************************/
static void _nas_timer_db_init(void)
{
int i;
for (i = 0; i < TIMER_DATABASE_SIZE; i++) {
_nas_timer_db.tq[i].id = NAS_TIMER_INACTIVE_ID;
}
}
/****************************************************************************
** **
** Name: _nas_timer_db_get_id() **
** **
** Description: Gets the identifier of the first available timer entry in **
** the queue of active timer entries **
** **
** Inputs: None **
** Others: _nas_timer_db **
** **
** Outputs: None **
** Return: The identifier of the first available **
** timer entry if the queue of active timers **
** is not full; -1 otherwise. **
** Others: _nas_timer_db **
** **
***************************************************************************/
static int _nas_timer_db_get_id(void)
{
int i;
/* Search from the current timer entry to the last timer entry */
for (i = _nas_timer_db.timer_id; i < TIMER_DATABASE_SIZE; i++) {
if (_nas_timer_db.tq[i].id < 0 ) {
_nas_timer_db.timer_id = i+1;
return i;
}
}
/* Search from the first timer entry to the current timer entry */
for (i = 0; i < _nas_timer_db.timer_id; i++) {
if (_nas_timer_db.tq[i].id < 0 ) {
_nas_timer_db.timer_id = i+1;
return i;
}
}
/* No available timer entry found */
return (-1);
}
/****************************************************************************
** **
** Name: _nas_timer_db_is_active() **
** **
** Description: Checks whether the entry with the given identifier is **
** active within the queue of active timer entries **
** **
** Inputs: id: Identifier of the timer entry to check **
** Others: _nas_timer_db **
** **
** Outputs: None **
** Return: TRUE if the timer entry is active; FALSE **
** if it is not an active timer entry. **
** Others: None **
** **
***************************************************************************/
static int _nas_timer_db_is_active(int id)
{
return ( (id != NAS_TIMER_INACTIVE_ID) &&
(_nas_timer_db.tq[id].id != NAS_TIMER_INACTIVE_ID) );
}
/****************************************************************************
** **
** Name: _nas_timer_db_create_entry() **
** **
** Description: Creates a new timer entry **
** **
** Inputs: sec: Time interval value **
** cb: Function executed upon timer expiration **
** args: Callback argument parameters **
** Others: None **
** **
** Outputs: None **
** Return: A pointer to the new timer entry if **
** successfully allocated; NULL otherwise **
** Others: None **
** **
***************************************************************************/
static nas_timer_entry_t *_nas_timer_db_create_entry(
long sec, nas_timer_callback_t cb,
void *args)
{
nas_timer_entry_t *te = (nas_timer_entry_t *)malloc(sizeof(nas_timer_entry_t));
if (te != NULL) {
te->itv.tv_sec = sec;
te->itv.tv_usec = 0;
te->tv.tv_sec = te->itv.tv_sec;
te->tv.tv_usec = te->itv.tv_usec;
te->cb = cb;
te->args = args;
}
return (te);
}
/****************************************************************************
** **
** Name: _nas_timer_db_delete_entry() **
** **
** Description: Deletes the entry with the given identifier from the ti- **
** mer database. **
** **
** Inputs: id: Identifier of the entry to be deleted **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _nas_timer_db **
** **
***************************************************************************/
static void _nas_timer_db_delete_entry(int id)
{
/* The identifier of the timer is valid within the timer queue */
assert(_nas_timer_db.tq[id].id == id);
/* Delete the timer entry from the queue */
_nas_timer_db.tq[id].id = NAS_TIMER_INACTIVE_ID;
free(_nas_timer_db.tq[id].entry);
_nas_timer_db.tq[id].entry = NULL;
}
/****************************************************************************
** **
** Name: _nas_timer_db_insert_entry() **
** **
** Description: Inserts the entry with the given identifier into the **
** queue of active timer entries and restarts the system **
** timer if the new entry is the next entry for which the **
** timer should be scheduled to expire. **
** **
** Inputs: id: Identifier of the new entry **
** te: Pointer to the entry to be inserted **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _nas_timer_db **
** **
***************************************************************************/
static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t *te)
{
struct itimerval it;
struct timespec ts;
struct timeval current_time;
int restart;
/* Enqueue the new timer entry */
_nas_timer_db.tq[id].id = id;
_nas_timer_db.tq[id].entry = te;
/* Save its interval timer value */
it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
it.it_value = te->tv;
/* Update its interval timer value */
clock_gettime(CLOCK_MONOTONIC, &ts);
current_time.tv_sec = ts.tv_sec;
current_time.tv_usec = ts.tv_nsec/1000;
/* tv = tv + time() */
_nas_timer_add(&te->tv, &current_time, &te->tv);
/* Insert the new timer entry into the list of active entries */
nas_timer_lock_db();
restart = _nas_timer_db_insert(&_nas_timer_db.tq[id]);
nas_timer_unlock_db();
#if !defined(ENABLE_ITTI)
if (restart) {
/* The new entry is the first entry of the list;
* restart the system timer */
setitimer(ITIMER_REAL, &it, 0);
}
#else
(void)(restart);
#endif
}
static int _nas_timer_db_insert(timer_queue_t *entry)
{
timer_queue_t *prev, *next; /* previous and next entry in the list */
/*
* Search the list of timer entries for the first entry with an interval
* timer value greater than the interval timer value of the new timer entry
*/
for (prev = NULL, next = _nas_timer_db.head; next != NULL; next = next->next) {
if (_nas_timer_cmp(&next->entry->tv, &entry->entry->tv) > 0) {
break;
}
prev = next;
}
/* Insert the new entry in the list of active timer entries */
/* prev <-- entry --> next */
entry->prev = prev;
entry->next = next;
/* Update the pointer from the previous entry */
if (entry->next != NULL) {
/* prev <-- entry <--> next */
entry->next->prev = entry;
}
/* Update the pointer from the next entry */
if (entry->prev != NULL) {
/* prev <--> entry <--> next */
entry->prev->next = entry;
} else {
/* The new entry is the first entry of the list */
_nas_timer_db.head = entry;
return TRUE;
}
/* The new entry is NOT the first entry of the list */
return FALSE;
}
/****************************************************************************
** **
** Name: _nas_timer_db_remove_entry() **
** **
** Description: Removes the entry with the given identifier from the **
** queue of active timer entries and restarts the system **
** timer if the entry was the next entry for which the timer **
** was scheduled to expire. **
** **
** Inputs: id: Identifier of the entry to be removed **
** Others: None **
** **
** Outputs: None **
** Return: A pointer to the removed entry **
** Others: _nas_timer_db **
** **
***************************************************************************/
static nas_timer_entry_t *_nas_timer_db_remove_entry(int id)
{
int restart;
/* The identifier of the timer is valid within the timer queue */
assert(_nas_timer_db.tq[id].id == id);
/* Remove the timer entry from the list of active entries */
nas_timer_lock_db();
restart = _nas_timer_db_remove(&_nas_timer_db.tq[id]);
nas_timer_unlock_db();
if (restart) {
int rc;
/* The entry was the first entry of the list;
* the system timer needs to be restarted */
struct itimerval it;
struct timeval tv;
struct timespec ts;
it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
clock_gettime(CLOCK_MONOTONIC, &ts);
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec/1000;
/* tv = tv - time() */
rc = _nas_timer_sub(&_nas_timer_db.head->entry->tv, &tv, &it.it_value);
#if defined(ENABLE_ITTI)
timer_remove(_nas_timer_db.head->entry->timer_id);
(void) (rc);
#else
if (rc < 0) {
/* The system timer should have already expired */
_nas_timer_handler(SIGALRM);
} else {
/* Restart the system timer */
setitimer(ITIMER_REAL, &it, 0);
}
#endif
}
/* Return a pointer to the removed entry */
return (_nas_timer_db.tq[id].entry);
}
static int _nas_timer_db_remove(timer_queue_t *entry)
{
/* Update the pointer from the previous entry */
/* prev ---> entry ---> next */
/* prev <--- entry <--- next */
if (entry->next != NULL) {
/* prev ---> entry ---> next */
/* prev <-------------- next */
entry->next->prev = entry->prev;
}
/* Update the pointer from the next entry */
if (entry->prev != NULL) {
/* prev --------------> next */
/* prev <-------------- next */
entry->prev->next = entry->next;
} else {
/* The entry was the first entry of the list */
_nas_timer_db.head = entry->next;
if (_nas_timer_db.head != NULL) {
/* Other timers are scheduled to expire */
return TRUE;
}
#if !defined(ENABLE_ITTI)
{
/* No more timer is scheduled to expire; stop the system timer */
struct itimerval it;
it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
it.it_value.tv_sec = it.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &it, 0);
return FALSE;
}
#endif
}
/* The entry was NOT the first entry of the list */
return FALSE;
}
/*
* -----------------------------------------------------------------------------
* Operator functions for timeval structures
* -----------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _nas_timer_cmp() **
** **
** Description: Performs timeval comparaison **
** **
** Inputs: a: The first timeval structure **
** b: The second timeval structure **
** Others: None **
** **
** Outputs: None **
** Return: -1 if a < b; 1 if a > b; 0 if a == b **
** Others: None **
** **
***************************************************************************/
static int _nas_timer_cmp(const struct timeval *a, const struct timeval *b)
{
if (a->tv_sec < b->tv_sec) {
return -1;
} else if (a->tv_sec > b->tv_sec) {
return 1;
} else if (a->tv_usec < b->tv_usec) {
return -1;
} else if (a->tv_usec > b->tv_usec) {
return 1;
}
return 0;
}
/****************************************************************************
** **
** Name: _nas_timer_add() **
** **
** Description: Performs timeval addition **
** **
** Inputs: a: The first timeval structure **
** b: The second timeval structure **
** Others: None **
** **
** Outputs: result: result = timeval(a + b) **
** Return: None **
** Others: None **
** **
***************************************************************************/
static void _nas_timer_add(const struct timeval *a, const struct timeval *b,
struct timeval *result)
{
result->tv_sec = a->tv_sec + b->tv_sec;
result->tv_usec = a->tv_usec + b->tv_usec;
if (result->tv_usec > 1000000) {
result->tv_sec++;
result->tv_usec -= 1000000;
}
}
/****************************************************************************
** **
** Name: _nas_timer_sub() **
** **
** Description: Performs timeval substraction **
** **
** Inputs: a: The first timeval structure **
** b: The second timeval structure **
** Others: None **
** **
** Outputs: result: a >= b, result = timeval(a - b) **
** Return: -1 if a < b; 0 otherwise **
** Others: None **
** **
***************************************************************************/
static int _nas_timer_sub(const struct timeval *a, const struct timeval *b,
struct timeval *result)
{
if (_nas_timer_cmp(a,b) > 0 ) {
result->tv_sec = a->tv_sec - b->tv_sec;
result->tv_usec = a->tv_usec - b->tv_usec;
if (result->tv_usec < 0) {
result->tv_sec--;
result->tv_usec += 1000000;
}
return 0;
}
return -1;
}
+88
View File
@@ -0,0 +1,88 @@
/*
* 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 nas_timer.h
Version 0.1
Date 2012/11/22
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Timer utilities
*****************************************************************************/
#ifndef __NAS_TIMER_H__
#define __NAS_TIMER_H__
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/*
* Timer identifier returned when in inactive state (timer is stopped or has
* failed to be started)
*/
#define NAS_TIMER_INACTIVE_ID (-1)
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/* Timer structure */
struct nas_timer_t {
int id; /* The timer identifier */
long sec; /* The timer interval value in seconds */
};
/* Type of the callback executed when the timer expired */
typedef void *(*nas_timer_callback_t)(void *);
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int nas_timer_init(void);
int nas_timer_start(long sec, nas_timer_callback_t cb, void *args);
int nas_timer_stop(int id);
int nas_timer_restart(int id);
#if defined(NAS_BUILT_IN_EPC)
void nas_timer_handle_signal_expiry(long timer_id, void *arg_p);
#endif
#endif /* __NAS_TIMER_H__ */
+188
View File
@@ -0,0 +1,188 @@
/*
* 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 parser.c
Version 0.1
Date 2012/02/27
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Usefull command line parser
*****************************************************************************/
#include "parser.h"
#include "commonDef.h"
#include <stdio.h> // fprintf
#include <string.h> // strcmp, strncpy
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: parser_print_usage() **
** **
** Description: Displays command line usage **
** **
** Inputs: command_line: Pointer to the command line structure **
** Others: None **
** **
** Outputs: Return: None **
** Others: None **
** **
***************************************************************************/
void parser_print_usage(const parser_command_line_t* command_line)
{
fprintf(stderr, "Usage: %s", command_line->name);
for (int i=0; i < command_line->nb_options; i++) {
fprintf(stderr, " [%s %s]",
command_line->options[i].name,
command_line->options[i].argument);
}
fprintf(stderr, "\n");
for (int i=0; i < command_line->nb_options; i++) {
fprintf(stderr, "\t%s\t%s\t(%s)\n",
command_line->options[i].argument,
command_line->options[i].usage,
command_line->options[i].value);
}
}
/****************************************************************************
** **
** Name: parser_get_options() **
** **
** Description: Parses the command line options **
** **
** Inputs: argc: Number of command line options **
** argv: Pointer to the command line **
** command_line: Pointer to the command line structure **
** Others: None **
** **
** Outputs: Return: RETURNerror, RETURNok **
** command_line: Pointer to the command line structure **
** Others: None **
** **
***************************************************************************/
int parser_get_options(int argc, const char** argv,
parser_command_line_t* command_line)
{
int argument_not_found, option_not_found = 1;
int option_length;
/* Initialize command line structure */
strncpy(command_line->name, argv[0], PARSER_COMMAND_NAME_SIZE);
for (int i=0; i < command_line->nb_options; i++) {
if ( strcmp(command_line->options[i].value, "NULL") ) {
command_line->options[i].pvalue = command_line->options[i].value;
}
}
/* No command line options */
if (argc == 1) {
return RETURNok;
}
/* Parse the command line looking for options */
while (*++argv && **argv == '-') {
argument_not_found = 1;
option_not_found = 1;
for (int i=0; i < command_line->nb_options; i++) {
if ( !strcmp(command_line->options[i].name, *argv) ) {
option_not_found = 0;
if (argv[1] && *argv[1] != '-') {
argument_not_found = 0;
option_length = (int) strlen(*++argv);
if (option_length >= PARSER_OPTION_VALUE_SIZE) {
fprintf(stderr, "%s: option name too long (%d), should be less than %d characters\n",
*argv, option_length,
PARSER_OPTION_VALUE_SIZE);
return RETURNerror;
}
strcpy(command_line->options[i].value, *argv);
if (command_line->options[i].pvalue == NULL) {
command_line->options[i].pvalue =
command_line->options[i].value;
}
}
break;
}
}
if (option_not_found) {
if ( strcmp(*argv, "-?") && strcmp(*argv, "-h") &&
strcmp(*argv, "-help") && strcmp(*argv, "--help") ) {
fprintf(stderr, "%s: illegal option %s\n",
command_line->name, *argv);
return RETURNerror;
}
} else if (argument_not_found) {
fprintf(stderr, "%s: option %s requires an argument\n",
command_line->name, *argv);
return RETURNerror;
}
}
if (option_not_found) {
return RETURNerror;
}
return RETURNok;
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
+96
View File
@@ -0,0 +1,96 @@
/*
* 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 parser.h
Version 0.1
Date 2012/02/27
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Usefull command line parser
*****************************************************************************/
#ifndef __PARSER_H__
#define __PARSER_H__
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/* -----------
* Option type
* -----------
* An option is defined with a name, an argument following the option's
* name, the usage message and a value
*/
typedef struct {
const char* name; /* Option name */
const char* argument; /* Argument following the option */
const char* usage; /* Option and Argument usage */
#define PARSER_OPTION_VALUE_SIZE 32
char value[PARSER_OPTION_VALUE_SIZE]; /* Option value */
char* pvalue;
} parser_option_t;
/* -----------------
* Command line type
* -----------------
* An command line is defined with a name, the number of options and the
* list of command's options
*/
typedef struct {
#define PARSER_COMMAND_NAME_SIZE 32
char name[PARSER_COMMAND_NAME_SIZE]; /* Command name */
const int nb_options; /* Number of options */
parser_option_t options[]; /* Command line options */
} parser_command_line_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
void parser_print_usage(const parser_command_line_t* commamd_line);
int parser_get_options(int argc, const char** argv,
parser_command_line_t* commamd_line);
#endif /* __PARSER_H__*/
+426
View File
@@ -0,0 +1,426 @@
/*
* 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 socket.c
Version 0.1
Date 2012/02/28
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Implements socket handlers
*****************************************************************************/
#include "socket.h"
#include "commonDef.h"
#include <stdlib.h> // malloc, free, atoi
#include <string.h> // memset
#include <unistd.h> // close
#include <errno.h> // EINTR
#include <sys/types.h>
#include <sys/socket.h> // socket, setsockopt, connect, bind, recv, send
#include <netdb.h> // getaddrinfo
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/* -------------------------------------
* Identifier of network socket endpoint
* -------------------------------------
* A network socket endpoint is defined with a type (client or server),
* a port number, and the name and address of the remote host it should
* be connected to. A socket file descriptor is created to handle the
* setup of the communication channel with the remote peer.
*/
struct socket_id_s {
int type; /* connection type (client/server) */
int port; /* port number */
#define SOCKET_HOSTNAME_SIZE 32
char rhost[SOCKET_HOSTNAME_SIZE]; /* remote hostname */
struct sockaddr_storage addr; /* remote address */
int fd; /* socket file descriptor */
};
/* Set socket option at the sockets API level (SOL_SOCKET) */
static int _socket_set_option(int sfd);
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: socket_udp_open() **
** **
** Description: Initializes a communication endpoint for any IPv4 and **
** IPv6 protocol used by a local host to send/receive UDP **
** datagrams to/from a remote host in "connected" mode of **
** operation. **
** **
** Inputs: type: Type of the connection (client/server) **
** host: For client application, the remote host- **
** name, or numerical IPv4 or IPv6 network **
** address to connect to. NULL for server **
** application. **
** port: The port number **
** Others: None **
** **
** Outputs: None **
** Return: A pointer to the local endpoint identifier **
** that has been allocated for communication **
** with the remote peer. NULL if the setup of **
** the communication endpoint failed. **
** Others: None **
** **
***************************************************************************/
void* socket_udp_open(int type, const char* host, const char* port)
{
struct addrinfo socket_info; /* endpoint information */
struct addrinfo *socket_addr, *sp; /* endpoint address */
int sfd; /* socket file descriptor */
/*
* Parameters sanity check
* -----------------------
* The local connection endpoint shall be of type CLIENT or SERVER
*/
if (host == NULL) {
type = SOCKET_SERVER;
} else if (type != SOCKET_CLIENT && type != SOCKET_SERVER) {
return NULL;
}
/*
* Initialize the endpoint address information
* -------------------------------------------
* The AI_PASSIVE flag allows "wildcard address" when hostname is not
* provided (NULL). The wildcard address is used by applications (ty-
* pically servers) that intend to accept connections on any of the
* hosts's network addresses. If the hostname is not NULL, then the
* AI_PASSIVE flag is ignored.
* When the AI_V4MAPPED flag is set, and AF_INET6 is specified, and no
* matching IPv6 addresses could be found, then IPv4-mapped IPv6 addresses
* are returned by getaddrinfo in the list pointed to by result.
*/
memset (&socket_info, 0, sizeof(struct addrinfo));
socket_info.ai_socktype = SOCK_DGRAM; /* Datagram socket */
socket_info.ai_flags = AI_NUMERICSERV; /* numeric port number */
if (type != SOCKET_CLIENT) {
/* Setup socket address options at the server side */
socket_info.ai_family = AF_INET6; /* Accept either IPv4 or IPv6
* connections */
socket_info.ai_flags |= AI_PASSIVE; /* Use "wildcard address" */
socket_info.ai_flags |= AI_V4MAPPED; /* IPv4-mapped IPv6 address */
} else {
/* Setup socket address options at the client side */
socket_info.ai_family = AF_INET; /* Any address family */
// socket_info.ai_flags |= AI_V4MAPPED; /* IPv4-mapped IPv6 address */
}
/*
* getaddrinfo() returns a linked list of address structures:
* - The network host may be multi-homed, accessible over multiple
* protocols (e.g. both AF_INET and AF_INET6);
* - The same service (port number) may be available from multiple
* socket types (one SOCK_STREAM address and another SOCK_DGRAM address);
*/
int rc = getaddrinfo (host, port, &socket_info, &socket_addr);
if (rc != 0) {
if (rc != EAI_SYSTEM) {
errno = rc;
}
return NULL;
}
/*
* Try each address until we successfully connect
*/
for (sp = socket_addr; sp != NULL; sp = sp->ai_next) {
/* Create the socket endpoint for communication */
sfd = socket (sp->ai_family, sp->ai_socktype, sp->ai_protocol);
if (sfd < 0) {
continue;
}
/*
* Initiate a communication channel at the CLIENT side
*/
if (type == SOCKET_CLIENT) {
/* Connect the socket to the remote server's address */
if (connect (sfd, sp->ai_addr, sp->ai_addrlen) != -1) {
break; /* Connection succeed */
}
}
/*
* Initiate a communication channel at the SERVER side
*/
else {
if (type == SOCKET_SERVER) {
/* Set socket options */
if (_socket_set_option (sfd) != RETURNok) {
continue;
}
/* Bind the socket to the local server's address */
if (bind (sfd, sp->ai_addr, sp->ai_addrlen) != -1) {
break; /* Bind succeed */
}
}
}
close (sfd);
}
/* Free the memory that was dynamically allocated for the linked list */
freeaddrinfo (socket_addr);
if (sp == NULL) {
/* Connect or bind failed */
return NULL;
}
/* The connection endpoint has been successfully setup */
socket_id_t * sid = (socket_id_t *) malloc (sizeof(struct socket_id_s));
if (sid != NULL) {
sid->type = type;
sid->port = atoi (port);
sid->fd = sfd;
}
return sid;
}
/****************************************************************************
** **
** Name: socket_close() **
** **
** Description: Cleanup the specified communication endpoint: Close the **
** socket file descriptor and frees all the memory space **
** allocated to handle the communication channel towards the **
** remote peer **
** **
** Inputs: None **
** Others: None **
** **
** Outputs: id: The identifier of the connection endpoint **
** Return: None **
** Others: None **
** **
***************************************************************************/
void socket_close(void* id)
{
if (id) {
close (((socket_id_t*) id)->fd);
free (id);
}
}
/****************************************************************************
** **
** Name: socket_recv() **
** **
** Description: Receives data from a given communication endpoint to a **
** receive buffer of specified length **
** **
** Inputs: id: The identifier of the connection endpoint **
** length: Length of the receive buffer **
** Others: None **
** **
** Outputs: id: The identifier of the connection endpoint **
** buffer: The receive buffer **
** Return: The number of bytes received when success; **
** RETURNerror otherwise. **
** Others: None **
** **
***************************************************************************/
ssize_t socket_recv(void* id, char* buffer, size_t length)
{
socket_id_t* sid = (socket_id_t*) (id);
ssize_t rbytes = -1;
if (sid->type == SOCKET_CLIENT) {
/* Receive data from the connected socket */
rbytes = recv (sid->fd, buffer, length, 0);
} else if (sid->type == SOCKET_SERVER) {
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
/* Receive data from the socket and retreive the remote host address */
rbytes = recvfrom (sid->fd, buffer, length, 0, (struct sockaddr *) &addr, &addrlen);
sid->addr = addr;
}
if (errno == EINTR) {
/* A signal was caught */
return 0;
} else if (rbytes < 0) {
/* Receive failed */
return RETURNerror;
}
return rbytes;
}
/****************************************************************************
** **
** Name: socket_send() **
** **
** Description: Sends data to a given communication endpoint from a send **
** buffer of specified length **
** **
** Inputs: id: The identifier of the connection endpoint **
** buffer: The send buffer **
** length: Length of the send buffer **
** Others: None **
** **
** Outputs: None **
** Return: The number of bytes sent when success; **
** RETURNerror otherwise. **
** Others: None **
** **
***************************************************************************/
ssize_t socket_send(const void* id, const char* buffer, size_t length)
{
const socket_id_t* sid = (socket_id_t*) (id);
ssize_t sbytes = -1;
if (sid->type == SOCKET_CLIENT) {
/* Send data to the connected socket */
sbytes = send (sid->fd, buffer, length, 0);
} else if (sid->type == SOCKET_SERVER) {
/* Send data to the socket using the remote host address */
sbytes = sendto (sid->fd, buffer, length, 0, (struct sockaddr *) &sid->addr, (socklen_t) sizeof(sid->addr));
}
if (errno == EINTR) {
/* A signal was caught */
return 0;
} else if (sbytes != length) {
/* Send failed */
return RETURNerror;
}
return sbytes;
}
/****************************************************************************
** **
** Name: socket_get_fd() **
** **
** Description: Get the value of the socket file descriptor created for **
** the given connection endpoint **
** **
** Inputs: id: The identifier of the connection endpoint **
** Others: None **
** **
** Outputs: None **
** Return: The file descriptor of the socket created **
** for this connection endpoint **
** Others: None **
** **
***************************************************************************/
int socket_get_fd(const void* id)
{
if (id) {
return ((socket_id_t*) id)->fd;
}
return RETURNerror;
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/****************************************************************************
** **
** Name: _socket_set_option() **
** **
** Description: Set socket option at the sockets API level (SOL_SOCKET) **
** **
** Inputs: sfd: Socket file descriptor **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _socket_set_option(int sfd)
{
int optval;
/* SO_REUSEADDR socket option:
* ---------------------------
* Allows the server to bind a socket to this port, unless
* there is an active listening socket already bound to the
* port. This is useful when recovering from a crash and the
* socket was not properly closed. The server can be restarted
* and it will simply open another socket on the same port and
* continue listening.
*/
optval = TRUE;
if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
return RETURNerror;
}
/* IPV6_V6ONLY socket option
* -------------------------
* When option is set to TRUE, the socket is restricted to sending and
* receiving IPv6 packets only.
* When option is set to FALSE, the socket can be used to send and receive
* packets to and from an IPv6 address or an IPv4-mapped IPv6 address.
*/
optval = FALSE;
if (setsockopt (sfd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) < 0) {
return RETURNerror;
}
return RETURNok;
}
+81
View File
@@ -0,0 +1,81 @@
/*
* 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 socket.h
Version 0.1
Date 2012/02/28
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Implements TCP socket handlers
*****************************************************************************/
#ifndef __SOCKET_H__
#define __SOCKET_H__
#include <sys/types.h>
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/* Type of the connection endpoint */
#define SOCKET_CLIENT 1
#define SOCKET_SERVER 2
/* Hidden structure that handles the connection endpoint data */
typedef struct socket_id_s socket_id_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
void* socket_udp_open(int type, const char* host, const char* port);
int socket_get_fd(const void* id);
ssize_t socket_recv(void* id, char* buffer, size_t length);
ssize_t socket_send(const void* id, const char* buffer, size_t length);
void socket_close(void* id);
#endif /* __SOCKET_H__*/
+353
View File
@@ -0,0 +1,353 @@
/*
* 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 stty.c
Version 0.1
Date 2012/11/29
Product NAS stack
Subsystem Utilities
Author Frederic Maurel
Description Terminal I/O device control setup
*****************************************************************************/
#include "commonDef.h"
#include <termios.h> // tcgetattr, tcsetattr
#include <unistd.h>
#include <string.h> // strdup, strtok, strcmp
#include <stdlib.h> // free
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/* Terminal I/O setting flags */
#define CFLG 0 /* control modes */
#define IFLG 1 /* input modes */
#define OFLG 2 /* output modes */
#define LFLG 3 /* local modes */
#define RFLG 4 /* control chars */
#define BFLG 5 /* baud speed modes */
/* Terminal I/O setting parameters */
typedef struct sttyset_s {
char *name;
int which;
int mask;
int value;
} sttyset_t;
/* Table of terminal I/O parameters */
static sttyset_t stty_params[] = {
{ "0", BFLG, 0, B0 },
{ "50", BFLG, 0, B50 },
{ "75", BFLG, 0, B75 },
{ "110", BFLG, 0, B110 },
{ "134", BFLG, 0, B134 },
{ "150", BFLG, 0, B150 },
{ "200", BFLG, 0, B200 },
{ "300", BFLG, 0, B300 },
{ "600", BFLG, 0, B600 },
{ "1200", BFLG, 0, B1200 },
{ "1800", BFLG, 0, B1800 },
{ "2400", BFLG, 0, B2400 },
{ "4800", BFLG, 0, B4800 },
{ "9600", BFLG, 0, B9600 },
{ "19200", BFLG, 0, B19200 },
{ "38400", BFLG, 0, B38400 },
#ifdef B57600
{ "57600", BFLG, 0, B57600 },
#endif
#ifdef B115200
{ "115200", BFLG, 0, B115200 },
#endif
#ifdef B230400
{ "230400", BFLG, 0, B230400 },
#endif
{ "cs7", CFLG, CSIZE, CS7 },
{ "cs8", CFLG, CSIZE, CS8 },
{ "cstopb", CFLG, CSTOPB, CSTOPB },
{ "cread", CFLG, CREAD, CREAD },
{ "parenb", CFLG, PARENB, PARENB },
{ "parodd", CFLG, PARODD, PARODD },
{ "hubcl", CFLG, HUPCL, HUPCL },
{ "clocal", CFLG, CLOCAL, CLOCAL },
#ifdef CRTSCTS
{ "crtscts",CFLG, CRTSCTS, CRTSCTS },
#endif
#ifdef ORTSFL
{ "ortsfl", CFLG, ORTSFL, ORTSFL },
#endif
#ifdef CTSFLOW
{ "ctsflow",CFLG, CTSFLOW, CTSFLOW },
#endif
#ifdef RTSFLOW
{ "rtsflow",CFLG, RTSFLOW, RTSFLOW },
#endif
{ "ignbrk", IFLG, IGNBRK, IGNBRK },
{ "brkint", IFLG, BRKINT, BRKINT },
{ "ignpar", IFLG, IGNPAR, IGNPAR },
{ "parmrk", IFLG, PARMRK, PARMRK },
{ "inpck", IFLG, INPCK, INPCK },
{ "istrip", IFLG, ISTRIP, ISTRIP },
{ "inlcr", IFLG, INLCR, INLCR },
{ "igncr", IFLG, IGNCR, IGNCR },
{ "icrnl", IFLG, ICRNL, ICRNL },
#ifdef IUCLC // Missing on OSX, FreeBSD
{ "iuclc", IFLG, IUCLC, IUCLC },
#endif
{ "ixon", IFLG, IXON, IXON },
{ "ixany", IFLG, IXANY, IXANY },
{ "ixoff", IFLG, IXOFF, IXOFF },
#ifdef IMAXBEL
{ "imaxbel",IFLG, IMAXBEL, IMAXBEL },
#endif
{ "opost", OFLG, OPOST, OPOST },
#ifdef ILCUC // Missing on OSX, FreeBSD
{ "olcuc", OFLG, OLCUC, OLCUC },
#endif
{ "onlcr", OFLG, ONLCR, ONLCR },
{ "ocrnl", OFLG, OCRNL, OCRNL },
{ "onocr", OFLG, ONOCR, ONOCR },
{ "onlret", OFLG, ONLRET, ONLRET },
{ "ofil", OFLG, OFILL, OFILL },
{ "ofdel", OFLG, OFDEL, OFDEL },
{ "nl0", OFLG, NLDLY, NL0 },
{ "nl1", OFLG, NLDLY, NL1 },
{ "cr0", OFLG, CRDLY, CR0 },
{ "cr1", OFLG, CRDLY, CR1 },
{ "cr2", OFLG, CRDLY, CR2 },
{ "cr3", OFLG, CRDLY, CR3 },
{ "tab0", OFLG, TABDLY, TAB0 },
{ "tab1", OFLG, TABDLY, TAB1 },
{ "tab2", OFLG, TABDLY, TAB2 },
{ "tab3", OFLG, TABDLY, TAB3 },
{ "bs0", OFLG, BSDLY, BS0 },
{ "bs1", OFLG, BSDLY, BS1 },
{ "vt0", OFLG, VTDLY, VT0 },
{ "vt1", OFLG, VTDLY, VT1 },
{ "ff0", OFLG, FFDLY, FF0 },
{ "ff1", OFLG, FFDLY, FF1 },
{ "isig", LFLG, ISIG, ISIG },
{ "icanon", LFLG, ICANON, ICANON },
#ifdef XCASE // Missing on OSX, FreeBSD
{ "xcase", LFLG, XCASE, XCASE },
#endif
{ "echo", LFLG, ECHO, ECHO },
{ "echoe", LFLG, ECHOE, ECHOE },
{ "echok", LFLG, ECHOK, ECHOK },
{ "echonl", LFLG, ECHONL, ECHONL },
{ "noflsh", LFLG, NOFLSH, NOFLSH },
{ "tostop", LFLG, TOSTOP, TOSTOP },
#ifdef ECHOCTL
{ "echoctl",LFLG, ECHOCTL, ECHOCTL },
#endif
#ifdef ECHOPRT
{ "echoprt",LFLG, ECHOPRT, ECHOPRT },
#endif
#ifdef ECHOKE
{ "echoke", LFLG, ECHOKE, ECHOKE },
#endif
#ifdef FLUSHO
{ "flusho", LFLG, FLUSHO, FLUSHO },
#endif
#ifdef PENDIN
{ "pendin", LFLG, PENDIN, PENDIN },
#endif
{ "iexten", LFLG, IEXTEN, IEXTEN },
#ifdef TOSTOP
{ "tostop", LFLG, TOSTOP, TOSTOP },
#endif
{ "raw", RFLG, 0, 0 },
{ NULL, 0, 0, 0 }
};
static int _stty_set_this(struct termios *term, const sttyset_t *p, int turnon);
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: stty_set() **
** **
** Description: Set the parameters associated with the terminal referred **
** by the given descriptor **
** **
** Inputs: p: The TTY parameters **
** turnon: Indicate whether the parameter should be **
** turned on (TRUE) or turned off (FALSE) **
** Others: None **
** **
** Outputs: term: The termios structure to fill **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int stty_set(int fd, const char *params)
{
int rc = RETURNok;
register char *p;
register char *s;
struct termios term;
register int i;
int mode;
/* Get current tty attributes */
if ( tcgetattr(fd, &term) < 0 ) {
return RETURNerror;
}
s = strdup(params);
p = strtok(s," \t\n");
while (p && (rc != RETURNerror)) {
mode = 1;
if ( *p == '-' ) {
mode = 0;
p++;
}
for ( i=0; stty_params[i].name; i++ ) {
if ( !strcmp(p, stty_params[i].name) ) {
rc = _stty_set_this(&term, &stty_params[i], mode);
break;
}
}
p = strtok(NULL," \t\n");
}
free(s);
/* Apply new tty settings immediatly */
if (rc != RETURNerror) {
if ( tcsetattr(fd, TCSANOW, &term) < 0 ) {
rc = RETURNerror;
}
}
return (rc);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/****************************************************************************
** **
** Name: _stty_set_this() **
** **
** Description: Fills the termios structure with the given TTY parameters **
** **
** Inputs: p: The TTY parameters **
** turnon: Indicate whether the parameter should be **
** turned on (TRUE) or turned off (FALSE) **
** Others: None **
** **
** Outputs: term: The termios structure to fill **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _stty_set_this(struct termios *term, const sttyset_t *p, int turnon)
{
int rc = RETURNok;
switch ( p->which ) {
case CFLG:
term->c_cflag &= ~(p->mask);
if ( turnon )
term->c_cflag |= p->value;
break;
case IFLG:
term->c_iflag &= ~(p->mask);
if ( turnon )
term->c_iflag |= p->value;
break;
case OFLG:
term->c_oflag &= ~(p->mask);
if ( turnon )
term->c_oflag |= p->value;
break;
case LFLG:
term->c_lflag &= ~(p->mask);
if ( turnon )
term->c_lflag |= p->value;
break;
case RFLG:
term->c_iflag = 0;
term->c_oflag = 0;
term->c_lflag = 0;
term->c_cc[VMIN] = 1;
term->c_cc[VTIME] = 0;
break;
case BFLG:
if (cfsetispeed(term, p->value) < 0) {
rc = RETURNerror;
} else if (cfsetospeed(term, p->value) < 0) {
rc = RETURNerror;
}
break;
default:
rc = RETURNerror;
}
return (rc);
}
+36
View File
@@ -0,0 +1,36 @@
ifndef PROJDIR
PROJDIR = $(PWD)/../../..
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
LIBS = -lutil
INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR)
LIBSUTIL = $(LIBDIR)/$(LIBUTIL).a $(LIBDIR)/$(LIBUTIL).so
TIMER_OBJ = timer.o
TIMER_TARGET = timer
TARGETS = $(TIMER_TARGET)
all: $(TARGETS)
%.o: %.c Makefile
$(CC) $(CFLAGS) -c $< -o $@
$(TIMER_TARGET): $(TIMER_OBJ) $(LIBSUTIL)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
$(RM) $(OBJS) $(TARGETS) *.bak *~
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
timer.o: $(UTILDIR)/timer.h $(INCDIR)/commonDef.h
+248
View File
@@ -0,0 +1,248 @@
/*
* 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 timer.c
Version 0.1
Date 2012/11/27
Product Test
Subsystem Timer utility main test
Author Frederic Maurel
Description Tests the timer utility functions
*****************************************************************************/
#include "nas_timer.h"
#include "commonDef.h"
#include <pthread.h>
#include <stdio.h> // printf
#include <stdlib.h> // exit
#include <time.h> // clock_gettime
#include <poll.h> // poll
/****************************************************************************/
/**************** 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 TIMER_1S 1 /* 1 second */
#define TIMER_2S 2 /* 2 seconds */
#define TIMER_3S 3 /* 3 seconds */
#define TIMER_4S 4 /* 4 seconds */
typedef struct {
unsigned int id;
unsigned int sec;
struct timespec start;
} _timer_t;
static void* _timer_callback(void* args);
static void* _timer_callback_joinable(void* args);
static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
static unsigned int _nb_timers = 0;
static int _start(_timer_t* timer, unsigned int sec);
static int _stop(_timer_t* timer);
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int main (int argc, const char* argv[])
{
int rc;
_timer_t timer1, timer2, timer3, timer4;
#define NB_TIMERS_MAX 10
_timer_t timer[NB_TIMERS_MAX];
/* Initialize timer utility */
rc = timer_init();
if (rc == RETURNerror) {
printf("ERROR: timer_init() failed\n");
exit (EXIT_FAILURE);
}
/* Start NB_TIMERS_MAX timers to expire at time interval of 1s */
for (int i=0; i < NB_TIMERS_MAX; i++) {
if (_start(&timer[i], i) != RETURNok) {
printf("ERROR: timer_start(i=%u) failed\n", i);
}
}
/* Start timer 1 to expire in 1s */
if (_start(&timer1, TIMER_1S) != RETURNok) {
printf("ERROR: timer_start() failed\n");
}
/* Start timer 2 to expire in 3s */
if (_start(&timer2, TIMER_3S) != RETURNok) {
printf("ERROR: timer_start() failed\n");
}
/* Start timer 3 to expire in 2s */
if (_start(&timer3, TIMER_2S) != RETURNok) {
printf("ERROR: timer_start() failed\n");
}
/* Stop timer 1 */
if (_stop(&timer1) != RETURNok) {
printf("ERROR: timer_stop(id=%u) failed\n", timer3.id);
}
/* Wait for the first timer to expire */
poll(0, 0, -1);
/* Start timer 4 to expire in 4s */
if (_start(&timer4, TIMER_4S) != RETURNok) {
printf("ERROR: timer_start() failed\n");
}
/* Wait for all timers to expire */
while (_nb_timers > 0) {
poll(0, 0, 10000);
}
exit(EXIT_SUCCESS);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
static int _timespec_sub(struct timespec* a, struct timespec* b, struct timespec* result)
{
if (a->tv_sec < b->tv_sec) return -1;
else if (a->tv_nsec < b->tv_nsec) return -1;
result->tv_sec = a->tv_sec - b->tv_sec;
result->tv_nsec = a->tv_nsec - b->tv_nsec;
if (result->tv_nsec < 0) {
result->tv_sec--;
result->tv_nsec += 1000000000;
}
return 0;
}
static void* _timer_callback(void* args)
{
_timer_t* timer = (_timer_t*) args;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
if (_timespec_sub(&ts, &timer->start, &ts) < 0) {
printf("ERROR:_timespec_sub() failed: %ld.%.9ld > %ld.%.9ld\n",
timer->start.tv_sec, timer->start.tv_nsec,
ts.tv_sec, ts.tv_nsec);
} else {
printf("%s\t: Timer %u expired after %ld.%.9ld seconds (%u s)\n",
__FUNCTION__, timer->id, ts.tv_sec, ts.tv_nsec, timer->sec);
timer->id = timer_stop(timer->id);
pthread_mutex_lock(&_mutex);
_nb_timers -= 1;
pthread_mutex_unlock(&_mutex);
}
return NULL;
}
static void* _timer_callback_joinable(void* args)
{
_timer_t* timer = (_timer_t*) args;
struct timespec ts;
int* rc = (int*)malloc(sizeof(int));
clock_gettime(CLOCK_MONOTONIC, &ts);
if (_timespec_sub(&ts, &timer->start, &ts) < 0) {
printf("ERROR:_timespec_sub() failed: %ld.%.9ld > %ld.%.9ld\n",
timer->start.tv_sec, timer->start.tv_nsec,
ts.tv_sec, ts.tv_nsec);
*rc = RETURNerror;
} else {
printf("%s\t: Timer %u expired after %ld.%.9ld seconds (%u s)\n",
__FUNCTION__, timer->id, ts.tv_sec, ts.tv_nsec, timer->sec);
timer->id = timer_stop(timer->id);
pthread_mutex_lock(&_mutex);
_nb_timers -= 1;
pthread_mutex_unlock(&_mutex);
*rc = timer->id;
}
return rc;
}
static int _start(_timer_t* timer, unsigned int sec)
{
int rc = RETURNerror;
timer->sec = sec;
clock_gettime(CLOCK_MONOTONIC, &timer->start);
timer->id = timer_start(timer->sec, _timer_callback_joinable,
(void*) timer);
if (timer->id != TIMER_INACTIVE_ID) {
printf("Timer id=%u scheduled to expire in %u seconds\n",
timer->id, timer->sec);
_nb_timers += 1;
rc = RETURNok;
}
return (rc);
}
static int _stop(_timer_t* timer)
{
int rc = RETURNerror;
printf("Stop timer id=%u\n", timer->id);
timer->id = timer_stop(timer->id);
if (timer->id == TIMER_INACTIVE_ID) {
_nb_timers -= 1;
rc = RETURNok;
}
return (rc);
}
@@ -0,0 +1,101 @@
Attach.c[168] DEBUG Start timer T3410 (id=-1, time=15)
_timer_db_insert_entry: DEBUG - Restart system timer for id=0, time=15.000000
timer_start: DEBUG - Timer id=0 started
Attach.c[171] DEBUG Timer T3410 (id=0) started
Attach.c[173] DEBUG Stop T3402 (id=-1)
timer_stop: DEBUG - Stop timer id=-1
Attach.c[175] DEBUG Timer T3402 (id=-1) stopped
Attach.c[176] DEBUG Stop T3411 (id=-1)
timer_stop: DEBUG - Stop timer id=-1
Attach.c[178] DEBUG Timer T3411 (id=-1) stopped
--------------------------------------------------------------------------------
Attach.c[219] WARNING T3410 timer expired, attach counter = 0
Attach.c[226] DEBUG Start timer T3411 (id=-1, time=10)
timer_start: DEBUG - Timer id=1 started
Attach.c[229] DEBUG Timer T3411 (id=1, time=10) started
_timer_db_remove_entry: DEBUG - Remove entry id=0
_timer_db_remove: DEBUG - Remove timer id=0
_timer_db_remove_entry: DEBUG - Restart system timer for id=1, time=9.999921
--------------------------------------------------------------------------------
Attach.c[288] WARNING T3411 timer expired
Attach.c[168] DEBUG Start timer T3410 (id=0, time=15)
timer_start: DEBUG - Timer id=2 started
Attach.c[171] DEBUG Timer T3410 (id=2) started
Attach.c[173] DEBUG Stop T3402 (id=-1)
timer_stop: DEBUG - Stop timer id=-1
Attach.c[175] DEBUG Timer T3402 (id=-1) stopped
Attach.c[176] DEBUG Stop T3411 (id=1)
timer_stop: DEBUG - Stop timer id=1
_timer_db_remove_entry: DEBUG - Remove entry id=1
_timer_db_remove: DEBUG - Remove timer id=1
_timer_db_remove_entry: DEBUG - Restart system timer for id=2, time=14.988820
Attach.c[178] DEBUG Timer T3411 (id=1) stopped
_timer_db_remove_entry: DEBUG - Remove entry id=2
_timer_db_remove: DEBUG - Remove timer id=2
_timer_db_remove: DEBUG - Stop system timer
--------------------------------------------------------------------------------
Attach.c[168] DEBUG Start timer T3410 (id=-1, time=15)
_timer_db_insert_entry: DEBUG - Restart system timer for id=0, time=15.000000
timer_start: DEBUG - Timer id=0 started
Attach.c[171] DEBUG Timer T3410 (id=0) started
Attach.c[173] DEBUG Stop T3402 (id=-1)
timer_stop: DEBUG - Stop timer id=-1
Attach.c[175] DEBUG Timer T3402 (id=-1) stopped
Attach.c[176] DEBUG Stop T3411 (id=-1)
timer_stop: DEBUG - Stop timer id=-1
Attach.c[178] DEBUG Timer T3411 (id=-1) stopped
--------------------------------------------------------------------------------
Attach.c[219] WARNING T3410 timer expired, attach counter = 0
Attach.c[226] DEBUG Start timer T3411 (id=-1, time=10)
timer_start: DEBUG - Timer id=1 started
Attach.c[229] DEBUG Timer T3411 (id=1, time=10) started
timer_stop: DEBUG - Stop timer id=0
_timer_db_remove_entry: DEBUG - Remove entry id=0
_timer_db_remove: DEBUG - Remove timer id=0
_timer_db_remove_entry: DEBUG - Restart system timer for id=1, time=9.999934
--------------------------------------------------------------------------------
Attach.c[288] WARNING T3411 timer expired
Attach.c[168] DEBUG Start timer T3410 (id=0, time=15)
timer_start: DEBUG - Timer id=2 started
Attach.c[171] DEBUG Timer T3410 (id=2) started
Attach.c[173] DEBUG Stop T3402 (id=-1)
timer_stop: DEBUG - Stop timer id=-1
Attach.c[175] DEBUG Timer T3402 (id=-1) stopped
Attach.c[176] DEBUG Stop T3411 (id=1)
timer_stop: DEBUG - Stop timer id=1
timer_stop: DEBUG - Stop timer id=1
_timer_db_remove_entry: DEBUG - Remove entry id=1
_timer_db_remove: DEBUG - Remove timer id=1
_timer_db_remove_entry: DEBUG - Restart system timer for id=2, time=14.999969
Attach.c[178] DEBUG Timer T3411 (id=1) stopped
UEprocess: timer.c:519: _timer_db_remove_entry: Assertion `_timer_db.tq[id].id == id' failed.
Aborted