1c87c5fbaSopenharmony_ci/* tiny -- tiny sender 2c87c5fbaSopenharmony_ci * 3c87c5fbaSopenharmony_ci * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org> 4c87c5fbaSopenharmony_ci * 5c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 6c87c5fbaSopenharmony_ci * 7c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see 8c87c5fbaSopenharmony_ci * README for terms of use. 9c87c5fbaSopenharmony_ci */ 10c87c5fbaSopenharmony_ci 11c87c5fbaSopenharmony_ci#include <string.h> 12c87c5fbaSopenharmony_ci#include <stdlib.h> 13c87c5fbaSopenharmony_ci#include <stdio.h> 14c87c5fbaSopenharmony_ci#include <ctype.h> 15c87c5fbaSopenharmony_ci#include <limits.h> 16c87c5fbaSopenharmony_ci#include <sys/select.h> 17c87c5fbaSopenharmony_ci#include <sys/types.h> 18c87c5fbaSopenharmony_ci#include <sys/socket.h> 19c87c5fbaSopenharmony_ci#include <netinet/in.h> 20c87c5fbaSopenharmony_ci#include <arpa/inet.h> 21c87c5fbaSopenharmony_ci#include <netdb.h> 22c87c5fbaSopenharmony_ci#include <signal.h> 23c87c5fbaSopenharmony_ci 24c87c5fbaSopenharmony_ci#include <coap3/coap.h> 25c87c5fbaSopenharmony_ci 26c87c5fbaSopenharmony_ci#define Nn 8 /* duplicate definition of N if built on sky motes */ 27c87c5fbaSopenharmony_ci#define ENCODE_HEADER_SIZE 4 28c87c5fbaSopenharmony_ci#define HIBIT (1 << (Nn - 1)) 29c87c5fbaSopenharmony_ci#define EMASK ((1 << ENCODE_HEADER_SIZE) - 1) 30c87c5fbaSopenharmony_ci#define MMASK ((1 << Nn) - 1 - EMASK) 31c87c5fbaSopenharmony_ci#define MAX_VALUE ( (1 << Nn) - (1 << ENCODE_HEADER_SIZE) ) * (1 << ((1 << ENCODE_HEADER_SIZE) - 1)) 32c87c5fbaSopenharmony_ci 33c87c5fbaSopenharmony_ci#define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK)) 34c87c5fbaSopenharmony_ci 35c87c5fbaSopenharmony_ci/* ls and s must be integer variables */ 36c87c5fbaSopenharmony_ci/* #define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls) */ 37c87c5fbaSopenharmony_ciCOAP_STATIC_INLINE unsigned char 38c87c5fbaSopenharmony_ciCOAP_PSEUDOFP_ENCODE_8_4_DOWN(unsigned int v, int *ls) { 39c87c5fbaSopenharmony_ci if (v < HIBIT) 40c87c5fbaSopenharmony_ci return v; 41c87c5fbaSopenharmony_ci *ls = coap_fls(v) - Nn; 42c87c5fbaSopenharmony_ci return ((v >> *ls) & MMASK) + *ls; 43c87c5fbaSopenharmony_ci} 44c87c5fbaSopenharmony_ci#define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<<ENCODE_HEADER_SIZE<<ls)-1)) >> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls)) 45c87c5fbaSopenharmony_ci 46c87c5fbaSopenharmony_cistatic int quit = 0; 47c87c5fbaSopenharmony_ci 48c87c5fbaSopenharmony_ci/* SIGINT handler: set quit to 1 for graceful termination */ 49c87c5fbaSopenharmony_cistatic void 50c87c5fbaSopenharmony_cihandle_sigint(int signum COAP_UNUSED) { 51c87c5fbaSopenharmony_ci quit = 1; 52c87c5fbaSopenharmony_ci} 53c87c5fbaSopenharmony_ci 54c87c5fbaSopenharmony_cistatic coap_pdu_t * 55c87c5fbaSopenharmony_cimake_pdu(coap_session_t *session, unsigned int value) { 56c87c5fbaSopenharmony_ci coap_pdu_t *pdu; 57c87c5fbaSopenharmony_ci unsigned char enc; 58c87c5fbaSopenharmony_ci static unsigned char buf[20]; 59c87c5fbaSopenharmony_ci int len, ls; 60c87c5fbaSopenharmony_ci 61c87c5fbaSopenharmony_ci if (!(pdu = coap_pdu_init(COAP_MESSAGE_NON, COAP_REQUEST_CODE_POST, 62c87c5fbaSopenharmony_ci coap_new_message_id(session), COAP_DEFAULT_MTU))) 63c87c5fbaSopenharmony_ci return NULL; 64c87c5fbaSopenharmony_ci 65c87c5fbaSopenharmony_ci enc = COAP_PSEUDOFP_ENCODE_8_4_DOWN(value, &ls); 66c87c5fbaSopenharmony_ci 67c87c5fbaSopenharmony_ci len = sprintf((char *)buf, "%c%u", enc, COAP_PSEUDOFP_DECODE_8_4(enc)); 68c87c5fbaSopenharmony_ci coap_add_data(pdu, len, buf); 69c87c5fbaSopenharmony_ci 70c87c5fbaSopenharmony_ci return pdu; 71c87c5fbaSopenharmony_ci} 72c87c5fbaSopenharmony_ci 73c87c5fbaSopenharmony_cistatic void 74c87c5fbaSopenharmony_ciusage(const char *program) { 75c87c5fbaSopenharmony_ci const char *p; 76c87c5fbaSopenharmony_ci 77c87c5fbaSopenharmony_ci p = strrchr(program, '/'); 78c87c5fbaSopenharmony_ci if (p) 79c87c5fbaSopenharmony_ci program = ++p; 80c87c5fbaSopenharmony_ci 81c87c5fbaSopenharmony_ci fprintf(stderr, "%s -- tiny fake sensor\n" 82c87c5fbaSopenharmony_ci "(c) 2010 Olaf Bergmann <bergmann@tzi.org>\n\n" 83c87c5fbaSopenharmony_ci "usage: %s [group address]\n" 84c87c5fbaSopenharmony_ci "\n\nSends some fake sensor values to specified multicast group\n", 85c87c5fbaSopenharmony_ci program, program); 86c87c5fbaSopenharmony_ci} 87c87c5fbaSopenharmony_ci 88c87c5fbaSopenharmony_cistatic coap_session_t * 89c87c5fbaSopenharmony_ciget_session(coap_context_t *ctx, const char *group) { 90c87c5fbaSopenharmony_ci int s; 91c87c5fbaSopenharmony_ci struct addrinfo hints; 92c87c5fbaSopenharmony_ci struct addrinfo *result, *rp; 93c87c5fbaSopenharmony_ci coap_session_t *session; 94c87c5fbaSopenharmony_ci int hops = 16; 95c87c5fbaSopenharmony_ci 96c87c5fbaSopenharmony_ci if (!ctx) 97c87c5fbaSopenharmony_ci return NULL; 98c87c5fbaSopenharmony_ci 99c87c5fbaSopenharmony_ci memset(&hints, 0, sizeof(struct addrinfo)); 100c87c5fbaSopenharmony_ci hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 101c87c5fbaSopenharmony_ci hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ 102c87c5fbaSopenharmony_ci hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; 103c87c5fbaSopenharmony_ci 104c87c5fbaSopenharmony_ci s = getaddrinfo(group, NULL, &hints, &result); 105c87c5fbaSopenharmony_ci if (s != 0) { 106c87c5fbaSopenharmony_ci fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); 107c87c5fbaSopenharmony_ci return NULL; 108c87c5fbaSopenharmony_ci } 109c87c5fbaSopenharmony_ci 110c87c5fbaSopenharmony_ci /* iterate through results until success */ 111c87c5fbaSopenharmony_ci for (rp = result; rp != NULL; rp = rp->ai_next) { 112c87c5fbaSopenharmony_ci coap_address_t addr; 113c87c5fbaSopenharmony_ci coap_address_init(&addr); 114c87c5fbaSopenharmony_ci addr.size = rp->ai_addrlen; 115c87c5fbaSopenharmony_ci memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); 116c87c5fbaSopenharmony_ci 117c87c5fbaSopenharmony_ci session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); 118c87c5fbaSopenharmony_ci if (!session) 119c87c5fbaSopenharmony_ci continue; 120c87c5fbaSopenharmony_ci 121c87c5fbaSopenharmony_ci if (coap_is_mcast(&addr)) { 122c87c5fbaSopenharmony_ci /* set socket options for multicast */ 123c87c5fbaSopenharmony_ci if (!coap_mcast_set_hops(session, hops)) 124c87c5fbaSopenharmony_ci perror("setsockopt: IPV6_MULTICAST_HOPS"); 125c87c5fbaSopenharmony_ci 126c87c5fbaSopenharmony_ci } 127c87c5fbaSopenharmony_ci freeaddrinfo(result); 128c87c5fbaSopenharmony_ci return session; 129c87c5fbaSopenharmony_ci } 130c87c5fbaSopenharmony_ci 131c87c5fbaSopenharmony_ci fprintf(stderr, "no session available for group '%s'\n", group); 132c87c5fbaSopenharmony_ci freeaddrinfo(result); 133c87c5fbaSopenharmony_ci return NULL; 134c87c5fbaSopenharmony_ci} 135c87c5fbaSopenharmony_ci 136c87c5fbaSopenharmony_ciint 137c87c5fbaSopenharmony_cimain(int argc, char **argv) { 138c87c5fbaSopenharmony_ci struct timeval tv; 139c87c5fbaSopenharmony_ci coap_pdu_t *pdu; 140c87c5fbaSopenharmony_ci coap_session_t *session; 141c87c5fbaSopenharmony_ci struct sigaction sa; 142c87c5fbaSopenharmony_ci coap_context_t *ctx; 143c87c5fbaSopenharmony_ci 144c87c5fbaSopenharmony_ci /* Initialize libcoap library */ 145c87c5fbaSopenharmony_ci coap_startup(); 146c87c5fbaSopenharmony_ci 147c87c5fbaSopenharmony_ci if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) { 148c87c5fbaSopenharmony_ci usage(argv[0]); 149c87c5fbaSopenharmony_ci exit(1); 150c87c5fbaSopenharmony_ci } 151c87c5fbaSopenharmony_ci 152c87c5fbaSopenharmony_ci ctx = coap_new_context(NULL); 153c87c5fbaSopenharmony_ci if (!ctx) 154c87c5fbaSopenharmony_ci return -1; 155c87c5fbaSopenharmony_ci 156c87c5fbaSopenharmony_ci session = get_session(ctx, argc > 1 ? argv[1] : "::1"); 157c87c5fbaSopenharmony_ci 158c87c5fbaSopenharmony_ci if (!session) 159c87c5fbaSopenharmony_ci return -1; 160c87c5fbaSopenharmony_ci 161c87c5fbaSopenharmony_ci memset(&sa, 0, sizeof(sa)); 162c87c5fbaSopenharmony_ci sigemptyset(&sa.sa_mask); 163c87c5fbaSopenharmony_ci sa.sa_handler = handle_sigint; 164c87c5fbaSopenharmony_ci sa.sa_flags = 0; 165c87c5fbaSopenharmony_ci sigaction(SIGINT, &sa, NULL); 166c87c5fbaSopenharmony_ci sigaction(SIGTERM, &sa, NULL); 167c87c5fbaSopenharmony_ci /* So we do not exit on a SIGPIPE */ 168c87c5fbaSopenharmony_ci sa.sa_handler = SIG_IGN; 169c87c5fbaSopenharmony_ci sigaction(SIGPIPE, &sa, NULL); 170c87c5fbaSopenharmony_ci 171c87c5fbaSopenharmony_ci while (!quit) { 172c87c5fbaSopenharmony_ci 173c87c5fbaSopenharmony_ci if (!(pdu = make_pdu(session, rand() & 0xfff))) 174c87c5fbaSopenharmony_ci break; 175c87c5fbaSopenharmony_ci 176c87c5fbaSopenharmony_ci coap_send(session, pdu); 177c87c5fbaSopenharmony_ci 178c87c5fbaSopenharmony_ci tv.tv_sec = 5; 179c87c5fbaSopenharmony_ci tv.tv_usec = 0; 180c87c5fbaSopenharmony_ci 181c87c5fbaSopenharmony_ci select(0, 0, 0, 0, &tv); 182c87c5fbaSopenharmony_ci 183c87c5fbaSopenharmony_ci } 184c87c5fbaSopenharmony_ci 185c87c5fbaSopenharmony_ci coap_free_context(ctx); 186c87c5fbaSopenharmony_ci coap_cleanup(); 187c87c5fbaSopenharmony_ci 188c87c5fbaSopenharmony_ci return 0; 189c87c5fbaSopenharmony_ci} 190