Re: [libmicrohttpd] Complete request on fd becoming ready

2017-03-27 Thread Kenneth Mastro
On the MHD side, it may depend on connection volume and your hardware.  You
could use the 'thread per connection' mode, which would allow the thread to
wait for a response without blocking other connections.  Alternatively, you
could use MHD's 'suspend/resume' functionality to reduce the number of MHD
threads (and thus free up the primary MHD thread to service other
connections/requests).

If you don't use the 'thread per connection' mode, I strongly suspect
you're going to want/need to use at least 1 other thread to service the
binary protocol side of things.  I'm not certain, but I don't think MHD has
a mechanism where you can 'service it repeatedly' from a main loop (as is
common in some embedded systems or real-time applications).  If your
hardware can support it, I'd really recommend adding one or more threads to
handle the back-end.  (C++ might make that easier than straight C, by the
way.)

For application structure, there are lots of ways to do it.  That really
doesn't have much to do with MHD.  Off the top of my head, I'd consider
using condition variables, wait/notify, and some kind of 'result pointer'
to transfer data between threads.  I do this all the time (in C++ on Linux
- not sure how hard that would be to do in C or other platforms).  You
could also just use 2 blocking queues and have a thread on each side to
process the data from one queue and feed stuff to the other queue for the
other side to handle.  It really depends on how many simultaneous requests
you want to process.

If traffic/request volume is sufficiently low, the simplest thing to do is
use MHD's 'thread per connection' mode and just do the back-end I/O in that
thread.  Send the request, wait for the response, and send the result back
out MHD to the caller.  Just make sure the back-end is thread-safe and/or
the MHD side waits for a request to finish before sending another (even if
it's simply by using a mutex).  It's hard to know what to suggest without a
lot more info.

In short - this sounds a lot more like a threading problem than any problem
you might have with MHD.

Hope that helps.


Ken



On Sun, Mar 26, 2017 at 8:44 PM, Hein-Pieter van Braam  wrote:

> Hello all,
>
> I am writing an MHD application where the MHD HTTP server acts as a
> proxy between a HTTP REST API and a different binary protocol on the
> backend. My MHD application opens a new TCP connection to the backend,
> translates the request, and waits for an answer.
>
> The waiting on an answer part would normally be blocking, and reading
> the MHD manual I can't come up with a way of using async io here. What
> would an MHD application look like that creates response objects from
> (another) polling loop, and where do I even place this loop?
>
> I have been thinking of a variety of convoluted things with threads,
> then I figured it'd probably be better to ask the experts :)
>
> Thanks!
>
> - HP
>
>


Re: [libmicrohttpd] Complete request on fd becoming ready

2017-03-27 Thread Hein-Pieter van Braam
Hi!

Thank you for your reply, I think my original question wasn't very well
posed. Let me try to rephrase it.

In the epoll + threadpool configuration of MHD, MHD itself uses an
epoll() type loop to service fds that are ready to send or receive
traffic from clients. I/O is non-blocking and when MHD is waiting on
the kernel to finish sending traffic back to the client, or waiting on
traffic from the client, the fd goes back into the wait list of epoll.

What I'm hoping to achieve is to receive traffic from my backend in a
similar manner. So I'm hoping for something like this:

* MHD mainloop accept()'s a new connection
* MHD pushes this new connection to a thread on its threadpool
* MHD runs the request handler for the connection
* Request handler parses the HTTP request and constructs a request in
the binary protocol.
* Request handler opens a non-blocking connection to the backend
server.
< .. magic .. >
* The request gets sent to the backend server once the connection to
the backend becomes ready for writing.
< .. more magic .. >
* Once the listening FD for the backend connection becomes ready,
create a response object and send it to the client to have MHD then use
its normal async loop to service the client.

What I'm thinking of doing now is to do something like this in the
request handler:

* Send the parsed request to a separate thread that has its own epoll()
loop, along with struct MHD_Connection *connection.
* Return MHD_OK
* In the separate thread, deal with the request like normal, when the
backend socket becomes ready for reading construct the MHD_Response and
call MHD_queue_response (connection, MHD_HTTP_OK, response);
* Destroy the response object

Now, I'm not entirely sure if this will work for a variety of reasons.
I don't know if it's safe toe call MHD_queue_response() in this manner
for instance.

I was also wondering if there was a way of combining these loops so I
don't have to do it this way. Maybe if external select does what I
think it does I could use that as my programs' main loop instead of
MHD's, but I don't know if that will actually be any better. 


On Mon, 2017-03-27 at 08:33 -0400, Kenneth Mastro wrote:
> 
> If traffic/request volume is sufficiently low, the simplest thing to
> do is use MHD's 'thread per connection' mode and just do the back-end 
> I/O in that thread.  Send the request, wait for the response, and
> send the result back out MHD to the caller.  Just make sure the back-
> end is thread-safe and/or the MHD side waits for a request to finish
> before sending another (even if it's simply by using a mutex).  It's
> hard to know what to suggest without a lot more info.

This is more or less what I'm doing now. Doing blocking I/O to the
backend service in a thread per connection.

> In short - this sounds a lot more like a threading problem than any
> problem you might have with MHD.

It's not so much a 'problem' as that I'm trying to figure out how to
optimize my program so it can be fully asynchronous. 


> 
> 
> On Sun, Mar 26, 2017 at 8:44 PM, Hein-Pieter van Braam 
> wrote:
> > Hello all,
> > 
> > I am writing an MHD application where the MHD HTTP server acts as a
> > proxy between a HTTP REST API and a different binary protocol on
> > the
> > backend. My MHD application opens a new TCP connection to the
> > backend,
> > translates the request, and waits for an answer.
> > 
> > The waiting on an answer part would normally be blocking, and
> > reading
> > the MHD manual I can't come up with a way of using async io here.
> > What
> > would an MHD application look like that creates response objects
> > from
> > (another) polling loop, and where do I even place this loop? 
> > 
> > I have been thinking of a variety of convoluted things with
> > threads,
> > then I figured it'd probably be better to ask the experts :)
> > 
> > Thanks!
> > 
> > - HP
> > 
> > 
> 
> 



Re: [libmicrohttpd] Complete request on fd becoming ready

2017-03-27 Thread Kenneth Mastro
See inline comments, below.

Ken


On Mon, Mar 27, 2017 at 9:04 AM, Hein-Pieter van Braam  wrote:

> Hi!
>
> Thank you for your reply, I think my original question wasn't very well
> posed. Let me try to rephrase it.


> In the epoll + threadpool configuration of MHD, MHD itself uses an
> epoll() type loop to service fds that are ready to send or receive
> traffic from clients. I/O is non-blocking and when MHD is waiting on
> the kernel to finish sending traffic back to the client, or waiting on
> traffic from the client, the fd goes back into the wait list of epoll.
>
> What I'm hoping to achieve is to receive traffic from my backend in a
> similar manner. So I'm hoping for something like this:
>
> * MHD mainloop accept()'s a new connection
> * MHD pushes this new connection to a thread on its threadpool
> * MHD runs the request handler for the connection
> * Request handler parses the HTTP request and constructs a request in
> the binary protocol.
> * Request handler opens a non-blocking connection to the backend
> server.
> < .. magic .. >
> * The request gets sent to the backend server once the connection to
> the backend becomes ready for writing.
> < .. more magic .. >
> * Once the listening FD for the backend connection becomes ready,
> create a response object and send it to the client to have MHD then use
> its normal async loop to service the client.
>

I'm not entirely sure what 'magic' you need.  I may not understand your
problem well enough, though.  It sounds like you want to use MHD's
suspend/resume functionality to allow MHD to use epoll internally to
service connections, and then feed it responses when the response is
ready.  I have not used MHD's suspend/resume code personally (I use the
'thread per connection' mode), but I know many people have.

>From what I recall, the gist is:
* You get a request from the caller.  That causes MHD to call your code to
process it.
* You do what you need to get things going, and then 'suspend' the
connection.
* This allows MHD to use that thread to continue to process incoming
requests.
* Once the result is ready, you call the 'resume' function to allow you to
do stuff with that connection again.
* At this point I THINK MHD calls your callback again, thus giving you the
option to queue a response.  (I.e., you don't just queue it from any old
thread.  You have to wait for one of MHD's threads to service you for that
particular connection.)

I'm a bit hazy on the details and/or logistics of the above, but I think
that's about right.  I personally can't help more with that, but I think
searching the mailing list archive might be helpful.  I've seen messages
roll through here in the past couple years that talk about this.  Maybe
somebody with more experience in this area can chime in.


What I'm thinking of doing now is to do something like this in the
> request handler:
>
> * Send the parsed request to a separate thread that has its own epoll()
> loop, along with struct MHD_Connection *connection.
> * Return MHD_OK
> * In the separate thread, deal with the request like normal, when the
> backend socket becomes ready for reading construct the MHD_Response and
> call MHD_queue_response (connection, MHD_HTTP_OK, response);
> * Destroy the response object
>
> Now, I'm not entirely sure if this will work for a variety of reasons.
> I don't know if it's safe toe call MHD_queue_response() in this manner
> for instance.
>

See my above comment.  It sounds like you want to use the suspend/resume
functionality and you're just wondering how to get it to work.  Valid
question.  I'm not sure how robust the example code for suspend/resume is.
(I remember thinking it wasn't impressively clear and/or wasn't really
available at the time, but I only gave it cursory attention.  The mailing
list archive may be of more help.)



> I was also wondering if there was a way of combining these loops so I
> don't have to do it this way. Maybe if external select does what I
> think it does I could use that as my programs' main loop instead of
> MHD's, but I don't know if that will actually be any better.
>

Fair enough.  I don't know if you can service other things in an MHD
external epoll.  (I don't see why not, but I have never used MHD's external
select stuff.)  If you have the horsepower (and it won't take much),
keeping the loops separate may be a bit simpler.  I.e., skip the external
select.  Let MHD do its thing and you do your thing.  You have the problem
of getting the data back to the caller either way and will still need to
use suspend/resume since you shouldn't block the MHD threads.  (Or just use
thread per connection, of course.  You can do whatever you want in those
threads because MHD doesn't need them to service other connections with
them.)




>
> On Mon, 2017-03-27 at 08:33 -0400, Kenneth Mastro wrote:
> >
> > If traffic/request volume is sufficiently low, the simplest thing to
> > do is use MHD's 'thread per connection' mode and just do the back-end
> > I/O in tha

[libmicrohttpd] why does not libmicrohttpd support for resume from break-point??

2017-03-27 Thread ??**??
why does not libmicrohttpd support for resume from break-point?? how do?? 
Please give some suggestions??

[libmicrohttpd] feature request: give a possibility to re-assign callbacks

2017-03-27 Thread Vitaliy T
Hello,

1. Subj.
2. Why is this should be useful?

2.1. When you're actively using suspend/resume functionality and later
trying to shutdown the MHD daemon, then last one, by default, uses
default callbacks (which were given at the startup) for _resumed_
connections (as docs says).

By good intentions, such callbacks must be transformed into stubs,
that is, { return MHD_NO; } to complete the task properly. Currently,
it is possible to wait, I may say, weeks if there are thousands of
active requests.

2.2. It gives a possibility to write, I have no good words for this
except next, the polymorph-like servers. For instance, it may be funny
(and may be be a serious work) to load an external shared library and
then re-assign callbacks to the functions which the library contains.

Either, are there any alternatives about how to do tasks above I don't know?

P.S. Yes, I know, that the task must be done properly, that is, there
are no active connections, the daemon should be in quince-mode, or
connections must be blocked by a firewall and so on. This is not a
problem.

Thanks!

-- 
With Best Regards,
Vitaliy V. Tokarev



Re: [libmicrohttpd] MHD_quiesce_daemon() question

2017-03-27 Thread Christian Grothoff
On 03/26/2017 10:36 PM, Evgeny Grin wrote:
> On 26.03.2017 8:33, silvioprog wrote:
>> I found the following related message:
>>
>> https://lists.gnu.org/archive/html/libmicrohttpd/2014-09/msg00012.html
>>
>> I've used a similar logic, but with item X below, because I need to wait
>> the client processing:
>>
>> 1) MHD_quiesce_daemon()
>> *X) while (info.num_connections > 0) sleep(0.5s) # pseudo code*
>> 2) MHD_stop_daemon()
>> 3) close()
>>
>> Real implementation:
>>
>> bool bf_httpsrv_shutdown(struct bf_httpsrv *srv, bool force) {
>> MHD_socket fd;
>> if (srv && srv->listening) {
>> fd = MHD_quiesce_daemon(srv->mhd);
>> if (!force)
>> while (MHD_get_daemon_info(srv->mhd, 
>> MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections > 0)
>> usleep(1000 * 500); //TODO: allow to use external callback
>> MHD_stop_daemon(srv->mhd);
>> if (fd != MHD_INVALID_SOCKET)
>> close(fd);
>> srv->listening = false;
>> return true;
>> }
>> return false;
>> }
>>
>>
>> Calling it with bf_httpsrv_shutdown(srv, false) the server stops waiting
>> for clients processing.
>>
>> So, what do you think about the logic above? Should it be improved?!
>>
>> Thanks in advance for any suggestions!
> 
> If you don't check returned value from MHD_quiesce_daemon(), you may
> later found that you didn't quiesced daemon, so move check right after
> MHD_quiesce_daemon() and added error handling.
> If you didn't set connection timeout, connection may live indefinitely.
> Moreover, even with connection timeout, clients may continue processing
> on same HTTP 1.1 connections with new requests indefinitely.
> Furthermore, even with HTTP 1.0 and connection timeout hypothetical
> client may read answer very slow with results in very long unpredictable
> closure of connection.
> So: yes, you code will work but may result in very long (hours, for
> example) or even indefinitely long daemon shutdown.
> 

And while Evgeny is 100% correct, let me point out the opposite concern:
0.5 s can still be an eternity (think: shell scripts, automated tests,
etc.) and that you ideally should use MHD_OPTION_NOTIFY_CONNECTION to
notify main() that you are "done". For example by doing a semaphore-down
operation/IPC write in main() and a semaphore-up()/IPC read in the
callback IF you are past quiesce and info tells you that you are the
last connection.



signature.asc
Description: OpenPGP digital signature


[libmicrohttpd] Reading data from named pipe

2017-03-27 Thread Alex Reynolds
I have an API that reads a subset of data from an archive and writes it to
a FILE*. I can use this API to write this data subset to a temporary file
via mkstemp() and fdopen().

I am currently using MHD_create_response_from_callback() to read chunks of
bytes from this temporary file and write them to the web client. This works
well on small files.

To avoid the I/O cost of writing a larger temporary file, and then reading
from it, I set up a named pipe via mkfifo() and a FILE* that points to it.
When I have MHD_create_response_from_callback() try to read from this named
pipe, in the same way that it is set up to read from the temporary file,
the server and client hang.

If this is possible, what is the correct way to serve data from a named
pipe?

Regards,
Alex


Re: [libmicrohttpd] feature request: give a possibility to re-assign callbacks

2017-03-27 Thread Evgeny Grin
On 27.03.2017 17:29, Vitaliy T wrote:
> 1. Subj.
Which callbacks would you like to reassign?

> 2. Why is this should be useful?
> 
> 2.1. When you're actively using suspend/resume functionality and later
> trying to shutdown the MHD daemon, then last one, by default, uses
> default callbacks (which were given at the startup) for _resumed_
> connections (as docs says).
> 
> By good intentions, such callbacks must be transformed into stubs,
> that is, { return MHD_NO; } to complete the task properly. Currently,
> it is possible to wait, I may say, weeks if there are thousands of
> active requests.

What prevents to return "MHD_NO" early from the same callback when required?

> 2.2. It gives a possibility to write, I have no good words for this
> except next, the polymorph-like servers. For instance, it may be funny
> (and may be be a serious work) to load an external shared library and
> then re-assign callbacks to the functions which the library contains.
> 
> Either, are there any alternatives about how to do tasks above I don't know?
Simple (pseudo code):

int callback(void *user_data)
{
  struct my_data * const info = (struct my_data *) user_data;
  switch(info->callback_type)
  {
case use_callback_a: return call_callback_a(user_data);
case use_callback_b: return call_callback_b(user_data);
default:
  return info->current_callback(user_data);
  }
}

Will this work for you?


-- 
Wishes,
Evgeny



Re: [libmicrohttpd] why does not libmicrohttpd support for resume from break-point?

2017-03-27 Thread Evgeny Grin
Hi!

Could you clarify, what do you mean by "resume from break-point"?

-- 
Best Wishes,
Evgeny Grin

On 27.03.2017 5:21, 星**光 wrote:
> why does not libmicrohttpd support for resume from break-point? how
> do? Please give some suggestions?



Re: [libmicrohttpd] feature request: give a possibility to re-assign callbacks

2017-03-27 Thread Vitaliy T
On 27 March 2017 at 23:19, Evgeny Grin  wrote:
> Which callbacks would you like to reassign?

At least, MHD_AccessHandlerCallback (a.k.a DH).

> What prevents to return "MHD_NO" early from the same callback when required?

Nothing. But on each request we do at least one useless check.

> Simple (pseudo code): [...]
> Will this work for you?

Yes, it will work for me. But I asked about "the right way" :) Your
code also uses de-referencing, which also consumes CPU.
Anyway, I will live fine with such a workaround. It can be added to
the MHD's tutorial.

Thanks!

-- 
With Best Regards,
Vitaliy V. Tokarev



Re: [libmicrohttpd] MHD_quiesce_daemon() question

2017-03-27 Thread silvioprog
Thanks for replying Evgeny, you and Christian always saving my day. :-)

I read and re-read your and Christian answer, and finally I found a
possible way to never lock the server at shutdown: adding an option to exit
the server after configurable attempts. It can solve the timeout problem
too, because I can't ensure that the programmer have configured it (anyway
my library will assume 15 seconds by default). So, the code below applies
your tips and implements the attempts approach:

bool bf_httpsrv_shutdown(struct bf_httpsrv *srv) {
MHD_socket fd;
uint8_t shutdown_attempts; /* Max 256. */
if (srv && srv->listening) {
fd = MHD_quiesce_daemon(srv->mhd);
if (fd != MHD_INVALID_SOCKET)
close(fd);
else
_BF_LOG("Server quiesce failed.\n");
if (srv->forced_shutdown) {
shutdown_attempts = 1;
while (MHD_get_daemon_info(srv->mhd,
MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections > 0) {
if (shutdown_attempts >= srv->shutdown_attempts) { /*
Default srv->shutdown_attempts is 10. */
_BF_LOG("Forced server shutdown.\n");
exit(EINTR);
}
shutdown_attempts++;
sleep(1);
}
}
MHD_stop_daemon(srv->mhd);
srv->listening = false;
return true;
}
return false;
}


Unfortunately if exit was called the MHD_stop_daemon() will be not called,
probably raising some memory leak, but current I have no idea how it could
be solved.

Feel totally free to point improvements about this new version. :-)

On Sun, Mar 26, 2017 at 5:36 PM, Evgeny Grin  wrote:

> On 26.03.2017 8:33, silvioprog wrote:
> > I found the following related message:
> >
> > https://lists.gnu.org/archive/html/libmicrohttpd/2014-09/msg00012.html
> >
> > I've used a similar logic, but with item X below, because I need to wait
> > the client processing:
> >
> > 1) MHD_quiesce_daemon()
> > *X) while (info.num_connections > 0) sleep(0.5s) # pseudo code*
> > 2) MHD_stop_daemon()
> > 3) close()
> >
> > Real implementation:
> >
> > bool bf_httpsrv_shutdown(struct bf_httpsrv *srv, bool force) {
> > MHD_socket fd;
> > if (srv && srv->listening) {
> > fd = MHD_quiesce_daemon(srv->mhd);
> > if (!force)
> > while (MHD_get_daemon_info(srv->mhd,
> MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections > 0)
> > usleep(1000 * 500); //TODO: allow to use external
> callback
> > MHD_stop_daemon(srv->mhd);
> > if (fd != MHD_INVALID_SOCKET)
> > close(fd);
> > srv->listening = false;
> > return true;
> > }
> > return false;
> > }
> >
> >
> > Calling it with bf_httpsrv_shutdown(srv, false) the server stops waiting
> > for clients processing.
> >
> > So, what do you think about the logic above? Should it be improved?!
> >
> > Thanks in advance for any suggestions!
>
> If you don't check returned value from MHD_quiesce_daemon(), you may
> later found that you didn't quiesced daemon, so move check right after
> MHD_quiesce_daemon() and added error handling.
> If you didn't set connection timeout, connection may live indefinitely.
> Moreover, even with connection timeout, clients may continue processing
> on same HTTP 1.1 connections with new requests indefinitely.
> Furthermore, even with HTTP 1.0 and connection timeout hypothetical
> client may read answer very slow with results in very long unpredictable
> closure of connection.
> So: yes, you code will work but may result in very long (hours, for
> example) or even indefinitely long daemon shutdown.
>
> --
> Best Wishes,
> Evgeny Grin
>

-- 
Silvio Clécio


Re: [libmicrohttpd] MHD_quiesce_daemon() question

2017-03-27 Thread silvioprog
Thanks a lot for your great idea, dude. I certainly will use it very soon.
:-)

I took a look at IPCs, but now, I would like something that stops receiving
new clients and forces the current ones to finish their processing.
Probably I may use IPCs (or any existing feature in MHD) to send some
signal to the clients warning that the server will be finished in N
seconds, so the clients could finish their processing immediately.

On Mon, Mar 27, 2017 at 1:00 AM, Christian Grothoff 
wrote:

> On 03/26/2017 10:36 PM, Evgeny Grin wrote:
> > On 26.03.2017 8:33, silvioprog wrote:
> >> I found the following related message:
> >>
> >> https://lists.gnu.org/archive/html/libmicrohttpd/2014-09/msg00012.html
> >>
> >> I've used a similar logic, but with item X below, because I need to wait
> >> the client processing:
> >>
> >> 1) MHD_quiesce_daemon()
> >> *X) while (info.num_connections > 0) sleep(0.5s) # pseudo code*
> >> 2) MHD_stop_daemon()
> >> 3) close()
> >>
> >> Real implementation:
> >>
> >> bool bf_httpsrv_shutdown(struct bf_httpsrv *srv, bool force) {
> >> MHD_socket fd;
> >> if (srv && srv->listening) {
> >> fd = MHD_quiesce_daemon(srv->mhd);
> >> if (!force)
> >> while (MHD_get_daemon_info(srv->mhd,
> MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections > 0)
> >> usleep(1000 * 500); //TODO: allow to use external
> callback
> >> MHD_stop_daemon(srv->mhd);
> >> if (fd != MHD_INVALID_SOCKET)
> >> close(fd);
> >> srv->listening = false;
> >> return true;
> >> }
> >> return false;
> >> }
> >>
> >>
> >> Calling it with bf_httpsrv_shutdown(srv, false) the server stops waiting
> >> for clients processing.
> >>
> >> So, what do you think about the logic above? Should it be improved?!
> >>
> >> Thanks in advance for any suggestions!
> >
> > If you don't check returned value from MHD_quiesce_daemon(), you may
> > later found that you didn't quiesced daemon, so move check right after
> > MHD_quiesce_daemon() and added error handling.
> > If you didn't set connection timeout, connection may live indefinitely.
> > Moreover, even with connection timeout, clients may continue processing
> > on same HTTP 1.1 connections with new requests indefinitely.
> > Furthermore, even with HTTP 1.0 and connection timeout hypothetical
> > client may read answer very slow with results in very long unpredictable
> > closure of connection.
> > So: yes, you code will work but may result in very long (hours, for
> > example) or even indefinitely long daemon shutdown.
> >
>
> And while Evgeny is 100% correct, let me point out the opposite concern:
> 0.5 s can still be an eternity (think: shell scripts, automated tests,
> etc.) and that you ideally should use MHD_OPTION_NOTIFY_CONNECTION to
> notify main() that you are "done". For example by doing a semaphore-down
> operation/IPC write in main() and a semaphore-up()/IPC read in the
> callback IF you are past quiesce and info tells you that you are the
> last connection.
>
>


-- 
Silvio Clécio