wrapper of the mbed port of Cyassl. It's based of the work of Ashley Mills
Dependents: TLS_cyassl-Example TLS_cyassl-Example2 HTTPSClientExample2
Fork of TLS_cyassl by
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.
Revision 0:815067fd66c9, committed 2013-09-12
- Comitter:
- feb11
- Date:
- Thu Sep 12 16:37:08 2013 +0000
- Child:
- 1:9494492e9bf7
- Commit message:
- initial import
Changed in this revision
--- /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_ */