off_t __plseek(int fd, off_t offset, int whence) { idStream *is = getStreamData(getpid(), fd); if(!is) return -1; UNUSED(offset); UNUSED(whence); return /*lseek(is->fd, offset, whence)*/-1; }
int createPipe(int size, int flags) { Spipe *p = newSpipeData(); if(!p) return -1; int pid = getpid(); enterProcessCriticalCode(pid); int fd = open_fd(); if(fd < 0) return fd; idStream *is = getStreamData(getpid(), fd); createMutex(&p->locker); p->memory = malloc(size+4); p->seek = 0; p->offset = 0; p->size = size; p->ready_read_wid = createAdvWaitCond("waiter", 0); p->ready_write_wid = createAdvWaitCond("waiter", 0); p->fully_flushed_wid = createAdvWaitCond("waiter", 0); p->fully_empty_wid = createAdvWaitCond("waiter", 0); p->flags = flags; is->fd = p->id; is->type = PIPE_STREAM; is->mode = O_RDWR; is->pid = pid; is->read = __pread; is->write = __pwrite; is->flush = __pflush; is->lseek = __plseek; is->close = __pclose; wakeOneWaitCond(p->ready_write_wid); leaveProcessCriticalCode(pid); return fd; }
ServerProtocol *ServerHttp2::process() { struct Request req; req.timeout = std::chrono::milliseconds(15000); req.protocol_variant = Transfer::ProtocolVariant::HTTP_2; Http2::ConnectionData conn; sendEmptySettings( this->sock, req.timeout, conn, Http2::FrameFlag::EMPTY ); if (getClientPreface(this->sock, req.timeout) == false) { constexpr uint32_t last_stream_id = 0; goAway( this->sock, req.timeout, conn, last_stream_id, Http2::ErrorCode::PROTOCOL_ERROR ); return this; } conn.client_settings = Http2::ConnectionSettings::defaultSettings(); conn.server_settings = Http2::ConnectionSettings::defaultSettings(); std::vector<char> buf(conn.server_settings.max_frame_size); std::unordered_map<uint32_t, Http2::IncStream> streams { { 0, Http2::IncStream(0, conn) } }; Http2::IncStream &primary = streams.find(0)->second; this->stream = &primary; size_t streams_process_count = 0; uint32_t last_stream_id = 0; Http2::FrameMeta meta {}; long read_size = 0; do { if (getNextHttp2FrameMeta(this->sock, req.timeout, buf, meta, read_size) == false) { break; } const uint8_t *addr = reinterpret_cast<const uint8_t *>( buf.data() ) + Http2::FRAME_HEADER_SIZE; const uint8_t *end = addr + meta.length; if (meta.stream_id > last_stream_id) { last_stream_id = meta.stream_id; } Http2::IncStream &stream = getStreamData(streams, meta.stream_id, conn); if (Http2::StreamState::CLOSED == stream.state) { rstStream(this->sock, req.timeout, stream, Http2::ErrorCode::STREAM_CLOSED); continue; } if (meta.type != Http2::FrameType::CONTINUATION) { stream.frame_type = meta.type; } Http2::ErrorCode result = Http2::ErrorCode::NO_ERROR; switch (stream.frame_type) { case Http2::FrameType::DATA: { result = parseHttp2Data(meta, stream, addr, end); stream.window_size_inc -= meta.length; if (stream.reserved) { DataVariant::DataReceiver *dr = reinterpret_cast<DataVariant::DataReceiver *>(stream.reserved); if (stream.window_size_inc - long(conn.server_settings.max_frame_size) <= 0) { size_t update_size = conn.server_settings.initial_window_size + (dr->full_size - dr->recv_total) - size_t(stream.window_size_inc); if (update_size > Http2::MAX_WINDOW_UPDATE) { update_size = Http2::MAX_WINDOW_UPDATE; } sendWindowUpdate(this->sock, req.timeout, stream, uint32_t(update_size) ); sendWindowUpdate(this->sock, req.timeout, primary, uint32_t(update_size) ); stream.window_size_inc += update_size; } } break; } case Http2::FrameType::HEADERS: { result = parseHttp2Headers(meta, stream, addr, end); if (meta.flags & Http2::FrameFlag::END_HEADERS) { Transfer::request_data *rd = static_cast<Transfer::request_data *>(&stream); stream.reserved = createDataReceiver(rd, this->settings.variants); if (stream.reserved) { DataVariant::DataReceiver *dr = reinterpret_cast<DataVariant::DataReceiver *>(stream.reserved); dr->reserved = new std::string(); } } break; } case Http2::FrameType::PRIORITY: result = Http2::ErrorCode::NO_ERROR; break; case Http2::FrameType::RST_STREAM: result = parseHttp2rstStream(meta, stream, addr, end); break; case Http2::FrameType::SETTINGS: { result = parseHttp2Settings(meta, stream, addr, end); if (Http2::ErrorCode::NO_ERROR == result && (meta.flags & Http2::FrameFlag::ACK) == false) { conn.decoding_dynamic_table.changeHeaderTableSize(conn.client_settings.header_table_size); conn.decoding_dynamic_table.changeMaxHeaderListSize(conn.client_settings.max_header_list_size); sendEmptySettings(this->sock, req.timeout, conn, Http2::FrameFlag::ACK); } break; } case Http2::FrameType::PUSH_PROMISE: result = Http2::ErrorCode::NO_ERROR; break; case Http2::FrameType::PING: { result = parseHttp2Ping(meta); if (Http2::ErrorCode::NO_ERROR == result && (meta.flags & Http2::FrameFlag::ACK) == false) { const uint64_t ping_data = *reinterpret_cast<const uint64_t *>(addr); ping(this->sock, req.timeout, conn, ping_data); } break; } case Http2::FrameType::GOAWAY: result = parseHttp2GoAway(meta, stream, addr, end); break; case Http2::FrameType::WINDOW_UPDATE: result = parseHttp2WindowUpdate(meta, stream, addr, end); break; default: result = Http2::ErrorCode::PROTOCOL_ERROR; break; } if (result != Http2::ErrorCode::NO_ERROR) { stream.state = Http2::StreamState::CLOSED; rstStream(this->sock, req.timeout, stream, result); // TODO: remove closed stream(s) from unordered map } else if ( (meta.flags & Http2::FrameFlag::END_STREAM) && meta.stream_id != 0) { stream.reserved = this->sock.get_tls_session(); sockets.lock(); sockets.emplace( std::tuple<Socket::Socket, Http2::IncStream *> { Socket::Socket(this->sock.get_handle() ), &stream } ); sockets.unlock(); this->controls.eventProcessQueue->notify(); ++streams_process_count; } } while (Http2::StreamState::CLOSED != primary.state); while (conn.sync.completed.load() < streams_process_count) { conn.sync.event.wait(); } goAway( this->sock, req.timeout, conn, last_stream_id, Http2::ErrorCode::NO_ERROR ); for (auto &pair : streams) { destroyDataReceiver(pair.second.reserved); } return this; }
int __pclose(int fd) { idStream *is = getStreamData(getpid(), fd); if(!is) return -1; return closePipe(is->fd); }
int __pflush(int fd) { idStream *is = getStreamData(getpid(), fd); if(!is) return -1; return 0; }
ssize_t __pwrite(int fd, const void *data, size_t size) { idStream *is = getStreamData(getpid(), fd); if(!is) return -1; return writePipe(is->fd, data, size); }
ssize_t __pread(int fd, void *data, size_t size) { idStream *is = getStreamData(getpid(), fd); if(!is) return -1; return readPipe(is->fd, data, size); }