]> granicus.if.org Git - esp-idf/commitdiff
Use esp-tls in the http2 example
authorKedar Sovani <kedars@gmail.com>
Sun, 4 Feb 2018 04:32:31 +0000 (10:02 +0530)
committerJitin George <jitin@espressif.com>
Fri, 6 Apr 2018 11:46:27 +0000 (17:16 +0530)
components/esp-tls/esp-tls.c
components/esp-tls/esp-tls.h
examples/protocols/http2_request/components/sh2lib/connectlib.c [deleted file]
examples/protocols/http2_request/components/sh2lib/connectlib.h [deleted file]
examples/protocols/http2_request/components/sh2lib/sh2lib.c
examples/protocols/http2_request/components/sh2lib/sh2lib.h

index 3ed8939c0722670823392c85a60870aa770cf4d9..d7599ed53b3dedd7584110c56fa284bb84f070f7 100644 (file)
@@ -7,6 +7,7 @@
 #include <sys/socket.h>
 #include <netdb.h>
 
+#include <http_parser.h>
 #include "esp-tls.h"
 
 
@@ -209,3 +210,28 @@ struct esp_tls *esp_tls_conn_new(const char *hostname, int hostlen, int port, st
     return tls;
 }
 
+static int get_port(const char *url, struct http_parser_url *u)
+{
+    if (u->field_data[UF_PORT].len) {
+        return strtol(&url[u->field_data[UF_PORT].off], NULL, 10);
+    } else {
+        if (strncmp(&url[u->field_data[UF_SCHEMA].off], "http", u->field_data[UF_SCHEMA].len) == 0) {
+            return 80;
+        } else if (strncmp(&url[u->field_data[UF_SCHEMA].off], "https", u->field_data[UF_SCHEMA].len) == 0) {
+            return 443;
+        }
+    }
+    return 0;
+}
+
+struct esp_tls *esp_tls_conn_http_new(const char *url, struct esp_tls_cfg *cfg)
+{
+    /* Parse URI */
+    struct http_parser_url u;
+    http_parser_url_init(&u);
+    http_parser_parse_url(url, strlen(url), 0, &u);
+
+    /* Connect to host */
+    return esp_tls_conn_new(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len,
+                           get_port(url, &u), cfg);
+}
index 08cc63cf21030a69492fb95fd858aa93e4c882f6..f921a5e6f69a13eddf922de93ae2ffac8323698b 100644 (file)
@@ -37,6 +37,9 @@ struct esp_tls {
  */
 struct esp_tls *esp_tls_conn_new(const char *hostname, int hostlen, int port, struct esp_tls_cfg *cfg);
 
+/* Convenience API for HTTP URIs */
+struct esp_tls *esp_tls_conn_http_new(const char *url, struct esp_tls_cfg *cfg);
+    
 static inline ssize_t esp_tls_conn_write(struct esp_tls *tls, const char *data, size_t datalen)
 {
     return tls->write(tls, data, datalen);
diff --git a/examples/protocols/http2_request/components/sh2lib/connectlib.c b/examples/protocols/http2_request/components/sh2lib/connectlib.c
deleted file mode 100644 (file)
index 2fe42cb..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/* With adaptations by Espressif Systems
- *
- * Copyright (c) 2013 Tatsuhiro Tsujikawa
- *
- * 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 <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <netdb.h>
-
-#include "connectlib.h"
-
-/* Basic parser from nghttp2/examples/client.c */
-int parse_uri(struct uri *res, const char *uri)
-{
-    /* We only interested in https */
-    size_t len, i, offset;
-    int ipv6addr = 0;
-    memset(res, 0, sizeof(struct uri));
-    len = strlen(uri);
-    if (len < 9 || memcmp("https://", uri, 8) != 0) {
-        return -1;
-    }
-    offset = 8;
-    res->host = res->hostport = &uri[offset];
-    res->hostlen = 0;
-    if (uri[offset] == '[') {
-        /* IPv6 literal address */
-        ++offset;
-        ++res->host;
-        ipv6addr = 1;
-        for (i = offset; i < len; ++i) {
-            if (uri[i] == ']') {
-                res->hostlen = i - offset;
-                offset = i + 1;
-                break;
-            }
-        }
-    } else {
-        const char delims[] = ":/?#";
-        for (i = offset; i < len; ++i) {
-            if (strchr(delims, uri[i]) != NULL) {
-                break;
-            }
-        }
-        res->hostlen = i - offset;
-        offset = i;
-    }
-    if (res->hostlen == 0) {
-        return -1;
-    }
-    /* Assuming https */
-    res->port = 443;
-    if (offset < len) {
-        if (uri[offset] == ':') {
-            /* port */
-            const char delims[] = "/?#";
-            int port = 0;
-            ++offset;
-            for (i = offset; i < len; ++i) {
-                if (strchr(delims, uri[i]) != NULL) {
-                    break;
-                }
-                if ('0' <= uri[i] && uri[i] <= '9') {
-                    port *= 10;
-                    port += uri[i] - '0';
-                    if (port > 65535) {
-                        return -1;
-                    }
-                } else {
-                    return -1;
-                }
-            }
-            if (port == 0) {
-                return -1;
-            }
-            offset = i;
-            res->port = (uint16_t)port;
-        }
-    }
-    res->hostportlen = (size_t)(uri + offset + ipv6addr - res->host);
-    for (i = offset; i < len; ++i) {
-        if (uri[i] == '#') {
-            break;
-        }
-    }
-    if (i - offset == 0) {
-        res->path = "/";
-        res->pathlen = 1;
-    } else {
-        res->path = &uri[offset];
-        res->pathlen = i - offset;
-    }
-    return 0;
-}
-
-int connect_to_host(const char *host, size_t hostlen, uint16_t port)
-{
-    int ret;
-    struct addrinfo hints = {
-        .ai_family = AF_UNSPEC,
-        .ai_socktype = SOCK_STREAM,
-    };
-
-    char service[6];
-    snprintf(service, sizeof(service), "%u", port);
-
-    char *use_host = calloc(1, hostlen + 1);
-    if (!use_host) {
-         return -1;
-    }
-    strncpy(use_host, host, hostlen);
-
-    struct addrinfo *res;
-    ret = getaddrinfo(use_host, service, &hints, &res);
-    if (ret) {
-        free(use_host);
-        return -1;
-    }
-    free(use_host);
-
-    ret = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-    if (ret < 0) {
-        goto err_freeaddr;
-    }
-
-    int fd = ret;
-    ret = connect(fd, res->ai_addr, res->ai_addrlen);
-    if (ret < 0) {
-        goto err_freesocket;
-    }
-
-    return fd;
-
-err_freesocket:
-    close(fd);
-err_freeaddr:
-    freeaddrinfo(res);
-    return -1;
-}
-
diff --git a/examples/protocols/http2_request/components/sh2lib/connectlib.h b/examples/protocols/http2_request/components/sh2lib/connectlib.h
deleted file mode 100644 (file)
index 86677fd..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#ifndef __ESP_EXAMPLE_CONNECT_LIB_H_
-#define __ESP_EXAMPLE_CONNECT_LIB_H_
-
-struct uri {
-    const char *host;
-    /* In this program, path contains query component as well. */
-    const char *path;
-    size_t pathlen;
-    const char *hostport;
-    size_t hostlen;
-    size_t hostportlen;
-    uint16_t port;
-};
-
-/* connect() to a TCP host, return socket descriptor */
-int connect_to_host(const char *host, size_t hostlen, uint16_t port);
-
-/* Parse a URI into its components */
-int parse_uri(struct uri *res, const char *uri);
-
-#endif /* ! __ESP_EXAMPLE_CONNECT_LIB_H_ */
index ba46593f62c62666fc25d232755d45e327fe9750..04817e16fb3cf59527810dd9bf08b27693bc707a 100644 (file)
@@ -21,8 +21,8 @@
 #include <ctype.h>
 #include <netdb.h>
 #include <esp_log.h>
+#include <esp-tls.h>
 
-#include "connectlib.h"
 #include "sh2lib.h"
 
 static const char *TAG = "sh2lib";
@@ -75,10 +75,9 @@ static int do_ssl_connect(struct sh2lib_handle *hd, int sockfd, const char *host
 static ssize_t callback_send_inner(struct sh2lib_handle *hd, const uint8_t *data,
                                    size_t length)
 {
-    int rv = SSL_write(hd->ssl, data, (int)length);
+    int rv = esp_tls_conn_write(hd->http2_tls, (const char *)data, (int)length);
     if (rv <= 0) {
-        int err = SSL_get_error(hd->ssl, rv);
-        if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
+        if (rv == -SSL_ERROR_WANT_WRITE || rv == -SSL_ERROR_WANT_READ) {
             rv = NGHTTP2_ERR_WOULDBLOCK;
         } else {
             rv = NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -128,10 +127,9 @@ static ssize_t callback_recv(nghttp2_session *session, uint8_t *buf,
 {
     struct sh2lib_handle *hd = user_data;
     int rv;
-    rv = SSL_read(hd->ssl, buf, (int)length);
+    rv = esp_tls_conn_read(hd->http2_tls, (char *)buf, (int)length);
     if (rv < 0) {
-        int err = SSL_get_error(hd->ssl, rv);
-        if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
+        if (rv == -SSL_ERROR_WANT_WRITE || rv == -SSL_ERROR_WANT_READ) {
             rv = NGHTTP2_ERR_WOULDBLOCK;
         } else {
             rv = NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -281,24 +279,10 @@ static int do_http2_connect(struct sh2lib_handle *hd)
 int sh2lib_connect(struct sh2lib_handle *hd, const char *uri)
 {
     memset(hd, 0, sizeof(*hd));
-
-    struct uri res;
-    /* Parse the URI */
-    if (parse_uri(&res, uri) != 0) {
-        ESP_LOGE(TAG, "[sh2-connect] Failed to parse URI");
-        return -1;
-    }
-
-    /* TCP connection with the server */
-    int sockfd = connect_to_host(res.host, res.hostlen, res.port);
-    if (sockfd < 0) {
-        ESP_LOGE(TAG, "[sh2-connect] Failed to connect to %s", uri);
-        return -1;
-    }
-
-    /* SSL Connection on the socket */
-    if (do_ssl_connect(hd, sockfd, res.host) != 0) {
-        ESP_LOGE(TAG, "[sh2-connect] SSL Handshake failed with %s", uri);
+    struct esp_tls_cfg tls_cfg;
+    tls_cfg.alpn_protos = (unsigned char *) "\x02h2";
+    if ((hd->http2_tls = esp_tls_conn_http_new(uri, &tls_cfg)) == NULL) {
+        ESP_LOGE(TAG, "[sh2-connect] esp-tls connection failed");
         goto error;
     }
 
@@ -308,6 +292,9 @@ int sh2lib_connect(struct sh2lib_handle *hd, const char *uri)
         goto error;
     }
 
+    int flags = fcntl(hd->http2_tls->sockfd, F_GETFL, 0);
+    fcntl(hd->http2_tls->sockfd, F_SETFL, flags | O_NONBLOCK);
+
     return 0;
 error:
     sh2lib_free(hd);
@@ -320,17 +307,9 @@ void sh2lib_free(struct sh2lib_handle *hd)
         nghttp2_session_del(hd->http2_sess);
         hd->http2_sess = NULL;
     }
-    if (hd->ssl) {
-        SSL_free(hd->ssl);
-        hd->ssl = NULL;
-    }
-    if (hd->ssl_ctx) {
-        SSL_CTX_free(hd->ssl_ctx);
-        hd->ssl_ctx = NULL;
-    }
-    if (hd->sockfd) {
-        close(hd->sockfd);
-        hd->ssl_ctx = 0;
+    if (hd->http2_tls) {
+       esp_tls_conn_delete(hd->http2_tls);
+        hd->http2_tls = NULL;
     }
     if (hd->hostname) {
         free(hd->hostname);
@@ -346,11 +325,13 @@ int sh2lib_execute(struct sh2lib_handle *hd)
         ESP_LOGE(TAG, "[sh2-execute] HTTP2 session send failed %d", ret);
         return -1;
     }
+
     ret = nghttp2_session_recv(hd->http2_sess);
     if (ret != 0) {
         ESP_LOGE(TAG, "[sh2-execute] HTTP2 session recv failed %d", ret);
         return -1;
     }
+
     return 0;
 }
 
index 97095eb5af18b977c7300d86309d983e7fb162df..0112768bbbbb5c5e56522584450c9419464cf527 100644 (file)
  * @brief Handle for working with sh2lib APIs
  */
 struct sh2lib_handle {
-    /* Ideally, CTX is per-program, so we could potentially take it out of this
-     * per-connection structure
-     */
-    SSL_CTX         *ssl_ctx;      /*!< Pointer to the SSL context */
-    SSL             *ssl;          /*!< Pointer to the SSL handle */
     nghttp2_session *http2_sess;   /*!< Pointer to the HTTP2 session handle */
     int              sockfd;       /*!< Socket file descriptor */
     char            *hostname;     /*!< The hostname we are connected to */
+    struct esp_tls  *http2_tls;    /*!< Pointer to the TLS session handle */
 };
 
 /** Flag indicating receive stream is reset */