예제 #1
0
 static void removeIfExists(
     ChannelPipeline pipeline, Class<? extends ChannelHandler> handlerClass) {
   ChannelHandler channelHandler = pipeline.get(handlerClass);
   if (channelHandler != null) {
     pipeline.remove(channelHandler);
   }
 }
 private static String getWebSocketLocation(ChannelPipeline cp, HttpRequest req, String path) {
   String protocol = "ws";
   if (cp.get(SslHandler.class) != null) {
     // SSL in use so use Secure WebSockets
     protocol = "wss";
   }
   return protocol + "://" + req.getHttpHeaders().getHeaderString(HttpHeaders.Names.HOST) + path;
 }
예제 #3
0
  /**
   * Reconnect to the remote address that the closed channel was connected to. This creates a new
   * {@link ChannelPipeline} with the same handler instances contained in the old channel's
   * pipeline.
   *
   * @param timeout Timer task handle.
   * @throws Exception when reconnection fails.
   */
  @Override
  public void run(Timeout timeout) throws Exception {
    ChannelPipeline old = channel.pipeline();
    final CommandHandler<?, ?> handler = old.get(CommandHandler.class);
    final RedisAsyncConnection<?, ?> connection = old.get(RedisAsyncConnection.class);

    ChannelFuture connect = null;
    // TODO use better concurrent workaround
    synchronized (bootstrap) {
      connect =
          bootstrap
              .handler(
                  new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel ch) throws Exception {
                      ch.pipeline().addLast(this, handler, connection);
                    }
                  })
              .connect();
    }
    connect.sync();
  }
  /** 连接建立成功后要加载的channelHandler */
  protected void bindHandler(ChannelPipeline pipe, CMPPEndpointEntity entity) {
    // 修改连接空闲时间,使用server.xml里配置的连接空闲时间生效
    if (entity instanceof CMPPServerChildEndpointEntity) {
      ChannelHandler handler = pipe.get(GlobalConstance.IdleCheckerHandlerName);
      if (handler != null) {
        pipe.replace(
            handler,
            GlobalConstance.IdleCheckerHandlerName,
            new IdleStateHandler(0, 0, entity.getIdleTimeSec(), TimeUnit.SECONDS));
      }
    }
    pipe.addFirst(
        "socketLog",
        new LoggingHandler(
            String.format(GlobalConstance.loggerNamePrefix, entity.getId()), LogLevel.TRACE));
    pipe.addLast("msgLog", new CMPPMessageLogHandler(entity));

    pipe.addLast("CmppActiveTestRequestMessageHandler", GlobalConstance.activeTestHandler);
    pipe.addLast("CmppActiveTestResponseMessageHandler", GlobalConstance.activeTestRespHandler);
    pipe.addLast("CmppTerminateRequestMessageHandler", GlobalConstance.terminateHandler);
    pipe.addLast("CmppTerminateResponseMessageHandler", GlobalConstance.terminateRespHandler);

    List<BusinessHandlerInterface> handlers = entity.getBusinessHandlerSet();
    if (handlers != null && handlers.size() > 0) {
      for (BusinessHandlerInterface handler : handlers) {
        if (handler instanceof AbstractBusinessHandler) {
          AbstractBusinessHandler buziHandler = (AbstractBusinessHandler) handler;
          buziHandler.setEndpointEntity(entity);
          if (buziHandler.isSharable()) {
            pipe.addLast(buziHandler.name(), buziHandler);
          } else {
            AbstractBusinessHandler cloned = null;
            try {
              cloned = buziHandler.clone();

            } catch (CloneNotSupportedException e) {
              logger.error("handlers is not shareable and not implements Cloneable", e);
            }
            if (cloned != null) {
              cloned.setEndpointEntity(entity);
              pipe.addLast(buziHandler.name(), cloned);
              logger.info("handlers is not shareable . clone it success. {}", cloned);
            }
          }
        }
      }
    }
    // 黑洞处理,丢弃所有消息
    pipe.addLast("BlackHole", GlobalConstance.blackhole);
  }
예제 #5
0
  @Override
  public void send(final InputStream stream) throws Exception {
    byte[] chunk = new byte[bufferSize];
    int count = ByteStreams.read(stream, chunk, 0, bufferSize);
    if (count <= 0) {
      return;
    }
    ByteBuf buffer = Unpooled.wrappedBuffer(chunk, 0, count);
    if (count < bufferSize) {
      send(buffer);
    } else {
      DefaultHttpResponse rsp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);

      if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) {
        headers.set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
      } else {
        if (keepAlive) {
          headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
        }
      }

      // dump headers
      rsp.headers().set(headers);
      ChannelHandlerContext ctx = this.ctx;
      ctx.attr(NettyRequest.NEED_FLUSH).set(false);

      // add chunker
      ChannelPipeline pipeline = ctx.pipeline();
      if (pipeline.get("chunker") == null) {
        pipeline.addAfter("encoder", "chunker", new ChunkedWriteHandler());
      }

      // group all write
      ctx.channel()
          .eventLoop()
          .execute(
              () -> {
                // send headers
                ctx.write(rsp);
                // send head chunk
                ctx.write(buffer);
                // send tail
                ctx.write(new ChunkedStream(stream, bufferSize));
                keepAlive(ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT));
              });
    }

    committed = true;
  }
  /**
   * Handle the web socket handshake for the web socket specification <a href=
   * "http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17">HyBi versions 13-17</a>.
   * Versions 13-17 share the same wire protocol.
   *
   * <p>Browser request to the server:
   *
   * <pre>
   * GET /chat HTTP/1.1
   * Host: server.example.com
   * Upgrade: websocket
   * Connection: Upgrade
   * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   * Sec-WebSocket-Origin: http://example.com
   * Sec-WebSocket-Protocol: chat, superchat
   * Sec-WebSocket-Version: 13
   * </pre>
   *
   * <p>Server response:
   *
   * <pre>
   * HTTP/1.1 101 Switching Protocols
   * Upgrade: websocket
   * Connection: Upgrade
   * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
   * Sec-WebSocket-Protocol: chat
   * </pre>
   *
   * @param channel Channel
   * @param req HTTP request
   */
  @Override
  public ChannelFuture handshake(Channel channel, HttpRequest req) {

    if (logger.isDebugEnabled()) {
      logger.debug(String.format("Channel %s WS Version 13 server handshake", channel.getId()));
    }

    HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);

    String key = req.getHeader(Names.SEC_WEBSOCKET_KEY);
    if (key == null) {
      throw new WebSocketHandshakeException("not a WebSocket request: missing key");
    }
    String acceptSeed = key + WEBSOCKET_13_ACCEPT_GUID;
    byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
    String accept = WebSocketUtil.base64(sha1);

    if (logger.isDebugEnabled()) {
      logger.debug(
          String.format("WS Version 13 Server Handshake key: %s. Response: %s.", key, accept));
    }

    res.setStatus(HttpResponseStatus.SWITCHING_PROTOCOLS);
    res.addHeader(Names.UPGRADE, WEBSOCKET.toLowerCase());
    res.addHeader(Names.CONNECTION, Names.UPGRADE);
    res.addHeader(Names.SEC_WEBSOCKET_ACCEPT, accept);
    String protocol = req.getHeader(Names.SEC_WEBSOCKET_PROTOCOL);
    if (protocol != null) {
      res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, selectSubprotocol(protocol));
    }

    ChannelFuture future = channel.write(res);

    // Upgrade the connection and send the handshake response.
    ChannelPipeline p = channel.getPipeline();
    if (p.get(HttpChunkAggregator.class) != null) {
      p.remove(HttpChunkAggregator.class);
    }

    p.replace(
        HttpRequestDecoder.class,
        "wsdecoder",
        new WebSocket13FrameDecoder(true, allowExtensions, this.getMaxFramePayloadLength()));
    p.replace(HttpResponseEncoder.class, "wsencoder", new WebSocket13FrameEncoder(false));

    return future;
  }
예제 #7
0
  public void sendLoginSuccess(int status, Player player) {
    ByteBuf buf = channel.alloc().buffer(11);
    buf.writeByte(player.getRights());
    buf.writeByte(0);
    buf.writeByte(0);
    buf.writeByte(0);
    buf.writeByte(0);
    buf.writeByte(0);
    buf.writeByte(0);
    buf.writeShort(player.getId());
    buf.writeByte(1);
    buf.writeByte(1);

    ChannelPipeline pipeline = channel.pipeline();

    GameSession session = new GameSession(server, channel, player);
    RsChannelHandler handler = pipeline.get(RsChannelHandler.class);
    handler.setSession(session);

    pipeline.remove(ReadTimeoutHandler.class); // TODO a different timeout mechanism is used in-game

    LoginResponse response = new LoginResponse(status, buf);
    channel.write(response);

    pipeline.addFirst(
        new GameFrameEncoder(outRandom),
        new GameMessageEncoder(server.getCodecRepository()),
        new GameFrameDecoder(inRandom),
        new GameMessageDecoder(server.getCodecRepository()));

    if (displayMode == 0 || displayMode == 1)
      player.getInterfaceSet().setDisplayMode(DisplayMode.FIXED);
    else player.getInterfaceSet().setDisplayMode(DisplayMode.RESIZABLE);

    session.init();
  }
예제 #8
0
  NetSocket createNetSocket() {
    DefaultNetSocket socket =
        new DefaultNetSocket(vertx, channel, context, server.tcpHelper, false);
    Map<Channel, DefaultNetSocket> connectionMap = new HashMap<Channel, DefaultNetSocket>(1);
    connectionMap.put(channel, socket);

    // Flush out all pending data
    endReadAndFlush();

    // remove old http handlers and replace the old handler with one that handle plain sockets
    ChannelPipeline pipeline = channel.pipeline();
    ChannelHandler compressor = pipeline.get(HttpChunkContentCompressor.class);
    if (compressor != null) {
      pipeline.remove(compressor);
    }

    pipeline.remove("httpDecoder");
    if (pipeline.get("chunkedWriter") != null) {
      pipeline.remove("chunkedWriter");
    }

    channel
        .pipeline()
        .replace(
            "handler",
            "handler",
            new VertxNetHandler(server.vertx, connectionMap) {
              @Override
              public void exceptionCaught(ChannelHandlerContext chctx, Throwable t)
                  throws Exception {
                // remove from the real mapping
                server.connectionMap.remove(channel);
                super.exceptionCaught(chctx, t);
              }

              @Override
              public void channelInactive(ChannelHandlerContext chctx) throws Exception {
                // remove from the real mapping
                server.connectionMap.remove(channel);
                super.channelInactive(chctx);
              }

              @Override
              public void channelRead(ChannelHandlerContext chctx, Object msg) throws Exception {
                if (msg instanceof HttpContent) {
                  ReferenceCountUtil.release(msg);
                  return;
                }
                super.channelRead(chctx, msg);
              }
            });

    // check if the encoder can be removed yet or not.
    if (lastWriteFuture == null) {
      channel.pipeline().remove("httpEncoder");
    } else {
      lastWriteFuture.addListener(
          new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
              channel.pipeline().remove("httpEncoder");
            }
          });
    }
    return socket;
  }
 public static void removeTimeoutHandler(ChannelPipeline pipeline) {
   if (pipeline.get(READ_TIMEOUT_HANDLER_NAME) != null) {
     pipeline.remove(READ_TIMEOUT_HANDLER_NAME);
   }
 }