/**
* 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 org.apache.cassandra.net;
import java.net.SocketAddress;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.*;
import java.nio.channels.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.cassandra.utils.LogUtil;
import org.apache.log4j.Logger;
import org.apache.cassandra.utils.*;
import org.apache.cassandra.config.DatabaseDescriptor;
public class UdpConnection extends SelectionKeyHandler
{
private static Logger logger_ = Logger.getLogger(UdpConnection.class);
private static final int BUFFER_SIZE = 4096;
private static final int protocol_ = 0xBADBEEF;
private DatagramChannel socketChannel_;
private SelectionKey key_;
public void init() throws IOException
{
socketChannel_ = DatagramChannel.open();
socketChannel_.socket().setReuseAddress(true);
socketChannel_.configureBlocking(false);
}
public void init(InetAddress localEp) throws IOException
{
socketChannel_ = DatagramChannel.open();
socketChannel_.socket().bind(new InetSocketAddress(localEp, DatabaseDescriptor.getControlPort()));
socketChannel_.socket().setReuseAddress(true);
socketChannel_.configureBlocking(false);
key_ = SelectorManager.getUdpSelectorManager().register(socketChannel_, this, SelectionKey.OP_READ);
}
public boolean write(Message message, InetAddress to) throws IOException
{
boolean bVal = true;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
Message.serializer().serialize(message, dos);
byte[] data = bos.toByteArray();
if ( data.length > 0 )
{
if (logger_.isTraceEnabled())
logger_.trace("Size of Gossip packet " + data.length);
byte[] protocol = FBUtilities.toByteArray(protocol_);
ByteBuffer buffer = ByteBuffer.allocate(data.length + protocol.length);
buffer.put( protocol );
buffer.put(data);
buffer.flip();
int n = socketChannel_.send(buffer, new InetSocketAddress(to, DatabaseDescriptor.getControlPort()));
if ( n == 0 )
{
bVal = false;
}
}
return bVal;
}
void close()
{
try
{
if ( socketChannel_ != null )
socketChannel_.close();
}
catch ( IOException ex )
{
logger_.error( LogUtil.throwableToString(ex) );
}
}
public DatagramChannel getDatagramChannel()
{
return socketChannel_;
}
private byte[] gobbleHeaderAndExtractBody(ByteBuffer buffer)
{
byte[] body = new byte[0];
byte[] protocol = new byte[4];
buffer = buffer.get(protocol, 0, protocol.length);
int value = FBUtilities.byteArrayToInt(protocol);
if ( protocol_ != value )
{
logger_.info("Invalid protocol header in the incoming message " + value);
return body;
}
body = new byte[buffer.remaining()];
buffer.get(body, 0, body.length);
return body;
}
public void read(SelectionKey key)
{
turnOffInterestOps(key, SelectionKey.OP_READ);
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
try
{
SocketAddress sa = socketChannel_.receive(buffer);
if ( sa == null )
{
if (logger_.isDebugEnabled())
logger_.debug("*** No datagram packet was available to be read ***");
return;
}
buffer.flip();
byte[] bytes = gobbleHeaderAndExtractBody(buffer);
if ( bytes.length > 0 )
{
DataInputStream dis = new DataInputStream( new ByteArrayInputStream(bytes) );
Message message = Message.serializer().deserialize(dis);
if ( message != null )
{
MessagingService.receive(message);
}
}
}
catch ( IOException ioe )
{
logger_.warn(LogUtil.throwableToString(ioe));
}
finally
{
turnOnInterestOps(key_, SelectionKey.OP_READ );
}
}
}
|