Skip to content

Commit

Permalink
Forwarded searches preserve TLS setting of original search
Browse files Browse the repository at this point in the history
  • Loading branch information
kasemir committed Aug 9, 2023
1 parent c1d0d7e commit 7dc08d4
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 24 deletions.
29 changes: 18 additions & 11 deletions core/pva/src/main/java/org/epics/pva/client/ChannelSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -403,13 +403,15 @@ else if (count == 0)
/** Issue a PVA server list request */
public void list()
{
final boolean tls = !PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank();

// Search is invoked for new SearchedChannel(channel, now)
// as well as by regular, timed search.
// Lock the send buffer to avoid concurrent use.
synchronized (send_buffer)
{
logger.log(Level.FINE, "List Request");
sendSearch(0, null);
sendSearch(0, null, tls);
}
}

Expand All @@ -418,13 +420,14 @@ public void list()
*/
private void search(final Collection<SearchRequest.Channel> channels)
{
// TODO How to decide if TCP search (EPICS_PVA_NAME_SERVERS) should use TLS?
// Configure via flags in EPICS_PVA_NAME_SERVERS?
// For now setting EPICS_PVA_TLS_KEYCHAIN enables TLS for all searches, UDP and TCP
final boolean tls = !PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank();

// Search via TCP
for (AddressInfo name_server : name_server_addresses)
{
// TODO How to decide if TCP search should use TLS?
// Configure via EPICS_PVA_NAME_SERVERS?
// For now configuring EPICS_PVA_TLS_KEYCHAIN enables TLS for all name server lookups
final boolean tls = !PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank();
final ClientTCPHandler tcp = tcp_provider.apply(name_server.getAddress(), tls);

// In case of connection errors (TCP connection blocked by firewall),
Expand All @@ -443,7 +446,7 @@ private void search(final Collection<SearchRequest.Channel> channels)
// Use 'any' reply address since reply will be via this TCP socket
final InetSocketAddress response_address = new InetSocketAddress(0);

SearchRequest.encode(true, seq, channels, response_address , buffer);
SearchRequest.encode(true, seq, channels, response_address, tls , buffer);
};
tcp.submit(search_request);
}
Expand All @@ -462,19 +465,23 @@ private void search(final Collection<SearchRequest.Channel> channels)
// match up duplicate packets and allows debugging bucket usage
final int seq = current_search_bucket.get();
logger.log(Level.FINE, () -> "UDP Search Request #" + seq + " for " + channels);
sendSearch(seq, channels);
sendSearch(seq, channels, tls);
}
}

/** Send a 'list' or channel search out via UDP */
private void sendSearch(final int seq, final Collection<SearchRequest.Channel> channels)
/** Send a 'list' or channel search out via UDP
* @param seq Search sequence number
* @param channels Channels to search, <code>null</code> for listing channels
* @param tls Use TLS?
*/
private void sendSearch(final int seq, final Collection<SearchRequest.Channel> channels, final boolean tls)
{
// Buffer starts out with UNICAST bit set in the search message
for (AddressInfo addr : unicast_search_addresses)
{
send_buffer.clear();
final InetSocketAddress response = udp.getResponseAddress(addr);
SearchRequest.encode(true, seq, channels, response, send_buffer);
SearchRequest.encode(true, seq, channels, response, tls, send_buffer);
send_buffer.flip();
try
{
Expand All @@ -492,7 +499,7 @@ private void sendSearch(final int seq, final Collection<SearchRequest.Channel> c
{
send_buffer.clear();
final InetSocketAddress response = udp.getResponseAddress(addr);
SearchRequest.encode(false, seq, channels, response, send_buffer);
SearchRequest.encode(false, seq, channels, response, tls, send_buffer);
send_buffer.flip();
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ private boolean handleSearchRequest(final InetSocketAddress from, final byte ver
if (search.reply_required)
{
forward_buffer.clear();
SearchRequest.encode(false, 0, null, search.client, forward_buffer);
SearchRequest.encode(false, 0, null, search.client, search.tls, forward_buffer);
forward_buffer.flip();
logger.log(Level.FINER, () -> "Forward search to list servers to " + local_multicast + "\n" + Hexdump.toHexdump(forward_buffer));
send(forward_buffer, local_multicast);
Expand All @@ -293,7 +293,7 @@ private boolean handleSearchRequest(final InetSocketAddress from, final byte ver
else
{
forward_buffer.clear();
SearchRequest.encode(false, search.seq, search.channels, search.client, forward_buffer);
SearchRequest.encode(false, search.seq, search.channels, search.client, search.tls, forward_buffer);
forward_buffer.flip();
logger.log(Level.FINER, () -> "Forward search to " + local_multicast + "\n" + Hexdump.toHexdump(forward_buffer));
send(forward_buffer, local_multicast);
Expand Down
13 changes: 6 additions & 7 deletions core/pva/src/main/java/org/epics/pva/common/SearchRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import java.util.List;
import java.util.logging.Level;

import org.epics.pva.PVASettings;
import org.epics.pva.data.PVAAddress;
import org.epics.pva.data.PVAString;

Expand Down Expand Up @@ -183,9 +182,10 @@ else if ("tcp".equals(protocol))
* @param seq Sequence number
* @param channels Channels to search, <code>null</code> for 'list'
* @param address client's address
* @param tls Use TLS?
* @param buffer Buffer into which to encode
*/
public static void encode(final boolean unicast, final int seq, final Collection<Channel> channels, final InetSocketAddress address, final ByteBuffer buffer)
public static void encode(final boolean unicast, final int seq, final Collection<Channel> channels, final InetSocketAddress address, final boolean tls, final ByteBuffer buffer)
{
// Create with zero payload size, to be patched later
PVAHeader.encodeMessageHeader(buffer, PVAHeader.FLAG_NONE, PVAHeader.CMD_SEARCH, 0);
Expand Down Expand Up @@ -225,15 +225,14 @@ public static void encode(final boolean unicast, final int seq, final Collection
}
else
{
// Only support tcp, or both tls and tcp?
// TODO pass 'use_tls' in because encode might also be called by ServerUDPHandler.forwardSearchRequest
if (PVASettings.EPICS_PVA_TLS_KEYCHAIN.isBlank())
buffer.put((byte)1);
else
// Support both tls and tcp, or only tcp?
if (tls)
{
buffer.put((byte)2);
PVAString.encodeString("tls", buffer);
}
else
buffer.put((byte)1);
PVAString.encodeString("tcp", buffer);

buffer.putShort((short)channels.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ private boolean handleSearch(final InetSocketAddress from, final byte version,
{ // pvlist request
final boolean handled = server.handleSearchRequest(0, -1, null, search.client, search.tls, null);
if (! handled && search.unicast)
PVAServer.POOL.submit(() -> forwardSearchRequest(0, null, search.client));
PVAServer.POOL.submit(() -> forwardSearchRequest(0, null, search.client, search.tls));
}
}
else
Expand All @@ -205,7 +205,7 @@ private boolean handleSearch(final InetSocketAddress from, final byte version,
if (forward != null)
{
final List<SearchRequest.Channel> to_forward = forward;
PVAServer.POOL.submit(() -> forwardSearchRequest(search.seq, to_forward, search.client));
PVAServer.POOL.submit(() -> forwardSearchRequest(search.seq, to_forward, search.client, search.tls));
}
}

Expand All @@ -223,16 +223,17 @@ private boolean handleSearch(final InetSocketAddress from, final byte version,
* @param seq Search sequence or 0
* @param channels Channel CIDs and names or <code>null</code> for 'list'
* @param address Client's address and port
* @param tls Use TLS or plain TCP?
*/
private void forwardSearchRequest(final int seq, final Collection<SearchRequest.Channel> channels, final InetSocketAddress address)
private void forwardSearchRequest(final int seq, final Collection<SearchRequest.Channel> channels, final InetSocketAddress address, final boolean tls)
{
// TODO Remove the local IPv4 multicast re-send from the protocol, just use multicast from the start as with IPv6
if (local_multicast == null)
return;
synchronized (send_buffer)
{
send_buffer.clear();
SearchRequest.encode(false, seq, channels, address, send_buffer);
SearchRequest.encode(false, seq, channels, address, tls, send_buffer);
send_buffer.flip();
logger.log(Level.FINER, () -> "Forward search to " + local_multicast + "\n" + Hexdump.toHexdump(send_buffer));
try
Expand Down

0 comments on commit 7dc08d4

Please sign in to comment.