private static HttpResponse addEtag( HttpRequest nettyRequest, HttpResponse httpResponse, File file) { if (Play.mode == Play.Mode.DEV) { httpResponse.setHeader(CACHE_CONTROL, "no-cache"); } else { String maxAge = Play.configuration.getProperty("http.cacheControl", "3600"); if (maxAge.equals("0")) { httpResponse.setHeader(CACHE_CONTROL, "no-cache"); } else { httpResponse.setHeader(CACHE_CONTROL, "max-age=" + maxAge); } } boolean useEtag = Play.configuration.getProperty("http.useETag", "true").equals("true"); long last = file.lastModified(); final String etag = "\"" + last + "-" + file.hashCode() + "\""; if (!isModified(etag, last, nettyRequest)) { if (nettyRequest.getMethod().equals(HttpMethod.GET)) { httpResponse.setStatus(HttpResponseStatus.NOT_MODIFIED); } if (useEtag) { httpResponse.setHeader(ETAG, etag); } } else { httpResponse.setHeader(LAST_MODIFIED, Utils.getHttpDateFormatter().format(new Date(last))); if (useEtag) { httpResponse.setHeader(ETAG, etag); } } return httpResponse; }
public static boolean isModified(String etag, long last, HttpRequest nettyRequest) { if (nettyRequest.containsHeader(IF_NONE_MATCH)) { final String browserEtag = nettyRequest.getHeader(IF_NONE_MATCH); if (browserEtag.equals(etag)) { return false; } return true; } if (nettyRequest.containsHeader(IF_MODIFIED_SINCE)) { final String ifModifiedSince = nettyRequest.getHeader(IF_MODIFIED_SINCE); if (!StringUtils.isEmpty(ifModifiedSince)) { try { Date browserDate = Utils.getHttpDateFormatter().parse(ifModifiedSince); if (browserDate.getTime() >= last) { return false; } } catch (ParseException ex) { Logger.warn("Can't parse HTTP date", ex); } return true; } } return true; }
protected static void addToRequest(HttpRequest nettyRequest, Request request) { for (String key : nettyRequest.getHeaderNames()) { Http.Header hd = new Http.Header(); hd.name = key.toLowerCase(); hd.values = new ArrayList<String>(); for (String next : nettyRequest.getHeaders(key)) { hd.values.add(next); } request.headers.put(hd.name, hd); } String value = nettyRequest.getHeader(COOKIE); if (value != null) { Set<Cookie> cookies = new CookieDecoder().decode(value); if (cookies != null) { for (Cookie cookie : cookies) { Http.Cookie playCookie = new Http.Cookie(); playCookie.name = cookie.getName(); playCookie.path = cookie.getPath(); playCookie.domain = cookie.getDomain(); playCookie.secure = cookie.isSecure(); playCookie.value = cookie.getValue(); playCookie.httpOnly = cookie.isHttpOnly(); request.cookies.put(playCookie.name, playCookie); } } } }
@Override public void messageReceived(ChannelHandlerContext context, MessageEvent e) throws Exception { if (e.getMessage() instanceof HttpRequest) { HttpRequest message = (HttpRequest) e.getMessage(); HttpResponse response; if (new QueryStringDecoder(message.getUri()).getPath().equals(START_TIME_PATH)) { response = new DefaultHttpResponse(HTTP_1_1, OK); response.setHeader("Access-Control-Allow-Origin", "*"); response.setContent( ChannelBuffers.copiedBuffer(getApplicationStartTime(), CharsetUtil.US_ASCII)); } else { response = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND); } context.getChannel().write(response).addListener(ChannelFutureListener.CLOSE); } }
protected static void writeResponse( ChannelHandlerContext ctx, Response response, HttpResponse nettyResponse, HttpRequest nettyRequest) { Logger.trace("writeResponse: begin"); byte[] content = null; final boolean keepAlive = isKeepAlive(nettyRequest); if (nettyRequest.getMethod().equals(HttpMethod.HEAD)) { content = new byte[0]; } else { content = response.out.toByteArray(); } ChannelBuffer buf = ChannelBuffers.copiedBuffer(content); nettyResponse.setContent(buf); if (keepAlive) { // Add 'Content-Length' header only for a keep-alive connection. Logger.trace("writeResponse: content length [" + response.out.size() + "]"); setContentLength(nettyResponse, response.out.size()); } ChannelFuture f = ctx.getChannel().write(nettyResponse); // Decide whether to close the connection or not. if (!keepAlive) { // Close the connection when the whole content is written out. f.addListener(ChannelFutureListener.CLOSE); } Logger.trace("writeResponse: end"); }
private void writeResponse( ChannelHandlerContext ctx, MessageEvent e, RequestV2 request, InetAddress ia) { // Decide whether to close the connection or not. boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase( nettyRequest.headers().get(HttpHeaders.Names.CONNECTION)) || nettyRequest.getProtocolVersion().equals(HttpVersion.HTTP_1_0) && !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase( nettyRequest.headers().get(HttpHeaders.Names.CONNECTION)); // Build the response object. HttpResponse response; if (request.getLowRange() != 0 || request.getHighRange() != 0) { response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.PARTIAL_CONTENT); } else { String soapAction = nettyRequest.headers().get("SOAPACTION"); if (soapAction != null && soapAction.contains("X_GetFeatureList")) { LOGGER.debug("Invalid action in SOAPACTION: " + soapAction); response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); } else { response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); } } StartStopListenerDelegate startStopListenerDelegate = new StartStopListenerDelegate(ia.getHostAddress()); // Attach it to the context so it can be invoked if connection is reset unexpectedly ctx.setAttachment(startStopListenerDelegate); try { request.answer(response, e, close, startStopListenerDelegate); } catch (IOException e1) { LOGGER.trace("HTTP request V2 IO error: " + e1.getMessage()); // note: we don't call stop() here in a finally block as // answer() is non-blocking. we only (may) need to call it // here in the case of an exception. it's a no-op if it's // already been called startStopListenerDelegate.stop(); } }
void saveExceededSizeError(HttpRequest nettyRequest, Request request, Response response) { String warning = nettyRequest.getHeader(HttpHeaders.Names.WARNING); String length = nettyRequest.getHeader(HttpHeaders.Names.CONTENT_LENGTH); if (warning != null) { Logger.trace("saveExceededSizeError: begin"); try { StringBuilder error = new StringBuilder(); error.append("\u0000"); // Cannot put warning which is play.netty.content.length.exceeded // as Key as it will result error when printing error error.append("play.netty.maxContentLength"); error.append(":"); String size = null; try { size = JavaExtensions.formatSize(Long.parseLong(length)); } catch (Exception e) { size = length + " bytes"; } error.append(Messages.get(warning, size)); error.append("\u0001"); error.append(size); error.append("\u0000"); if (request.cookies.get(Scope.COOKIE_PREFIX + "_ERRORS") != null && request.cookies.get(Scope.COOKIE_PREFIX + "_ERRORS").value != null) { error.append(request.cookies.get(Scope.COOKIE_PREFIX + "_ERRORS").value); } String errorData = URLEncoder.encode(error.toString(), "utf-8"); Http.Cookie c = new Http.Cookie(); c.value = errorData; c.name = Scope.COOKIE_PREFIX + "_ERRORS"; request.cookies.put(Scope.COOKIE_PREFIX + "_ERRORS", c); Logger.trace("saveExceededSizeError: end"); } catch (Exception e) { throw new UnexpectedException("Error serialization problem", e); } } }
public File get() throws IOException { ClientBootstrap bootstrap = new ClientBootstrap( new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); bootstrap.setOption("connectTimeoutMillis", 5000L); // set 5 sec bootstrap.setOption("receiveBufferSize", 1048576); // set 1M ChannelPipelineFactory factory = new HttpClientPipelineFactory(file); bootstrap.setPipelineFactory(factory); ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)); // Wait until the connection attempt succeeds or fails. Channel channel = future.awaitUninterruptibly().getChannel(); if (!future.isSuccess()) { bootstrap.releaseExternalResources(); throw new IOException(future.getCause()); } String query = uri.getPath() + (uri.getQuery() != null ? "?" + uri.getQuery() : ""); // Prepare the HTTP request. HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, query); request.setHeader(HttpHeaders.Names.HOST, host); LOG.info("Fetch: " + request.getUri()); request.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); request.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP); // Send the HTTP request. channel.write(request); // Wait for the server to close the connection. channel.getCloseFuture().awaitUninterruptibly(); // Shut down executor threads to exit. bootstrap.releaseExternalResources(); return file; }
@Override public void handle(HttpRequest request, Channel channel) throws Exception { // 设置调用方ip,X-Forwarded-For 是使用了代理(如nginx)会附加在HTTP头域上的 if (request.headers().contains("X-Forwarded-For")) { request.headers().set(Names.HOST, request.headers().get("X-Forwarded-For")); } else { InetSocketAddress insocket = (InetSocketAddress) channel.getRemoteAddress(); request.headers().set(Names.HOST, insocket.getAddress().getHostAddress()); } HttpResponse response = new NaviHttpResponse(request.getProtocolVersion(), HttpResponseStatus.OK); for (INaviHttpRequestListener listener : listeners) { boolean res = listener.process(request, response); log.debug(listener.getClass().getName() + " is completed!"); if (!res) { break; } } sendHttpResponse(channel, request, response); }
private void sendHttpResponse(Channel channel, HttpRequest request, HttpResponse response) { if (!channel.isOpen()) { return; } // response的内容已在各Listener中填充 response.headers().set(Names.CONTENT_LENGTH, response.getContent().readableBytes()); response.headers().set(Names.SERVER, "NAVI/1.1.4(UNIX)"); if (!HttpHeaders.isKeepAlive(request) || response.getStatus() != HttpResponseStatus.OK || ServerConfigure.isChannelClose()) { response.headers().set(Names.CONNECTION, "close"); channel.setAttachment(WRITING); ChannelFuture f = channel.write(response); f.addListener(ChannelFutureListener.CLOSE); f.addListener( new ChannelFutureListener() { public void operationComplete(ChannelFuture f) throws Exception { if (!f.isSuccess()) { log.error(f.getCause().getMessage(), f.getCause()); } } }); } else { if (request.getProtocolVersion() == HttpVersion.HTTP_1_0) { response.headers().add(Names.CONNECTION, "Keep-Alive"); } channel.setAttachment(WRITING); ChannelFuture f = channel.write(response); f.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); f.addListener( new ChannelFutureListener() { public void operationComplete(ChannelFuture f) throws Exception { if (!f.isSuccess()) { log.error(f.getCause().getMessage(), f.getCause()); } } }); } }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { HttpRequest request = (HttpRequest) e.getMessage(); if (request.getContent().readableBytes() == 0) { BaseTransport.respond(e.getChannel(), INTERNAL_SERVER_ERROR, "Payload expected."); return; } transportMetrics.messagesReceived.mark(); transportMetrics.messagesReceivedSize.update(request.getContent().readableBytes()); // logger.debug("Received {}", request.getContent().toString(CharsetUtil.UTF_8)); String contentTypeHeader = request.getHeader(CONTENT_TYPE); if (contentTypeHeader == null) { contentTypeHeader = BaseTransport.CONTENT_TYPE_PLAIN; } String decodedContent; if (BaseTransport.CONTENT_TYPE_FORM.equals(contentTypeHeader)) { QueryStringDecoder decoder = new QueryStringDecoder("?" + request.getContent().toString(CharsetUtil.UTF_8)); List<String> d = decoder.getParameters().get("d"); if (d == null) { BaseTransport.respond(e.getChannel(), INTERNAL_SERVER_ERROR, "Payload expected."); return; } decodedContent = d.get(0); } else { decodedContent = request.getContent().toString(CharsetUtil.UTF_8); } if (decodedContent.length() == 0) { BaseTransport.respond(e.getChannel(), INTERNAL_SERVER_ERROR, "Payload expected."); return; } String[] messages = MAPPER.readValue(decodedContent, String[].class); for (String message : messages) { SockJsMessage jsMessage = new SockJsMessage(message); ctx.sendUpstream(new UpstreamMessageEvent(e.getChannel(), jsMessage, e.getRemoteAddress())); } if (isJsonpEnabled) { BaseTransport.respond(e.getChannel(), OK, "ok"); } else { BaseTransport.respond(e.getChannel(), NO_CONTENT, ""); } }
public Request parseRequest(ChannelHandlerContext ctx, HttpRequest nettyRequest) throws Exception { Logger.trace("parseRequest: begin"); Logger.trace("parseRequest: URI = " + nettyRequest.getUri()); int index = nettyRequest.getUri().indexOf("?"); String querystring = ""; String uri = nettyRequest.getUri(); // Remove domain and port from URI if it's present. if (uri.startsWith("http://") || uri.startsWith("https://")) { // Begins searching / after 9th character (last / of https://) uri = uri.substring(uri.indexOf("/", 9)); } String path = URLDecoder.decode(uri, "UTF-8"); if (index != -1) { path = URLDecoder.decode(uri.substring(0, index), "UTF-8"); querystring = uri.substring(index + 1); } final Request request = new Request(); request.remoteAddress = getRemoteIPAddress(ctx); request.method = nettyRequest.getMethod().getName(); request.path = path; request.querystring = querystring; final String contentType = nettyRequest.getHeader(CONTENT_TYPE); if (contentType != null) { request.contentType = contentType.split(";")[0].trim().toLowerCase(); } else { request.contentType = "text/html"; } if (nettyRequest.getHeader("X-HTTP-Method-Override") != null) { request.method = nettyRequest.getHeader("X-HTTP-Method-Override").intern(); } ChannelBuffer b = nettyRequest.getContent(); if (b instanceof FileChannelBuffer) { FileChannelBuffer buffer = (FileChannelBuffer) b; // An error occurred Integer max = Integer.valueOf(Play.configuration.getProperty("play.netty.maxContentLength", "-1")); request.body = buffer.getInputStream(); if (!(max == -1 || request.body.available() < max)) { request.body = new ByteArrayInputStream(new byte[0]); } } else { ByteArrayOutputStream out = new ByteArrayOutputStream(); IOUtils.copy(new ChannelBufferInputStream(b), out); byte[] n = out.toByteArray(); request.body = new ByteArrayInputStream(n); } request.url = uri; request.host = nettyRequest.getHeader(HOST); request.isLoopback = ((InetSocketAddress) ctx.getChannel().getRemoteAddress()).getAddress().isLoopbackAddress() && request.host.matches("^127\\.0\\.0\\.1:?[0-9]*$"); if (request.host == null) { request.host = ""; request.port = 80; request.domain = ""; } else { if (request.host.contains(":")) { final String[] host = request.host.split(":"); request.port = Integer.parseInt(host[1]); request.domain = host[0]; } else { request.port = 80; request.domain = request.host; } } if (Play.configuration.containsKey("XForwardedSupport") && nettyRequest.getHeader("X-Forwarded-For") != null) { if (!Arrays.asList( Play.configuration.getProperty("XForwardedSupport", "127.0.0.1").split(",")) .contains(request.remoteAddress)) { throw new RuntimeException( "This proxy request is not authorized: " + request.remoteAddress); } else { request.secure = ("https".equals(Play.configuration.get("XForwardedProto")) || "https".equals(nettyRequest.getHeader("X-Forwarded-Proto")) || "on".equals(nettyRequest.getHeader("X-Forwarded-Ssl"))); if (Play.configuration.containsKey("XForwardedHost")) { request.host = (String) Play.configuration.get("XForwardedHost"); } else if (nettyRequest.getHeader("X-Forwarded-Host") != null) { request.host = nettyRequest.getHeader("X-Forwarded-Host"); } if (nettyRequest.getHeader("X-Forwarded-For") != null) { request.remoteAddress = nettyRequest.getHeader("X-Forwarded-For"); } } } addToRequest(nettyRequest, request); request.resolveFormat(); request._init(); Logger.trace("parseRequest: end"); return request; }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { RequestV2 request = null; RendererConfiguration renderer = null; String userAgentString = null; StringBuilder unknownHeaders = new StringBuilder(); String separator = ""; HttpRequest nettyRequest = this.nettyRequest = (HttpRequest) e.getMessage(); InetSocketAddress remoteAddress = (InetSocketAddress) e.getChannel().getRemoteAddress(); InetAddress ia = remoteAddress.getAddress(); // Is the request from our own Cling service, i.e. self-originating? boolean isSelf = ia.getHostAddress().equals(PMS.get().getServer().getHost()) && nettyRequest.headers().get(HttpHeaders.Names.USER_AGENT) != null && nettyRequest.headers().get(HttpHeaders.Names.USER_AGENT).contains("UMS/"); // Filter if required if (isSelf || filterIp(ia)) { e.getChannel().close(); LOGGER.trace( isSelf ? ("Ignoring self-originating request from " + ia + ":" + remoteAddress.getPort()) : ("Access denied for address " + ia + " based on IP filter")); return; } LOGGER.trace("Opened request handler on socket " + remoteAddress); PMS.get().getRegistry().disableGoToSleep(); request = new RequestV2(nettyRequest.getMethod().getName(), nettyRequest.getUri().substring(1)); LOGGER.trace( "Request: " + nettyRequest.getProtocolVersion().getText() + " : " + request.getMethod() + " : " + request.getArgument()); if (nettyRequest.getProtocolVersion().getMinorVersion() == 0) { request.setHttp10(true); } HttpHeaders headers = nettyRequest.headers(); // The handler makes a couple of attempts to recognize a renderer from its requests. // IP address matches from previous requests are preferred, when that fails request // header matches are attempted and if those fail as well we're stuck with the // default renderer. // Attempt 1: try to recognize the renderer by its socket address from previous requests renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(ia); // If the renderer exists but isn't marked as loaded it means it's unrecognized // by upnp and we still need to attempt http recognition here. if (renderer == null || !renderer.loaded) { // Attempt 2: try to recognize the renderer by matching headers renderer = RendererConfiguration.getRendererConfigurationByHeaders(headers.entries(), ia); } if (renderer != null) { request.setMediaRenderer(renderer); } Set<String> headerNames = headers.names(); Iterator<String> iterator = headerNames.iterator(); while (iterator.hasNext()) { String name = iterator.next(); String headerLine = name + ": " + headers.get(name); LOGGER.trace("Received on socket: " + headerLine); if (headerLine.toUpperCase().startsWith("USER-AGENT")) { userAgentString = headerLine.substring(headerLine.indexOf(':') + 1).trim(); } try { StringTokenizer s = new StringTokenizer(headerLine); String temp = s.nextToken(); if (temp.toUpperCase().equals("SOAPACTION:")) { request.setSoapaction(s.nextToken()); } else if (temp.toUpperCase().equals("CALLBACK:")) { request.setSoapaction(s.nextToken()); } else if (headerLine.toUpperCase().contains("RANGE: BYTES=")) { String nums = headerLine.substring(headerLine.toUpperCase().indexOf("RANGE: BYTES=") + 13).trim(); StringTokenizer st = new StringTokenizer(nums, "-"); if (!nums.startsWith("-")) { request.setLowRange(Long.parseLong(st.nextToken())); } if (!nums.startsWith("-") && !nums.endsWith("-")) { request.setHighRange(Long.parseLong(st.nextToken())); } else { request.setHighRange(-1); } } else if (headerLine.toLowerCase().contains("transfermode.dlna.org:")) { request.setTransferMode( headerLine .substring(headerLine.toLowerCase().indexOf("transfermode.dlna.org:") + 22) .trim()); } else if (headerLine.toLowerCase().contains("getcontentfeatures.dlna.org:")) { request.setContentFeatures( headerLine .substring(headerLine.toLowerCase().indexOf("getcontentfeatures.dlna.org:") + 28) .trim()); } else { Matcher matcher = TIMERANGE_PATTERN.matcher(headerLine); if (matcher.find()) { String first = matcher.group(1); if (first != null) { request.setTimeRangeStartString(first); } String end = matcher.group(2); if (end != null) { request.setTimeRangeEndString(end); } } else { /** * If we made it to here, none of the previous header checks matched. Unknown headers * make interesting logging info when we cannot recognize the media renderer, so keep * track of the truly unknown ones. */ boolean isKnown = false; // Try to match known headers. String lowerCaseHeaderLine = headerLine.toLowerCase(); for (String knownHeaderString : KNOWN_HEADERS) { if (lowerCaseHeaderLine.startsWith(knownHeaderString)) { isKnown = true; break; } } // It may be unusual but already known if (renderer != null) { String additionalHeader = renderer.getUserAgentAdditionalHttpHeader(); if (StringUtils.isNotBlank(additionalHeader) && lowerCaseHeaderLine.startsWith(additionalHeader)) { isKnown = true; } } if (!isKnown) { // Truly unknown header, therefore interesting. Save for later use. unknownHeaders.append(separator).append(headerLine); separator = ", "; } } } } catch (Exception ee) { LOGGER.error("Error parsing HTTP headers", ee); } } // Still no media renderer recognized? if (request.getMediaRenderer() == null) { // Attempt 3: Not really an attempt; all other attempts to recognize // the renderer have failed. The only option left is to assume the // default renderer. request.setMediaRenderer(RendererConfiguration.resolve(ia, null)); if (request.getMediaRenderer() != null) { LOGGER.trace( "Using default media renderer: " + request.getMediaRenderer().getRendererName()); if (userAgentString != null && !userAgentString.equals("FDSSDP")) { // We have found an unknown renderer LOGGER.info( "Media renderer was not recognized. Possible identifying HTTP headers: User-Agent: " + userAgentString + ("".equals(unknownHeaders.toString()) ? "" : ", " + unknownHeaders.toString())); PMS.get().setRendererFound(request.getMediaRenderer()); } } else { // If RendererConfiguration.resolve() didn't return the default renderer // it means we know via upnp that it's not really a renderer. return; } } else { if (userAgentString != null) { LOGGER.debug("HTTP User-Agent: " + userAgentString); } LOGGER.trace("Recognized media renderer: " + request.getMediaRenderer().getRendererName()); } if (nettyRequest.headers().contains(HttpHeaders.Names.CONTENT_LENGTH)) { byte data[] = new byte[(int) HttpHeaders.getContentLength(nettyRequest)]; ChannelBuffer content = nettyRequest.getContent(); content.readBytes(data); request.setTextContent(new String(data, "UTF-8")); } LOGGER.trace( "HTTP: " + request.getArgument() + " / " + request.getLowRange() + "-" + request.getHighRange()); writeResponse(ctx, e, request, ia); }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { HttpRequest request = (HttpRequest) e.getMessage(); if (request.getMethod() != GET) { sendError(ctx, METHOD_NOT_ALLOWED); return; } // Parsing the URL into key-values final Map<String, List<String>> params = new QueryStringDecoder(request.getUri()).getParameters(); final List<String> types = params.get("type"); final List<String> taskIdList = params.get("ta"); final List<String> subQueryIds = params.get("sid"); final List<String> partitionIds = params.get("p"); if (types == null || taskIdList == null || subQueryIds == null || partitionIds == null) { sendError(ctx, "Required type, taskIds, subquery Id, and partition id", BAD_REQUEST); return; } if (types.size() != 1 || subQueryIds.size() != 1) { sendError(ctx, "Required type, taskIds, subquery Id, and partition id", BAD_REQUEST); return; } final List<FileChunk> chunks = Lists.newArrayList(); String repartitionType = types.get(0); String sid = subQueryIds.get(0); String partitionId = partitionIds.get(0); List<String> taskIds = splitMaps(taskIdList); // the working dir of tajo worker for each query String queryBaseDir = queryId + "/output" + "/"; LOG.info( "PullServer request param: repartitionType=" + repartitionType + ", sid=" + sid + ", partitionId=" + partitionId + ", taskIds=" + taskIdList); String taskLocalDir = conf.get(ConfVars.WORKER_TEMPORAL_DIR.varname); if (taskLocalDir == null || taskLocalDir.equals("")) { LOG.error("Tajo local directory should be specified."); } LOG.info("PullServer baseDir: " + taskLocalDir + "/" + queryBaseDir); // if a subquery requires a range partitioning if (repartitionType.equals("r")) { String ta = taskIds.get(0); Path path = localFS.makeQualified( lDirAlloc.getLocalPathToRead( queryBaseDir + "/" + sid + "/" + ta + "/output/", conf)); String startKey = params.get("start").get(0); String endKey = params.get("end").get(0); boolean last = params.get("final") != null; FileChunk chunk; try { chunk = getFileCunks(path, startKey, endKey, last); } catch (Throwable t) { LOG.error("ERROR Request: " + request.getUri(), t); sendError(ctx, "Cannot get file chunks to be sent", BAD_REQUEST); return; } if (chunk != null) { chunks.add(chunk); } // if a subquery requires a hash repartition } else if (repartitionType.equals("h")) { for (String ta : taskIds) { Path path = localFS.makeQualified( lDirAlloc.getLocalPathToRead( queryBaseDir + "/" + sid + "/" + ta + "/output/" + partitionId, conf)); File file = new File(path.toUri()); FileChunk chunk = new FileChunk(file, 0, file.length()); chunks.add(chunk); } } else { LOG.error("Unknown repartition type: " + repartitionType); return; } // Write the content. Channel ch = e.getChannel(); if (chunks.size() == 0) { HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NO_CONTENT); ch.write(response); if (!isKeepAlive(request)) { ch.close(); } } else { FileChunk[] file = chunks.toArray(new FileChunk[chunks.size()]); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); long totalSize = 0; for (FileChunk chunk : file) { totalSize += chunk.length(); } setContentLength(response, totalSize); // Write the initial line and the header. ch.write(response); ChannelFuture writeFuture = null; for (FileChunk chunk : file) { writeFuture = sendFile(ctx, ch, chunk); if (writeFuture == null) { sendError(ctx, NOT_FOUND); return; } } // Decide whether to close the connection or not. if (!isKeepAlive(request)) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } }
private void websocketHandshake(final ChannelHandlerContext ctx, HttpRequest req, MessageEvent e) throws Exception { // Create the WebSocket handshake response. HttpResponse res = new DefaultHttpResponse( HttpVersion.HTTP_1_1, new HttpResponseStatus(101, "Web Socket Protocol Handshake")); res.addHeader(HttpHeaders.Names.UPGRADE, HttpHeaders.Values.WEBSOCKET); res.addHeader(CONNECTION, HttpHeaders.Values.UPGRADE); // Fill in the headers and contents depending on handshake method. if (req.containsHeader(SEC_WEBSOCKET_KEY1) && req.containsHeader(SEC_WEBSOCKET_KEY2)) { // New handshake method with a challenge: res.addHeader(SEC_WEBSOCKET_ORIGIN, req.getHeader(ORIGIN)); res.addHeader( SEC_WEBSOCKET_LOCATION, "ws://" + req.getHeader(HttpHeaders.Names.HOST) + req.getUri()); String protocol = req.getHeader(SEC_WEBSOCKET_PROTOCOL); if (protocol != null) { res.addHeader(SEC_WEBSOCKET_PROTOCOL, protocol); } // Calculate the answer of the challenge. String key1 = req.getHeader(SEC_WEBSOCKET_KEY1); String key2 = req.getHeader(SEC_WEBSOCKET_KEY2); int a = (int) (Long.parseLong(key1.replaceAll("[^0-9]", "")) / key1.replaceAll("[^ ]", "").length()); int b = (int) (Long.parseLong(key2.replaceAll("[^0-9]", "")) / key2.replaceAll("[^ ]", "").length()); long c = req.getContent().readLong(); ChannelBuffer input = ChannelBuffers.buffer(16); input.writeInt(a); input.writeInt(b); input.writeLong(c); try { ChannelBuffer output = ChannelBuffers.wrappedBuffer(MessageDigest.getInstance("MD5").digest(input.array())); res.setContent(output); } catch (NoSuchAlgorithmException ex) { throw new UnexpectedException(ex); } } else { // Old handshake method with no challenge: res.addHeader(WEBSOCKET_ORIGIN, req.getHeader(ORIGIN)); res.addHeader( WEBSOCKET_LOCATION, "ws://" + req.getHeader(HttpHeaders.Names.HOST) + req.getUri()); String protocol = req.getHeader(WEBSOCKET_PROTOCOL); if (protocol != null) { res.addHeader(WEBSOCKET_PROTOCOL, protocol); } } // Keep the original request Http.Request request = parseRequest(ctx, req); // Route the websocket request request.method = "WS"; Map<String, String> route = Router.route(request.method, request.path); if (!route.containsKey("action")) { // No route found to handle this websocket connection ctx.getChannel() .write(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND)); return; } // Upgrade the connection and send the handshake response. ChannelPipeline p = ctx.getChannel().getPipeline(); p.remove("aggregator"); p.replace("decoder", "wsdecoder", new WebSocketFrameDecoder()); // Connect ctx.getChannel().write(res); p.replace("encoder", "wsencoder", new WebSocketFrameEncoder()); req.setMethod(new HttpMethod("WEBSOCKET")); // Inbound Http.Inbound inbound = new Http.Inbound() { @Override public boolean isOpen() { return ctx.getChannel().isOpen(); } }; channels.put(ctx, inbound); // Outbound Http.Outbound outbound = new Http.Outbound() { final List<ChannelFuture> writeFutures = Collections.synchronizedList(new ArrayList<ChannelFuture>()); Promise<Void> closeTask; synchronized void writeAndClose(ChannelFuture writeFuture) { if (!writeFuture.isDone()) { writeFutures.add(writeFuture); writeFuture.addListener( new ChannelFutureListener() { public void operationComplete(ChannelFuture cf) throws Exception { writeFutures.remove(cf); futureClose(); } }); } } void futureClose() { if (closeTask != null && writeFutures.isEmpty()) { closeTask.invoke(null); } } @Override public void send(String data) { if (!isOpen()) { throw new IllegalStateException("The outbound channel is closed"); } writeAndClose(ctx.getChannel().write(new DefaultWebSocketFrame(data))); } @Override public void send(byte opcode, byte[] data, int offset, int length) { if (!isOpen()) { throw new IllegalStateException("The outbound channel is closed"); } writeAndClose( ctx.getChannel() .write(new DefaultWebSocketFrame(opcode, wrappedBuffer(data, offset, length)))); } @Override public synchronized boolean isOpen() { return ctx.getChannel().isOpen() && closeTask == null; } @Override public synchronized void close() { closeTask = new Promise<Void>(); closeTask.onRedeem( new Action<Promise<Void>>() { public void invoke(Promise<Void> completed) { writeFutures.clear(); ctx.getChannel().disconnect(); closeTask = null; } }); futureClose(); } }; Invoker.invoke(new WebSocketInvocation(route, request, inbound, outbound, ctx, e)); }
public void copyResponse( ChannelHandlerContext ctx, Request request, Response response, HttpRequest nettyRequest) throws Exception { Logger.trace("copyResponse: begin"); // response.out.flush(); // Decide whether to close the connection or not. HttpResponse nettyResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(response.status)); if (exposePlayServer) { nettyResponse.setHeader(SERVER, signature); } if (response.contentType != null) { nettyResponse.setHeader( CONTENT_TYPE, response.contentType + (response.contentType.startsWith("text/") && !response.contentType.contains("charset") ? "; charset=utf-8" : "")); } else { nettyResponse.setHeader(CONTENT_TYPE, "text/plain; charset=utf-8"); } addToResponse(response, nettyResponse); final Object obj = response.direct; File file = null; ChunkedInput stream = null; InputStream is = null; if (obj instanceof File) { file = (File) obj; } else if (obj instanceof InputStream) { is = (InputStream) obj; } else if (obj instanceof ChunkedInput) { stream = (ChunkedInput) obj; } final boolean keepAlive = isKeepAlive(nettyRequest); if (file != null && file.isFile()) { try { nettyResponse = addEtag(nettyRequest, nettyResponse, file); if (nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { Channel ch = ctx.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); if (!keepAlive) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } else { nettyResponse.setHeader( CONTENT_TYPE, MimeTypes.getContentType(file.getName(), "text/plain")); final RandomAccessFile raf = new RandomAccessFile(file, "r"); try { long fileLength = raf.length(); if (keepAlive) { // Add 'Content-Length' header only for a keep-alive connection. Logger.trace("file length is [" + fileLength + "]"); setContentLength(nettyResponse, fileLength); } Channel ch = ctx.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); // Write the content. // If it is not a HEAD if (!nettyRequest.getMethod().equals(HttpMethod.HEAD)) { writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192)); } else { raf.close(); } if (!keepAlive) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } catch (Throwable exx) { try { raf.close(); } catch (Throwable ex) { /* Left empty */ } try { ctx.getChannel().close(); } catch (Throwable ex) { /* Left empty */ } } } } catch (Exception e) { throw e; } } else if (is != null) { ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); if (!nettyRequest.getMethod().equals(HttpMethod.HEAD) && !nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { writeFuture = ctx.getChannel().write(new ChunkedStream(is)); } else { is.close(); } if (!keepAlive) { writeFuture.addListener(ChannelFutureListener.CLOSE); } } else if (stream != null) { ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); if (!nettyRequest.getMethod().equals(HttpMethod.HEAD) && !nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { writeFuture = ctx.getChannel().write(stream); } else { stream.close(); } if (!keepAlive) { writeFuture.addListener(ChannelFutureListener.CLOSE); } } else { writeResponse(ctx, response, nettyResponse, nettyRequest); } Logger.trace("copyResponse: end"); }
@Override public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) throws Exception { Logger.trace("messageReceived: begin"); final Object msg = e.getMessage(); // Http request if (msg instanceof HttpRequest) { final HttpRequest nettyRequest = (HttpRequest) msg; // Websocket upgrade if (HttpHeaders.Values.UPGRADE.equalsIgnoreCase(nettyRequest.getHeader(CONNECTION)) && HttpHeaders.Values.WEBSOCKET.equalsIgnoreCase( nettyRequest.getHeader(HttpHeaders.Names.UPGRADE))) { websocketHandshake(ctx, nettyRequest, e); return; } // Plain old HttpRequest try { final Request request = parseRequest(ctx, nettyRequest); final Response response = new Response(); Http.Response.current.set(response); // Buffered in memory output response.out = new ByteArrayOutputStream(); // Direct output (will be set later) response.direct = null; // Streamed output (using response.writeChunk) response.onWriteChunk( new Action<Object>() { public void invoke(Object result) { writeChunk(request, response, ctx, nettyRequest, result); } }); // Raw invocation boolean raw = false; for (PlayPlugin plugin : Play.plugins) { if (plugin.rawInvocation(request, response)) { raw = true; break; } } if (raw) { copyResponse(ctx, request, response, nettyRequest); } else { // Deleguate to Play framework Invoker.invoke(new NettyInvocation(request, response, ctx, nettyRequest, e)); } } catch (Exception ex) { serve500(ex, ctx, nettyRequest); } } // Websocket frame if (msg instanceof WebSocketFrame) { WebSocketFrame frame = (WebSocketFrame) msg; websocketFrameReceived(ctx, frame); } Logger.trace("messageReceived: end"); }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (!(e.getMessage() instanceof HttpRequest)) { super.messageReceived(ctx, e); } HttpRequest request = (HttpRequest) e.getMessage(); URI uri = entityManager.normalizeURI(getEntityManager().getURIBase() + request.getUri()); String path = uri.getPath(); System.out.println("# received request: " + uri); /* * TODO: * - if GET "$base/entities/create", return entity creation form * - if GET "$base/entities/" || GET "$base/.well-known/servers" return entity list * - if POST "$base/entities/", call createEntity($postdata) * * - if GET "$base/sources/", return sources list * - if GET "$base/sources/edit" return sources edit form * - if POST "$base/sources/", call setSources($postdata) */ if (uri.equals(entityManager.normalizeURI(pathPrefix + "/list-entities"))) { if (request.getMethod() == HttpMethod.GET) { StringBuffer sb = new StringBuffer(); sb.append("<html><head><title>SLSE List</title></head><body><h1>SLSE List</h1><ol>"); for (ServiceLevelSemanticEntity slse : this.slseCache.getAll()) { sb.append("<li>"); sb.append(slse.getURI() + "<pre>" + slse.getDescribes() + "</pre>"); sb.append("</li>"); } sb.append("</ol></body></html>"); Channels.write(ctx.getChannel(), Answer.create(sb.toString())); } } else if (uri.equals(entityManager.normalizeURI(pathPrefix + "/create-entity"))) { if (request.getMethod() == HttpMethod.GET) { // copy into // HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), // HttpResponseStatus.OK); // response.setContent(ChannelBuffers.wrappedBuffer(htmlContent)); Channels.write(ctx.getChannel(), Answer.create(new String(htmlContent))); // Channels.write(ctx.getChannel(), // Answer.create(new File("data/slse/ui/create_entity_form.html"))); } else if (request.getMethod() == HttpMethod.POST) { QueryStringDecoder qsd = new QueryStringDecoder( "http://blub.blah/?" + request.getContent().toString(Charset.defaultCharset())); String elementsQuery = ""; String name = ""; boolean dependsOnSensorValues = false; boolean multiNodeQuery = false; for (Map.Entry<String, List<String>> entry : qsd.getParameters().entrySet()) { String key = entry.getKey(); for (String value : entry.getValue()) { if (entry.getKey().equals("elementsQuery")) { elementsQuery = value; } else if (entry.getKey().equals("name")) { name = value; } else if (key.equals("dependsOnSensorValues") && value.equals("yes")) { dependsOnSensorValues = true; } else if (key.equals("multiNodeQuery") && value.equals("yes")) { multiNodeQuery = true; } } } System.out.println( "# adding rule: name=" + name + " dependsOnSensorValues=" + dependsOnSensorValues + " multiNodeQuery=" + multiNodeQuery); slseBuilder.addRule(name, elementsQuery, dependsOnSensorValues, multiNodeQuery); Channels.write( ctx.getChannel(), Answer.create( "<html><head><meta http-equiv=\"REFRESH\" content=\"0;url=/\"></head></html>")); } } else { uri = entityManager.toThing(uri); Model r = ModelFactory.createDefaultModel(); if (waitForPolling) { // System.out.println("# waiting for esecache: " + uri); synchronized (eseCache) { while (!eseCache.isPollComplete()) { try { eseCache.wait(1000); } catch (InterruptedException ex) { ex .printStackTrace(); // To change body of catch statement use File | Settings | // File Templates. } } } } // System.out.println("# waiting for slseCache: " + uri); synchronized (slseCache) { if (slseCache.get(uri.toString()) == null) { System.out.println( "! SLSE not found in cache: " + uri.toString() + " returning empty model"); } else { r.add(slseCache.get(uri.toString()).getModel()); } } ChannelFuture future = Channels.write(ctx.getChannel(), r); if (!HttpHeaders.isKeepAlive(request)) { future.addListener(ChannelFutureListener.CLOSE); } // System.out.println("# done: " + uri); } }
public void serveStatic( RenderStatic renderStatic, ChannelHandlerContext ctx, Request request, Response response, HttpRequest nettyRequest, MessageEvent e) { Logger.trace("serveStatic: begin"); HttpResponse nettyResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(response.status)); if (exposePlayServer) { nettyResponse.setHeader(SERVER, signature); } try { VirtualFile file = Play.getVirtualFile(renderStatic.file); if (file != null && file.exists() && file.isDirectory()) { file = file.child("index.html"); if (file != null) { renderStatic.file = file.relativePath(); } } if ((file == null || !file.exists())) { serve404( new NotFound("The file " + renderStatic.file + " does not exist"), ctx, request, nettyRequest); } else { boolean raw = false; for (PlayPlugin plugin : Play.plugins) { if (plugin.serveStatic(file, Request.current(), Response.current())) { raw = true; break; } } if (raw) { copyResponse(ctx, request, response, nettyRequest); } else { final File localFile = file.getRealFile(); final boolean keepAlive = isKeepAlive(nettyRequest); nettyResponse = addEtag(nettyRequest, nettyResponse, localFile); if (nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { Channel ch = e.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); if (!keepAlive) { // Write the content. writeFuture.addListener(ChannelFutureListener.CLOSE); } } else { final RandomAccessFile raf = new RandomAccessFile(localFile, "r"); try { long fileLength = raf.length(); Logger.trace("keep alive " + keepAlive); Logger.trace( "content type " + (MimeTypes.getContentType(localFile.getName(), "text/plain"))); if (keepAlive && !nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { // Add 'Content-Length' header only for a keep-alive connection. Logger.trace("file length " + fileLength); setContentLength(nettyResponse, fileLength); } nettyResponse.setHeader( CONTENT_TYPE, (MimeTypes.getContentType(localFile.getName(), "text/plain"))); Channel ch = e.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); // Write the content. if (!nettyRequest.getMethod().equals(HttpMethod.HEAD)) { writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192)); } else { raf.close(); } if (!keepAlive) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } catch (Throwable exx) { try { raf.close(); } catch (Throwable ex) { /* Left empty */ } try { ctx.getChannel().close(); } catch (Throwable ex) { /* Left empty */ } } } } } } catch (Throwable ez) { Logger.error(ez, "serveStatic for request %s", request.method + " " + request.url); try { HttpResponse errorResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); ChannelBuffer buf = ChannelBuffers.copiedBuffer("Internal Error (check logs)".getBytes("utf-8")); errorResponse.setContent(buf); ChannelFuture future = ctx.getChannel().write(errorResponse); future.addListener(ChannelFutureListener.CLOSE); } catch (Exception ex) { Logger.error(ez, "serveStatic for request %s", request.method + " " + request.url); } } Logger.trace("serveStatic: end"); }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { RequestV2 request = null; RendererConfiguration renderer = null; String userAgentString = null; StringBuilder unknownHeaders = new StringBuilder(); String separator = ""; boolean isWindowsMediaPlayer = false; HttpRequest nettyRequest = this.nettyRequest = (HttpRequest) e.getMessage(); InetSocketAddress remoteAddress = (InetSocketAddress) e.getChannel().getRemoteAddress(); InetAddress ia = remoteAddress.getAddress(); // Apply the IP filter if (filterIp(ia)) { e.getChannel().close(); LOGGER.trace("Access denied for address " + ia + " based on IP filter"); return; } LOGGER.trace("Opened request handler on socket " + remoteAddress); PMS.get().getRegistry().disableGoToSleep(); if (HttpMethod.GET.equals(nettyRequest.getMethod())) { request = new RequestV2("GET", nettyRequest.getUri().substring(1)); } else if (HttpMethod.POST.equals(nettyRequest.getMethod())) { request = new RequestV2("POST", nettyRequest.getUri().substring(1)); } else if (HttpMethod.HEAD.equals(nettyRequest.getMethod())) { request = new RequestV2("HEAD", nettyRequest.getUri().substring(1)); } else { request = new RequestV2(nettyRequest.getMethod().getName(), nettyRequest.getUri().substring(1)); } LOGGER.trace( "Request: " + nettyRequest.getProtocolVersion().getText() + " : " + request.getMethod() + " : " + request.getArgument()); if (nettyRequest.getProtocolVersion().getMinorVersion() == 0) { request.setHttp10(true); } // The handler makes a couple of attempts to recognize a renderer from its requests. // IP address matches from previous requests are preferred, when that fails request // header matches are attempted and if those fail as well we're stuck with the // default renderer. // Attempt 1: try to recognize the renderer by its socket address from previous requests renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(ia); if (renderer != null) { if (!"WMP".equals(renderer.getRendererName())) { PMS.get().setRendererfound(renderer); request.setMediaRenderer(renderer); LOGGER.trace( "Matched media renderer \"" + renderer.getRendererName() + "\" based on address " + ia); } else { LOGGER.trace("Detected and blocked Windows Media Player"); isWindowsMediaPlayer = true; } } for (String name : nettyRequest.getHeaderNames()) { String headerLine = name + ": " + nettyRequest.getHeader(name); LOGGER.trace("Received on socket: " + headerLine); if (renderer == null && headerLine != null && headerLine.toUpperCase().startsWith("USER-AGENT")) { userAgentString = headerLine.substring(headerLine.indexOf(":") + 1).trim(); // Attempt 2: try to recognize the renderer by matching the "User-Agent" header renderer = RendererConfiguration.getRendererConfigurationByUA(userAgentString); if (renderer != null) { if (!"WMP".equals(renderer.getRendererName())) { request.setMediaRenderer(renderer); renderer.associateIP(ia); // Associate IP address for later requests PMS.get().setRendererfound(renderer); LOGGER.trace( "Matched media renderer \"" + renderer.getRendererName() + "\" based on header \"" + headerLine + "\""); } else if (!isWindowsMediaPlayer) { LOGGER.trace("Detected and blocked Windows Media Player"); isWindowsMediaPlayer = true; } } } if (renderer == null && headerLine != null) { // Attempt 3: try to recognize the renderer by matching an additional header renderer = RendererConfiguration.getRendererConfigurationByUAAHH(headerLine); if (renderer != null) { request.setMediaRenderer(renderer); renderer.associateIP(ia); // Associate IP address for later requests PMS.get().setRendererfound(renderer); LOGGER.trace( "Matched media renderer \"" + renderer.getRendererName() + "\" based on header \"" + headerLine + "\""); } } try { StringTokenizer s = new StringTokenizer(headerLine); String temp = s.nextToken(); if (temp.toUpperCase().equals("SOAPACTION:")) { request.setSoapaction(s.nextToken()); } else if (temp.toUpperCase().equals("CALLBACK:")) { request.setSoapaction(s.nextToken()); } else if (headerLine.toUpperCase().indexOf("RANGE: BYTES=") > -1) { String nums = headerLine.substring(headerLine.toUpperCase().indexOf("RANGE: BYTES=") + 13).trim(); StringTokenizer st = new StringTokenizer(nums, "-"); if (!nums.startsWith("-")) { request.setLowRange(Long.parseLong(st.nextToken())); } if (!nums.startsWith("-") && !nums.endsWith("-")) { request.setHighRange(Long.parseLong(st.nextToken())); } else { request.setHighRange(-1); } } else if (headerLine.toLowerCase().indexOf("transfermode.dlna.org:") > -1) { request.setTransferMode( headerLine .substring(headerLine.toLowerCase().indexOf("transfermode.dlna.org:") + 22) .trim()); } else if (headerLine.toLowerCase().indexOf("getcontentfeatures.dlna.org:") > -1) { request.setContentFeatures( headerLine .substring(headerLine.toLowerCase().indexOf("getcontentfeatures.dlna.org:") + 28) .trim()); } else { Matcher matcher = TIMERANGE_PATTERN.matcher(headerLine); if (matcher.find()) { String first = matcher.group(1); if (first != null) { request.setTimeRangeStartString(first); } String end = matcher.group(2); if (end != null) { request.setTimeRangeEndString(end); } } else { // If we made it to here, none of the previous header checks matched. // Unknown headers make interesting logging info when we cannot recognize // the media renderer, so keep track of the truly unknown ones. boolean isKnown = false; // Try to match possible known headers. for (String knownHeaderString : KNOWN_HEADERS) { if (headerLine.toLowerCase().startsWith(knownHeaderString.toLowerCase())) { isKnown = true; break; } } if (!isKnown) { // Truly unknown header, therefore interesting. Save for later use. unknownHeaders.append(separator).append(headerLine); separator = ", "; } } } } catch (Exception ee) { LOGGER.error("Error parsing HTTP headers", ee); } } if (!isWindowsMediaPlayer) { if (request != null) { // Still no media renderer recognized? if (request.getMediaRenderer() == null) { // Attempt 4: Not really an attempt; all other attempts to recognize // the renderer have failed. The only option left is to assume the // default renderer. request.setMediaRenderer(RendererConfiguration.getDefaultConf()); LOGGER.trace( "Using default media renderer: " + request.getMediaRenderer().getRendererName()); if (userAgentString != null && !userAgentString.equals("FDSSDP")) { // We have found an unknown renderer LOGGER.info( "Media renderer was not recognized. Possible identifying HTTP headers: User-Agent: " + userAgentString + ("".equals(unknownHeaders.toString()) ? "" : ", " + unknownHeaders.toString())); PMS.get().setRendererfound(request.getMediaRenderer()); } } else { if (userAgentString != null) { LOGGER.debug("HTTP User-Agent: " + userAgentString); } LOGGER.trace( "Recognized media renderer: " + request.getMediaRenderer().getRendererName()); } } if (HttpHeaders.getContentLength(nettyRequest) > 0) { byte data[] = new byte[(int) HttpHeaders.getContentLength(nettyRequest)]; ChannelBuffer content = nettyRequest.getContent(); content.readBytes(data); request.setTextContent(new String(data, "UTF-8")); } if (request != null) { LOGGER.trace( "HTTP: " + request.getArgument() + " / " + request.getLowRange() + "-" + request.getHighRange()); } writeResponse(e, request, ia); } }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { HttpRequest request = (HttpRequest) e.getMessage(); if (request.getMethod() != GET) { sendError(ctx, METHOD_NOT_ALLOWED); return; } String base = ContainerLocalizer.USERCACHE + "/" + userName + "/" + ContainerLocalizer.APPCACHE + "/" + appId + "/output" + "/"; final Map<String, List<String>> params = new QueryStringDecoder(request.getUri()).getParameters(); List<FileChunk> chunks = Lists.newArrayList(); List<String> taskIds = splitMaps(params.get("ta")); int sid = Integer.valueOf(params.get("sid").get(0)); int partitionId = Integer.valueOf(params.get("p").get(0)); for (String ta : taskIds) { File file = new File(base + "/" + sid + "/" + ta + "/output/" + partitionId); FileChunk chunk = new FileChunk(file, 0, file.length()); chunks.add(chunk); } FileChunk[] file = chunks.toArray(new FileChunk[chunks.size()]); // try { // file = retriever.handle(ctx, request); // } catch (FileNotFoundException fnf) { // LOG.error(fnf); // sendError(ctx, NOT_FOUND); // return; // } catch (IllegalArgumentException iae) { // LOG.error(iae); // sendError(ctx, BAD_REQUEST); // return; // } catch (FileAccessForbiddenException fafe) { // LOG.error(fafe); // sendError(ctx, FORBIDDEN); // return; // } catch (IOException ioe) { // LOG.error(ioe); // sendError(ctx, INTERNAL_SERVER_ERROR); // return; // } // Write the content. Channel ch = e.getChannel(); if (file == null) { HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NO_CONTENT); ch.write(response); if (!isKeepAlive(request)) { ch.close(); } } else { HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); long totalSize = 0; for (FileChunk chunk : file) { totalSize += chunk.length(); } setContentLength(response, totalSize); // Write the initial line and the header. ch.write(response); ChannelFuture writeFuture = null; for (FileChunk chunk : file) { writeFuture = sendFile(ctx, ch, chunk); if (writeFuture == null) { sendError(ctx, NOT_FOUND); return; } } // Decide whether to close the connection or not. if (!isKeepAlive(request)) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } }