Annotation of embedaddon/miniupnpd/miniupnpc-libuv/minissdpc-libuv.c, revision 1.1
1.1 ! misho 1: /* $Id: minissdpc.c,v 1.32 2016/10/07 09:04:36 nanard 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>