📄 ssl_scache_shmcb.c
字号:
}#if 0 /* Unused so far */static unsigned long shmcb_get_safe_ulong(unsigned long *ptr){ unsigned long ret; shmcb_set_safe_ulong_ex((unsigned char *)(&ret), (const unsigned char *)ptr); return ret;}static void shmcb_set_safe_ulong_ex(unsigned char *dest, const unsigned char *src){ memcpy(dest, src, sizeof(unsigned long));}#endifstatic time_t shmcb_get_safe_time(time_t * ptr){ time_t ret; shmcb_set_safe_time_ex((unsigned char *)(&ret), (const unsigned char *)ptr); return ret;}static void shmcb_set_safe_time_ex(unsigned char *dest, const unsigned char *src){ memcpy(dest, src, sizeof(time_t));}/***** High-Level "handlers" as per ssl_scache.c***/static void *shmcb_malloc(size_t size){ SSLModConfigRec *mc = myModConfig(); return ap_mm_malloc(mc->pSessionCacheDataMM, size);}void ssl_scache_shmcb_init(server_rec *s, pool *p){ SSLModConfigRec *mc = myModConfig(); AP_MM *mm; void *shm_segment = NULL; int avail, avail_orig; /* * Create shared memory segment */ if (mc->szSessionCacheDataFile == NULL) { ssl_log(s, SSL_LOG_ERROR, "SSLSessionCache required"); ssl_die(); } if ((mm = ap_mm_create(mc->nSessionCacheDataSize, mc->szSessionCacheDataFile)) == NULL) { ssl_log(s, SSL_LOG_ERROR, "Cannot allocate shared memory: %s", ap_mm_error()); ssl_die(); } mc->pSessionCacheDataMM = mm; /* * Make sure the child processes have access to the underlying files */ ap_mm_permission(mm, SSL_MM_FILE_MODE, ap_user_id, -1); /* * Create cache inside the shared memory segment */ avail = avail_orig = ap_mm_available(mm); ssl_log(s, SSL_LOG_TRACE, "Shared-memory segment has %u available", avail); /* * For some reason to do with MM's internal management, I can't * allocate the full amount. Implement a reasonable form of trial * and error and output trace information. */ while ((shm_segment == NULL) && ((avail_orig - avail) * 100 < avail_orig)) { shm_segment = shmcb_malloc(avail); if (shm_segment == NULL) { ssl_log(s, SSL_LOG_TRACE, "shmcb_malloc attempt for %u bytes failed", avail); avail -= 2; } } if (shm_segment == NULL) { ssl_log(s, SSL_LOG_ERROR, "Cannot allocate memory for the 'shmcb' session cache\n"); ssl_die(); } ssl_log(s, SSL_LOG_TRACE, "shmcb_init allocated %u bytes of shared " "memory", avail); if (!shmcb_init_memory(s, shm_segment, avail)) { ssl_log(s, SSL_LOG_ERROR, "Failure initialising 'shmcb' shared memory"); ssl_die(); } ssl_log(s, SSL_LOG_INFO, "Shared memory session cache initialised"); /* * Success ... we hack the memory block into place by cheating for * now and stealing a member variable the original shared memory * cache was using. :-) */ mc->tSessionCacheDataTable = (table_t *) shm_segment; return;}void ssl_scache_shmcb_kill(server_rec *s){ SSLModConfigRec *mc = myModConfig(); if (mc->pSessionCacheDataMM != NULL) { ap_mm_destroy(mc->pSessionCacheDataMM); mc->pSessionCacheDataMM = NULL; } return;}BOOL ssl_scache_shmcb_store(server_rec *s, UCHAR *id, int idlen, time_t timeout, SSL_SESSION * pSession){ SSLModConfigRec *mc = myModConfig(); void *shm_segment; BOOL to_return = FALSE; /* We've kludged our pointer into the other cache's member variable. */ shm_segment = (void *) mc->tSessionCacheDataTable; ssl_mutex_on(s); if (!shmcb_store_session(s, shm_segment, id, idlen, pSession, timeout)) /* in this cache engine, "stores" should never fail. */ ssl_log(s, SSL_LOG_ERROR, "'shmcb' code was unable to store a " "session in the cache."); else { ssl_log(s, SSL_LOG_TRACE, "shmcb_store successful"); to_return = TRUE; } ssl_mutex_off(s); return to_return;}SSL_SESSION *ssl_scache_shmcb_retrieve(server_rec *s, UCHAR *id, int idlen){ SSLModConfigRec *mc = myModConfig(); void *shm_segment; SSL_SESSION *pSession; /* We've kludged our pointer into the other cache's member variable. */ shm_segment = (void *) mc->tSessionCacheDataTable; ssl_mutex_on(s); pSession = shmcb_retrieve_session(s, shm_segment, id, idlen); ssl_mutex_off(s); if (pSession) ssl_log(s, SSL_LOG_TRACE, "shmcb_retrieve had a hit"); else { ssl_log(s, SSL_LOG_TRACE, "shmcb_retrieve had a miss"); ssl_log(s, SSL_LOG_INFO, "Client requested a 'session-resume' but " "we have no such session."); } return pSession;}void ssl_scache_shmcb_remove(server_rec *s, UCHAR *id, int idlen){ SSLModConfigRec *mc = myModConfig(); void *shm_segment; /* We've kludged our pointer into the other cache's member variable. */ shm_segment = (void *) mc->tSessionCacheDataTable; ssl_mutex_on(s); shmcb_remove_session(s, shm_segment, id, idlen); ssl_mutex_off(s);}void ssl_scache_shmcb_expire(server_rec *s){ /* NOP */ return;}void ssl_scache_shmcb_status(server_rec *s, pool *p, void (*func) (char *, void *), void *arg){ SSLModConfigRec *mc = myModConfig(); SHMCBHeader *header; SHMCBQueue queue; SHMCBCache cache; SHMCBIndex *idx; void *shm_segment; unsigned int loop, total, cache_total, non_empty_divisions; int index_pct, cache_pct; double expiry_total; time_t average_expiry, now, max_expiry, min_expiry, idxexpiry; ssl_log(s, SSL_LOG_TRACE, "inside ssl_scache_shmcb_status"); /* We've kludged our pointer into the other cache's member variable. */ shm_segment = (void *) mc->tSessionCacheDataTable; /* Get the header structure. */ shmcb_get_header(shm_segment, &header); total = cache_total = non_empty_divisions = 0; average_expiry = max_expiry = min_expiry = 0; expiry_total = 0; /* It may seem strange to grab "now" at this point, but in theory * we should never have a negative threshold but grabbing "now" after * the loop (which performs expiries) could allow that chance. */ now = time(NULL); for (loop = 0; loop <= header->division_mask; loop++) { if (shmcb_get_division(header, &queue, &cache, loop)) { shmcb_expire_division(s, &queue, &cache); total += shmcb_get_safe_uint(queue.pos_count); cache_total += shmcb_get_safe_uint(cache.pos_count); if (shmcb_get_safe_uint(queue.pos_count) > 0) { idx = shmcb_get_index(&queue, shmcb_get_safe_uint(queue.first_pos)); non_empty_divisions++; idxexpiry = shmcb_get_safe_time(&(idx->expires)); expiry_total += (double) idxexpiry; max_expiry = (idxexpiry > max_expiry ? idxexpiry : max_expiry); if (min_expiry == 0) min_expiry = idxexpiry; else min_expiry = (idxexpiry < min_expiry ? idxexpiry : min_expiry); } } } index_pct = (100 * total) / (header->index_num * (header->division_mask + 1)); cache_pct = (100 * cache_total) / (header->cache_data_size * (header->division_mask + 1)); func(ap_psprintf(p, "cache type: <b>SHMCB</b>, shared memory: <b>%d</b> " "bytes, current sessions: <b>%d</b><br>", mc->nSessionCacheDataSize, total), arg); func(ap_psprintf(p, "sub-caches: <b>%d</b>, indexes per sub-cache: " "<b>%d</b><br>", (int) header->division_mask + 1, (int) header->index_num), arg); if (non_empty_divisions != 0) { average_expiry = (time_t)(expiry_total / (double)non_empty_divisions); func(ap_psprintf(p, "time left on oldest entries' SSL sessions: "), arg); if (now < average_expiry) func(ap_psprintf(p, "avg: <b>%d</b> seconds, (range: %d...%d)<br>", (int)(average_expiry - now), (int) (min_expiry - now), (int)(max_expiry - now)), arg); else func(ap_psprintf(p, "expiry threshold: <b>Calculation Error!</b>" "<br>"), arg); } func(ap_psprintf(p, "index usage: <b>%d%%</b>, cache usage: <b>%d%%</b>" "<br>", index_pct, cache_pct), arg); func(ap_psprintf(p, "total sessions stored since starting: <b>%lu</b><br>", header->num_stores), arg); func(ap_psprintf(p, "total sessions expired since starting: <b>%lu</b><br>", header->num_expiries), arg); func(ap_psprintf(p, "total (pre-expiry) sessions scrolled out of the " "cache: <b>%lu</b><br>", header->num_scrolled), arg); func(ap_psprintf(p, "total retrieves since starting: <b>%lu</b> hit, " "<b>%lu</b> miss<br>", header->num_retrieves_hit, header->num_retrieves_miss), arg); func(ap_psprintf(p, "total removes since starting: <b>%lu</b> hit, " "<b>%lu</b> miss<br>", header->num_removes_hit, header->num_removes_miss), arg); ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_status"); return;}/***** Memory manipulation and low-level cache operations ***/static BOOL shmcb_init_memory( server_rec *s, void *shm_mem, unsigned int shm_mem_size){ SHMCBHeader *header; SHMCBQueue queue; SHMCBCache cache; unsigned int temp, loop, granularity; ssl_log(s, SSL_LOG_TRACE, "entered shmcb_init_memory()"); /* Calculate some sizes... */ temp = sizeof(SHMCBHeader); /* If the segment is ridiculously too small, bail out */ if (shm_mem_size < (2*temp)) { ssl_log(s, SSL_LOG_ERROR, "shared memory segment too small"); return FALSE; } /* Make temp the amount of memory without the header */ temp = shm_mem_size - temp; /* Work on the basis that you need 10 bytes index for each session * (approx 150 bytes), which is to divide temp by 160 - and then * make sure we err on having too index space to burn even when * the cache is full, which is a lot less stupid than having * having not enough index space to utilise the whole cache!. */ temp /= 120; ssl_log(s, SSL_LOG_TRACE, "for %u bytes, recommending %u indexes", shm_mem_size, temp); /* We should divide these indexes evenly amongst the queues. Try * to get it so that there are roughly half the number of divisions * as there are indexes in each division. */ granularity = 256; while ((temp / granularity) < (2 * granularity)) granularity /= 2; /* So we have 'granularity' divisions, set 'temp' equal to the * number of indexes in each division. */ temp /= granularity; /* Too small? Bail ... */ if (temp < 5) { ssl_log(s, SSL_LOG_ERROR, "shared memory segment too small"); return FALSE; } /* OK, we're sorted - from here on in, the return should be TRUE */ header = (SHMCBHeader *)shm_mem; header->division_mask = (unsigned char)(granularity - 1); header->division_offset = sizeof(SHMCBHeader); header->index_num = temp; header->index_offset = (2 * sizeof(unsigned int)); header->index_size = sizeof(SHMCBIndex); header->queue_size = header->index_offset + (header->index_num * header->index_size); /* Now calculate the space for each division */ temp = shm_mem_size - header->division_offset; header->division_size = temp / granularity;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -