Esempio n. 1
0
static int example_static (u_test_case_t *tc)
{
    u_hmap_opts_t opts;
    u_hmap_t *hmap = NULL;
    u_hmap_o_t *obj = NULL;
    int fibonacci[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };

    u_dbg("example_static()");

    u_hmap_opts_init(&opts);

    /* hmap owns data by default - change it */
    u_test_err_if (u_hmap_opts_unset_option(&opts, U_HMAP_OPTS_OWNSDATA));

    u_test_err_if (u_hmap_new(&opts, &hmap));

    /* insert some sample elements */
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, "first", &fibonacci[0]), NULL));
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, "fifth", &fibonacci[4]), NULL)); 
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, "last", 
                &fibonacci[(sizeof(fibonacci)/sizeof(int))-1]), NULL));

    /* retrieve and print values to dbg */
    u_test_err_if (u_hmap_get(hmap, "last", &obj)); 
    u_dbg("hmap['%s'] = %d", (char *) obj->key, *((int *) obj->val));
    u_test_err_if (u_hmap_get(hmap, "fifth", &obj)); 
    u_dbg("hmap['%s'] = %d", (char *) obj->key, *((int *) obj->val)); 
    u_test_err_if (u_hmap_get(hmap, "first", &obj)); 
    u_dbg("hmap['%s'] = %d", (char *) obj->key, *((int *) obj->val));
    
    u_hmap_dbg(hmap);

    /* remove an element and replace it */
    u_test_err_if (u_hmap_del(hmap, "fifth", &obj)); 
    u_hmap_o_free(obj);
    
    /* check that it has been deleted */
    u_test_err_if (u_hmap_get(hmap, "fifth", &obj) == 0); 

    /* delete the other two elements */
    u_test_err_if (u_hmap_del(hmap, "last", &obj)); 
    u_hmap_o_free(obj);
    u_test_err_if (u_hmap_del(hmap, "first", &obj)); 
    u_hmap_o_free(obj);

    /* free hmap and options */
    u_hmap_free(hmap);
    
    return U_TEST_SUCCESS;
err:
    U_FREEF(hmap, u_hmap_free);

    return U_TEST_FAILURE;
}
Esempio n. 2
0
/** 
 *  \brief Parse an URI string and create the corresponding ::u_uri_t object 
 *
 *  Parse the NUL-terminated string \p uri and create an ::u_uri_t object at 
 *  \p *pu 
 *
 *  \param  uri     the NUL-terminated string that must be parsed
 *  \param  opts    bitmask of or'ed ::u_uri_opts_t values
 *  \param  pu      the newly created ::u_uri_t object containing the b
 *
 *  \retval  0  on success
 *  \retval ~0  on error
 */
int u_uri_crumble (const char *uri, u_uri_opts_t opts, u_uri_t **pu)
{
    u_uri_t *u = NULL;
    int rc = 0;
    char es[1024];
    regex_t re;
    regmatch_t pmatch[10];

    dbg_return_if (uri == NULL, ~0);
    dbg_return_if (pu == NULL, ~0);

    dbg_err_if ((rc = regcomp(&re, uri_pat, REG_EXTENDED)));
    dbg_err_if ((rc = regexec(&re, uri, 10, pmatch, 0)));

    dbg_err_if (u_uri_new(opts, &u));
    dbg_err_if (u_uri_fill(u, uri, pmatch));

    regfree(&re);

    *pu = u;

    return 0;
err:
    if (rc)
    {
        regerror(rc, &re, es, sizeof es);
        u_dbg("%s: %s", uri, es);
    }
    regfree(&re);

    if (u)
        u_uri_free(u);

    return ~0;
}
Esempio n. 3
0
int ec_resource_update_rep(ec_res_t *res, const uint8_t *data, size_t data_sz,
        ec_mt_t media_type, uint8_t etag[EC_ETAG_SZ])
{
    ec_rep_t *rep;

    dbg_return_if (res == NULL, -1);

    if ((rep = ec_resource_get_rep(res, media_type, etag)) == NULL)
    {
        u_dbg("no representation matches the supplied media-type and ETag");
        return -1;
    }
    else
    {
        dbg_err_if (ec_resource_add_rep(res, data, data_sz, media_type, etag));

        /* Remove representation only in case the updated representation
         * has been successfully added. */
        (void) ec_rep_del(res, rep);
    }

    return 0;
err:
    return -1;
}
Esempio n. 4
0
int serve_get(ec_server_t *srv, ec_rep_t *rep)
{
    ec_res_t *res = ec_rep_get_res(rep);

    /* Set response code, payload, etag and content-type. */
    (void) set_payload(srv, rep->data, rep->data_sz);
    (void) ec_response_set_code(srv, EC_CONTENT);
    (void) ec_response_add_etag(srv, rep->etag, sizeof rep->etag);
    (void) ec_response_add_content_type(srv, rep->media_type);

    /* Add max-age if != from default. */
    if (res->max_age != EC_COAP_DEFAULT_MAX_AGE)
        (void) ec_response_add_max_age(srv, res->max_age);

    /* See if the client asked for Observing the resource. */
    if (ec_request_get_observe(srv) == 0)
    {
        uint16_t o_cnt;

        /* Add a NON notifier attached to ob_serve callback. */
        if (!ec_add_observer(srv, ob_serve, NULL, res->max_age,
                rep->media_type, EC_COAP_NON, rep->etag,
                sizeof rep->etag))
        {
            /* Get counter from time */
            (void) ec_get_observe_counter(&o_cnt);
            (void) ec_response_add_observe(srv, o_cnt);
        }
        else
            u_dbg("could not add requested observation");
    }

    return 0;
}
Esempio n. 5
0
static ssize_t gzip_transform(codec_t *codec, char *dst, size_t *dcount, 
        const char *src, size_t src_sz)
{
    codec_gzip_t *iz;
    size_t consumed;
 
    dbg_return_if (codec == NULL, -1);
    dbg_return_if (src == NULL, -1);
    dbg_return_if (dst == NULL, -1); 
    dbg_return_if (dcount == NULL || *dcount == 0, -1);
    dbg_return_if (src_sz == 0, -1);

    iz = (codec_gzip_t*)codec;
    
    iz->zstr.next_out = dst;
    iz->zstr.avail_out = *dcount;

    iz->zstr.next_in = (char*)src;
    iz->zstr.avail_in = src_sz;

    iz->err = iz->op(&iz->zstr, Z_NO_FLUSH);
    dbg_err_if(iz->err != Z_OK && iz->err != Z_STREAM_END);

    consumed = src_sz - iz->zstr.avail_in;  /* consumed */
    *dcount = *dcount - iz->zstr.avail_out; /* written */

    return consumed; /* # of consumed input bytes */
err:
    u_dbg("%s", zError(iz->err));
    return -1;
}
Esempio n. 6
0
/* this is the main function of the service. when this function returns the
 * service will be terminated by the SCM */
void WINAPI ServiceMain(DWORD argc, PTSTR *argv)
{
    SERVICE_STATUS *pSt = &ctx->status;

    /* register the service with the ServiceControlManager */
    ctx->hServiceStatus = RegisterServiceCtrlHandlerEx(ss_name, HandlerEx, ctx);
    dbg_err_if( ctx->hServiceStatus == 0 );

    /* init the status struct and update the service status */
    ZeroMemory(pSt, sizeof(SERVICE_STATUS));
    /* just one service in this exe */
    pSt->dwServiceType = SERVICE_WIN32_OWN_PROCESS; 
    /* action supported by the service */
    pSt->dwControlsAccepted = SERVICE_ACCEPT_STOP;
    /* error returned while starting/stopping */
    pSt->dwWin32ExitCode = NO_ERROR;          
    /* service specific exit code */
    pSt->dwServiceSpecificExitCode = 0;          
    /* we're still initializing */
    pSt->dwCurrentState = SERVICE_START_PENDING;
    /* for progress operation */
    pSt->dwCheckPoint = 1;
    /* wait hint */
    pSt->dwWaitHint = 1000;
    /* set status */
    dbg_err_if(SetServiceStatus(ctx->hServiceStatus, pSt) == 0);

    dbg_err_if(parse_opt(argc, argv));

    /* load config and initialize */
    dbg_err_if(app_init());

    /* this should happen after initialization but I don't want to
       mess main.c with win32-only code */

    /* notify the end of initialization */
    u_dbg("SERVICE_RUNNING");
    ctx->status.dwCurrentState = SERVICE_RUNNING;
    ctx->status.dwCheckPoint = ctx->status.dwWaitHint = 0;    
    dbg_err_if(!SetServiceStatus(ctx->hServiceStatus, &ctx->status));

    /* run the main loop */
    app_run();

    /* let the service terminate */
    ctx->status.dwCurrentState = SERVICE_STOPPED;
    dbg_err_if(!SetServiceStatus(ctx->hServiceStatus, &ctx->status));

    return;

err:
    warn_strerror(GetLastError());

    /* let the service terminate */
    ctx->status.dwCurrentState = SERVICE_STOPPED;
    dbg_err_if(!SetServiceStatus(ctx->hServiceStatus, &ctx->status));
}
Esempio n. 7
0
/* this function will be called by the SCM to request an action */
DWORD WINAPI HandlerEx(DWORD dwControl, DWORD dwEventType, 
        LPVOID lpEventData, LPVOID lpContext)
{
    enum { DENY_ACTION = 0xff };

    switch(dwControl)
    {
    case SERVICE_CONTROL_INTERROGATE:
        u_dbg("SERVICE_CONTROL_INTERROGATE" );
        SetServiceStatus(ctx->hServiceStatus, &ctx->status);
        return NO_ERROR;

    case SERVICE_CONTROL_STOP:
        u_dbg("SERVICE_CONTROL_STOP");

        if(ctx->status.dwCurrentState == SERVICE_STOPPED)
            return NO_ERROR; /* service already stopped */

        /* start the stop procedure, move to stop_pending state */
        ctx->status.dwCheckPoint = 1;
        ctx->status.dwWaitHint = 2000;
        ctx->status.dwCurrentState = SERVICE_STOP_PENDING; 
        SetServiceStatus(ctx->hServiceStatus, &ctx->status);

        server_stop(ctx->server);
        return NO_ERROR;

    case SERVICE_CONTROL_PAUSE:
        u_dbg("SERVICE_CONTROL_PAUSE");
        break;

    case SERVICE_CONTROL_CONTINUE:
        u_dbg("SERVICE_CONTROL_CONTINUE");
        break;

    case SERVICE_CONTROL_SHUTDOWN:
        u_dbg("SERVICE_CONTROL_SHUTDOWN");
        break;

    case SERVICE_CONTROL_PARAMCHANGE:
        u_dbg("SERVICE_CONTROL_PARAMCHANGE");
        break;

    default:
        u_dbg("SERVICE_CONTROL_UNKNOWN!!!!");
    }
    if(dwControl > 127 && dwControl < 255)
    {
        /* user defined control code */
        u_dbg("SERVICE_CONTROL_USER_DEFINED");
    }

    return ERROR_CALL_NOT_IMPLEMENTED;
}
Esempio n. 8
0
static int example_easy_opaque (u_test_case_t *tc)
{
    enum { 
        VAL_SZ = sizeof(mystruct2_t),
        ELEMS_NUM = 4
    };
    u_hmap_opts_t opts;
    u_hmap_t *hmap = NULL;
    const char *keys[] = { "!@#", "$%^", "&*(", "()_" };
    mystruct2_t vals[] = { { 'a', 1, 1.1 }, { 'b', 2, 2.2 }, 
        { 'c', 3, 3.3 }, { 'd', 4, 4.4 } };
    mystruct2_t *pval;
    int i;

    u_dbg("example_easy_opaque()");

    u_hmap_opts_init(&opts);

    u_test_err_if (u_hmap_opts_set_val_type(&opts, U_HMAP_OPTS_DATATYPE_OPAQUE));
    u_test_err_if (u_hmap_opts_set_val_sz(&opts, VAL_SZ));

    u_test_err_if (u_hmap_easy_new(&opts, &hmap));

    /* insert elements */
    for (i = 0 ; i < ELEMS_NUM; i++) 
        u_test_err_if (u_hmap_easy_put(hmap, keys[i], &vals[i]));

#ifdef DEBUG_HEAVY
    u_hmap_dbg(hmap);
#endif

    /* check elements */
    for (i = 0; i < ELEMS_NUM; i++) {

        pval = u_hmap_easy_get(hmap, keys[i]);
        u_test_err_if (pval == NULL);

        u_test_err_if ((pval->c != vals[i].c) ||
                (pval->x != vals[i].x) ||
                (pval->d != vals[i].d));
    }

    /* free hmap (options and elements are freed automatically) */
    u_hmap_easy_free(hmap);

    return U_TEST_SUCCESS;
err:
    U_FREEF(hmap, u_hmap_free);

    return U_TEST_FAILURE;
}
Esempio n. 9
0
static int example_dynamic_own_hmap (u_test_case_t *tc)
{
    u_hmap_opts_t opts;
    u_hmap_t *hmap = NULL;
    u_hmap_o_t *obj = NULL;

    u_dbg("example_dynamic_own_hmap()");

    u_hmap_opts_init(&opts);

    /* objects don't need to be freed - same as default:
    u_test_err_if (u_hmap_opts_set_freefunc(&opts, NULL));
    */

    /* hmap owns both keys and data - allow overwrite */
    u_test_err_if (u_hmap_opts_set_val_type(&opts, U_HMAP_OPTS_DATATYPE_STRING));
    u_test_err_if (u_hmap_opts_unset_option(&opts, U_HMAP_OPTS_NO_OVERWRITE));
    u_test_err_if (u_hmap_new(&opts, &hmap));

    /* insert some sample elements */
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, "EN", "Hello world!"), NULL));
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, "IT", "Ciao mondo!"), NULL));
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, "DE", "Hallo Welt!"), NULL));

    /* retrieve and print values to console */
    u_test_err_if (u_hmap_get(hmap, "DE", &obj)); 
    u_test_err_if (u_hmap_get(hmap, "EN", &obj)); 

    /* remove an element and replace it */
    u_test_err_if (u_hmap_del(hmap, "DE", NULL)); 
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, "DE", "Auf Wiedersehen!"), NULL));
    u_test_err_if (u_hmap_get(hmap, "DE", &obj)); 

    /* check some values */
    u_test_err_if (u_hmap_get(hmap, "IT", &obj)); 
    u_test_err_if (strcmp(obj->val, "Ciao mondo!") != 0);
    u_test_err_if (u_hmap_get(hmap, "DE", &obj)); 
    u_test_err_if (strcmp(obj->val, "Auf Wiedersehen!") != 0);

    /* free hmap (options and elements are freed automatically) */
    u_hmap_free(hmap);

    return U_TEST_SUCCESS;

err:
    U_FREEF(hmap, u_hmap_free);

    return U_TEST_FAILURE;
}
Esempio n. 10
0
static int gzip_free(codec_t *codec)
{
    codec_gzip_t *iz;
    int err;

    nop_return_if (codec == NULL, 0);
    
    iz = (codec_gzip_t*)codec;
    dbg_err_if((err = iz->opEnd(&iz->zstr)) != Z_OK);
    U_FREE(iz);

    return 0;
err:
    u_dbg("%s", zError(err));
    return ~0;
}
Esempio n. 11
0
void ec_net_pullup_all(evutil_socket_t sd, ec_pdu_handler_t pdu_proc, void *arg)
{
    int e;
    struct sockaddr_storage peer;
    socklen_t peer_len = sizeof(peer);
    uint8_t d[EC_COAP_MAX_REQ_SIZE + 1];

    /* Dequeue all buffered PDUs. */
    for (;;)
    {
        int flags = 0;

        /* Pull up next UDP packet from the socket input buffer. */
        ssize_t n = ec_net_pullup(sd, d, sizeof d, &flags,
                (struct sockaddr *) &peer, &peer_len, &e);

        /* Skip empty or too big UDP datagrams (TODO check truncation.) */
        if (!n || n == sizeof d)
            continue;

        if (n < 0)
        {
            /* If no messages are available at the socket, the receive call
             * waits for a message to arrive, unless the socket is nonblocking 
             * in which case the value -1 is returned and the external variable
             * errno set to EAGAIN. */
            switch (e)
            {
                case EAGAIN:
                    return;
                case EINTR:
                    continue;
                default:
                    u_dbg("%s", evutil_socket_error_to_string(e));
                    return;
            }
        }

        /* Process the received PDU invoking whatever PDU processor was 
         * supplied (i.e. client or server.) */
        if (pdu_proc(d, (size_t) n, sd, &peer, arg) == EC_NET_CBRC_DEAD)
            return;
    }
}
Esempio n. 12
0
static ssize_t gzip_flush(codec_t *codec, char *dst, size_t *dcount)
{
    codec_gzip_t *iz;

    dbg_return_if (codec == NULL, -1);
    dbg_return_if (dst == NULL, -1);
    dbg_return_if (dcount == NULL, -1);

    iz = (codec_gzip_t*)codec;
    
    /* can't set it to NULL even if zlib must not use it (avail_in == 0) */
    iz->zstr.next_in = (char*)0xDEADBEEF;
    iz->zstr.avail_in = 0;

#if !defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1200
    /* zlib < 1.2.0 workaround: push a dummy byte at the end of the 
       stream when inflating (see zlib ChangeLog) */
    if(iz->action == GZIP_UNCOMPRESS && iz->dummy == 0)
    { 
        iz->zstr.next_in = &iz->dummy; /* dummy byte */
        iz->zstr.avail_in = 1; 
        iz->dummy++;
    }
#endif

    iz->zstr.next_out = dst;
    iz->zstr.avail_out = *dcount;

    /* should be Z_STREAM_END while uncompressing */
    if(iz->err != Z_STREAM_END)
    {
        iz->err = iz->op(&iz->zstr, 
            iz->action == GZIP_COMPRESS ? Z_FINISH : Z_NO_FLUSH);
        dbg_err_if(iz->err != Z_OK && iz->err != Z_STREAM_END);
    } 

    *dcount = *dcount - iz->zstr.avail_out;   /* written */

    return iz->err == Z_STREAM_END && *dcount == 0 ? 
        CODEC_FLUSH_COMPLETE : CODEC_FLUSH_CHUNK;
err:
    u_dbg("%s", zError(iz->err));
    return -1;
}
Esempio n. 13
0
static int example_easy_dynamic (u_test_case_t *tc)
{
    u_hmap_opts_t opts;
    u_hmap_t *hmap = NULL;
    mystruct_t *mystruct;

    u_dbg("example_easy_dynamic()");

    u_hmap_opts_init(&opts);

    /* setup custom free function */
    u_test_err_if (u_hmap_opts_set_val_freefunc(&opts, &mystruct_free));
    /* no string function for custom object */
    u_test_err_if (u_hmap_opts_set_strfunc(&opts, NULL));

    u_test_err_if (u_hmap_easy_new(&opts, &hmap));

    /* insert 3 objects */
    u_test_err_if (u_hmap_easy_put(hmap, "a", mystruct_create()));
    u_test_err_if (u_hmap_easy_put(hmap, "b", mystruct_create()));
    u_test_err_if (u_hmap_easy_put(hmap, "c", mystruct_create()));

    /* test overwrite - should fail */
    u_test_err_if (u_hmap_easy_put(hmap, "b", mystruct_create()) == 0);

#ifdef DEBUG_HEAVY
    u_hmap_dbg(hmap);
#endif

    /* check a value */
    u_test_err_if ((mystruct = u_hmap_easy_get(hmap, "a")) == NULL);
    u_test_err_if (strcmp(mystruct->a, "first string") != 0);
    u_test_err_if (strcmp(mystruct->b, "second string") != 0);
    
    /* internal objects freed automatically using custom function */
    u_hmap_easy_free(hmap);

    return U_TEST_SUCCESS;
err:
    U_FREEF(hmap, u_hmap_easy_free);

    return U_TEST_FAILURE;
}
Esempio n. 14
0
static int klog_args_check (klog_args_t *ka)
{
    dbg_return_if (ka == NULL, ~0);

    if (ka->type == KLOG_TYPE_UNKNOWN)
        warn_err("unknown log type");

    /* do not filter if not specified or if a wrong value has been supplied */
    if (ka->threshold == KLOG_LEVEL_UNKNOWN)
    {
        u_dbg("threshold unspecified: assuming lowest possible (DEBUG)");
        ka->threshold = KLOG_DEBUG;
    }

    switch (ka->type)
    {
        case KLOG_TYPE_MEM:
            if (ka->mlimit == 0)
                ka->mlimit = KLOG_MLIMIT_DFL;
            break;
        case KLOG_TYPE_FILE:
            if (ka->fbasename == NULL)
                warn_err("log file path is mandatory !");
            if (ka->fsplits == 0)
                ka->fsplits =  KLOG_FSPLITS_DFL;
            if (ka->flimit == 0)
                ka->flimit = KLOG_FLIMIT_DFL;
            break;
        case KLOG_TYPE_SYSLOG:
            if (ka->sfacility == KLOG_FACILITY_UNKNOWN)
            {
                warn("facility unspecified: defaults to LOG_LOCAL7");
                ka->sfacility = LOG_LOCAL7;
            }
            break;
        default:
            warn_err("what are you doing here ?");
    }

    return 0;
err:
    return ~0;
}
Esempio n. 15
0
ssize_t ec_net_pullup(evutil_socket_t sd, uint8_t *b, size_t b_sz,
        int *flags, struct sockaddr *peer, socklen_t *peer_len, int *e)
{
    ssize_t n;
    struct msghdr msg;
    struct iovec iov[1];

    dbg_return_if (sd == -1, -1);
    dbg_return_if (b == NULL, -1);
    dbg_return_if (e == NULL, -1);
    dbg_return_if (flags == NULL, -1);
    /* b_sz==0 allowed here ? */

    memset(&msg, sizeof msg, 0);

    msg.msg_name = peer;
    msg.msg_namelen = *peer_len;
    iov[0].iov_base = b;
    iov[0].iov_len = b_sz;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    *e = 0;

    if ((n = recvmsg(sd, &msg, *flags)) < 0)
    {
        if ((*e = evutil_socket_geterror(sd)) != EAGAIN)
            u_dbg("%s", evutil_socket_error_to_string(*e));
     
        goto err;
    }

    *flags = msg.msg_flags;

    /* TODO retrieve cmsg with type IP_RECVDSTADDR to tell datagrams that 
       where sent to a multicast destination. */

    return n;
err:
    return -1;
}
Esempio n. 16
0
int ec_conn_get_confirmable(ec_conn_t *conn, bool *is_con)
{
    dbg_return_if (conn == NULL, -1);
    dbg_return_if (is_con == NULL, -1);

    switch (conn->is_confirmable)
    {
        case 1:
            *is_con = true;
            break;
        case 2:
            *is_con = false;
            break;
        case 0:
            u_dbg("confirmable flag not set !");
            /* Fall through. */
        default:
            return -1;
    }

    return 0;
}
Esempio n. 17
0
/*
   The PUT method requests that the resource identified by the request
   URI be updated or created with the enclosed representation.  The
   representation format is specified by the media type given in the
   Content-Type Option.

   If a resource exists at the request URI the enclosed representation
   SHOULD be considered a modified version of that resource, and a 2.04
   (Changed) response SHOULD be returned.  If no resource exists then
   the server MAY create a new resource with that URI, resulting in a
   2.01 (Created) response.  If the resource could not be created or
   modified, then an appropriate error response code SHOULD be sent.

   Further restrictions to a PUT can be made by including the If-Match
   (see Section 5.10.9) or If-None-Match (see Section 5.10.10) options
   in the request.

   PUT is not safe, but idempotent.
 */
int serve_put(ec_server_t *srv, ec_rep_t *rep)
{
    /* This routine handles the update of a resource using the PUT method.
     * Creation of a resource via PUT is done by the create() routine. */

    ec_mt_t mt;
    size_t pload_sz;
    uint8_t etag[EC_ETAG_SZ] = { 0 }, *pload;
    ec_res_t *res = ec_rep_get_res(rep);
    size_t bsz = g_ctx.bsz ? g_ctx.bsz : EC_COAP_BLOCK_MAX;
    blockopt_t b1 = { .bnum = 0, .more = false, .bsz = 0 };

    /* Check conditionals:
     * 1) If-None-Match
     * "If the target resource does exist, then the server MUST NOT perform
     *  the requested method.  Instead, the server MUST respond with the 4.12
     *  (Precondition Failed) response code." */
    if (res && ec_request_get_if_none_match(srv) == 0)
    {
        (void) ec_response_set_code(srv, EC_PRECONDITION_FAILED);
        return 0;
    }

    /* 2) If-Match (TODO) */

    /* Get payload and media type (if specified.) */
    pload = ec_request_get_payload(srv, &pload_sz);
    if (pload_sz > bsz)
    {
        (void) ec_response_set_code(srv, EC_REQUEST_ENTITY_TOO_LARGE);
        return 0;
    }

    /* Get media type (if not specified default to text/plain. */
    if (ec_request_get_content_type(srv, &mt))
        mt = EC_MT_TEXT_PLAIN;

    /* Handle Block1 Option.
     * Implementation is stateful: we just check that bnum corresponds to
     * expected and add the new representation atomically. */
    if (ec_request_get_block1(srv, &b1.bnum, &b1.more, &b1.bsz) == 0)
    {
        dbg_err_if (b1.bnum != g_ctx.b1.bnum++);

        if (b1.bsz)
           bsz = U_MIN(bsz, b1.bsz);

        dbg_err_if (ec_response_add_block1(srv, b1.bnum, b1.more, bsz));
    }

    /* First block. */
    if (g_ctx.resbuf == NULL)
        dbg_err_if (u_buf_create(&g_ctx.resbuf));

    /* All blocks are appended to resource buffer. */
    if (pload)
        dbg_err_if (u_buf_append(g_ctx.resbuf, pload, pload_sz));

    /* Last block - now we can process it. */
    if (!b1.more)
    {
        /* Add new representation. */
        dbg_err_if (ec_resource_add_rep(res, u_buf_ptr(g_ctx.resbuf),
                    u_buf_len(g_ctx.resbuf), mt, etag));

        /* Delete old in case media-type matches. */
        if (mt == rep->media_type)
            (void) ec_rep_del(res, rep);

        /* Return Etag of the new representation. */
        (void) ec_response_add_etag(srv, etag, sizeof etag);

        /* Reset state. */
        u_buf_free(g_ctx.resbuf);
        g_ctx.resbuf = NULL;
        g_ctx.b1.bnum = 0;
        g_ctx.b1.more = false;
        g_ctx.b1.bsz = 0;
    }

    (void) ec_response_set_code(srv, EC_CHANGED);
    return 0;
err:
    (void) ec_response_set_code(srv, EC_INTERNAL_SERVER_ERROR);

    /* Reset state. */
    if (g_ctx.resbuf)
        u_buf_free(g_ctx.resbuf);
    g_ctx.resbuf = NULL;
    g_ctx.b1.bnum = 0;
    g_ctx.b1.more = false;
    g_ctx.b1.bsz = 0;

    return -1;
}

/*
 * The POST method requests that the representation enclosed in the
 * request be processed.  The actual function performed by the POST
 * method is determined by the origin server and dependent on the target
 * resource.  It usually results in a new resource being created or the
 * target resource being updated.
 *
 * If a resource has been created on the server, a 2.01 (Created)
 * response that includes the URI of the new resource in a sequence of
 * one or more Location-Path and/or Location-Query Options SHOULD be
 * returned.  If the POST succeeds but does not result in a new resource
 * being created on the server, a 2.04 (Changed) response SHOULD be
 * returned.  If the POST succeeds and results in the target resource
 * being deleted, a 2.02 (Deleted) response SHOULD be returned.
 *
 * POST is neither safe nor idempotent.
 */
/* 
 * Creates a new resource at <request_uri>/<num>, where num is an incremental
 * counter.
 */
int serve_post(ec_server_t *srv)
{
    /* Request vars. */
    ec_mt_t mt;
    ec_res_t *res = NULL;
    bool is_proxy = false;
    uint8_t *pload;
    size_t pload_sz;
    ec_method_mask_t mm = EC_METHOD_MASK_ALL;
    char uri[U_URI_STRMAX];
    char ruri[U_URI_STRMAX];

    /* Block handling. */
    size_t bsz = g_ctx.bsz ? g_ctx.bsz : EC_COAP_BLOCK_MAX;
    blockopt_t b1 = { .bnum = 0, .more = false, .bsz = 0 };

    /* Path tokenisation. */
    size_t nelems, i;
    char **tv = NULL;

    pload = ec_request_get_payload(srv, &pload_sz);
    if (pload_sz > bsz)
    {
        (void) ec_response_set_code(srv, EC_REQUEST_ENTITY_TOO_LARGE);
        return 0;
    }

    /* Get media type (if not specified default to text/plain. */
    if (ec_request_get_content_type(srv, &mt))
        mt = EC_MT_TEXT_PLAIN;
    
    /* Handle Block1 Option.
     * Implementation is stateful: we just check that bnum corresponds to
     * expected and add the new representation atomically. */
    if (ec_request_get_block1(srv, &b1.bnum, &b1.more, &b1.bsz) == 0)
    {
        dbg_err_if (b1.bnum != g_ctx.b1.bnum++);

        if (b1.bsz)
           bsz = U_MIN(bsz, b1.bsz);

        dbg_err_if (ec_response_add_block1(srv, b1.bnum, b1.more, bsz));
    }

    /* First block. */
    if (g_ctx.resbuf == NULL)
        dbg_err_if (u_buf_create(&g_ctx.resbuf));

    /* All blocks are appended to resource buffer. */
    if (pload)
        dbg_err_if (u_buf_append(g_ctx.resbuf, pload, pload_sz));

    /* Last block - now we can process it. */
    if (!b1.more)
    {
        (void) ec_request_get_uri(srv, uri, &is_proxy);

        dbg_err_if (u_snprintf(ruri, sizeof ruri, "%s/%u", uri, g_ctx.resnum));

        u_dbg("creating resource on uri: %s", ruri);

        /* Create resource with all methods allowed. */
        dbg_err_ifm ((res = ec_resource_new(ruri, mm, EC_COAP_DEFAULT_MAX_AGE))
                == NULL, "resource creation failed");

        /* Create new resource representation with the requested media type. */
        /* Each resource only has one representation in this implementation.
         * Use automatic ETag. */
        dbg_err_ifm (ec_resource_add_rep(res, u_buf_ptr(g_ctx.resbuf),
                    u_buf_len(g_ctx.resbuf), mt, NULL),
                "error adding representation for %s", ruri);

        /* Attach resource to FS. */
        dbg_err_ifm (ec_filesys_put_resource(g_ctx.fs, res),
                "adding resource failed");
        res = NULL;

        /* Register the callback that will serve this URI.
         * XXX If we get an error here it's really a bad thing because
         * the resource has been already registered and we go into an
         * inconsistent state. */
        dbg_err_ifm (ec_register_cb(g_ctx.coap, ruri, serve, NULL),
                "registering callback for %s failed", ruri);

        dbg_err_if (u_strtok(ruri, "/", &tv, &nelems));
        dbg_err_if (nelems < 3);

        for (i = 2; i < nelems; i++)  /* Get path only */
            dbg_err_if (ec_response_add_location_path(srv, tv[i]));

        u_strtok_cleanup(tv, nelems);

        /* Reset state. */
        u_buf_free(g_ctx.resbuf);
        g_ctx.resbuf = NULL;
        g_ctx.b1.bnum = 0;
        g_ctx.b1.more = false;
        g_ctx.b1.bsz = 0;

        g_ctx.resnum++;
    }

    (void) ec_response_set_code(srv, EC_CREATED);
    return 0;
err:
    (void) ec_response_set_code(srv, EC_INTERNAL_SERVER_ERROR);
    if (res)
        ec_resource_free(res);
    if (tv)
        u_strtok_cleanup(tv, nelems);

    /* Reset state. */
    if (g_ctx.resbuf)
        u_buf_free(g_ctx.resbuf);
    g_ctx.resbuf = NULL;
    g_ctx.b1.bnum = 0;
    g_ctx.b1.more = false;
    g_ctx.b1.bsz = 0;
    return -1;

#if 0
    /* This routine handles the creation of a resource using the POST method. */
    ec_mt_t mt;
    uint8_t *pload;
    size_t pload_sz;
    ec_res_t *res = NULL;
    bool is_proxy = false;
    ec_method_mask_t mm = EC_METHOD_MASK_ALL;
    char uri[U_URI_STRMAX], *first, *uri_tmp, *uri_res;

    /* Get payload (may be empty/NULL).
     * If it is not empty/NULL check/parse the content */
    pload = ec_request_get_payload(srv, &pload_sz);

    first = strtok((char *) pload, ">");
    do
    {
        uri_tmp = strpbrk(first, "<");

        (void) ec_request_get_uri(srv, uri, &is_proxy);

        uri_res = strcat(uri, ++uri_tmp);

        CHAT("adding resource for: %s", uri_res);

        /* Create resource with all methods allowed. */
        dbg_err_ifm ((res = ec_resource_new(uri_res, mm, 3600)) == NULL,
                "resource creation failed");

        /* Get media type (if not specified default to text/plain. */
        if (ec_request_get_content_type(srv, &mt))
            mt = EC_MT_TEXT_PLAIN;

        /* Create new resource representation with the requested media type. */
        /* Each resource only has one representation in this implementation.
         * Use automatic ETag. */
        dbg_err_ifm (ec_resource_add_rep(res, (const uint8_t *) " ", 1, mt, NULL),
                "error adding representation for %s", uri_res);

        /* Attach resource to FS. */
        dbg_err_ifm (ec_filesys_put_resource(g_ctx.fs, res),
                "adding resource failed");
        res = NULL;

        /* Register the callback that will serve this URI.
         * XXX If we get an error here it's really a bad thing because
         * the resource has been already registered and we go into an
         * inconsistent state. */
        dbg_err_ifm (ec_register_cb(g_ctx.coap, uri_res, serve, NULL),
                "registering callback for %s failed", uri_res);

        first = NULL;
        uri[0] = '\0';
        first = strtok(NULL, ">");
    }
    while (first != NULL);

    /* 2.01 Created */
    (void) ec_response_set_code(srv, EC_CREATED);

    return EC_CBRC_READY;
err:
    if (res)
        ec_resource_free(res);
    return EC_CBRC_ERROR;
#endif
}

#if 0
ec_cbrc_t create(ec_server_t *srv, void *u0, struct timeval *u1, bool u2)
{
    uint8_t *pload;
    size_t pload_sz;
    ec_res_t *res = NULL;
    ec_method_t method;
    bool is_proxy = false;
    char uri[U_URI_STRMAX];
    ec_mt_t mt;
    ec_method_mask_t mm = EC_METHOD_MASK_ALL;

    u_unused_args(u0, u1, u2);

    /* Get the requested URI and method. */
    (void) ec_request_get_uri(srv, uri, &is_proxy);

    switch ((method = ec_server_get_method(srv)))
    {
        case EC_COAP_POST:
            (void) serve_post(srv, NULL);
            return EC_CBRC_READY;
        case EC_COAP_PUT:
            break;
        default:
            (void) ec_response_set_code(srv, EC_NOT_FOUND);
            return EC_CBRC_READY;
    }

    CHAT("adding resource for: %s", uri);

    /* Create resource with all methods allowed. */
    dbg_err_ifm((res = ec_resource_new(uri, mm, 3600)) == NULL,
            "resource creation failed");

    /* Get payload (may be empty/NULL). */
    pload = ec_request_get_payload(srv, &pload_sz);

    /* Get media type (if not specified default to text/plain. */
    if (ec_request_get_content_type(srv, &mt))
        mt = EC_MT_TEXT_PLAIN;

    /* Create new resource representation with the requested media type. */
    /* Each resource only has one representation in this implementation.
     * Use automatic ETag. */
    dbg_err_ifm (ec_resource_add_rep(res, pload, pload_sz, mt, NULL),
            "error adding representation for %s", uri);

    /* Attach resource to FS. */
    dbg_err_ifm (ec_filesys_put_resource(g_ctx.fs, res),
            "adding resource failed");
    res = NULL;

    /* Register the callback that will serve this URI.
     * XXX If we get an error here it's really a bad thing because
     * the resource has been already registered and we go into an
     * inconsistent state. */
    dbg_err_ifm (ec_register_cb(g_ctx.coap, uri, serve, NULL),
            "registering callback for %s failed", uri);

    /* 2.01 Created */
    (void) ec_response_set_code(srv, EC_CREATED);

    return EC_CBRC_READY;
err:
    (void) ec_response_set_code(srv, EC_INTERNAL_SERVER_ERROR);
    if (res)
        ec_resource_free(res);
    return EC_CBRC_ERROR;
}
Esempio n. 18
0
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, 
    LPSTR lpCmdLine, int nCmdShow)
{
    SERVICE_TABLE_ENTRY ServiceTable[] = 
    {
        {   ss_name, ServiceMain }, 
        {   NULL, NULL }    /* end of list */
    };
    int rc = 0;
    const char *name, *desc;

    memset(ctx, 0, sizeof(context_t));

    /* parse command line parameters (and set ctx vars). NOTE: this work only 
       if launched by command line, for services see ServiceMain */
    dbg_err_if(parse_opt(__argc, __argv));

    if(ctx->serv_op)
    {
        /* load config and initialize */
        dbg_err_if(app_init());

        /* set up service name and description reading from the config file */
        name = u_config_get_subkey_value(ctx->config, "daemon.name");
        if(name)
            u_strlcpy(ss_name, name, sizeof ss_name);

        desc = u_config_get_subkey_value(ctx->config, "daemon.description");
        if(desc)
            u_strlcpy(ss_desc, desc, sizeof ss_desc);

        if(ctx->serv_op == SERV_INSTALL)
            dbg_err_if(InstallService());
        else    
            dbg_err_if(RemoveService());
    } else if(ctx->daemon) {
        u_dbg("Starting in service mode...");
        /* StartServiceCtrlDispatcher does not return until the service 
           has stopped running...  */
        if(!StartServiceCtrlDispatcher(ServiceTable))
            warn_strerror(GetLastError());
    } else {
        /* load config and initialize */
        dbg_err_if(app_init());

        rc = app_run();
    }

    dbg_err_if(app_term());

    /* if debugging then call exit(3) because it's needed to gprof to dump 
       its stats file (gmon.out) */
    if(ctx->debug)
        return rc;

    /* don't use return because exit(3) will be called and we don't want
       FILE* buffers to be automatically flushed (klog_file_t will write same 
       lines more times, once by the parent process and N times by any child
       created when FILE buffer was not empty) */
    _exit(rc); 
err:
    app_term();

    if(ctx->debug) 
        return rc;
    _exit(EXIT_FAILURE);
}
Esempio n. 19
0
static int parse_opt(int argc, char **argv)
{
    int ret;
#ifdef OS_WIN
        #define CMDLINE_FORMAT "nhVFdiuf:cp:"
#else
        #define CMDLINE_FORMAT "nhVFdf:cp:"
#endif

    /* set defaults */
    ctx->daemon++;

    while((ret = getopt(argc, argv, CMDLINE_FORMAT)) != -1)
    {
        switch(ret)
        {
        case 'f':   /* source a config file */
            ctx->ext_config = u_strdup(optarg);
            dbg_err_if(ctx->ext_config == NULL);
            u_dbg("ext config: %s", ctx->ext_config);
            break;

        case 'c':   /* override config from command-line */
            ctx->cmd_config = 1;
            break;

        case 'p':   /* PID file */
            ctx->pid_file = u_strdup(optarg);
            dbg_err_if(ctx->pid_file == NULL);
            u_dbg("PID file: %s", ctx->pid_file);
            break;

        case 'd':   /* turn on debugging */
            ctx->debug++;
            break;

        case 'F':   /* run in foreground (not as a daemon/service) */
            ctx->daemon = 0;
            break;

        case 'V':   /* print version and exit */
            u_print_version_and_exit();
            break;

        case 'n':   /* don't chdir in daemon mode */
            ctx->nochdir = 1;
            break;

#ifdef OS_WIN
        case 'i':   /* install kloned service and exit */
            ctx->serv_op = SERV_INSTALL;
            break;

        case 'u':   /* uninstall kloned service and exit */
            ctx->serv_op = SERV_REMOVE;
            break;
#endif

        default:
        case 'h': 
            usage();
        }
    }

    ctx->narg = argc - optind;
    ctx->arg = argv + optind;

    return 0;
err:
    return ~0;
}
Esempio n. 20
0
static int example_dynamic_own_user (u_test_case_t *tc)
{
    u_hmap_opts_t opts;
    u_hmap_t *hmap = NULL;
    u_hmap_o_t *obj = NULL;

#define OBJ_FREE(obj) \
    if (obj) { \
        u_free(obj->key); \
        u_free(obj->val); \
        u_hmap_o_free(obj); \
        obj = NULL; \
    }
    
    u_dbg("example_dynamic_own_user()");

    u_hmap_opts_init(&opts);

    /* hmap owns data by default - change it */
    u_test_err_if (u_hmap_opts_unset_option(&opts, U_HMAP_OPTS_OWNSDATA));

    /* no overwrites allowed by default - change this too  */
    u_test_err_if (u_hmap_opts_unset_option(&opts, U_HMAP_OPTS_NO_OVERWRITE));

    u_test_err_if (u_hmap_new(&opts, &hmap));

    /* insert some sample elements */
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, (void *) u_strdup("EN"), 
                    (void *) u_strdup("Hello world!")), &obj));
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, (void *) u_strdup("IT"), 
                    (void *) u_strdup("Ciao mondo!")), &obj));
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, (void *) u_strdup("DE"), 
                    (void *) u_strdup("Hallo Welt!")), &obj));

    /* retrieve and print values to console */
    u_test_err_if (u_hmap_get(hmap, "IT", &obj)); 
    u_dbg("hmap['%s'] = %s", (char *) obj->key, (char *) obj->val);
    u_test_err_if (u_hmap_get(hmap, "DE", &obj)); 
    u_dbg("hmap['%s'] = %s", (char *) obj->key, (char *) obj->val);
    u_test_err_if (u_hmap_get(hmap, "EN", &obj)); 
    u_dbg("hmap['%s'] = %s", (char *) obj->key, (char *) obj->val);

    /* remove an element and replace it */
    u_test_err_if (u_hmap_del(hmap, "DE", &obj)); 
    OBJ_FREE(obj);

    /* check that it has been deleted */
    u_test_err_if (u_hmap_get(hmap, "DE", &obj) == 0); 

    /* replace with a new element and print it */
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, (void *) u_strdup("DE"), 
                    (void *) u_strdup("Auf Wiedersehen!")), NULL));
    u_test_err_if (u_hmap_put(hmap, u_hmap_o_new(hmap, (void *) u_strdup("DE"), 
                    (void *) u_strdup("Auf Wiedersehen2!")), &obj));
    OBJ_FREE(obj);
    u_test_err_if (u_hmap_get(hmap, "DE", &obj)); 
    u_dbg("hmap['%s'] = %s", (char *) obj->key, (char *) obj->val);

    u_hmap_del(hmap, "IT", &obj);
    OBJ_FREE(obj);
    u_hmap_del(hmap, "DE", &obj);
    OBJ_FREE(obj);
    u_hmap_del(hmap, "EN", &obj);
    OBJ_FREE(obj);

    /* free hmap (options and elements are freed automatically) */
    u_hmap_free(hmap);

    return U_TEST_SUCCESS;

err:
    U_FREEF(hmap, u_hmap_free);

    return U_TEST_FAILURE;
}
Esempio n. 21
0
static int example_easy_static (u_test_case_t *tc)
{
    u_hmap_opts_t opts;
    u_hmap_t *hmap = NULL;

    u_dbg("example_easy_static()");

    u_hmap_opts_init(&opts);

    /* no free function needed for static data */
    u_test_err_if (u_hmap_opts_set_val_freefunc(&opts, NULL));
    u_test_err_if (u_hmap_easy_new(&opts, &hmap));

    u_test_err_if (u_hmap_easy_put(hmap, "0", "zero"));
    u_test_err_if (u_hmap_easy_put(hmap, "1", "one"));
    u_test_err_if (u_hmap_easy_put(hmap, "2", "two"));
    u_test_err_if (u_hmap_easy_put(hmap, "3", "three"));

    /* value that doesn't exist */
    u_test_err_if (u_hmap_easy_get(hmap, "4") != NULL);

    /* test deletion */
    u_test_err_if (u_hmap_easy_del(hmap, "3"));
    u_test_err_if (u_hmap_easy_get(hmap, "3") != NULL);
    u_test_err_if (u_hmap_easy_put(hmap, "3", "THREE"));

#ifdef DEBUG_HEAVY
    u_hmap_dbg(hmap);
#endif

    /* print out all values */
    u_test_err_if (strcmp(u_hmap_easy_get(hmap, "0"), "zero") != 0);
    u_test_err_if (strcmp(u_hmap_easy_get(hmap, "1"), "one") != 0);
    u_test_err_if (strcmp(u_hmap_easy_get(hmap, "2"), "two") != 0);
    u_test_err_if (strcmp(u_hmap_easy_get(hmap, "3"), "THREE") != 0);

    /* test overwrite - should fail */
    u_test_err_if (u_hmap_easy_put(hmap, "2", "TWO") == 0);
    u_test_err_if (strcmp(u_hmap_easy_get(hmap, "2"), "two") != 0);

    U_FREEF(hmap, u_hmap_easy_free);

    /* make a new hmap that _allows_ overwrite */
    u_test_err_if (u_hmap_opts_unset_option(&opts, U_HMAP_OPTS_NO_OVERWRITE));
    u_test_err_if (u_hmap_easy_new(&opts, &hmap));

    /* put elements */
    u_test_err_if (u_hmap_easy_put(hmap, "a", "alpha"));
    u_test_err_if (u_hmap_easy_put(hmap, "b", "beta"));
    u_test_err_if (u_hmap_easy_put(hmap, "a", "ALPHA"));

#ifdef DEBUG_HEAVY
    u_hmap_dbg(hmap);
#endif

    /* check elements */
    u_test_err_if (strcmp(u_hmap_easy_get(hmap, "a"), "ALPHA") != 0);
    u_test_err_if (strcmp(u_hmap_easy_get(hmap, "b"), "beta") != 0);
    
    /* free hmap (options and elements are freed automatically) */
    u_hmap_easy_free(hmap);

    return U_TEST_SUCCESS;
err:
    U_FREEF(hmap, u_hmap_easy_free);

    return U_TEST_FAILURE;
}