mirror of
				https://github.com/espressif/esp-protocols.git
				synced 2025-10-30 22:21:39 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			153 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
 | |
|  *
 | |
|  * SPDX-License-Identifier: Unlicense OR CC0-1.0
 | |
|  */
 | |
| #include <sys/socket.h>
 | |
| #include <netdb.h>
 | |
| #include <unistd.h>
 | |
| #include "esp_log.h"
 | |
| #include "mbedtls_wrap.hpp"
 | |
| 
 | |
| using namespace idf::mbedtls_cxx;
 | |
| 
 | |
| namespace {
 | |
| constexpr auto *TAG = "simple_tls_client";
 | |
| }
 | |
| 
 | |
| class TlsSocketClient: public Tls {
 | |
| public:
 | |
|     TlsSocketClient() = default;
 | |
|     ~TlsSocketClient() override
 | |
|     {
 | |
|         if (sock >= 0) {
 | |
|             ::close(sock);
 | |
|         }
 | |
|     }
 | |
|     int send(const unsigned char *buf, size_t len) override
 | |
|     {
 | |
|         return ::send(sock, buf, len, 0);
 | |
|     }
 | |
|     int recv(unsigned char *buf, size_t len) override
 | |
|     {
 | |
|         return ::recv(sock, buf, len, 0);
 | |
|     }
 | |
|     bool connect(const char *host, int port)
 | |
|     {
 | |
|         addr_info addr(host, AF_INET, SOCK_STREAM);
 | |
|         if (!addr) {
 | |
|             ESP_LOGE(TAG, "Failed to resolve host");
 | |
|             return false;
 | |
|         }
 | |
|         sock = addr.get_sock();
 | |
|         if (sock < 0) {
 | |
|             ESP_LOGE(TAG, "Failed to create socket");
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         if (::connect(sock, addr.get_addr(port), sizeof(struct sockaddr)) < 0) {
 | |
|             ESP_LOGE(TAG, "Failed to connect %d", errno);
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         if (!init(is_server{false}, do_verify{false})) {
 | |
|             return false;
 | |
|         }
 | |
|         return handshake() == 0;
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     int sock{-1};
 | |
|     /**
 | |
|      * RAII wrapper of the address_info
 | |
|      */
 | |
|     struct addr_info {
 | |
|         struct addrinfo *ai {
 | |
|             nullptr
 | |
|         };
 | |
|         ~addr_info()
 | |
|         {
 | |
|             freeaddrinfo(ai);
 | |
|         }
 | |
|         explicit addr_info(const char *host, int family, int type)
 | |
|         {
 | |
|             struct addrinfo hints {};
 | |
|             hints.ai_family = family;
 | |
|             hints.ai_socktype = type;
 | |
|             if (getaddrinfo(host, nullptr, &hints, &ai) < 0) {
 | |
|                 freeaddrinfo(ai);
 | |
|                 ai = nullptr;
 | |
|             }
 | |
|         }
 | |
|         explicit operator bool() const
 | |
|         {
 | |
|             return ai != nullptr;
 | |
|         }
 | |
|         struct sockaddr *get_addr(uint16_t port) const {
 | |
|             auto *p = (struct sockaddr_in *)ai->ai_addr;
 | |
|             p->sin_port = htons(port);
 | |
|             return (struct sockaddr *)p;
 | |
|         }
 | |
|         int get_sock() const
 | |
|         {
 | |
|             return socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 | |
|         }
 | |
|     };
 | |
| };
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| void tls_client()
 | |
| {
 | |
|     const unsigned char message[] = "Hello\n";
 | |
|     unsigned char reply[128];
 | |
|     TlsSocketClient client;
 | |
|     if (!client.connect("tcpbin.com", 4243)) {
 | |
|         ESP_LOGE(TAG, "Failed to connect! %d", errno);
 | |
|         return;
 | |
|     }
 | |
|     if (client.write(message, sizeof(message)) < 0) {
 | |
|         ESP_LOGE(TAG, "Failed to write!");
 | |
|         return;
 | |
|     }
 | |
|     int len = client.read(reply, sizeof(reply));
 | |
|     if (len < 0) {
 | |
|         ESP_LOGE(TAG, "Failed to read!");
 | |
|         return;
 | |
|     }
 | |
|     ESP_LOGI(TAG, "Successfully received: %.*s", len, reply);
 | |
| }
 | |
| 
 | |
| } // namespace
 | |
| 
 | |
| #if CONFIG_IDF_TARGET_LINUX
 | |
| /**
 | |
|  * Linux target: We're already connected, just run the client
 | |
|  */
 | |
| int main()
 | |
| {
 | |
|     tls_client();
 | |
|     return 0;
 | |
| }
 | |
| #else
 | |
| /**
 | |
|  * ESP32 chipsets:  Need to initialize system components
 | |
|  *                  and connect to network
 | |
|  */
 | |
| 
 | |
| #include "nvs_flash.h"
 | |
| #include "esp_event.h"
 | |
| #include "protocol_examples_common.h"
 | |
| #include "esp_netif.h"
 | |
| 
 | |
| extern "C" void app_main()
 | |
| {
 | |
|     ESP_ERROR_CHECK(nvs_flash_init());
 | |
|     ESP_ERROR_CHECK(esp_netif_init());
 | |
|     ESP_ERROR_CHECK(esp_event_loop_create_default());
 | |
|     ESP_ERROR_CHECK(example_connect());
 | |
| 
 | |
|     tls_client();
 | |
| }
 | |
| #endif
 |