コード例 #1
0
ファイル: SelectPoll.cpp プロジェクト: jimmy486/kuma
int SelectPoll::unregisterFd(SOCKET_FD fd)
{
    KUMA_INFOTRACE("SelectPoll::unregisterFd, fd="<<fd);
    int max_fd = int(poll_items_.size() - 1);
    if (fd < 0 || fd > max_fd) {
        KUMA_WARNTRACE("SelectPoll::unregisterFd, failed, max_fd=" << max_fd);
        return KUMA_ERROR_INVALID_PARAM;
    }
    updateFdSet(fd, 0);
    int idx = poll_items_[fd].idx;
    if (fd == max_fd) {
        poll_items_.pop_back();
    } else {
        poll_items_[fd].fd = INVALID_FD;
        poll_items_[fd].cb = nullptr;
        poll_items_[fd].idx = -1;
    }
    int last_idx = int(poll_fds_.size() - 1);
    if (idx > last_idx || -1 == idx) {
        return KUMA_ERROR_NOERR;
    }
    if (idx != last_idx) {
        std::iter_swap(poll_fds_.begin() + idx, poll_fds_.end() - 1);
        poll_items_[poll_fds_[idx].fd].idx = idx;
    }
    poll_fds_.pop_back();
    return KUMA_ERROR_NOERR;
}
コード例 #2
0
ファイル: VPoll.cpp プロジェクト: Jamol/kuma
KMError VPoll::unregisterFd(SOCKET_FD fd)
{
    int max_fd = int(poll_items_.size() - 1);
    KUMA_INFOTRACE("VPoll::unregisterFd, fd="<<fd<<", max_fd="<<max_fd);
    if (fd < 0 || -1 == max_fd || fd > max_fd) {
        KUMA_WARNTRACE("VPoll::unregisterFd, failed, max_fd="<<max_fd);
        return KMError::INVALID_PARAM;
    }
    int idx = poll_items_[fd].idx;
    if(fd < max_fd) {
        poll_items_[fd].reset();
    } else if (fd == max_fd) {
        poll_items_.pop_back();
    }
    
    int last_idx = int(poll_fds_.size() - 1);
    if (idx > last_idx || -1 == idx) {
        return KMError::NOERR;
    }
    if (idx != last_idx) {
        std::iter_swap(poll_fds_.begin()+idx, poll_fds_.end()-1);
        poll_items_[poll_fds_[idx].fd].idx = idx;
    }
    poll_fds_.pop_back();
    return KMError::NOERR;
}
コード例 #3
0
ファイル: EPoll.cpp プロジェクト: zhaowolong/kuma
int EPoll::unregisterFd(SOCKET_FD fd)
{
    KUMA_INFOTRACE("EPoll::unregisterFd, fd="<<fd);
    epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, NULL);
    if(fd < poll_items_.size()) {
        poll_items_[fd].fd = INVALID_FD;
        poll_items_[fd].cb = nullptr;
    }
    return KUMA_ERROR_NOERR;
}
コード例 #4
0
ファイル: HttpParserImpl.cpp プロジェクト: jimmy486/kuma
void HttpParserImpl::onHeaderComplete()
{
    header_complete_ = true;
    auto it = header_map_.find("Content-Length");
    if(it != header_map_.end()) {
        content_length_ = atoi(it->second.c_str());
        has_content_length_ = true;
        KUMA_INFOTRACE("HttpParser::onHeaderComplete, Content-Length="<<content_length_);
    }
    it = header_map_.find("Transfer-Encoding");
    if(it != header_map_.end()) {
        is_chunked_ = is_equal("chunked", it->second);
        KUMA_INFOTRACE("HttpParser::onHeaderComplete, Transfer-Encoding="<<it->second);
    }
    it = header_map_.find("Upgrade");
    if(it != header_map_.end()) {
        upgrade_ = true;
        KUMA_INFOTRACE("HttpParser::onHeaderComplete, Upgrade="<<it->second);
    }
    if(cb_event_) cb_event_(HTTP_HEADER_COMPLETE);
}
コード例 #5
0
ファイル: EventLoopImpl.cpp プロジェクト: jimmy486/kuma
void EventLoopImpl::loop(uint32_t max_wait_ms)
{
    while (!stop_loop_) {
        loopOnce(max_wait_ms);
    }
    LoopCallback cb;
    while (cb_queue_.dequeue(cb)) {
        if (cb) {
            cb();
        }
    }
    KUMA_INFOTRACE("EventLoop::loop, stopped");
}
コード例 #6
0
ファイル: KQueue.cpp プロジェクト: zoujiaqing/kuma
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;
}
コード例 #7
0
ファイル: EPoll.cpp プロジェクト: zhaowolong/kuma
int EPoll::updateFd(SOCKET_FD fd, uint32_t events)
{
    if(fd >= poll_items_.size() || INVALID_FD == poll_items_[fd].fd) {
        return KUMA_ERROR_FAILED;
    }
    struct epoll_event evt = {0};
    evt.data.ptr = (void*)(long)fd;
    evt.events = get_events(events);
    if(epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) < 0) {
        KUMA_INFOTRACE("EPoll::updateFd error, fd="<<fd<<", errno="<<errno);
        return KUMA_ERROR_FAILED;
    }
    return KUMA_ERROR_NOERR;
}
コード例 #8
0
ファイル: OpenSslLib.cpp プロジェクト: jimmy486/kuma
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;
}
コード例 #9
0
ファイル: SelectPoll.cpp プロジェクト: jimmy486/kuma
int SelectPoll::registerFd(SOCKET_FD fd, uint32_t events, IOCallback& cb)
{
    KUMA_INFOTRACE("SelectPoll::registerFd, fd="<<fd);
    resizePollItems(fd);
    if (INVALID_FD == poll_items_[fd].fd || -1 == poll_items_[fd].idx) {
        PollFD pfd;
        pfd.fd = fd;
        pfd.events = events;
        poll_fds_.push_back(pfd);
        poll_items_[fd].idx = int(poll_fds_.size() - 1);
    }
    poll_items_[fd].fd = fd;
    poll_items_[fd].cb = cb;
    updateFdSet(fd, events);
    return KUMA_ERROR_NOERR;
}
コード例 #10
0
ファイル: KQueue.cpp プロジェクト: zoujiaqing/kuma
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;
}
コード例 #11
0
ファイル: EPoll.cpp プロジェクト: zhaowolong/kuma
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;
}
コード例 #12
0
ファイル: EPoll.cpp プロジェクト: zhaowolong/kuma
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;
}
コード例 #13
0
ファイル: VPoll.cpp プロジェクト: Jamol/kuma
KMError VPoll::registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb)
{
    if (fd < 0) {
        return KMError::INVALID_PARAM;
    }
    resizePollItems(fd);
    int idx = -1;
    if (INVALID_FD == poll_items_[fd].fd || -1 == poll_items_[fd].idx) { // new
        pollfd pfd;
        pfd.fd = fd;
        pfd.events = get_events(events);
        poll_fds_.push_back(pfd);
        idx = int(poll_fds_.size() - 1);
        poll_items_[fd].idx = idx;
    }
    poll_items_[fd].fd = fd;
    poll_items_[fd].events = events;
    poll_items_[fd].cb = std::move(cb);
    KUMA_INFOTRACE("VPoll::registerFd, fd="<<fd<<", events="<<events<<", index="<<idx);
    
    return KMError::NOERR;
}
コード例 #14
0
ファイル: KQueue.cpp プロジェクト: zoujiaqing/kuma
KMError KQueue::unregisterFd(SOCKET_FD fd)
{
    int max_fd = int(poll_items_.size() - 1);
    KUMA_INFOTRACE("KQueue::unregisterFd, fd="<<fd<<", max_fd="<<max_fd);
    if (fd < 0 || fd > max_fd) {
        KUMA_WARNTRACE("KQueue::unregisterFd, failed, max_fd=" << max_fd);
        return KMError::INVALID_PARAM;
    }
    struct kevent kevents[2];
    int nchanges = 0;
    if (poll_items_[fd].events & KUMA_EV_READ) {
        EV_SET(&kevents[nchanges++], fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
    }
    if (poll_items_[fd].events & KUMA_EV_WRITE) {
        EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
    }
    ::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0);
    if(fd < max_fd) {
        poll_items_[fd].reset();
    } else if (fd == max_fd) {
        poll_items_.pop_back();
    }
    return KMError::NOERR;
}
コード例 #15
0
ファイル: TcpSocketImpl.cpp プロジェクト: jimmy486/kuma
int TcpSocketImpl::bind(const char *bind_host, uint16_t bind_port)
{
    KUMA_INFOTRACE("bind, bind_host="<<bind_host<<", bind_port="<<bind_port);
    if(getState() != ST_IDLE) {
        KUMA_ERRXTRACE("bind, invalid state, state="<<getState());
        return KUMA_ERROR_INVALID_STATE;
    }
    if(fd_ != INVALID_FD) {
        cleanup();
    }
    sockaddr_storage ss_addr = {0};
    struct addrinfo hints = {0};
    hints.ai_family = AF_UNSPEC;
    hints.ai_flags = AI_NUMERICHOST;//AI_ADDRCONFIG; // will block 10 seconds in some case if not set AI_ADDRCONFIG
    if(km_set_sock_addr(bind_host, bind_port, &hints, (struct sockaddr*)&ss_addr, sizeof(ss_addr)) != 0) {
        return KUMA_ERROR_INVALID_PARAM;
    }
    fd_ = ::socket(ss_addr.ss_family, SOCK_STREAM, 0);
    if(INVALID_FD == fd_) {
        KUMA_ERRXTRACE("bind, socket failed, err="<<getLastError());
        return KUMA_ERROR_FAILED;
    }
    int addr_len = sizeof(ss_addr);
#ifdef KUMA_OS_MAC
    if(AF_INET == ss_addr.ss_family)
        addr_len = sizeof(sockaddr_in);
    else
        addr_len = sizeof(sockaddr_in6);
#endif
    int ret = ::bind(fd_, (struct sockaddr*)&ss_addr, addr_len);
    if(ret < 0) {
        KUMA_ERRXTRACE("bind, bind failed, err="<<getLastError());
        return KUMA_ERROR_FAILED;
    }
    return KUMA_ERROR_NOERR;
}
コード例 #16
0
ファイル: OpenSslLib.cpp プロジェクト: jimmy486/kuma
int OpenSslLib::appVerifyCallback(X509_STORE_CTX *ctx, void *arg)
{
    if(!ctx || !arg) {
        return -1;
    }
    
    int ok = 1;
    struct app_verify_arg *cb_arg = (struct app_verify_arg *)arg;
    
    if (cb_arg->app_verify) {
        char *s = NULL, buf[256];
        if(ctx->cert) {
            s = X509_NAME_oneline(X509_get_subject_name(ctx->cert), buf, 256);
        }
        if(s != NULL) {
            KUMA_INFOTRACE("appVerifyCallback, depth="<<ctx->error_depth<<", "<<buf);
        }
        return 1;
    }
    
    ok = X509_verify_cert(ctx);
    
    return ok;
}
コード例 #17
0
ファイル: EventLoopImpl.cpp プロジェクト: jimmy486/kuma
void EventLoopImpl::stop()
{
    KUMA_INFOTRACE("EventLoop::stop");
    stop_loop_ = true;
    poll_->notify();
}
コード例 #18
0
ファイル: HttpParserImpl.cpp プロジェクト: jimmy486/kuma
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;
}
コード例 #19
0
ファイル: HttpParserImpl.cpp プロジェクト: jimmy486/kuma
void HttpParserImpl::onComplete()
{
    KUMA_INFOTRACE("HttpParser::onComplete");
    if(cb_event_) cb_event_(HTTP_COMPLETE);
}