Copyright © https://mongoose-os.com

Mongoose OS Forum

frame

Concurrent uploads with SSL

Hello,

we occure an error with concurrent file transfers. Concurrent tranfers are possible if no SSL encryption is enabled, but as soon as we enable encryption only one transfer is handled and the other transfers sending a few bytes and waiting until the first transfer is finished.

Problem is, as long as a file transfer is running no other requests is handled, so it is not even possible to do a get request while the upload is running.

I tested it with the big upload example in which i added OpenSSL encryption, then i run the example and send 3 post requests with 130 MB files to the server but all were handled sequentially.

Is there any way to enable concurrent file transfers while using encryption?

Thanks.

Kind regards,
Marcel Wirtz
MIDAN SOFTWARE GmbH

Comments

  • This sounds weird, shouldn't be like this. Could you show a small test program to reproduce the problem?

  • Sure, as i mentioned i just changed the big upload example to use a SSL certificate. The Uploads itself were made with cURL and ISO images around 130mb.

    // Copyright (c) 2015 Cesanta Software Limited
    // All rights reserved
    //
    // This example demonstrates how to handle very large requests without keeping
    // them in memory.
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "mongoose.h"
    
    static const char *s_http_port = "8080";
    static struct mg_serve_http_opts s_http_server_opts;
    
    static const char *s_ssl_cert = "server.pem";
    static const char *s_ssl_key = "server.key";
    
    struct file_writer_data {
      FILE *fp;
      size_t bytes_written;
    };
    
    static void handle_upload(struct mg_connection *nc, int ev, void *p) {
      struct file_writer_data *data = (struct file_writer_data *) nc->user_data;
      struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *) p;
    
      switch (ev) {
        case MG_EV_HTTP_PART_BEGIN: {
          if (data == NULL) {
            data = calloc(1, sizeof(struct file_writer_data));
            data->fp = tmpfile();
            data->bytes_written = 0;
    
            if (data->fp == NULL) {
              mg_printf(nc, "%s",
                        "HTTP/1.1 500 Failed to open a file\r\n"
                        "Content-Length: 0\r\n\r\n");
              nc->flags |= MG_F_SEND_AND_CLOSE;
              return;
            }
            nc->user_data = (void *) data;
          }
          break;
        }
        case MG_EV_HTTP_PART_DATA: {
          if (fwrite(mp->data.p, 1, mp->data.len, data->fp) != mp->data.len) {
            mg_printf(nc, "%s",
                      "HTTP/1.1 500 Failed to write to a file\r\n"
                      "Content-Length: 0\r\n\r\n");
            nc->flags |= MG_F_SEND_AND_CLOSE;
            return;
          }
          data->bytes_written += mp->data.len;
          break;
        }
        case MG_EV_HTTP_PART_END: {
          mg_printf(nc,
                    "HTTP/1.1 200 OK\r\n"
                    "Content-Type: text/plain\r\n"
                    "Connection: close\r\n\r\n"
                    "Written %ld of POST data to a temp file\n\n",
                    (long) ftell(data->fp));
          nc->flags |= MG_F_SEND_AND_CLOSE;
          fclose(data->fp);
          free(data);
          nc->user_data = NULL;
          break;
        }
      }
    }
    
    static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
      if (ev == MG_EV_HTTP_REQUEST) {
        mg_serve_http(nc, ev_data, s_http_server_opts);
      }
    }
    
    int main(void) {
      struct mg_mgr mgr;
      struct mg_connection *c;
      struct mg_bind_opts bind_opts;
      const char *err;
    
      memset(&bind_opts, 0, sizeof(bind_opts));
      bind_opts.ssl_cert = s_ssl_cert;
      bind_opts.ssl_key = s_ssl_key;
      bind_opts.error_string = &err;
    
      mg_mgr_init(&mgr, NULL);
      c = mg_bind_opt(&mgr, s_http_port, ev_handler, bind_opts);
      if (c == NULL) {
        fprintf(stderr, "Cannot start server on port %s\n", s_http_port);
        exit(EXIT_FAILURE);
      }
    
      s_http_server_opts.document_root = ".";  // Serve current directory
    
      mg_register_http_endpoint(c, "/upload", handle_upload MG_UD_ARG(NULL));
    
      // Set up HTTP server parameters
      mg_set_protocol_http_websocket(c);
    
      printf("Starting web server on port %s\n", s_http_port);
      for (;;) {
        mg_mgr_poll(&mgr, 1000);
      }
      mg_mgr_free(&mgr);
    
      return 0;
    }
    
  • SergeySergey Dublin, Ireland

    Thanks Marcel. Does it behave like this with latest mongoose server code?

  • marcelwirtzmarcelwirtz Germany
    edited November 22

    We first noticed it with Mongoose version 6.6 and it did not change after the update to 6.10 and we did not test this with the versions between 6.6 and 6.10.

  • SergeySergey Dublin, Ireland

    Please test with the latest mongoose.

  • Hey,
    i tested it this morning again, but it did not work with the 6.10 release and did not work if i clone the actual master.

    Here a gif where you can see how it looks like. The files are uploaded sequentially and then fnished at once. If i run this on an Apache Webserver with SSL all 3 files get uploaded at the same time, if i use the example code above they are uploaded sequentially.

  • Any updates on this?

    Kind regards,
    Marcel

Sign In or Register to comment.