HTTPmsg_PT.cc 47.4 KB
Newer Older
                        if(get_line(buffer, line, false) == BUFFER_CRLF)
                            HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "Trailing \\r\\n ok!");
                        else
                            TTCN_Logger::log(TTCN_WARNING,"Trailing \\r\\n after the closing chunk is not present, instead it is <%s>!", (const char*)line);
                    }
/*                    else if(chunk_size < 0) // the chunk_size is unsigned, never true
                    {
                        HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "chunk_size less than 0");
                        decoding_params.error = TRUE;
                        chunk_size = 0;
                    }*/
                    else // chunk_size > 0
                    {
                        HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "processing next chunk, size: %d", chunk_size);
                        if(buffer->get_read_len() < chunk_size)
                        {
                            HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "chunk size is greater than the buffer length, more data is needed");
                            decoding_params.isMessage = FALSE;
                            chunk_size = 0;
                        }
                    }
                }
                break;
            case FALSE:
                HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "buffer does not contain a whole line, more data is needed");
                decoding_params.isMessage = FALSE;
                chunk_size = 0;
                break;
            case BUFFER_CRLF:
                HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "beginning CRLF removed");
                continue;
            case BUFFER_FAIL:
                HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "BUFFER_FAIL");
                decoding_params.error = FALSE;
                chunk_size = 0;
                break;
            default:
                decoding_params.isMessage = FALSE;
                chunk_size = 0;
                HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "more data is needed");
        }

        body = body + OCTETSTRING(chunk_size, buffer->get_read_data());
        HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "pull %d bytes from %d", chunk_size, buffer->get_read_len());
        buffer->set_pos(buffer->get_pos() + chunk_size);
        // hack
        if(buffer->get_read_len() && buffer->get_read_data()[0] == '\n')  // don't read from the buffer if there is nothing in it.
        {
            HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,"hack: adjusted buffer position after the '\\n'");
            buffer->set_pos(buffer->get_pos() + 1);
        }
        HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name,  "remaining data: <%s>, len: %d", (const char *)CHARSTRING(buffer->get_read_len(), (const char*)buffer->get_read_data()), buffer->get_read_len());
    }
}

int get_line(TTCN_Buffer* buffer, CHARSTRING& to, const bool concatenate_header_lines)
{
    unsigned int i = 0;
    const unsigned char *cc_to = buffer->get_read_data();

    if(!buffer->get_read_len())
        return FALSE;

    while(1)
    {
        for( ; i < buffer->get_read_len() && cc_to[i] != '\0' && cc_to[i] != '\r' && cc_to[i] != '\n'; i++);

        if(i >= buffer->get_read_len())
        {
            to = CHARSTRING("");
            return FALSE;
        }
        else
        {
            if(cc_to[i] == '\n') {//
              if(report_lf){
                switch(HTTPmsg__Types::crlf__mode){
                  case HTTPmsg__Types::strict__crlf__mode::ERROR_:
                    return BUFFER_FAIL;
                    break;
                  case HTTPmsg__Types::strict__crlf__mode::WARNING__ONCE:
                    report_lf=false;
                    // no break
                  case HTTPmsg__Types::strict__crlf__mode::WARNING:
                    TTCN_warning("Missing '\\r'.");
                    break;
                  default:
                    break;
                }
              }
              if(i > 0 && (i + 1) < buffer->get_read_len() && concatenate_header_lines && (cc_to[i+1] == ' ' || cc_to[i+1] == '\t'))
                    i += 1;
                  else
                  {
                      to = CHARSTRING(i, (const char*)cc_to);
                      buffer->set_pos(buffer->get_pos() + i + 1);
                      return i == 0 ? BUFFER_CRLF : TRUE;
                  }

            } else
            {
                if((i + 1) < buffer->get_read_len() && cc_to[i + 1] != '\n')
                  return BUFFER_FAIL;
                else if(i > 0 && (i + 2) < buffer->get_read_len() && concatenate_header_lines && (cc_to[i+2] == ' ' || cc_to[i+2] == '\t'))
                  i += 2;
                else
                {
                    to = CHARSTRING(i, (const char*)cc_to);
                    buffer->set_pos(buffer->get_pos() + i + 2);
                    return i == 0 ? BUFFER_CRLF : TRUE;
                }
            }
        }
    }
}

void log_to_hexa(TTCN_Buffer* buffer)
{
    int len = buffer->get_read_len();
    const unsigned char* ptr = buffer->get_read_data();
    for(int i = buffer->get_pos(); i < len; i++)
    {
        TTCN_Logger::log_event(" %02X", ptr[i]);
    }
}


const char* HTTPmsg__PT::local_port_name()              { return "";}
const char* HTTPmsg__PT::remote_address_name()          { return "";}
const char* HTTPmsg__PT::local_address_name()           { return "";}
const char* HTTPmsg__PT::remote_port_name()             { return "";}
const char* HTTPmsg__PT::use_notification_ASPs_name()   { return "use_notification_ASPs";}
const char* HTTPmsg__PT::halt_on_connection_reset_name(){ return "";}
const char* HTTPmsg__PT::server_mode_name()             { return "";}
const char* HTTPmsg__PT::socket_debugging_name()        { return "http_debugging";}
const char* HTTPmsg__PT::nagling_name()                 { return "";}
const char* HTTPmsg__PT::server_backlog_name()          { return "server_backlog";}
const char* HTTPmsg__PT::ssl_use_ssl_name()                { return "";}
const char* HTTPmsg__PT::ssl_use_session_resumption_name() { return "";}
const char* HTTPmsg__PT::ssl_private_key_file_name()       { return "KEYFILE";}
const char* HTTPmsg__PT::ssl_trustedCAlist_file_name()     { return "TRUSTEDCALIST_FILE";}
const char* HTTPmsg__PT::ssl_certificate_file_name()       { return "CERTIFICATEFILE";}
const char* HTTPmsg__PT::ssl_password_name()               { return "PASSWORD";}
const char* HTTPmsg__PT::ssl_verifycertificate_name()      { return "VERIFYCERTIFICATE";}


} //eof namespace "HTTPmsg__PortType"

namespace HTTPmsg__Types {

using namespace HTTPmsg__PortType;

//=========================================================================
//==== Working Functions independent from sending and receiving:===
//=========================================================================

//from AbstractSocket
void log_debug(const bool socket_debugging, const char *test_port_type, const char *test_port_name, const char *fmt, ...)
{
  if (socket_debugging) {
    TTCN_Logger::begin_event(TTCN_DEBUG);
    if ((test_port_type!=NULL && test_port_name!=NULL)&&(strlen(test_port_type)!=0 && strlen(test_port_name)!=0))
       TTCN_Logger::log_event("%s test port (%s): ", test_port_type, test_port_name);
    va_list args;
    va_start(args, fmt);
    TTCN_Logger::log_event_va_list(fmt, args);
    va_end(args);
    TTCN_Logger::end_event();
  }
}

void log_warning(const char *test_port_type, const char *test_port_name, const char *fmt, ...)
{
  TTCN_Logger::begin_event(TTCN_WARNING);
  if (test_port_type!=NULL && test_port_name!=NULL)
       TTCN_Logger::log_event("%s test port (%s): ", test_port_type, test_port_name);
  va_list args;
  va_start(args, fmt);
  TTCN_Logger::log_event_va_list(fmt, args);
  va_end(args);
  TTCN_Logger::end_event();
}

//=========================================================================
//==== Encoder-decoder Functions independent from sending and receiving:===
//=========================================================================

/*********************************************************
* Function: enc__HTTPMessage
*
* Purpose:
*    To encode msg type of HTTPMessage into OCTETSTRING separated from sending functionality
*    It is for users using this test port as a protocol module
*
* References:
*   RFC2616
*
* Precondition:
*  msg is filled in properly
* Postcondition:
*
*
* Parameters:
*  msg - the HTTP Message to be encoded
*
* Return Value:
*   OCTETSTRING - the encoded message
* Detailed Comments:
*   -
*
*********************************************************/
OCTETSTRING enc__HTTPMessage( const HTTPmsg__Types::HTTPMessage& msg ) {
  TTCN_Buffer buf;
  buf.clear();
  HTTPmsg__PortType::f_HTTP_encodeCommon( msg, buf);
  return OCTETSTRING(buf.get_len(), buf.get_data());
}
/*********************************************************
* Function: dec__HTTPMessage
*
* Purpose:
*    To decode msg type of OCTETSTRING into HTTPMessage separated from receiving functionality
*    It is for users using this test port as a protocol module
*
* References:
*   RFC2616
*
* Precondition:
*  stream is filled in properly
* Postcondition:
*  -
*
* Parameters:
*  stream - the message to be decoded
*  msg    - reference to the record type of HTTPMessage which will contain the decoded value if the return value less than the length of the original stream
* Return Value:
*   integer - the length of the remaining data which is not decoded yet.
* Detailed Comments:
*   If the full stream is decoded, the return value is zero
*   If nothing is decoded (decoding failed) the return value equals to the original length of the stream
*
*********************************************************/

INTEGER dec__HTTPMessage(OCTETSTRING const& stream, HTTPMessage& msg, const BOOLEAN& socket_debugging =  dec__HTTPMessage_socket__debugging_defval )
{
  TTCN_Logger::log(TTCN_DEBUG, "starting HTTPmsg__Types::dec__HTTPMessage");
  TTCN_Buffer *buf_p = new TTCN_Buffer() ;
  buf_p->put_os(stream);

  int buf_len = buf_p->get_read_len();
  if( buf_len > 0)
  {
      if(f_HTTP_decodeCommon(buf_p, msg, true, socket_debugging, NULL, NULL))
      {
        log_debug(socket_debugging,"","","dec__HTTPMessage, after decoding:\nbuf_len: %d\nget_len: %d\nget_read_len:%d",
            buf_len,
            buf_p->get_len(),
            buf_p->get_read_len());
        buf_len = buf_p->get_read_len(); //remaining data length
      }
      else
        buf_len = -1;


  } else buf_len = -1;
  delete buf_p;
  return buf_len;
}

}//namespace