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