Annotation of embedaddon/miniupnpd/miniupnpc-libuv/minissdpc-libuv.c, revision 1.1.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>