Fixed Erbium bugs (ext. header, client request path) and added server resource config defines.
This commit is contained in:
parent
f26920ae9b
commit
c861ce0197
|
@ -96,21 +96,18 @@ handle_incoming_data(void)
|
||||||
|
|
||||||
PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());
|
PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());
|
||||||
|
|
||||||
uint8_t *data = uip_appdata + uip_ext_len;
|
|
||||||
uint16_t data_len = uip_datalen() - uip_ext_len;
|
|
||||||
|
|
||||||
if (uip_newdata()) {
|
if (uip_newdata()) {
|
||||||
|
|
||||||
PRINTF("receiving UDP datagram from: ");
|
PRINTF("receiving UDP datagram from: ");
|
||||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||||
PRINTF(":%u\n Length: %u\n Data: ", uip_ntohs(UIP_UDP_BUF->srcport), data_len );
|
PRINTF(":%u\n Length: %u\n Data: ", uip_ntohs(UIP_UDP_BUF->srcport), uip_datalen() );
|
||||||
PRINTBITS(data, data_len);
|
PRINTBITS(uip_appdata, uip_datalen());
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
|
||||||
coap_packet_t message[1];
|
coap_packet_t message[1];
|
||||||
coap_transaction_t *transaction = NULL;
|
coap_transaction_t *transaction = NULL;
|
||||||
|
|
||||||
error = coap_parse_message(message, data, data_len);
|
error = coap_parse_message(message, uip_appdata, uip_datalen());
|
||||||
|
|
||||||
if (error==NO_ERROR)
|
if (error==NO_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -257,7 +254,7 @@ handle_incoming_data(void)
|
||||||
/* reuse input buffer */
|
/* reuse input buffer */
|
||||||
coap_init_message(message, COAP_TYPE_ACK, INTERNAL_SERVER_ERROR_500, message->tid);
|
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_set_payload(message, (uint8_t *) error_messages[error], strlen(error_messages[error]));
|
||||||
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, data, coap_serialize_message(message, data));
|
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, uip_appdata, coap_serialize_message(message, uip_appdata));
|
||||||
}
|
}
|
||||||
} /* if (new data) */
|
} /* if (new data) */
|
||||||
|
|
||||||
|
|
|
@ -82,9 +82,6 @@ handle_incoming_data(void)
|
||||||
|
|
||||||
PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());
|
PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());
|
||||||
|
|
||||||
uint8_t *data = uip_appdata + uip_ext_len;
|
|
||||||
uint16_t data_len = uip_datalen() - uip_ext_len;
|
|
||||||
|
|
||||||
/* Static declaration reduces stack peaks and program code size. */
|
/* 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 message[1]; /* This way the packet can be treated as pointer as usual. */
|
||||||
static coap_packet_t response[1];
|
static coap_packet_t response[1];
|
||||||
|
@ -94,11 +91,11 @@ handle_incoming_data(void)
|
||||||
|
|
||||||
PRINTF("receiving UDP datagram from: ");
|
PRINTF("receiving UDP datagram from: ");
|
||||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||||
PRINTF(":%u\n Length: %u\n Data: ", uip_ntohs(UIP_UDP_BUF->srcport), data_len );
|
PRINTF(":%u\n Length: %u\n Data: ", uip_ntohs(UIP_UDP_BUF->srcport), uip_datalen() );
|
||||||
PRINTBITS(data, data_len);
|
PRINTBITS(uip_appdata, uip_datalen());
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
|
||||||
coap_error_code = coap_parse_message(message, data, data_len);
|
coap_error_code = coap_parse_message(message, uip_appdata, uip_datalen());
|
||||||
|
|
||||||
if (coap_error_code==NO_ERROR)
|
if (coap_error_code==NO_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +259,7 @@ handle_incoming_data(void)
|
||||||
/* Reuse input buffer for error message. */
|
/* Reuse input buffer for error message. */
|
||||||
coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->tid);
|
coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->tid);
|
||||||
coap_set_payload(message, (uint8_t *) coap_error_message, strlen(coap_error_message));
|
coap_set_payload(message, (uint8_t *) coap_error_message, strlen(coap_error_message));
|
||||||
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, data, coap_serialize_message(message, data));
|
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, uip_appdata, coap_serialize_message(message, uip_appdata));
|
||||||
}
|
}
|
||||||
} /* if (new data) */
|
} /* if (new data) */
|
||||||
|
|
||||||
|
|
|
@ -82,9 +82,6 @@ handle_incoming_data(void)
|
||||||
|
|
||||||
PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());
|
PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());
|
||||||
|
|
||||||
uint8_t *data = uip_appdata + uip_ext_len;
|
|
||||||
uint16_t data_len = uip_datalen() - uip_ext_len;
|
|
||||||
|
|
||||||
/* Static declaration reduces stack peaks and program code size. */
|
/* 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 message[1]; /* This way the packet can be treated as pointer as usual. */
|
||||||
static coap_packet_t response[1];
|
static coap_packet_t response[1];
|
||||||
|
@ -94,11 +91,11 @@ handle_incoming_data(void)
|
||||||
|
|
||||||
PRINTF("receiving UDP datagram from: ");
|
PRINTF("receiving UDP datagram from: ");
|
||||||
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
|
||||||
PRINTF(":%u\n Length: %u\n Data: ", uip_ntohs(UIP_UDP_BUF->srcport), data_len );
|
PRINTF(":%u\n Length: %u\n Data: ", uip_ntohs(UIP_UDP_BUF->srcport), uip_datalen() );
|
||||||
PRINTBITS(data, data_len);
|
PRINTBITS(uip_appdata, uip_datalen());
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
|
||||||
coap_error_code = coap_parse_message(message, data, data_len);
|
coap_error_code = coap_parse_message(message, uip_appdata, uip_datalen());
|
||||||
|
|
||||||
if (coap_error_code==NO_ERROR)
|
if (coap_error_code==NO_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -263,7 +260,7 @@ handle_incoming_data(void)
|
||||||
/* Reuse input buffer for error message. */
|
/* Reuse input buffer for error message. */
|
||||||
coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->tid);
|
coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->tid);
|
||||||
coap_set_payload(message, (uint8_t *) coap_error_message, strlen(coap_error_message));
|
coap_set_payload(message, (uint8_t *) coap_error_message, strlen(coap_error_message));
|
||||||
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, data, coap_serialize_message(message, data));
|
coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, uip_appdata, coap_serialize_message(message, uip_appdata));
|
||||||
}
|
}
|
||||||
} /* if (new data) */
|
} /* if (new data) */
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO: This server address is hard-coded for Cooja. */
|
/* TODO: This server address is hard-coded for Cooja. */
|
||||||
#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */
|
#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) /* cooja2 */
|
||||||
|
|
||||||
#define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT+1)
|
#define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT+1)
|
||||||
#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT)
|
#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT)
|
||||||
|
@ -89,7 +89,8 @@ static struct etimer et;
|
||||||
|
|
||||||
/* Example URIs that can be queried. */
|
/* Example URIs that can be queried. */
|
||||||
#define NUMBER_OF_URLS 4
|
#define NUMBER_OF_URLS 4
|
||||||
char* service_urls[NUMBER_OF_URLS] = {".well-known/core", "/toggle", "battery/", "error/in//path"};
|
/* leading and ending slashes only for demo purposes, get cropped automatically when setting the Uri-Path */
|
||||||
|
char* service_urls[NUMBER_OF_URLS] = {".well-known/core", "/actuators/toggle", "battery/", "error/in//path"};
|
||||||
#if PLATFORM_HAS_BUTTON
|
#if PLATFORM_HAS_BUTTON
|
||||||
static int uri_switch = 0;
|
static int uri_switch = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,6 +42,20 @@
|
||||||
#include "contiki.h"
|
#include "contiki.h"
|
||||||
#include "contiki-net.h"
|
#include "contiki-net.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Define which resources to include to meet memory constraints. */
|
||||||
|
#define REST_RES_HELLO 1
|
||||||
|
#define REST_RES_MIRROR 0
|
||||||
|
#define REST_RES_CHUNKS 1
|
||||||
|
#define REST_RES_POLLING 0
|
||||||
|
#define REST_RES_EVENT 1
|
||||||
|
#define REST_RES_LEDS 0
|
||||||
|
#define REST_RES_TOGGLE 1
|
||||||
|
#define REST_RES_LIGHT 1
|
||||||
|
#define REST_RES_BATTERY 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET)
|
#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET)
|
||||||
#warning "Compiling with static routing!"
|
#warning "Compiling with static routing!"
|
||||||
#include "static-routing.h"
|
#include "static-routing.h"
|
||||||
|
@ -89,6 +103,8 @@
|
||||||
#define PRINTLLADDR(addr)
|
#define PRINTLLADDR(addr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if REST_RES_HELLO
|
||||||
/*
|
/*
|
||||||
* Resources are defined by the RESOURCE macro.
|
* Resources are defined by the RESOURCE macro.
|
||||||
* Signature: resource name, the RESTful methods it handles, and its URI path (omitting the leading slash).
|
* Signature: resource name, the RESTful methods it handles, and its URI path (omitting the leading slash).
|
||||||
|
@ -123,7 +139,9 @@ helloworld_handler(void* request, void* response, uint8_t *buffer, uint16_t pref
|
||||||
REST.set_header_etag(response, (uint8_t *) &length, 1);
|
REST.set_header_etag(response, (uint8_t *) &length, 1);
|
||||||
REST.set_response_payload(response, buffer, length);
|
REST.set_response_payload(response, buffer, length);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if REST_RES_MIRROR
|
||||||
/* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */
|
/* This resource mirrors the incoming request. It shows how to access the options and how to set them for the response. */
|
||||||
RESOURCE(mirror, METHOD_GET | METHOD_POST | METHOD_PUT | METHOD_DELETE, "debug/mirror", "title=\"Returns your decoded message\";rt=\"Debug\"");
|
RESOURCE(mirror, METHOD_GET | METHOD_POST | METHOD_PUT | METHOD_DELETE, "debug/mirror", "title=\"Returns your decoded message\";rt=\"Debug\"");
|
||||||
|
|
||||||
|
@ -274,7 +292,9 @@ mirror_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre
|
||||||
#endif
|
#endif
|
||||||
#endif /* CoAP-specific example */
|
#endif /* CoAP-specific example */
|
||||||
}
|
}
|
||||||
|
#endif /* REST_RES_MIRROR */
|
||||||
|
|
||||||
|
#if REST_RES_CHUNKS
|
||||||
/*
|
/*
|
||||||
* For data larger than REST_MAX_CHUNK_SIZE (e.g., stored in flash) resources must be aware of the buffer limitation
|
* For data larger than REST_MAX_CHUNK_SIZE (e.g., stored in flash) resources must be aware of the buffer limitation
|
||||||
* and split their responses by themselves. To transfer the complete resource through a TCP stream or CoAP's blockwise transfer,
|
* and split their responses by themselves. To transfer the complete resource through a TCP stream or CoAP's blockwise transfer,
|
||||||
|
@ -329,7 +349,9 @@ chunks_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre
|
||||||
*offset = -1;
|
*offset = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if REST_RES_POLLING
|
||||||
/*
|
/*
|
||||||
* Example for a periodic resource.
|
* Example for a periodic resource.
|
||||||
* It takes an additional period parameter, which defines the interval to call [name]_periodic_handler().
|
* It takes an additional period parameter, which defines the interval to call [name]_periodic_handler().
|
||||||
|
@ -365,8 +387,9 @@ polling_periodic_handler(resource_t *r)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined (PLATFORM_HAS_BUTTON)
|
#if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT
|
||||||
/*
|
/*
|
||||||
* Example for an event resource.
|
* Example for an event resource.
|
||||||
* Additionally takes a period parameter that defines the interval to call [name]_periodic_handler().
|
* Additionally takes a period parameter that defines the interval to call [name]_periodic_handler().
|
||||||
|
@ -404,11 +427,12 @@ event_event_handler(resource_t *r)
|
||||||
#endif /* PLATFORM_HAS_BUTTON */
|
#endif /* PLATFORM_HAS_BUTTON */
|
||||||
|
|
||||||
#if defined (PLATFORM_HAS_LEDS)
|
#if defined (PLATFORM_HAS_LEDS)
|
||||||
|
#if REST_RES_LEDS
|
||||||
/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/
|
/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/
|
||||||
RESOURCE(led, METHOD_POST | METHOD_PUT , "actuators/leds", "title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\"");
|
RESOURCE(leds, METHOD_POST | METHOD_PUT , "actuators/leds", "title=\"LEDs: ?color=r|g|b, POST/PUT mode=on|off\";rt=\"Control\"");
|
||||||
|
|
||||||
void
|
void
|
||||||
led_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
leds_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
const char *color = NULL;
|
const char *color = NULL;
|
||||||
|
@ -450,7 +474,9 @@ led_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_s
|
||||||
REST.set_response_status(response, REST.status.BAD_REQUEST);
|
REST.set_response_status(response, REST.status.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if REST_RES_TOGGLE
|
||||||
/* A simple actuator example. Toggles the red led */
|
/* A simple actuator example. Toggles the red led */
|
||||||
RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "actuators/toggle", "title=\"Red LED\";rt=\"Control\"");
|
RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "actuators/toggle", "title=\"Red LED\";rt=\"Control\"");
|
||||||
void
|
void
|
||||||
|
@ -458,9 +484,10 @@ toggle_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre
|
||||||
{
|
{
|
||||||
leds_toggle(LEDS_RED);
|
leds_toggle(LEDS_RED);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif /* PLATFORM_HAS_LEDS */
|
#endif /* PLATFORM_HAS_LEDS */
|
||||||
|
|
||||||
#if defined (PLATFORM_HAS_LIGHT)
|
#if defined (PLATFORM_HAS_LIGHT) && REST_RES_LIGHT
|
||||||
/* A simple getter example. Returns the reading from light sensor with a simple etag */
|
/* A simple getter example. Returns the reading from light sensor with a simple etag */
|
||||||
RESOURCE(light, METHOD_GET, "sensors/light", "title=\"Photosynthetic and solar light (supports JSON)\";rt=\"LightSensor\"");
|
RESOURCE(light, METHOD_GET, "sensors/light", "title=\"Photosynthetic and solar light (supports JSON)\";rt=\"LightSensor\"");
|
||||||
void
|
void
|
||||||
|
@ -501,7 +528,7 @@ light_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred
|
||||||
}
|
}
|
||||||
#endif /* PLATFORM_HAS_LIGHT */
|
#endif /* PLATFORM_HAS_LIGHT */
|
||||||
|
|
||||||
#if defined (PLATFORM_HAS_BATTERY)
|
#if defined (PLATFORM_HAS_BATTERY) && REST_RES_BATTERY
|
||||||
/* A simple getter example. Returns the reading from light sensor with a simple etag */
|
/* A simple getter example. Returns the reading from light sensor with a simple etag */
|
||||||
RESOURCE(battery, METHOD_GET, "sensors/battery", "title=\"Battery status\";rt=\"Battery\"");
|
RESOURCE(battery, METHOD_GET, "sensors/battery", "title=\"Battery status\";rt=\"Battery\"");
|
||||||
void
|
void
|
||||||
|
@ -565,25 +592,35 @@ PROCESS_THREAD(rest_server_example, ev, data)
|
||||||
rest_init_framework();
|
rest_init_framework();
|
||||||
|
|
||||||
/* Activate the application-specific resources. */
|
/* Activate the application-specific resources. */
|
||||||
|
#if REST_RES_HELLO
|
||||||
rest_activate_resource(&resource_helloworld);
|
rest_activate_resource(&resource_helloworld);
|
||||||
|
#endif
|
||||||
|
#if REST_RES_MIRROR
|
||||||
rest_activate_resource(&resource_mirror);
|
rest_activate_resource(&resource_mirror);
|
||||||
|
#endif
|
||||||
|
#if REST_RES_CHUNKS
|
||||||
rest_activate_resource(&resource_chunks);
|
rest_activate_resource(&resource_chunks);
|
||||||
|
#endif
|
||||||
|
#if REST_RES_POLLING
|
||||||
rest_activate_periodic_resource(&periodic_resource_polling);
|
rest_activate_periodic_resource(&periodic_resource_polling);
|
||||||
|
#endif
|
||||||
#if defined (PLATFORM_HAS_BUTTON)
|
#if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT
|
||||||
SENSORS_ACTIVATE(button_sensor);
|
SENSORS_ACTIVATE(button_sensor);
|
||||||
rest_activate_event_resource(&resource_event);
|
rest_activate_event_resource(&resource_event);
|
||||||
#endif
|
#endif
|
||||||
#if defined (PLATFORM_HAS_LEDS)
|
#if defined (PLATFORM_HAS_LEDS)
|
||||||
rest_activate_resource(&resource_led);
|
#if REST_RES_LEDS
|
||||||
|
rest_activate_resource(&resource_leds);
|
||||||
|
#endif
|
||||||
|
#if REST_RES_TOGGLE
|
||||||
rest_activate_resource(&resource_toggle);
|
rest_activate_resource(&resource_toggle);
|
||||||
|
#endif
|
||||||
#endif /* PLATFORM_HAS_LEDS */
|
#endif /* PLATFORM_HAS_LEDS */
|
||||||
|
#if defined (PLATFORM_HAS_LIGHT) && REST_RES_LIGHT
|
||||||
#if defined (PLATFORM_HAS_LIGHT)
|
|
||||||
SENSORS_ACTIVATE(light_sensor);
|
SENSORS_ACTIVATE(light_sensor);
|
||||||
rest_activate_resource(&resource_light);
|
rest_activate_resource(&resource_light);
|
||||||
#endif
|
#endif
|
||||||
#if defined (PLATFORM_HAS_BATTERY)
|
#if defined (PLATFORM_HAS_BATTERY) && REST_RES_BATTERY
|
||||||
SENSORS_ACTIVATE(battery_sensor);
|
SENSORS_ACTIVATE(battery_sensor);
|
||||||
rest_activate_resource(&resource_battery);
|
rest_activate_resource(&resource_battery);
|
||||||
#endif
|
#endif
|
||||||
|
@ -591,7 +628,7 @@ PROCESS_THREAD(rest_server_example, ev, data)
|
||||||
/* Define application-specific events here. */
|
/* Define application-specific events here. */
|
||||||
while(1) {
|
while(1) {
|
||||||
PROCESS_WAIT_EVENT();
|
PROCESS_WAIT_EVENT();
|
||||||
#if defined (PLATFORM_HAS_BUTTON)
|
#if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT
|
||||||
if (ev == sensors_event && data == &button_sensor) {
|
if (ev == sensors_event && data == &button_sensor) {
|
||||||
PRINTF("BUTTON\n");
|
PRINTF("BUTTON\n");
|
||||||
/* Call the event_handler for this application-specific event. */
|
/* Call the event_handler for this application-specific event. */
|
||||||
|
|
Loading…
Reference in a new issue