Ethernet test for tinydtls-0.5.0
Dependencies: EthernetInterface mbed-rtos mbed tinydtls
Fork of tinydtls_test_ethernet by
Diff: main.cpp
- Revision:
- 1:391ec57807fa
- Parent:
- 0:6ae42a2aff75
- Child:
- 2:21019cad4c93
--- a/main.cpp Wed Oct 09 14:48:52 2013 +0000 +++ b/main.cpp Thu Oct 10 21:38:25 2013 +0000 @@ -1,16 +1,379 @@ +#define __DEBUG__ 4 + +#ifndef __MODULE__ +#define __MODULE__ "main.cpp" +#endif + #include "mbed.h" #include "rtos.h" -#include "VodafoneUSBModem.h" #include "bsd_socket.h" -#include "dtls.h" +#include <dtls.h> +#include "global.h" +#include "debug.h" +#include "errno.h" +#include "dbg.h" + +#include "EthernetInterface.h" DigitalOut myled(LED1); +void fail(int code) { + while(1) { + myled = !myled; + Thread::wait(100); + } +} + +/* This function is the "key store" for tinyDTLS. It is called to + * retrieve a key for the given identiy within this particular + * session. */ +int +get_key(struct dtls_context_t *ctx, + const session_t *session, + const unsigned char *id, size_t id_len, + const dtls_key_t **result) { + DBG("Entered get_key"); + + static const dtls_key_t psk = { + .type = DTLS_KEY_PSK, + .key.psk.id = (unsigned char *)"Client_identity", + .key.psk.id_length = 15, + .key.psk.key = (unsigned char *)"secretPSK", + .key.psk.key_length = 9 + }; + + *result = &psk; + return 0; +} + +#define APN_GDSP +//#define APN_CONTRACT + +#ifdef APN_GDSP + #define APN "ppinternetd.gdsp" + #define APN_USERNAME "" + #define APN_PASSWORD "" +#endif + +#ifdef APN_CONTRACT + #define APN "internet" + #define APN_USERNAME "web" + #define APN_PASSWORD "web" +#endif + +/* stolen from libcoap: */ +int +resolve_address(const char *server, struct sockaddr *dst) { + + struct addrinfo *res, *ainfo; + struct addrinfo hints; + static char addrstr[256]; + int error; + + memset(addrstr, 0, sizeof(addrstr)); + if (server && strlen(server) > 0) + memcpy(addrstr, server, strlen(server)); + else + memcpy(addrstr, "localhost", 9); + + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; + + error = getaddrinfo(addrstr, "", &hints, &res); + + if (error != 0) { + DBG("Some bullshit error");//fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); + return error; + } + + for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) { + + switch (ainfo->ai_family) { + case AF_INET: + + memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen); + return ainfo->ai_addrlen; + default: + ; + } + } + + freeaddrinfo(res); + return -1; +} + + +sockaddr_in bindAddr,serverAddress; +bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) { + *sockfd = -1; + // create the socket + if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) { + DBG("Error opening socket"); + return false; + } + socklen_t sockAddrInLen = sizeof(struct sockaddr_in); + + // bind socket + memset(&bindAddr, 0x00, sockAddrInLen); + bindAddr.sin_family = AF_INET; // IP family + bindAddr.sin_port = htons(port); + bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation + // call bind + if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) { + DBG("Error binding socket"); + perror(NULL); + } + + INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port)); + + // create the socket address + memset(&serverAddress, 0x00, sizeof(struct sockaddr_in)); + serverAddress.sin_addr.s_addr = inet_addr(ipAddress); + serverAddress.sin_family = AF_INET; + serverAddress.sin_port = htons(port); + + // do socket connect + //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port)); + if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) { + shutdown(*sockfd,SHUT_RDWR); + close(*sockfd); + DBG("Could not connect"); + return false; + } + return true; +} + +int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { + DBG("read_from_peer called"); + size_t i; + for (i = 0; i < len; i++) + printf("%c", data[i]); + return 0; +} + +int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { + DBG("send_to_peer called"); + int fd = *(int *)dtls_get_app_data(ctx); + return sendto(fd, data, len, MSG_DONTWAIT, + &session->addr.sa, session->size); +} + + +int +dtls_handle_read(struct dtls_context_t *ctx) { + DBG("dtls_handle_read called"); + int fd; + session_t session; +#define MAX_READ_BUF 512 + static uint8 buf[MAX_READ_BUF]; + int len; + + fd = *(int *)dtls_get_app_data(ctx); + /* + if(!fd) { + DBG("FD NULL"); + return -1; + }*/ + + memset(&session, 0x00, sizeof(session_t)); + DBG("BEFORE: "); + for(uint8_t i=0; i<sizeof(session_t); i++) { + DBGX("%x ",((uint8_t*)&session)[i]); + } + DBGX("\r\n"); + session.size = sizeof(sockaddr_in); + uint32_t bullshit = sizeof(sockaddr_in); + len = recvfrom(fd, buf, MAX_READ_BUF, 0, + &session.addr.sa, &bullshit); + + //((uint8_t*)&session)[4] = 0x00; + //session.addr.sin.sin_family = AF_INET; + DBG("AFTER: %d",bullshit); + for(uint8_t i=0; i<sizeof(session_t); i++) { + DBGX("%x ",((uint8_t*)&session)[i]); + } + DBGX("\r\n"); + short x = session.addr.sin.sin_family; + if(session.addr.sin.sin_family==AF_INET) { + DBG("AF_INET alright"); + } + DBG("%x %x",((uint8_t*)x)[0],((uint8_t*)x)[1]); + if (len < 0) { + DBG("Got nothing from read"); + perror("recvfrom"); + return -1; + } else { +#ifndef NDEBUG + unsigned char addrbuf[72]; + dsrv_print_addr(&session, addrbuf, sizeof(addrbuf)); + DBG("got %d bytes from %s\n", len, (char *)addrbuf); + dump((unsigned char *)&session, sizeof(session_t)); + DBGX("\r\n"); + dump(buf, len); + DBGX("\r\n"); +#endif + } + + return dtls_handle_message(ctx, &session, buf, len); +} + +static dtls_handler_t cb = { + .write = send_to_peer, + .read = read_from_peer, + .event = NULL, + .get_key = get_key + }; + int main() { - while(1) { - myled = 1; - wait(0.2); - myled = 0; - wait(0.2); + DBG_INIT(); + DBG_SET_SPEED(115200); + DBG_SET_NEWLINE("\r\n"); + + DBG("Tiny DTLS test"); + + // DTLS context struct + dtls_context_t *dtls_context = NULL; + int ret = 0; + fd_set rfds, wfds; + struct timeval timeout; + session_t dst; + + // structure for getting address of incoming packets + sockaddr_in fromAddr; + socklen_t fromAddrLen = sizeof(struct sockaddr_in); + memset(&fromAddr,0x00,fromAddrLen); + + // connect to cellular network + /* + VodafoneUSBModem modem; + modem.connect(APN,APN_USERNAME,APN_PASSWORD); + */ + EthernetInterface modem; + DBG("Connecting to network interface"); + modem.init(); + if(modem.connect(10000)) { + DBG("Error initialising ethernet interface"); + } + DBG("DONE."); + + dtls_init(); + dtls_set_log_level(LOG_DEBUG); + + // setup socket to remote server + int sockfd = NULL; + + + //if(!connectToSocketUDP("109.74.199.96", 5683, &sockfd)) { + if(!connectToSocketUDP("192.168.1.99", 4433, &sockfd)) { + DBG("Error connecting to socket"); + fail(1); } + DBG("\"Connected\" to UDP socket, sockfd: %d",sockfd); + /* + int on = 1; + if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) { + dsrv_log(LOG_ALERT, "setsockopt SO_REUSEADDR: %s\n", strerror(errno)); + }*/ + + /* + memset(&dst, 0, sizeof(session_t)); + // resolve destination address where server should be sent + //int res = resolve_address("192.168.1.99", &dst.addr.sa); + int res = resolve_address("109.74.199.96", &dst.addr.sa); + if (res < 0) { + dsrv_log(LOG_EMERG, "failed to resolve address\n"); + fail(9); + } + dst.size = res; + + // use port number from command line when specified or the listen port, otherwise + dst.addr.sin.sin_port = htons(4433);//atoi(optind < argc ? argv[optind++] : port_str)); + + // init socket and set it to non-blocking + sockfd = socket(dst.addr.sa.sa_family, SOCK_DGRAM, 0); + if (sockfd < 0) { + dsrv_log(LOG_ALERT, "socket: %s\n", strerror(errno)); + return 0; + }*/ + + // tinydtls stuff + + // destination address is stored in a session type + + memset(&dst, 0x00, sizeof(session_t)); + dst.size = sizeof(sockaddr_in); + DBG("starting copy at offset: %d",(int)&dst.addr-(int)&dst); + serverAddress.sin_len = dst.size; + memcpy(&dst.addr, &serverAddress, dst.size); + + + //dst.addr.sin.sin_port = htons(4433); + + // dtls init must always be called for memory allocation + + // setup DTLS context + DBG("Creating DTLS context"); + dtls_context = dtls_new_context(&sockfd); + if(!dtls_context) { + DBG("Cannot create context"); + fail(3); + } + DBG("DTLS context created"); + + // forced to use this call back system + + dtls_set_handler(dtls_context, &cb); + + DBG("Issuing dtls_connect"); + ret = dtls_connect(dtls_context, &dst); + if(ret<0) { + DBG("Error in dtls_connect: %d",ret); + modem.disconnect(); + fail(4); + } + if(ret==0) { + DBG("Channel already exists"); + modem.disconnect(); + fail(5); + } + DBG("dtls_connect successfull"); + while (1) { + // setup file descriptor lists for select + FD_ZERO(&rfds); + FD_ZERO(&wfds); + //FD_SET(fileno(stdin), &rfds); + FD_SET(sockfd, &rfds); + // FD_SET(sockfd, &wfds); + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + int result = select(sockfd+1, &rfds, &wfds, 0, &timeout); + + if(result < 0) { // error + if (errno != EINTR) + perror("select"); + } else if (result == 0) { + // timeout + } else { + // OK + // check which file descriptor had an event + if(FD_ISSET(sockfd, &wfds)) { + // FIXME (from tinydtls) + } else if (FD_ISSET(sockfd, &rfds)) + if(dtls_handle_read(dtls_context)<0) { + modem.disconnect(); + fail(6); + } + } + //else if (FD_ISSET(fileno(stdin), &rfds)) + //handle_stdin(); + //} + + //if(len) { + // try_send(dtls_context, &dst); + //} + } + }