summaryrefslogtreecommitdiff
path: root/src/pdu.h
blob: c164fd14e3800abba7f01b1e9bba00689667ddb0 (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
#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;
			uint8_t reject_duplicates: 1;
			uint8_t validity_period_format: 2;
		};
	} 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 */