wrapper of the mbed port of Cyassl. It's based of the work of Ashley Mills

Dependencies:   cyassl-lib

Dependents:   TLS_cyassl-Example TLS_cyassl-Example2 HTTPSClientExample2

Fork of TLS_cyassl by Francois Berder

Import programTLS_cyassl-Example

This program shows how to use TLS_cyassl to connect to mbed.org

Import programTLS_cyassl-Example2

This example show how to create a small TLS server using the TLS_cyassl library.

Files at this revision

API Documentation at this revision

Comitter:
feb11
Date:
Thu Sep 12 16:37:08 2013 +0000
Child:
1:9494492e9bf7
Commit message:
initial import

Changed in this revision

TLSConnection.cpp Show annotated file Show diff for this revision Revisions of this file
TLSConnection.h Show annotated file Show diff for this revision Revisions of this file
bsd_socket.h Show annotated file Show diff for this revision Revisions of this file
cert.h Show annotated file Show diff for this revision Revisions of this file
cyassl-lib.lib Show annotated file Show diff for this revision Revisions of this file
dbg.cpp Show annotated file Show diff for this revision Revisions of this file
dbg.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TLSConnection.cpp	Thu Sep 12 16:37:08 2013 +0000
@@ -0,0 +1,119 @@
+#define __DEBUG__ 4 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "TLSConnection.cpp"
+#endif
+
+#include "dbg.h"
+#include "TLSConnection.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include "bsd_socket.h"
+#include "cert.h"
+#undef NO_CERTS
+#undef NO_FILESYSTEM
+#include "ssl.h"
+#include "logging.h"
+
+const static int HTTPS_PORT = 443;
+
+void printError(CYASSL *ssl, int resultCode) {
+/*
+   int err = CyaSSL_get_error(ssl, resultCode);
+   char errorString[80];
+   CyaSSL_ERR_error_string(err, errorString);
+   printf("Error: CyaSSL_write %s\n", errorString);
+*/
+}
+
+TLSConnection::TLSConnection():
+    Socket(),
+    Endpoint(),
+    _is_connected(false),
+    _ssl_ctx(),
+    _ssl()
+{
+}
+
+void debugCallback(const int logLevel,const char *const logMessage) {
+   //DBG(logMessage);
+}
+
+bool TLSConnection::connect(const char *host)
+{
+    if (init_socket(SOCK_STREAM) < 0)
+        return false;
+
+    if (set_address(host, HTTPS_PORT) != 0)
+        return false;
+
+    if (lwip_connect(_sock_fd, (const struct sockaddr *) &_remoteHost, sizeof(_remoteHost)) < 0) {
+        close();
+        return false;
+    }
+    
+    CyaSSL_Init();
+    CyaSSL_Debugging_ON();
+
+    CyaSSL_SetLoggingCb(&debugCallback);
+
+    CYASSL_METHOD* method = CyaTLSv1_2_client_method();
+    if(method == NULL) 
+    {
+        return false;
+    }
+   
+    _ssl_ctx = CyaSSL_CTX_new(method);
+    if(_ssl_ctx == NULL)
+    {
+        return false;
+    }    
+    CyaSSL_CTX_load_verify_buffer(_ssl_ctx,(unsigned char*)root_cert, root_cert_len,SSL_FILETYPE_ASN1);
+   
+    _ssl = CyaSSL_new(_ssl_ctx);
+    if(_ssl == NULL) 
+    {
+        return false;
+    }
+   
+    CyaSSL_set_fd(_ssl, _sock_fd);
+
+    int result = CyaSSL_connect(_ssl);
+    if(result!=SSL_SUCCESS) 
+    {
+        printError(_ssl,result);
+        return false;
+    }  
+
+    _is_connected = true;
+
+    return true;
+}
+
+bool TLSConnection::is_connected(void)
+{
+    return _is_connected;
+}
+
+int TLSConnection::send_all(char *data, int length)
+{
+    return 0;
+}
+
+int TLSConnection::receive(char *data, int length)
+{
+    return 0;
+}
+
+bool TLSConnection::close(bool shutdown)
+{
+    if(!_is_connected)
+        return true;
+
+    _is_connected = false;
+
+    CyaSSL_CTX_free(_ssl_ctx);
+    CyaSSL_Cleanup();  
+
+    return Socket::close(shutdown) == 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TLSConnection.h	Thu Sep 12 16:37:08 2013 +0000
@@ -0,0 +1,73 @@
+#ifndef TLSCONNECTION_H
+#define TLSCONNECTION_H
+
+#include "Socket.h"
+#include "Endpoint.h"
+#include "ssl.h"
+
+/** This class provides a user-friendly interface for the
+    axTLS library.
+*/
+class TLSConnection : public Socket, public Endpoint
+{
+public :
+
+    TLSConnection();
+
+    /** This function tries to establish a TLS connection
+        with the given host.
+        It will first try to establish a TCP connection on
+        port 443 with the host. Then, it runs the TLS 
+        handshake protocol.
+
+        \param host A valid hostname (e.g. "mbed.org")
+        \return True if it managed to establish a connection
+        with the host. False otherwise.
+    */
+    bool connect(const char *host);
+
+    /** Indicates whether a connection is established or not.
+
+        \return true if a connection is established, otherwise
+       returns false.
+    */
+    bool is_connected(void);
+
+    /** Sends some data to the host. This method does not return
+        until length bytes have been sent.
+
+        \param data A pointer to some data
+        \param length Number of bytes to send
+        \return Number of bytes sent, or -1 if an error occured.
+    */
+    int send_all(char *data, int length);
+
+    /** Receive some data from the host.
+
+        \param data
+        \param length Maximum number of bytes to receive
+        \return Number of bytes read in range 0..length, or -1
+        if an error occured.
+    */
+    int receive(char *data, int length);
+
+    /** Close the connection.
+
+        \param shutdown
+        \return True if the connection was closed with success,
+        false otherwise. If no connection was established,
+        returns true immediately.
+    */
+    bool close(bool shutdown = true);
+
+private :
+
+    bool _is_connected;
+
+    CYASSL_CTX *_ssl_ctx;
+    CYASSL *_ssl;
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsd_socket.h	Thu Sep 12 16:37:08 2013 +0000
@@ -0,0 +1,140 @@
+#ifndef BSD_SOCKET_H_
+#define BSD_SOCKET_H_
+ 
+#ifdef __cplusplus
+extern "C" {
+#endif
+ 
+#include "lwip/sockets.h"
+ 
+#include "lwip/inet.h"
+ 
+#include "lwip/netdb.h"
+ 
+//Sockets
+ 
+inline int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+  return lwip_accept(s, addr, addrlen);
+}
+ 
+inline int bind(int s, const struct sockaddr *name, socklen_t namelen)
+{
+  return lwip_bind(s, name, namelen);
+}
+ 
+inline int shutdown(int s, int how)
+{
+  return lwip_shutdown(s, how);
+}
+ 
+inline int getsockname (int s, struct sockaddr *name, socklen_t *namelen)
+{
+  return lwip_getsockname(s, name, namelen);
+}
+ 
+inline int getpeername (int s, struct sockaddr *name, socklen_t *namelen)
+{
+  return lwip_getpeername(s, name, namelen);
+}
+ 
+inline int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+  return lwip_getsockopt(s, level, optname, optval, optlen);
+}
+ 
+inline int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+  return lwip_setsockopt(s, level, optname, optval, optlen);
+}
+ 
+inline int connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+  return lwip_connect(s, name, namelen);
+}
+ 
+inline int listen(int s, int backlog)
+{
+  return lwip_listen(s, backlog);
+}
+ 
+inline int recv(int s, void *mem, size_t len, int flags)
+{
+  return lwip_recv(s, mem, len, flags);
+}
+ 
+inline int recvfrom(int s, void *mem, size_t len, int flags,
+      struct sockaddr *from, socklen_t *fromlen)
+{
+  return lwip_recvfrom(s, mem, len, flags, from, fromlen);
+}
+ 
+inline int send(int s, const void *dataptr, size_t size, int flags)
+{
+  return lwip_send(s, dataptr, size, flags);
+}
+ 
+inline int sendto(int s, const void *dataptr, size_t size, int flags,
+    const struct sockaddr *to, socklen_t tolen)
+{
+  return lwip_sendto(s, dataptr, size, flags, to, tolen);
+}
+ 
+inline int socket(int domain, int type, int protocol)
+{
+  return lwip_socket(domain, type, protocol);
+}
+ 
+inline int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+                struct timeval *timeout)
+{
+  return lwip_select(maxfdp1, readset, writeset, exceptset, timeout);
+}
+ 
+inline int ioctlsocket(int s, long cmd, void *argp)
+{
+  return lwip_ioctl(s, cmd, argp);
+}
+ 
+inline int read(int s, void *mem, size_t len)
+{
+  return lwip_read(s, mem, len);
+}
+ 
+inline int write(int s, const void *dataptr, size_t size)
+{
+  return lwip_write(s, dataptr, size);
+}
+ 
+inline int close(int s)
+{
+  return lwip_close(s);
+}
+ 
+//DNS
+/*
+inline struct hostent *gethostbyname(const char *name)
+{
+  return lwip_gethostbyname(name);
+}
+ 
+inline int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop)
+{
+  return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
+}*/
+ 
+inline void freeaddrinfo(struct addrinfo *ai)
+{
+  return lwip_freeaddrinfo(ai);
+}
+ 
+inline int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
+{
+  return lwip_getaddrinfo(nodename, servname, hints, res);
+}
+ 
+#ifdef __cplusplus
+}
+#endif
+ 
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cert.h	Thu Sep 12 16:37:08 2013 +0000
@@ -0,0 +1,41 @@
+static const uint8_t root_cert[] =
+{
+    0x30 ,0x82 ,0x02 ,0x3C ,0x30 ,0x82 ,0x01 ,0xA5 ,0x02 ,0x10 ,0x3C ,0x91 ,0x31 ,0xCB ,0x1F ,0xF6,
+    0xD0 ,0x1B ,0x0E ,0x9A ,0xB8 ,0xD0 ,0x44 ,0xBF ,0x12 ,0xBE ,0x30 ,0x0D ,0x06 ,0x09 ,0x2A ,0x86,
+    0x48 ,0x86 ,0xF7 ,0x0D ,0x01 ,0x01 ,0x05 ,0x05 ,0x00 ,0x30 ,0x5F ,0x31 ,0x0B ,0x30 ,0x09 ,0x06,
+    0x03 ,0x55 ,0x04 ,0x06 ,0x13 ,0x02 ,0x55 ,0x53 ,0x31 ,0x17 ,0x30 ,0x15 ,0x06 ,0x03 ,0x55 ,0x04,
+    0x0A ,0x13 ,0x0E ,0x56 ,0x65 ,0x72 ,0x69 ,0x53 ,0x69 ,0x67 ,0x6E ,0x2C ,0x20 ,0x49 ,0x6E ,0x63,
+    0x2E ,0x31 ,0x37 ,0x30 ,0x35 ,0x06 ,0x03 ,0x55 ,0x04 ,0x0B ,0x13 ,0x2E ,0x43 ,0x6C ,0x61 ,0x73,
+    0x73 ,0x20 ,0x33 ,0x20 ,0x50 ,0x75 ,0x62 ,0x6C ,0x69 ,0x63 ,0x20 ,0x50 ,0x72 ,0x69 ,0x6D ,0x61,
+    0x72 ,0x79 ,0x20 ,0x43 ,0x65 ,0x72 ,0x74 ,0x69 ,0x66 ,0x69 ,0x63 ,0x61 ,0x74 ,0x69 ,0x6F ,0x6E,
+    0x20 ,0x41 ,0x75 ,0x74 ,0x68 ,0x6F ,0x72 ,0x69 ,0x74 ,0x79 ,0x30 ,0x1E ,0x17 ,0x0D ,0x39 ,0x36,
+    0x30 ,0x31 ,0x32 ,0x39 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x30 ,0x5A ,0x17 ,0x0D ,0x32 ,0x38 ,0x30,
+    0x38 ,0x30 ,0x32 ,0x32 ,0x33 ,0x35 ,0x39 ,0x35 ,0x39 ,0x5A ,0x30 ,0x5F ,0x31 ,0x0B ,0x30 ,0x09,
+    0x06 ,0x03 ,0x55 ,0x04 ,0x06 ,0x13 ,0x02 ,0x55 ,0x53 ,0x31 ,0x17 ,0x30 ,0x15 ,0x06 ,0x03 ,0x55,
+    0x04 ,0x0A ,0x13 ,0x0E ,0x56 ,0x65 ,0x72 ,0x69 ,0x53 ,0x69 ,0x67 ,0x6E ,0x2C ,0x20 ,0x49 ,0x6E,
+    0x63 ,0x2E ,0x31 ,0x37 ,0x30 ,0x35 ,0x06 ,0x03 ,0x55 ,0x04 ,0x0B ,0x13 ,0x2E ,0x43 ,0x6C ,0x61,
+    0x73 ,0x73 ,0x20 ,0x33 ,0x20 ,0x50 ,0x75 ,0x62 ,0x6C ,0x69 ,0x63 ,0x20 ,0x50 ,0x72 ,0x69 ,0x6D,
+    0x61 ,0x72 ,0x79 ,0x20 ,0x43 ,0x65 ,0x72 ,0x74 ,0x69 ,0x66 ,0x69 ,0x63 ,0x61 ,0x74 ,0x69 ,0x6F,
+    0x6E ,0x20 ,0x41 ,0x75 ,0x74 ,0x68 ,0x6F ,0x72 ,0x69 ,0x74 ,0x79 ,0x30 ,0x81 ,0x9F ,0x30 ,0x0D,
+    0x06 ,0x09 ,0x2A ,0x86 ,0x48 ,0x86 ,0xF7 ,0x0D ,0x01 ,0x01 ,0x01 ,0x05 ,0x00 ,0x03 ,0x81 ,0x8D,
+    0x00 ,0x30 ,0x81 ,0x89 ,0x02 ,0x81 ,0x81 ,0x00 ,0xC9 ,0x5C ,0x59 ,0x9E ,0xF2 ,0x1B ,0x8A ,0x01,
+    0x14 ,0xB4 ,0x10 ,0xDF ,0x04 ,0x40 ,0xDB ,0xE3 ,0x57 ,0xAF ,0x6A ,0x45 ,0x40 ,0x8F ,0x84 ,0x0C,
+    0x0B ,0xD1 ,0x33 ,0xD9 ,0xD9 ,0x11 ,0xCF ,0xEE ,0x02 ,0x58 ,0x1F ,0x25 ,0xF7 ,0x2A ,0xA8 ,0x44,
+    0x05 ,0xAA ,0xEC ,0x03 ,0x1F ,0x78 ,0x7F ,0x9E ,0x93 ,0xB9 ,0x9A ,0x00 ,0xAA ,0x23 ,0x7D ,0xD6,
+    0xAC ,0x85 ,0xA2 ,0x63 ,0x45 ,0xC7 ,0x72 ,0x27 ,0xCC ,0xF4 ,0x4C ,0xC6 ,0x75 ,0x71 ,0xD2 ,0x39,
+    0xEF ,0x4F ,0x42 ,0xF0 ,0x75 ,0xDF ,0x0A ,0x90 ,0xC6 ,0x8E ,0x20 ,0x6F ,0x98 ,0x0F ,0xF8 ,0xAC,
+    0x23 ,0x5F ,0x70 ,0x29 ,0x36 ,0xA4 ,0xC9 ,0x86 ,0xE7 ,0xB1 ,0x9A ,0x20 ,0xCB ,0x53 ,0xA5 ,0x85,
+    0xE7 ,0x3D ,0xBE ,0x7D ,0x9A ,0xFE ,0x24 ,0x45 ,0x33 ,0xDC ,0x76 ,0x15 ,0xED ,0x0F ,0xA2 ,0x71,
+    0x64 ,0x4C ,0x65 ,0x2E ,0x81 ,0x68 ,0x45 ,0xA7 ,0x02 ,0x03 ,0x01 ,0x00 ,0x01 ,0x30 ,0x0D ,0x06,
+    0x09 ,0x2A ,0x86 ,0x48 ,0x86 ,0xF7 ,0x0D ,0x01 ,0x01 ,0x05 ,0x05 ,0x00 ,0x03 ,0x81 ,0x81 ,0x00,
+    0x10 ,0x72 ,0x52 ,0xA9 ,0x05 ,0x14 ,0x19 ,0x32 ,0x08 ,0x41 ,0xF0 ,0xC5 ,0x6B ,0x0A ,0xCC ,0x7E,
+    0x0F ,0x21 ,0x19 ,0xCD ,0xE4 ,0x67 ,0xDC ,0x5F ,0xA9 ,0x1B ,0xE6 ,0xCA ,0xE8 ,0x73 ,0x9D ,0x22,
+    0xD8 ,0x98 ,0x6E ,0x73 ,0x03 ,0x61 ,0x91 ,0xC5 ,0x7C ,0xB0 ,0x45 ,0x40 ,0x6E ,0x44 ,0x9D ,0x8D,
+    0xB0 ,0xB1 ,0x96 ,0x74 ,0x61 ,0x2D ,0x0D ,0xA9 ,0x45 ,0xD2 ,0xA4 ,0x92 ,0x2A ,0xD6 ,0x9A ,0x75,
+    0x97 ,0x6E ,0x3F ,0x53 ,0xFD ,0x45 ,0x99 ,0x60 ,0x1D ,0xA8 ,0x2B ,0x4C ,0xF9 ,0x5E ,0xA7 ,0x09,
+    0xD8 ,0x75 ,0x30 ,0xD7 ,0xD2 ,0x65 ,0x60 ,0x3D ,0x67 ,0xD6 ,0x48 ,0x55 ,0x75 ,0x69 ,0x3F ,0x91,
+    0xF5 ,0x48 ,0x0B ,0x47 ,0x69 ,0x22 ,0x69 ,0x82 ,0x96 ,0xBE ,0xC9 ,0xC8 ,0x38 ,0x86 ,0x4A ,0x7A,
+    0x2C ,0x73 ,0x19 ,0x48 ,0x69 ,0x4E ,0x6B ,0x7C ,0x65 ,0xBF ,0x0F ,0xFC ,0x70 ,0xCE ,0x88 ,0x90
+};
+
+static const uint32_t root_cert_len = sizeof(root_cert);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cyassl-lib.lib	Thu Sep 12 16:37:08 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/feb11/code/cyassl-lib/#e784a2103975
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg.cpp	Thu Sep 12 16:37:08 2013 +0000
@@ -0,0 +1,127 @@
+/* dbg.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "dbg.h"
+
+#include "mbed.h"
+#include "rtos.h"
+
+#include <cstdio>
+#include <cstdarg>
+
+using namespace std;
+
+static Serial debug_pc(USBTX, USBRX);
+
+static char debug_newline[3];
+
+static void debug_lock(bool set)
+{
+  static Mutex* mtx = new Mutex(); //Singleton runtime initialisation to avoid static initialisation chaos problems
+  static bool init = false;
+  if(set)
+  {
+    mtx->lock();
+    if(!init)
+    {
+      strncpy( debug_newline, "\n", 2 );
+      printf("[START]\n");
+      fflush(stdout);
+      init = true;
+    }
+  }
+  else
+  {
+    mtx->unlock();
+  }
+}
+
+void debug_init()
+{
+  debug_lock(true); //Force init
+  debug_lock(false);
+}
+
+void debug_set_newline(const char* newline)
+{
+  debug_lock(true);
+  strncpy( debug_newline, newline, 2 );
+  debug_newline[2] = '\0';
+  debug_lock(false);
+}
+
+void debug_set_speed(int speed)
+{
+  debug_pc.baud(speed);
+}
+
+void debug(int level, const char* module, int line, const char* fmt, ...)
+{
+  debug_lock(true);
+  switch(level)
+  {
+  default:
+  case 1:
+    printf("[ERROR]");
+    break;
+  case 2:
+    printf("[WARN]");
+    break;
+  case 3:
+    printf("[INFO]");
+    break;
+  case 4:
+    printf("[DBG]");
+    break;
+  }
+
+  printf(" Module %s - Line %d: ", module, line);
+
+  va_list argp;
+
+  va_start(argp, fmt);
+  vprintf(fmt, argp);
+  va_end(argp);
+
+  printf(debug_newline);
+
+  fflush(stdout);
+
+  debug_lock(false);
+
+}
+
+void debug_error(const char* module, int line, int ret)
+{
+  debug_lock(true);
+  printf("[RC] Module %s - Line %d : Error %d\n", module, line, ret);
+  fflush(stdout);
+  debug_lock(false);
+}
+
+void debug_exact(const char* fmt, ...)
+{
+  debug_lock(true);
+  va_list argp;
+
+  va_start(argp, fmt);
+  vprintf(fmt, argp);
+  va_end(argp);
+  debug_lock(false);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg.h	Thu Sep 12 16:37:08 2013 +0000
@@ -0,0 +1,79 @@
+/* dbg.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DBG_H_
+#define DBG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void debug_init(void);
+void debug(int level, const char* module, int line, const char* fmt, ...);
+void debug_set_newline(const char* newline);
+void debug_set_speed(int speed);
+void debug_error(const char* module, int line, int ret);
+void debug_exact(const char* fmt, ...);
+
+#define DBG_INIT() do{ debug_init(); }while(0)
+
+#define DBG_SET_NEWLINE( x ) do{ debug_set_newline(x); }while(0)
+
+#define DBG_SET_SPEED( x ) do{ debug_set_speed(x); }while(0)
+
+#if __DEBUG__ > 0
+#ifndef __MODULE__
+#error "__MODULE__ must be defined"
+#endif
+#endif
+
+#if __DEBUG__ >= 1
+#define ERR(...) do{ debug(1, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define ERR(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 2
+#define WARN(...) do{ debug(2, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define WARN(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 3
+#define INFO(...) do{ debug(3, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define CHECK(ret) do{ if(ret){ debug_error(__MODULE__, __LINE__, ret); } }while(0)
+#else
+#define INFO(...) do{ }while(0)
+#define CHECK(ret) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 4
+#define DBG(...) do{ debug(4, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define DBGX(...) do{ debug_exact(__VA_ARGS__); }while(0)
+#else
+#define DBG(...) do{ }while(0)
+#define DBGX(...) do{ }while(0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DBG_H_ */