Handle the new address format in send_subscr().
[pytipc.git] / tipc_ll.c
blobeb142602383be0c58ac6e26d120a87105023dc54
2 /*
3 * Python bindings for TIPC
4 * Alberto Bertogli (albertito@gmail.com)
6 * This is the low-level module, used by the python one to construct
7 * friendlier objects.
8 */
10 #include <Python.h>
12 #include <sys/types.h> /* socket defines */
13 #include <sys/socket.h> /* socket functions */
14 #include <stdlib.h> /* malloc() */
15 #include <stdint.h> /* uint32_t and friends */
16 #include <arpa/inet.h> /* htonls() and friends */
17 #include <string.h> /* memcpy() */
19 #include <linux/tipc.h> /* TIPC stuff */
23 * Internal useful functions
26 static int fill_sockaddr(struct sockaddr_tipc *sa, PyObject *addr)
28 unsigned int atype, stype, lower, upper;
29 unsigned int scope = TIPC_CLUSTER_SCOPE;
31 if (!PyArg_ParseTuple(addr, "iiii|i;Invalid TIPC address format",
32 &atype, &stype, &lower, &upper, &scope))
33 return 0;
35 memset(sa, 0, sizeof(struct sockaddr_tipc));
37 sa->family = AF_TIPC;
38 sa->scope = scope;
40 if (atype == TIPC_ADDR_NAME) {
41 sa->addrtype = TIPC_ADDR_NAME;
42 sa->addr.name.name.type = stype;
43 sa->addr.name.name.instance = lower;
44 } else {
45 sa->addrtype = TIPC_ADDR_NAMESEQ;
46 sa->addr.nameseq.type = stype;
47 sa->addr.nameseq.lower = lower;
48 sa->addr.nameseq.upper = upper;
50 return 1;
53 static PyObject *sa_to_tuple(const struct sockaddr_tipc *sa)
55 if (sa->addrtype == TIPC_ADDR_NAMESEQ) {
56 return Py_BuildValue("iiiii",
57 sa->addrtype,
58 sa->addr.nameseq.type,
59 sa->addr.nameseq.lower,
60 sa->addr.nameseq.upper,
61 sa->scope);
62 } else {
63 return Py_BuildValue("iiiii",
64 sa->addrtype,
65 sa->addr.name.name.type,
66 sa->addr.name.name.instance,
67 sa->addr.name.name.instance,
68 sa->scope);
74 * Exported functions
77 static PyObject *tipc_socket(PyObject *self, PyObject *args)
79 int fd, stype;
81 if (!PyArg_ParseTuple(args, "i:tipc_socket", &stype)) {
82 return NULL;
85 Py_BEGIN_ALLOW_THREADS
86 fd = socket(AF_TIPC, stype, 0);
87 Py_END_ALLOW_THREADS
88 if (fd < 0)
89 return PyErr_SetFromErrno(PyExc_IOError);
91 return PyLong_FromLong(fd);
95 static PyObject *tipc_bind(PyObject *self, PyObject *args)
97 int fd, rv;
98 struct sockaddr_tipc sa;
99 PyObject *addr;
101 if (!PyArg_ParseTuple(args, "iO:tipc_bind", &fd, &addr))
102 return NULL;
104 if (!fill_sockaddr(&sa, addr))
105 return NULL;
107 Py_BEGIN_ALLOW_THREADS
108 rv = bind(fd, (struct sockaddr *) &sa, sizeof(sa));
109 Py_END_ALLOW_THREADS
111 if (rv < 0)
112 return PyErr_SetFromErrno(PyExc_IOError);
114 return PyLong_FromLong(rv);
118 static PyObject *tipc_connect(PyObject *self, PyObject *args)
120 int fd, rv;
121 struct sockaddr_tipc sa;
122 PyObject *addr;
124 if (!PyArg_ParseTuple(args, "iO:tipc_connect", &fd, &addr))
125 return NULL;
127 if (!fill_sockaddr(&sa, addr))
128 return NULL;
130 Py_BEGIN_ALLOW_THREADS
131 rv = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
132 Py_END_ALLOW_THREADS
134 if (rv < 0)
135 return PyErr_SetFromErrno(PyExc_IOError);
137 return PyLong_FromLong(rv);
141 static PyObject *tipc_accept(PyObject *self, PyObject *args)
143 int fd, newfd;
144 struct sockaddr_tipc sa;
145 socklen_t salen = sizeof(sa);
147 if (!PyArg_ParseTuple(args, "i:tipc_accept", &fd)) {
148 return NULL;
151 Py_BEGIN_ALLOW_THREADS
152 newfd = accept(fd, (struct sockaddr *) &sa, &salen);
153 Py_END_ALLOW_THREADS
155 if (newfd < 0)
156 return PyErr_SetFromErrno(PyExc_IOError);
157 return Py_BuildValue("iO", newfd, sa_to_tuple(&sa));
161 static PyObject *tipc_sendto(PyObject *self, PyObject *args)
163 int fd, rv;
164 char *buf;
165 size_t len;
166 struct sockaddr_tipc sa;
167 PyObject *addr;
169 if (!PyArg_ParseTuple(args, "is#O:tipc_sendto", &fd, &buf, &len, &addr))
170 return NULL;
172 if (!fill_sockaddr(&sa, addr))
173 return NULL;
175 Py_BEGIN_ALLOW_THREADS
176 rv = sendto(fd, buf, len, 0, (struct sockaddr *) &sa, sizeof(sa));
177 Py_END_ALLOW_THREADS
179 if (rv < 0)
180 return PyErr_SetFromErrno(PyExc_IOError);
182 return PyLong_FromLong(rv);
185 static PyObject *tipc_recvfrom(PyObject *self, PyObject *args)
187 int fd;
188 char *buf;
189 size_t maxlen;
190 struct sockaddr_tipc sa;
191 socklen_t salen = sizeof(sa);
192 int rv;
193 PyObject *str;
195 if (!PyArg_ParseTuple(args, "ii:tipc_recvfrom", &fd, &maxlen)) {
196 return NULL;
199 buf = malloc(maxlen);
200 if (buf == NULL)
201 return PyErr_NoMemory();
203 Py_BEGIN_ALLOW_THREADS
204 rv = recvfrom(fd, buf, maxlen, 0,
205 (struct sockaddr *) &sa, &salen);
206 Py_END_ALLOW_THREADS
208 if (rv < 0)
209 return PyErr_SetFromErrno(PyExc_IOError);
211 str = PyString_FromStringAndSize(buf, rv);
212 free(buf);
214 return Py_BuildValue("OO", str, sa_to_tuple(&sa));
217 static PyObject *tipc_build_subscr(PyObject *self, PyObject *args)
219 int stype, lower, upper;
220 uint32_t timeout, filter;
221 struct tipc_subscr subs;
223 if (!PyArg_ParseTuple(args, "iiiii:tipc_build_subscr",
224 &stype, &lower, &upper, &timeout, &filter)) {
225 return NULL;
228 subs.seq.type = stype;
229 subs.seq.lower = lower;
230 subs.seq.upper = upper;
231 subs.timeout = timeout;
232 subs.filter = filter;
234 return PyString_FromStringAndSize((char *) &subs,
235 sizeof(subs));
238 static PyObject *tipc_parse_event(PyObject *self, PyObject *args)
240 unsigned char *buf;
241 size_t len;
242 struct tipc_event *event;
244 if (!PyArg_ParseTuple(args, "s#:tipc_parse_event",
245 &buf, &len)) {
246 return NULL;
249 /* Return None if the buffer looks strange */
250 if (len < sizeof(event))
251 return Py_BuildValue("");
253 event = (struct tipc_event *) buf;
255 return Py_BuildValue("iii(iiiii)",
256 event->event,
257 event->found_lower,
258 event->found_upper,
259 event->s.seq.type,
260 event->s.seq.lower,
261 event->s.seq.upper,
262 event->s.timeout,
263 event->s.filter);
269 static PyMethodDef pytipc_functions[] = {
270 { "socket", (PyCFunction) tipc_socket, METH_VARARGS, NULL },
271 { "bind", (PyCFunction) tipc_bind, METH_VARARGS, NULL },
272 { "connect", (PyCFunction) tipc_connect, METH_VARARGS, NULL },
273 { "accept", (PyCFunction) tipc_accept, METH_VARARGS, NULL },
274 { "sendto", (PyCFunction) tipc_sendto, METH_VARARGS, NULL },
275 { "recvfrom", (PyCFunction) tipc_recvfrom, METH_VARARGS, NULL },
276 { "build_subscr", (PyCFunction) tipc_build_subscr, METH_VARARGS, NULL },
277 { "parse_event", (PyCFunction) tipc_parse_event, METH_VARARGS, NULL },
278 { NULL }
281 PyMODINIT_FUNC inittipc_ll(void)
283 PyObject *m;
285 m = Py_InitModule("tipc_ll", pytipc_functions);
286 PyModule_AddIntConstant(m, "AF_TIPC", AF_TIPC);
288 /* for addresses */
289 PyModule_AddIntConstant(m, "TIPC_ADDR_NAME", TIPC_ADDR_NAME);
290 PyModule_AddIntConstant(m, "TIPC_ADDR_NAMESEQ", TIPC_ADDR_NAMESEQ);
292 PyModule_AddIntConstant(m, "TIPC_ZONE_SCOPE", TIPC_ZONE_SCOPE);
293 PyModule_AddIntConstant(m, "TIPC_CLUSTER_SCOPE", TIPC_CLUSTER_SCOPE);
294 PyModule_AddIntConstant(m, "TIPC_NODE_SCOPE", TIPC_NODE_SCOPE);
297 /* for setsockopt() */
298 PyModule_AddIntConstant(m, "SOL_TIPC", SOL_TIPC);
299 PyModule_AddIntConstant(m, "TIPC_IMPORTANCE", TIPC_IMPORTANCE);
300 PyModule_AddIntConstant(m, "TIPC_SRC_DROPPABLE", TIPC_SRC_DROPPABLE);
301 PyModule_AddIntConstant(m, "TIPC_DEST_DROPPABLE",
302 TIPC_DEST_DROPPABLE);
303 PyModule_AddIntConstant(m, "TIPC_CONN_TIMEOUT", TIPC_CONN_TIMEOUT);
305 PyModule_AddIntConstant(m, "TIPC_LOW_IMPORTANCE",
306 TIPC_LOW_IMPORTANCE);
307 PyModule_AddIntConstant(m, "TIPC_MEDIUM_IMPORTANCE",
308 TIPC_MEDIUM_IMPORTANCE);
309 PyModule_AddIntConstant(m, "TIPC_HIGH_IMPORTANCE",
310 TIPC_HIGH_IMPORTANCE);
311 PyModule_AddIntConstant(m, "TIPC_CRITICAL_IMPORTANCE",
312 TIPC_CRITICAL_IMPORTANCE);
314 /* for subscriptions */
315 PyModule_AddIntConstant(m, "TIPC_SUB_PORTS", TIPC_SUB_PORTS);
316 PyModule_AddIntConstant(m, "TIPC_SUB_SERVICE", TIPC_SUB_SERVICE);
317 PyModule_AddIntConstant(m, "TIPC_SUB_CANCEL", TIPC_SUB_CANCEL);
318 PyModule_AddIntConstant(m, "TIPC_WAIT_FOREVER", TIPC_WAIT_FOREVER);
319 PyModule_AddIntConstant(m, "TIPC_PUBLISHED", TIPC_PUBLISHED);
320 PyModule_AddIntConstant(m, "TIPC_WITHDRAWN", TIPC_WITHDRAWN);
321 PyModule_AddIntConstant(m, "TIPC_SUBSCR_TIMEOUT", TIPC_SUBSCR_TIMEOUT);
322 PyModule_AddIntConstant(m, "TIPC_CFG_SRV", TIPC_CFG_SRV);
323 PyModule_AddIntConstant(m, "TIPC_TOP_SRV", TIPC_TOP_SRV);