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>