Test of tinydtls over cellular

Dependencies:   VodafoneUSBModem mbed-rtos mbed tinydtls

Committer:
ashleymills
Date:
Fri Oct 18 14:08:05 2013 +0000
Revision:
2:fe574f2c2b6a
Parent:
1:1dd9b8218515
Updated to tinydtls v0.5.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 1:1dd9b8218515 1 #define __DEBUG__ 4
ashleymills 1:1dd9b8218515 2
ashleymills 1:1dd9b8218515 3 #ifndef __MODULE__
ashleymills 1:1dd9b8218515 4 #define __MODULE__ "main.cpp"
ashleymills 1:1dd9b8218515 5 #endif
ashleymills 1:1dd9b8218515 6
ashleymills 0:6ae42a2aff75 7 #include "mbed.h"
ashleymills 0:6ae42a2aff75 8 #include "rtos.h"
ashleymills 1:1dd9b8218515 9 #include "bsd_socket.h"
ashleymills 1:1dd9b8218515 10
ashleymills 1:1dd9b8218515 11 #include <dtls.h>
ashleymills 1:1dd9b8218515 12 #include "global.h"
ashleymills 1:1dd9b8218515 13 #include "debug.h"
ashleymills 1:1dd9b8218515 14 #include "errno.h"
ashleymills 1:1dd9b8218515 15
ashleymills 0:6ae42a2aff75 16 #include "VodafoneUSBModem.h"
ashleymills 0:6ae42a2aff75 17 DigitalOut myled(LED1);
ashleymills 0:6ae42a2aff75 18
ashleymills 1:1dd9b8218515 19 void fail(int code) {
ashleymills 1:1dd9b8218515 20 while(1) {
ashleymills 1:1dd9b8218515 21 myled = !myled;
ashleymills 1:1dd9b8218515 22 Thread::wait(100);
ashleymills 1:1dd9b8218515 23 }
ashleymills 1:1dd9b8218515 24 }
ashleymills 1:1dd9b8218515 25
ashleymills 2:fe574f2c2b6a 26 static const dtls_psk_key_t client_psk = {
ashleymills 2:fe574f2c2b6a 27 .id = (unsigned char *)"Client_identity",
ashleymills 2:fe574f2c2b6a 28 .id_length = 15,
ashleymills 2:fe574f2c2b6a 29 .key = (unsigned char *)"secretPSK",
ashleymills 2:fe574f2c2b6a 30 .key_length = 9
ashleymills 2:fe574f2c2b6a 31 };
ashleymills 2:fe574f2c2b6a 32
ashleymills 1:1dd9b8218515 33 /* This function is the "key store" for tinyDTLS. It is called to
ashleymills 1:1dd9b8218515 34 * retrieve a key for the given identiy within this particular
ashleymills 1:1dd9b8218515 35 * session. */
ashleymills 2:fe574f2c2b6a 36 int
ashleymills 2:fe574f2c2b6a 37 get_psk_key(struct dtls_context_t *ctx,
ashleymills 2:fe574f2c2b6a 38 const session_t *session,
ashleymills 2:fe574f2c2b6a 39 const unsigned char *id, size_t id_len,
ashleymills 2:fe574f2c2b6a 40 const dtls_psk_key_t **result) {
ashleymills 2:fe574f2c2b6a 41 DBG("id: %d, len: %d",id,id_len);
ashleymills 2:fe574f2c2b6a 42 *result = &client_psk;
ashleymills 1:1dd9b8218515 43
ashleymills 1:1dd9b8218515 44 return 0;
ashleymills 1:1dd9b8218515 45 }
ashleymills 1:1dd9b8218515 46
ashleymills 1:1dd9b8218515 47 //#define APN_GDSP
ashleymills 1:1dd9b8218515 48 #define APN_CONTRACT
ashleymills 1:1dd9b8218515 49
ashleymills 1:1dd9b8218515 50 #ifdef APN_GDSP
ashleymills 1:1dd9b8218515 51 #define APN "ppinternetd.gdsp"
ashleymills 1:1dd9b8218515 52 #define APN_USERNAME ""
ashleymills 1:1dd9b8218515 53 #define APN_PASSWORD ""
ashleymills 1:1dd9b8218515 54 #endif
ashleymills 1:1dd9b8218515 55
ashleymills 1:1dd9b8218515 56 #ifdef APN_CONTRACT
ashleymills 1:1dd9b8218515 57 #define APN "internet"
ashleymills 1:1dd9b8218515 58 #define APN_USERNAME "web"
ashleymills 1:1dd9b8218515 59 #define APN_PASSWORD "web"
ashleymills 1:1dd9b8218515 60 #endif
ashleymills 1:1dd9b8218515 61
ashleymills 1:1dd9b8218515 62 // globals
ashleymills 1:1dd9b8218515 63 int gDTLSConnected = 0;
ashleymills 1:1dd9b8218515 64 sockaddr_in bindAddr,serverAddress;
ashleymills 1:1dd9b8218515 65
ashleymills 1:1dd9b8218515 66 // this is used to setup sockaddr_in structures for a remote host
ashleymills 1:1dd9b8218515 67 // it also listens for incoming UDP packets on the local interface on port
ashleymills 1:1dd9b8218515 68 bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) {
ashleymills 1:1dd9b8218515 69 *sockfd = -1;
ashleymills 1:1dd9b8218515 70 // create the socket
ashleymills 1:1dd9b8218515 71 if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
ashleymills 1:1dd9b8218515 72 DBG("Error opening socket");
ashleymills 1:1dd9b8218515 73 return false;
ashleymills 1:1dd9b8218515 74 }
ashleymills 1:1dd9b8218515 75 socklen_t sockAddrInLen = sizeof(struct sockaddr_in);
ashleymills 1:1dd9b8218515 76
ashleymills 1:1dd9b8218515 77 // bind socket to 11111
ashleymills 1:1dd9b8218515 78 memset(&bindAddr, 0x00, sockAddrInLen);
ashleymills 1:1dd9b8218515 79 bindAddr.sin_family = AF_INET; // IP family
ashleymills 1:1dd9b8218515 80 bindAddr.sin_port = htons(port);
ashleymills 1:1dd9b8218515 81 bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation
ashleymills 1:1dd9b8218515 82 // call bind
ashleymills 1:1dd9b8218515 83 if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) {
ashleymills 1:1dd9b8218515 84 DBG("Error binding socket");
ashleymills 1:1dd9b8218515 85 perror(NULL);
ashleymills 1:1dd9b8218515 86 }
ashleymills 1:1dd9b8218515 87
ashleymills 1:1dd9b8218515 88 INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port));
ashleymills 1:1dd9b8218515 89
ashleymills 1:1dd9b8218515 90 // create the socket address
ashleymills 1:1dd9b8218515 91 memset(&serverAddress, 0x00, sizeof(struct sockaddr_in));
ashleymills 1:1dd9b8218515 92 serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
ashleymills 1:1dd9b8218515 93 serverAddress.sin_family = AF_INET;
ashleymills 1:1dd9b8218515 94 serverAddress.sin_port = htons(port);
ashleymills 1:1dd9b8218515 95
ashleymills 1:1dd9b8218515 96 // do socket connect
ashleymills 1:1dd9b8218515 97 //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
ashleymills 1:1dd9b8218515 98 if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
ashleymills 1:1dd9b8218515 99 shutdown(*sockfd,SHUT_RDWR);
ashleymills 1:1dd9b8218515 100 close(*sockfd);
ashleymills 1:1dd9b8218515 101 DBG("Could not connect");
ashleymills 1:1dd9b8218515 102 return false;
ashleymills 1:1dd9b8218515 103 }
ashleymills 1:1dd9b8218515 104 return true;
ashleymills 1:1dd9b8218515 105 }
ashleymills 1:1dd9b8218515 106 // this is a required callback for tinydtls it is called
ashleymills 1:1dd9b8218515 107 // whenever tinydtls handles a raw buffer through dtls_handle_message.
ashleymills 1:1dd9b8218515 108 // tinydtls extracts the unencrypted data and passes it onto this function
ashleymills 1:1dd9b8218515 109 int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
ashleymills 1:1dd9b8218515 110 DBG("read_from_peer called");
ashleymills 1:1dd9b8218515 111 size_t i;
ashleymills 1:1dd9b8218515 112 for (i = 0; i < len; i++)
ashleymills 1:1dd9b8218515 113 printf("%c", data[i]);
ashleymills 1:1dd9b8218515 114 return 0;
ashleymills 1:1dd9b8218515 115 }
ashleymills 1:1dd9b8218515 116
ashleymills 1:1dd9b8218515 117 /// this is a required callback for tinydtls it is called
ashleymills 1:1dd9b8218515 118 // whenever tinydtls needs to send a raw buffer (i.e whenever dtls_write is called by the application)
ashleymills 1:1dd9b8218515 119 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
ashleymills 1:1dd9b8218515 120 DBG("send_to_peer called");
ashleymills 1:1dd9b8218515 121 int fd = *(int *)dtls_get_app_data(ctx);
ashleymills 1:1dd9b8218515 122 return sendto(fd, data, len, MSG_DONTWAIT,
ashleymills 1:1dd9b8218515 123 &session->addr.sa, session->size);
ashleymills 1:1dd9b8218515 124 }
ashleymills 1:1dd9b8218515 125
ashleymills 1:1dd9b8218515 126 // this is used to handle incoming packets for tinydtls
ashleymills 1:1dd9b8218515 127 // raw buffers are passed to dtls_handle_message, who
ashleymills 1:1dd9b8218515 128 // processes them and passes the data onto the read callback
ashleymills 1:1dd9b8218515 129 int dtls_handle_read(struct dtls_context_t *ctx) {
ashleymills 1:1dd9b8218515 130 DBG("dtls_handle_read called");
ashleymills 1:1dd9b8218515 131 int fd;
ashleymills 1:1dd9b8218515 132 session_t session;
ashleymills 1:1dd9b8218515 133 #define MAX_READ_BUF 256
ashleymills 1:1dd9b8218515 134 static uint8 buf[MAX_READ_BUF];
ashleymills 1:1dd9b8218515 135 int len;
ashleymills 1:1dd9b8218515 136
ashleymills 1:1dd9b8218515 137 fd = *(int *)dtls_get_app_data(ctx);
ashleymills 1:1dd9b8218515 138
ashleymills 1:1dd9b8218515 139 memset(&session, 0, sizeof(session_t));
ashleymills 1:1dd9b8218515 140 session.size = sizeof(session.addr);
ashleymills 1:1dd9b8218515 141 len = recvfrom(fd, buf, MAX_READ_BUF, 0,
ashleymills 1:1dd9b8218515 142 &session.addr.sa, &session.size);
ashleymills 1:1dd9b8218515 143
ashleymills 1:1dd9b8218515 144 if(len < 0) {
ashleymills 1:1dd9b8218515 145 DBG("Got nothing from read");
ashleymills 1:1dd9b8218515 146 perror("recvfrom");
ashleymills 1:1dd9b8218515 147 return -1;
ashleymills 1:1dd9b8218515 148 } else {
ashleymills 1:1dd9b8218515 149 #if __DEBUG__ > 0
ashleymills 1:1dd9b8218515 150 unsigned char addrbuf[72];
ashleymills 1:1dd9b8218515 151 dsrv_print_addr(&session, addrbuf, sizeof(addrbuf));
ashleymills 1:1dd9b8218515 152 DBG("Got %d bytes from %s", len, (char *)addrbuf);
ashleymills 1:1dd9b8218515 153 dump((unsigned char *)&session, sizeof(session_t));
ashleymills 1:1dd9b8218515 154 DBGX("\r\n");
ashleymills 1:1dd9b8218515 155 dump(buf, len);
ashleymills 1:1dd9b8218515 156 DBGX("\r\n");
ashleymills 1:1dd9b8218515 157 #endif
ashleymills 1:1dd9b8218515 158 }
ashleymills 1:1dd9b8218515 159
ashleymills 1:1dd9b8218515 160 return dtls_handle_message(ctx, &session, buf, len);
ashleymills 1:1dd9b8218515 161 }
ashleymills 1:1dd9b8218515 162
ashleymills 1:1dd9b8218515 163 // callback called on tinydtls events (currently only ever called for DTLS_EVENT_CONNECTED)
ashleymills 1:1dd9b8218515 164 int event_handler(
ashleymills 1:1dd9b8218515 165 struct dtls_context_t *ctx,
ashleymills 1:1dd9b8218515 166 session_t *session,
ashleymills 1:1dd9b8218515 167 dtls_alert_level_t level,
ashleymills 1:1dd9b8218515 168 unsigned short code) {
ashleymills 1:1dd9b8218515 169 DBG("DTLS SESSION SETUP COMPLETE");
ashleymills 1:1dd9b8218515 170 gDTLSConnected = 1;
ashleymills 1:1dd9b8218515 171 return 0;
ashleymills 1:1dd9b8218515 172 }
ashleymills 1:1dd9b8218515 173
ashleymills 2:fe574f2c2b6a 174 // structure for required DTLS callbacks
ashleymills 1:1dd9b8218515 175 static dtls_handler_t cb = {
ashleymills 1:1dd9b8218515 176 .write = send_to_peer,
ashleymills 1:1dd9b8218515 177 .read = read_from_peer,
ashleymills 1:1dd9b8218515 178 .event = event_handler,
ashleymills 2:fe574f2c2b6a 179 .get_psk_key = get_psk_key,
ashleymills 2:fe574f2c2b6a 180 .get_ecdsa_key = NULL,// get_ecdsa_key,
ashleymills 2:fe574f2c2b6a 181 .verify_ecdsa_key = NULL//verify_ecdsa_key
ashleymills 1:1dd9b8218515 182 };
ashleymills 1:1dd9b8218515 183
ashleymills 0:6ae42a2aff75 184 int main() {
ashleymills 1:1dd9b8218515 185 DBG_INIT();
ashleymills 1:1dd9b8218515 186 DBG_SET_SPEED(115200);
ashleymills 1:1dd9b8218515 187 DBG_SET_NEWLINE("\r\n");
ashleymills 1:1dd9b8218515 188
ashleymills 1:1dd9b8218515 189 DBG("Tiny DTLS test");
ashleymills 1:1dd9b8218515 190
ashleymills 1:1dd9b8218515 191 // DTLS context struct
ashleymills 1:1dd9b8218515 192 dtls_context_t *dtls_context = NULL;
ashleymills 1:1dd9b8218515 193 int ret = 0, counter = 0;
ashleymills 1:1dd9b8218515 194 fd_set rfds, wfds;
ashleymills 1:1dd9b8218515 195 struct timeval timeout;
ashleymills 1:1dd9b8218515 196 char outBuf[64];
ashleymills 1:1dd9b8218515 197
ashleymills 1:1dd9b8218515 198 // structure for getting address of incoming packets
ashleymills 1:1dd9b8218515 199 sockaddr_in fromAddr;
ashleymills 1:1dd9b8218515 200 socklen_t fromAddrLen = sizeof(struct sockaddr_in);
ashleymills 1:1dd9b8218515 201 memset(&fromAddr,0x00,fromAddrLen);
ashleymills 1:1dd9b8218515 202
ashleymills 1:1dd9b8218515 203 // connect to cellular network
ashleymills 1:1dd9b8218515 204 VodafoneUSBModem modem;
ashleymills 1:1dd9b8218515 205 modem.connect(APN,APN_USERNAME,APN_PASSWORD);
ashleymills 1:1dd9b8218515 206
ashleymills 1:1dd9b8218515 207 // setup socket to remote server
ashleymills 1:1dd9b8218515 208 int sockfd = NULL;
ashleymills 1:1dd9b8218515 209 if(!connectToSocketUDP("109.74.199.96", 5683, &sockfd)) {
ashleymills 1:1dd9b8218515 210 DBG("Error connecting to socket");
ashleymills 1:1dd9b8218515 211 fail(1);
ashleymills 1:1dd9b8218515 212 }
ashleymills 1:1dd9b8218515 213 DBG("\"Connected\" to UDP socket");
ashleymills 1:1dd9b8218515 214 int on = 1;
ashleymills 1:1dd9b8218515 215 if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) {
ashleymills 1:1dd9b8218515 216 DBG("setsockopt SO_REUSEADDR: %s", strerror(errno));
ashleymills 1:1dd9b8218515 217 }
ashleymills 1:1dd9b8218515 218
ashleymills 1:1dd9b8218515 219 // tinydtls stuff
ashleymills 1:1dd9b8218515 220
ashleymills 1:1dd9b8218515 221 // destination address is stored in a session type
ashleymills 1:1dd9b8218515 222 session_t dst;
ashleymills 1:1dd9b8218515 223 memset(&dst, 0, sizeof(session_t));
ashleymills 1:1dd9b8218515 224 dst.size = sizeof(sockaddr_in);
ashleymills 1:1dd9b8218515 225 serverAddress.sin_len = dst.size;
ashleymills 1:1dd9b8218515 226 memcpy(&dst.addr.sa, &serverAddress, dst.size);
ashleymills 1:1dd9b8218515 227 //dst.addr.sin.sin_port = htons(4433);
ashleymills 1:1dd9b8218515 228
ashleymills 1:1dd9b8218515 229 // dtls init must always be called for memory allocation
ashleymills 1:1dd9b8218515 230 dtls_init();
ashleymills 1:1dd9b8218515 231 dtls_set_log_level(LOG_DEBUG);
ashleymills 1:1dd9b8218515 232 // setup DTLS context
ashleymills 1:1dd9b8218515 233 DBG("Creating DTLS context");
ashleymills 1:1dd9b8218515 234 dtls_context = dtls_new_context(&sockfd);
ashleymills 1:1dd9b8218515 235 if(!dtls_context) {
ashleymills 1:1dd9b8218515 236 DBG("Cannot create context");
ashleymills 1:1dd9b8218515 237 fail(3);
ashleymills 0:6ae42a2aff75 238 }
ashleymills 1:1dd9b8218515 239 DBG("DTLS context created");
ashleymills 1:1dd9b8218515 240
ashleymills 1:1dd9b8218515 241 // forced to use this call back system
ashleymills 1:1dd9b8218515 242
ashleymills 1:1dd9b8218515 243 dtls_set_handler(dtls_context, &cb);
ashleymills 1:1dd9b8218515 244
ashleymills 1:1dd9b8218515 245 DBG("Issuing dtls_connect");
ashleymills 1:1dd9b8218515 246 ret = dtls_connect(dtls_context, &dst);
ashleymills 1:1dd9b8218515 247 if(ret<0) {
ashleymills 1:1dd9b8218515 248 DBG("Error in dtls_connect: %d",ret);
ashleymills 1:1dd9b8218515 249 modem.disconnect();
ashleymills 1:1dd9b8218515 250 fail(4);
ashleymills 1:1dd9b8218515 251 }
ashleymills 1:1dd9b8218515 252 if(ret==0) {
ashleymills 1:1dd9b8218515 253 DBG("Channel already exists");
ashleymills 1:1dd9b8218515 254 modem.disconnect();
ashleymills 1:1dd9b8218515 255 fail(5);
ashleymills 1:1dd9b8218515 256 }
ashleymills 1:1dd9b8218515 257 DBG("dtls_connect successfull");
ashleymills 1:1dd9b8218515 258 while (1) {
ashleymills 1:1dd9b8218515 259 // setup file descriptor lists for select
ashleymills 1:1dd9b8218515 260 FD_ZERO(&rfds);
ashleymills 1:1dd9b8218515 261 FD_ZERO(&wfds);
ashleymills 1:1dd9b8218515 262 //FD_SET(fileno(stdin), &rfds);
ashleymills 1:1dd9b8218515 263 FD_SET(sockfd, &rfds);
ashleymills 1:1dd9b8218515 264 // FD_SET(sockfd, &wfds);
ashleymills 1:1dd9b8218515 265
ashleymills 1:1dd9b8218515 266 timeout.tv_sec = 5;
ashleymills 1:1dd9b8218515 267 timeout.tv_usec = 0;
ashleymills 1:1dd9b8218515 268
ashleymills 1:1dd9b8218515 269 int result = select(sockfd+1, &rfds, &wfds, 0, &timeout);
ashleymills 1:1dd9b8218515 270
ashleymills 1:1dd9b8218515 271 if(result < 0) { // error
ashleymills 1:1dd9b8218515 272 if (errno != EINTR)
ashleymills 1:1dd9b8218515 273 perror("select");
ashleymills 1:1dd9b8218515 274 } else if (result == 0) {
ashleymills 1:1dd9b8218515 275 // timeout
ashleymills 1:1dd9b8218515 276 DBG("select timeout");
ashleymills 1:1dd9b8218515 277 // if we are connected, send some random data (every time select times out)
ashleymills 1:1dd9b8218515 278 // heh, abusing select as a timer
ashleymills 1:1dd9b8218515 279 if(gDTLSConnected) {
ashleymills 1:1dd9b8218515 280 sprintf(outBuf,"This is a pointless test message: %d\r\n",counter++);
ashleymills 1:1dd9b8218515 281 dtls_write(dtls_context, &dst, (uint8 *)outBuf, strlen(outBuf));
ashleymills 1:1dd9b8218515 282 //try_send(dtls_context, &dst);
ashleymills 1:1dd9b8218515 283 }
ashleymills 1:1dd9b8218515 284 } else {
ashleymills 1:1dd9b8218515 285 // OK
ashleymills 1:1dd9b8218515 286 // check which file descriptor had an event
ashleymills 1:1dd9b8218515 287 if(FD_ISSET(sockfd, &wfds)) {
ashleymills 1:1dd9b8218515 288 // FIXME (from tinydtls)
ashleymills 1:1dd9b8218515 289 } else if (FD_ISSET(sockfd, &rfds))
ashleymills 1:1dd9b8218515 290 if(dtls_handle_read(dtls_context)<0) {
ashleymills 1:1dd9b8218515 291 modem.disconnect();
ashleymills 1:1dd9b8218515 292 fail(6);
ashleymills 1:1dd9b8218515 293 }
ashleymills 1:1dd9b8218515 294 }
ashleymills 1:1dd9b8218515 295 //else if (FD_ISSET(fileno(stdin), &rfds))
ashleymills 1:1dd9b8218515 296 //handle_stdin();
ashleymills 1:1dd9b8218515 297 //}
ashleymills 1:1dd9b8218515 298
ashleymills 1:1dd9b8218515 299
ashleymills 1:1dd9b8218515 300 }
ashleymills 1:1dd9b8218515 301
ashleymills 0:6ae42a2aff75 302 }