
uk.co.real_logic.aeron.driver.media.SendChannelEndpoint Maven / Gradle / Ivy
/*
* Copyright 2014 - 2015 Real Logic Ltd.
*
* 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.
*/
package uk.co.real_logic.aeron.driver.media;
import uk.co.real_logic.aeron.driver.event.EventLogger;
import uk.co.real_logic.aeron.protocol.NakFlyweight;
import uk.co.real_logic.aeron.protocol.StatusMessageFlyweight;
import uk.co.real_logic.aeron.driver.*;
import uk.co.real_logic.agrona.collections.BiInt2ObjectMap;
import uk.co.real_logic.agrona.collections.Int2ObjectHashMap;
import uk.co.real_logic.agrona.concurrent.AtomicCounter;
import uk.co.real_logic.agrona.concurrent.UnsafeBuffer;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import static uk.co.real_logic.aeron.logbuffer.FrameDescriptor.frameType;
import static uk.co.real_logic.aeron.protocol.HeaderFlyweight.HDR_TYPE_NAK;
import static uk.co.real_logic.aeron.protocol.HeaderFlyweight.HDR_TYPE_SM;
import static uk.co.real_logic.aeron.protocol.StatusMessageFlyweight.SEND_SETUP_FLAG;
/**
* Aggregator of multiple {@link NetworkPublication}s onto a single transport session for
* sending data and processing of control frames.
*/
public class SendChannelEndpoint extends UdpChannelTransport
{
private final NakFlyweight nakMessage;
private final StatusMessageFlyweight statusMessage;
private final Int2ObjectHashMap driversPublicationByStreamId = new Int2ObjectHashMap<>();
private final BiInt2ObjectMap sendersPublicationByStreamAndSessionId = new BiInt2ObjectMap<>();
private final AtomicCounter nakMessagesReceived;
private final AtomicCounter statusMessagesReceived;
public SendChannelEndpoint(
final UdpChannel udpChannel,
final EventLogger logger,
final LossGenerator lossGenerator,
final SystemCounters systemCounters)
{
super(
udpChannel,
udpChannel.remoteControl(),
udpChannel.localControl(),
udpChannel.remoteData(),
lossGenerator,
logger);
this.nakMessagesReceived = systemCounters.nakMessagesReceived();
this.statusMessagesReceived = systemCounters.statusMessagesReceived();
nakMessage = new NakFlyweight(receiveBuffer());
statusMessage = new StatusMessageFlyweight(receiveBuffer());
}
/**
* Called from the {@link Sender} to create the channel for the transport.
*/
public void openChannel()
{
openDatagramChannel();
}
public String originalUriString()
{
return udpChannel().originalUriString();
}
/**
* Called from the {@link DriverConductor} to find the publication associated with a sessionId and streamId
*
* @param streamId for the publication
* @return publication
*/
public NetworkPublication getPublication(final int streamId)
{
return driversPublicationByStreamId.get(streamId);
}
/**
* Called form the {@link DriverConductor} to associate a publication with a sessionId and streamId.
*
* @param publication to associate
*/
public void addPublication(final NetworkPublication publication)
{
driversPublicationByStreamId.put(publication.streamId(), publication);
}
/**
* Called from the {@link DriverConductor} to remove an association of a publication.
*
* @param publication to remove
* @return publication removed
*/
public NetworkPublication removePublication(final NetworkPublication publication)
{
return driversPublicationByStreamId.remove(publication.streamId());
}
/**
* Called from the {@link DriverConductor} to return the number of associated publications.
*
* @return number of publications associated.
*/
public int sessionCount()
{
return driversPublicationByStreamId.size();
}
/**
* Called from the {@link Sender} to add information to the control packet dispatcher.
*
* @param publication to add to the dispatcher
*/
public void registerForSend(final NetworkPublication publication)
{
sendersPublicationByStreamAndSessionId.put(publication.sessionId(), publication.streamId(), publication);
}
/**
* Called from the {@link Sender} to remove information from the control packet dispatcher.
*
* @param publication to remove
*/
public void unregisterForSend(final NetworkPublication publication)
{
sendersPublicationByStreamAndSessionId.remove(publication.sessionId(), publication.streamId());
}
public int pollForData()
{
int bytesReceived = 0;
final InetSocketAddress srcAddress = receive();
if (null != srcAddress)
{
final ByteBuffer receiveByteBuffer = receiveByteBuffer();
final int length = receiveByteBuffer.position();
logger().logFrameIn(receiveByteBuffer, 0, length, srcAddress);
final UnsafeBuffer receiveBuffer = receiveBuffer();
if (isValidFrame(receiveBuffer, length))
{
bytesReceived = dispatch(receiveBuffer, srcAddress);
}
}
return bytesReceived;
}
private int dispatch(final UnsafeBuffer buffer, final InetSocketAddress srcAddress)
{
int framesRead = 0;
switch (frameType(buffer, 0))
{
case HDR_TYPE_NAK:
onNakMessage(nakMessage);
framesRead = 1;
break;
case HDR_TYPE_SM:
onStatusMessage(statusMessage, srcAddress);
framesRead = 1;
break;
}
return framesRead;
}
private void onStatusMessage(final StatusMessageFlyweight statusMsg, final InetSocketAddress srcAddress)
{
final NetworkPublication publication = sendersPublicationByStreamAndSessionId.get(
statusMsg.sessionId(), statusMsg.streamId());
if (null != publication)
{
if (SEND_SETUP_FLAG == (statusMsg.flags() & SEND_SETUP_FLAG))
{
publication.triggerSendSetupFrame();
}
else
{
publication.onStatusMessage(
statusMsg.consumptionTermId(),
statusMsg.consumptionTermOffset(),
statusMsg.receiverWindowLength(),
srcAddress);
}
statusMessagesReceived.orderedIncrement();
}
}
private void onNakMessage(final NakFlyweight nakMsg)
{
final NetworkPublication publication = sendersPublicationByStreamAndSessionId.get(nakMsg.sessionId(), nakMsg.streamId());
if (null != publication)
{
publication.onNak(nakMsg.termId(), nakMsg.termOffset(), nakMsg.length());
nakMessagesReceived.orderedIncrement();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy