예제 #1
0
  @SuppressWarnings("unchecked")
  public static void resolve(Http.Request request, Http.Response response)
      throws NotFound, RenderStatic {

    if (!Play.started) {
      return;
    }

    Http.Request.current.set(request);
    Http.Response.current.set(response);

    Scope.Params.current.set(request.params);
    Scope.RenderArgs.current.set(new Scope.RenderArgs());
    Scope.RouteArgs.current.set(new Scope.RouteArgs());
    Scope.Session.current.set(Scope.Session.restore());
    Scope.Flash.current.set(Scope.Flash.restore());
    CachedBoundActionMethodArgs.init();

    ControllersEnhancer.currentAction.set(new Stack<String>());

    if (request.resolved) {
      return;
    }

    // Route and resolve format if not already done
    if (request.action == null) {
      Play.pluginCollection.routeRequest(request);
      Route route = Router.route(request);
      Play.pluginCollection.onRequestRouting(route);
    }
    request.resolveFormat();

    // Find the action method
    try {
      Method actionMethod = null;
      Object[] ca = getActionMethod(request.action);
      actionMethod = (Method) ca[1];
      request.controller = ((Class) ca[0]).getName().substring(12).replace("$", "");
      request.controllerClass = ((Class) ca[0]);
      request.actionMethod = actionMethod.getName();
      request.action = request.controller + "." + request.actionMethod;
      request.invokedMethod = actionMethod;
      if (Logger.isTraceEnabled()) {
        Logger.trace("------- %s", actionMethod);
      }
      request.resolved = true;
    } catch (ActionNotFoundException e) {
      //                Logger.error(e, "%s action not found", e.getAction());
      // bran: avoid excessive messages
      Logger.error("%s action not found", e.getAction());
      throw new NotFound(String.format("%s action not found", e.getAction()));
    }
  }
예제 #2
0
  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));
  }