]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Use one mailbox per client. Much more robust and does not risk to hang browser if...
authorAndreas Öman <andreas@lonelycoder.com>
Sat, 19 Apr 2008 12:08:48 +0000 (12:08 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Sat, 19 Apr 2008 12:08:48 +0000 (12:08 +0000)
ajaxui/ajaxui.c
ajaxui/ajaxui.h
ajaxui/ajaxui_config_dvb.c
ajaxui/ajaxui_config_xmltv.c
ajaxui/ajaxui_mailbox.c
ajaxui/ajaxui_mailbox.h
ajaxui/tvheadend.js

index 1f75a8c2befbdb02c244fd8f5df6a99239af7082..84782f128b05b02f8e1e53efa13a6c37262109cf 100644 (file)
@@ -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>");
index e695d7516838c57658275774729a1326282361cd..d1b3839d123c65c7659d33b53505aaa8dbba7a2d 100644 (file)
@@ -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_ */
index b650819fe8ce4f747f32bb1198ff060c12f98ede..28722e140e45da38b3dd9eba054c1e8f3a0db1a4 100644 (file)
@@ -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>");
index c69b0872d4ad217078845faca0de433dd8cbec6d..a917fe051477602af388d63d59826a36b52f3364 100644 (file)
@@ -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;
 }
index 4c7862db6c0a84dba6f90a0742d1f224baa19af4..43a165426c722e63479abcc8cd587d390be73d60 100644 (file)
@@ -23,6 +23,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <libavutil/md5.h>
+
 #include "tvhead.h"
 #include "dispatch.h"
 #include "http.h"
 #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;
+
+  ctx = alloca(av_md5_size);
 
-  /* We need to keep a hidden element in a part of the document that
-     is directly mapped to this mailbox.
+  gettimeofday(&tv, NULL);
 
-     This element is updated in every reply and if it fails,
-     there will be no more updates.
+  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);
 
-     This avoid getting stale updaters that keeps on going if parts
-     of the document is reloaded faster than the mailbox sees it */
+  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;
 
-  tcp_qprintf(tq, "<div style=\"display: none\" id=\"mbox_%d\"></div>", boxid);
+  mbdebug("Generated mailbox %s\n", id);
 
-  ajax_js(tq, "new Ajax.Request('/ajax/mailbox/%d')", boxid);
+  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)
-    return 409;
+  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);
 
index 611ec7492024031e7c55ca6ac00e735dc2d9e948..7dcb6c1a140a39821b1a72baef8bacccac5f6025 100644 (file)
@@ -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;
 
index 306c5f7edfd0bc54a6030f412c5657b72792d93b..51b532bc090ad920671674b1fc8bbd5165d98f26 100644 (file)
@@ -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); }
+       })
+}
\ No newline at end of file