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 */
017package org.fusesource.hawtdispatch.example;
018
019import org.fusesource.hawtbuf.AsciiBuffer;
020import org.fusesource.hawtbuf.Buffer;
021import org.fusesource.hawtdispatch.Dispatch;
022import org.fusesource.hawtdispatch.Task;
023import org.fusesource.hawtdispatch.transport.AbstractProtocolCodec;
024import org.fusesource.hawtdispatch.transport.DefaultTransportListener;
025import org.fusesource.hawtdispatch.transport.SslTransport;
026
027import javax.net.ssl.SSLContext;
028import javax.net.ssl.TrustManager;
029import javax.net.ssl.X509TrustManager;
030import java.io.IOException;
031import java.net.URI;
032import java.security.SecureRandom;
033import java.security.cert.X509Certificate;
034import java.util.concurrent.CountDownLatch;
035import java.util.concurrent.Executors;
036
037/**
038 */
039public 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);
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}