| 219 | } |
| 220 | |
| 221 | void |
| 222 | Http3App::_handle_uni_stream_on_read_ready(int /* event */, VIO *vio) |
| 223 | { |
| 224 | Http3ErrorUPtr error = Http3ErrorUPtr(nullptr); |
| 225 | Http3StreamType type; |
| 226 | QUICStreamVCAdapter *adapter = static_cast<QUICStreamVCAdapter *>(vio->vc_server); |
| 227 | auto it = this->_remote_uni_stream_map.find(adapter->stream().id()); |
| 228 | if (it == this->_remote_uni_stream_map.end()) { |
| 229 | // Set uni stream suitable app (HTTP/3 or QPACK) by stream type |
| 230 | uint8_t buf; |
| 231 | vio->get_reader()->read(&buf, 1); |
| 232 | type = Http3Stream::type(&buf); |
| 233 | |
| 234 | Dbg(dbg_ctl, "[%" PRIu64 "] %s stream is opened", adapter->stream().id(), Http3DebugNames::stream_type(type)); |
| 235 | |
| 236 | auto ret = this->_remote_uni_stream_map.insert(std::make_pair(adapter->stream().id(), type)); |
| 237 | if (!ret.second) { |
| 238 | // A stream for the type is already exists |
| 239 | // TODO Return an error |
| 240 | } |
| 241 | } else { |
| 242 | type = it->second; |
| 243 | } |
| 244 | |
| 245 | switch (type) { |
| 246 | case Http3StreamType::CONTROL: { |
| 247 | if (this->_control_stream_id == 0) { |
| 248 | this->_control_stream_id = adapter->stream().id(); |
| 249 | } else if (this->_control_stream_id != adapter->stream().id()) { |
| 250 | error = std::make_unique<Http3Error>(Http3ErrorClass::CONNECTION, Http3ErrorCode::H3_STREAM_CREATION_ERROR, |
| 251 | "Only one control stream per peer is permitted"); |
| 252 | Dbg(dbg_ctl, "CONTROL stream [%" PRIu64 "] error: %hu, %s", this->_control_stream_id, error->get_code(), error->msg); |
| 253 | break; |
| 254 | } |
| 255 | uint64_t nread = 0; |
| 256 | error = this->_control_stream_dispatcher.on_read_ready(adapter->stream().id(), type, *vio->get_reader(), nread); |
| 257 | if (error && error->cls != Http3ErrorClass::UNDEFINED) { |
| 258 | Dbg(dbg_ctl, "CONTROL stream [%" PRIu64 "] error: %hu, %s", this->_control_stream_id, error->get_code(), error->msg); |
| 259 | } |
| 260 | // The sender MUST NOT close the control stream, and the receiver MUST NOT request that the sender close the control stream. |
| 261 | // If either control stream is closed at any point, this MUST be treated as a connection error of type |
| 262 | // H3_CLOSED_CRITICAL_STREAM. |
| 263 | break; |
| 264 | } |
| 265 | case Http3StreamType::PUSH: { |
| 266 | error = |
| 267 | std::make_unique<Http3Error>(Http3ErrorClass::CONNECTION, Http3ErrorCode::H3_STREAM_CREATION_ERROR, "Only servers can push"); |
| 268 | Dbg(dbg_ctl, "PUSH stream [%" PRIu64 "] error: %hu, %s", adapter->stream().id(), error->get_code(), error->msg); |
| 269 | // if a server receives a client-initiated push stream, this MUST be treated as a connection error of type |
| 270 | // H3_STREAM_CREATION_ERROR |
| 271 | break; |
| 272 | } |
| 273 | case Http3StreamType::QPACK_ENCODER: |
| 274 | case Http3StreamType::QPACK_DECODER: { |
| 275 | this->_set_qpack_stream(type, adapter); |
| 276 | break; |
| 277 | } |
| 278 | case Http3StreamType::UNKNOWN: { |
no test coverage detected