<%args> objectID; int resourceID = 0; <%pre> #include #include #include #include #include "../include/tools.h" #include "../include/media/mediaManager.h" #include "../include/server.h" #include #include #include using namespace upnp; <# int doRequest(tnt::HttpReply reply, tnt::HttpRequest request, std::string objectID, int resourceID) { #> <%cpp> if(objectID.empty()){ reply.out() << "Object ID missing"; return HTTP_BAD_REQUEST; } cMediaServer* server = cMediaServer::GetInstance(); cMediaManager& manager = server->GetManager(); boost::shared_ptr streamer(manager.GetResourceStreamer(objectID, resourceID)); if(!streamer.get()){ reply.out() << "Object ID not found or invalid"; return HTTP_NOT_FOUND; } int code = HTTP_OK; reply.setContentType(streamer->GetContentType()); reply.setHeader("friendlyName.dlna.org ", server->GetServerDescription().friendlyName); reply.setHeader("contentFeatures.dlna.org ", streamer->GetContentFeatures()); reply.setHeader("transferMode.dlna.org ", streamer->GetTransferMode(reply.getHeader("transferMode.dlna.org"))); if(streamer->GetContentLength() > 0){ reply.setContentLengthHeader(streamer->GetContentLength()); if(streamer->Seekable()) reply.setHeader("Accept-Ranges", "bytes"); } if(!request.isMethodHEAD()){ if(!streamer->Open()){ code = HTTP_INTERNAL_SERVER_ERROR; goto ret; } int offset = 0, length = std::numeric_limits::max(); bool hasRange = false; if(streamer->Seekable() && streamer->GetContentLength() > 0){ if(request.hasHeader("Range")){ std::string rangeRequest = request.getHeader("Range"); if(rangeRequest.find("bytes=",0) == 0){ int minus = rangeRequest.find_first_of('-',6); offset = atoi(rangeRequest.substr(6, minus - 6).c_str()); length = atoi(rangeRequest.substr(minus + 1).c_str()) - offset; if(length == 0) length = std::numeric_limits::max(); hasRange = (offset == 0 && length == std::numeric_limits::max()) ? false : true; } } if(!streamer->Seek(offset, SEEK_SET)){ code = HTTP_INTERNAL_SERVER_ERROR; goto ret; } } char buffer[KB(16)]; ssize_t bytesRead = 0; size_t totalBytesRead = 0; size_t toRead = std::min(length, sizeof(buffer)); while (0 < (bytesRead = streamer->Read(buffer, toRead)) && length > 0) { reply.out().write(buffer, bytesRead); if (!reply.out()) { code = HTTP_GONE; goto ret; } length -= bytesRead; totalBytesRead += bytesRead; toRead = std::min(length, sizeof(buffer)); } reply.setContentLengthHeader(totalBytesRead); if ((bytesRead < 0 || length <= 0) && hasRange) { std::stringstream ss; ss << "bytes " << offset << "-" << offset + totalBytesRead << "/" << streamer->GetContentLength(); reply.setHeader("Content-Range", ss.str()); code = HTTP_PARTIAL_CONTENT; goto ret; } } ret: streamer->Close(); //reply.out() << std::flush; return code; <# } #>