-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathpython4yahdlc.c
More file actions
189 lines (161 loc) · 4.97 KB
/
python4yahdlc.c
File metadata and controls
189 lines (161 loc) · 4.97 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "yahdlc.h"
#define MAX_FRAME_PAYLOAD 512
#define HEADERS_LENGTH 8
#define TOTAL_FRAME_LENGTH MAX_FRAME_PAYLOAD + HEADERS_LENGTH
static PyObject *Yahdlc_MessageError;
static PyObject *Yahdlc_FCSError;
/* ---------- yahdlc functions ---------- */
/**
* Retrieves data from the specified buffer containing the HDLC frame.
*/
static PyObject *get_data(PyObject *self, PyObject *args)
{
int ret;
const char *frame_data;
char recv_data[TOTAL_FRAME_LENGTH];
Py_ssize_t buf_length = 0;
unsigned int recv_length = 0;
yahdlc_control_t control;
if (!PyArg_ParseTuple(args, "s#", &frame_data, &buf_length))
return NULL;
if (buf_length > TOTAL_FRAME_LENGTH)
{
PyErr_SetString(PyExc_ValueError, "buffer too long");
return NULL;
}
ret = yahdlc_get_data(&control, frame_data, buf_length, recv_data, &recv_length);
// If success.
if (ret >= 0)
{
PyObject *t;
t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyBytes_FromStringAndSize(recv_data, recv_length));
PyTuple_SetItem(t, 1, PyLong_FromUnsignedLong(control.frame));
PyTuple_SetItem(t, 2, PyLong_FromUnsignedLong(control.seq_no));
return t;
}
else if (ret == -EINVAL)
{
PyErr_SetString(PyExc_ValueError, "invalid parameter");
return NULL;
}
else if (ret == -ENOMSG)
{
PyErr_SetString(Yahdlc_MessageError, "invalid message");
return NULL;
}
// If the FCS is not valid, we return the sequence number
// to be sent back as NACK.
else if (ret == -EIO)
{
PyErr_SetObject(Yahdlc_FCSError, PyLong_FromUnsignedLong(control.seq_no));
return NULL;
}
else
{
PyErr_SetString(PyExc_RuntimeError, "unknown error");
return NULL;
}
}
/**
* Resets the values used by the 'yahdlc_get_data' function
* to keep track of the received buffers.
*/
static PyObject *get_data_reset(PyObject *self, PyObject *args)
{
yahdlc_get_data_reset();
Py_RETURN_NONE;
}
/**
* Creates an HDLC frame with the specified data buffer.
*/
static PyObject *frame_data(PyObject *self, PyObject *args)
{
int ret;
const char *send_data;
char frame_data[TOTAL_FRAME_LENGTH];
Py_ssize_t data_length = 0;
unsigned int frame_length = 0, frame_type = YAHDLC_FRAME_DATA, seq_no = 0;
yahdlc_control_t control;
if (!PyArg_ParseTuple(args, "s#|II", &send_data, &data_length, &frame_type, &seq_no))
return NULL;
if (data_length > MAX_FRAME_PAYLOAD)
{
PyErr_SetString(PyExc_ValueError, "data too long");
return NULL;
}
else if (frame_type != YAHDLC_FRAME_DATA && frame_type != YAHDLC_FRAME_ACK && frame_type != YAHDLC_FRAME_NACK)
{
PyErr_SetString(PyExc_ValueError, "bad frame type");
return NULL;
}
else if (seq_no > 7)
{
PyErr_SetString(PyExc_ValueError, "invalid sequence number");
return NULL;
}
control.frame = frame_type;
control.seq_no = seq_no;
ret = yahdlc_frame_data(&control, send_data, data_length, frame_data, &frame_length);
// If success.
if (ret == 0)
return PyBytes_FromStringAndSize(frame_data, frame_length);
else
{
PyErr_SetString(PyExc_ValueError, "invalid parameter");
return NULL;
}
}
/* ---------- Settings ---------- */
/**
* Python module's methods.
*/
static PyMethodDef YahdlcMethods[] = {
{"get_data", get_data, METH_VARARGS, "Retrieves data from the specified buffer containing the HDLC frame."},
{"get_data_reset", get_data_reset, METH_VARARGS, "Resets the values used by the 'get_data' method to keep track of the received buffers."},
{"frame_data", frame_data, METH_VARARGS, "Creates an HDLC frame with the specified data buffer."},
{NULL, NULL, 0, NULL}
};
/**
* Python module itself.
*/
static struct PyModuleDef yahdlc_module =
{
PyModuleDef_HEAD_INIT,
"yahdlc",
"HDLC implementation",
-1,
YahdlcMethods
};
/**
* Initialises the Python module.
*/
PyMODINIT_FUNC PyInit_yahdlc(void)
{
PyObject *m;
m = PyModule_Create(&yahdlc_module);
if (m == NULL)
return NULL;
Yahdlc_MessageError = PyErr_NewException("yahdlc.MessageError", NULL, NULL);
Py_XINCREF(Yahdlc_MessageError);
if (PyModule_AddObject(m, "MessageError", Yahdlc_MessageError) < 0) {
Py_XDECREF(Yahdlc_MessageError);
Py_CLEAR(Yahdlc_MessageError);
Py_DECREF(m);
return NULL;
}
Yahdlc_FCSError = PyErr_NewException("yahdlc.FCSError", NULL, NULL);
Py_XINCREF(Yahdlc_FCSError);
if (PyModule_AddObject(m, "FCSError", Yahdlc_FCSError) < 0) {
Py_XDECREF(Yahdlc_FCSError);
Py_CLEAR(Yahdlc_FCSError);
Py_DECREF(m);
return NULL;
}
PyModule_AddIntConstant(m, "FRAME_DATA", YAHDLC_FRAME_DATA);
PyModule_AddIntConstant(m, "FRAME_ACK", YAHDLC_FRAME_ACK);
PyModule_AddIntConstant(m, "FRAME_NACK", YAHDLC_FRAME_NACK);
return m;
}