KMError KQueue::wait(uint32_t wait_ms) { timespec tval = { 0, 0 }; if(wait_ms != -1) { tval.tv_sec = wait_ms/1000; tval.tv_nsec = (wait_ms - tval.tv_sec*1000)*1000*1000; } struct kevent kevents[MAX_EVENT_NUM]; int nevents = kevent(kqueue_fd_, 0, 0, kevents, MAX_EVENT_NUM, wait_ms == -1 ? NULL : &tval); if (nevents < 0) { if(errno != EINTR) { KUMA_ERRTRACE("KQueue::wait, errno="<<errno); } KUMA_INFOTRACE("KQueue::wait, nevents="<<nevents<<", errno="<<errno); } else { SOCKET_FD fds[MAX_EVENT_NUM] = { INVALID_FD }; int nfds = 0; int max_fd = int(poll_items_.size() - 1); for (int i=0; i<nevents; ++i) { SOCKET_FD fd = (SOCKET_FD)kevents[i].ident; if(fd >= 0 && fd <= max_fd) { uint32_t revents = 0; if (kevents[i].filter == EVFILT_READ) { revents |= KUMA_EV_READ; } else if (kevents[i].filter == EVFILT_WRITE) { revents |= KUMA_EV_WRITE; } if (kevents[i].flags & EV_ERROR) { revents |= KUMA_EV_ERROR; } if (!revents) { continue; } if (poll_items_[fd].revents == 0) { fds[nfds++] = fd; } poll_items_[fd].revents = revents; } } for (int i=0; i<nfds; ++i) { SOCKET_FD fd = fds[i]; if (fd < poll_items_.size()) { uint32_t revents = poll_items_[fd].revents; poll_items_[fd].revents = 0; IOCallback &cb = poll_items_[fd].cb; if(cb) cb(revents); } } } return KMError::NOERR; }
KMError KQueue::registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb) { if (fd < 0) { return KMError::INVALID_PARAM; } resizePollItems(fd); struct kevent kevents[2]; int nchanges = 0; if (INVALID_FD != poll_items_[fd].fd) { if (!!(poll_items_[fd].events & KUMA_EV_READ) && !(events & KUMA_EV_READ)) { EV_SET(&kevents[nchanges++], fd, EVFILT_READ, EV_DELETE, 0, 0, 0); poll_items_[fd].events &= ~KUMA_EV_READ; } if (!!(poll_items_[fd].events & KUMA_EV_WRITE) && !(events & KUMA_EV_WRITE)) { EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); poll_items_[fd].events &= ~KUMA_EV_WRITE; } ::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0); if (poll_items_[fd].events == events) { poll_items_[fd].cb = std::move(cb); return KMError::NOERR; } } nchanges = 0; unsigned short op = EV_ADD; if (work_on_et_mode_) { op |= EV_CLEAR; } if (events & KUMA_EV_READ) { EV_SET(&kevents[nchanges++], fd, EVFILT_READ, op , 0, 0, 0); } if (events & KUMA_EV_WRITE) { EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, op , 0, 0, 0); } poll_items_[fd].fd = fd; poll_items_[fd].events = events; poll_items_[fd].cb = std::move(cb); if(::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0) == -1) { KUMA_ERRTRACE("KQueue::registerFd error, fd=" << fd << ", ev=" << events << ", errno=" << errno); return KMError::FAILED; } KUMA_INFOTRACE("KQueue::registerFd, fd=" << fd << ", ev=" << events); return KMError::NOERR; }
int EPoll::wait(uint32_t wait_ms) { struct epoll_event events[MAX_EVENT_NUM]; int nfds = epoll_wait(epoll_fd_, events, MAX_EVENT_NUM , wait_ms); if (nfds < 0) { if(errno != EINTR) { KUMA_ERRTRACE("EPoll::wait, errno="<<errno); } KUMA_INFOTRACE("EPoll::wait, epoll_wait, nfds="<<nfds<<", errno="<<errno); } else { for (int i=0; i<nfds; ++i) { SOCKET_FD fd = (SOCKET_FD)(long)events[i].data.ptr; if(fd < poll_items_.size()) { IOCallback &cb = poll_items_[fd].cb; if(cb) cb(get_kuma_events(events[i].events)); } } } return KUMA_ERROR_NOERR; }
int EPoll::registerFd(SOCKET_FD fd, uint32_t events, IOCallback&& cb) { resizePollItems(fd); int epoll_op = EPOLL_CTL_ADD; if (INVALID_FD != poll_items_[fd].fd) { epoll_op = EPOLL_CTL_MOD; } poll_items_[fd].fd = fd; poll_items_[fd].cb = std::move(cb); struct epoll_event evt = {0}; evt.data.ptr = (void*)(long)fd; evt.events = get_events(events);//EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLET; if(epoll_ctl(epoll_fd_, epoll_op, fd, &evt) < 0) { KUMA_ERRTRACE("EPoll::registerFd error, fd=" << fd << ", ev=" << evt.events << ", errno=" << errno); return KUMA_ERROR_FAILED; } KUMA_INFOTRACE("EPoll::registerFd, fd=" << fd << ", ev=" << evt.events); return KUMA_ERROR_NOERR; }
KMError KQueue::updateFd(SOCKET_FD fd, uint32_t events) { if(fd < 0 || fd >= poll_items_.size() || INVALID_FD == poll_items_[fd].fd) { return KMError::FAILED; } struct kevent kevents[2]; int nchanges = 0; if (!!(poll_items_[fd].events & KUMA_EV_READ) && !(events & KUMA_EV_READ)) { EV_SET(&kevents[nchanges++], fd, EVFILT_READ, EV_DELETE, 0, 0, 0); poll_items_[fd].events &= ~KUMA_EV_READ; } if (!!(poll_items_[fd].events & KUMA_EV_WRITE) && !(events & KUMA_EV_WRITE)) { EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); poll_items_[fd].events &= ~KUMA_EV_WRITE; } ::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0); if (poll_items_[fd].events == events) { return KMError::NOERR; } nchanges = 0; unsigned short op = EV_ADD; if (work_on_et_mode_) { op |= EV_CLEAR; } if (events & KUMA_EV_READ) { EV_SET(&kevents[nchanges++], fd, EVFILT_READ, op , 0, 0, 0); } if (events & KUMA_EV_WRITE) { EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, op , 0, 0, 0); } if(::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0) == -1) { KUMA_ERRTRACE("KQueue::updateFd error, fd="<<fd<<", errno="<<errno); return KMError::FAILED; } //KUMA_INFOTRACE("KQueue::updateFd, fd="<<fd<<", ev="<<events); return KMError::NOERR; }
KMError VPoll::wait(uint32_t wait_ms) { #ifdef KUMA_OS_WIN int num_revts = WSAPoll(&poll_fds_[0], poll_fds_.size(), wait_ms); #else int num_revts = poll(&poll_fds_[0], (nfds_t)poll_fds_.size(), wait_ms); #endif if (-1 == num_revts) { if(EINTR == errno) { errno = 0; } else { KUMA_ERRTRACE("VPoll::wait, err="<<getLastError()); } return KMError::INVALID_STATE; } // copy poll fds since event handler may unregister fd PollFdVector poll_fds = poll_fds_; int idx = 0; int last_idx = int(poll_fds.size() - 1); while(num_revts > 0 && idx <= last_idx) { if(poll_fds[idx].revents) { --num_revts; if(poll_fds[idx].fd < poll_items_.size()) { auto &item = poll_items_[poll_fds[idx].fd]; auto revents = get_kuma_events(poll_fds[idx].revents); revents &= item.events; if (revents && item.cb) { item.cb(revents, nullptr, 0); } } } ++idx; } return KMError::NOERR; }
int OpenSslLib::verifyCallback(int ok, X509_STORE_CTX *ctx) { if(NULL == ctx) { return -1; } if(ctx->current_cert) { char *s, buf[1024]; s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf)); if(s != NULL) { if(ok) { KUMA_INFOTRACE("verifyCallback ok, depth="<<ctx->error_depth<<", subject="<<buf); if(X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, sizeof(buf))) { KUMA_INFOTRACE("verifyCallback, issuer="<<buf); } } else { KUMA_ERRTRACE("verifyCallback failed, depth="<<ctx->error_depth <<", err="<<ctx->error<<", subject="<<buf); } } } if (0 == ok) { KUMA_INFOTRACE("verifyCallback, err="<<X509_verify_cert_error_string(ctx->error)); switch (ctx->error) { //case X509_V_ERR_CERT_NOT_YET_VALID: //case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: KUMA_INFOTRACE("verifyCallback, ... ignored, err="<<ctx->error); ok = 1; break; } } return ok; }
HttpParserImpl::ParseState HttpParserImpl::parseChunk(const char*& cur_pos, const char* end) { const char* p_line = nullptr; const char* p_end = nullptr; bool b_line = false; while (cur_pos < end) { switch (chunk_state_) { case CHUNK_READ_SIZE: { b_line = getLine(cur_pos, end, p_line, p_end); if(!b_line) {// need more data, save remain data. if(saveData(cur_pos, end) != KUMA_ERROR_NOERR) { return PARSE_STATE_ERROR; } cur_pos = end; return PARSE_STATE_CONTINUE; } std::string str; if(!str_buf_.empty()) { str.swap(str_buf_); clearBuffer(); } str.append(p_line, p_end); // need not parse chunk extension chunk_size_ = (uint32_t)strtol(str.c_str(), NULL, 16); KUMA_INFOTRACE("HttpParser::parseChunk, chunk_size="<<chunk_size_); if(0 == chunk_size_) {// chunk completed chunk_state_ = CHUNK_READ_TRAILER; } else { chunk_bytes_read_ = 0; chunk_state_ = CHUNK_READ_DATA; } break; } case CHUNK_READ_DATA: { uint32_t cur_len = uint32_t(end - cur_pos); if(chunk_size_ - chunk_bytes_read_ <= cur_len) {// data enough const char* notify_data = cur_pos; uint32_t notify_len = chunk_size_ - chunk_bytes_read_; total_bytes_read_ += notify_len; chunk_bytes_read_ = chunk_size_ = 0; // reset chunk_state_ = CHUNK_READ_DATA_CR; cur_pos += notify_len; bool destroyed = false; destroy_flag_ptr_ = &destroyed; if(cb_data_) cb_data_(notify_data, notify_len); if(destroyed) { return PARSE_STATE_DESTROY; } destroy_flag_ptr_ = nullptr; } else {// need more data const char* notify_data = cur_pos; total_bytes_read_ += cur_len; chunk_bytes_read_ += cur_len; cur_pos += cur_len; if(cb_data_) cb_data_(notify_data, cur_len); return PARSE_STATE_CONTINUE; } break; } case CHUNK_READ_DATA_CR: { if(*cur_pos != CR) { KUMA_ERRTRACE("HttpParser::parseChunk, can not find data CR"); read_state_ = HTTP_READ_ERROR; return PARSE_STATE_ERROR; } ++cur_pos; chunk_state_ = CHUNK_READ_DATA_LF; break; } case CHUNK_READ_DATA_LF: { if(*cur_pos != LF) { KUMA_ERRTRACE("HttpParser::parseChunk, can not find data LF"); read_state_ = HTTP_READ_ERROR; return PARSE_STATE_ERROR; } ++cur_pos; chunk_state_ = CHUNK_READ_SIZE; break; } case CHUNK_READ_TRAILER: { b_line = getLine(cur_pos, end, p_line, p_end); if(b_line) { if(p_line == p_end && bufferEmpty()) { // blank line, http completed read_state_ = HTTP_READ_DONE; onComplete(); return PARSE_STATE_DONE; } clearBuffer(); // discard trailer } else { // need more data if(saveData(cur_pos, end) != KUMA_ERROR_NOERR) { return PARSE_STATE_ERROR; } cur_pos = end; // all data was consumed return PARSE_STATE_CONTINUE; } break; } } } return HTTP_READ_DONE == read_state_?PARSE_STATE_DONE:PARSE_STATE_CONTINUE; }