Re: Longpoll with Libsoup
- From: Henry Högelow <h hoegelow raumfeld com>
- To: libsoup-list gnome org
- Subject: Re: Longpoll with Libsoup
- Date: Mon, 14 May 2012 09:05:29 +0200
Hi,
in former versions of the libsoup it was enough just to poll the
underlying socket from time to time. On SOUP_SOCKET_ERROR it was finishing
the messages itself. Now, a little bit more code is needed. Here is how I
solved it in C++:
For each incoming request install a poll on the underlying socket. Also
hold a set of all messages received on a specific socket. Whenever reading
from the socket results in SOUP_SOCKET_EOF or SOUP_SOCKET_ERROR, call
soup_message_finished on the associated messages.
namespace SOCKET_POLL
{
typedef set<SoupMessage*> tRecordSet;
map<SoupSocket*, tRecordSet> s_socketToMessages;
gboolean pollSocket(SoupSocket *socket)
{
char buffer;
gsize len = 0;
SoupSocketIOStatus result = soup_socket_read (socket, &buffer, 1,
&len, NULL, NULL);
if(result == SOUP_SOCKET_EOF || result == SOUP_SOCKET_ERROR)
{
tRecordSet &s = s_socketToMessages[socket];
tRecordSet localCopy;
swap(s, localCopy);
for(SoupMessage* msg : localCopy)
{
soup_message_finished(msg);
}
soup_socket_disconnect(socket);
s_socketToMessages.erase(socket);
return FALSE;
}
return TRUE;
}
void removePoll(guint pollerTimer, SoupSocket *socket)
{
g_source_remove(pollerTimer);
s_socketToMessages.erase(socket);
}
void msg_finished(SoupMessage *msg, SoupSocket *socket)
{
auto sIT = s_socketToMessages.find(socket);
if(sIT != s_socketToMessages.end())
{
tRecordSet &s = sIT->second;
auto msgIT = s.find(msg);
if(msgIT != s.end())
{
s.erase(msgIT);
if(s.empty())
{
s_socketToMessages.erase(sIT);
}
}
}
}
void installSocketPoll(SoupServer *server, SoupMessage *msg, SoupSocket
*socket)
{
if(s_socketToMessages.find(socket) == s_socketToMessages.end())
{
guint poller = g_timeout_add_seconds(30, (GSourceFunc)pollSocket,
socket);
g_object_weak_ref((GObject*)socket, (GWeakNotify)removePoll,
(void*)poller);
}
s_socketToMessages[socket].insert(msg);
g_signal_connect(msg, "finished", (GCallback)&msg_finished, socket);
}
}
void Server::serverCallback (SoupServer *server, SoupMessage *msg, const
char *strPath,
GHashTable *query, SoupClientContext
*context, Server *pThis)
{
SOCKET_POLL::installSocketPoll(server, msg,
soup_client_context_get_socket(context));
.....
}
Best, Henry
Am 13.05.2012, 20:04 Uhr, schrieb Christian Hergert <chris dronelabs com>:
Hi,
I have a similar question to Mark's post about longpolling a few weeks
ago. I have a system that is doing lonpolling. However, I would like to
stop various backend work when the client disconnects. I haven't found a
way to get an event upon the client disconnecting.
What I've tried:
Create a server, tried both sync and async w/ mainloop.
Handle incoming request, pause message to simulate longpoll.
Attach to various signals on the message's SoupSocket such as:
- disconnect
- event
Get the raw FD for the socket w/ soup_socket_get_fd().
Create a new GSource that poll's for (G_IO_ERR | G_IO_HUP) on FD.
It appears based on the code I've read that "disconnect" would be
unlikely to fire while the SoupMessage's IO is paused. (That is why I
tried the route of polling the FD myself with a custom GSource and
g_source_add_poll().
Anyway, still no luck as those poll conditions don't seem to fire.
For the client, I tried both curl and telnet w/ ^]quit.
Thanks for libsoup, it's fantastic.
-- Christian
_______________________________________________
libsoup-list mailing list
libsoup-list gnome org
http://mail.gnome.org/mailman/listinfo/libsoup-list
--
Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]