// ML : cache * string -> string_ptr String apsml_cacheGet (Region rAddr, cache *c, String key1, request_data *rd) /*{{{ */ { // ap_log_error(APLOG_MARK, LOG_DEBUG, 0, rd->server, "apsml_cacheGet 1"); // ppCache (c, rd); // keyNhash kn; char *key = &(key1->data); // kn.hash = charhashfunction (kn.key); // ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheGet: key == %s, hash: %i", kn.key, kn.hash); int too_old = 0; apr_thread_rwlock_rdlock (c->rwlock); apr_proc_mutex_lock(rd->ctx->cachelock.plock); unsigned long cachehash = c->hashofname % rd->ctx->cachelock.shmsize; unsigned long cacheversion = rd->ctx->cachelock.version[cachehash]; apr_proc_mutex_unlock(rd->ctx->cachelock.plock); // ap_log_error(APLOG_MARK, LOG_DEBUG, 0, rd->server, // "apsml_cacheGet global version: %d, local version %d", cacheversion, c->version); if (cacheversion != c->version) { apr_thread_rwlock_unlock (c->rwlock); apsml_cacheFlush(c, rd, 0); c->version = cacheversion; return (String) NULL; } entry *entry; // void **entry1 = (void **) &entry; if (entrytable_find (c->htable, key, &entry) == hash_DNE) { entry = NULL; // ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheGet: No such thing"); } if (entry) { // we found an entry // which should be put on top of the list // We require locking on the list // If time is too old then drop the entry time_t ct = time (NULL); apr_thread_mutex_lock (c->mutex); LINKEDLIST_REMOVE (entry); //time_t t = ct < entry->time ? 0 : ct - entry->time; if (entry->timeout) { if (ct > entry->time) { // entry too old too_old = 1; /* ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheGet: Entry too old, ct == %ld, entry->time == %ld", ct, entry->time); */ LINKEDLIST_INSERTOVER (c->sentinel, entry); } else { // keep entry fresh LINKEDLIST_INSERTUNDER (c->sentinel, entry); // ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheGet: Entry fine ct == %i, entry->time == %i", // ct, entry->time); cacheheap_heapchangekey(c->heap, entry->heappos, MAX (ct + entry->timeout, entry->time)); //entry->time = MAX (ct + entry->timeout, entry->time); } } else { LINKEDLIST_INSERTUNDER (c->sentinel, entry); } // ap_log_rerror(APLOG_MARK, LOG_NOTICE, 0, rd->request, "apsml_cacheGetFound: etime: %d, rtime: %d, too_old: %i key: %s, value %d, valuedata: %s", entry->time, time(NULL), too_old, key, entry, entry->data); apr_thread_mutex_unlock (c->mutex); } String s; if (too_old == 0 && entry) { s = convertStringToML (rAddr, entry->data); } else { s = (String) NULL; } apr_thread_rwlock_unlock (c->rwlock); // ap_log_rerror(APLOG_MARK, LOG_NOTICE, 0, rd->request, "apsml_cacheGet: Returning"); return s; } /*}}} */
// ML: cache * String * String -> (int * string_ptr) int apsml_cacheSet (int resultPair, Region sAddr, cache * c, int keyValPair, request_data * rd) /*{{{ */ { // allocate new entry and key,value placeholders // ppCache(c, rd); String key1 = (String) elemRecordML (keyValPair, 0); String value1 = (String) elemRecordML (keyValPair, 1); time_t timeout = (time_t) elemRecordML (keyValPair, 2); char *value = &(value1->data); int valuesize = sizeStringDefine(value1); char *key = &(key1->data); int keysize = sizeStringDefine(key1); int size = sizeof (entry) + keysize + 1 + valuesize + 1; entry *newentry = (entry *) malloc (size); // ap_log_error (APLOG_MARK, LOG_DEBUG, 0, rd->server, // "apsml_cacheCreate: malloc 0x%x, length: %d, sizeof(entry): %d, keysize: %d, valuesize: %d, key: %s, val: %s", (unsigned long) newentry, size, sizeof(entry), keysize, valuesize, key, value); if (newentry == NULL) return 0; char *newkey = (char *) (newentry + 1); char *newvalue = newkey + (keysize + 1); // prepare entry by copy data to my space and set pointers strncpy (newkey, key, keysize); newkey[keysize] = 0; strncpy (newvalue, value, valuesize); newvalue[valuesize] = 0; newentry->key = newkey; // newentry->key.hash = charhashfunction (newkey); newentry->data = newvalue; newentry->size = keysize + valuesize + sizeof (entry) + 2; time_t ct = time (NULL); if (timeout && c->timeout) { newentry->timeout = MIN (timeout, c->timeout); } else if (timeout) { newentry->timeout = timeout; } else { newentry->timeout = c->timeout; } newentry->time = ct + newentry->timeout; // We are going in !!! (as we get a writes lock we have // complete control [no more locks]) apr_thread_rwlock_wrlock (c->rwlock); int tmpsize = c->htable->hashTableSize; entry *oldentry = NULL; // void **oldentry1 = (void **) &oldentry; // ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheSet: key %s, hash: %i", key, newentry->key.hash); if (entrytable_find (c->htable, newentry->key, &oldentry) == hash_DNE) { // No old entry with that key if ((newentry->timeout == -1 && cacheheap_heapinsert(c->heap, newentry, (time_t) 0) == heap_OUTOFMEM) || (newentry->timeout && newentry->timeout != (time_t) -1 && cacheheap_heapinsert(c->heap, newentry, newentry->time) == heap_OUTOFMEM)) { ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheSet: pid %d, received heap_OUTOFMEM", rd->ctx->pid); free(newentry); newentry = 0; } if (newentry && entrytable_insert (c->htable, newentry->key, newentry) == hash_OUTOFMEM) { ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheSet: pid %d, received hash_OUTOFMEM", rd->ctx->pid); free (newentry); newentry = 0; } // ppCache(c, rd); oldentry = 0; } else { // Old exists if ((newentry->timeout == (time_t) -1 && cacheheap_heapinsert(c->heap, newentry, (time_t) 0) == heap_OUTOFMEM) || (newentry->timeout && newentry->timeout != (time_t) -1 && cacheheap_heapinsert(c->heap, newentry, newentry->time) == heap_OUTOFMEM)) { ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheSet: pid %d, received heap_OUTOFMEM", rd->ctx->pid); free(newentry); newentry = 0; } if (newentry && entrytable_update (c->htable, newentry->key, newentry) == hash_OUTOFMEM) { ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheSet: pid %d, received hash_OUTOFMEM", rd->ctx->pid); free (newentry); newentry = 0; } } if (newentry) { c->size += newentry->size; c->size += (tmpsize - c->htable->hashTableSize) * sizeof (entrytable_hashelement_t); } // ppCache(c, rd); int too_old = 0; if (oldentry) { // Old entry needs removel // time_t t = (ct - oldentry->time) < 0 ? 0 : ct - oldentry->time; if (oldentry->timeout && ct > oldentry->time) { too_old = 1; second (resultPair) = 0; } else { second (resultPair) = (int) convertStringToML (sAddr, oldentry->data); } listremoveitem (c, oldentry, rd); } if (too_old) oldentry = 0; if (newentry) LINKEDLIST_INSERTUNDER (c->sentinel, newentry); // I think we are done now // ppCache(c, rd); entry *curentry; // ap_log_error(APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheSet: size %d, maxsize = %d, ct: %d", c->size, c->maxsize, ct); while (cacheheap_heapminimal(c->heap, &curentry) != heap_UNDERFLOW) { if (curentry->time < ct) { cacheremoveitem(c, curentry, rd); } else break; } // ppCache(c, rd); if (c->maxsize != -1) { while (c->size > c->maxsize) { curentry = c->sentinel->up; if (curentry == c->sentinel) break; cacheremoveitem (c, curentry, rd); } } apr_thread_rwlock_unlock (c->rwlock); // ppCache(c, rd); if (oldentry && newentry) { first (resultPair) = 1; return resultPair; } second (resultPair) = 0; if (newentry) { first (resultPair) = 2; return resultPair; } first (resultPair) = 0; return resultPair; } /*}}} */
static uintptr_t * apdns_getFQDN_MX_1 (Region rAddrLPairs, Region rAddrEPairs, Region rAddrString, char *str, uintptr_t *list, int depth, request_data *rd) { if (depth < 0) return list; // i,j are used as loop counters // the dnspackage returned from the resolver is scanned from top to buttom // next is the package pointer relative to the start of the package int j, next; char ans[NS_PACKETSZ + 1]; char dnsnamesa[NS_MAXDNAME]; char *dnsnames = dnsnamesa; char *input = str; uintptr_t *pair, *listpair; String rs; dnshead *head = (dnshead *) ans; // get the dns package int n = res_search (input, C_IN, T_MX, (unsigned char *) ans, NS_PACKETSZ + 1); input = 0; if (n == -1) return list; if (n < sizeof (dnshead)) return list; ntohhead (ans, head); if ((head->flags & 0xF) != 0) return list; if (head->anscount < 1) return list; // skip questions next = NS_HFIXEDSZ; for (j = 0; j < head->questcount; j++) { next = skipname (ans, next, n); next = iflessthan (next + 4, n); if (next < 0) return list; } // The answers int rv; for (j = 0; j < head->anscount; j++) { // int a_name = next; if (next >= n) return list; next = skipname (ans, next, n); if (next + NS_RRFIXEDSZ >= n || next < 0) return list; uint16_t a_type = twocharto16 (ans[next], ans[next + 1]); next += 4; uint32_t a_ttl = fourcharto32 (ans[next], ans[next + 1], ans[next + 2], ans[next + 3]); next += 4; uint16_t a_rdlength = twocharto16 (ans[next], ans[next + 1]); next += 2; if (a_type == T_MX) { // We got a mx record if (next + a_rdlength >= n || a_rdlength < 3) return list; uint16_t a_mx_pref = twocharto16 (ans[next], ans[next + 1]); rv = dumpname (dnsnames, NS_MAXDNAME, ans, next + 2, n); rs = convertStringToML (rAddrString, dnsnames); allocRecordML (rAddrEPairs, 3, pair); elemRecordML (pair, 0) = (uintptr_t) a_mx_pref; elemRecordML (pair, 1) = (uintptr_t) a_ttl; elemRecordML (pair, 2) = (uintptr_t) rs; allocRecordML (rAddrLPairs, 2, listpair); first (listpair) = (uintptr_t) pair; second (listpair) = (uintptr_t) list; makeCONS (listpair, list); ap_log_error (APLOG_MARK, LOG_DEBUG, 0, rd->server, "apdns_getFQDN_MX: pref %i, ttl %i, %s", a_mx_pref, a_ttl, dnsnames); } else if (a_type == T_CNAME) { // we got an alias (cononical name) rv = dumpname (dnsnames, NS_MAXDNAME, ans, next, n); input = dnsnames; break; } else { // we got something we did not ask for // or cannot handle at the momnet return list; } next += a_rdlength; } if (input) return apdns_getFQDN_MX_1 (rAddrLPairs, rAddrEPairs, rAddrString, input, list, depth - 1, rd); return list; }