Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}