📄 cache.c
字号:
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 + -