Uploaded image for project: 'Traffic Server'
  1. Traffic Server
  2. TS-4322

ProfileSM Proposal

    XMLWordPrintableJSON

    Details

    • Type: Improvement
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: sometime
    • Component/s: Core, Network
    • Labels:
      None

      Description

      Preface
      =======

      NetVConnection is a base class for all NetIO derived classes:

      • NetVConnection
      • UnixNetVConnection for TCP NetIO
      • SSLNetVConnection for SSL NetIO

      with the below codes to test a NetVC whether is a SSLNetVC :

        sslvc = dynamic_cast<SSLNetVConnection *>netvc;
        if (sslvc != NULL)
        {
           // netvc is a SSLNetVConnection
        } else {
           // netvc is a UnixNetVConnection
        }
      

      ATS support HTTP, SPDY and H2 protocol, and also support them with SSL/TLS.

      Sometimes we want to talk in HTTP/TCP first, and then talk in HTTP/SSL,

      Example : HTTPS over HTTP CONNECT method

      Client send a CONNECT method request
          C->P: CONNECT www.example.com:443 HTTP/1.1
          C->P: Host: www.example.com:443
          C->P:
      ATS reply a HTTP 200/OK, then build a TCP tunnel to www.example.com:443
          P->C: 200 OK
          P->C: 
      Client send a SSL Handshake Client Hello message
          C->P: <Client Hello>
      ATS tunnel the message
          P->S: <Client Hello>
      Server response a SSL Handshake Server Hello message
          P<-S: <Server Hello>
      ATS tunnel the message
          C<-P: <Server Hello>
      Server send a Certificate to ATS
          P<-S: <Certificate>
      ATS tunnel the message
          C<-P: <Certificate>
      etc . . .
      

      currently, It isn't a easy way upgrading to SSLNetVConnection from UnixNetVConnection.

      the ProfileSM is designed to setup a plugable mechanism for UnixNetVConnection to handle(abstract) different type of I/O operation.

      so we will have TcpProfileSM and UdpProfileSM as low level ProfileSM and SslProfileSM as high level ProfileSM.

      How to implement
      ================

      Introduce a new class ProfileSM & TcpProfileSM & SslProfileSM :

      It is a derived class from Continuation

      • Has handleEvent() function
      • Has mutex member

      TcpProfileSM is a derived class from ProfileSM

      SslProfileSM is a derived class from ProfileSM

      handshakeEvent(int event, void *data) function

      • only defined in SslProfileSM
      • the SSL handshake handle function
      • `event' can be IOCORE_EVENTS_READ or IOCORE_EVENTS_WRITE
      • it is callback from NetHandler::mainNetEvent()
      • `data' is a pointer to Nethandler type
      • it is implement NPN/ALPN support and replace SSLNextProtocolAccept & SSLNextProtocolTrampoline, pick some codes from sslvc->net_read_io(), write_to_net_io()
      • set Continuation->handler to mainEvent() when HandShake done.

      mainEvent(int event, void *data) function

      • the first entrance
      • `event' can be IOCORE_EVENTS_READ or IOCORE_EVENTS_WRITE
      • it is callback from NetHandler::mainNetEvent()
      • `data' is a pointer to Nethandler type

      handle_read(NetHandler *nh, EThread *lthread)

      • it is called by mainEvent() if event is IOCORE_EVENTS_READ
      • for TcpProfileSM, it call vc->net_read_io(nh, lthread)
      • for SslProfileSM, it call sslvc->net_read_io(nh, lthread)

      handle_write(NetHandler *nh, EThread *lthread)

      • it is called by mainEvent() if event is IOCORE_EVENTS_WRITE
      • for TcpProfileSM, it call write_to_net(nh, lthread)
      • for SslProfileSM, it call write_to_net(nh, lthread)

      raw_read() and raw_readv()

      • for TcpProfileSM, it is wrap for syscall read() & readv()
      • for SslProfileSM, it is wrap for SSL_read()

      raw_write() and raw_writev()

      • for TcpProfileSM, it is wrap for syscall write() & writev()
      • for SslProfileSM, it is wrap for SSL_write()

      ProfileSM *low_profilesm;

      • for TcpProfileSM, it set to NULL
      • for SslProfileSM, it set to TcpProfileSM

      minor change in functions

      • vc->net_read_io()
      • sslvc->net_read_io()
      • read_from_net()
      • ssl_read_from_net()
      • write_to_net(), write_to_net_io()
      • vc->load_buffer_and_write()
      • sslvc->load_buffer_and_write()

      add misc for SslProfileSM (reference SSLUnixNetVConnection)

      • SSL *ssl;
      • MIOBuffer *handshakebuffer

      At last,

      add ProfileSM *profile_sm to UnixNetVConnection as a member

      modify NetHandler::mainNetEvent()

      • vc->net_read_io(this, trigger_event->ethread);
      • change to
      • vc->profile_sm->handleEvent(IOCORE_EVENTS_READ, this);
      • write_to_net(this, vc, trigger_event->ethread);
      • change to
      • vc->profile_sm->handleEvent(IOCORE_EVENTS_WRITE, this);

      New World
      =========

      the UnixNetVConnection with new TcpProfileSM and HttpSM process:

      NetAccept

      • new UnixNetVC
      • new TcpProfileSM
      • attach TcpProfileSM to UnixNetVC
      • callback NET_EVENT_ACCEPT to ProtocolProbeAccept::mainEvent()

      ProtocolProbeAccept::mainEvent()

      • probe = new ProtocolProbeTrampoline(this, netvc->mutex, buf, reader);
      • vio = netvc->do_io_read(probe, buffer_size, probe->iobuf);
      • vio->reenable();

      NetHandler::mainNetEvent()

      • callback IOCORE_EVENTS_READ to TcpProfileSM

      TcpProfileSM::mainEvent()

      • call handle_read()
      • raw_read()
      • callback ProtocolProbeTrampoline::ioCompletionEvent(VC_EVENT_READ_COMPLETE, vio)
      • ProtocolProbe and create HttpSessionAccept()

      the UnixNetVConnection with new TcpProfileSM, SslProfileSM and HttpSM process:

      NetAccept

      • new UnixNetVC
      • new TcpProfileSM
      • attach TcpProfileSM to UnixNetVC
      • new SslProfileSM
      • attach TcpProfileSM to UnixNetVC
      • callback NET_EVENT_ACCEPT to ProtocolProbeAccept::mainEvent()

      ProtocolProbeAccept::mainEvent()

      • probe = new ProtocolProbeTrampoline(this, netvc->mutex, buf, reader);
      • vio = netvc->do_io_read(probe, buffer_size, probe->iobuf);
      • vio->reenable();

      NetHandler::mainNetEvent()

      • callback IOCORE_EVENTS_READ to SslProfileSM

      SslProfileSM::handshakeEvent()

      • call make_ssl_connection() to initlization SSL/CTX
      • raw_read() and create rBIO with handshake buffer
      • call SSL_accept()
      • if handshake done, free handshake buffer then set handler to mainEvent
      • if handshake error, copy handshake buffer into low_profilesm, deattach
        SslProfileSM and set vc->profile_sm = low_profilesm
      • read_reschedule(vc) if ssl_want_read or vc->read.vio was set
      • write_reschedule(vc) if ssl_want_write or vc->write.vio was set

      SslProfileSM::mainEvent()

      • call handle_read()
      • raw_read()
      • callback ProtocolProbeTrampoline::ioCompletionEvent(VC_EVENT_READ_COMPLETE, vio)
      • ProtocolProbe and create HttpSessionAccept()

      TcpProfileSM::mainEvent()

      • call handle_read()
      • move handshake buffer to vio buffer if handshake buffer existed
      • raw_read()
      • callback ProtocolProbeTrampoline::ioCompletionEvent(VC_EVENT_READ_COMPLETE, vio)
      • ProtocolProbe and create HttpSessionAccept()

      the SSLNetVConnection could be replaced by the above process.

      the UnixNetVConnection only as a resource container, saved

      • socket fd
      • read vio
      • writw vio

      and has a timeout control mechanism with InactivityCop.

      with SslProfileSM, ATS doesn't care if a NetVC is a SSLNetVC. which means ATS can handle TCP & SSL connection in the same way by UnixNetVConnection.

      so we can delete these lines from ATS:

      proxy/http/HttpClientSession.cc
      
        if (!iobuf) {
          SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(new_vc);
          if (ssl_vc) {
            iobuf = ssl_vc->get_ssl_iobuf();
            sm_reader = ssl_vc->get_ssl_reader();
          }   
        }
      
      proxy/http2/Http2SessionAccept.cc
      
          if (ssl_vc) {
            iobuf = ssl_vc->get_ssl_iobuf();
            reader = ssl_vc->get_ssl_reader();
          }   
      
      proxy/spdy/SpdySessionAccept.cc
      
          if (ssl_vc) {
            iobuf = ssl_vc->get_ssl_iobuf();
            reader = ssl_vc->get_ssl_reader();
          }   
      
      

      SSLNextProtocolTrampoline has a member `iobuf', it is used to save first content and transfer into ProtocolProbeAccept as a protocol probe buffer.
      thus, HttpSM/SpdySM/H2SM should check the type of vc and get the right probe buffer, `sslvc->iobuf' or `this->iobuf'.

      Merge SSLNextProtocolAccept and SSLNextProtocolTrampoline into SslProfileSM and modify ProtocolProbeTrampoline to accept `Protocol Type' from SslProfileSM by NPN/ALPN.

      After the code merged, only one protocol probe buffer in ProtocolProbeTrampoline, and doesn't need check the type of vc.

        Attachments

        1. ATS SslProfileSMv1.png
          1.43 MB
          Chao Xu
        2. ATS TcpProfileSM.png
          1.01 MB
          Chao Xu

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                oknet Chao Xu
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated:

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 3h
                  3h