⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cache.c

📁 基于minigui的浏览器. 这是最新版本.
💻 C
📖 第 1 页 / 共 3 页
字号:
   return;}/* * Update cache clients for a single cache-entry * Tasks: *   - Set the client function (if not already set) *   - Look if new data is available and pass it to client functions *   - Remove clients when done *   - Call redirect handler * * todo: Implement CA_Abort Op in client callback */static void Cache_process_queue(CacheData_t *entry){   guint i;   gint st;   const gchar *Type;   CacheClient_t *Client;   DilloWeb *ClientWeb;   BrowserWindow *Client_bw = NULL;   static gboolean Busy = FALSE;   gboolean AbortEntry = FALSE;   gboolean OfferDownload = FALSE;   gboolean TypeMismatch = FALSE;   if ( Busy )      DEBUG_MSG(5, "FATAL!:*** >>>> Cache_process_queue Caught busy!!!\n");   if (!(entry->Flags & CA_GotHeader))      return;   if (!(entry->Flags & CA_GotContentType)) {      st = a_Misc_get_content_type_from_data(              entry->Data, entry->ValidSize, &Type);      if (st == 0 || entry->Flags & CA_GotData) {         if (a_Misc_content_type_check(entry->TypeHdr, Type) < 0) {            MSG_HTTP("Content-Type '%s' doesn't match the real data.\n",                     entry->TypeHdr);            TypeMismatch = TRUE;         }         entry->TypeDet = g_strdup(Type);         entry->Flags |= CA_GotContentType;      } else         return;  /* i.e., wait for more data */   }   Busy = TRUE;   for ( i = 0; (Client = g_slist_nth_data(ClientQueue, i)); ++i ) {      if ( Client->Url == entry->Url ) {         ClientWeb = Client->Web;    /* It was a (void*) */         Client_bw = ClientWeb->bw;  /* 'bw' in a local var */         if (ClientWeb->flags & WEB_RootUrl) {            if (!(entry->Flags & CA_MsgErased)) {               /* clear the "expecting for reply..." message */               a_Interface_msg(Client_bw, "");               entry->Flags |= CA_MsgErased;            }            if (TypeMismatch)               a_Interface_msg(Client_bw,"HTTP warning: Content-Type '%s' "                               "doesn't match the real data.", entry->TypeHdr);            if (entry->Flags & CA_Redirect) {               if (!Client->Callback) {                  Client->Callback = a_Cache_null_client;                  Client_bw->redirect_level++;               }            } else {               Client_bw->redirect_level = 0;            }         } else {            /* For non root URLs, ignore redirections and 404 answers */            if (entry->Flags & CA_Redirect || entry->Flags & CA_NotFound)               Client->Callback = a_Cache_null_client;         }         /* Set the client function */         if (!Client->Callback) {            if (TypeMismatch) {               AbortEntry = TRUE;               Client->Callback = a_Cache_null_client;            } else {               st = a_Web_dispatch_by_type(                       entry->TypeHdr ? entry->TypeHdr : entry->TypeDet,                       ClientWeb, &Client->Callback, &Client->CbData);               if (st == -1) {                  /* MIME type is not viewable */                  Client->Callback = a_Cache_null_client;                  if (ClientWeb->flags & WEB_RootUrl) {                     /* Unhandled MIME type, prepare a download offer... */                     AbortEntry = TRUE;                     OfferDownload = TRUE;                  } else {                     /* TODO: Resource Type not handled.                      * Not aborted to avoid multiple connections on the same                      * resource. A better idea is to abort the connection and                      * to keep a failed-resource flag in the cache entry. */                     MSG_HTTP("Unhandled MIME type: <%s>\n",                              entry->TypeHdr ? entry->TypeHdr:entry->TypeDet);                  }               }            }            if (AbortEntry) {               a_Interface_remove_client(Client_bw, Client->Key);               Cache_client_dequeue(Client, NULLKey);               --i; /* Keep the index value in the next iteration */               continue;            }         }         /* Send data to our client */         if ( (Client->BufSize = entry->ValidSize) > 0) {            Client->Buf = (guchar *)entry->Data;            (Client->Callback)(CA_Send, Client);         }         /* Remove client when done */         if ( (entry->Flags & CA_GotData) ) {            /* Copy flags to a local var */            gint flags = ClientWeb->flags;            /* We finished sending data, let the client know */            if (!Client->Callback)               DEBUG_MSG(3, "Client Callback is NULL");            else               (Client->Callback)(CA_Close, Client);            Cache_client_dequeue(Client, NULLKey);            --i; /* Keep the index value in the next iteration */            /* call Cache_redirect() from this 'if' to assert one call only. */            if ( entry->Flags & CA_Redirect )               Cache_redirect(entry, flags, Client_bw);            _MSG("Cache_process_queue: NumRootClients=%d sens_idle_id = %d\n",                 Client_bw->NumRootClients, Client_bw->sens_idle_id);         }      }   } /* for */   if (AbortEntry) {      /* Abort the entry, remove it from cache, and maybe offer download.       * (the dialog is made before 'entry' is freed) */      if (OfferDownload && Cache_download_enabled(entry->Url))         a_Interface_offer_link_download(Client_bw, entry->Url);      Cache_entry_remove(entry, NULL);   }   Busy = FALSE;   DEBUG_MSG(1, "QueueSize ====> %d\n", g_slist_length(ClientQueue));}/* * Callback function for Cache_delayed_process_queue. */static gint Cache_delayed_process_queue_callback(gpointer data){   gpointer entry;   while ((entry = g_slist_nth_data(DelayedQueue, 0))) {      Cache_process_queue( (CacheData_t *)entry );      /* note that if Cache_process_queue removes the entry,       * the following g_slist_remove has no effect. */      DelayedQueue = g_slist_remove(DelayedQueue, entry);   }   DelayedQueueIdleId = 0;   return FALSE;}/* * Set a call to Cache_process_queue from the gtk_main cycle. */static void Cache_delayed_process_queue(CacheData_t *entry){   /* there's no need to repeat entries in the queue */   if (!g_slist_find(DelayedQueue, entry))      DelayedQueue = g_slist_prepend(DelayedQueue, entry);   if (DelayedQueueIdleId == 0)      DelayedQueueIdleId =         gtk_idle_add((GtkFunction)Cache_delayed_process_queue_callback, NULL);}/* * Remove a cache client * todo: beware of downloads */static void Cache_remove_client_raw(CacheClient_t *Client, gint Key){   Cache_client_dequeue(Client, Key);}/* * Remove every Interface-client of a single Url. * todo: beware of downloads * (this is transitory code) */static void Cache_remove_interface_clients(const DilloUrl *Url){   guint i;   DilloWeb *Web;   CacheClient_t *Client;   for ( i = 0; (Client = g_slist_nth_data(ClientQueue, i)); ++i ) {      if ( Client->Url == Url ) {         Web = Client->Web;         a_Interface_remove_client(Web->bw, Client->Key);      }   }}/* * Remove a client from the client queue * todo: notify the dicache and upper layers */static void Cache_stop_client(gint Key, gint force){   CacheClient_t *Client;   CacheData_t *entry;   GSList *List;   DilloUrl *url;   if (!(List = g_slist_find_custom(ClientQueue, GINT_TO_POINTER(Key),                                    Cache_client_key_cmp))){      _MSG("WARNING: Cache_stop_client, inexistent client\n");      return;   }   Client = List->data;   url = (DilloUrl *)Client->Url;   Cache_remove_client_raw(Client, NULLKey);   if (force &&       !g_slist_find_custom(ClientQueue, url, Cache_client_url_cmp)) {      /* it was the last client of this entry */      if ((entry = Cache_entry_search(url))) {         if (entry->CCCQuery) {            a_Cache_ccc(OpAbort, 1, BCK, entry->CCCQuery, NULL, NULL);         } else if (entry->CCCAnswer) {            a_Cache_ccc(OpStop, 2, BCK, entry->CCCAnswer, NULL, Client);         }      }   }}/* * Remove a client from the client queue * (It may keep feeding the cache, but nothing else) */void a_Cache_stop_client(gint Key){   Cache_stop_client(Key, 0);}/* * CCC function for the CACHE module */void a_Cache_ccc(int Op, int Branch, int Dir, ChainLink *Info,                 void *Data1, void *Data2){   CacheData_t *entry;   a_Chain_debug_msg("a_Cache_ccc", Op, Branch, Dir);   if ( Branch == 1 ) {      if (Dir == BCK) {         /* Querying branch */         switch (Op) {         case OpStart:            /* Localkey = entry->Url */            Info->LocalKey = Data2;            break;         case OpStop:            break;         case OpAbort:            Cache_entry_remove_raw(NULL, Info->LocalKey);            a_Chain_bcb(OpAbort, Info, NULL, NULL);            g_free(Info);            break;         }      } else {  /* FWD */         switch (Op) {         case OpSend:            /* Start the answer-reading chain */            a_Cache_ccc(OpStart, 2, BCK, a_Chain_new(), Data1, Info->LocalKey);            break;         case OpEnd:            /* unlink HTTP_Info */            a_Chain_del_link(Info, BCK);            /* 'entry->CCCQuery' and 'Info' point to the same place! */            if ((entry = Cache_entry_search(Info->LocalKey)) != NULL)               entry->CCCQuery = NULL;            g_free(Info);            break;         case OpAbort:            /* Unlink HTTP_Info */            a_Chain_del_link(Info, BCK);            /* remove interface client-references of this entry */            Cache_remove_interface_clients(Info->LocalKey);            /* remove clients of this entry */            Cache_stop_clients(Info->LocalKey, 0);            /* remove the entry */            Cache_entry_remove_raw(NULL, Info->LocalKey);            g_free(Info);            break;         }      }   } else if (Branch == 2) {      if (Dir == FWD) {         /* Answering branch */         switch (Op) {         case OpStart:            /* Data2 = entry->Url */            Info->LocalKey = Data2;            if ((entry = Cache_entry_search(Info->LocalKey))) {               entry->CCCAnswer = Info;            } else {               /* The cache-entry was removed */               a_Chain_bcb(OpAbort, Info, NULL, NULL);               g_free(Info);            }            break;         case OpSend:            /* Send data */            if ((entry = Cache_entry_search(Info->LocalKey))) {               Cache_process_io(IORead, Data1);            } else {               a_Chain_bcb(OpAbort, Info, NULL, NULL);               g_free(Info);            }            break;         case OpEnd:            /* Unlink HTTP_Info */            a_Chain_del_link(Info, BCK);            g_free(Info);            Cache_process_io(IOClose, Data1);            break;         case OpAbort:            a_Chain_del_link(Info, BCK);            g_free(Info);            Cache_process_io(IOAbort, Data1);            break;         }      } else {  /* BCK */         switch (Op) {         case OpStart:            {            IOData_t *io2;            Info->LocalKey = Data2;            if ((entry = Cache_entry_search(Data2)))    /* Is Data2 valid? */               entry->CCCAnswer = Info;            /* Link IO to receive the answer */            io2 = a_IO_new(IORead, *(int*)Data1);            a_IO_set_buf(io2, NULL, IOBufLen);            io2->ExtData = Data2;       /* We have it as LocalKey */            a_Chain_link_new(Info, a_Cache_ccc, BCK, a_IO_ccc, 2, 2);            a_Chain_bcb(OpStart, Info, io2, NULL);            break;            }         case OpStop:            MSG(" Not implemented\n");            break;         case OpAbort:            Cache_entry_remove_raw(NULL, Info->LocalKey);            a_Chain_bcb(OpAbort, Info, NULL, NULL);            g_free(Info);            break;         }      }   }}static gbooleanCache_remove_hash_entry(gpointer key, gpointer value, gpointer user_data){   Cache_entry_free((CacheData_t *)value);   return TRUE;}/* * Memory deallocator (only called at exit time) */void a_Cache_freeall(void){   CacheClient_t *Client;   /* free the client queue */   while ( (Client = g_slist_nth_data(ClientQueue, 0)) )      Cache_client_dequeue(Client, NULLKey);   /* free the main cache */   /* Remove every cache entry */   g_hash_table_foreach_remove(CacheHash, (GHRFunc)Cache_remove_hash_entry,                               NULL);   /* Remove the cache hash */   g_hash_table_destroy(CacheHash);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -