static void mkcert(std::shared_ptr<X509> &cert, std::shared_ptr<EVP_PKEY> &pkey, int bits, int serial, int days) { RSA *rsa; X509_NAME *name=NULL; pkey.reset(EVP_PKEY_new(), &EVP_PKEY_free); if (!pkey) throw std::bad_alloc(); cert.reset(X509_new(), &X509_free); if (!cert) throw std::bad_alloc(); rsa = RSA_generate_key(bits,RSA_F4,NULL,NULL); MORDOR_VERIFY(EVP_PKEY_assign_RSA(pkey.get(),rsa)); X509_set_version(cert.get(),2); ASN1_INTEGER_set(X509_get_serialNumber(cert.get()),serial); X509_gmtime_adj(X509_get_notBefore(cert.get()),0); X509_gmtime_adj(X509_get_notAfter(cert.get()),(long)60*60*24*days); X509_set_pubkey(cert.get(),pkey.get()); name=X509_get_subject_name(cert.get()); /* This function creates and adds the entry, working out the * correct string type and performing checks on its length. * Normally we'd check the return value for errors... */ X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (const unsigned char *)"United States", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char *)"Mordor Default Self-signed Certificate", -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(cert.get(),name); /* Add various extensions: standard extensions */ add_ext(cert.get(), NID_basic_constraints, "critical,CA:TRUE"); add_ext(cert.get(), NID_key_usage, "critical,keyCertSign,cRLSign"); add_ext(cert.get(), NID_subject_key_identifier, "hash"); /* Some Netscape specific extensions */ add_ext(cert.get(), NID_netscape_cert_type, "sslCA"); MORDOR_VERIFY(X509_sign(cert.get(),pkey.get(),EVP_md5())); }
void IOManagerEPoll::tickle() { int rc = write(m_tickleFds[1], "T", 1); MORDOR_LOG_VERBOSE(g_log) << this << " write(" << m_tickleFds[1] << ", 1): " << rc << " (" << errno << ")"; MORDOR_VERIFY(rc == 1); }
void add_ext(X509 *cert, int nid, const char *value) { X509_EXTENSION *ex = NULL; X509V3_CTX ctx; /* This sets the 'context' of the extensions. */ /* No configuration database */ X509V3_set_ctx_nodb(&ctx); /* Issuer and subject certs: both the target since it is self signed, * no request and no CRL */ X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); MORDOR_VERIFY(X509V3_EXT_conf_nid(NULL, &ctx, nid, (char*) value)); X509_add_ext(cert,ex,-1); X509_EXTENSION_free(ex); }
void IOManagerEPoll::idle() { epoll_event events[64]; while (true) { unsigned long long nextTimeout; if (stopping(nextTimeout)) return; int rc = -1; errno = EINTR; while (rc < 0 && errno == EINTR) { int timeout = -1; if (nextTimeout != ~0ull) timeout = (int)(nextTimeout / 1000) + 1; rc = epoll_wait(m_epfd, events, 64, timeout); if (rc < 0 && errno == EINTR) nextTimeout = nextTimer(); } MORDOR_LOG_LEVEL(g_log, rc < 0 ? Log::ERROR : Log::VERBOSE) << this << " epoll_wait(" << m_epfd << "): " << rc << " (" << errno << ")"; if (rc < 0) MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("epoll_wait"); std::vector<boost::function<void ()> > expired = processTimers(); schedule(expired.begin(), expired.end()); for(int i = 0; i < rc; ++i) { epoll_event &event = events[i]; if (event.data.fd == m_tickleFds[0]) { unsigned char dummy; int rc2 = read(m_tickleFds[0], &dummy, 1); MORDOR_VERIFY(rc2 == 1); MORDOR_LOG_VERBOSE(g_log) << this << " received tickle"; continue; } bool err = event.events & (EPOLLERR | EPOLLHUP); boost::mutex::scoped_lock lock(m_mutex); std::map<int, AsyncEvent>::iterator it = m_pendingEvents.find(event.data.fd); if (it == m_pendingEvents.end()) continue; AsyncEvent &e = it->second; MORDOR_LOG_TRACE(g_log) << " epoll_event {" << (epoll_events_t)event.events << ", " << event.data.fd << "}, registered for " << (epoll_events_t)e.event.events; if ((event.events & EPOLLERR) && (e.event.events & EPOLLERR)) { if (e.m_dgError) e.m_schedulerError->schedule(e.m_dgError); else e.m_schedulerError->schedule(e.m_fiberError); // Block other events from firing e.m_dgError = NULL; e.m_fiberError.reset(); e.m_dgIn = NULL; e.m_fiberIn.reset(); e.m_dgOut = NULL; e.m_fiberOut.reset(); event.events = 0; e.event.events = 0; } if ((event.events & EPOLLHUP) && (e.event.events & EPOLLHUP)) { if (e.m_dgClose) e.m_schedulerError->schedule(e.m_dgClose); else e.m_schedulerError->schedule(e.m_fiberClose); // Block write event from firing e.m_dgOut = NULL; e.m_fiberOut.reset(); e.m_dgClose = NULL; e.m_fiberClose.reset(); event.events &= EPOLLOUT; e.event.events &= EPOLLOUT; err = false; } if (((event.events & EPOLLIN) || err) && (e.event.events & EPOLLIN)) { if (e.m_dgIn) e.m_schedulerIn->schedule(e.m_dgIn); else e.m_schedulerIn->schedule(e.m_fiberIn); e.m_dgIn = NULL; e.m_fiberIn.reset(); event.events |= EPOLLIN; } if (((event.events & EPOLLOUT) || err) && (e.event.events & EPOLLOUT)) { if (e.m_dgOut) e.m_schedulerOut->schedule(e.m_dgOut); else e.m_schedulerOut->schedule(e.m_fiberOut); e.m_dgOut = NULL; e.m_fiberOut.reset(); event.events |= EPOLLOUT; } e.event.events &= ~event.events; int op = e.event.events == 0 ? EPOLL_CTL_DEL : EPOLL_CTL_MOD; int rc2 = epoll_ctl(m_epfd, op, event.data.fd, &e.event); MORDOR_LOG_LEVEL(g_log, rc2 ? Log::ERROR : Log::VERBOSE) << this << " epoll_ctl(" << m_epfd << ", " << (epoll_ctl_op_t)op << ", " << event.data.fd << ", " << (epoll_events_t)e.event.events << "): " << rc2 << " (" << errno << ")"; if (rc2) MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("epoll_ctl"); if (op == EPOLL_CTL_DEL) m_pendingEvents.erase(it); } Fiber::yield(); } }