renamed openair-cn to openair3
git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7886 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -0,0 +1,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.
|
||||
*/
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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_) */
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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_) */
|
||||
|
||||
@@ -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 *********************/
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -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__*/
|
||||
@@ -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 *********************/
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -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__*/
|
||||
@@ -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
|
||||
|
||||
@@ -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__*/
|
||||
@@ -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, ¤t_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;
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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 *********************/
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -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__*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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__*/
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user