Example #1
0
/** Performs the libcurl initialisation of the thread
 *
 * @param[in] thread		to initialise.
 * @param[in] multiplex		Run multiple requests over the same connection simultaneously.
 * @return
 *	- 0 on success.
 *	- -1 on error.
 */
int rest_io_init(rlm_rest_thread_t *thread,
#ifndef CURLPIPE_MULTIPLEX
		 UNUSED
#endif
		 bool multiplex)
{
	CURLMcode	ret;
	CURLM		*mandle;
	char const	*option = "unknown";

	mandle = thread->mandle = curl_multi_init();
	if (!thread->mandle) {
		ERROR("Curl multi-handle instantiation failed");
		return -1;
	}

	SET_OPTION(CURLMOPT_TIMERFUNCTION, _rest_io_timer_modify);
	SET_OPTION(CURLMOPT_TIMERDATA, thread);

	SET_OPTION(CURLMOPT_SOCKETFUNCTION, _rest_io_event_modify);
	SET_OPTION(CURLMOPT_SOCKETDATA, thread);

#ifdef CURLPIPE_MULTIPLEX
	SET_OPTION(CURLMOPT_PIPELINING, multiplex ? CURLPIPE_MULTIPLEX : CURLPIPE_NOTHING);
#endif

	return 0;

error:
	ERROR("Failed setting curl option %s: %s (%i)", option, curl_multi_strerror(ret), ret);

	return -1;
}
Example #2
0
static void
apply_vbr_preset(lame_global_flags * gfp, int a, int enforce)
{
    vbr_presets_t const *vbr_preset = get_vbr_preset(lame_get_VBR(gfp));
    float   x = gfp->VBR_q_frac;
    vbr_presets_t p = vbr_preset[a];
    vbr_presets_t q = vbr_preset[a + 1];
    vbr_presets_t const *set = &p;

    NOOP(vbr_q);
    NOOP(quant_comp);
    NOOP(quant_comp_s);
    NOOP(expY);
    LERP(st_lrm);
    LERP(st_s);
    LERP(masking_adj);
    LERP(masking_adj_short);
    LERP(ath_lower);
    LERP(ath_curve);
    LERP(ath_sensitivity);
    LERP(interch);
    NOOP(safejoint);
    LERP(sfb21mod);
    LERP(msfix);
    LERP(minval);
    LERP(ath_fixpoint);

    (void) lame_set_VBR_q(gfp, set->vbr_q);
    SET_OPTION(quant_comp, set->quant_comp, -1);
    SET_OPTION(quant_comp_short, set->quant_comp_s, -1);
    if (set->expY) {
        (void) lame_set_experimentalY(gfp, set->expY);
    }
    SET_OPTION(short_threshold_lrm, set->st_lrm, -1);
    SET_OPTION(short_threshold_s, set->st_s, -1);
    SET_OPTION(maskingadjust, set->masking_adj, 0);
    SET_OPTION(maskingadjust_short, set->masking_adj_short, 0);
    if (lame_get_VBR(gfp) == vbr_mt || lame_get_VBR(gfp) == vbr_mtrh) {
        lame_set_ATHtype(gfp, 5);
    }
    SET_OPTION(ATHlower, set->ath_lower, 0);
    SET_OPTION(ATHcurve, set->ath_curve, -1);
    SET_OPTION(athaa_sensitivity, set->ath_sensitivity, 0);
    if (set->interch > 0) {
        SET_OPTION(interChRatio, set->interch, -1);
    }

    /* parameters for which there is no proper set/get interface */
    if (set->safejoint > 0) {
        (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2);
    }
    if (set->sfb21mod > 0) {
        int const nsp = lame_get_exp_nspsytune(gfp);
        int const val = (nsp >> 20) & 63;
        if (val == 0) {
            int const sf21mod = (set->sfb21mod << 20) | nsp;
            (void) lame_set_exp_nspsytune(gfp, sf21mod);
        }
    }
Example #3
0
/* block allocator related options are parsed here */
int reiserfs_parse_alloc_options(struct super_block * s, char * options)
{
    char * this_char, * value;

    REISERFS_SB(s)->s_alloc_options.bits = 0; /* clear default settings */

    while ( (this_char = strsep (&options, ":")) != NULL ) {
        if ((value = strchr (this_char, '=')) != NULL)
            *value++ = 0;

        if (!strcmp(this_char, "concentrating_formatted_nodes")) {
            int temp;
            SET_OPTION(concentrating_formatted_nodes);
            temp = (value && *value) ? simple_strtoul (value, &value, 0) : 10;
            if (temp <= 0 || temp > 100) {
                REISERFS_SB(s)->s_alloc_options.border = 10;
            } else {
                REISERFS_SB(s)->s_alloc_options.border = 100 / temp;
            }
            continue;
        }
        if (!strcmp(this_char, "displacing_large_files")) {
            SET_OPTION(displacing_large_files);
            REISERFS_SB(s)->s_alloc_options.large_file_size =
                (value && *value) ? simple_strtoul (value, &value, 0) : 16;
            continue;
        }
        if (!strcmp(this_char, "displacing_new_packing_localities")) {
            SET_OPTION(displacing_new_packing_localities);
            continue;
        };

        if (!strcmp(this_char, "old_hashed_relocation")) {
            SET_OPTION(old_hashed_relocation);
            continue;
        }

        if (!strcmp(this_char, "new_hashed_relocation")) {
            SET_OPTION(new_hashed_relocation);
            continue;
        }

        if (!strcmp(this_char, "dirid_groups")) {
            SET_OPTION(dirid_groups);
            continue;
        }
        if (!strcmp(this_char, "oid_groups")) {
            SET_OPTION(oid_groups);
            continue;
        }
        if (!strcmp(this_char, "packing_groups")) {
            SET_OPTION(packing_groups);
            continue;
        }
        if (!strcmp(this_char, "hashed_formatted_nodes")) {
            SET_OPTION(hashed_formatted_nodes);
            continue;
        }

        if (!strcmp(this_char, "skip_busy")) {
            SET_OPTION(skip_busy);
            continue;
        }

        if (!strcmp(this_char, "hundredth_slices")) {
            SET_OPTION(hundredth_slices);
            continue;
        }

        if (!strcmp(this_char, "old_way")) {
            SET_OPTION(old_way);
            continue;
        }

        if (!strcmp(this_char, "displace_based_on_dirid")) {
            SET_OPTION(displace_based_on_dirid);
            continue;
        }

        if (!strcmp(this_char, "preallocmin")) {
            REISERFS_SB(s)->s_alloc_options.preallocmin =
                (value && *value) ? simple_strtoul (value, &value, 0) : 4;
            continue;
        }

        if (!strcmp(this_char, "preallocsize")) {
            REISERFS_SB(s)->s_alloc_options.preallocsize =
                (value && *value) ? simple_strtoul (value, &value, 0) : PREALLOCATION_SIZE;
            continue;
        }

        reiserfs_warning (s, "zam-4001: %s : unknown option - %s",
                          __FUNCTION__ , this_char);
        return 1;
    }

    reiserfs_warning (s, "allocator options = [%08x]\n", SB_ALLOC_OPTS(s));
    return 0;
}
/*----------------------------------------------------------------------------*/
static
int
coap_receive(void)
{
    coap_error_code = NO_ERROR;

    PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());

    /* Static declaration reduces stack peaks and program code size. */
    static coap_packet_t message[1]; /* This way the packet can be treated as pointer as usual. */
    static coap_packet_t response[1];
    static coap_transaction_t *transaction = NULL;

    if (uip_newdata()) {

        PRINTF("receiving UDP datagram from: ");
        PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
        PRINTF(":%u\n  Length: %u\n  Data: ", uip_ntohs(UIP_UDP_BUF->srcport), uip_datalen() );
        PRINTBITS(uip_appdata, uip_datalen());
        PRINTF("\n");

        coap_error_code = coap_parse_message(message, uip_appdata, uip_datalen());

        if (coap_error_code==NO_ERROR)
        {

            /*TODO duplicates suppression, if required by application */

            PRINTF("  Parsed: v %u, t %u, oc %u, c %u, mid %u\n", message->version, message->type, message->option_count, message->code, message->mid);
            PRINTF("  URL: %.*s\n", message->uri_path_len, message->uri_path);
            PRINTF("  Payload: %.*s\n", message->payload_len, message->payload);

            /* Handle requests. */
            if (message->code >= COAP_GET && message->code <= COAP_DELETE)
            {
                /* Use transaction buffer for response to confirmable request. */
                if ( (transaction = coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport)) )
                {
                    uint32_t block_num = 0;
                    uint16_t block_size = REST_MAX_CHUNK_SIZE;
                    uint32_t block_offset = 0;
                    int32_t new_offset = 0;

                    /* prepare response */
                    if (message->type==COAP_TYPE_CON)
                    {
                        /* Reliable CON requests are answered with an ACK. */
                        coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, message->mid);
                    }
                    else
                    {
                        /* Unreliable NON requests are answered with a NON as well. */
                        coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());
                    }

                    /* resource handlers must take care of different handling (e.g., TOKEN_OPTION_REQUIRED_240) */
                    if (IS_OPTION(message, COAP_OPTION_TOKEN))
                    {
                        coap_set_header_token(response, message->token, message->token_len);
                        SET_OPTION(response, COAP_OPTION_TOKEN);
                    }

                    /* get offset for blockwise transfers */
                    if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset))
                    {
                        PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
                        block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
                        new_offset = block_offset;
                    }

                    /* Invoke resource handler. */
                    if (service_cbk)
                    {
                        /* Call REST framework and check if found and allowed. */
                        if (service_cbk(message, response, transaction->packet+COAP_MAX_HEADER_SIZE, block_size, &new_offset))
                        {
                            if (coap_error_code==NO_ERROR)
                            {
                                /* Apply blockwise transfers. */
                                if ( IS_OPTION(message, COAP_OPTION_BLOCK1) && response->code<BAD_REQUEST_4_00 && !IS_OPTION(response, COAP_OPTION_BLOCK1) )
                                {
                                    PRINTF("Block1 NOT IMPLEMENTED\n");

                                    coap_error_code = NOT_IMPLEMENTED_5_01;
                                    coap_error_message = "NoBlock1Support";
                                }
                                else if ( IS_OPTION(message, COAP_OPTION_BLOCK2) )
                                {
                                    /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
                                    if (new_offset==block_offset)
                                    {
                                        PRINTF("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size);
                                        if (block_offset >= response->payload_len)
                                        {
                                            PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n");

                                            response->code = BAD_OPTION_4_02;
                                            coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
                                        }
                                        else
                                        {
                                            coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size);
                                            coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
                                        } /* if (valid offset) */
                                    }
                                    else
                                    {
                                        /* resource provides chunk-wise data */
                                        PRINTF("Blockwise: blockwise resource, new offset %ld\n", new_offset);
                                        coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size);
                                        if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size);
                                    } /* if (resource aware of blockwise) */
                                }
                                else if (new_offset!=0)
                                {
                                    PRINTF("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE);

                                    coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE);
                                    coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE));
                                } /* if (blockwise request) */
                            } /* no errors/hooks */
                        } /* successful service callback */

                        /* Serialize response. */
                        if (coap_error_code==NO_ERROR)
                        {
                            if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0)
                            {
                                coap_error_code = PACKET_SERIALIZATION_ERROR;
                            }
                        }

                    }
                    else
                    {
                        coap_error_code = NOT_IMPLEMENTED_5_01;
                        coap_error_message = "NoServiceCallbck"; // no a to fit 16 bytes
                    } /* if (service callback) */

                } else {
                    coap_error_code = SERVICE_UNAVAILABLE_5_03;
                    coap_error_message = "NoFreeTraBuffer";
                } /* if (transaction buffer) */
            }
            else
            {
                /* Responses */

                if (message->type==COAP_TYPE_ACK)
                {
                    PRINTF("Received ACK\n");
                }
                else if (message->type==COAP_TYPE_RST)
                {
                    PRINTF("Received RST\n");
                    /* Cancel possible subscriptions. */
                    coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->mid);
                }

                transaction = coap_get_transaction_by_mid(message->mid);
                if (message->type != COAP_TYPE_CON && transaction)
                {
                    /* Free transaction memory before callback, as it may create a new transaction. */
                    restful_response_handler callback = transaction->callback;
                    void *callback_data = transaction->callback_data;
                    coap_clear_transaction(transaction);

                    /* Check if someone registered for the response */
                    if (callback) {
                        callback(callback_data, message);
                    }
                } /* if (ACKed transaction) */
                /* Observe notification */
                if ((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) \
                        && IS_OPTION(message, COAP_OPTION_OBSERVE)) {
                    PRINTF("Observe [%u]\n", message->observe);
                    coap_handle_notification(&UIP_IP_BUF->srcipaddr,                     \
                                             UIP_UDP_BUF->srcport, message);
                }
                transaction = NULL;

            } /* Request or Response */

        } /* if (parsed correctly) */

        if (coap_error_code==NO_ERROR)
        {
            if (transaction) coap_send_transaction(transaction);
        }
        else if (coap_error_code==MANUAL_RESPONSE)
        {
            PRINTF("Clearing transaction for manual response");
            coap_clear_transaction(transaction);
        }
        else
        {
            PRINTF("ERROR %u: %s\n", coap_error_code, coap_error_message);
            coap_clear_transaction(transaction);

            /* Set to sendable error code. */
            if (coap_error_code >= 192)
            {
                coap_error_code = INTERNAL_SERVER_ERROR_5_00;
            }
            /* Reuse input buffer for error message. */
            coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->mid);
            coap_set_payload(message, coap_error_message, strlen(coap_error_message));
            coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, uip_appdata, coap_serialize_message(message, uip_appdata));
        }
    } /* if (new data) */

    return coap_error_code;
}
Example #5
0
int lwm2m_dm_write_attributes(lwm2m_context_t * contextP,
                              uint16_t clientID,
                              lwm2m_uri_t * uriP,
                              lwm2m_attributes_t * attrP,
                              lwm2m_result_callback_t callback,
                              void * userData)
{
#define _PRV_BUFFER_SIZE 32
    lwm2m_client_t * clientP;
    lwm2m_transaction_t * transaction;
    coap_packet_t * coap_pkt;
    uint8_t buffer[_PRV_BUFFER_SIZE];
    size_t length;

    LOG_ARG("clientID: %d", clientID);
    LOG_URI(uriP);
    if (attrP == NULL) return COAP_400_BAD_REQUEST;

    if (0 != (attrP->toSet & attrP->toClear)) return COAP_400_BAD_REQUEST;
    if (0 != (attrP->toSet & ATTR_FLAG_NUMERIC) && !LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST;
    if (ATTR_FLAG_NUMERIC == (attrP->toSet & ATTR_FLAG_NUMERIC)
     && (attrP->lessThan + 2 * attrP->step >= attrP->greaterThan)) return COAP_400_BAD_REQUEST;

    clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
    if (clientP == NULL) return COAP_404_NOT_FOUND;

    transaction = transaction_new(clientP->sessionH, COAP_PUT, clientP->altPath, uriP, contextP->nextMID++, 4, NULL);
    if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;

    if (callback != NULL)
    {
        dm_data_t * dataP;

        dataP = (dm_data_t *)lwm2m_malloc(sizeof(dm_data_t));
        if (dataP == NULL)
        {
            transaction_free(transaction);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }
        memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t));
        dataP->clientID = clientP->internalID;
        dataP->callback = callback;
        dataP->userData = userData;

        transaction->callback = prv_resultCallback;
        transaction->userData = (void *)dataP;
    }

    coap_pkt = (coap_packet_t *)transaction->message;
    free_multi_option(coap_pkt->uri_query);
    if (attrP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
    {
        memcpy(buffer, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN);
        length = utils_intToText(attrP->minPeriod, buffer + ATTR_MIN_PERIOD_LEN, _PRV_BUFFER_SIZE - ATTR_MIN_PERIOD_LEN);
        if (length == 0)
        {
            transaction_free(transaction);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }
        coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_MIN_PERIOD_LEN + length, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
    {
        memcpy(buffer, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN);
        length = utils_intToText(attrP->maxPeriod, buffer + ATTR_MAX_PERIOD_LEN, _PRV_BUFFER_SIZE - ATTR_MAX_PERIOD_LEN);
        if (length == 0)
        {
            transaction_free(transaction);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }
        coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_MAX_PERIOD_LEN + length, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN)
    {
        memcpy(buffer, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN);
        length = utils_floatToText(attrP->greaterThan, buffer + ATTR_GREATER_THAN_LEN, _PRV_BUFFER_SIZE - ATTR_GREATER_THAN_LEN);
        if (length == 0)
        {
            transaction_free(transaction);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }
        coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_GREATER_THAN_LEN + length, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toSet & LWM2M_ATTR_FLAG_LESS_THAN)
    {
        memcpy(buffer, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN);
        length = utils_floatToText(attrP->lessThan, buffer + ATTR_LESS_THAN_LEN, _PRV_BUFFER_SIZE - ATTR_LESS_THAN_LEN);
        if (length == 0)
        {
            transaction_free(transaction);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }
        coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_LESS_THAN_LEN + length, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toSet & LWM2M_ATTR_FLAG_STEP)
    {
        memcpy(buffer, ATTR_STEP_STR, ATTR_STEP_LEN);
        length = utils_floatToText(attrP->step, buffer + ATTR_STEP_LEN, _PRV_BUFFER_SIZE - ATTR_STEP_LEN);
        if (length == 0)
        {
            transaction_free(transaction);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }
        coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_STEP_LEN + length, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toClear & LWM2M_ATTR_FLAG_MIN_PERIOD)
    {
        coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN -1, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toClear & LWM2M_ATTR_FLAG_MAX_PERIOD)
    {
        coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN - 1, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toClear & LWM2M_ATTR_FLAG_GREATER_THAN)
    {
        coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN - 1, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toClear & LWM2M_ATTR_FLAG_LESS_THAN)
    {
        coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN - 1, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }
    if (attrP->toClear & LWM2M_ATTR_FLAG_STEP)
    {
        coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t*)ATTR_STEP_STR, ATTR_STEP_LEN - 1, 0);
        SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
    }

    contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);

    return transaction_send(contextP, transaction);
}
Example #6
0
static int parse_who_options(aClient *sptr, int argc, char **argv)
{
char *s = argv[0];
int what = WHO_ADD;
int i = 1;

/* A few helper macro's because this is used a lot, added during recode by Syzop. */

/** function requiress a parameter: check if there's one, if not: return -1. */
#define REQUIRE_PARAM() { if (i >= argc) { \
                           who_sendhelp(sptr); \
                           return -1; \
                      } } while(0);
/** set option 'x' depending on 'what' (add/want or del/dontwant) */
#define SET_OPTION(x) { if (what == WHO_ADD) \
                           x = WHO_WANT; \
                      else \
                           x = WHO_DONTWANT; \
                      } while(0);
/** Eat a param, set the param in memory and set the option to want or dontwant */
#define DOIT(x,y) { REQUIRE_PARAM(); x = argv[i]; SET_OPTION(y); i++; } while(0);

	if (*s != '-' && *s != '+')
		return 0;

	while (*s)
 	{
		switch (*s)
		{
			case '+':
	  			what = WHO_ADD;
	  			break;
			case '-':
				what = WHO_DEL;
				break;
			case 'a':
				SET_OPTION(wfl.want_away);
				break;
			case 'c':
				DOIT(wfl.channel, wfl.want_channel);
				break;
			case 'g':
				REQUIRE_PARAM()
				if (!IsAnOper(sptr))
					break; /* oper-only */
				wfl.gecos = argv[i];
				SET_OPTION(wfl.want_gecos);
				i++;
				break;
			case 's':
				DOIT(wfl.server, wfl.want_server);
				break;
			case 'h':
				DOIT(wfl.host, wfl.want_host);
				break;
			case 'i':
				REQUIRE_PARAM()
				if (!IsAnOper(sptr))
					break; /* oper-only */
				wfl.ip = argv[i];
				SET_OPTION(wfl.want_ip);
				i++;
				break;
			case 'n':
				DOIT(wfl.nick, wfl.want_nick);
				break;
			case 'u':
				DOIT(wfl.user, wfl.want_user);
				break;
			case 'm':
				REQUIRE_PARAM()
				{
					char *s = argv[i];
					int *umodes;

					if (what == WHO_ADD)
						umodes = &wfl.umodes_want;
					else
						umodes = &wfl.umodes_dontwant;

					while (*s)
					{
					int i;
						for (i = 0; i <= Usermode_highest; i++)
							if (*s == Usermode_Table[i].flag)
							{
								*umodes |= Usermode_Table[i].mode;
								break;
							}
					s++;
					}

					if (!IsAnOper(sptr))
						*umodes = *umodes & (UMODE_OPER | UMODE_LOCOP | UMODE_SADMIN | UMODE_ADMIN | UMODE_COADMIN | UMODE_NETADMIN | UMODE_BOT);
					if (*umodes == 0)
						return -1;
				}
				i++;
				break;
			case 'M':
				SET_OPTION(wfl.common_channels_only);
				break;
			case 'R':
				if (!IsAnOper(sptr))
					break;
				if (what == WHO_ADD)
					who_flags |= WF_REALHOST;
				else
					who_flags &= ~WF_REALHOST;
				break;
			case 'I':
				if (!IsAnOper(sptr))
					break;
				if (what == WHO_ADD)
					who_flags |= WF_IP;
				
				else
					who_flags &= ~WF_IP;
				break;
			default:
				who_sendhelp(sptr);
				return -1;
		}
		s++;
    }

  return i;
#undef REQUIRE_PARAM
#undef SET_OPTION
#undef DOIT
}
Example #7
0
static int start_write(sox_format_t * const ft)
{
  priv_t * p = (priv_t *)ft->priv;
  FLAC__StreamEncoderState status;
  unsigned compression_level = MAX_COMPRESSION; /* Default to "best" */

  if (ft->encoding.compression != HUGE_VAL) {
    compression_level = ft->encoding.compression;
    if (compression_level != ft->encoding.compression ||
        compression_level > MAX_COMPRESSION) {
      lsx_fail_errno(ft, SOX_EINVAL,
                 "FLAC compression level must be a whole number from 0 to %i",
                 MAX_COMPRESSION);
      return SOX_EOF;
    }
  }

  p->encoder = FLAC__stream_encoder_new();
  if (p->encoder == NULL) {
    lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder instance");
    return SOX_EOF;
  }
  p->decoded_samples = lsx_malloc(sox_globals.bufsiz * sizeof(FLAC__int32));

  p->bits_per_sample = ft->encoding.bits_per_sample;

  lsx_report("encoding at %i bits per sample", p->bits_per_sample);

  FLAC__stream_encoder_set_channels(p->encoder, ft->signal.channels);
  FLAC__stream_encoder_set_bits_per_sample(p->encoder, p->bits_per_sample);
  FLAC__stream_encoder_set_sample_rate(p->encoder, (unsigned)(ft->signal.rate + .5));

  { /* Check if rate is streamable: */
    static const unsigned streamable_rates[] =
      {8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
    size_t i;
    sox_bool streamable = sox_false;
    for (i = 0; !streamable && i < array_length(streamable_rates); ++i)
       streamable = (streamable_rates[i] == ft->signal.rate);
    if (!streamable) {
      lsx_report("non-standard rate; output may not be streamable");
      FLAC__stream_encoder_set_streamable_subset(p->encoder, sox_false);
    }
  }

#if FLAC_API_VERSION_CURRENT >= 10
  FLAC__stream_encoder_set_compression_level(p->encoder, compression_level);
#else
  {
    static struct {
      unsigned blocksize;
      FLAC__bool do_exhaustive_model_search;
      FLAC__bool do_mid_side_stereo;
      FLAC__bool loose_mid_side_stereo;
      unsigned max_lpc_order;
      unsigned max_residual_partition_order;
      unsigned min_residual_partition_order;
    } const options[MAX_COMPRESSION + 1] = {
      {1152, sox_false, sox_false, sox_false, 0, 2, 2},
      {1152, sox_false, sox_true, sox_true, 0, 2, 2},
      {1152, sox_false, sox_true, sox_false, 0, 3, 0},
      {4608, sox_false, sox_false, sox_false, 6, 3, 3},
      {4608, sox_false, sox_true, sox_true, 8, 3, 3},
      {4608, sox_false, sox_true, sox_false, 8, 3, 3},
      {4608, sox_false, sox_true, sox_false, 8, 4, 0},
      {4608, sox_true, sox_true, sox_false, 8, 6, 0},
      {4608, sox_true, sox_true, sox_false, 12, 6, 0},
    };
#define SET_OPTION(x) do {\
  lsx_report(#x" = %i", options[compression_level].x); \
  FLAC__stream_encoder_set_##x(p->encoder, options[compression_level].x);\
} while (0)
    SET_OPTION(blocksize);
    SET_OPTION(do_exhaustive_model_search);
    SET_OPTION(max_lpc_order);
    SET_OPTION(max_residual_partition_order);
    SET_OPTION(min_residual_partition_order);
    if (ft->signal.channels == 2) {
      SET_OPTION(do_mid_side_stereo);
      SET_OPTION(loose_mid_side_stereo);
    }
#undef SET_OPTION
  }
#endif

  if (ft->signal.length != 0) {
    FLAC__stream_encoder_set_total_samples_estimate(p->encoder, (FLAC__uint64)(ft->signal.length / ft->signal.channels));

    p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
    if (p->metadata[p->num_metadata] == NULL) {
      lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table template");
      return SOX_EOF;
    }
    {
#if FLAC_API_VERSION_CURRENT >= 8
      if (!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(p->metadata[p->num_metadata], (unsigned)(10 * ft->signal.rate + .5), (FLAC__uint64)(ft->signal.length/ft->signal.channels))) {
#else
      size_t samples = 10 * ft->signal.rate;
      size_t total_samples = ft->signal.length/ft->signal.channels;
      if (!FLAC__metadata_object_seektable_template_append_spaced_points(p->metadata[p->num_metadata], total_samples / samples + (total_samples % samples != 0), (FLAC__uint64)total_samples)) {
#endif
        lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table points");
        return SOX_EOF;
      }
    }
    p->metadata[p->num_metadata]->is_last = sox_false; /* the encoder will set this for us */
    ++p->num_metadata;
  }

  if (ft->oob.comments) {     /* Make the comment structure */
    FLAC__StreamMetadata_VorbisComment_Entry entry;
    int i;

    p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
    for (i = 0; ft->oob.comments[i]; ++i) {
      static const char prepend[] = "Comment=";
      char * text = lsx_calloc(strlen(prepend) + strlen(ft->oob.comments[i]) + 1, sizeof(*text));
      /* Prepend `Comment=' if no field-name already in the comment */
      if (!strchr(ft->oob.comments[i], '='))
        strcpy(text, prepend);
      entry.entry = (FLAC__byte *) strcat(text, ft->oob.comments[i]);
      entry.length = strlen(text);
      FLAC__metadata_object_vorbiscomment_append_comment(p->metadata[p->num_metadata], entry, /*copy= */ sox_true);
      free(text);
    }
    ++p->num_metadata;
  }

  if (p->num_metadata)
    FLAC__stream_encoder_set_metadata(p->encoder, p->metadata, p->num_metadata);

#if FLAC_API_VERSION_CURRENT <= 7
  FLAC__stream_encoder_set_write_callback(p->encoder, flac_stream_encoder_write_callback);
  FLAC__stream_encoder_set_metadata_callback(p->encoder, flac_stream_encoder_metadata_callback);
  FLAC__stream_encoder_set_client_data(p->encoder, ft);
  status = FLAC__stream_encoder_init(p->encoder);
#else
  status = FLAC__stream_encoder_init_stream(p->encoder, flac_stream_encoder_write_callback,
      flac_stream_encoder_seek_callback, flac_stream_encoder_tell_callback, flac_stream_encoder_metadata_callback, ft);
#endif

  if (status != FLAC__STREAM_ENCODER_OK) {
    lsx_fail_errno(ft, SOX_EINVAL, "%s", FLAC__StreamEncoderStateString[status]);
    return SOX_EOF;
  }
  return SOX_SUCCESS;
}



static size_t write_samples(sox_format_t * const ft, sox_sample_t const * const sampleBuffer, size_t const len)
{
  priv_t * p = (priv_t *)ft->priv;
  unsigned i;

  for (i = 0; i < len; ++i) {
    long pcm = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i], ft->clips);
    p->decoded_samples[i] = pcm >> (32 - p->bits_per_sample);
    switch (p->bits_per_sample) {
      case  8: p->decoded_samples[i] =
          SOX_SAMPLE_TO_SIGNED_8BIT(sampleBuffer[i], ft->clips);
        break;
      case 16: p->decoded_samples[i] =
          SOX_SAMPLE_TO_SIGNED_16BIT(sampleBuffer[i], ft->clips);
        break;
      case 24: p->decoded_samples[i] = /* sign extension: */
          SOX_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],ft->clips) << 8;
        p->decoded_samples[i] >>= 8;
        break;
      case 32: p->decoded_samples[i] =
          SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i],ft->clips);
        break;
    }
  }
  FLAC__stream_encoder_process_interleaved(p->encoder, p->decoded_samples, (unsigned) len / ft->signal.channels);
  return FLAC__stream_encoder_get_state(p->encoder) == FLAC__STREAM_ENCODER_OK ? len : 0;
}
static int
apply_abr_preset(lame_global_flags * gfp, int preset, int enforce)
{
    int     k;

    typedef struct {
        int     abr_kbps;
        int     quant_comp;
        int     quant_comp_s;
        int     safejoint;
        FLOAT   nsmsfix;
        FLOAT   st_lrm;      /*short threshold */
        FLOAT   st_s;
        FLOAT   nsbass;
        FLOAT   scale;
        FLOAT   masking_adj;
        FLOAT   ath_lower;
        FLOAT   ath_curve;
        FLOAT   interch;
        int     sfscale;
    } abr_presets_t;


    /* *INDENT-OFF* */

    /* 
     *  Switch mappings for ABR mode
     */
    const abr_presets_t abr_switch_map[] = {        
    /* kbps  quant q_s safejoint nsmsfix st_lrm  st_s  ns-bass scale   msk ath_lwr ath_curve  interch , sfscale */
      {  8,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,  -30.0,     11,    0.0012,        1}, /*   8, impossible to use in stereo */
      { 16,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,  -25.0,     11,    0.0010,        1}, /*  16 */
      { 24,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,  -20.0,     11,    0.0010,        1}, /*  24 */
      { 32,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,  -15.0,     11,    0.0010,        1}, /*  32 */
      { 40,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,  -10.0,     11,    0.0009,        1}, /*  40 */
      { 48,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,  -10.0,     11,    0.0009,        1}, /*  48 */
      { 56,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,   -6.0,     11,    0.0008,        1}, /*  56 */
      { 64,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,   -2.0,     11,    0.0008,        1}, /*  64 */
      { 80,     9,  9,        0,      0,  6.60,  145,       0, 0.95,    0,     .0,      8,    0.0007,        1}, /*  80 */
      { 96,     9,  9,        0,   2.50,  6.60,  145,       0, 0.95,    0,    1.0,      5.5,  0.0006,        1}, /*  96 */
      {112,     9,  9,        0,   2.25,  6.60,  145,       0, 0.95,    0,    2.0,      4.5,  0.0005,        1}, /* 112 */
      {128,     9,  9,        0,   1.95,  6.40,  140,       0, 0.95,    0,    3.0,      4,    0.0002,        1}, /* 128 */
      {160,     9,  9,        1,   1.79,  6.00,  135,       0, 0.95,   -2,    5.0,      3.5,  0,             1}, /* 160 */
      {192,     9,  9,        1,   1.49,  5.60,  125,       0, 0.97,   -4,    7.0,      3,    0,             0}, /* 192 */
      {224,     9,  9,        1,   1.25,  5.20,  125,       0, 0.98,   -6,    9.0,      2,    0,             0}, /* 224 */
      {256,     9,  9,        1,   0.97,  5.20,  125,       0, 1.00,   -8,   10.0,      1,    0,             0}, /* 256 */
      {320,     9,  9,        1,   0.90,  5.20,  125,       0, 1.00,  -10,   12.0,      0,    0,             0}  /* 320 */
    };

    /* *INDENT-ON* */

    /* Variables for the ABR stuff */
    int     r;
    int     actual_bitrate = preset;

    r = nearestBitrateFullIndex(preset);


    (void) lame_set_VBR(gfp, vbr_abr);
    (void) lame_set_VBR_mean_bitrate_kbps(gfp, (actual_bitrate));
    (void) lame_set_VBR_mean_bitrate_kbps(gfp, min_int(lame_get_VBR_mean_bitrate_kbps(gfp), 320));
    (void) lame_set_VBR_mean_bitrate_kbps(gfp, max_int(lame_get_VBR_mean_bitrate_kbps(gfp), 8));
    (void) lame_set_brate(gfp, lame_get_VBR_mean_bitrate_kbps(gfp));


    /* parameters for which there is no proper set/get interface */
    if (abr_switch_map[r].safejoint > 0)
        (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); /* safejoint */

    if (abr_switch_map[r].sfscale > 0)
        (void) lame_set_sfscale(gfp, 1);

    /* ns-bass tweaks */
    if (fabs(abr_switch_map[r].nsbass) > 0) {
        k = (int) (abr_switch_map[r].nsbass * 4);
        if (k < 0)
            k += 64;
        (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 2));
    }




    SET_OPTION(quant_comp, abr_switch_map[r].quant_comp, -1);
    SET_OPTION(quant_comp_short, abr_switch_map[r].quant_comp_s, -1);

    SET_OPTION(msfix, abr_switch_map[r].nsmsfix, -1);

    SET_OPTION(short_threshold_lrm, abr_switch_map[r].st_lrm, -1);
    SET_OPTION(short_threshold_s, abr_switch_map[r].st_s, -1);

    /* ABR seems to have big problems with clipping, especially at low bitrates */
    /* so we compensate for that here by using a scale value depending on bitrate */
    SET_OPTION(scale, abr_switch_map[r].scale, -1);

    SET_OPTION(maskingadjust, abr_switch_map[r].masking_adj, 0);
    if (abr_switch_map[r].masking_adj > 0) {
        SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * .9, 0);
    }
    else {
        SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * 1.1, 0);
    }


    SET_OPTION(ATHlower, abr_switch_map[r].ath_lower, 0);
    SET_OPTION(ATHcurve, abr_switch_map[r].ath_curve, -1);

    SET_OPTION(interChRatio, abr_switch_map[r].interch, -1);


    return preset;
}
static void
apply_vbr_preset(lame_global_flags * gfp, int a, int enforce)
{
    vbr_presets_t const *vbr_preset = lame_get_VBR(gfp) == vbr_rh ? &vbr_old_switch_map[0]
        : &vbr_psy_switch_map[0];
    float   x = gfp->VBR_q_frac;
    vbr_presets_t p = vbr_preset[a];
    vbr_presets_t q = vbr_preset[a + 1];
    vbr_presets_t const *set = &p;

    NOOP(vbr_q);
    NOOP(quant_comp);
    NOOP(quant_comp_s);
    NOOP(expY);
    LERP(st_lrm);
    LERP(st_s);
    LERP(masking_adj);
    LERP(masking_adj_short);
    LERP(ath_lower);
    LERP(ath_curve);
    LERP(ath_sensitivity);
    LERP(interch);
    NOOP(safejoint);
    NOOP(sfb21mod);
    LERP(msfix);

    (void) lame_set_VBR_q(gfp, set->vbr_q);
    SET_OPTION(quant_comp, set->quant_comp, -1);
    SET_OPTION(quant_comp_short, set->quant_comp_s, -1);
    if (set->expY) {
        (void) lame_set_experimentalY(gfp, set->expY);
    }
    SET_OPTION(short_threshold_lrm, set->st_lrm, -1);
    SET_OPTION(short_threshold_s, set->st_s, -1);
    SET_OPTION(maskingadjust, set->masking_adj, 0);
    SET_OPTION(maskingadjust_short, set->masking_adj_short, 0);
    SET_OPTION(ATHlower, set->ath_lower, 0);
    SET_OPTION(ATHcurve, set->ath_curve, -1);
    SET_OPTION(athaa_sensitivity, set->ath_sensitivity, 0);
    if (set->interch > 0) {
        SET_OPTION(interChRatio, set->interch, -1);
    }

    /* parameters for which there is no proper set/get interface */
    if (set->safejoint > 0) {
        (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | set->safejoint);
    }
    if (set->sfb21mod > 0) {
        (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (set->sfb21mod << 20));
    }
    SET_OPTION(msfix, set->msfix, -1);

    if (enforce == 0) {
        gfp->VBR_q = a;
        gfp->VBR_q_frac = x;
    }
}
/*-----------------------------------------------------------------------------------*/
static
int
handle_incoming_data(void)
{
  int error = NO_ERROR;

  PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());

  if (uip_newdata()) {

    PRINTF("receiving UDP datagram from: ");
    PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
    PRINTF(":%u\n  Length: %u\n  Data: ", uip_ntohs(UIP_UDP_BUF->srcport), uip_datalen() );
    PRINTBITS(uip_appdata, uip_datalen());
    PRINTF("\n");

    coap_packet_t message[1];
    coap_transaction_t *transaction = NULL;

    error = coap_parse_message(message, uip_appdata, uip_datalen());

    if (error==NO_ERROR)
    {

      /*TODO duplicates suppression, if required */

      PRINTF("  Parsed: v %u, t %u, oc %u, c %u, tid %u\n", message->version, message->type, message->option_count, message->code, message->tid);
      PRINTF("  URL: %.*s\n", message->uri_path_len, message->uri_path);
      PRINTF("  Payload: %.*s\n", message->payload_len, message->payload);

      /* Handle requests. */
      if (message->code >= COAP_GET && message->code <= COAP_DELETE)
      {
        /* Use transaction buffer for response to confirmable request. */
        if ( (transaction = coap_new_transaction(message->tid, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport)) )
        {
            uint32_t block_num = 0;
            uint16_t block_size = REST_MAX_CHUNK_SIZE;
            uint32_t block_offset = 0;
            int32_t new_offset = 0;

            /* prepare response */
            coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */
            if (message->type==COAP_TYPE_CON)
            {
              /* Reliable CON requests are answered with an ACK. */
              coap_init_message(response, COAP_TYPE_ACK, OK_200, message->tid);
            }
            else
            {
              /* Unreliable NON requests are answered with a NON as well. */
              coap_init_message(response, COAP_TYPE_NON, OK_200, coap_get_tid());
            }

            /* resource handlers must take care of different handling (e.g., TOKEN_OPTION_REQUIRED_240) */
            if (IS_OPTION(message, COAP_OPTION_TOKEN))
            {
                coap_set_header_token(response, message->token, message->token_len);
                SET_OPTION(response, COAP_OPTION_TOKEN);
            }

            /* get offset for blockwise transfers */
            if (coap_get_header_block(message, &block_num, NULL, &block_size, &block_offset))
            {
                PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
                block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
                new_offset = block_offset;
            }

            /*------------------------------------------*/
            /* call application-specific handler        */
            /*------------------------------------------*/
            if (service_cbk) {
              service_cbk(message, response, transaction->packet+COAP_MAX_HEADER_SIZE, block_size, &new_offset);
            }
            /*------------------------------------------*/


            /* apply blockwise transfers */
            if ( IS_OPTION(message, COAP_OPTION_BLOCK) )
            {
              /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
              if (new_offset==block_offset)
              {
                PRINTF("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size);
                if (block_offset >= response->payload_len)
                {
                  response->code = BAD_REQUEST_400;
                  coap_set_payload(response, (uint8_t*)"Block out of scope", 18);
                }
                else
                {
                  coap_set_header_block(response, block_num, response->payload_len - block_offset > block_size, block_size);
                  coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
                } /* if (valid offset) */
              }
              else
              {
                /* resource provides chunk-wise data */
                PRINTF("Blockwise: blockwise resource, new offset %ld\n", new_offset);
                coap_set_header_block(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size);
                if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size);
              } /* if (resource aware of blockwise) */
            }
            else if (new_offset!=0)
            {
              PRINTF("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE);

              coap_set_header_block(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE);
              coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE));
            } /* if (blockwise request) */

            if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0)
            {
              error = PACKET_SERIALIZATION_ERROR;
            }

        } else {
            error = MEMORY_ALLOCATION_ERROR;
        }
      }
      else
      {
        /* Responses */
        coap_transaction_t *t;

        if (message->type==COAP_TYPE_ACK)
        {
          PRINTF("Received ACK\n");
        }
        else if (message->type==COAP_TYPE_RST)
        {
          PRINTF("Received RST\n");
          /* Cancel possible subscriptions. */
          if (IS_OPTION(message, COAP_OPTION_TOKEN))
          {
            PRINTF("  Token 0x%02X%02X\n", message->token[0], message->token[1]);
            coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->token, message->token_len);
          }
        }

        if ( (t = coap_get_transaction_by_tid(message->tid)) )
        {
          /* Free transaction memory before callback, as it may create a new transaction. */
          restful_response_handler callback = t->callback;
          void *callback_data = t->callback_data;
          coap_clear_transaction(t);

          /* Check if someone registered for the response */
          if (callback) {
            callback(callback_data, message);
          }
        } /* if (transaction) */
      }
    } /* if (parsed correctly) */

    if (error==NO_ERROR) {
      if (transaction) coap_send_transaction(transaction);
    }
    else
    {
      PRINTF("ERROR %u: %s\n", error, error_messages[error]);

      /* reuse input buffer */
      coap_init_message(message, COAP_TYPE_ACK, INTERNAL_SERVER_ERROR_500, message->tid);
      coap_set_payload(message, (uint8_t *) error_messages[error], strlen(error_messages[error]));
      coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, uip_appdata, coap_serialize_message(message, uip_appdata));
    }
  } /* if (new data) */

  return error;
}