You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficserver.apache.org by "Oknet Xu (JIRA)" <ji...@apache.org> on 2016/04/05 06:25:25 UTC

[jira] [Created] (TS-4322) ProfileSM Proposal

Oknet Xu created TS-4322:
----------------------------

             Summary: ProfileSM Proposal
                 Key: TS-4322
                 URL: https://issues.apache.org/jira/browse/TS-4322
             Project: Traffic Server
          Issue Type: Improvement
          Components: Core, Network
            Reporter: Oknet Xu


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 :

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

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

{code}
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 . . .
{code}

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:

{code}
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();
    }   

{code}

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.





--
This message was sent by Atlassian JIRA
(v6.3.4#6332)