virtual void startup() { thread_accepter_.start(new _ESQ accepter(setter_, dispatcher_, handler_), this); thread_transceiver_.start(new _ESQ transceiver(setter_, dispatcher_, handler_), this); thread_recycler_.start(new _ESQ recycler(setter_, dispatcher_, handler_), this); thread_destroyer_.start(new _ESQ destroyer(setter_, dispatcher_, handler_), this); processer_pools_.start(this); }
int ngrest_server_dispatch(ngrest_server_request* request, ngrest_mod_callbacks callbacks) { try { ngrest::MessageContext context; context.pool = pooler.obtain(); PoolRecycler recycler(context.pool); context.engine = &engine; context.transport = &transport; context.request = context.pool->alloc<ngrest::HttpRequest>(); context.response = context.pool->alloc<ngrest::HttpResponse>(); context.response->poolBody = pooler.obtain(65536); // 64 KB chunks for output buffer ngrest::HttpRequest* httpRequest = static_cast<ngrest::HttpRequest*>(context.request); ngrest::HttpResponse* httpResponse = static_cast<ngrest::HttpResponse*>(context.response); ModMessageCallback messageCallback(httpResponse); context.callback = &messageCallback; httpRequest->setMethod(request->method); httpRequest->path = request->uri; httpRequest->clientHost = request->clientHost; httpRequest->clientPort = request->clientPort; HeaderIterateContext itCtx = { httpRequest, nullptr, &context }; callbacks.iterate_request_headers(request->req, &itCtx, [](void* context, const char* name, const char* value) { HeaderIterateContext* itCtx = reinterpret_cast<HeaderIterateContext*>(context); ngrest::Header* header = itCtx->context->pool->alloc<ngrest::Header>(); char* headerName = itCtx->context->pool->putCString(name, true); toLowerCase(headerName); header->name = headerName; header->value = value; if (itCtx->lastHeader == nullptr) { itCtx->httpRequest->headers = header; } else { itCtx->lastHeader->next = header; } itCtx->lastHeader = header; return 1; }); if (request->hasBody) { ngrest::MemPool* poolRequest = pooler.obtain(65536); PoolRecycler recycler(poolRequest); if (request->bodySize > 0) poolRequest->reserve(request->bodySize + 1); // '\0' const int64_t chunkSize = poolRequest->getChunkSize(); int64_t bufferSize = chunkSize; int64_t read = 0; int64_t total = 0; char* buffer = poolRequest->grow(chunkSize); for (;;) { read = callbacks.read_block(request->req, buffer, bufferSize); if (read < 0) { callbacks.write_block(request->req, "Failed to read block!", 21); return 500; } if (!request->bodySize && !read) // eof while body size unknown. stopping read break; buffer += read; bufferSize -= read; if (bufferSize == 0) { buffer = poolRequest->grow(chunkSize); bufferSize = chunkSize; } total += read; if (request->bodySize && total >= request->bodySize) break; // according to request->bodySize the whole request is read } poolRequest->shrinkLastChunk(bufferSize); ngrest::MemPool::Chunk* body = poolRequest->flatten(); context.request->body = body->buffer; context.request->bodySize = body->size; engine.dispatchMessage(&context); // poolRequest will be recycled ouside this scope } else { engine.dispatchMessage(&context); } for (const ngrest::Header* header = httpResponse->headers; header; header = header->next) { if (!strcmp(header->name, "Content-Type")) { callbacks.set_content_type(request->req, header->value); } else { callbacks.set_response_header(request->req, header->name, header->value); } } ngrest_server_write_response(request, callbacks, httpResponse->poolBody); callbacks.finalize_response(request->req, httpResponse->statusCode); return 0; } catch (const std::exception& e) { const char* error = e.what(); ngrest::LogWarning() << error; callbacks.write_block(request->req, error, strlen(error)); } catch (...) { ngrest::LogWarning() << "Unknown exception raised"; callbacks.write_block(request->req, "Internal server error", 22); } return 500; }
void Output::run() { mutex()->lock (); if (!bytes_per_millisecond_) { qWarning("Output: invalid audio parameters"); mutex()->unlock (); return; } mutex()->unlock (); bool done = false; Buffer *b = 0; qint64 l, m = 0; dispatch(PlayerUtils::Playing); while (!done) { mutex()->lock(); recycler()->mutex()->lock(); done = user_stop_; while (!done && (recycler()->empty() || pause_)) { mutex()->unlock(); recycler()->cond()->wakeOne(); recycler()->cond()->wait(recycler()->mutex()); mutex()->lock (); done = user_stop_; } status(); if (!b) { b = recycler()->next(); if (b && b->rate) { kbps_ = b->rate; } } recycler()->cond()->wakeOne(); recycler()->mutex()->unlock(); mutex()->unlock(); if (b) { changeVolume(b->data, b->nbytes, channels_); l = 0; m = 0; if (is_seeking_) { enable(b->seeking_finished); is_seeking_ = !b->seeking_finished; } while (l < b->nbytes) { m = writeAudio(b->data + l, b->nbytes - l); if(m >= 0) { total_written_ += m; l+= m; } else { break; } } if(m < 0) { break; } } mutex()->lock(); //force buffer change recycler()->mutex()->lock (); recycler()->done(); recycler()->mutex()->unlock(); b = 0; mutex()->unlock(); } mutex()->lock (); //write remaining data if(finish_) { flush(); qDebug("Output: total written %lld", total_written_); } dispatch(PlayerUtils::Stopped); mutex()->unlock(); }