<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def starttls(self, ssl_context=None, post_handshake_callback=None):
 """ Start a TLS stream on top of the socket. This is an invalid operation if the stream is not in RAW_OPEN state. If `ssl_context` is set, it overrides the `ssl_context` passed to the constructor. If `post_handshake_callback` is set, it overrides the `post_handshake_callback` passed to the constructor. .. versionchanged:: 0.4 This method is now a barrier with respect to reads and writes: before the handshake is completed (including the post handshake callback, if any), no data is received or sent. """

        if self._state != _State.RAW_OPEN or self._closing:
            raise self._invalid_state("starttls() called")

        if ssl_context is not None:
            self._ssl_context = ssl_context
            self._extra.update(
                sslcontext=ssl_context
            )
        else:
            self._ssl_context = self._ssl_context_factory(self)

        if post_handshake_callback is not None:
            self._tls_post_handshake_callback = post_handshake_callback

        self._waiter = asyncio.Future()
        self._waiter.add_done_callback(self._waiter_done)
        self._initiate_tls()
        try:
            yield from self._waiter
        finally:
            self._waiter = None