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
Attachments
Issue Links
- links to