summaryrefslogtreecommitdiff
path: root/src/pdu.h
blob: 0305550365a63109897b8ca378a12c219424bd0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#ifndef __PDU_H
#define __PDU_H

#include <stdint.h>
#include <string.h>
#include <time.h>

#include <phonebook.h>

extern char *strptime(const char *s, const char *format, struct tm *tm);

#define PDU_BUFFER_SIZE		1024
#define PDU_ADDR_SIZE		PHONEBOOK_ADDR_SIZE

#define PDU_OCTETS_MAX		140
#define PDU_UD_8BIT_MAX		PDU_OCTETS_MAX
#define PDU_UD_7BIT_MAX		(PDU_OCTETS_MAX * 8 / 7)
#define PDU_UD_SIZE		(PDU_UD_7BIT_MAX + 1)

#define PDU_TIMESTAMP_LEN	14
#define PDU_TIMESTAMP_SIZE	(PDU_TIMESTAMP_LEN + 1)
#define GMT_OFFSET_LEN		2
#define GMT_OFFSET_IDX		(PDU_TIMESTAMP_LEN - GMT_OFFSET_LEN)

#define PDU_VPF_RELATIVE_2DAYS	0xA8

struct pdu_addr {
	char addr[PDU_ADDR_SIZE];
	uint8_t type;
	uint8_t len;
};

enum {
	PDU_MTI_DELIVER = 0,
	PDU_MTI_SUBMIT = 1,
	PDU_MTI_REPORT = 2,
	PDU_MTI_RESERVED = 3,
};

enum {
	PDU_VPF_NOT_PRESENT = 0,
	PDU_VPF_ENHANCED = 1,
	PDU_VPF_RELATIVE = 2,
	PDU_VPF_ABSOUTE = 3,
};

enum {
	PDU_ALPHABET_DEFAULT = 0,
	PDU_ALPHABET_EIGHT = 1,
	PDU_ALPHABET_UCS2 = 2,
	PDU_ALPHABET_RESERVED = 3,
};

struct pdu_info {
	int msg_len;
	struct pdu_addr smsc_addr;
	struct pdu_addr addr;
	union {
		uint8_t type;
		struct {
			uint8_t msg_type: 2;
			uint8_t more_msg: 1;
			uint8_t unused: 2;
			uint8_t status_report: 1;
			uint8_t user_data_header: 1;
			uint8_t reply_path: 1;
		};
		struct {
			uint8_t msg_type: 2;
			uint8_t reject_duplicates: 1;
			uint8_t validity_period_format: 2;
			uint8_t status_report: 1;
			uint8_t user_data_header: 1;
			uint8_t reply_path: 1;
		};
	} type;
	uint8_t msg_reference;
	uint8_t protocol_id;
	union {
		uint8_t data_coding;
		struct {
			uint8_t msg_class: 2;
			uint8_t alphabet: 2;
			uint8_t have_msg_class: 1;
			uint8_t compressed: 1;
			uint8_t unused: 2;
		} general;
	} data_coding;
	uint8_t validity_period;
	struct tm timestamp;
	uint8_t user_data_len;
	uint8_t user_data[PDU_UD_SIZE];
};

#define HEX_BYTE_LEN		2

int hex_nibble_scan(const char *buf, size_t len);
int hex_byte_decode(const char *buf);

int hex_byte_encode(char *buf, size_t len, int byte);

int nibble_swap(char *buf, size_t len);
int strunpad(char *str, unsigned char c);
int strpad(char *str, size_t len, unsigned char c);

int pdu_format_timestamp(struct pdu_info *pdu, char *str, size_t len, const char *fmt);
int pdu_format_vp(struct pdu_info *pdu, char *str, size_t len);
int pdu_addr_type_infer(const char *str);
int pdu_addr_fill(struct pdu_addr *addr, const char *addr_str, int type);
int pdu_user_data_read(int fd, struct pdu_info *pdu);

#define shiftr(a, n)		((a) >> (n))
#define shiftl(a, n)		((a) << (n))

#define bit_mask(n, s)		(((1 << (n)) - 1) << (s))
#define bit_maskr(n)		bit_mask(n, 0)
#define bit_maskl(n, b)		bit_mask(n, (b) - (n))

#define cycleup(n, mod)		((n) % (mod))
#define cycledown(n, mod)	((mod - 1) - ((n) % (mod)))

#define octet_align(n)		((((n) * 7) + ((-(n) * 7) & 7)) / 8)

#define STRLEN_CHECK(str, len, ret) \
do { \
	if (strnlen(str, len) < len) { \
		log_error("buffer ends unexpectedly early"); \
		return ret; \
	} \
} while (0)

#endif /* ~__PDU_H */