Commit f2359e48 authored by Yann Garcia's avatar Yann Garcia
Browse files

Bug fixed in http_layr/tcp_layer, honoring HTTP header connection close

parent 7db586d8
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -119,11 +119,9 @@ public: //! \publicsection
   *        The next send_data() on the transport layer re-establishes it.
   */
  virtual void close_connection() {
    printf(">>> close_connection: lowerLayers size=%d\n", (int)lowerLayers.size());
    for (std::vector<layer *>::const_iterator it = lowerLayers.cbegin(); it != lowerLayers.cend(); ++it) {
      (*it)->close_connection();
    }
    printf("<<< close_connection\n");
  };

  /*!
+10 −1
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ void http_layer::send_data(OCTETSTRING &p_data, params &params) {
  loggers::get_instance().log("http_layer::send_data: params: ");
  params.log();

  bool connection_close = false;
  if (_device_mode) { // Need to build an HTTP packet
    loggers::get_instance().log("http_layer::send_data: Build http layer");
    TTCN_Buffer buffer;
@@ -162,6 +163,7 @@ void http_layer::send_data(OCTETSTRING &p_data, params &params) {
    }
    if (it_type->second.compare("response") == 0) {
      buffer.put_cs("Connection: close");
      connection_close = true;
    } else {
      buffer.put_cs("Accept: ");
      if ((it = params.find(params::accept)) != params.cend()) {
@@ -191,7 +193,9 @@ void http_layer::send_data(OCTETSTRING &p_data, params &params) {
      buffer.put_cs("\r\n\r\n");
      buffer.put_os(p_data);
    } else {
      // Omit Content-length header for empty body
      if (it_type->second.compare("response") == 0) {
        buffer.put_cs("Content-length: 0\r\n");
      } // else, omit Content-length header for empty body
      buffer.put_cs("\r\n");
    }
    //buffer.put_cs("\r\n"); // FSCOM Remove the last CRLF to avoid adding 2 bytes to the Content-length header
@@ -200,6 +204,11 @@ void http_layer::send_data(OCTETSTRING &p_data, params &params) {

  loggers::get_instance().log_msg("http_layer::send_data: ", p_data);
  send_to_all_layers(p_data, params);

  if (connection_close) {
    loggers::get_instance().log("http_layer::send_data: 'Connection: close' sent, closing transport connection");
    close_connection(); // Propagates down to tcp_layer
  }
}

void http_layer::receive_data(OCTETSTRING &p_data, params &params) {
+18 −3
Original line number Diff line number Diff line
@@ -297,14 +297,29 @@ void tcp_layer::peer_half_closed(int p_client_id)
  peer_disconnected(p_client_id);
}

void tcp_layer::close_connection()
{
void tcp_layer::close_connection() {
  loggers::get_instance().log(">>> tcp_layer::close_connection: _client_id: %d", _client_id);

  if ((_params[params::server_mode].compare("0") == 0) && (_client_id != -1)) {
  if (_client_id != -1) {
    // Works in both modes:
    // - Client mode: closes the outgoing connection; the reconnect logic in
    //   send_data() (peer_list_get_nr_of_peers() == 0) re-establishes it on
    //   the next request.
    // - Server mode: _client_id is the accepted peer (set by add_user_data()
    //   on accept); remove_client() closes only that peer's fd — listen_fd is
    //   untouched, so the next incoming connection is accepted normally.
    // close(fd) inside remove_client() lets the kernel flush any buffered
    // outgoing bytes first, then emits the FIN — the sockets are blocking
    // (use_non_blocking_socket is not enabled in init()), so the HTTP
    // response handed over by send_message_on_fd() is already in the kernel
    // buffer at this point and cannot be truncated.
    remove_client(_client_id);
    _client_id = -1;
  } else {
    loggers::get_instance().log("tcp_layer::close_connection: No active connection, nothing to do");
  }

  loggers::get_instance().log("<<< tcp_layer::close_connection");
}

tcp_layer_factory tcp_layer_factory::_f;
+3 −2
Original line number Diff line number Diff line
@@ -67,8 +67,9 @@ public: //! \publicsection
   */
  virtual void receive_data(OCTETSTRING &p_data, params &info);

  /*! 
   * \brief Close the active client connection so the next send_data() reconnects. 
  /*! \brief Close the active (client or accepted) connection.
   *         Client mode: next send_data() reconnects.
   *         Server mode: the listen socket stays open, next peer is accepted normally.
   */
  virtual void close_connection();