Commit 08458e54 authored by HFJ's avatar HFJ

add tool files

parent 5153657a
/*-------------------------------------------------------------------
* Example algorithms f1, f1*, f2, f3, f4, f5, f5*
*-------------------------------------------------------------------
*
* A sample implementation of the example 3GPP authentication and
* key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. This is
* a byte-oriented implementation of the functions, and of the block
* cipher kernel function Rijndael.
*
* This has been coded for clarity, not necessarily for efficiency.
*
* The functions f2, f3, f4 and f5 share the same inputs and have
* been coded together as a single function. f1, f1* and f5* are
* all coded separately.
*
*-----------------------------------------------------------------*/
/************************ 3gpp 35.206 *****************************/
#include "authentication_algorithms_with_5gaka.hpp"
typedef unsigned char u8;
/*--------- Operator Variant Algorithm Configuration Field --------*/
/*------- Insert your value of OP here -------*/
u8 OP[16] = {0x63, 0xbf, 0xa5, 0x0e, 0xe6, 0x52, 0x33, 0x65,
0xff, 0x14, 0xc1, 0xf4, 0x5f, 0x88, 0x73, 0x7d};
/*------- Insert your value of OP here -------*/
//u8 op_c[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
uint8_t op_c[16] = {0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf};
/*--------------------------- prototypes --------------------------*/
void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_a[8] );
void f2345 ( u8 k[16], u8 rand[16],
u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6] );
void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_s[8] );
void f5star( u8 k[16], u8 rand[16],
u8 ak[6] );
/*-------------------------------------------------------------------
* Algorithm f1
*-------------------------------------------------------------------
*
* Computes network authentication code MAC-A from key K, random
* challenge RAND, sequence number SQN and authentication management
* field AMF.
*
*-----------------------------------------------------------------*/
void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_a[8] )
{
printf("opc: ");
for(int i=0; i< 16; i++)
printf("0x%x", op_c[i]);
printf("\n");
//u8 op_c[16];
u8 temp[16];
u8 in1[16];
u8 out1[16];
u8 rijndaelInput[16];
u8 i;
Authentication_5gaka::RijndaelKeySchedule( k );
//ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, temp );
for (i=0; i<6; i++)
{
in1[i] = sqn[i];
in1[i+8] = sqn[i];
}
for (i=0; i<2; i++)
{
in1[i+6] = amf[i];
in1[i+14] = amf[i];
}
/* XOR op_c and in1, rotate by r1=64, and XOR *
* on the constant c1 (which is all zeroes) */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
/* XOR on the value temp computed before */
for (i=0; i<16; i++)
rijndaelInput[i] ^= temp[i];
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, out1 );
for (i=0; i<16; i++)
out1[i] ^= op_c[i];
for (i=0; i<8; i++)
mac_a[i] = out1[i];
return;
} /* end of function f1 */
/*-------------------------------------------------------------------
* Algorithms f2-f5
*-------------------------------------------------------------------
*
* Takes key K and random challenge RAND, and returns response RES,
* confidentiality key CK, integrity key IK and anonymity key AK.
*
*-----------------------------------------------------------------*/
void f2345 ( u8 k[16], u8 rand[16],
u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6] )
{
//u8 op_c[16];
u8 temp[16];
u8 out[16];
u8 rijndaelInput[16];
u8 i;
Authentication_5gaka::RijndaelKeySchedule( k );
//ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, temp );
/* To obtain output block OUT2: XOR OPc and TEMP, *
* rotate by r2=0, and XOR on the constant c2 (which *
* is all zeroes except that the last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[i] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 1;
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<8; i++)
res[i] = out[i+8];
for (i=0; i<6; i++)
ak[i] = out[i];
/* To obtain output block OUT3: XOR OPc and TEMP, *
* rotate by r3=32, and XOR on the constant c3 (which *
* is all zeroes except that the next to last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+12) % 16] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 2;
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<16; i++)
ck[i] = out[i];
/* To obtain output block OUT4: XOR OPc and TEMP, *
* rotate by r4=64, and XOR on the constant c4 (which *
* is all zeroes except that the 2nd from last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 4;
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<16; i++)
ik[i] = out[i];
return;
} /* end of function f2345 */
/*-------------------------------------------------------------------
* Algorithm f1*
*-------------------------------------------------------------------
*
* Computes resynch authentication code MAC-S from key K, random
* challenge RAND, sequence number SQN and authentication management
* field AMF.
*
*-----------------------------------------------------------------*/
void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_s[8] )
{
//u8 op_c[16];
u8 temp[16];
u8 in1[16];
u8 out1[16];
u8 rijndaelInput[16];
u8 i;
Authentication_5gaka::RijndaelKeySchedule( k );
//ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, temp );
for (i=0; i<6; i++)
{
in1[i] = sqn[i];
in1[i+8] = sqn[i];
}
for (i=0; i<2; i++)
{
in1[i+6] = amf[i];
in1[i+14] = amf[i];
}
/* XOR op_c and in1, rotate by r1=64, and XOR *
* on the constant c1 (which is all zeroes) */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
/* XOR on the value temp computed before */
for (i=0; i<16; i++)
rijndaelInput[i] ^= temp[i];
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, out1 );
for (i=0; i<16; i++)
out1[i] ^= op_c[i];
for (i=0; i<8; i++)
mac_s[i] = out1[i+8];
return;
} /* end of function f1star */
/*-------------------------------------------------------------------
* Algorithm f5*
*-------------------------------------------------------------------
*
* Takes key K and random challenge RAND, and returns resynch
* anonymity key AK.
*
*-----------------------------------------------------------------*/
void f5star( u8 k[16], u8 rand[16],
u8 ak[6] )
{
//u8 op_c[16];
u8 temp[16];
u8 out[16];
u8 rijndaelInput[16];
u8 i;
Authentication_5gaka::RijndaelKeySchedule( k );
//ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, temp );
/* To obtain output block OUT5: XOR OPc and TEMP, *
* rotate by r5=96, and XOR on the constant c5 (which *
* is all zeroes except that the 3rd from last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+4) % 16] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 8;
Authentication_5gaka::RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<6; i++)
ak[i] = out[i];
return;
} /* end of function f5star */
This diff is collapsed.
#ifndef _5GAKA_H_
#define _5GAKA_H_
//extern "C"{
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <gmp.h>
#include <pthread.h>
#include <string>
//}
#define SQN_LENGTH_BITS (48)
#define SQN_LENGTH_OCTEST (SQN_LENGTH_BITS/8)
#define IK_LENGTH_BITS (128)
#define IK_LENGTH_OCTETS (IK_LENGTH_BITS/8)
#define RAND_LENGTH_OCTETS (16)
#define RAND_LENGTH_BITS (RAND_LENGTH_OCTETS*8)
#define XRES_LENGTH_OCTETS (8)
#define AUTN_LENGTH_OCTETS (16)
#define KASME_LENGTH_OCTETS (32)
#define MAC_S_LENGTH (8)
typedef mpz_t random_t;
typedef mpz_t sqn_t;
typedef struct {
uint8_t rand[16];
uint8_t rand_new;
uint8_t xres[8];
uint8_t autn[16];
uint8_t kasme[32];
} auc_vector_t;
typedef struct{
uint8_t avType;
uint8_t rand[16];
uint8_t xres[8];
uint8_t xresStar[16];
uint8_t autn[16];
uint8_t kausf[32];
}_5G_HE_AV_t;//clause 6.3.6.2.5, ts33.501
typedef struct{
uint8_t avType;
uint8_t rand[16];
uint8_t hxres[16];
uint8_t hxresStar[16];
uint8_t autn[16];
uint8_t kseaf[32];
}_5G_AV_t;
typedef struct random_state_s {
pthread_mutex_t lock;
gmp_randstate_t state;
} random_state_t;
#define _NEA0_ 0b0000
#define _128_NEA1_ 0b0001
#define _128_NEA2_ 0b0010
#define _128_NEA3_ 0b0011
#define _NIA0_ 0b0000
#define _128_NIA1_ 0b0001
#define _128_NIA2_ 0b0010
#define _128_NIA3_ 0b0011
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
class Authentication_5gaka{
public:
/****** sequence number functions ********/
//struct sqn_ue_s *sqn_exists(uint64_t imsi);
//void sqn_insert(struct sqn_ue_s *item);
//void sqn_init(struct sqn_ue_s *item);
//struct sqn_ue_s *sqn_new(uint64_t imsi);
//void sqn_list_init(void);
//void sqn_get(uint64_t imsi, uint8_t sqn[6]);
public:
/****** random number functions *********/
//void random_init(void);
//void generate_random(uint8_t *random, ssize_t length);
public:
/****** internal algorithms f1 f2 f3 f4 f5 ********/
static void f1 ( const uint8_t opc[16],const uint8_t k[16], const uint8_t _rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_a[8] );
static void f1star( const uint8_t kP[16],const uint8_t k[16], const uint8_t rand[16], const uint8_t sqn[6], const uint8_t amf[2], uint8_t mac_s[8] );
static void f2345 ( const uint8_t opc[16],const uint8_t k[16], const uint8_t _rand[16], uint8_t res[8], uint8_t ck[16], uint8_t ik[16], uint8_t ak[6] );
static void f5star( const uint8_t kP[16],const uint8_t k[16], const uint8_t rand[16], uint8_t ak[6] );
public:
/****** key derive ***********/
static void kdf(uint8_t *key, uint16_t key_len, uint8_t *s, uint16_t s_len, uint8_t *out, uint16_t out_len);
static void derive_kasme(uint8_t ck[16], uint8_t ik[16], uint8_t plmn[3], uint8_t sqn[6], uint8_t ak[6], uint8_t kasme[32]);
static void derive_kausf(uint8_t ck[16], uint8_t ik[16], std::string serving_network, uint8_t sqn[6], uint8_t ak[6], uint8_t kausf[32]);
static void derive_kseaf(std::string serving_network, uint8_t kausf[32], uint8_t kseaf[32]);
static void derive_kamf(std::string imsi, uint8_t *kseaf, uint8_t *kamf, uint16_t abba);
static void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t * knas);
static void derive_kgnb(uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t * kgnb);
static uint8_t *sqn_ms_derive(const uint8_t opc[16], uint8_t *key, uint8_t *auts, uint8_t *rand);
public:
/****** general functions ********/
static void ComputeOPc( const uint8_t kP[16], const uint8_t opP[16], uint8_t opcP[16] );
static void generate_autn(const uint8_t sqn[6], const uint8_t ak[6], const uint8_t amf[2], const uint8_t mac_a[8], uint8_t autn[16]);
static int generate_vector(const uint8_t opc[16], uint64_t imsi, uint8_t key[16], uint8_t plmn[3], uint8_t sqn[6], auc_vector_t *vector);
public:
/****** Rijndael ********/
static void RijndaelKeySchedule(const uint8_t key[16]);
static void RijndaelEncrypt(const uint8_t in[16], uint8_t out[16]);
private:
auc_vector_t auc_vector;
};
#endif
#include "authentication_algorithms_with_5gaka.hpp"
typedef uint8_t u8;
typedef uint32_t u32;
u8 roundKeys[11][4][4];
/*--------------------- Rijndael S box table ----------------------*/
u8 S[256] = {
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22,
};
/*------- This array does the multiplication by x in GF(2^8) ------*/
u8 Xtime[256] = {
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158,
160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190,
192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222,
224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254,
27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5,
59, 57, 63, 61, 51, 49, 55, 53, 43, 41, 47, 45, 35, 33, 39, 37,
91, 89, 95, 93, 83, 81, 87, 85, 75, 73, 79, 77, 67, 65, 71, 69,
123, 121, 127, 125, 115, 113, 119, 117, 107, 105, 111, 109, 99, 97, 103, 101,
155, 153, 159, 157, 147, 145, 151, 149, 139, 137, 143, 141, 131, 129, 135, 133,
187, 185, 191, 189, 179, 177, 183, 181, 171, 169, 175, 173, 163, 161, 167, 165,
219, 217, 223, 221, 211, 209, 215, 213, 203, 201, 207, 205, 195, 193, 199, 197,
251, 249, 255, 253, 243, 241, 247, 245, 235, 233, 239, 237, 227, 225, 231, 229
};
void Authentication_5gaka::RijndaelKeySchedule(const uint8_t key[16]){
u8 roundConst;
/******* first round key equals key ********/
for(int i=0; i<16; i++){
roundKeys[0][i & 0x03][i >> 2] = key[i];
}
roundConst = 1;
for(int i=1; i<11; i++){
roundKeys[i][0][0] = S[roundKeys[i - 1][1][3]]
^ roundKeys[i - 1][0][0] ^ roundConst;
roundKeys[i][1][0] = S[roundKeys[i - 1][2][3]]
^ roundKeys[i - 1][1][0];
roundKeys[i][2][0] = S[roundKeys[i - 1][3][3]]
^ roundKeys[i - 1][2][0];
roundKeys[i][3][0] = S[roundKeys[i - 1][0][3]]
^ roundKeys[i - 1][3][0];
for(int j=0; j<4; j++){
roundKeys[i][j][1] = roundKeys[i - 1][j][1] ^ roundKeys[i][j][0];
roundKeys[i][j][2] = roundKeys[i - 1][j][2] ^ roundKeys[i][j][1];
roundKeys[i][j][3] = roundKeys[i - 1][j][3] ^ roundKeys[i][j][2];
}
roundConst = Xtime[roundConst];
/*
if(roundConst < 128)
roundConst = 2*roundConst;
if(roundConst >= 128)
roundConst = (2*roundConst) ^ 283;
*/
}
//#if AUTH_ALG_ON
#if 0
for(int m=0; m<11; m++){
printf("roundKeys(%d)\n0x", m);
for(int i=0; i<16; i++)
printf("%x ", roundKeys[m][i & 0x3][i >> 2]);
printf("\n");
}
#endif
return;
}
/************ internal functions ******************/
void KeyAdd(u8 state[4][4], u8 roundKeys[11][4][4], int round){
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
state[i][j] ^= roundKeys[round][i][j];
return;
}
int ByteSub(u8 state[4][4]){
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
state[i][j] = S[state[i][j]];
return 0;
}
void ShiftRow(u8 state[4][4]){
u8 temp;
/*
* left rotate row 1 by 1
*/
temp = state[1][0];
state[1][0] = state[1][1];
state[1][1] = state[1][2];
state[1][2] = state[1][3];
state[1][3] = temp;
/*
* left rotate row 2 by 2
*/
temp = state[2][0];
state[2][0] = state[2][2];
state[2][2] = temp;
temp = state[2][1];
state[2][1] = state[2][3];
state[2][3] = temp;
/*
* left rotate row 3 by 3
*/
temp = state[3][0];
state[3][0] = state[3][3];
state[3][3] = state[3][2];
state[3][2] = state[3][1];
state[3][1] = temp;
return;
}
void MixColumn (u8 state[4][4]){
u8 temp, tmp, tmp0;
for(int i=0; i<4; i++){
temp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i];
tmp0 = state[0][i];
/*
* Xtime array does multiply by x in GF2^8
*/
tmp = Xtime[state[0][i] ^ state[1][i]];
state[0][i] ^= temp ^ tmp;
tmp = Xtime[state[1][i] ^ state[2][i]];
state[1][i] ^= temp ^ tmp;
tmp = Xtime[state[2][i] ^ state[3][i]];
state[2][i] ^= temp ^ tmp;
tmp = Xtime[state[3][i] ^ tmp0];
state[3][i] ^= temp ^ tmp;
}
return;
}
/*-------------------------------------------------------------------
Rijndael encryption function. Takes 16-byte input and creates
16-byte output (using round keys already derived from 16-byte
key).
-----------------------------------------------------------------*/
void Authentication_5gaka::RijndaelEncrypt(const uint8_t input[16], uint8_t output[16]){
int i=0, r=0;
u8 state[4][4];
for(i=0; i< 16; i++)
state[i & 0x3][i >> 2] = input[i];
KeyAdd(state, roundKeys, 0);
#if AUTH_ALG_ON
printf("end of round(%d)\n0x", 0);
#endif
for(int i=0; i<16; i++)
printf("%x ", state[i & 0x3][i >> 2]);
printf("\n");
for (r = 1; r <= 9; r++) {
ByteSub (state);
ShiftRow (state);
MixColumn (state);
KeyAdd (state, roundKeys, r);
#if AUTH_ALG_ON
printf("end of round(%d)\n0x", r);
for (i = 0; i < 16; i++)
printf("%x ", state[i & 0x3][i >> 2]);
printf("\n");
#endif
}
ByteSub (state);
ShiftRow (state);
KeyAdd (state, roundKeys, r);
#if AUTH_ALG_ON
printf("end of round(%d)\n0x", r);
for(int i=0; i<16; i++)
printf("%x ", state[i & 0x3][i >> 2]);
printf("\n");
#endif
for (i = 0; i < 16; i++)
output[i] = state[i & 0x3][i >> 2];
#if AUTH_ALG_ON
printf("output_encrypt: ");
for (i = 0; i < 16; i++)
printf("%x", output[i]);
printf("\n");
#endif
return;
}
#include <cstring>
#include <fstream>
#include "sha256.hpp"
Sha256::Sha256(){}
Sha256::~Sha256(){}
const unsigned int Sha256::sha256_k[64] = //UL = uint32
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
void Sha256::transform(const unsigned char *message, unsigned int block_nb)
{
uint32 w[64];
uint32 wv[8];
uint32 t1, t2;
const unsigned char *sub_block;
int i;
int j;
for (i = 0; i < (int) block_nb; i++) {
sub_block = message + (i << 6);
for (j = 0; j < 16; j++) {
SHA2_PACK32(&sub_block[j << 2], &w[j]);
}
for (j = 16; j < 64; j++) {
w[j] = Sha256_F4(w[j - 2]) + w[j - 7] + Sha256_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++) {
wv[j] = m_h[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + Sha256_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t2 = Sha256_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
m_h[j] += wv[j];
}
}
}
void Sha256::init()
{
m_h[0] = 0x6a09e667;
m_h[1] = 0xbb67ae85;
m_h[2] = 0x3c6ef372;
m_h[3] = 0xa54ff53a;
m_h[4] = 0x510e527f;
m_h[5] = 0x9b05688c;
m_h[6] = 0x1f83d9ab;
m_h[7] = 0x5be0cd19;
m_len = 0;
m_tot_len = 0;
}
void Sha256::update(const unsigned char *message, unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = SHA224_256_BLOCK_SIZE - m_len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&m_block[m_len], message, rem_len);
if (m_len + len < SHA224_256_BLOCK_SIZE) {
m_len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA224_256_BLOCK_SIZE;
shifted_message = message + rem_len;
transform(m_block, 1);
transform(shifted_message, block_nb);
rem_len = new_len % SHA224_256_BLOCK_SIZE;
memcpy(m_block, &shifted_message[block_nb << 6], rem_len);
m_len = rem_len;
m_tot_len += (block_nb + 1) << 6;
}
void Sha256::finalResult(unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = (1 + ((SHA224_256_BLOCK_SIZE - 9)
< (m_len % SHA224_256_BLOCK_SIZE)));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 6;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
for (i = 0 ; i < 8; i++) {
SHA2_UNPACK32(m_h[i], &digest[i << 2]);
}
}
#if 0
std::string sha256(std::string input)
{
unsigned char digest[Sha256::DIGEST_SIZE];
memset(digest,0,Sha256::DIGEST_SIZE);
Sha256 ctx = Sha256();
ctx.init();
ctx.update( (unsigned char*)input.c_str(), input.length());
ctx.final(digest);
char buf[2*Sha256::DIGEST_SIZE+1];
buf[2*Sha256::DIGEST_SIZE] = 0;
for (int i = 0; i < Sha256::DIGEST_SIZE; i++)
sprintf(buf+i*2, "%02x", digest[i]);
return std::string(buf);
}
#endif
#ifndef Sha256_H
#define Sha256_H
#include <string>
class Sha256
{
protected:
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint32 sha256_k[];
static const unsigned int SHA224_256_BLOCK_SIZE = (512/8);
public:
Sha256();
~Sha256();
void init();
void update(const unsigned char *message, unsigned int len);
void finalResult(unsigned char *digest);
static const unsigned int DIGEST_SIZE = ( 256 / 8);
protected:
void transform(const unsigned char *message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2*SHA224_256_BLOCK_SIZE];
uint32 m_h[8];
};
//std::string sha256(std::string input);
#define SHA2_SHFR(x, n) (x >> n)
#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define Sha256_F1(x) (SHA2_ROTR(x, 2) ^ SHA2_ROTR(x, 13) ^ SHA2_ROTR(x, 22))
#define Sha256_F2(x) (SHA2_ROTR(x, 6) ^ SHA2_ROTR(x, 11) ^ SHA2_ROTR(x, 25))
#define Sha256_F3(x) (SHA2_ROTR(x, 7) ^ SHA2_ROTR(x, 18) ^ SHA2_SHFR(x, 3))
#define Sha256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10))
#define SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (uint8) ((x) ); \
*((str) + 2) = (uint8) ((x) >> 8); \
*((str) + 1) = (uint8) ((x) >> 16); \
*((str) + 0) = (uint8) ((x) >> 24); \
}
#define SHA2_PACK32(str, x) \
{ \
*(x) = ((uint32) *((str) + 3) ) \
| ((uint32) *((str) + 2) << 8) \
| ((uint32) *((str) + 1) << 16) \
| ((uint32) *((str) + 0) << 24); \
}
#endif
This diff is collapsed.
include_directories(${SRC_TOP_DIR}/common)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
add_library( LOG STATIC
${SRC_TOP_DIR}/common/logger.cpp
)
#ifndef _PRINT_BUFFER_H
#define _PRINT_BUFFER_H
#include "logger.hpp"
#include <string>
using namespace std;
void print_buffer(const string app, const string commit, uint8_t *buf, int len){
if(!app.compare("ausf_server"))
Logger::ausf_server().debug(commit.c_str());
for(int i=0; i<len; i++)
printf("%x ",buf[i]);
printf("\n");
}
void hexStr2Byte(const char* src, unsigned char *dest, int len){
short i;
unsigned char hBy, lBy;
for(i=0; i<len; i+=2){
hBy = toupper(src[i]);
lBy = toupper(src[i+1]);
if(hBy > 0x39)
hBy -= 0x37;
else
hBy -= 0x30;
if(lBy > 0x39)
lBy -= 0x37;
else
lBy -= 0x30;
dest[i/2] = (hBy<<4) | lBy;
}
}
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file conversions.cpp
\brief
\author Sebastien ROUX
\company Eurecom
*/
#include "conversions.hpp"
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <ctype.h>
#include <inttypes.h>
#include <arpa/inet.h>
static const char hex_to_ascii_table[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
};
static const signed char ascii_to_hex_table[0x100] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
void conv::hexa_to_ascii (
uint8_t * from,
char *to,
size_t length)
{
size_t i;
for (i = 0; i < length; i++) {
uint8_t upper = (from[i] & 0xf0) >> 4;
uint8_t lower = from[i] & 0x0f;
to[2 * i] = hex_to_ascii_table[upper];
to[2 * i + 1] = hex_to_ascii_table[lower];
}
}
int conv::ascii_to_hex (
uint8_t * dst,
const char *h)
{
const unsigned char *hex = (const unsigned char *)h;
unsigned i = 0;
for (;;) {
int high,
low;
while (*hex && isspace (*hex))
hex++;
if (!*hex)
return 1;
high = ascii_to_hex_table[*hex++];
if (high < 0)
return 0;
while (*hex && isspace (*hex))
hex++;
if (!*hex)
return 0;
low = ascii_to_hex_table[*hex++];
if (low < 0)
return 0;
dst[i++] = (high << 4) | low;
}
}
//------------------------------------------------------------------------------
std::string conv::mccToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3)
{
std::string s = {};
uint16_t mcc16 = digit1*100+digit2*10+digit3;
//s.append(std::to_string(digit1)).append(std::to_string(digit2)).append(std::to_string(digit3));
s.append(std::to_string(mcc16));
return s;
}
//------------------------------------------------------------------------------
std::string conv::mncToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3)
{
std::string s = {};
uint16_t mcc16 = 0;
if (digit3 == 0x0F) {
mcc16 = digit1*10+digit2;
} else {
mcc16 = digit1*100+digit2*10+digit3;
}
s.append(std::to_string(mcc16));
return s;
}
//------------------------------------------------------------------------------
struct in_addr conv::fromString(const std::string addr4)
{
unsigned char buf[sizeof(struct in6_addr)] = {};
int s = inet_pton(AF_INET, addr4.c_str(), buf);
struct in_addr * ia = (struct in_addr *)buf;
return *ia;
}
//------------------------------------------------------------------------------
std::string conv::toString(const struct in_addr& inaddr)
{
std::string s = {};
char str[INET6_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET, (const void *)&inaddr, str, INET6_ADDRSTRLEN) == NULL) {
s.append("Error in_addr");
} else {
s.append(str);
}
return s;
}
//------------------------------------------------------------------------------
std::string conv::toString(const struct in6_addr& in6addr)
{
std::string s = {};
char str[INET6_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET6, (const void *)&in6addr, str, INET6_ADDRSTRLEN) == nullptr) {
s.append("Error in6_addr");
} else {
s.append(str);
}
return s;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file conversions.hpp
\brief
\author Sebastien ROUX, Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_CONVERSIONS_HPP_SEEN
#define FILE_CONVERSIONS_HPP_SEEN
#include <stdint.h>
#include <string>
#include <netinet/in.h>
/* Used to format an uint32_t containing an ipv4 address */
#define IN_ADDR_FMT "%u.%u.%u.%u"
#define PRI_IN_ADDR(aDDRESS) \
(uint8_t)((aDDRESS.s_addr) & 0x000000ff), \
(uint8_t)(((aDDRESS.s_addr) & 0x0000ff00) >> 8 ), \
(uint8_t)(((aDDRESS.s_addr) & 0x00ff0000) >> 16), \
(uint8_t)(((aDDRESS.s_addr) & 0xff000000) >> 24)
#define IPV4_ADDR_DISPLAY_8(aDDRESS) \
(aDDRESS)[0], (aDDRESS)[1], (aDDRESS)[2], (aDDRESS)[3]
class conv {
public:
static void hexa_to_ascii(uint8_t *from, char *to, size_t length);
static int ascii_to_hex(uint8_t *dst, const char *h);
static struct in_addr fromString(const std::string addr4);
static std::string toString(const struct in_addr& inaddr);
static std::string toString(const struct in6_addr& in6addr);
static std::string mccToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3);
static std::string mncToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3);
};
#endif /* FILE_CONVERSIONS_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file endpoint.hpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_ENDPOINT_HPP_SEEN
#define FILE_ENDPOINT_HPP_SEEN
#include "conversions.hpp"
#include <arpa/inet.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <string.h>
class endpoint {
public :
struct sockaddr_storage addr_storage;
socklen_t addr_storage_len;
endpoint() : addr_storage(), addr_storage_len(sizeof(struct sockaddr_storage)) {};
endpoint(const endpoint& e) : addr_storage(e.addr_storage), addr_storage_len(e.addr_storage_len) {};
endpoint(const struct sockaddr_storage& addr, const socklen_t len) : addr_storage(addr), addr_storage_len(len) {};
endpoint(const struct in_addr& addr, const uint16_t port)
{
struct sockaddr_in * addr_in = (struct sockaddr_in *)&addr_storage;
addr_in->sin_family = AF_INET;
addr_in->sin_port = htons(port);
addr_in->sin_addr.s_addr = addr.s_addr;
addr_storage_len = sizeof(struct sockaddr_in);
};
endpoint(const struct in6_addr& addr6, const uint16_t port)
{
struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)&addr_storage;
addr_in6->sin6_family = AF_INET6;
addr_in6->sin6_port = htons(port);
addr_in6->sin6_flowinfo = 0;
memcpy(&addr_in6->sin6_addr, &addr6, sizeof(struct in6_addr));
addr_in6->sin6_scope_id = 0;
addr_storage_len = sizeof(struct sockaddr_in6);
};
uint16_t port() const
{
return ntohs(((struct sockaddr_in *)&addr_storage)->sin_port);
}
sa_family_t family() const
{
return addr_storage.ss_family;
}
std::string toString() const
{
std::string str;
if (addr_storage.ss_family == AF_INET) {
struct sockaddr_in * addr_in = (struct sockaddr_in *)&addr_storage;
str.append(conv::toString(addr_in->sin_addr));
str.append(":").append(std::to_string(ntohs(addr_in->sin_port)));
}
else if (addr_storage.ss_family == AF_INET6) {
struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *)&addr_storage;
str.append(conv::toString(addr_in6->sin6_addr));
str.append(":").append(std::to_string(ntohs(addr_in6->sin6_port)));
}
return str;
}
};
#endif
#include "logger.hpp"
#include "spdlog/sinks/syslog_sink.h"
#include <iostream>
#include <sstream>
#include <string>
#include <memory>
Logger *Logger::m_singleton = NULL;
void Logger::_init(const char *app, const bool log_stdout, const bool log_rot_file){
int num_sinks = 0;
spdlog::set_async_mode(2048);
#if TRACE_IS_ON
spdlog::level::level_enum llevel = spdlog::level::trace;
#elif DEBUG_IS_ON
spdlog::level::level_enum llevel = spdlog::level::debug;
#elif INFO_IS_ON
spdlog::level::level_enum llevel = spdlog::level::info;
#else
spdlog::level::level_enum llevel = spdlog::level::warn;
#endif
if(log_stdout){
std::string filename = fmt::format("./{}.log",app);
m_sinks.push_back(std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>());
m_sinks[num_sinks++].get()->set_level(llevel);
}
if(log_rot_file){
std::string filename = fmt::format("./{}.log",app);
m_sinks.push_back(std::make_shared<spdlog::sinks::rotating_file_sink_mt>(filename, 5*1024*1024, 3));
}
std::stringstream ss;
ss << "[%Y-%m-%dT%H:%M:%S.%f] [" << app << "] [%n] [%l] %v";
// m_async_cmd = new _Logger("asnyc_c", m_sinks, ss.str().c_str());
// m_amf_app = new _Logger("amf_app", m_sinks, ss.str().c_str());
// m_config = new _Logger("configurations", m_sinks, ss.str().c_str());
// m_system = new _Logger("system", m_sinks, ss.str().c_str());
// m_sctp = new _Logger("sctp", m_sinks, ss.str().c_str());
// m_nas_mm = new _Logger("nas_mm", m_sinks, ss.str().c_str());
// m_ngap = new _Logger("ngap", m_sinks, ss.str().c_str());
// m_itti = new _Logger("itti", m_sinks, ss.str().c_str());
// m_amf_n2 = new _Logger("amf_n2", m_sinks, ss.str().c_str());
// m_task_amf_n2 = new _Logger("TASK_AMF_N2", m_sinks, ss.str().c_str());
// m_amf_n1 = new _Logger("amf_n1", m_sinks, ss.str().c_str());
// m_task_amf_n1 = new _Logger("TASK_AMF_N1", m_sinks, ss.str().c_str());
// m_amf_n11 = new _Logger("amf_n11", m_sinks, ss.str().c_str());
// m_task_amf_n11 = new _Logger("TASK_AMF_N11", m_sinks, ss.str().c_str());
m_amf_server = new _Logger("ausf_server", m_sinks, ss.str().c_str());
}
_Logger::_Logger( const char *category, std::vector<spdlog::sink_ptr> &sinks, const char *pattern )
: m_log( category, sinks.begin(), sinks.end() )
{
m_log.set_pattern( pattern );
#if TRACE_IS_ON
m_log.set_level( spdlog::level::trace );
#elif DEBUG_IS_ON
m_log.set_level( spdlog::level::debug );
#elif INFO_IS_ON
m_log.set_level( spdlog::level::info );
#else
m_log.set_level( spdlog::level::warn );
#endif
}
void _Logger::trace( const char *format, ... )
{
#if TRACE_IS_ON
va_list args;
va_start( args, format );
log( _ltTrace, format, args );
va_end( args );
#endif
}
void _Logger::trace( const std::string &format, ... )
{
#if TRACE_IS_ON
va_list args;
va_start( args, format );
log( _ltTrace, format.c_str(), args );
va_end( args );
#endif
}
void _Logger::debug( const char *format, ... )
{
#if DEBUG_IS_ON
va_list args;
va_start( args, format );
log( _ltDebug, format, args );
va_end( args );
#endif
}
void _Logger::debug( const std::string &format, ... )
{
#if DEBUG_IS_ON
va_list args;
va_start( args, format );
log( _ltDebug, format.c_str(), args );
va_end( args );
#endif
}
void _Logger::info( const char *format, ... )
{
#if INFO_IS_ON
va_list args;
va_start( args, format );
log( _ltInfo, format, args );
va_end( args );
#endif
}
void _Logger::info( const std::string &format, ... )
{
#if INFO_IS_ON
va_list args;
va_start( args, format );
log( _ltInfo, format.c_str(), args );
va_end( args );
#endif
}
void _Logger::startup( const char *format, ... )
{
va_list args;
va_start( args, format );
log( _ltStartup, format, args );
va_end( args );
}
void _Logger::startup( const std::string &format, ... )
{
va_list args;
va_start( args, format );
log( _ltStartup, format.c_str(), args );
va_end( args );
}
void _Logger::warn( const char *format, ... )
{
va_list args;
va_start( args, format );
log( _ltWarn, format, args );
va_end( args );
}
void _Logger::warn( const std::string &format, ... )
{
va_list args;
va_start( args, format );
log( _ltWarn, format.c_str(), args );
va_end( args );
}
void _Logger::error( const char *format, ... )
{
va_list args;
va_start( args, format );
log( _ltError, format, args );
va_end( args );
}
void _Logger::error( const std::string &format, ... )
{
va_list args;
va_start( args, format );
log( _ltError, format.c_str(), args );
va_end( args );
}
void _Logger::log( _LogType lt, const char *format, va_list &args )
{
char buffer[ 2048 ];
vsnprintf( buffer, sizeof(buffer), format, args );
switch ( lt )
{
case _ltTrace: m_log.trace( buffer ); break;
case _ltDebug: m_log.debug( buffer ); break;
case _ltInfo: m_log.info( buffer ); break;
case _ltStartup: m_log.warn( buffer ); break;
case _ltWarn: m_log.error( buffer ); break;
case _ltError: m_log.critical( buffer ); break;
}
}
#ifndef __LOGGER_H
#define __LOGGER_H
#include <cstdarg>
#include <stdexcept>
#include <vector>
#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info ", "start", "warn ", "error", "off " };
#define SPDLOG_ENABLE_SYSLOG
#include "spdlog/spdlog.h"
class LoggerException : public std::runtime_error
{
public:
explicit LoggerException(const char *m) : std::runtime_error(m) {}
explicit LoggerException(const std::string &m) : std::runtime_error(m) {}
};
class _Logger
{
public:
_Logger(const char * category, std::vector<spdlog::sink_ptr> &sinks, const char *pattern);
void trace(const char *format, ...);
void trace(const std::string &format, ...);
void debug(const char *format, ...);
void debug(const std::string &format, ...);
void info(const char *format, ...);
void info(const std::string &format, ...);
void startup(const char *format, ...);
void startup(const std::string &format, ...);
void warn(const char *format, ...);
void warn(const std::string &format, ...);
void error(const char *format, ...);
void error(const std::string &format, ...);
private:
_Logger();
enum _LogType
{
_ltTrace,
_ltDebug,
_ltInfo,
_ltStartup,
_ltWarn,
_ltError
};
void log(_LogType lt, const char *format, va_list &args);
spdlog::logger m_log;
};
class Logger
{
public:
static void init(const char *app, const bool log_stdout, const bool log_rot_file){singleton()._init(app, log_stdout, log_rot_file);}
static void init(const std::string &app, const bool log_stdout, const bool log_rot_file){init(app.c_str(), log_stdout, log_rot_file);}
// static _Logger &async_cmd(){return *singleton().m_async_cmd;}
// static _Logger &amf_app(){return *singleton().m_amf_app;}
// static _Logger &config(){return *singleton().m_config;}
// static _Logger &system(){return *singleton().m_system;}
// static _Logger &sctp(){return *singleton().m_sctp;}
// static _Logger &nas_mm(){return *singleton().m_nas_mm;}
// static _Logger &ngap(){return *singleton().m_ngap;}
// static _Logger &itti(){return *singleton().m_itti;}
// static _Logger &amf_n2(){return *singleton().m_amf_n2;}
// static _Logger &task_amf_n2(){return *singleton().m_task_amf_n2;}
// static _Logger &amf_n1(){return *singleton().m_amf_n1;}
// static _Logger &task_amf_n1(){return *singleton().m_task_amf_n1;}
// static _Logger &amf_n11(){return *singleton().m_amf_n11;}
// static _Logger &task_amf_n11(){return *singleton().m_task_amf_n11;}
static _Logger &ausf_server(){return *singleton().m_ausf_server;}
private:
static Logger *m_singleton;
static Logger &singleton(){if(!m_singleton) m_singleton = new Logger(); return *m_singleton;}
Logger(){}
~Logger(){}
void _init(const char *app, const bool log_stdout, const bool log_rot_file);
std::vector<spdlog::sink_ptr> m_sinks;
std::string m_pattern;
// _Logger *m_async_cmd;
// _Logger *m_amf_app;
// _Logger *m_config;
// _Logger *m_system;
// _Logger *m_sctp;
// _Logger *m_nas_mm;
// _Logger *m_ngap;
// _Logger *m_itti;
// _Logger *m_amf_n2;
// _Logger *m_task_amf_n2;
// _Logger *m_amf_n1;
// _Logger *m_task_amf_n1;
// _Logger *m_amf_n11;
// _Logger *m_task_amf_n11;
_Logger *m_ausf_server;
};
#endif
#ifndef UNF_TRIE_CHAR_STREAM_HH
#define UNF_TRIE_CHAR_STREAM_HH
#include <vector>
#include <string>
#include "util.hh"
namespace UNF {
namespace Trie {
class CharStream {
public:
CharStream(const char* str) : cur_(str) {}
unsigned char read() { return eos() ? '\0' : *cur_++; }
unsigned char prev() const { return cur_[-1]; }
unsigned char peek() const { return *cur_; }
const char* cur() const { return cur_; }
bool eos() const { return *cur_ == '\0'; }
void setCur(const char* new_cur) { cur_ = new_cur; }
private:
const char* cur_;
};
class RangeCharStream {
public:
RangeCharStream(const char* beg, const char* end) : cur_(beg), end_(end) {}
unsigned char read() { return eos() ? '\0' : *cur_++; }
unsigned char prev() const { return cur_[-1]; }
unsigned char peek() const { return *cur_; }
const char* cur() const { return cur_; }
const char* end() const { return end_; }
bool eos() const { return cur_ == end_; }
private:
const char* cur_;
const char* end_;
};
class CompoundCharStream {
public:
CompoundCharStream(const char* first, const char* second)
: beg1(first), beg2(second), cur1(beg1), cur2(beg2) {}
unsigned char read() { return !eos1() ? read1() : read2(); }
unsigned char peek() const { return !eos1() ? *cur1 : *cur2; }
unsigned char prev() const { return !eos1() || beg2==cur2 ? cur1[-1] : cur2[-1]; }
const char* cur() const { return !eos1() ? cur1 : cur2; }
bool eos() const { return eos1() && eos2(); }
bool within_first() const { return !eos1(); }
unsigned offset() const { return cur1-beg1 + cur2-beg2; }
void setCur(const char* p) {
if(beg1 <= p && p <= cur1) {
cur1=p;
cur2=beg2;
} else {
cur2=p;
}
}
protected:
unsigned char read1() { return eos1() ? '\0' : *cur1++; }
unsigned char read2() { return eos2() ? '\0' : *cur2++; }
bool eos1() const { return *cur1=='\0'; }
bool eos2() const { return *cur2=='\0'; }
protected:
const char* beg1;
const char* beg2;
const char* cur1;
const char* cur2;
};
class CharStreamForComposition : public CompoundCharStream {
public:
CharStreamForComposition (const char* first, const char* second,
const std::vector<unsigned char>& canonical_classes,
std::string& buf)
: CompoundCharStream(first, second), classes(canonical_classes), skipped(buf)
{}
void init_skipinfo() {
skipped.clear();
skipped_tail = 0;
}
void mark_as_last_valid_point() {
skipped_tail = skipped.size();
marked_point = cur();
}
void reset_at_marked_point() {
setCur(marked_point);
}
void append_read_char_to_str(std::string& s, const char* beg) const {
if(eos1()==false) {
s.append(beg, cur());
} else {
s.append(beg, cur1);
s.append(beg2, cur());
}
}
void append_skipped_chars_to_str(std::string& s) const {
s.append(skipped.begin(), skipped.begin()+skipped_tail);
}
unsigned char get_canonical_class() const {
return offset() < classes.size() ? classes[offset()] : 0;
}
bool next_combining_char(unsigned char prev_class, const char* ppp) {
while(Util::is_utf8_char_start_byte(peek()) == false)
read();
unsigned char mid_class = get_prev_canonical_class();
unsigned char cur_class = get_canonical_class();
if(prev_class==0 && mid_class==0 && cur_class!=0)
return false;
if(prev_class < cur_class && mid_class < cur_class) {
skipped.append(ppp, cur());
return true;
} else {
if(cur_class != 0) {
read();
return next_combining_char(prev_class,ppp);
}
return false;
}
}
private:
unsigned char get_prev_canonical_class() const {
return offset()-1 < classes.size() ? classes[offset()-1] : 0;
}
private:
const std::vector<unsigned char>& classes;
std::string& skipped;
unsigned skipped_tail;
const char* marked_point;
};
}
}
#endif
#ifndef UNF_TRIE_NODE_HH
#define UNF_TRIE_NODE_HH
namespace UNF {
namespace Trie {
class Node {
public:
unsigned jump(unsigned char ch) const { return base() + ch; }
unsigned value() const { return base(); }
unsigned check_char() const { return data>>24; }
unsigned to_uint() const { return data; }
static const Node* from_uint_array(const unsigned* node_uints)
{ return reinterpret_cast<const Node*>(node_uints); }
private:
unsigned base() const { return data & 0xFFFFFF; }
private:
unsigned data;
};
}
}
#endif
#ifndef UNF_NORMALIZER_HH
#define UNF_NORMALIZER_HH
#include <vector>
#include <string>
#include <algorithm>
#include <cstring>
#include "searcher.hh"
#include "char_stream.hh"
#include "table.hh"
#include "util.hh"
namespace UNF {
class Normalizer {
public:
enum Form { FORM_NFD, FORM_NFC, FORM_NFKD, FORM_NFKC };
public:
Normalizer()
: nf_d(TABLE::NODES, TABLE::CANONICAL_DECOM_ROOT, (const char *)TABLE::STRINGS),
nf_kd(TABLE::NODES, TABLE::COMPATIBILITY_DECOM_ROOT, (const char *)TABLE::STRINGS),
nf_c(TABLE::NODES, TABLE::CANONICAL_COM_ROOT, (const char *)TABLE::STRINGS),
nf_c_qc(TABLE::NODES, TABLE::NFC_ILLEGAL_ROOT),
nf_kc_qc(TABLE::NODES, TABLE::NFKC_ILLEGAL_ROOT),
ccc(TABLE::NODES, TABLE::CANONICAL_CLASS_ROOT)
{}
const char* normalize(const char* src, Form form) {
switch(form) {
case FORM_NFD: return nfd(src);
case FORM_NFC: return nfc(src);
case FORM_NFKD: return nfkd(src);
case FORM_NFKC: return nfkc(src);
default: return src;
}
}
const char* nfd(const char* src) { return decompose(src, nf_d); }
const char* nfkd(const char* src) { return decompose(src, nf_kd); }
const char* nfc(const char* src) { return compose(src, nf_c_qc, nf_d); }
const char* nfkc(const char* src) { return compose(src, nf_kc_qc, nf_kd); }
private:
const char* decompose(const char* src, const Trie::NormalizationForm& nf) {
const char* beg = next_invalid_char(src, nf);
if(*beg=='\0')
return src;
buffer.assign(src, beg);
do {
const char* end = next_valid_starter(beg, nf);
decompose_one(beg, end, nf, buffer);
beg = next_invalid_char(end, nf);
buffer.append(end, beg);
} while(*beg!='\0');
return buffer.c_str();
}
void decompose_one(const char* beg, const char* end, const Trie::NormalizationForm& nf, std::string& buf) {
unsigned last = buf.size();
nf.decompose(Trie::RangeCharStream(beg,end), buf);
char* bufbeg = const_cast<char*>(buf.data());
canonical_combining_class_ordering(bufbeg+last, bufbeg+buf.size());
}
const char* compose(const char* src, const Trie::NormalizationForm& nf, const Trie::NormalizationForm& nf_decomp) {
const char* beg = next_invalid_char(src, nf);
if(*beg=='\0')
return src;
buffer.assign(src, beg);
while(*beg!='\0') {
const char* end = next_valid_starter(beg, nf);
buffer2.clear();
decompose_one(beg, end, nf_decomp, buffer2);
end = compose_one(buffer2.c_str(), end, buffer);
beg = next_invalid_char(end, nf);
buffer.append(end, beg);
}
return buffer.c_str();
}
const char* compose_one(const char* starter, const char* rest_starter, std::string& buf) {
Trie::CharStreamForComposition in(starter, rest_starter, canonical_classes, buffer3);
while(in.within_first())
nf_c.compose(in, buf);
return in.cur();
}
void canonical_combining_class_ordering(char* beg, const char* end) {
canonical_classes.assign(end-beg+1, 0); // +1 is for sentinel value
ccc.sort(beg, canonical_classes);
}
const char* next_invalid_char(const char* src, const Trie::NormalizationForm& nf) const {
int last_canonical_class = 0;
const char* cur = Util::nearest_utf8_char_start_point(src);
const char* starter = cur;
for(; *cur != '\0'; cur = Util::nearest_utf8_char_start_point(cur+1)) {
int canonical_class = ccc.get_class(cur);
if(last_canonical_class > canonical_class && canonical_class != 0)
return starter;
if(nf.quick_check(cur)==false)
return starter;
if(canonical_class==0)
starter=cur;
last_canonical_class = canonical_class;
}
return cur;
}
const char* next_valid_starter(const char* src, const Trie::NormalizationForm& nf) const {
const char* cur = Util::nearest_utf8_char_start_point(src+1);
while(ccc.get_class(cur)!=0 || nf.quick_check(cur)==false)
cur = Util::nearest_utf8_char_start_point(cur+1);
return cur;
}
private:
const Trie::NormalizationForm nf_d;
const Trie::NormalizationForm nf_kd;
const Trie::NormalizationForm nf_c;
const Trie::NormalizationForm nf_c_qc;
const Trie::NormalizationForm nf_kc_qc;
const Trie::CanonicalCombiningClass ccc;
std::string buffer;
std::string buffer2;
std::string buffer3;
std::vector<unsigned char> canonical_classes;
};
}
#endif
#ifndef UNF_TRIE_SEARCHER_HH
#define UNF_TRIE_SEARCHER_HH
#include "char_stream.hh"
#include "node.hh"
#include "util.hh"
namespace UNF {
namespace Trie {
class Searcher {
public:
Searcher(const Node* nodes, unsigned root, const char* value=NULL)
: nodes(nodes), root(root), value(value) {}
unsigned find_value(const char* key, int default_value) const {
unsigned node_index=root;
for(CharStream in(key);; in.read()) {
node_index = nodes[node_index].jump(in.peek());
if(nodes[node_index].check_char()==in.peek()) {
unsigned terminal_index = nodes[node_index].jump('\0');
if(nodes[terminal_index].check_char()=='\0') {
return nodes[terminal_index].value();
}
} else
return default_value;
}
}
protected:
const Node* nodes;
const unsigned root;
const char* value;
};
class CanonicalCombiningClass : private Searcher {
public:
CanonicalCombiningClass(const unsigned* node_uints, unsigned root)
: Searcher(Node::from_uint_array(node_uints), root) {}
unsigned get_class(const char* str) const { return find_value(str,0); }
void sort(char* str, std::vector<unsigned char>& classes) const {
CharStream in(str);
unsigned sort_beg=0;
unsigned sort_end=0;
unsigned unicode_char_count=0;
loop_head:
unsigned beg = in.cur()-str;
for(unsigned node_index=root;;){
node_index = nodes[node_index].jump(in.read());
if(nodes[node_index].check_char()==in.prev()) {
unsigned terminal_index = nodes[node_index].jump('\0');
if(nodes[terminal_index].check_char()=='\0') {
if((unicode_char_count++)==0)
sort_beg = beg;
sort_end = in.cur()-str;
unsigned char klass = nodes[terminal_index].value();
for(unsigned i=beg; i < sort_end; i++)
classes[i] = klass;
break;
}
} else {
if(unicode_char_count > 1)
bubble_sort(str, classes, sort_beg, sort_end);
unicode_char_count = 0;
break;
}
}
Util::eat_until_utf8_char_start_point(in);
if(in.eos()==false)
goto loop_head;
if(unicode_char_count > 1)
bubble_sort(str, classes, sort_beg, sort_end);
}
private:
void bubble_sort(char* str, std::vector<unsigned char>& canonical_classes, unsigned beg, unsigned end) const {
for(unsigned limit=beg, next=end; limit != next;) {
limit = next;
for(unsigned i=beg+1; i < limit; i++)
if(canonical_classes[i-1] > canonical_classes[i]) {
std::swap(canonical_classes[i-1], canonical_classes[i]);
std::swap(str[i-1], str[i]);
next = i;
}
}
}
};
class NormalizationForm : private Searcher {
public:
NormalizationForm(const unsigned* node_uints, unsigned root, const char* value=NULL)
: Searcher(Node::from_uint_array(node_uints), root, value) {}
bool quick_check(const char* key) const { return find_value(key,0xFFFFFFFF)==0xFFFFFFFF; }
void decompose(RangeCharStream in, std::string& buffer) const {
loop_head:
const char* beg = in.cur();
for(unsigned node_index=root;;) {
node_index = nodes[node_index].jump(in.read());
if(nodes[node_index].check_char()==in.prev()) {
unsigned terminal_index = nodes[node_index].jump('\0');
if(nodes[terminal_index].check_char()=='\0') {
word_append(buffer, value, nodes[terminal_index].value());
beg = in.cur();
break;
}
} else {
Util::eat_until_utf8_char_start_point(in);
buffer.append(beg, in.cur());
break;
}
}
if(in.eos()==false)
goto loop_head;
}
void compose(CharStreamForComposition& in, std::string& buf) const {
in.init_skipinfo();
const char* const beg = in.cur();
const char* current_char_head = in.cur();
unsigned composed_char_info = 0;
unsigned node_index = root;
unsigned retry_root_node = root;
unsigned char retry_root_class = 0;
for(bool first=true;;) {
if(Util::is_utf8_char_start_byte(in.peek())) {
if(node_index != root)
first=false;
current_char_head = in.cur();
retry_root_node = node_index;
retry_root_class = in.get_canonical_class();
}
retry:
unsigned next_index = nodes[node_index].jump(in.peek());
if(nodes[next_index].check_char()==in.read()) {
// succeeded
node_index = next_index;
unsigned terminal_index = nodes[node_index].jump('\0');
if(nodes[terminal_index].check_char()=='\0') {
composed_char_info = nodes[terminal_index].value();
in.mark_as_last_valid_point();
if(in.eos() || retry_root_class > in.get_canonical_class())
break;
}
} else if (first==true) {
// no retry if current point is a part of first starter
break;
} else if (in.next_combining_char(retry_root_class, current_char_head)==true) {
// back previous code-point and retry
node_index = retry_root_node;
current_char_head = in.cur();
goto retry;
} else {
break;
}
}
if(composed_char_info != 0) {
// append composed unicode-character and skipped combining-characters
word_append(buf, value, composed_char_info);
in.append_skipped_chars_to_str(buf);
in.reset_at_marked_point();
} else {
// append one unicode-character
in.setCur(Util::nearest_utf8_char_start_point(beg+1));
in.append_read_char_to_str(buf, beg);
}
}
private:
static void word_append(std::string& buffer, const char* base, unsigned pos_info) {
buffer.append(base+(pos_info&0x3FFFF), pos_info>>18);
}
};
}
}
#endif
This diff is collapsed.
#ifndef UNF_UTIL_HH
#define UNF_UTIL_HH
namespace UNF {
namespace Util {
inline bool is_utf8_char_start_byte(char byte) {
if(!(byte&0x80)) return true; // ascii
else if (byte&0x40) return true; // start of a UTF-8 character byte sequence
return false;
}
inline const char* nearest_utf8_char_start_point(const char* s) {
for(; is_utf8_char_start_byte(*s)==false; s++);
return s;
}
template <class CharStream>
inline void eat_until_utf8_char_start_point(CharStream& in) {
for(; is_utf8_char_start_byte(in.peek())==false; in.read());
}
}
}
#endif
This diff is collapsed.
This diff is collapsed.
/*
Copyright (C) 2019-2020, Kip Warner.
Released under the terms of Apache License 2.0.
*/
// Multiple include protection...
#ifndef _BASE_64_H_
#define _BASE_64_H_
// Includes...
// Build environment configuration...
#include <pistache/config.h>
// Standard C++ / POSIX system headers...
#include <cstddef>
#include <string>
#include <vector>
#if __cplusplus < 201703L
namespace std {
typedef uint8_t byte;
}
#endif
// A class for performing decoding to raw bytes from base 64 encoding...
class Base64Decoder {
// Public methods...
public:
// Constructor...
explicit Base64Decoder(const std::string &Base64EncodedString)
: m_Base64EncodedString(Base64EncodedString) {}
// Calculate length of decoded raw bytes from that would be generated if
// the base 64 encoded input buffer was decoded. This is not a static
// method because we need to examine the string...
std::vector<std::byte>::size_type CalculateDecodedSize() const;
// Decode base 64 encoding into raw bytes...
const std::vector<std::byte> &Decode();
// Get raw decoded data...
const std::vector<std::byte> &GetRawDecodedData() const noexcept {
return m_DecodedData;
}
// Protected methods...
protected:
// Convert an octet character to corresponding sextet, provided it can
// safely be represented as such. Otherwise return 0xff...
std::byte DecodeCharacter(const unsigned char Character) const;
// Protected attributes...
protected:
// Base 64 encoded string to decode...
const std::string &m_Base64EncodedString;
// Decoded raw data...
std::vector<std::byte> m_DecodedData;
};
// A class for performing base 64 encoding from raw bytes...
class Base64Encoder {
// Public methods...
public:
// Construct encoder to encode from a raw input buffer...
explicit Base64Encoder(const std::vector<std::byte> &InputBuffer)
: m_InputBuffer(InputBuffer) {}
// Calculate length of base 64 string that would need to be generated
// for raw data of a given length...
static std::string::size_type CalculateEncodedSize(
const std::vector<std::byte>::size_type DecodedSize) noexcept;
// Encode raw data input buffer to base 64...
const std::string &Encode() noexcept;
// Encode a string into base 64 format...
static std::string EncodeString(const std::string &StringInput);
// Get the encoded data...
const std::string &GetBase64EncodedString() const noexcept {
return m_Base64EncodedString;
}
// Protected methods...
protected:
// Encode single binary byte to 6-bit base 64 character...
unsigned char EncodeByte(const std::byte Byte) const;
// Protected attributes...
protected:
// Raw bytes to encode to base 64 string...
const std::vector<std::byte> &m_InputBuffer;
// Base64 encoded string...
std::string m_Base64EncodedString;
};
// Multiple include protection...
#endif
/*
Mathieu Stefani, 29 janvier 2016
The Http client
*/
#pragma once
#include <pistache/async.h>
#include <pistache/http.h>
#include <pistache/os.h>
#include <pistache/reactor.h>
#include <pistache/timer_pool.h>
#include <pistache/view.h>
#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
namespace Pistache {
namespace Http {
namespace Default {
constexpr int Threads = 1;
constexpr int MaxConnectionsPerHost = 8;
constexpr bool KeepAlive = true;
constexpr size_t MaxResponseSize = std::numeric_limits<uint32_t>::max();
} // namespace Default
class Transport;
struct Connection : public std::enable_shared_from_this<Connection> {
using OnDone = std::function<void()>;
explicit Connection(size_t maxResponseSize);
struct RequestData {
RequestData(Async::Resolver resolve, Async::Rejection reject,
const Http::Request &request, OnDone onDone)
: resolve(std::move(resolve)), reject(std::move(reject)),
request(request), onDone(std::move(onDone)) {}
Async::Resolver resolve;
Async::Rejection reject;
Http::Request request;
OnDone onDone;
};
enum State : uint32_t { Idle, Used };
enum ConnectionState { NotConnected, Connecting, Connected };
void connect(const Address &addr);
void close();
bool isIdle() const;
bool tryUse();
void setAsIdle();
bool isConnected() const;
bool hasTransport() const;
void associateTransport(const std::shared_ptr<Transport> &transport);
Async::Promise<Response> perform(const Http::Request &request, OnDone onDone);
Async::Promise<Response> asyncPerform(const Http::Request &request,
OnDone onDone);
void performImpl(const Http::Request &request, Async::Resolver resolve,
Async::Rejection reject, OnDone onDone);
Fd fd() const;
void handleResponsePacket(const char *buffer, size_t totalBytes);
void handleError(const char *error);
void handleTimeout();
std::string dump() const;
private:
void processRequestQueue();
struct RequestEntry {
RequestEntry(Async::Resolver resolve, Async::Rejection reject,
std::shared_ptr<TimerPool::Entry> timer, OnDone onDone)
: resolve(std::move(resolve)), reject(std::move(reject)),
timer(std::move(timer)), onDone(std::move(onDone)) {}
Async::Resolver resolve;
Async::Rejection reject;
std::shared_ptr<TimerPool::Entry> timer;
OnDone onDone;
};
Fd fd_;
struct sockaddr_in saddr;
std::unique_ptr<RequestEntry> requestEntry;
std::atomic<uint32_t> state_;
std::atomic<ConnectionState> connectionState_;
std::shared_ptr<Transport> transport_;
Queue<RequestData> requestsQueue;
TimerPool timerPool_;
ResponseParser parser;
};
class ConnectionPool {
public:
ConnectionPool() = default;
void init(size_t maxConnsPerHost, size_t maxResponseSize);
std::shared_ptr<Connection> pickConnection(const std::string &domain);
static void releaseConnection(const std::shared_ptr<Connection> &connection);
size_t usedConnections(const std::string &domain) const;
size_t idleConnections(const std::string &domain) const;
size_t availableConnections(const std::string &domain) const;
void closeIdleConnections(const std::string &domain);
void shutdown();
private:
using Connections = std::vector<std::shared_ptr<Connection>>;
using Lock = std::mutex;
using Guard = std::lock_guard<Lock>;
mutable Lock connsLock;
std::unordered_map<std::string, Connections> conns;
size_t maxConnectionsPerHost;
size_t maxResponseSize;
};
class Client;
class RequestBuilder {
public:
friend class Client;
RequestBuilder &method(Method method);
RequestBuilder &resource(const std::string &val);
RequestBuilder &params(const Uri::Query &query);
RequestBuilder &header(const std::shared_ptr<Header::Header> &header);
template <typename H, typename... Args>
typename std::enable_if<Header::IsHeader<H>::value, RequestBuilder &>::type
header(Args &&... args) {
return header(std::make_shared<H>(std::forward<Args>(args)...));
}
RequestBuilder &cookie(const Cookie &cookie);
RequestBuilder &body(const std::string &val);
RequestBuilder &body(std::string &&val);
RequestBuilder &timeout(std::chrono::milliseconds val);
Async::Promise<Response> send();
private:
explicit RequestBuilder(Client *const client) : client_(client), request_() {}
Client *const client_;
Request request_;
};
class Client {
public:
friend class RequestBuilder;
struct Options {
friend class Client;
Options()
: threads_(Default::Threads),
maxConnectionsPerHost_(Default::MaxConnectionsPerHost),
keepAlive_(Default::KeepAlive),
maxResponseSize_(Default::MaxResponseSize) {}
Options &threads(int val);
Options &keepAlive(bool val);
Options &maxConnectionsPerHost(int val);
Options &maxResponseSize(size_t val);
private:
int threads_;
int maxConnectionsPerHost_;
bool keepAlive_;
size_t maxResponseSize_;
};
Client();
~Client();
static Options options();
void init(const Options &options = Options());
RequestBuilder get(const std::string &resource);
RequestBuilder post(const std::string &resource);
RequestBuilder put(const std::string &resource);
RequestBuilder patch(const std::string &resource);
RequestBuilder del(const std::string &resource);
void shutdown();
private:
std::shared_ptr<Aio::Reactor> reactor_;
ConnectionPool pool;
Aio::Reactor::Key transportKey;
std::atomic<uint64_t> ioIndex;
using Lock = std::mutex;
using Guard = std::lock_guard<Lock>;
Lock queuesLock;
std::unordered_map<std::string,
MPMCQueue<std::shared_ptr<Connection::RequestData>, 2048>>
requestsQueues;
bool stopProcessPequestsQueues;
private:
RequestBuilder prepareRequest(const std::string &resource,
Http::Method method);
Async::Promise<Response> doRequest(Http::Request request);
void processRequestQueue();
};
} // namespace Http
} // namespace Pistache
/* common.h
Mathieu Stefani, 12 August 2015
A collection of macro / utilities / constants
*/
#pragma once
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <cstring>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#define TRY(...) \
do { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": "; \
if (errno == 0) { \
oss << gai_strerror(static_cast<int>(ret)); \
} else { \
oss << strerror(errno); \
} \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
} while (0)
#define TRY_RET(...) \
[&]() { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": " << strerror(errno); \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
return ret; \
}(); \
(void)0
struct PrintException {
void operator()(std::exception_ptr exc) const {
try {
std::rethrow_exception(exc);
} catch (const std::exception &e) {
std::cerr << "An exception occured: " << e.what() << std::endl;
}
}
};
#define unreachable() __builtin_unreachable()
// Until we require C++17 compiler with [[maybe_unused]]
#define UNUSED(x) (void)(x);
#pragma once
#include <cstddef>
#include <cstdint>
#include <limits>
// Allow compile-time overload
namespace Pistache {
namespace Const {
static constexpr size_t MaxBacklog = 128;
static constexpr size_t MaxEvents = 1024;
static constexpr size_t MaxBuffer = 4096;
static constexpr size_t DefaultWorkers = 1;
static constexpr size_t DefaultTimerPoolSize = 128;
// Defined from CMakeLists.txt in project root
static constexpr size_t DefaultMaxRequestSize = 4096;
static constexpr size_t DefaultMaxResponseSize =
std::numeric_limits<uint32_t>::max();
static constexpr size_t ChunkSize = 1024;
static constexpr uint16_t HTTP_STANDARD_PORT = 80;
} // namespace Const
} // namespace Pistache
/*
Mathieu Stefani, 16 janvier 2016
Representation of a Cookie as per http://tools.ietf.org/html/rfc6265
*/
#pragma once
#include <ctime>
#include <list>
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <pistache/http_defs.h>
#include <pistache/optional.h>
namespace Pistache {
namespace Http {
struct Cookie {
friend std::ostream &operator<<(std::ostream &os, const Cookie &cookie);
Cookie(std::string name, std::string value);
std::string name;
std::string value;
Optional<std::string> path;
Optional<std::string> domain;
Optional<FullDate> expires;
Optional<int> maxAge;
bool secure;
bool httpOnly;
std::map<std::string, std::string> ext;
static Cookie fromRaw(const char *str, size_t len);
static Cookie fromString(const std::string &str);
private:
void write(std::ostream &os) const;
};
std::ostream &operator<<(std::ostream &os, const Cookie &cookie);
class CookieJar {
public:
using HashMapCookies =
std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<
std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> {
explicit iterator(const Storage::const_iterator &_iterator)
: iter_storage(_iterator), iter_cookie_values(), iter_storage_end() {}
iterator(const Storage::const_iterator &_iterator,
const Storage::const_iterator &end)
: iter_storage(_iterator), iter_cookie_values(), iter_storage_end(end) {
if (iter_storage != iter_storage_end) {
iter_cookie_values = iter_storage->second.begin();
}
}
Cookie operator*() const {
return iter_cookie_values->second; // return iter_storage->second;
}
const Cookie *operator->() const { return &(iter_cookie_values->second); }
iterator &operator++() {
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if (iter_storage != iter_storage_end)
iter_cookie_values = iter_storage->second.begin();
}
return *this;
}
iterator operator++(int) {
iterator ret(iter_storage, iter_storage_end);
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if (iter_storage != iter_storage_end) // this check is important
iter_cookie_values = iter_storage->second.begin();
}
return ret;
}
bool operator!=(iterator other) const {
return iter_storage != other.iter_storage;
}
bool operator==(iterator other) const {
return iter_storage == other.iter_storage;
}
private:
Storage::const_iterator iter_storage;
HashMapCookies::const_iterator iter_cookie_values;
Storage::const_iterator
iter_storage_end; // we need to know where main hashmap ends.
};
CookieJar();
void add(const Cookie &cookie);
void removeAllCookies();
void addFromRaw(const char *str, size_t len);
Cookie get(const std::string &name) const;
bool has(const std::string &name) const;
iterator begin() const { return iterator(cookies.begin(), cookies.end()); }
iterator end() const { return iterator(cookies.end()); }
private:
Storage cookies;
};
} // namespace Http
} // namespace Pistache
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#pragma once
namespace Pistache {
#define REQUIRES(condition) typename std::enable_if<(condition), int>::type = 0
} // namespace Pistache
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
libpistache-0.0.002-git20200802.so.0.0
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment