"Re-architecture"!

Instead of "only critique", here is a (possible) proposition to do both
"read-like" (efficiently) and the current stuff.

There should be a definition of what *semantically* is "read" or "write"
according to the request/use case.

The "do/doing/done" internal phase, should start with a "pre-rw" phase
defined as: whatever is needed to start the read or write phase defined
above.

"do/doing/done" = "pre-rw" + "rw phase" (+ EOF|trailers?)

[For the sake of simplifying the explanation, I am skipping the
"headers" phase here, including them in "pre-rw", they SHOULD of course
still be exposed coherently.]


Let me explain with an simple example: http/1.1 GET

In this case the "read" means reading the body.

"write" means nothing (returns an error).


Now we implement:

curl_easy_perform_rw()

  It does the same thing than CURL_CONNECT_ONLY + the new "pre-rw"
phase, then returns to the caller.

  In our example, the existing HTTP SETOPTs can still be used prior to
calling curl_easy_perform_rw(): location, user agent, cookies, specific
headers, proxies, authentication, etc...

  In a "classic" programming scheme, this is sort of "openfile()".

The caller then has:

curl_easy_read():

  Reads the http/1.1 body with the same semantic as read() -with or
without EAGAIN, both are possible, could be through a sort of direct_io
SETOPT flag to mimic the kernel-

  This new "read" is now as efficient as it can be, ranging from
directly receiving the exact amount of data from the socket into
caller's provided buffer (plain http/1.?), to being on top of "filters"
plus an OpenSSL BIO stack with possible proxies in the mix.

  http/1.1 GET is simple and in this case curl_easy_read() performs
about the same task as curl_easy_recv(). It still makes sense if we want
gzip/http 2, libcurl can simply add "filters" on top of the stack before
exposing curl_easy_read() (same principle as BIO filters for OpenSSL),
and it this case, curl_easy_read() would be curl_easy_recv() +
appropriate "filters".

curl_easy_write(): returns "error" in the example of http GET

curl_easy_eof()

curl_easy_cleanup(): stays to play the role of "closefile()".


curl_easy_perform() still exists (for 99,99% of those needing it of
course!) but is now (in our example):

curl_easy_perform(CURL *curl) {

  curl_easy_perform_rw(curl);

  while(!curl_easy_eof(curl)) {

      sz = curl_easy_read(curl, internal_buf, maxsz);

      res = curl->write_callback(internal_buf, 1, sz, userdata);

      /* some error handling code */

  }

}


Caveat (for simplification): the caller CANNOT mix
curl_read()/curl_write() and write/read callbacks in the same "perform".


So you see, quite a big challenge "reversing the stack" (callbacks on
top of BIO read, not the opposite) for a feature that nobody really
wanted so far!

There might be simpler solutions... they didn't cross my mind with the
few I know of libcurl.


Cheers
Alain
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:   https://curl.se/mail/etiquette.html

Reply via email to