/** * Detects if we're connecting to a Found Elasticsearch cluster (using pre-configured host * suffixes) and adds a SSL handler at the beginning of the pipeline if we're connecting to a * SSL-endpoint (using a list of pre-configured ports). */ @Override public void connectRequested(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { if (e.getValue() instanceof InetSocketAddress) { InetSocketAddress inetSocketAddress = (InetSocketAddress) e.getValue(); for (String suffix : hostSuffixes) { isFoundCluster = isFoundCluster || inetSocketAddress.getHostString().endsWith(suffix); } if (isFoundCluster) { for (int sslPort : sslPorts) { if (inetSocketAddress.getPort() == sslPort) { logger.debug( "Enabling SSL on transport layer with unsafeAllowSelfSigned=[{}].", unsafeAllowSelfSigned); FoundSSLHandler handler = FoundSSLUtils.getSSLHandler(unsafeAllowSelfSigned, inetSocketAddress); ctx.getPipeline().addFirst("ssl", handler); break; } } } else { ctx.getPipeline().remove(this); } } super.connectRequested(ctx, e); }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (handshakeComplete) { super.messageReceived(ctx, e); } else { if (e.getMessage() instanceof ChannelBuffer) { ChannelBuffer newBuffer = (ChannelBuffer) e.getMessage(); buffered = ChannelBuffers.copiedBuffer(buffered, newBuffer); if (buffered.readableBytes() < 8) { return; } int payloadLength = buffered.getInt(0); int revision = buffered.getInt(4); boolean handshakeSuccessful = false; if (revision == 1 || revision == -1) { if (buffered.readableBytes() < payloadLength + 4) { return; } buffered.skipBytes(8); if (revision == 1) { handshakeSuccessful = handleRevision1Response(ctx, payloadLength); } else { handshakeSuccessful = handleGenericResponse(ctx, payloadLength); } } else { handshakeSuccessful = handleUnknownRevisionResponse(ctx); } if (!handshakeSuccessful) { ctx.getChannel().close(); } if (keepAliveInterval.millis() > 0) { ctx.getPipeline() .addBefore( ctx.getName(), "found-connection-keep-alive", new ConnectionKeepAliveHandler(scheduler, keepAliveInterval)); } handshakeComplete = true; ChannelBuffer remaining = buffered.slice(); if (remaining.readableBytes() > 0) { ctx.sendUpstream( new UpstreamMessageEvent( ctx.getChannel(), remaining, ctx.getChannel().getRemoteAddress())); } ctx.getPipeline().remove(this); } } }
/* * (non-Javadoc) * * @see org.jboss.netty.handler.codec.oneone.OneToOneEncoder#encode(org.jboss * .netty.channel.ChannelHandlerContext, org.jboss.netty.channel.Channel, java.lang.Object) */ @Override protected Object encode(final ChannelHandlerContext ctx, final Channel channel, final Object msg) throws Exception { final ChannelBuffer message = (ChannelBuffer) msg; final AuthToClientChannelHandler channelHandler = (AuthToClientChannelHandler) ctx.getPipeline().getLast(); final int opcode = message.readUnsignedByte(); final int size = message.readableBytes(); final ChannelBuffer frame = ChannelBuffers.buffer(ByteOrder.LITTLE_ENDIAN, (size + 3)); frame.writeByte(opcode); frame.writeShort(size); final byte[] tmpa = new byte[message.readableBytes()]; message.readBytes(tmpa); frame.writeBytes(channelHandler.getCrypt().encrypt(tmpa)); log.debug(String.format("[SEND PACKET] : 0x%02X", opcode)); final List<String> d = breakStringInChunks(new BigInteger(1, tmpa).toString(16).toUpperCase(), 16); for (final String string : d) { log.debug(string); } return frame; }
/** * Process server response: * * <pre> * HTTP/1.1 101 WebSocket Protocol Handshake * Upgrade: WebSocket * Connection: Upgrade * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Location: ws://example.com/demo * Sec-WebSocket-Protocol: sample * * 8jKS'y:G*Co,Wxa- * </pre> * * @param ctx Channel context * @param response HTTP response returned from the server for the request sent by * beginOpeningHandshake00(). * @throws WebSocketHandshakeException */ @Override public void endOpeningHandshake(ChannelHandlerContext ctx, HttpResponse response) throws WebSocketHandshakeException { final HttpResponseStatus status = new HttpResponseStatus(101, "WebSocket Protocol Handshake"); if (!response.getStatus().equals(status)) { throw new WebSocketHandshakeException( "Invalid handshake response status: " + response.getStatus()); } String upgrade = response.getHeader(Names.UPGRADE); if (upgrade == null || !upgrade.equals(Values.WEBSOCKET)) { throw new WebSocketHandshakeException( "Invalid handshake response upgrade: " + response.getHeader(Names.UPGRADE)); } String connection = response.getHeader(Names.CONNECTION); if (connection == null || !connection.equals(Values.UPGRADE)) { throw new WebSocketHandshakeException( "Invalid handshake response connection: " + response.getHeader(Names.CONNECTION)); } byte[] challenge = response.getContent().array(); if (!Arrays.equals(challenge, expectedChallengeResponseBytes)) { throw new WebSocketHandshakeException("Invalid challenge"); } String protocol = response.getHeader(Names.SEC_WEBSOCKET_PROTOCOL); this.setSubProtocolResponse(protocol); ctx.getPipeline().replace("decoder", "ws-decoder", new WebSocket00FrameDecoder()); this.setOpenningHandshakeCompleted(true); return; }
@Override public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception { log.debug( "channelIdle on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this))); OFChannelHandler handler = ctx.getPipeline().get(OFChannelHandler.class); handler.sendEchoRequest(); }
public static void replaceDefaultHandler( @NotNull ChannelHandlerContext context, @NotNull SimpleChannelUpstreamHandler messageChannelHandler) { context .getPipeline() .replace( DelegatingHttpRequestHandler.class, "replacedDefaultHandler", messageChannelHandler); }
@BeforeMethod public void setUp() throws Exception { MockitoAnnotations.initMocks(this); handler = new SyslogTCPFramingRouterHandler(2048, Delimiters.lineDelimiter()); when(context.getPipeline()).thenReturn(pipeline); when(context.getName()).thenReturn("current"); }
private void receivedConnect(NetData.JoinMessage message) { logger.info("Received Start Join"); NetClient client = new NetClient(channelHandlerContext.getChannel(), networkSystem, identity); client.setPreferredName(message.getName()); client.setColor(new Color(message.getColor().getRgba())); client.setViewDistanceMode(ViewDistance.forIndex(message.getViewDistanceLevel())); channelHandlerContext.getPipeline().remove(this); serverHandler.connectionComplete(client); }
@Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { // Get the SslHandler in the current pipeline. // We added it in SecureChatPipelineFactory. final SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class); // Get notified when SSL handshake is done. ChannelFuture handshakeFuture = sslHandler.handshake(); handshakeFuture.addListener(new SslLister(sslHandler)); }
@Override public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { // add bind handler to pipeline String baseName = ctx.getName(); String name = format("%s:socket", baseName); ctx.getPipeline().addAfter(baseName, name, bindHandler); // propagate channel open event super.channelOpen(ctx, e); }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { ImapSession session = (ImapSession) attributes.get(ctx.getChannel()); ImapResponseComposer response = (ImapResponseComposer) ctx.getAttachment(); ImapMessage message = (ImapMessage) e.getMessage(); ChannelPipeline cp = ctx.getPipeline(); try { if (cp.get(NettyConstants.EXECUTION_HANDLER) != null) { cp.addBefore( NettyConstants.EXECUTION_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler); } else { cp.addBefore( NettyConstants.CORE_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler); } final ResponseEncoder responseEncoder = new ResponseEncoder(encoder, response, session); processor.process(message, responseEncoder, session); if (session.getState() == ImapSessionState.LOGOUT) { // Make sure we close the channel after all the buffers were flushed out Channel channel = ctx.getChannel(); if (channel.isConnected()) { channel.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); } } final IOException failure = responseEncoder.getFailure(); if (failure != null) { final Logger logger = session.getLog(); logger.info(failure.getMessage()); if (logger.isDebugEnabled()) { logger.debug("Failed to write " + message, failure); } throw failure; } } finally { ctx.getPipeline().remove(NettyConstants.HEARTBEAT_HANDLER); } super.messageReceived(ctx, e); }
@Override public void beforeAdd(ChannelHandlerContext ctx) throws Exception { if (ctx.getPipeline().isAttached()) { // channelOpen event has been fired already, which means // this.channelOpen() will not be invoked. // We have to initialize here instead. initialize(ctx); } else { // channelOpen event has not been fired yet. // this.channelOpen() will be invoked and initialization will occur there. } }
@Override public void handleUpstream(final ChannelHandlerContext ctx, final ChannelEvent e) throws Exception { Object o = null; if ((e instanceof MessageEvent) && this.first.compareAndSet(true, false) && ((o = ((MessageEvent) e).getMessage()) instanceof ChannelBuffer) && !maybeSsl((ChannelBuffer) o)) { ctx.getPipeline().removeFirst(); ctx.sendUpstream(e); } else { super.handleUpstream(ctx, e); } }
/** * {@inheritDoc} * * @see * org.jboss.netty.channel.ChannelUpstreamHandler#handleUpstream(org.jboss.netty.channel.ChannelHandlerContext, * org.jboss.netty.channel.ChannelEvent) */ @Override public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception { if (e instanceof MessageEvent) { MessageEvent me = (MessageEvent) e; if (me.getMessage() instanceof ChannelBuffer) { ChannelBuffer postDetectBuffer = protocolSwitch(ctx, e.getChannel(), (ChannelBuffer) me.getMessage(), e); if (postDetectBuffer != null) { ctx.getPipeline().remove(this); ctx.sendUpstream( new UpstreamMessageEvent( e.getChannel(), postDetectBuffer, ((MessageEvent) e).getRemoteAddress())); } } } else { ctx.sendUpstream(e); } }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent messageEvent) throws Exception { messageReceived = true; if (LOG.isTraceEnabled()) { LOG.trace("Message received: {}", messageEvent); } if (producer.getConfiguration().getRequestTimeout() > 0) { ChannelHandler handler = ctx.getPipeline().get("timeout"); if (handler != null) { LOG.trace("Removing timeout channel as we received message"); ctx.getPipeline().remove(handler); } } Exchange exchange = getExchange(ctx); if (exchange == null) { // we just ignore the received message as the channel is closed return; } AsyncCallback callback = getAsyncCallback(ctx); Message message; try { message = getResponseMessage(exchange, messageEvent); } catch (Exception e) { exchange.setException(e); callback.done(false); return; } // set the result on either IN or OUT on the original exchange depending on its pattern if (ExchangeHelper.isOutCapable(exchange)) { exchange.setOut(message); } else { exchange.setIn(message); } try { // should channel be closed after complete? Boolean close; if (ExchangeHelper.isOutCapable(exchange)) { close = exchange .getOut() .getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class); } else { close = exchange .getIn() .getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class); } // check the setting on the exchange property if (close == null) { close = exchange.getProperty(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class); } // should we disconnect, the header can override the configuration boolean disconnect = producer.getConfiguration().isDisconnect(); if (close != null) { disconnect = close; } if (disconnect) { if (LOG.isTraceEnabled()) { LOG.trace( "Closing channel when complete at address: {}", producer.getConfiguration().getAddress()); } NettyHelper.close(ctx.getChannel()); } } finally { // signal callback callback.done(false); } }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { if (LOG.isDebugEnabled()) { LOG.debug("messageReceived: Got " + e.getMessage().getClass()); } WritableRequest writableRequest = (WritableRequest) e.getMessage(); // Simulate a closed connection on the first request (if desired) // TODO: Move out into a separate, dedicated handler. if (closeFirstRequest && !ALREADY_CLOSED_FIRST_REQUEST) { LOG.info( "messageReceived: Simulating closing channel on first " + "request " + writableRequest.getRequestId() + " from " + writableRequest.getClientId()); setAlreadyClosedFirstRequest(); ctx.getChannel().close(); return; } if (writableRequest.getType() == RequestType.SASL_TOKEN_MESSAGE_REQUEST) { // initialize server-side SASL functionality, if we haven't yet // (in which case we are looking at the first SASL message from the // client). SaslNettyServer saslNettyServer = NettyServer.CHANNEL_SASL_NETTY_SERVERS.get(ctx.getChannel()); if (saslNettyServer == null) { if (LOG.isDebugEnabled()) { LOG.debug( "No saslNettyServer for " + ctx.getChannel() + " yet; creating now, with secret manager: " + secretManager); } saslNettyServer = new SaslNettyServer(secretManager); NettyServer.CHANNEL_SASL_NETTY_SERVERS.set(ctx.getChannel(), saslNettyServer); } else { if (LOG.isDebugEnabled()) { LOG.debug( "Found existing saslNettyServer on server:" + ctx.getChannel().getLocalAddress() + " for client " + ctx.getChannel().getRemoteAddress()); } } ((SaslTokenMessageRequest) writableRequest).processToken(saslNettyServer); // Send response to client. ctx.getChannel().write(writableRequest); if (saslNettyServer.isComplete()) { // If authentication of client is complete, we will also send a // SASL-Complete message to the client. if (LOG.isDebugEnabled()) { LOG.debug( "SASL authentication is complete for client with " + "username: "******"Removing SaslServerHandler from pipeline since SASL " + "authentication is complete."); } ctx.getPipeline().remove(this); } // do not send upstream to other handlers: no further action needs to be // done for SASL_TOKEN_MESSAGE_REQUEST requests. return; } else { // Client should not be sending other-than-SASL messages before // SaslServerHandler has removed itself from the pipeline. Such non-SASL // requests will be denied by the Authorize channel handler (the next // handler upstream in the server pipeline) if SASL authentication has // not completed. LOG.warn("Sending upstream an unexpected non-SASL message : " + writableRequest); ctx.sendUpstream(e); } }
@SuppressWarnings("unchecked") @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { ctx.getPipeline().remove(this); future.setResult(FutureResult.create(e.getCause())); }
@Override public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { super.channelOpen(ctx, e); this.channelHandlerContext = ctx; serverHandler = ctx.getPipeline().get(ServerHandler.class); }
/** Expected Message types: - HTTP Requests */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (!(e.getMessage() instanceof HttpRequest)) { super.messageReceived(ctx, e); return; } HttpRequest httpRequest = (HttpRequest) e.getMessage(); URI targetUri = toThing(URI.create("http://" + httpRequest.getHeader("HOST") + httpRequest.getUri())); log.debug("Received HTTP request for " + targetUri); if (httpRequest.getHeader("HOST").contains(DNS_WILDCARD_POSTFIX)) { String targetUriHost = InetAddress.getByName(targetUri.getHost()).getHostAddress(); // remove leading zeros per block targetUriHost = targetUriHost.replaceAll(":0000", ":0"); targetUriHost = targetUriHost.replaceAll(":000", ":0"); targetUriHost = targetUriHost.replaceAll(":00", ":0"); targetUriHost = targetUriHost.replaceAll("(:0)([ABCDEFabcdef123456789])", ":$2"); // return shortened IP targetUriHost = targetUriHost.replaceAll("((?:(?:^|:)0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)", "::$2"); log.debug("Target host: " + targetUriHost); String targetUriPath = targetUri.getRawPath(); log.debug("Target path: " + targetUriPath); if (IPAddressUtil.isIPv6LiteralAddress(targetUriHost)) { targetUriHost = "[" + targetUriHost + "]"; } targetUri = toThing(URI.create("http://" + targetUriHost + httpRequest.getUri())); log.debug("Shortened target URI: " + targetUri); } URI uriToCheck = targetUri; if ((uriToCheck.getQuery() != null) && (uriToCheck.getQuery().equals("html"))) { uriToCheck = toThing(URI.create("http://" + targetUri.getHost() + targetUri.getPath())); } if (entities.containsKey(uriToCheck)) { Backend backend = entities.get(uriToCheck); try { ctx.getPipeline().remove("Backend to handle request"); } catch (NoSuchElementException ex) { // Fine. There was no handler to be removed. } ctx.getPipeline().addLast("Backend to handle request", backend); log.debug("Forward request to " + backend); } else if (virtualEntities.containsKey(uriToCheck)) { Backend backend = virtualEntities.get(uriToCheck); try { ctx.getPipeline().remove("Backend to handle request"); } catch (NoSuchElementException ex) { // Fine. There was no handler to be removed. } ctx.getPipeline().addLast("Backend to handle request", backend); log.debug("Forward request to " + backend); } // else if (targetUriPath.equals(PATH_TO_SERVER_LIST)) { // // Handle request for resource at path ".well-known/core" // StringBuilder buf = new StringBuilder(); // for(URI entity: getServices()) { // buf.append(toThing(entity).toString() + "\n"); // } // Channels.write(ctx.getChannel(), // Answer.create(buf.toString()).setMime("text/plain")); // return; // } // else if("/visualizer".equals(targetUriPath)){ // try { // ctx.getPipeline().remove("Backend to handle request"); // } // catch(NoSuchElementException ex) { // //Fine. There was no handler to be removed. // } // ctx.getPipeline().addLast("VisualizerService", VisualizerService.getInstance()); // log.debug("Forward request to visualizer."); // } /*else if(targetUriPath.startsWith(SERVER_PATH_TO_SLSE_UI)) { String f = LOCAL_PATH_TO_SLSE_UI + targetUriPath.substring(SERVER_PATH_TO_SLSE_UI.length()); Channels.write(ctx.getChannel(), Answer.create(new File(f)).setMime("text/n3")); }*/ else if ("/".equals(targetUri.getRawPath())) { HttpResponse httpResponse = new DefaultHttpResponse(httpRequest.getProtocolVersion(), HttpResponseStatus.OK); httpResponse.setContent(getHtmlListOfServices()); ChannelFuture future = Channels.write(ctx.getChannel(), httpResponse); future.addListener(ChannelFutureListener.CLOSE); return; } else if (httpRequest.getUri().endsWith("spitfire-logo.png") || (httpRequest.getUri().endsWith("favicon.ico"))) { File img; if (httpRequest.getUri().endsWith("spitfire-logo.png")) { img = new File("spitfire-logo.png"); } else { img = new File("favicon.ico"); } int imgLength = (int) img.length(); FileInputStream in = new FileInputStream(img); byte[] imgMemory = new byte[imgLength]; in.read(imgMemory); in.close(); HttpResponse httpResponse = new DefaultHttpResponse(httpRequest.getProtocolVersion(), HttpResponseStatus.OK); httpResponse.setContent(ChannelBuffers.wrappedBuffer(imgMemory)); ChannelFuture future = Channels.write(ctx.getChannel(), httpResponse); future.addListener(ChannelFutureListener.CLOSE); if (httpRequest.getUri().endsWith("spitfire-logo.png")) { log.debug("Served request for Spitfire image."); } else { log.debug("Served favicon."); } return; } ctx.sendUpstream(e); }
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req, MessageEvent e) throws Exception { /* 获取请求头中的cookie字段 */ String cookieInReqHeader = req.getHeader(COOKIE); /* * 根据URL地址判断当前的请求处理方式 * 1.如果URL为ServerHandler.ROOT_DIR,那么处理用户登录过程 * 2.如果URL为WebSocketHandler.WEBSOCKET_PATH,则处理连接WebSocket建立过程 * 3.........(等待后续添加) */ if (req.getUri().equals(ServerHandler.ROOT_DIR)) // 判断URL为根目录地址 { HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK); /* * 判断当前请求头中的cookie是否为空 * 如果为空,需要强制要求浏览器设置cookie */ if (cookieInReqHeader == null) { String sessionId = Session.produceSessionId(); ServerHandler.sessionManager.add( new Session(sessionId, Session.INDEX, ctx.getChannel().getId())); ChannelBuffer content = ServerWritePage.getContent(Session.INDEX); buildResponse(res, true, sessionId, content, content.readableBytes()); sendHttpResponse(ctx, req, res); } else { /* 即使浏览器请求头中的cookie不为空 * 可能服务器的Session集合中并不包含对应的cookie,此时仍然需要强制浏览器重设cookie */ if (!ServerHandler.sessionManager.contain(cookieInReqHeader)) { String sessionId = Session.produceSessionId(); ServerHandler.sessionManager.add( new Session(sessionId, Session.INDEX, ctx.getChannel().getId())); ChannelBuffer content = ServerWritePage.getContent(Session.INDEX); buildResponse(res, true, sessionId, content, content.readableBytes()); sendHttpResponse(ctx, req, res); } else { int sessionState = ServerHandler.sessionManager.find(cookieInReqHeader).getCurrentState(); if (sessionState == Session.INDEX) // 判断当前的Session状态是否为登录页面状态 { if (req.getMethod() == GET) // 如果当前网页被重复刷新,需要始终维持此Session并向用户送回登陆页面 { ServerHandler.sessionManager.sessionActiveTimeUpdate(cookieInReqHeader); ChannelBuffer content = ServerWritePage.getContent(Session.INDEX); buildResponse(res, false, null, content, content.readableBytes()); sendHttpResponse(ctx, req, res); } if (req.getMethod() == POST) // 如果用户点击了登录按钮 { HashMap<String, String> parameterList = getPostParameter(req); // 获取POST请求参数 if (parameterList.get("navigatorName").equals("Firefox") || parameterList.get("navigatorName").equals("Chrome") || parameterList .get("navigatorName") .equals("Safari")) // 暂时简单判断浏览器版本,并根据浏览器版本发回连接建立页面 { try { // session的状态和活动时间都被相继更新 ServerHandler.sessionManager.sessionStateUpdate( cookieInReqHeader, Session.WEBSOCKET); ServerHandler.sessionManager.sessionActiveTimeUpdate(cookieInReqHeader); ChannelBuffer content = ServerWritePage.getContent(Session.WEBSOCKET); buildResponse(res, false, null, content, content.readableBytes()); sendHttpResponse(ctx, req, res); } catch (Exception a) { a.printStackTrace(); } } else // 根据其他浏览器版本选择 long Polling或者streaming方式同样建立连接 { /* To deal with long polling and streaming */ /* To send back the correspondent page */ } } } else if (sessionState == Session.WEBSOCKET) // 当前的Session状态是否为WebSocket连接建立状态 { /* * 如果已经是连接建立状态,但用户刷新了此页面,此时仍然需要维持Session * WebSocket连接已经建立的情况下,刷新页面之后用户将不需要重新登录 * 但是先前的WebSocket连接将被强制关闭,并且重新发出新的连接建立请求 * 即强制一个用户只能向服务器请求一条WebSocket连接 */ if (req.getMethod() == GET) { if (ServerHandler.clientChannelGroup.find( ServerHandler.sessionManager.find(cookieInReqHeader).getChannelId()) != null) { ServerHandler.clientChannelGroup .find(ServerHandler.sessionManager.find(cookieInReqHeader).getChannelId()) .close(); } ServerHandler.sessionManager.sessionActiveTimeUpdate(cookieInReqHeader); ChannelBuffer content = ServerWritePage.getContent(Session.WEBSOCKET); buildResponse(res, false, null, content, content.readableBytes()); sendHttpResponse(ctx, req, res); } } } } } else if (req.getUri().equals(WebSocketHandler.WEBSOCKET_PATH)) // 根据地址判断WebSocket请求是否被发送 { ServerHandler.sessionManager.sessionChannelIdUpdate( cookieInReqHeader, ctx.getChannel().getId()); ctx.getPipeline() .addLast("websocket", new WebSocketHandler()); // 将WebSocketHandler加入到当前的Pipeline中 ctx.getPipeline().remove(this); // 将当前的Handler移除掉 ctx.sendUpstream(e); // 将Pipeline中的事件传递到WebSocketHandler中 ServerHandler.clientChannelGroup.add(ctx.getChannel()); // 并且将当前的Channel加入到Group中 } else { // 如果请求到了其他地址,发回请求地址无法响应的回复 HttpResponse res = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND); sendHttpResponse(ctx, req, res); return; } }
/** * Sends the opening request to the server: * * <pre> * GET /demo HTTP/1.1 * Upgrade: WebSocket * Connection: Upgrade * Host: example.com * Origin: http://example.com * Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 * Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 * * ^n:ds[4U * </pre> * * @param ctx Channel context * @param channel Channel into which we can write our request */ @Override public void beginOpeningHandshake(ChannelHandlerContext ctx, Channel channel) { // Make keys int spaces1 = createRandomNumber(1, 12); int spaces2 = createRandomNumber(1, 12); int max1 = Integer.MAX_VALUE / spaces1; int max2 = Integer.MAX_VALUE / spaces2; int number1 = createRandomNumber(0, max1); int number2 = createRandomNumber(0, max2); int product1 = number1 * spaces1; int product2 = number2 * spaces2; String key1 = Integer.toString(product1); String key2 = Integer.toString(product2); key1 = insertRandomCharacters(key1); key2 = insertRandomCharacters(key2); key1 = insertSpaces(key1, spaces1); key2 = insertSpaces(key2, spaces2); byte[] key3 = createRandomBytes(8); ByteBuffer buffer = ByteBuffer.allocate(4); buffer.putInt(number1); byte[] number1Array = buffer.array(); buffer = ByteBuffer.allocate(4); buffer.putInt(number2); byte[] number2Array = buffer.array(); byte[] challenge = new byte[16]; System.arraycopy(number1Array, 0, challenge, 0, 4); System.arraycopy(number2Array, 0, challenge, 4, 4); System.arraycopy(key3, 0, challenge, 8, 8); this.expectedChallengeResponseBytes = md5(challenge); // Get path URI wsURL = this.getWebSocketURL(); String path = wsURL.getPath(); if (wsURL.getQuery() != null && wsURL.getQuery().length() > 0) { path = wsURL.getPath() + "?" + wsURL.getQuery(); } // Format request HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); request.addHeader(Names.UPGRADE, Values.WEBSOCKET); request.addHeader(Names.CONNECTION, Values.UPGRADE); request.addHeader(Names.HOST, wsURL.getHost()); request.addHeader(Names.ORIGIN, "http://" + wsURL.getHost()); request.addHeader(Names.SEC_WEBSOCKET_KEY1, key1); request.addHeader(Names.SEC_WEBSOCKET_KEY2, key2); if (this.getSubProtocolRequest() != null && !this.getSubProtocolRequest().equals("")) { request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, this.getSubProtocolRequest()); } request.setContent(ChannelBuffers.copiedBuffer(key3)); channel.write(request); ctx.getPipeline().replace("encoder", "ws-encoder", new WebSocket00FrameEncoder()); }