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

📄 cache.c

📁 嵌入式浏览器Dillo源码
💻 C
📖 第 1 页 / 共 3 页
字号:
      if ( entry->Flags & CA_GotHeader ) {         /* Let's scan, allocate, and set things according to header info */         Cache_parse_header(entry, io, len);         /* Now that we have it parsed, let's update our clients */         Cache_process_queue(entry);      }      return;   }   Status = io->Status;   entry->ValidSize += Status;   if ( Status < (gint)io->IOVec.iov_len ) {      /* An incomplete buffer; update buffer & size */      io->IOVec.iov_len  -= Status;      io->IOVec.iov_base = (char *)io->IOVec.iov_base + Status;   } else if ( Status == (gint)io->IOVec.iov_len ) {      /* A full buffer! */      if ( !entry->TotalSize ) {         /* We are receiving in small chunks... */         entry->Data = g_realloc(entry->Data,entry->ValidSize+entry->BuffSize);         io->IOVec.iov_base = (char *)entry->Data + entry->ValidSize;         io->IOVec.iov_len  = entry->BuffSize;      } else {         /* We have a preallocated buffer! */         io->IOVec.iov_len  -= Status;         io->IOVec.iov_base = (char *)io->IOVec.iov_base + Status;      }   }   Cache_process_queue(entry);}/* * Process redirections (HTTP 30x answers) * (This is a work in progress --not finished yet) */static gint Cache_redirect(CacheData_t *entry, gint Flags, BrowserWindow *bw){   DilloUrl *NewUrl;   /* if there's a redirect loop, stop now */   if (entry->Flags & CA_RedirectLoop) {     a_Interface_msg(bw, "ERROR: redirect loop for: %s", URL_STR_(entry->Url));     return 0;   }   if ( ((entry->Flags & CA_Redirect) && entry->Location) &&        ((entry->Flags & CA_ForceRedirect) || !entry->ValidSize ||         entry->ValidSize < 1024 ) ) {      DEBUG_MSG(3, ">>>Redirect from: %s\n to %s\n",              URL_STR_(entry->Url), URL_STR_(entry->Location));      DEBUG_MSG(3,"%s", entry->Header->str);      if ( Flags & WEB_RootUrl ) {         /* Redirection of the main page */         a_Nav_remove_top_url(bw);         NewUrl =a_Url_new(URL_STR_(entry->Location),URL_STR_(entry->Url),0,0);         a_Nav_push(bw, NewUrl);         a_Url_free(NewUrl);      } else {         /* Sub entity redirection (most probably an image) */         if ( !entry->ValidSize ) {            DEBUG_MSG(3,">>>Image redirection without entity-content<<<\n");         } else {            DEBUG_MSG(3, ">>>Image redirection with entity-content<<<\n");         }      }   }   return 0;}/* * Do nothing, but let the cache fill the entry. * (Currently used to ignore image redirects  --Jcid) */void a_Cache_null_client(int Op, CacheClient_t *Client){ 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){   gint i;   CacheClient_t *Client;   DilloWeb *ClientWeb;   static gboolean Busy = FALSE;   gboolean EntryHasClients = FALSE;   const DilloUrl *Url = entry->Url;   if ( Busy )      DEBUG_MSG(5, "FATAL!:*** >>>> Cache_process_queue Caught busy!!!\n");   Busy = TRUE;   if ( !(entry->Flags & CA_GotHeader) ) {      Busy = FALSE;      return;   }   for ( i = 0; (Client = g_slist_nth_data(ClientQueue, i)); ++i ) {      if ( Client->Url == Url ) {         EntryHasClients = TRUE;         ClientWeb = Client->Web; /* It was a (void*) */         /* For root URLs, clear the "expecting for reply..." message */         if (ClientWeb->flags & WEB_RootUrl && !(entry->Flags & CA_MsgErased)){            a_Interface_msg(ClientWeb->bw, "");            entry->Flags |= CA_MsgErased;         }         /* For non root URLs, ignore redirections and 404 answers */         if ( !(ClientWeb->flags & WEB_RootUrl) &&              (entry->Flags & CA_Redirect || entry->Flags & CA_NotFound) )            Client->Callback = a_Cache_null_client;         /* Set client function */         if ( !Client->Callback )            a_Web_dispatch_by_type(entry->Type, ClientWeb,                                   &Client->Callback, &Client->CbData);         /* 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 Client data to local vars */            void *bw = ClientWeb->bw;            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 */            if ( entry->Flags & CA_Redirect )               Cache_redirect(entry, flags, bw);         }      }   } /* for */   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){   Cache_process_queue( (CacheData_t *)data );   return FALSE;}/* * Call Cache_process_queue from the gtk_main cycle */static void Cache_delayed_process_queue(CacheData_t *entry){   gtk_idle_add((GtkFunction)Cache_delayed_process_queue_callback, entry);}/* * 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){   gint 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))){      DEBUG_MSG(5, "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, entry->CCCQuery, NULL, NULL);         } else if (entry->CCCAnswer) {            a_Cache_ccc(OpStop, -1, 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, ChainLink *Info, void *Data, void *ExtraData){   CacheData_t *entry;   if ( Branch == 1 ) {      /* Querying branch */      switch (Op) {      case OpStart:         DEBUG_MSG(3, "Cache CCC (OpStart) [0]");         Info->LocalKey = ExtraData;         break;      case OpEnd:         /* unlink HTTP_Info */         a_Chain_del_link(Info, CCC_BCK);         /* 'entry->CCCQuery' and 'Info' point to the same place! */         if ((entry = Cache_entry_search(Info->LocalKey)) != NULL)            entry->CCCQuery = NULL;         g_free(Info);         DEBUG_MSG(3, "Cache CCC (OpEnd) [0]\n");         break;      case OpAbort:         /* Unlink HTTP_Info */         a_Chain_del_link(Info, CCC_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);         DEBUG_MSG(3, "Cache CCC (OpAbort) [0]\n");         break;      }   } else if (Branch == 2) {      /* Answering branch */      switch (Op) {      case OpStart:         Info->LocalKey = ExtraData;         if ((entry = Cache_entry_search(Info->LocalKey))) {            entry->CCCAnswer = Info;         } else {            /* The cache-entry was removed */            a_Chain_bcb(OpAbort, -1, Info, NULL, NULL);            g_free(Info);         }         break;      case OpSend:         /* Send data */         if ((entry = Cache_entry_search(Info->LocalKey))) {            Cache_process_io(IORead, Data);         } else {            a_Chain_bcb(OpAbort, -1, Info, NULL, NULL);            g_free(Info);         }         break;      case OpEnd:         /* Unlink HTTP_Info */         a_Chain_del_link(Info, CCC_BCK);         g_free(Info);         Cache_process_io(IOClose, Data);         DEBUG_MSG(3, "Cache CCC (OpEnd) [1]\n");         break;      case OpAbort:         a_Chain_del_link(Info, CCC_BCK);         g_free(Info);         Cache_process_io(IOAbort, Data);         DEBUG_MSG(3, "Cache CCC (OpAbort) [1]\n");         break;      }   } else if (Branch == -1) {      /* Backwards operations */      switch (Op) {      case OpStop:         /* We'll let it fill the entry by now... */         /* a_Chain_bcb(OpStop, -1, Info, NULL, NULL);            g_free(Info); */         break;      case OpAbort:         DEBUG_MSG(2, "Cache: OpAbort [-1]\n");         Cache_entry_remove_raw(NULL, Info->LocalKey);         a_Chain_bcb(OpAbort, -1, 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 + -