static inline void *__mtype_new_list( MTYPE *mt, int count ) { MTBLANK *top, *end; uint32_t c, i; if( count <= 0 ) return NULL; c = (uint32_t) count; lock_mem( mt ); // get enough while( mt->fcount < c ) __mtype_alloc_free( mt, 0 ); top = end = mt->flist; // run down count - 1 elements for( i = c - 1; i > 0; i-- ) end = end->next; // end is now the last in the list we want mt->flist = end->next; mt->fcount -= c; unlock_mem( mt ); end->next = NULL; return (void *) top; }
static inline void __mtype_free_list( MTYPE *mt, int count, void *first, void *last ) { MTBLANK *l = (MTBLANK *) last; lock_mem( mt ); l->next = mt->flist; mt->flist = first; mt->fcount += count; unlock_mem( mt ); }
static inline void __mtype_free( MTYPE *mt, void *p ) { MTBLANK *b = (MTBLANK *) p; lock_mem( mt ); b->next = mt->flist; mt->flist = p; ++(mt->fcount); unlock_mem( mt ); }
static inline void *__mtype_new( MTYPE *mt ) { MTBLANK *b; lock_mem( mt ); if( !mt->fcount ) __mtype_alloc_free( mt, 0 ); b = mt->flist; mt->flist = b->next; --(mt->fcount); unlock_mem( mt ); b->next = NULL; return (void *) b; }
IOBUF *stats_report_mtype( char *name, MTYPE *mt, time_t ts, IOBUF *b ) { char *prfx = ctl->stats->self->prefix; uint32_t freec, alloc; uint64_t bytes; // grab some stats under lock // we CANNOT bprintf under lock because // one of the reported types is buffers lock_mem( mt ); bytes = (uint64_t) mt->alloc_sz * (uint64_t) mt->total; alloc = mt->total; freec = mt->fcount; unlock_mem( mt ); // and report them bprintf( "mem.%s.free %u", name, freec ); bprintf( "mem.%s.alloc %u", name, alloc ); bprintf( "mem.%s.kb %lu", name, bytes / 1024 ); return b; }
void main_loop(std::vector<std::string> * hosts, char *bytes_file, char show_bps, std::string username, std::string password, const char *cdevice) { int n_to_do, bits_out=0, loop; char *dummy; static short psl=0, psr=0; /* previous samples */ static char a=1; /* alternater */ unsigned char byte_out=0; int input_buffer_size; char *input_buffer; snd_pcm_t *chandle; snd_pcm_format_t format; int err; unsigned char bytes[4096]; // 4096 * 8: 9992, must be less then 9999 int bytes_out = 0; char server_type[128]; snprintf(server_type, sizeof server_type, "eb_server_audio v" VERSION " %s", cdevice); protocol *p = NULL; if (!hosts -> empty()) p = new protocol(hosts, username, password, true, server_type, DEFAULT_COMM_TO); lock_mem(bytes, sizeof bytes); recover_sound_dev(&chandle, false, cdevice, &format); init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { char got_any = 0; input_buffer_size = snd_pcm_frames_to_bytes(chandle, DEFAULT_SAMPLE_RATE * 2); input_buffer = reinterpret_cast<char *>(malloc_locked(input_buffer_size)); if (!input_buffer) error_exit("problem allocating %d bytes of memory", input_buffer_size); /* Discard the first data read */ /* it often contains weird looking data - probably a click from */ /* driver loading / card initialisation */ snd_pcm_sframes_t garbage_frames_read = snd_pcm_readi(chandle, input_buffer, DEFAULT_SAMPLE_RATE); /* Make sure we aren't hitting a disconnect/suspend case */ if (garbage_frames_read < 0) { dolog(LOG_INFO, "snd_pcm_readi: failed retrieving audio", snd_strerror(garbage_frames_read)); // FIXME if ((err = snd_pcm_recover(chandle, garbage_frames_read, 0)) < 0) { dolog(LOG_INFO, "snd_pcm_recover fail : %s", snd_strerror(err)); dolog(LOG_INFO, "Failure retrieving sound from soundcard, re-opening device"); recover_sound_dev(&chandle, true, cdevice, &format); } } /* Read a buffer of audio */ n_to_do = DEFAULT_SAMPLE_RATE * 2; dummy = input_buffer; while (n_to_do > 0 && !do_exit) { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, n_to_do); /* Make sure we aren't hitting a disconnect/suspend case */ if (frames_read < 0) frames_read = snd_pcm_recover(chandle, frames_read, 0); /* Nope, something else is wrong. Bail. */ if (frames_read == -1) { if ((err = snd_pcm_recover(chandle, frames_read, 0)) < 0) { dolog(LOG_INFO, "snd_pcm_recover fail : %s", snd_strerror(err)); dolog(LOG_INFO, "Failure retrieving sound from soundcard, re-opening device"); recover_sound_dev(&chandle, true, cdevice, &format); } } else { n_to_do -= frames_read; dummy += frames_read; } } /* de-biase the data */ for(loop=0; loop<(DEFAULT_SAMPLE_RATE * 2/*16bits*/ * 2/*stereo*/ * 2) && !do_exit; loop+=8) { int w1, w2, w3, w4, o1, o2; if (format == SND_PCM_FORMAT_S16_BE) { w1 = (input_buffer[loop+0]<<8) + input_buffer[loop+1]; w2 = (input_buffer[loop+2]<<8) + input_buffer[loop+3]; w3 = (input_buffer[loop+4]<<8) + input_buffer[loop+5]; w4 = (input_buffer[loop+6]<<8) + input_buffer[loop+7]; } else { w1 = (input_buffer[loop+1]<<8) + input_buffer[loop+0]; w2 = (input_buffer[loop+3]<<8) + input_buffer[loop+2]; w3 = (input_buffer[loop+5]<<8) + input_buffer[loop+4]; w4 = (input_buffer[loop+7]<<8) + input_buffer[loop+6]; } /* Determine order of channels for each sample, subtract previous sample * to compensate for unbalanced audio devices */ o1 = order(w1-psl, w2-psr); o2 = order(w3-psl, w4-psr); if (a > 0) { psl = w3; psr = w4; } else { psl = w1; psr = w2; } /* If both samples have the same order, there is bias in the samples, so we * discard them; if both channels are equal on either sample, we discard * them too; additionally, alternate the sample we'll use next (even more * bias removal) */ if (o1 == o2 || o1 < 0 || o2 < 0) { a = -a; } else { /* We've got a random bit; the bit is either the order from the first or * the second sample, determined by the alternator 'a' */ char bit = (a > 0) ? o1 : o2; byte_out <<= 1; byte_out += bit; bits_out++; got_any = 1; if (bits_out>=8) { bytes[bytes_out++] = byte_out; if (bytes_out == sizeof bytes) { if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, bytes_out); if (p && p -> message_transmit_entropy_data(bytes, bytes_out) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); bytes_out = 0; } bits_out = 0; } } } if (!got_any) dolog(LOG_WARNING, "no bits in audio-stream, please make sure the recording channel is not muted"); free_locked(input_buffer, input_buffer_size); } unlock_mem(bytes, sizeof bytes); if (!do_exit) snd_pcm_close(chandle); delete p; }
int main(int argc, char *argv[]) { int dev_random_fd = open(DEV_RANDOM, O_RDWR); const int max_bits_in_kernel_rng = kernel_rng_get_max_entropy_count(); const int write_threshold = kernel_rng_get_write_threshold(); int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; std::string username, password; int interval = -1; std::vector<std::string> hosts; int log_level = LOG_INFO; printf("eb_client_linux_kernel v" VERSION ", (C) 2009-2017 by [email protected]\n"); while((c = getopt(argc, argv, "b:hX:P:I:L:l:sn")) != -1) { switch(c) { case 'b': interval = atof(optarg); if (interval < 1) error_exit("Interval must be > 0"); break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } if (username.length() == 0 || password.length() == 0) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty()) error_exit("no host to connect to selected"); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } protocol *p = new protocol(&hosts, username, password, false, client_type, DEFAULT_COMM_TO); (void)umask(0177); no_core(); write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); dolog(LOG_INFO, "started with %d bits in kernel rng", kernel_rng_get_entropy_count()); if (dev_random_fd == -1) error_exit("failed to open %s", DEV_RANDOM); bit_count_estimator bce(BCE_SHANNON); for(;!do_exit;) { struct timeval tv, *ptv = NULL; if (interval > 0) { tv.tv_sec = interval / 1000; tv.tv_usec = int(interval * 1000) % 1000; ptv = &tv; } // wait for /dev/random te become writable which means the entropy- // level dropped below a certain threshold fd_set write_fd; FD_ZERO(&write_fd); FD_SET(dev_random_fd, &write_fd); dolog(LOG_DEBUG, "wait for low-event"); for(;!do_exit;) { int rc = select(dev_random_fd + 1, NULL, &write_fd, NULL, ptv); printf("%d\n", rc); if (rc >= 0) break; if (errno != EINTR && errno != EAGAIN) error_exit("Select error: %m"); } if (do_exit) break; int n_bits_in_kernel_rng = kernel_rng_get_entropy_count(); dolog(LOG_DEBUG, "kernel rng bit count: %d", n_bits_in_kernel_rng); if (n_bits_in_kernel_rng < write_threshold) { /* find out how many bits to add */ int n_bits_to_get = max_bits_in_kernel_rng - n_bits_in_kernel_rng; if (n_bits_to_get <= 0) { dolog(LOG_DEBUG, "number of bits to get <= 0: %d", n_bits_to_get); continue; } if (n_bits_to_get > 9999) n_bits_to_get = 9999; if (n_bits_to_get < 8) n_bits_to_get = 8; dolog(LOG_INFO, "%d bits left (%d max), will get %d bits", n_bits_in_kernel_rng, max_bits_in_kernel_rng, n_bits_to_get); int n_bytes_to_get = (n_bits_to_get + 7) / 8; unsigned char *buffer = static_cast<unsigned char *>(malloc(n_bytes_to_get)); if (!buffer) error_exit("out of memory allocating %d bytes", n_bytes_to_get); lock_mem(buffer, n_bytes_to_get); int n_bytes = p -> request_bytes(buffer, n_bits_to_get, false, &do_exit); if (do_exit) break; int is_n_bits = bce.get_bit_count(reinterpret_cast<unsigned char *>(buffer), n_bytes); int rc = kernel_rng_add_entropy(reinterpret_cast<unsigned char *>(buffer), n_bytes, is_n_bits); if (rc == -1) error_exit("error submiting entropy data to kernel"); dolog(LOG_DEBUG, "new entropy count: %d", kernel_rng_get_entropy_count()); memset(buffer, 0x00, n_bytes_to_get); unlock_mem(buffer, n_bytes_to_get); free(buffer); } } unlink(pid_file); delete p; return 0; }