Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.cxf.transport.udp.UDPConduit Maven / Gradle / Ivy
/**
* 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.cxf.transport.udp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.InterfaceAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.URI;
import java.util.Enumeration;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.apache.cxf.Bus;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.helpers.LoadingByteArrayOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.transport.AbstractConduit;
import org.apache.cxf.workqueue.WorkQueue;
import org.apache.cxf.workqueue.WorkQueueManager;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.DatagramSessionConfig;
import org.apache.mina.transport.socket.nio.NioDatagramConnector;
/**
*
*/
public class UDPConduit extends AbstractConduit {
private static final String CXF_MESSAGE_ATTR = "CXFMessage";
private static final String MULTI_RESPONSE_TIMEOUT = "udp.multi.response.timeout";
private static final String HOST_PORT = UDPConduit.class + ".host:port";
private static final Logger LOG = LogUtils.getL7dLogger(UDPDestination.class);
Bus bus;
NioDatagramConnector connector = new NioDatagramConnector();
ConcurrentHashMap> connections
= new ConcurrentHashMap>();
public UDPConduit(EndpointReferenceType t,
final Bus bus) {
super(t);
this.bus = bus;
connector.getSessionConfig().setReadBufferSize(64 * 1024);
connector.getSessionConfig().setSendBufferSize(64 * 1024);
connector.setHandler(new IoHandlerAdapter() {
public void messageReceived(IoSession session, Object buf) {
Message message = (Message)session.getAttribute(CXF_MESSAGE_ATTR);
dataReceived(message, (IoBuffer)buf, true);
}
});
}
private void dataReceived(Message message, IoBuffer buf, boolean async) {
if (message.getExchange().getInMessage() == null) {
final Message inMessage = new MessageImpl();
inMessage.setExchange(message.getExchange());
message.getExchange().setInMessage(inMessage);
IoSessionInputStream ins = new IoSessionInputStream(buf);
inMessage.setContent(InputStream.class, ins);
inMessage.put(IoSessionInputStream.class, ins);
if (async) {
WorkQueueManager queuem = bus.getExtension(WorkQueueManager.class);
WorkQueue queue = queuem.getNamedWorkQueue("udp-conduit");
if (queue == null) {
queue = queuem.getAutomaticWorkQueue();
}
queue.execute(new Runnable() {
public void run() {
incomingObserver.onMessage(inMessage);
}
});
} else {
incomingObserver.onMessage(inMessage);
if (!message.getExchange().isSynchronous()) {
message.getExchange().setInMessage(null);
}
}
} else {
IoSessionInputStream ins = message.getExchange().getInMessage().get(IoSessionInputStream.class);
ins.setBuffer((IoBuffer)buf);
}
}
public void close(Message msg) throws IOException {
super.close(msg);
if (msg.getExchange().isOneWay()
|| msg.getExchange().getInMessage() == msg
|| msg.getExchange().getInFaultMessage() == msg) {
String s = (String)msg.getExchange().get(HOST_PORT);
ConnectFuture c = msg.getExchange().get(ConnectFuture.class);
if (s != null && c != null) {
c.getSession().removeAttribute(CXF_MESSAGE_ATTR);
Queue q = connections.get(s);
if (q == null) {
connections.putIfAbsent(s, new ArrayBlockingQueue(10));
q = connections.get(s);
}
if (!q.offer(c)) {
c.getSession().close(false);
}
}
}
}
public void close() {
super.close();
for (Queue f : connections.values()) {
for (ConnectFuture cf : f) {
cf.getSession().close(false);
}
}
connections.clear();
connector.dispose();
connector = null;
}
public void prepare(final Message message) throws IOException {
try {
String address = (String)message.get(Message.ENDPOINT_ADDRESS);
if (StringUtils.isEmpty(address)) {
address = this.getTarget().getAddress().getValue();
}
URI uri = new URI(address);
if (StringUtils.isEmpty(uri.getHost())) {
//NIO doesn't support broadcast, we need to drop down to raw
//java.io for these
String s = uri.getSchemeSpecificPart();
if (s.startsWith("//:")) {
s = s.substring(3);
}
if (s.indexOf('/') != -1) {
s = s.substring(0, s.indexOf('/'));
}
int port = Integer.parseInt(s);
sendViaBroadcast(message, null, port);
} else {
InetSocketAddress isa = null;
String hp = "";
isa = new InetSocketAddress(uri.getHost(), uri.getPort());
hp = uri.getHost() + ":" + uri.getPort();
if (isa.getAddress().isMulticastAddress()) {
sendViaBroadcast(message, isa, isa.getPort());
return;
}
Queue q = connections.get(hp);
ConnectFuture connFuture = null;
if (q != null) {
connFuture = q.poll();
}
if (connFuture == null) {
connFuture = connector.connect(isa);
connFuture.await();
((DatagramSessionConfig)connFuture.getSession().getConfig()).setSendBufferSize(64 * 1024);
((DatagramSessionConfig)connFuture.getSession().getConfig()).setReceiveBufferSize(64 * 1024);
}
connFuture.getSession().setAttribute(CXF_MESSAGE_ATTR, message);
message.setContent(OutputStream.class, new UDPConduitOutputStream(connector, connFuture, message));
message.getExchange().put(ConnectFuture.class, connFuture);
message.getExchange().put(HOST_PORT, uri.getHost() + ":" + uri.getPort());
}
} catch (Exception ex) {
throw new IOException(ex);
}
}
private void sendViaBroadcast(Message message, InetSocketAddress isa, int port) {
message.setContent(OutputStream.class,
new UDPBroadcastOutputStream(port, isa, message));
}
private final class UDPBroadcastOutputStream extends LoadingByteArrayOutputStream {
private final int port;
private final Message message;
private final InetSocketAddress multicast;
private UDPBroadcastOutputStream(int port, InetSocketAddress isa, Message message) {
this.port = port;
this.message = message;
this.multicast = isa;
}
public void close() throws IOException {
super.close();
DatagramSocket socket;
if (multicast != null) {
socket = new MulticastSocket(null);
} else {
socket = new DatagramSocket();
}
socket.setSendBufferSize(this.size());
socket.setReceiveBufferSize(64 * 1024);
socket.setBroadcast(true);
if (multicast == null) {
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
if (!networkInterface.isUp() || networkInterface.isLoopback()) {
continue;
}
for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
InetAddress broadcast = interfaceAddress.getBroadcast();
if (broadcast == null) {
continue;
}
DatagramPacket sendPacket = new DatagramPacket(this.getRawBytes(),
0,
this.size(),
broadcast,
port);
try {
socket.send(sendPacket);
} catch (Exception e) {
//ignore
}
}
}
} else {
DatagramPacket sendPacket = new DatagramPacket(this.getRawBytes(),
0,
this.size(),
multicast);
try {
socket.send(sendPacket);
} catch (Exception e) {
//ignore
}
}
if (!message.getExchange().isOneWay()) {
byte bytes[] = new byte[64 * 1024];
DatagramPacket p = new DatagramPacket(bytes, bytes.length);
Object to = message.getContextualProperty(MULTI_RESPONSE_TIMEOUT);
Integer i = null;
if (to instanceof String) {
i = Integer.parseInt((String)to);
} else if (to instanceof Integer) {
i = (Integer)to;
}
if (i == null || i <= 0 || message.getExchange().isSynchronous()) {
socket.setSoTimeout(30000);
socket.receive(p);
dataReceived(message, IoBuffer.wrap(bytes, 0, p.getLength()), false);
} else {
socket.setSoTimeout(i);
boolean found = false;
try {
while (true) {
socket.receive(p);
dataReceived(message, IoBuffer.wrap(bytes, 0, p.getLength()), false);
found = true;
}
} catch (java.net.SocketTimeoutException ex) {
if (!found) {
throw ex;
}
}
}
}
socket.close();
}
public void flush() throws IOException {
}
}
public class UDPConduitOutputStream extends OutputStream {
final ConnectFuture future;
final NioDatagramConnector connector;
final Message message;
IoBuffer buffer = IoBuffer.allocate(64 * 1024 - 42); //max size
boolean closed;
public UDPConduitOutputStream(NioDatagramConnector connector,
ConnectFuture connFuture,
Message m) {
this.connector = connector;
this.future = connFuture;
this.message = m;
}
public void write(int b) throws IOException {
buffer.put(new byte[] {(byte)b}, 0, 1);
}
public void write(byte b[], int off, int len) throws IOException {
while (len > buffer.remaining()) {
int nlen = buffer.remaining();
buffer.put(b, off, nlen);
len -= nlen;
off += nlen;
send();
buffer = IoBuffer.allocate((64 * 1024) - 42);
}
buffer.put(b, off, len);
}
private void send() throws IOException {
try {
future.await();
} catch (InterruptedException e) {
if (future.getException() != null) {
throw new IOException(future.getException());
}
throw new IOException(e);
}
if (future.getException() != null) {
throw new IOException(future.getException());
}
buffer.flip();
future.getSession().write(buffer);
}
public void close() throws IOException {
if (closed) {
return;
}
closed = true;
send();
}
}
protected Logger getLogger() {
return LOG;
}
}