mirror of
https://github.com/obgm/libcoap.git
synced 2026-11-02 16:05:50 +03:00
144 lines
3.2 KiB
C
144 lines
3.2 KiB
C
/* coap -- simple implementation of the Constrained Application Protocol (CoAP)
|
|
* as defined in draft-ietf-core-coap-00
|
|
*
|
|
* (c) 2010 Olaf Bergmann <bergmann@tzi.org>
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <sys/select.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
|
|
#include "coap.h"
|
|
|
|
coap_pdu_t *
|
|
coap_new_get( const char *uri ) {
|
|
coap_pdu_t *pdu;
|
|
|
|
if ( !uri || ! ( pdu = coap_new_pdu() ) )
|
|
return NULL;
|
|
|
|
pdu->hdr->type = COAP_MESSAGE_CON;
|
|
pdu->hdr->code = COAP_REQUEST_GET;
|
|
|
|
if ( *uri ) {
|
|
if ( *uri != '/' )
|
|
coap_add_option ( pdu, COAP_OPTION_URI_FULL, strlen( uri ), (unsigned char *)uri );
|
|
else {
|
|
++uri;
|
|
if ( *uri )
|
|
coap_add_option ( pdu, COAP_OPTION_URI_PATH, strlen( uri ), (unsigned char *)uri );
|
|
}
|
|
}
|
|
|
|
return pdu;
|
|
}
|
|
|
|
void
|
|
send_request( coap_context_t *ctx, coap_pdu_t *pdu ) {
|
|
struct addrinfo *res, *ainfo;
|
|
struct addrinfo hints;
|
|
int error;
|
|
struct sockaddr_in6 dst;
|
|
|
|
memset ((char *)&hints, 0, sizeof(hints));
|
|
hints.ai_socktype = SOCK_DGRAM;
|
|
hints.ai_family = AF_INET6;
|
|
|
|
/* error = getaddrinfo("ns.tzi.org", "", &hints, &res);*/
|
|
error = getaddrinfo("::1", "", &hints, &res);
|
|
|
|
if (error != 0) {
|
|
perror("getaddrinfo");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
|
|
|
|
if ( ainfo->ai_family == AF_INET6 ) {
|
|
|
|
memset(&dst, 0, sizeof dst );
|
|
dst.sin6_family = AF_INET6;
|
|
dst.sin6_port = htons( COAP_DEFAULT_PORT );
|
|
memcpy( &dst.sin6_addr, &((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr, sizeof(dst.sin6_addr) );
|
|
|
|
coap_send_confirmed( ctx, &dst, pdu );
|
|
goto leave;
|
|
}
|
|
}
|
|
|
|
leave:
|
|
freeaddrinfo(res);
|
|
}
|
|
|
|
void
|
|
message_handler( coap_context_t *ctx, coap_queue_t *node, void *data) {
|
|
#ifndef NDEBUG
|
|
printf("** process pdu: ");
|
|
coap_show_pdu( node->pdu );
|
|
#endif
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv) {
|
|
coap_context_t *ctx;
|
|
fd_set readfds;
|
|
struct timeval tv, *timeout;
|
|
int result;
|
|
time_t now;
|
|
coap_queue_t *nextpdu;
|
|
coap_pdu_t *pdu;
|
|
|
|
ctx = coap_new_context();
|
|
if ( !ctx )
|
|
return -1;
|
|
|
|
coap_register_message_handler( ctx, message_handler );
|
|
|
|
if (! (pdu = coap_new_get( COAP_DEFAULT_URI_WELLKNOWN ) ) )
|
|
return -1;
|
|
|
|
send_request( ctx, pdu );
|
|
|
|
while ( 1 ) {
|
|
FD_ZERO(&readfds);
|
|
FD_SET( ctx->sockfd, &readfds );
|
|
|
|
nextpdu = coap_peek_next( ctx );
|
|
|
|
time(&now);
|
|
while ( nextpdu && nextpdu->t <= now ) {
|
|
coap_retransmit( ctx, coap_pop_next( ctx ) );
|
|
nextpdu = coap_peek_next( ctx );
|
|
}
|
|
|
|
if ( nextpdu ) { /* set timeout if there is a pdu to send */
|
|
tv.tv_usec = 0;
|
|
tv.tv_sec = nextpdu->t - now;
|
|
timeout = &tv;
|
|
} else
|
|
timeout = NULL; /* no timeout otherwise */
|
|
|
|
result = select( ctx->sockfd + 1, &readfds, 0, 0, timeout );
|
|
|
|
if ( result < 0 ) { /* error */
|
|
perror("select");
|
|
} else if ( result > 0 ) { /* read from socket */
|
|
if ( FD_ISSET( ctx->sockfd, &readfds ) ) {
|
|
coap_read( ctx ); /* read received data */
|
|
coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */
|
|
}
|
|
}
|
|
}
|
|
|
|
coap_free_context( ctx );
|
|
|
|
return 0;
|
|
}
|