// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package vncclient.vnc; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import streamer.ByteBuffer; import streamer.InputStreamSource; import streamer.Link; import streamer.OneTimeSwitch; import streamer.OutputStreamSink; import streamer.Pipeline; import streamer.PipelineImpl; /** * VNC server sends hello packet with RFB protocol version, e.g. * "RFB 003.007\n". We need to send response packet with supported protocol * version, e.g. "RFB 003.003\n". */ public class Vnc33Hello extends OneTimeSwitch { public Vnc33Hello(String id) { super(id); } @Override protected void handleOneTimeData(ByteBuffer buf, Link link) { if (verbose) System.out.println("[" + this + "] INFO: Data received: " + buf + "."); // Initial packet is exactly 12 bytes long if (!cap(buf, 12, 12, link, false)) return; // Read protocol version String rfbProtocol = new String(buf.data, buf.offset, buf.length, RfbConstants.US_ASCII_CHARSET); buf.unref(); // Server should use RFB protocol 3.x if (!rfbProtocol.contains(RfbConstants.RFB_PROTOCOL_VERSION_MAJOR)) throw new RuntimeException("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\"."); // Send response: we support RFB 3.3 only String ourProtocolString = RfbConstants.RFB_PROTOCOL_VERSION + "\n"; ByteBuffer outBuf = new ByteBuffer(ourProtocolString.getBytes(RfbConstants.US_ASCII_CHARSET)); if (verbose) { outBuf.putMetadata("sender", this); outBuf.putMetadata("version", RfbConstants.RFB_PROTOCOL_VERSION); } pushDataToOTOut(outBuf); // Switch off this element from circuit switchOff(); } @Override public String toString() { return "Vnc3.3 Hello(" + id + ")"; } /** * Example. */ public static void main(String args[]) { // System.setProperty("streamer.Link.debug", "true"); System.setProperty("streamer.Element.debug", "true"); // System.setProperty("streamer.Pipeline.debug", "true"); InputStream is = new ByteArrayInputStream("RFB 003.007\ntest".getBytes(RfbConstants.US_ASCII_CHARSET)); ByteArrayOutputStream initOS = new ByteArrayOutputStream(); ByteArrayOutputStream mainOS = new ByteArrayOutputStream(); InputStreamSource inputStreamSource = new InputStreamSource("source", is); OutputStreamSink outputStreamSink = new OutputStreamSink("mainSink", mainOS); Vnc33Hello hello = new Vnc33Hello("hello"); Pipeline pipeline = new PipelineImpl("test"); pipeline.addAndLink(inputStreamSource, hello, outputStreamSink); pipeline.add(new OutputStreamSink("initSink", initOS)); pipeline.link("hello >" + OneTimeSwitch.OTOUT, "initSink"); pipeline.runMainLoop("source", STDOUT, false, false); String initOut = new String(initOS.toByteArray(), RfbConstants.US_ASCII_CHARSET); String mainOut = new String(mainOS.toByteArray(), RfbConstants.US_ASCII_CHARSET); if (!"RFB 003.003\n".equals(initOut)) System.err.println("Unexpected value for hello response: \"" + initOut + "\"."); if (!"test".equals(mainOut)) System.err.println("Unexpected value for main data: \"" + mainOut + "\"."); } }