Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: Teensy 4.1 ethernet with mongoose network library

  1. #1
    Junior Member
    Join Date
    Jan 2023
    Posts
    8

    Teensy 4.1 ethernet with mongoose network library

    Hi all,
    There is a fairly well-known cross-platform library in the embedded world called "mongoose" : https://mongoose.ws/

    This library is able to:
    • TCP client/server
    • UDP client/server
    • HTTP(S) client/server
    • Websocket(S) client/server
    • MQTT(S) client/server



    It is completely asynchronous and above all, it does not rely on any intermediate network layer (like QNEthernet or Native Ethernet or even LWIP).
    I just realized its port for the Teensy 4.1 and its performance is superior to anything I've tested elsewhere.
    To install it, just copy the two files (.h / .c) from the library into the project folder and include the .h in your project.

    While waiting for my PR to be merged, you can already try it from here : https://github.com/cesanta/mongoose/pull/1954

    And there an sketch exemple that serve an LittleFS "www" directory on HTTP :
    Code:
    #include "driver_teensy41.h"
    #include "mongoose.h"
    
    #include "IPAddress.h"
    
    #include <LittleFS.h>
    #include <MTP_Teensy.h>
    
    struct mg_mgr mgr;  // Mongoose event manager
    struct mip_if mif;  // MIP network interface
    
    LittleFS_Program _fs;
    
    struct Entry {
      const char endsWith[16];
      const char mimeType[32];
    };
    
    // Table of extension->MIME strings stored in PROGMEM, needs to be global due
    // to GCC section typing rules
    const Entry mimeTable[] = {{".html", "text/html"},
                               {".htm", "text/html"},
                               {".css", "text/css"},
                               {".txt", "text/plain"},
                               {".js", "application/javascript"},
                               {".json", "application/json"},
                               {".png", "image/png"},
                               {".gif", "image/gif"},
                               {".jpg", "image/jpeg"},
                               {".ico", "image/x-icon"},
                               {".svg", "image/svg+xml"},
                               {".ttf", "application/x-font-ttf"},
                               {".otf", "application/x-font-opentype"},
                               {".woff", "application/font-woff"},
                               {".woff2", "application/font-woff2"},
                               {".eot", "application/vnd.ms-fontobject"},
                               {".sfnt", "application/font-sfnt"},
                               {".xml", "text/xml"},
                               {".pdf", "application/pdf"},
                               {".zip", "application/zip"},
                               {".gz", "application/x-gzip"},
                               {".appcache", "text/cache-manifest"},
                               {"", "application/octet-stream"}};
    
    const char *mygm_http_get_content_type(const String &f) {
      const char *contentType = NULL;
      int s = (sizeof(mimeTable) / sizeof(mimeTable[0]));
      for (int i = 0; i < s; i++)
        if (f.endsWith(mimeTable[i].endsWith)) contentType = mimeTable[i].mimeType;
    
      if (!contentType) contentType = mimeTable[s - 1].mimeType;
    
      return contentType;
    }
    
    #define CHUNKSIZE 1350
    struct FileContainerStruct {
      File file;
      char *chunkBuffer;
    };
    
    void mymg_http_serve_file_begin(struct mg_connection *c, mg_str *uri) {
      String path = "/www" + String(uri->ptr).substring(0, uri->len);
      if (path.endsWith("/")) path += "index.html";
    
      const char *contentType = mygm_http_get_content_type(path);
    
      FileContainerStruct *pFcs = new FileContainerStruct();
    
      pFcs->chunkBuffer = new char[CHUNKSIZE];
      if (!(pFcs->chunkBuffer)) {
        delete pFcs;
        mg_http_reply(c, 500, "", "Memory allocation error\n");
        return;
      }
    
      pFcs->file = _fs.open(path.c_str(), FILE_READ);
      Serial.printf(" -> %s : %s (%d/%d) : ", path.c_str(), pFcs->file.name(),
                    pFcs->file.size(), pFcs->file.available());
      Serial.printf("%s\n", contentType);
    
      if (!(pFcs->file)) {
        delete pFcs;
        mg_http_reply(c, 404, "", "File Not found\n");
        return;
      }
    
      c->fn_data = pFcs;
      mg_printf(c,
                "HTTP/1.1 200 OK\r\nTransfer-Encoding: "
                "chunked\r\nContent-Type: %s\r\n\r\n",
                contentType);
    }
    
    void mymg_http_serve_file_chunk(struct mg_connection *c) {
      if (!(c->fn_data)) return;
      if (c->send.len != 0) return;
    
      FileContainerStruct *pFcs = (FileContainerStruct *) c->fn_data;
      size_t l = pFcs->file.readBytes(pFcs->chunkBuffer, CHUNKSIZE);
      mg_http_write_chunk(c, pFcs->chunkBuffer, l);
      if (l == 0) mymg_http_server_file_interrupt(c);
    }
    
    void mymg_http_server_file_interrupt(struct mg_connection *c) {
      if (!(c->fn_data)) return;
    
      FileContainerStruct *pFcs = (FileContainerStruct *) c->fn_data;
    
      Serial.printf("Close : %s\n", pFcs->file.name());
      pFcs->file.close();
      delete pFcs->chunkBuffer;
      delete pFcs;
      c->fn_data = NULL;
    }
    
    static void handler(struct mg_connection *c, int ev, void *ev_data,
                        void *fn_data) {
      struct mg_http_message *hm = (struct mg_http_message *) ev_data;
    
      switch (ev) {
        case MG_EV_HTTP_MSG:
          if (mg_http_match_uri(hm, "/api/hello")) {
            mg_http_reply(c, 200, "", "OK : %.*s\n", hm->uri.len, hm->uri.ptr);
            break;
          }
    
          // serve file
          mymg_http_serve_file_begin(c, &(hm->uri));
          break;
    
        case MG_EV_POLL:
          mymg_http_serve_file_chunk(c);
          break;
    
        case MG_EV_CLOSE:
        case MG_EV_ERROR:
          mymg_http_server_file_interrupt(c);
          break;
      }
    }
    
    void setup() {
      Serial.begin(115200);
    
      if (!_fs.begin(1024 * 1024 * 2)) {
        Serial.print("Error starting file system.\n");
        while (1)
          ;  // Error, so don't do anything more - stay stuck here
      }
    
      MTP.addFilesystem(_fs, "LittleFS");
    
      // Set logging function to a serial print
      mg_log_set_fn([](char ch, void *) { Serial.print(ch); }, NULL);
      mg_log_set(MG_LL_INFO);
      mg_mgr_init(&mgr);
    
      MG_INFO(("Starting TCP/IP stack..."));
    
      mif.driver = &mip_driver_teensy41;
    
      IPAddress ip(192, 168, 123, 10);
      IPAddress mask(255, 255, 255, 0);
      mif.enable_dhcp_client = false;
      mif.enable_dhcp_server = false;
    
      mif.ip = ip;
      mif.mask = mask;
    
      mip_init(&mgr, &mif);
    
      // Setup HTTP listener. Respond "ok" on any HTTP request
      mg_http_listen(&mgr, "http://0.0.0.0", handler, NULL);
    }
    
    void loop() {
      mg_mgr_poll(&mgr, 1);
      MTP.loop();
    }
    Thanks to ssilverman and PaulStoffregen for their work.

  2. #2
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    566
    This is an interesting project. I wonder how its built-in IP stack fares from a security standpoint.
    For example:
    https://i.blackhat.com/eu-20/Wednesd...rabilities.pdf
    https://www.helpnetsecurity.com/2021...es-tcp-ip-iot/

  3. #3
    Quote Originally Posted by shawn View Post
    This is an interesting project. I wonder how its built-in IP stack fares from a security standpoint.
    For example:
    https://i.blackhat.com/eu-20/Wednesd...rabilities.pdf
    https://www.helpnetsecurity.com/2021...es-tcp-ip-iot/
    I noticed on the mongoose site that it can be used with lwIP, so it should be usable with QNEthernet instead of the built-in stack?

  4. #4
    Junior Member
    Join Date
    Jan 2023
    Posts
    8
    Quote Originally Posted by joepasquariello View Post
    I noticed on the mongoose site that it can be used with lwIP, so it should be usable with QNEthernet instead of the built-in stack?
    Unfortunately not. See this ticket : https://github.com/cesanta/mongoose/...ent-1373561860

  5. #5
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    566
    Quote Originally Posted by joepasquariello View Post
    I noticed on the mongoose site that it can be used with lwIP, so it should be usable with QNEthernet instead of the built-in stack?
    That’s true, but some work would need to be done to enable the Socket API. QNEthernet disables this and uses the raw API by default. See this comment and its thread: https://github.com/cesanta/mongoose/...ent-1373570774

    Edit: Ninja’d

  6. #6
    Junior Member
    Join Date
    Feb 2022
    Posts
    8
    When I try to use it, it expects a
    Code:
    mongoose_custom.h
    . Can you explain how to set this up correctly?

  7. #7
    Junior Member
    Join Date
    Jan 2023
    Posts
    8
    Yes. Create a "mongoose_custom.h" file with the following :

    Code:
    #pragma once
    
    #if defined(ARDUINO_TEENSY41)
    #include "Arduino.h"
    
    #define MG_ARCH_TEENSY41 42
    #endif
    
    #include <errno.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <time.h>
    
    #define MG_ARCH               MG_ARCH_TEENSY41
    #define MG_ENABLE_SOCKET      0
    #define MG_ENABLE_MIP         1
    #define mkdir(a, b) (-1)

  8. #8
    Junior Member
    Join Date
    Aug 2022
    Posts
    13
    Hi, I used to Test this Library, but was not able to build.

    I use Arduino 1.8.19.

    Where I have to put folder mongoose-master?
    Where I have to put driver_teensy41.h ?

    Thank you.

  9. #9
    Junior Member
    Join Date
    Jan 2023
    Posts
    8
    Ok.. Try this : https://we.tl/t-1bGb5p2P8W

  10. #10
    Junior Member
    Join Date
    Aug 2022
    Posts
    13
    Fine! That works. Small error big effect..

    Thanks for your work and your support.

  11. #11
    Junior Member
    Join Date
    Feb 2022
    Posts
    8
    I just saw that it has GPLv2 license. This makes it unusable for anything else than private projects, as your entire code becomes GPLv2 with all obligations as you compile it. Are there similar projects like this with more free licenses like LGPL or MIT?

  12. #12
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    566
    It looks like they also have commercial licensing available (but you probably found that already):
    https://mongoose.ws/licensing/

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •