use of java.nio.channels.SocketChannel in project http-kit by http-kit.
the class HttpClient method doWrite.
private void doWrite(SelectionKey key) {
Request req = (Request) key.attachment();
SocketChannel ch = (SocketChannel) key.channel();
try {
if (req instanceof HttpsRequest) {
HttpsRequest httpsReq = (HttpsRequest) req;
if (httpsReq.handshaken) {
// will flip to OP_READ
httpsReq.writeWrappedRequest();
} else {
buffer.clear();
if (httpsReq.doHandshake(buffer) < 0) {
// will be a No status exception
req.finish();
}
}
} else {
ByteBuffer[] buffers = req.request;
ch.write(buffers);
if (!buffers[buffers.length - 1].hasRemaining()) {
key.interestOps(OP_READ);
}
}
} catch (IOException e) {
if (!cleanAndRetryIfBroken(key, req)) {
req.finish(e);
}
} catch (Exception e) {
// rarely happen
req.finish(e);
}
}
use of java.nio.channels.SocketChannel in project http-kit by http-kit.
the class HttpClient method finishConnect.
private void finishConnect(SelectionKey key, long now) {
SocketChannel ch = (SocketChannel) key.channel();
Request req = (Request) key.attachment();
try {
if (ch.finishConnect()) {
req.isConnected = true;
req.onProgress(now);
key.interestOps(OP_WRITE);
if (req instanceof HttpsRequest) {
((HttpsRequest) req).engine.beginHandshake();
}
}
} catch (IOException e) {
// not added to kee-alive yet;
closeQuietly(key);
req.finish(e);
}
}
use of java.nio.channels.SocketChannel in project http-kit by http-kit.
the class HttpsRequest method doHandshake.
final int doHandshake(ByteBuffer peerAppData) throws IOException {
SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
while (!handshaken) {
switch(hs) {
case NEED_TASK:
Runnable runnable;
while ((runnable = engine.getDelegatedTask()) != null) {
runnable.run();
}
break;
case NEED_UNWRAP:
int read = ((SocketChannel) key.channel()).read(peerNetData);
if (read < 0) {
return -1;
} else {
peerNetData.flip();
SSLEngineResult res = engine.unwrap(peerNetData, peerAppData);
peerNetData.compact();
switch(res.getStatus()) {
case // Not possible, peerAppData is 64k
BUFFER_OVERFLOW:
break;
case CLOSED:
return -1;
case // need more data from peer
BUFFER_UNDERFLOW:
return 0;
}
// do not flip to write here, since TCP buffer is writable
}
break;
case NEED_WRAP:
SSLEngineResult res = engine.wrap(EMPTY_BUFFER, myNetData);
myNetData.flip();
((SocketChannel) key.channel()).write(myNetData);
if (myNetData.hasRemaining()) {
// TODO, make sure data get written
} else {
myNetData.clear();
if (res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_WRAP)
key.interestOps(SelectionKey.OP_READ);
}
break;
}
hs = engine.getHandshakeStatus();
handshaken = hs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING || hs == SSLEngineResult.HandshakeStatus.FINISHED;
if (handshaken) {
wrapRequest();
// TCP buffer maybe empty this time
writeWrappedRequest();
}
}
return 0;
}
use of java.nio.channels.SocketChannel in project http-kit by http-kit.
the class SSLTest method main.
public static void main(String[] args) throws Exception {
SSLEngine engine = CLIENT_CONTEXT.createSSLEngine();
engine.setUseClientMode(true);
// Create a nonblocking socket channel
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(true);
socketChannel.connect(new InetSocketAddress("google.com", 443));
// int i = 0;
while (!socketChannel.finishConnect()) {
// System.out.println("----------" + i++);
Thread.sleep(50);
// do something until connect completed
}
// Create byte buffers to use for holding application and encoded data
SSLSession session = engine.getSession();
ByteBuffer myNetData = ByteBuffer.allocate(session.getPacketBufferSize());
ByteBuffer peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
ByteBuffer peerNetData = ByteBuffer.allocate(session.getPacketBufferSize());
peerNetData.limit(0);
ByteBuffer myAppData = ByteBuffer.wrap(("GET / HTTP/1.1\r\nHost: \r\n\r\n").getBytes());
engine.beginHandshake();
SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
while (hs != SSLEngineResult.HandshakeStatus.FINISHED && hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
System.out.println("hs status: " + hs);
switch(hs) {
case NEED_TASK:
Runnable runnable;
while ((runnable = engine.getDelegatedTask()) != null) {
System.out.println("get task " + runnable);
runnable.run();
}
break;
case NEED_UNWRAP:
if (!peerNetData.hasRemaining()) {
peerNetData.clear();
int read = socketChannel.read(peerNetData);
System.out.println("read: " + read + "\t" + peerNetData);
peerNetData.flip();
}
SSLEngineResult status = engine.unwrap(peerNetData, peerAppData);
// peerNetData.compact();
System.out.println("unwrap: " + status);
switch(status.getStatus()) {
case BUFFER_UNDERFLOW:
peerNetData.compact();
// peerNetData.flip();
int read = socketChannel.read(peerNetData);
System.out.println("flip read: " + read + "\t" + peerNetData);
peerNetData.flip();
break;
}
break;
case NEED_WRAP:
myNetData.clear();
SSLEngineResult wrapStatus = engine.wrap(myAppData, myNetData);
System.out.println("wrap: " + wrapStatus);
myNetData.flip();
while (myNetData.hasRemaining()) {
socketChannel.write(myNetData);
}
break;
}
hs = engine.getHandshakeStatus();
}
// https://raw.github.com/http-kit/scale-clojure-web-app/master/results/600k/heap_usage.png
for (int i = 0; i < 5; i++) {
myNetData.clear();
peerAppData.clear();
myAppData = ByteBuffer.wrap(("GET / HTTP/1.1\r\nHost: www.google.co.jp\r\n\r\n").getBytes());
SSLEngineResult wrapStatus = engine.wrap(myAppData, myNetData);
// System.out.println("---------wrap: " + wrapStatus);
myNetData.flip();
while (myNetData.hasRemaining()) {
socketChannel.write(myNetData);
}
peerNetData.clear();
int read = socketChannel.read(peerNetData);
// System.out.println("-------read: " + read + "\t" + peerNetData);
peerNetData.flip();
// Exception in thread "main" javax.net.ssl.SSLException: bad record MAC
SSLEngineResult status = engine.unwrap(peerNetData, peerAppData);
while (status.getStatus() != SSLEngineResult.Status.OK) {
// System.out.println("-------unwrap: " + status);
peerNetData.compact();
read = socketChannel.read(peerNetData);
System.out.println("-------read: " + read + "\t" + peerNetData);
peerNetData.flip();
status = engine.unwrap(peerNetData, peerAppData);
}
peerAppData.flip();
System.out.println(peerAppData);
byte[] data = new byte[peerAppData.remaining()];
peerAppData.get(data);
System.out.println(new String(data));
// peerNetData.compact();
}
// Do initial handshake
// doHandleShake2(socketChannel, engine, myNetData, peerNetData);
}
use of java.nio.channels.SocketChannel in project http-kit by http-kit.
the class HttpServer method doWrite.
private void doWrite(SelectionKey key) {
ServerAtta atta = (ServerAtta) key.attachment();
SocketChannel ch = (SocketChannel) key.channel();
try {
// 1. keep byte data order, 2. ensure visibility
synchronized (atta) {
LinkedList<ByteBuffer> toWrites = atta.toWrites;
int size = toWrites.size();
if (size == 1) {
ch.write(toWrites.get(0));
// TODO investigate why needed.
// ws request for write, but has no data?
} else if (size > 0) {
ByteBuffer[] buffers = new ByteBuffer[size];
toWrites.toArray(buffers);
ch.write(buffers, 0, buffers.length);
}
Iterator<ByteBuffer> ite = toWrites.iterator();
while (ite.hasNext()) {
if (!ite.next().hasRemaining()) {
ite.remove();
}
}
// all done
if (toWrites.size() == 0) {
if (atta.isKeepAlive()) {
key.interestOps(OP_READ);
} else {
closeKey(key, CLOSE_NORMAL);
}
}
}
} catch (IOException e) {
// the remote forcibly closed the connection
closeKey(key, CLOSE_AWAY);
}
}
Aggregations