Use one mailbox per client. Much more robust and does not risk to hang browser if we get too many open boxes
This commit is contained in:
parent
eb37060de5
commit
cc204b709d
7 changed files with 104 additions and 39 deletions
|
@ -26,6 +26,7 @@
|
|||
#include "tvhead.h"
|
||||
#include "http.h"
|
||||
#include "ajaxui.h"
|
||||
#include "ajaxui_mailbox.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
#include "obj/ajaxui.cssh"
|
||||
|
@ -57,6 +58,22 @@ const char *ajax_tabnames[] = {
|
|||
[AJAX_TAB_ABOUT] = "About",
|
||||
};
|
||||
|
||||
|
||||
const char *
|
||||
ajaxui_escape_apostrophe(const char *content)
|
||||
{
|
||||
static char buf[2000];
|
||||
int i = 0;
|
||||
|
||||
while(i < sizeof(buf) - 2 && *content) {
|
||||
if(*content == '\'')
|
||||
buf[i++] = '\\';
|
||||
buf[i++] = *content++;
|
||||
}
|
||||
buf[i] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX table header
|
||||
*/
|
||||
|
@ -410,7 +427,22 @@ ajax_page_root(http_connection_t *hc, http_reply_t *hr,
|
|||
|
||||
tcp_qprintf(tq, "<div style=\"float: left; width: 100%\">");
|
||||
|
||||
ajax_box_begin(tq, AJAX_BOX_FILLED, "topmenu", NULL, NULL);
|
||||
ajax_box_begin(tq, AJAX_BOX_FILLED, NULL, NULL, NULL);
|
||||
|
||||
tcp_qprintf(tq,
|
||||
"<div style=\"width: 100%%; overflow: auto\">"
|
||||
"<div style=\"float: left; width: 30%%\">"
|
||||
"Tvheadend v1.x (r?)"
|
||||
"</div>"
|
||||
"<div style=\"float: left; width: 40%%\" id=\"topmenu\"></div>"
|
||||
"<div style=\"float: left; width: 30%%; text-align: right\">"
|
||||
"<input class=\"nicebox\" type=\"checkbox\" checked> "
|
||||
"Dynamic updates"
|
||||
"</div>"
|
||||
"</div>");
|
||||
|
||||
ajax_mailbox_start(tq);
|
||||
|
||||
ajax_box_end(tq, AJAX_BOX_FILLED);
|
||||
|
||||
tcp_qprintf(tq, "<div id=\"topdeck\"></div>");
|
||||
|
|
|
@ -79,4 +79,6 @@ void ajax_table_header(http_connection_t *hc, tcp_queue_t *tq,
|
|||
void ajax_table_row(tcp_queue_t *tq, const char *cells[], int columnsizes[],
|
||||
int *bgptr, const char *idprefix[], const char *idpostfix);
|
||||
|
||||
const char *ajaxui_escape_apostrophe(const char *content);
|
||||
|
||||
#endif /* AJAXUI_H_ */
|
||||
|
|
|
@ -229,9 +229,6 @@ ajax_adaptereditor(http_connection_t *hc, http_reply_t *hr,
|
|||
"'/ajax/dvbadaptermuxlist/%s', {method: 'get', evalScripts: true})",
|
||||
tda->tda_identifier, tda->tda_identifier);
|
||||
|
||||
ajax_mailbox_start(tq, tda->tda_identifier);
|
||||
|
||||
|
||||
tcp_qprintf(tq, "<hr><div id=\"addmux\">");
|
||||
dvb_make_add_link(tq, tda, NULL);
|
||||
tcp_qprintf(tq, "</div>");
|
||||
|
|
|
@ -107,7 +107,6 @@ ajax_config_xmltv_tab(http_connection_t *hc, http_reply_t *hr)
|
|||
xg->xg_identifier);
|
||||
|
||||
}
|
||||
ajax_mailbox_start(tq, "xmltvgrabbers");
|
||||
tcp_qprintf(tq, "</div>");
|
||||
|
||||
ajax_box_end(tq, AJAX_BOX_SIDEBOX);
|
||||
|
@ -165,8 +164,6 @@ ajax_xmltvgrabber(http_connection_t *hc, http_reply_t *hr,
|
|||
tcp_qprintf(tq,"</div>");
|
||||
|
||||
ajax_box_end(tq, AJAX_BOX_SIDEBOX);
|
||||
|
||||
ajax_mailbox_start(tq, xg->xg_identifier);
|
||||
http_output_html(hc, hr);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libavutil/md5.h>
|
||||
|
||||
#include "tvhead.h"
|
||||
#include "dispatch.h"
|
||||
#include "http.h"
|
||||
|
@ -34,6 +36,10 @@
|
|||
#define MAILBOX_EMPTY_REPLY_TIMEOUT 10
|
||||
|
||||
|
||||
//#define mbdebug(fmt...) printf(fmt);
|
||||
#define mbdebug(fmt...)
|
||||
|
||||
|
||||
static LIST_HEAD(, ajaxui_mailbox) mailboxes;
|
||||
|
||||
int mailbox_tally;
|
||||
|
@ -50,8 +56,7 @@ typedef struct ajaxui_letter {
|
|||
typedef struct ajaxui_mailbox {
|
||||
LIST_ENTRY(ajaxui_mailbox) amb_link;
|
||||
|
||||
uint32_t amb_boxid;
|
||||
char *amb_subscriptionid;
|
||||
char *amb_boxid; /* an md5hash */
|
||||
|
||||
dtimer_t amb_timer;
|
||||
|
||||
|
@ -83,6 +88,8 @@ amb_destroy(ajaxui_mailbox_t *amb)
|
|||
{
|
||||
ajaxui_letter_t *al;
|
||||
|
||||
mbdebug("mailbox[%s]: destroyed\n", amb->amb_boxid);
|
||||
|
||||
while((al = TAILQ_FIRST(&amb->amb_letters)) != NULL)
|
||||
al_destroy(amb, al);
|
||||
|
||||
|
@ -90,7 +97,7 @@ amb_destroy(ajaxui_mailbox_t *amb)
|
|||
|
||||
dtimer_disarm(&amb->amb_timer);
|
||||
|
||||
free(amb->amb_subscriptionid);
|
||||
free(amb->amb_boxid);
|
||||
free(amb);
|
||||
}
|
||||
|
||||
|
@ -123,45 +130,55 @@ ajax_mailbox_connection_lost(http_reply_t *hr, void *opaque)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
int
|
||||
ajax_mailbox_create(const char *subscriptionid)
|
||||
static ajaxui_mailbox_t *
|
||||
ajax_mailbox_create(const char *id)
|
||||
{
|
||||
ajaxui_mailbox_t *amb = calloc(1, sizeof(ajaxui_mailbox_t));
|
||||
|
||||
amb->amb_boxid = strdup(id);
|
||||
|
||||
mailbox_tally++;
|
||||
|
||||
amb->amb_boxid = mailbox_tally;
|
||||
amb->amb_subscriptionid = strdup(subscriptionid);
|
||||
|
||||
LIST_INSERT_HEAD(&mailboxes, amb, amb_link);
|
||||
|
||||
TAILQ_INIT(&amb->amb_letters);
|
||||
|
||||
dtimer_arm(&amb->amb_timer, ajax_mailbox_unused, amb,
|
||||
MAILBOX_UNUSED_TIMEOUT);
|
||||
return amb->amb_boxid;
|
||||
return amb;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
ajax_mailbox_start(tcp_queue_t *tq, const char *identifier)
|
||||
ajax_mailbox_start(tcp_queue_t *tq)
|
||||
{
|
||||
int boxid = ajax_mailbox_create(identifier);
|
||||
struct timeval tv;
|
||||
uint8_t sum[16];
|
||||
char id[33];
|
||||
int i;
|
||||
struct AVMD5 *ctx;
|
||||
|
||||
/* We need to keep a hidden element in a part of the document that
|
||||
is directly mapped to this mailbox.
|
||||
ctx = alloca(av_md5_size);
|
||||
|
||||
This element is updated in every reply and if it fails,
|
||||
there will be no more updates.
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
This avoid getting stale updaters that keeps on going if parts
|
||||
of the document is reloaded faster than the mailbox sees it */
|
||||
av_md5_init(ctx);
|
||||
av_md5_update(ctx, (void *)&tv, sizeof(tv));
|
||||
av_md5_update(ctx, (void *)&mailbox_tally, sizeof(uint32_t));
|
||||
av_md5_final(ctx, sum);
|
||||
|
||||
tcp_qprintf(tq, "<div style=\"display: none\" id=\"mbox_%d\"></div>", boxid);
|
||||
for(i = 0; i < 16; i++) {
|
||||
id[i * 2 + 0] = "0123456789abcdef"[sum[i] >> 4];
|
||||
id[i * 2 + 1] = "0123456789abcdef"[sum[i] & 15];
|
||||
}
|
||||
id[32] = 0;
|
||||
|
||||
ajax_js(tq, "new Ajax.Request('/ajax/mailbox/%d')", boxid);
|
||||
mbdebug("Generated mailbox %s\n", id);
|
||||
|
||||
ajax_mailbox_create(id);
|
||||
ajax_js(tq, "mailboxquery('%s')", id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,15 +194,19 @@ ajax_mailbox_reply(ajaxui_mailbox_t *amb, http_reply_t *hr)
|
|||
if this div no longer exist, the rest of the javascript will bail
|
||||
out and we will not be reloaded */
|
||||
|
||||
tcp_qprintf(&hr->hr_tq, "$('mbox_%d').innerHTML='';\r\n", amb->amb_boxid);
|
||||
mbdebug("mailbox[%s]: sending reply\n", amb->amb_boxid);
|
||||
|
||||
while((al = TAILQ_FIRST(&amb->amb_letters)) != NULL) {
|
||||
tcp_qprintf(&hr->hr_tq, "try {\r\n");
|
||||
tcp_qprintf(&hr->hr_tq, "%s%s", al->al_payload_a, al->al_payload_b ?: "");
|
||||
mbdebug("\t%s%s", al->al_payload_a, al->al_payload_b ?: "");
|
||||
|
||||
tcp_qprintf(&hr->hr_tq, "}\r\n"
|
||||
"catch(err) {}\r\n");
|
||||
al_destroy(amb, al);
|
||||
}
|
||||
|
||||
tcp_qprintf(&hr->hr_tq, "new Ajax.Request('/ajax/mailbox/%d');\r\n",
|
||||
amb->amb_boxid);
|
||||
tcp_qprintf(&hr->hr_tq, "mailboxquery('%s');\r\n", amb->amb_boxid);
|
||||
|
||||
http_output(hr->hr_connection, hr, "text/javascript", NULL, 0);
|
||||
amb->amb_hr = NULL;
|
||||
|
@ -218,28 +239,35 @@ static int
|
|||
ajax_mailbox_poll(http_connection_t *hc, http_reply_t *hr,
|
||||
const char *remain, void *opaque)
|
||||
{
|
||||
uint32_t boxid;
|
||||
ajaxui_mailbox_t *amb;
|
||||
|
||||
if(remain == NULL)
|
||||
return HTTP_STATUS_NOT_FOUND;
|
||||
|
||||
boxid = atoi(remain);
|
||||
mbdebug("mailbox[%s]: Incomming request ... ", remain);
|
||||
|
||||
LIST_FOREACH(amb, &mailboxes, amb_link)
|
||||
if(amb->amb_boxid == boxid)
|
||||
if(!strcmp(amb->amb_boxid, remain))
|
||||
break;
|
||||
if(amb == NULL)
|
||||
return HTTP_STATUS_NOT_FOUND;
|
||||
|
||||
if(amb->amb_hr != NULL)
|
||||
if(amb == NULL) {
|
||||
amb = ajax_mailbox_create(remain);
|
||||
mbdebug("creating mailbox ... ");
|
||||
}
|
||||
|
||||
if(amb->amb_hr != NULL) {
|
||||
mbdebug("mailbox already processing\n");
|
||||
return 409;
|
||||
|
||||
}
|
||||
if(TAILQ_FIRST(&amb->amb_letters) != NULL) {
|
||||
/* Pending letters, direct reply */
|
||||
mbdebug("direct reply\n");
|
||||
ajax_mailbox_reply(amb, hr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mbdebug("nothing in queue, waiting\n");
|
||||
|
||||
amb->amb_hr = hr;
|
||||
|
||||
hr->hr_opaque = amb;
|
||||
|
@ -286,8 +314,6 @@ ajax_mailbox_add_to_subscription(const char *subscription,
|
|||
ajaxui_letter_t *al;
|
||||
|
||||
LIST_FOREACH(amb, &mailboxes, amb_link) {
|
||||
if(strcmp(subscription, amb->amb_subscriptionid))
|
||||
continue;
|
||||
|
||||
/* Avoid inserting the same message twice */
|
||||
|
||||
|
@ -329,6 +355,8 @@ ajax_mailbox_update_div(const char *subscription, const char *prefix,
|
|||
char buf_a[500];
|
||||
char buf_b[500];
|
||||
|
||||
content = ajaxui_escape_apostrophe(content);
|
||||
|
||||
snprintf(buf_a, sizeof(buf_a), "$('%s_%s').innerHTML=", prefix, postfix);
|
||||
snprintf(buf_b, sizeof(buf_b), "'%s';\n\r", content);
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ void ajax_mailbox_tdmi_services_change(th_dvb_mux_instance_t *tdmi);
|
|||
|
||||
void ajax_mailbox_tda_change(th_dvb_adapter_t *tda);
|
||||
|
||||
void ajax_mailbox_start(tcp_queue_t *tq, const char *identifier);
|
||||
void ajax_mailbox_start(tcp_queue_t *tq);
|
||||
|
||||
struct xmltv_grabber;
|
||||
|
||||
|
|
|
@ -66,3 +66,12 @@ function tentative_chname(id, url, name)
|
|||
parameters: { newname: newname }});
|
||||
}
|
||||
}
|
||||
|
||||
function mailboxquery(boxid)
|
||||
{
|
||||
new Ajax.Request('/ajax/mailbox/' + boxid,
|
||||
{
|
||||
onFailure: function(req) { alert(req.responseText); },
|
||||
onException: function(t,e) { alert(e); }
|
||||
})
|
||||
}
|
Loading…
Add table
Reference in a new issue