/** Copyright 2013 the original author or authors.
*
* Licensed 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.
*/
/**
*
* @author <a href='mailto:th33musk3t33rs@gmail.com'>3.musket33rs</a>
*
* @since 0.1
*/
package org.threemusketeers.websocket;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.net.URI;
public class WebSocket {
private EventLoopGroup group;
private URI uri;
private WebSocketNotification notification;
private WebSocketClientHandler handler;
private Bootstrap bootstrap;
private Channel channel;
public WebSocket(String url, EventLoopGroup group, WebSocketNotification notification) {
this.group = group;
uri = URI.create(url);
this.notification = notification;
String protocol = uri.getScheme();
if (!"ws".equals(protocol)) {
notification.onerror("Unsupported protocol: " + protocol);
}
handler = new WebSocketClientHandler(uri, notification, this);
try {
createBootstrap();
} catch (InterruptedException e) {
channel.close();
notification.onerror("Unable to create WebSocket");
}
}
void createBootstrap() throws InterruptedException {
bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("http-codec", new HttpClientCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(8192));
pipeline.addLast("ws-handler", handler);
}
});
channel = bootstrap.connect(uri.getHost(), uri.getPort()).sync().channel();
}
public void close() {
channel.write(new CloseWebSocketFrame());
handler.close();
// WebSocketClientHandler will close the connection when the server
// responds to the CloseWebSocketFrame.
try {
channel.closeFuture().sync();
} catch (InterruptedException e) {
notification.onerror("Unable to close WebSocket");
}
}
public boolean send(String data) {
channel.write(new TextWebSocketFrame(data));
return true;
}
}