Ethernet test for tinydtls-0.5.0

Dependencies:   EthernetInterface mbed-rtos mbed tinydtls

Fork of tinydtls_test_ethernet by Ashley Mills

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #define __DEBUG__ 4
00002 
00003 #ifndef __MODULE__
00004 #define __MODULE__ "main.cpp"
00005 #endif
00006 
00007 #include "mbed.h"
00008 #include "rtos.h"
00009 #include "bsd_socket.h"
00010 
00011 #include "dtls.h"
00012 #include "global.h"
00013 #include "debug.h"
00014 #include "errno.h"
00015 #include "dbg.h"
00016 
00017 #include "EthernetInterface.h"
00018 DigitalOut myled(LED1);
00019 
00020 void fail(int code) {
00021    while(1) {
00022       myled = !myled;
00023       Thread::wait(100);
00024    }
00025 }
00026 
00027 static const unsigned char ecdsa_priv_key[] = {
00028             0x41, 0xC1, 0xCB, 0x6B, 0x51, 0x24, 0x7A, 0x14,
00029             0x43, 0x21, 0x43, 0x5B, 0x7A, 0x80, 0xE7, 0x14,
00030             0x89, 0x6A, 0x33, 0xBB, 0xAD, 0x72, 0x94, 0xCA,
00031             0x40, 0x14, 0x55, 0xA1, 0x94, 0xA9, 0x49, 0xFA};
00032 
00033 static const unsigned char ecdsa_pub_key_x[] = {
00034             0x36, 0xDF, 0xE2, 0xC6, 0xF9, 0xF2, 0xED, 0x29,
00035             0xDA, 0x0A, 0x9A, 0x8F, 0x62, 0x68, 0x4E, 0x91,
00036             0x63, 0x75, 0xBA, 0x10, 0x30, 0x0C, 0x28, 0xC5,
00037             0xE4, 0x7C, 0xFB, 0xF2, 0x5F, 0xA5, 0x8F, 0x52};
00038 
00039 static const unsigned char ecdsa_pub_key_y[] = {
00040             0x71, 0xA0, 0xD4, 0xFC, 0xDE, 0x1A, 0xB8, 0x78,
00041             0x5A, 0x3C, 0x78, 0x69, 0x35, 0xA7, 0xCF, 0xAB,
00042             0xE9, 0x3F, 0x98, 0x72, 0x09, 0xDA, 0xED, 0x0B,
00043             0x4F, 0xAB, 0xC3, 0x6F, 0xC7, 0x72, 0xF8, 0x29};
00044 
00045 
00046 static const dtls_psk_key_t client_psk = {
00047     .id = (unsigned char *)"Client_identity",
00048     .id_length = 15,
00049     .key = (unsigned char *)"secretPSK",
00050     .key_length = 9
00051 };
00052 
00053 /* This function is the "key store" for tinyDTLS. It is called to
00054  * retrieve a key for the given identiy within this particular
00055  * session. */
00056 int
00057 get_psk_key(struct dtls_context_t *ctx,
00058         const session_t *session,
00059         const unsigned char *id, size_t id_len,
00060         const dtls_psk_key_t **result) {
00061   DBG("id: %d, len: %d",id,id_len);
00062   *result = &client_psk;
00063 
00064   return 0;
00065 }
00066 
00067 int
00068 get_ecdsa_key(struct dtls_context_t *ctx,
00069           const session_t *session,
00070           const dtls_ecdsa_key_t **result) {
00071   static const dtls_ecdsa_key_t ecdsa_key = {
00072     .curve = DTLS_ECDH_CURVE_SECP256R1,
00073     .priv_key = ecdsa_priv_key,
00074     .pub_key_x = ecdsa_pub_key_x,
00075     .pub_key_y = ecdsa_pub_key_y
00076   };
00077 
00078   *result = &ecdsa_key;
00079   return 0;
00080 }
00081 
00082 int
00083 verify_ecdsa_key(struct dtls_context_t *ctx,
00084          const session_t *session,
00085          const unsigned char *other_pub_x,
00086          const unsigned char *other_pub_y,
00087          size_t key_size) {
00088   return 0;
00089 }
00090 
00091 
00092 #define APN_GDSP
00093 //#define APN_CONTRACT
00094 
00095 #ifdef APN_GDSP
00096    #define APN "ppinternetd.gdsp" 
00097    #define APN_USERNAME ""
00098    #define APN_PASSWORD ""
00099 #endif
00100 
00101 #ifdef APN_CONTRACT
00102    #define APN "internet" 
00103    #define APN_USERNAME "web"
00104    #define APN_PASSWORD "web"
00105 #endif
00106 
00107 sockaddr_in bindAddr,serverAddress;
00108 bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) {
00109   *sockfd = -1;
00110   // create the socket
00111   if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
00112      DBG("Error opening socket");
00113      return false;
00114   }
00115   socklen_t sockAddrInLen = sizeof(struct sockaddr_in);
00116    
00117   // bind socket
00118   memset(&bindAddr,  0x00, sockAddrInLen);
00119   bindAddr.sin_family = AF_INET; // IP family
00120   bindAddr.sin_port = htons(port);
00121   bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation
00122   // call bind
00123   if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) {
00124      DBG("Error binding socket");
00125      perror(NULL);
00126   }
00127 
00128   INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port));
00129          
00130   // create the socket address
00131   memset(&serverAddress, 0x00, sizeof(struct sockaddr_in));
00132   serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
00133   serverAddress.sin_family = AF_INET;
00134   serverAddress.sin_port = htons(port);
00135 
00136   // do socket connect
00137   //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
00138   if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
00139      shutdown(*sockfd,SHUT_RDWR);
00140      close(*sockfd);
00141      DBG("Could not connect");
00142      return false;
00143   }
00144   return true;
00145 }
00146 
00147 int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
00148   DBG("read_from_peer called: %d",len);
00149   size_t i;
00150   for (i = 0; i < len; i++)
00151     printf("%c", data[i]);
00152   return 0;
00153 }
00154 
00155 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
00156   DBG("send_to_peer called: %d",len);
00157   int fd = *(int *)dtls_get_app_data(ctx);
00158   return sendto(fd, data, len, MSG_DONTWAIT,
00159         &session->addr.sa, session->size);
00160 }
00161 
00162 
00163 int
00164 dtls_handle_read(struct dtls_context_t *ctx) {
00165   DBG("dtls_handle_read called");
00166   int fd;
00167   session_t session;
00168 #define MAX_READ_BUF 512
00169   static uint8 buf[MAX_READ_BUF];
00170   int len;
00171 
00172   fd = *(int *)dtls_get_app_data(ctx);
00173   /*
00174   if(!fd) {
00175      DBG("FD NULL");
00176      return -1;
00177   }*/
00178 
00179  memset(&session, 0, sizeof(session_t));
00180  session.size = sizeof(session.addr);
00181   len = recvfrom(fd, buf, MAX_READ_BUF, 0, 
00182          &session.addr.sa, &session.size);        
00183  
00184   if (len < 0) {
00185     DBG("Got nothing from read");
00186     perror("recvfrom");
00187     return -1;
00188   } else {
00189 #ifndef NDEBUG
00190     unsigned char addrbuf[72];
00191     dsrv_print_addr(&session, addrbuf, sizeof(addrbuf));
00192     DBG("got %d bytes from %s\n", len, (char *)addrbuf);
00193     /*
00194     dump((unsigned char *)&session, sizeof(session_t));
00195     DBGX("\r\n");
00196     dump(buf, len);
00197     DBGX("\r\n");
00198     */
00199 #endif
00200   }
00201 
00202   return dtls_handle_message(ctx, &session, buf, len);
00203 }    
00204 int gDTLSConnected = 0;
00205 
00206 // callback called on tinydtls events (currently only ever called for DTLS_EVENT_CONNECTED)
00207 int event_handler(
00208    struct dtls_context_t *ctx,
00209    session_t *session, 
00210    dtls_alert_level_t level,
00211    unsigned short code) {
00212    DBG("DTLS SESSION SETUP COMPLETE");
00213    gDTLSConnected = 1;
00214    return 0;
00215 }
00216 
00217 static dtls_handler_t cb = {
00218   .write = send_to_peer,
00219   .read  = read_from_peer,
00220   .event = event_handler,
00221   .get_psk_key = get_psk_key,
00222   .get_ecdsa_key = NULL,// get_ecdsa_key,
00223   .verify_ecdsa_key = NULL//verify_ecdsa_key
00224 };
00225 
00226 int main() {
00227     DBG_INIT();
00228     DBG_SET_SPEED(115200);
00229     DBG_SET_NEWLINE("\r\n");
00230     
00231     DBG("Tiny DTLS test");
00232 
00233     // DTLS context struct    
00234     dtls_context_t *dtls_context = NULL;
00235     int ret = 0;
00236     fd_set rfds, wfds;
00237     struct timeval timeout;
00238     session_t dst;
00239 
00240     // structure for getting address of incoming packets
00241     sockaddr_in fromAddr;
00242     socklen_t fromAddrLen = sizeof(struct sockaddr_in);
00243     memset(&fromAddr,0x00,fromAddrLen);
00244     
00245     // connect to cellular network
00246     /*
00247     VodafoneUSBModem modem;
00248     modem.connect(APN,APN_USERNAME,APN_PASSWORD);
00249     */
00250     EthernetInterface modem;
00251     DBG("Connecting to network interface");
00252     modem.init();
00253     if(modem.connect(10000)) {
00254        DBG("Error initialising ethernet interface");
00255     }
00256     DBG("DONE.");
00257     
00258     dtls_init();
00259     dtls_set_log_level(LOG_DEBUG);
00260 
00261     // setup socket to remote server
00262     int sockfd = NULL;
00263     
00264     
00265     //if(!connectToSocketUDP("109.74.199.96", 4433, &sockfd)) {
00266     if(!connectToSocketUDP("192.168.1.99", 4433, &sockfd)) {  
00267        DBG("Error connecting to socket");
00268        fail(1);
00269     }
00270     DBG("\"Connected\" to UDP socket, sockfd: %d",sockfd);
00271     
00272     int on = 1;
00273     if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) {
00274        dsrv_log(LOG_ALERT, "setsockopt SO_REUSEADDR: %s\n", strerror(errno));
00275     }
00276      
00277     // tinydtls stuff
00278     
00279     // destination address is stored in a session type
00280     
00281     memset(&dst, 0x00, sizeof(session_t));
00282     dst.size = sizeof(sockaddr_in);
00283     DBG("starting copy at offset: %d",(int)&dst.addr-(int)&dst);
00284     serverAddress.sin_len  = dst.size;
00285     memcpy(&dst.addr, &serverAddress, dst.size);
00286     
00287     
00288     //dst.addr.sin.sin_port = htons(4433);
00289     
00290     // dtls init must always be called for memory allocation
00291     
00292     // setup DTLS context
00293     DBG("Creating DTLS context");
00294     dtls_context = dtls_new_context(&sockfd);
00295     if(!dtls_context) {
00296        DBG("Cannot create context");
00297        fail(3);
00298     }
00299     DBG("DTLS context created");
00300     
00301     // forced to use this call back system
00302     
00303     dtls_set_handler(dtls_context, &cb);
00304     
00305     DBG("Issuing dtls_connect");
00306     ret = dtls_connect(dtls_context, &dst);
00307     if(ret<0) {
00308        DBG("Error in dtls_connect: %d",ret);
00309        modem.disconnect();
00310        fail(4);
00311     }
00312     if(ret==0) {
00313        DBG("Channel already exists");
00314        modem.disconnect();
00315        fail(5);
00316     }
00317     DBG("dtls_connect successfull");
00318     int counter = 0;
00319     char outBuf[64];
00320     while (1) {
00321         // setup file descriptor lists for select
00322         FD_ZERO(&rfds);
00323         FD_ZERO(&wfds);
00324         //FD_SET(fileno(stdin), &rfds);
00325         FD_SET(sockfd, &rfds);
00326         // FD_SET(sockfd, &wfds);
00327     
00328         timeout.tv_sec = 15;
00329         timeout.tv_usec = 0;
00330         DBG("Waiting for data");
00331         int result = select(sockfd+1, &rfds, &wfds, 0, &timeout);
00332     
00333         if(result < 0) { // error
00334         if (errno != EINTR)
00335             perror("select");
00336         } else if (result == 0) {
00337            // timeout
00338            if(gDTLSConnected) {
00339               DBG("Sending data");
00340               sprintf(outBuf,"This is a pointless test message: %d\r\n",counter++);
00341               dtls_write(dtls_context, &dst, (uint8 *)outBuf, strlen(outBuf));
00342               //try_send(dtls_context, &dst);
00343            }
00344         } else {
00345            // OK
00346            // check which file descriptor had an event
00347            if(FD_ISSET(sockfd, &wfds)) {
00348               // FIXME (from tinydtls)
00349            } else if (FD_ISSET(sockfd, &rfds))
00350               if(dtls_handle_read(dtls_context)<0) {
00351                  modem.disconnect();
00352                  fail(6);
00353               }
00354            } 
00355         //else if (FD_ISSET(fileno(stdin), &rfds))
00356            //handle_stdin();
00357         //}
00358 
00359        //if(len) {
00360        //  try_send(dtls_context, &dst);
00361        //}
00362   }
00363 
00364 }