void WebSocketImpl::onClose(int err) { KUMA_INFOXTRACE("onClose, err="<<err); cleanup(); setState(STATE_CLOSED); if(cb_error_) cb_error_(KUMA_ERROR_SOCKERR); }
void TcpSocketImpl::onClose(int err) { KUMA_INFOXTRACE("onClose, err="<<err<<", state="<<getState()); cleanup(); setState(ST_CLOSED); if(cb_error_) cb_error_(err); }
int WebSocketImpl::close() { KUMA_INFOXTRACE("close"); cleanup(); setState(STATE_CLOSED); return KUMA_ERROR_NOERR; }
int TcpSocketImpl::attachFd(SOCKET_FD fd, SSL* ssl, uint32_t flags) { KUMA_INFOXTRACE("attachFd, with ssl, fd="<<fd<<", flags="<<flags<<", state="<<getState()); if(getState() != ST_IDLE) { KUMA_ERRXTRACE("attachFd, invalid state, state="<<getState()); return KUMA_ERROR_INVALID_STATE; } fd_ = fd; flags_ = flags; setSocketOption(); setState(ST_OPEN); if(SslEnabled()) { if (ssl) { ssl_handler_ = new SslHandler(); ssl_handler_->attachSsl(ssl); } else { int ret = startSslHandshake(true); if(ret != KUMA_ERROR_NOERR) { return ret; } } } loop_->registerFd(fd_, KUMA_EV_NETWORK, [this] (uint32_t ev) { ioReady(ev); }); registered_ = true; return KUMA_ERROR_NOERR; }
int TcpSocketImpl::startSslHandshake(bool is_server) { #ifdef KUMA_HAS_OPENSSL KUMA_INFOXTRACE("startSslHandshake, is_server="<<is_server<<", fd="<<fd_<<", state="<<getState()); if(INVALID_FD == fd_) { KUMA_ERRXTRACE("startSslHandshake, invalid fd"); return KUMA_ERROR_INVALID_STATE; } if(ssl_handler_) { ssl_handler_->close(); delete ssl_handler_; ssl_handler_ = nullptr; } ssl_handler_ = new SslHandler(); int ret = ssl_handler_->attachFd(fd_, is_server); if(ret != KUMA_ERROR_NOERR) { return ret; } flags_ |= FLAG_HAS_SSL; SslHandler::SslState ssl_state = ssl_handler_->doSslHandshake(); if(SslHandler::SslState::SSL_ERROR == ssl_state) { return KUMA_ERROR_SSL_FAILED; } return KUMA_ERROR_NOERR; #else return KUMA_ERROR_UNSUPPORT; #endif }
int TcpSocketImpl::attachFd(SOCKET_FD fd, uint32_t flags) { KUMA_INFOXTRACE("attachFd, fd="<<fd<<", flags="<<flags<<", state="<<getState()); if(getState() != ST_IDLE) { KUMA_ERRXTRACE("attachFd, invalid state, state="<<getState()); return KUMA_ERROR_INVALID_STATE; } flags_ = flags; #ifndef KUMA_HAS_OPENSSL if (SslEnabled()) { KUMA_ERRXTRACE("attachFd, OpenSSL is disabled"); return KUMA_ERROR_UNSUPPORT; } #endif fd_ = fd; setSocketOption(); setState(ST_OPEN); #ifdef KUMA_HAS_OPENSSL if(SslEnabled()) { int ret = startSslHandshake(true); if(ret != KUMA_ERROR_NOERR) { return ret; } } #endif loop_->registerFd(fd_, KUMA_EV_NETWORK, [this] (uint32_t ev) { ioReady(ev); }); registered_ = true; return KUMA_ERROR_NOERR; }
int TcpSocketImpl::close() { KUMA_INFOXTRACE("close, state="<<getState()); loop_->runInEventLoopSync([this] { cleanup(); setState(ST_CLOSED); }); return KUMA_ERROR_NOERR; }
void WebSocketImpl::onStateOpen() { KUMA_INFOXTRACE("onStateOpen"); setState(STATE_OPEN); if(is_server_) { if(cb_write_) cb_write_(0); } else { if(cb_connect_) cb_connect_(0); } }
int TcpSocketImpl::detachFd(SOCKET_FD &fd) { KUMA_INFOXTRACE("detachFd, fd="<<fd_<<", state="<<getState()); fd = fd_; fd_ = INVALID_FD; if(registered_) { registered_ = false; loop_->unregisterFd(fd, false); } cleanup(); setState(ST_CLOSED); return KUMA_ERROR_NOERR; }
void TcpSocketImpl::onConnect(int err) { KUMA_INFOXTRACE("onConnect, err="<<err<<", state="<<getState()); if(0 == err) { setState(ST_OPEN); #ifdef KUMA_HAS_OPENSSL if(SslEnabled()) { err = startSslHandshake(false); if(KUMA_ERROR_NOERR == err && ssl_handler_->getState() == SslHandler::SslState::SSL_HANDSHAKE) { return; // continue to SSL handshake } } #endif } if(err != KUMA_ERROR_NOERR) { cleanup(); setState(ST_CLOSED); } EventCallback cb_connect = std::move(cb_connect_); if(cb_connect) cb_connect(err); }
void EventLoop::Impl::loop(uint32_t max_wait_ms) { while (!stop_loop_) { loopOnce(max_wait_ms); } processTasks(); while (pending_objects_) { auto obj = pending_objects_; pending_objects_ = pending_objects_->next_; obj->onLoopExit(); } { LockGuard g(obs_mutex_); ObserverCallback cb; while (obs_queue_.dequeue(cb)) { cb(LoopActivity::EXIT); } } KUMA_INFOXTRACE("loop, stopped"); }
int TcpSocketImpl::connect_i(const char* host, uint16_t port, uint32_t timeout) { KUMA_INFOXTRACE("connect_i, host="<<host<<", port="<<port<<", this="<<this); #ifndef KUMA_HAS_OPENSSL if (SslEnabled()) { KUMA_ERRXTRACE("connect_i, OpenSSL is disabled"); return KUMA_ERROR_UNSUPPORT; } #endif sockaddr_storage ss_addr = {0}; struct addrinfo hints = {0}; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; // will block 10 seconds in some case if not set AI_ADDRCONFIG if(km_set_sock_addr(host, port, &hints, (struct sockaddr*)&ss_addr, sizeof(ss_addr)) != 0) { return KUMA_ERROR_INVALID_PARAM; } if(INVALID_FD == fd_) { fd_ = ::socket(ss_addr.ss_family, SOCK_STREAM, 0); if(INVALID_FD == fd_) { KUMA_ERRXTRACE("connect_i, socket failed, err="<<getLastError()); return KUMA_ERROR_FAILED; } } setSocketOption(); 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 = ::connect(fd_, (struct sockaddr *)&ss_addr, addr_len); if(0 == ret) { setState(ST_CONNECTING); // wait for writable event } else if(ret < 0 && #ifdef KUMA_OS_WIN WSAEWOULDBLOCK #else EINPROGRESS #endif == getLastError()) { setState(ST_CONNECTING); } else { KUMA_ERRXTRACE("connect_i, error, fd="<<fd_<<", err="<<getLastError()); cleanup(); setState(ST_CLOSED); return KUMA_ERROR_FAILED; } #if defined(KUMA_OS_LINUX) || defined(KUMA_OS_MAC) socklen_t len = sizeof(ss_addr); #else int len = sizeof(ss_addr); #endif char local_ip[128] = {0}; uint16_t local_port = 0; ret = getsockname(fd_, (struct sockaddr*)&ss_addr, &len); if(ret != -1) { km_get_sock_addr((struct sockaddr*)&ss_addr, sizeof(ss_addr), local_ip, sizeof(local_ip), &local_port); } KUMA_INFOXTRACE("connect_i, fd="<<fd_<<", local_ip="<<local_ip <<", local_port="<<local_port<<", state="<<getState()); loop_->registerFd(fd_, KUMA_EV_NETWORK, [this] (uint32_t ev) { ioReady(ev); }); registered_ = true; return KUMA_ERROR_NOERR; }
void EventLoop::Impl::stop() { KUMA_INFOXTRACE("stop"); stop_loop_ = true; poll_->notify(); }