1: /* $Id: minissdpc-libuv.c,v 1.1.1.1 2023/09/27 11:25:11 misho Exp $ */
2: /* vim: tabstop=4 shiftwidth=4 noexpandtab
3: * Project : miniupnp
4: * Web : http://miniupnp.free.fr/
5: * Author : Thomas BERNARD
6: * copyright (c) 2005-2019 Thomas Bernard
7: * This software is subjet to the conditions detailed in the
8: * provided LICENCE file. */
9: #include <stdio.h>
10: #include <stdlib.h>
11: #include <string.h>
12:
13: #include "minissdpc-libuv.h"
14:
15: #include "codelength.h"
16: #include <uv.h>
17:
18: struct userdata_s
19: {
20: void* cb;
21: void* userdata;
22: };
23:
24: static void connect_cb(uv_connect_t* req, int status)
25: {
26: uv_stream_t *stream = req->handle;
27: struct userdata_s *us = stream->data;
28: void(*user_connect_cb)(void*, void*) = us->cb;
29:
30: if(status < 0)
31: user_connect_cb(0, us->userdata);
32: else
33: user_connect_cb(req->handle, us->userdata);
34:
35: free(req);
36: free(us);
37:
38: if(status < 0)
39: free(stream);
40: }
41:
42: int
43: connectToMiniSSDPD(const char * socketpath, void(*user_connect_cb)(void* connect, void* userdata), void *userdata)
44: {
45: if(user_connect_cb == 0)
46: return MINISSDPC_INVALID_INPUT;
47:
48: if(!socketpath)
49: socketpath = "/var/run/minissdpd.sock";
50:
51: uv_pipe_t *p = malloc(sizeof(uv_pipe_t));
52:
53: if(uv_pipe_init(uv_default_loop(), p, 1) < 0)
54: return MINISSDPC_SOCKET_ERROR;
55:
56: uv_connect_t *conn = malloc(sizeof(uv_connect_t));
57: struct userdata_s *us = malloc(sizeof(struct userdata_s));
58: us->cb = user_connect_cb;
59: us->userdata = userdata;
60: p->data = us;
61: uv_pipe_connect(conn, p, socketpath, &connect_cb);
62: return MINISSDPC_SUCCESS;
63: }
64:
65: static void
66: close_cb(uv_handle_t *handle)
67: {
68: free(handle);
69: }
70:
71: MINIUPNP_LIBSPEC void
72: disconnectFromMiniSSDPD(void *session)
73: {
74: uv_close((uv_handle_t *)session, close_cb);
75: }
76:
77: static void write_cb(uv_write_t* req, int status)
78: {
79: uv_stream_t* stream = req->handle;
80: struct userdata_s *us = stream->data;
81: void(*user_write_cb)(void*, int, void*) = us->cb;
82: user_write_cb(req->handle, status == 0, us->userdata);
83: // free(req->bufs->base);
84: free(req);
85: free(us);
86: }
87:
88: MINIUPNP_LIBSPEC int
89: requestDevicesFromMiniSSDPD(void *session, const char * devtype, void(*requestFinish)(void *connect, int success, void* userdata), void* userdata)
90: {
91: char *buffer;
92: char *p;
93: unsigned int stsize;
94:
95: if (devtype == NULL)
96: {
97: return MINISSDPC_UNKNOWN_ERROR;
98: }
99: stsize = strlen(devtype);
100:
101: buffer = malloc(256);
102: if(buffer == NULL)
103: {
104: return MINISSDPC_MEMORY_ERROR;
105: }
106: p = buffer;
107:
108: if(stsize == 8 && 0 == memcmp(devtype, "ssdp:all", 8))
109: {
110: buffer[0] = 3; /* request type 3 : everything */
111: }
112: else
113: {
114: buffer[0] = 1; /* request type 1 : request devices/services by type */
115: }
116:
117: p++;
118: unsigned int l = stsize;
119: CODELENGTH(l, p);
120:
121: if(p + stsize > buffer + 256)
122: {
123: /* devtype is too long ! */
124: #ifdef DEBUG
125: fprintf(stderr, "devtype is too long ! stsize=%u sizeof(buffer)=%u\n",
126: stsize, (unsigned)sizeof(buffer));
127: #endif /* DEBUG */
128: free(buffer);
129: return MINISSDPC_INVALID_INPUT;
130: }
131:
132: memcpy(p, devtype, stsize);
133: p += stsize;
134: uv_write_t *req = malloc(sizeof(uv_write_t));
135:
136: if(req == NULL)
137: {
138: free(buffer);
139: return MINISSDPC_MEMORY_ERROR;
140: }
141:
142: struct userdata_s *us = malloc(sizeof(struct userdata_s));
143:
144: if(us == NULL)
145: {
146: free(req);
147: free(buffer);
148: return MINISSDPC_MEMORY_ERROR;
149: }
150:
151: us->cb = requestFinish;
152: us->userdata = userdata;
153: uv_stream_t* stream = session;
154: stream->data = us;
155: uv_buf_t data[] =
156: {
157: { .base = buffer, .len = p - buffer }
158: };
159: uv_write(req, stream, data, 1, write_cb);
160: return MINISSDPC_SUCCESS;
161: }
162:
163: static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf)
164: {
165: (void)handle;
166: buf->base = malloc(size);
167: buf->len = size;
168: }
169:
170: static void read_cb(uv_stream_t *stream, ssize_t size, const uv_buf_t* buffer)
171: {
172: struct userdata_s *us = stream->data;
173: void(*user_write_cb)(void *connect, void *userdata, struct UPNPDev*) = us->cb;
174: struct UPNPDev * devlist = NULL;
175: char * p = buffer->base;
176: unsigned int i, ndev;
177:
178: if(size == 0)
179: {
180: return;
181: }
182:
183: if(size < 0)
184: {
185: user_write_cb(stream, us->userdata, devlist);
186: uv_read_stop(stream);
187: free(us);
188: stream->data = NULL;
189: return;
190: }
191:
192: ndev = *p;
193: p++;
194:
195: for(i = 0; i < ndev; i++)
196: {
197: unsigned int urlsize;
198: char *url = NULL;
199: unsigned int stsize;
200: char *st = NULL;
201: unsigned int usnsize;
202: char *usn = NULL;
203:
204: DECODELENGTH(urlsize, p);
205: if(size != 0)
206: {
207: url = strndup(p, urlsize);
208:
209: if(url == NULL)
210: break;
211: }
212: p += urlsize;
213:
214: DECODELENGTH(stsize, p);
215: if(size != 0)
216: {
217: st = strndup(p, stsize);
218:
219: if(st == NULL)
220: {
221: free(url);
222: break;
223: }
224: }
225: p += stsize;
226:
227: DECODELENGTH(usnsize, p);
228: if(size != 0)
229: {
230: usn = strndup(p, usnsize);
231:
232: if(usn == NULL)
233: {
234: free(url);
235: free(st);
236: break;
237: }
238: }
239: p += usnsize;
240:
241: struct UPNPDev *tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
242: if(tmp == NULL)
243: {
244: free(url);
245: free(st);
246: free(usn);
247: break;
248: }
249:
250: tmp->pNext = devlist;
251: tmp->descURL = tmp->buffer;
252: tmp->st = tmp->buffer + 1 + urlsize;
253: tmp->usn = tmp->buffer + 1 + urlsize + 1 + stsize;
254: memcpy(tmp->descURL, url, urlsize+1);
255: memcpy(tmp->st, st, stsize+1);
256: memcpy(tmp->usn, usn, usnsize+1);
257: free(url);
258: free(st);
259: free(usn);
260: tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */
261: devlist = tmp;
262: }
263:
264: user_write_cb(stream, us->userdata, devlist);
265: uv_read_stop(stream);
266: stream->data = NULL;
267: free(us);
268: }
269:
270: void
271: receiveDevicesFromMiniSSDPD(void *session, void(*requestFinish)(void *session, void *userdata, struct UPNPDev*), void* userdata)
272: {
273: struct userdata_s *us = malloc(sizeof(struct userdata_s));
274: us->cb = requestFinish;
275: us->userdata = userdata;
276: uv_stream_t *stream = session;
277: stream->data = us;
278: uv_read_start(stream, alloc_cb, read_cb);
279: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>