void * noit_livestream_thread_main(void *e_vptr) { int mask; eventer_t e = e_vptr; acceptor_closure_t *ac = e->closure; noit_livestream_closure_t *jcl = ac->service_ctx; /* Go into blocking mode */ if(eventer_set_fd_blocking(e->fd) == -1) { noitL(noit_error, "failed setting livestream to blocking: [%d] [%s]\n", errno, strerror(errno)); goto alldone; } while(1) { u_int32_t netlen; struct log_entry *le = NULL; int rv; sem_wait(&jcl->lqueue_sem); pthread_mutex_lock(&jcl->lqueue_lock); if(jcl->lqueue) { /* If there are items, pop and advance the header pointer */ le = jcl->lqueue; jcl->lqueue = jcl->lqueue->next; if(!jcl->lqueue) jcl->lqueue_end = NULL; } pthread_mutex_unlock(&jcl->lqueue_lock); if(!le) continue; /* Here we actually push the message */ netlen = htonl(le->len); if((rv = Ewrite(&netlen, sizeof(netlen))) != sizeof(netlen)) { noitL(noit_error, "Error writing le header over SSL %d != %d\n", rv, (int)sizeof(netlen)); goto alldone; } if((rv = Ewrite(le->buff, le->len)) != le->len) { noitL(noit_error, "Error writing livestream message over SSL %d != %d\n", rv, le->len); goto alldone; } } alldone: e->opset->close(e->fd, &mask, e); jcl->wants_shutdown = 1; if(ac) acceptor_closure_free(ac); return NULL; }
void * noit_jlog_thread_main(void *e_vptr) { int mask, bytes_read; eventer_t e = e_vptr; acceptor_closure_t *ac = e->closure; noit_jlog_closure_t *jcl = ac->service_ctx; char inbuff[sizeof(jlog_id)]; eventer_set_fd_blocking(e->fd); while(1) { jlog_id client_chkpt; int sleeptime = (ac->cmd == NOIT_JLOG_DATA_TEMP_FEED) ? 1 : DEFAULT_SECONDS_BETWEEN_BATCHES; jlog_get_checkpoint(jcl->jlog, ac->remote_cn, &jcl->chkpt); jcl->count = jlog_ctx_read_interval(jcl->jlog, &jcl->start, &jcl->finish); if(jcl->count < 0) { char idxfile[PATH_MAX]; noitL(noit_error, "jlog_ctx_read_interval: %s\n", jlog_ctx_err_string(jcl->jlog)); switch (jlog_ctx_err(jcl->jlog)) { case JLOG_ERR_FILE_CORRUPT: case JLOG_ERR_IDX_CORRUPT: jlog_repair_datafile(jcl->jlog, jcl->start.log); jlog_repair_datafile(jcl->jlog, jcl->start.log + 1); noitL(noit_error, "jlog reconstructed, deleting corresponding index.\n"); STRSETDATAFILE(jcl->jlog, idxfile, jcl->start.log); strlcat(idxfile, INDEX_EXT, sizeof(idxfile)); unlink(idxfile); STRSETDATAFILE(jcl->jlog, idxfile, jcl->start.log + 1); strlcat(idxfile, INDEX_EXT, sizeof(idxfile)); unlink(idxfile); goto alldone; break; default: goto alldone; } } if(jcl->count > MAX_ROWS_AT_ONCE) { /* Artificially set down the range to make the batches a bit easier * to handle on the stratcond/postgres end. * However, we must have more data, so drop the sleeptime to 0 */ jcl->count = MAX_ROWS_AT_ONCE; jcl->finish.marker = jcl->start.marker + jcl->count; sleeptime = 0; } if(jcl->count > 0) { if(noit_jlog_push(e, jcl)) { goto alldone; } /* Read our jlog_id accounting for possibly short reads */ bytes_read = 0; while(bytes_read < sizeof(jlog_id)) { int len; if((len = e->opset->read(e->fd, inbuff + bytes_read, sizeof(jlog_id) - bytes_read, &mask, e)) <= 0) goto alldone; bytes_read += len; } memcpy(&client_chkpt, inbuff, sizeof(jlog_id)); /* Fix the endian */ client_chkpt.log = ntohl(client_chkpt.log); client_chkpt.marker = ntohl(client_chkpt.marker); if(memcmp(&jcl->chkpt, &client_chkpt, sizeof(jlog_id))) { noitL(noit_error, "client %s submitted invalid checkpoint %u:%u expected %u:%u\n", ac->remote_cn, client_chkpt.log, client_chkpt.marker, jcl->chkpt.log, jcl->chkpt.marker); goto alldone; } gettimeofday(&jcl->feed_stats->last_checkpoint, NULL); jlog_ctx_read_checkpoint(jcl->jlog, &jcl->chkpt); } else { /* we have nothing to write -- maybe we have no checks configured... * If this is the case "forever", the remote might disconnect and * we would never know. Do the painful work of detecting a * disconnected client. */ struct pollfd pfd; pfd.fd = e->fd; pfd.events = POLLIN | POLLHUP | POLLRDNORM; pfd.revents = 0; if(poll(&pfd, 1, 0) != 0) { /* normally, we'd recv PEEK|DONTWAIT. However, the client should * not be writing to us. So, we know we can't have any legitimate * data on this socket (true even though this is SSL). So, if we're * here then "shit went wrong" */ noitL(noit_error, "jlog client %s disconnected while idle\n", ac->remote_cn); goto alldone; } } if(sleeptime) sleep(sleeptime); } alldone: e->opset->close(e->fd, &mask, e); noit_atomic_dec32(&jcl->feed_stats->connections); noit_jlog_closure_free(jcl); acceptor_closure_free(ac); return NULL; }
static int ssh2_drive_session(eventer_t e, int mask, void *closure, struct timeval *now) { int i; const char *fingerprint; ssh2_check_info_t *ci = closure; struct timeval diff; int timeout_ms = 10; /* 10ms, gets set below */ if(ci->state == WANT_CLOSE) { noit_check_t *check = ci->check; ssh2_log_results(ci->self, ci->check); ssh2_cleanup(ci->self, ci->check); eventer_remove_fd(e->fd); e->opset->close(e->fd, &mask, e); check->flags &= ~NP_RUNNING; return 0; } switch(mask) { case EVENTER_ASYNCH_WORK: if(eventer_set_fd_blocking(e->fd)) { ci->timed_out = 0; ci->error = strdup("socket error"); return 0; } ci->session = libssh2_session_init(); #define set_method(a,b) do { \ int rv; \ if(ci->methods.a && \ (rv = libssh2_session_method_pref(ci->session, b, ci->methods.a)) != 0) { \ ci->timed_out = 0; \ ci->error = strdup((rv == LIBSSH2_ERROR_METHOD_NOT_SUPPORTED) ? \ #a " method not supported" : "error setting " #a); \ return 0; \ } \ } while(0) set_method(kex, LIBSSH2_METHOD_KEX); set_method(hostkey, LIBSSH2_METHOD_HOSTKEY); set_method(crypt_cs, LIBSSH2_METHOD_CRYPT_CS); set_method(crypt_sc, LIBSSH2_METHOD_CRYPT_SC); set_method(mac_cs, LIBSSH2_METHOD_MAC_CS); set_method(mac_sc, LIBSSH2_METHOD_MAC_SC); set_method(comp_cs, LIBSSH2_METHOD_COMP_CS); set_method(comp_sc, LIBSSH2_METHOD_COMP_SC); if(compare_timeval(*now, e->whence) < 0) { sub_timeval(e->whence, *now, &diff); timeout_ms = diff.tv_sec * 1000 + diff.tv_usec / 1000; } #if LIBSSH2_VERSION_NUM >= 0x010209 libssh2_session_set_timeout(ci->session, timeout_ms); #endif if (libssh2_session_startup(ci->session, e->fd)) { ci->timed_out = 0; ci->error = strdup("ssh session startup failed"); return 0; } fingerprint = libssh2_hostkey_hash(ci->session, LIBSSH2_HOSTKEY_HASH_MD5); for(i=0;i<16;i++) { snprintf(ci->fingerprint + (i*2), 3, "%02x", (unsigned char)fingerprint[i]); } ci->fingerprint[32] = '\0'; ci->timed_out = 0; return 0; break; case EVENTER_ASYNCH_CLEANUP: if(ci->session) { libssh2_session_disconnect(ci->session, "Bye!"); libssh2_session_free(ci->session); ci->session = NULL; } ci->state = WANT_CLOSE; break; default: abort(); } return 0; }