001    /**
002     * Copyright (C) 2012 FuseSource, Inc.
003     * http://fusesource.com
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *    http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.fusesource.hawtdispatch.example;
018    
019    import org.fusesource.hawtbuf.AsciiBuffer;
020    import org.fusesource.hawtbuf.Buffer;
021    import org.fusesource.hawtdispatch.Dispatch;
022    import org.fusesource.hawtdispatch.Task;
023    import org.fusesource.hawtdispatch.transport.AbstractProtocolCodec;
024    import org.fusesource.hawtdispatch.transport.DefaultTransportListener;
025    import org.fusesource.hawtdispatch.transport.SslTransport;
026    
027    import javax.net.ssl.SSLContext;
028    import javax.net.ssl.TrustManager;
029    import javax.net.ssl.X509TrustManager;
030    import java.io.IOException;
031    import java.net.URI;
032    import java.security.SecureRandom;
033    import java.security.cert.X509Certificate;
034    import java.util.concurrent.CountDownLatch;
035    import java.util.concurrent.Executors;
036    
037    /**
038     */
039    public class SSLClientExample {
040    
041        // A fake trust manager to accept self signed certs.
042        static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
043                new X509TrustManager() {
044                    public X509Certificate[] getAcceptedIssuers() {
045                        return new X509Certificate[0];
046                    }
047    
048                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
049                    }
050    
051                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
052                    }
053                }
054        };
055    
056        // A very simple codec that just passes along byte buffers..
057        // A more realistic example can be found at:
058        // https://github.com/fusesource/stompjms/blob/master/stompjms-client/src/main/java/org/fusesource/stomp/codec/StompProtocolCodec.java
059        private static class BufferProtocolCodec extends AbstractProtocolCodec {
060            @Override
061            protected void encode(Object value) throws IOException {
062                Buffer buffer = (Buffer) value;
063                nextWriteBuffer.write(buffer.getData());
064            }
065    
066            @Override
067            protected Action initialDecodeAction() {
068                return readCommand();
069            }
070    
071            protected Action readCommand() {
072                return new Action() {
073                    public Object apply() throws IOException {
074                        int length = readBuffer.position() - readStart;
075                        if (length > 0) {
076                            int offset = readStart;
077                            readEnd = offset + length;
078                            readStart = readEnd;
079                            return new Buffer(readBuffer.array(), offset, length);
080                        } else {
081                            return null;
082                        }
083                    }
084                };
085            }
086        }
087    
088        public static void main(String[] args) throws Exception {
089    
090            // Setup an SSLContext that accepts self signed certs.
091            SSLContext sslContext = SSLContext.getInstance("SSL");
092            sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom());
093    
094            final SslTransport client = new SslTransport();
095            client.setDispatchQueue(Dispatch.createQueue());
096            client.setSSLContext(sslContext);
097            client.setBlockingExecutor(Executors.newCachedThreadPool());
098            client.setProtocolCodec(new BufferProtocolCodec());
099            client.connecting(new URI("ssl://localhost:61614"), null);
100    
101            final CountDownLatch done = new CountDownLatch(1);
102            final Task onClose = new Task() {
103                public void run() {
104                    System.out.println("Client closed.");
105                    done.countDown();
106                }
107            };
108            client.setTransportListener(new DefaultTransportListener() {
109    
110                @Override
111                public void onTransportConnected() {
112                    System.out.println("Connected");
113                    client.resumeRead();
114    
115                    // Once we are connected send some data..
116                    client.offer(new AsciiBuffer(
117                            "CONNECT\n" +
118                                    "login:admin\n" +
119                                    "passcode:password\n" +
120                                    "\n\u0000\n"
121                    ));
122                }
123    
124                // all we do is echo back the request, but change the frame,
125                // command to RESPONSE.
126                @Override
127                public void onTransportCommand(Object command) {
128                    Buffer frame = (Buffer) command;
129                    System.out.println("Received :" + frame.ascii());
130                    client.stop(onClose);
131                }
132    
133                @Override
134                public void onTransportFailure(IOException error) {
135                    System.out.println("Transport failure :" + error);
136                    client.stop(onClose);
137                }
138            });
139            client.start(Dispatch.NOOP);
140            done.await();
141    
142        }
143    
144    }