Skip to content

Commit 9f5b7fb

Browse files
authored
Merge pull request #3423 from ControlSystemStudio/pva_echo
PVA: Add sequence to 'echo'
2 parents c1fcdc7 + 84e1d11 commit 9f5b7fb

File tree

5 files changed

+49
-20
lines changed

5 files changed

+49
-20
lines changed

core/pva/src/main/java/org/epics/pva/client/ClientTCPHandler.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ class ClientTCPHandler extends TCPHandler
9898
/** Time [ms] when this client sent last message to server */
9999
private volatile long last_message_sent;
100100

101-
private static final RequestEncoder echo_request = new EchoRequest();
101+
/** Creates echo requests, tracks the counter for this TCP connection */
102+
private final EchoRequest echo_request = new EchoRequest();
102103

103104
/** Indicates completion of the connection validation:
104105
* Server sent connection validation request,
@@ -112,7 +113,7 @@ class ClientTCPHandler extends TCPHandler
112113
public ClientTCPHandler(final PVAClient client, final InetSocketAddress address, final Guid guid, final boolean tls) throws Exception
113114
{
114115
super(createSocket(address, tls), true);
115-
logger.log(Level.FINE, () -> "TCPHandler " + guid + " for " + address + " created ============================");
116+
logger.log(Level.FINE, () -> "TCPHandler " + (tls ? "(TLS) " : "") + guid + " for " + address + " created ============================");
116117
this.client = client;
117118
this.guid = guid;
118119

@@ -248,7 +249,7 @@ private void checkResponsiveness()
248249
if (idle > PVASettings.EPICS_PVA_CONN_TMO * 1000)
249250
{
250251
// If silent for full EPICS_CA_CONN_TMO, disconnect and start over
251-
logger.log(Level.FINE, () -> this + " silent for " + idle + "ms, closing");
252+
logger.log(Level.FINE, () -> this + " idle for " + idle + "ms, closing");
252253
client.shutdownConnection(this);
253254
return;
254255
}
@@ -268,13 +269,13 @@ private void checkResponsiveness()
268269
request_echo = true;
269270
}
270271

271-
// How long have we been silent, which could case the server to close connection?
272+
// How long have we been silent, which could cause the server to close connection?
272273
final long silent = now - last_message_sent;
273274
if (! request_echo && silent >= PVASettings.EPICS_PVA_CONN_TMO * 1000 / 2)
274275
{
275276
// With default EPICS_CA_CONN_TMO of 30 seconds,
276-
// Echo requested every 15 seconds.
277-
logger.log(Level.FINE, () -> "Client to " + this + " silent for " + silent + "ms, requesting echo");
277+
// Echo sent every 15 seconds to inform server that this client is still alive.
278+
logger.log(Level.FINE, () -> "Client to " + this + " silent for " + silent + "ms, sending echo");
278279
request_echo = true;
279280
}
280281

@@ -289,6 +290,12 @@ private void checkResponsiveness()
289290
}
290291
}
291292

293+
/** @return Most recently sent echo request */
294+
String getActiveEchoRequest()
295+
{
296+
return echo_request.getActiveRequest();
297+
}
298+
292299
/** Called whenever e.g. value is received and server is thus alive */
293300
void markAlive()
294301
{

core/pva/src/main/java/org/epics/pva/client/ClientUDPHandler.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2019-2023 Oak Ridge National Laboratory.
2+
* Copyright (c) 2019-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
1616
import java.net.StandardSocketOptions;
1717
import java.nio.ByteBuffer;
1818
import java.nio.channels.DatagramChannel;
19+
import java.util.Arrays;
1920
import java.util.logging.Level;
2021

2122
import org.epics.pva.PVASettings;
@@ -337,7 +338,15 @@ private boolean handleSearchReply(final InetSocketAddress from, final byte versi
337338

338339
// Server may reply with list of PVs that it does _not_ have...
339340
if (! response.found)
340-
search_response.handleSearchResponse(-1, server, version, response.guid, response.tls);
341+
{
342+
// Did server provide list of channels that it _doesn't_ know?!
343+
if (response.cid.length > 0)
344+
logger.log(Level.FINE,
345+
"Server " + from + " sent search reply for not-found channels " +
346+
Arrays.toString(response.cid));
347+
else // Server simply indicates its presence, no channel detail
348+
search_response.handleSearchResponse(-1, server, version, response.guid, response.tls);
349+
}
341350
else
342351
for (int cid : response.cid)
343352
search_response.handleSearchResponse(cid, server, version, response.guid, response.tls);

core/pva/src/main/java/org/epics/pva/client/EchoHandler.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2019 Oak Ridge National Laboratory.
2+
* Copyright (c) 2019-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -37,11 +37,12 @@ public void handleCommand(final ClientTCPHandler tcp, final ByteBuffer buffer) t
3737
{
3838
final byte[] payload = new byte[payload_size];
3939
buffer.get(payload);
40-
if (Arrays.equals(payload, EchoRequest.CHECK))
40+
final String expected = tcp.getActiveEchoRequest();
41+
if (Arrays.equals(payload, expected.getBytes()))
4142
logger.log(Level.FINE, () -> "Received ECHO:\n" + Hexdump.toHexdump(payload));
4243
else
4344
{
44-
logger.log(Level.WARNING, this + " received invalid echo reply:\n" +
45+
logger.log(Level.WARNING, this + " received invalid echo reply, expected " + expected + ":\n" +
4546
Hexdump.toHexdump(payload));
4647
return;
4748
}

core/pva/src/main/java/org/epics/pva/client/EchoRequest.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2019 Oak Ridge National Laboratory.
2+
* Copyright (c) 2019-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
1010
import static org.epics.pva.PVASettings.logger;
1111

1212
import java.nio.ByteBuffer;
13+
import java.util.concurrent.atomic.AtomicInteger;
1314
import java.util.logging.Level;
1415

1516
import org.epics.pva.common.PVAHeader;
@@ -21,7 +22,9 @@
2122
@SuppressWarnings("nls")
2223
class EchoRequest implements RequestEncoder
2324
{
24-
static final byte[] CHECK = new byte[] { 'e', 'c', 'h', 'o' };
25+
// Random number so replies don't all start with 'echo00'
26+
private final AtomicInteger counter = new AtomicInteger((int)(Math.random() * 100));
27+
private volatile String active_check = "";
2528

2629
@Override
2730
public void encodeRequest(final byte version, final ByteBuffer buffer) throws Exception
@@ -33,10 +36,19 @@ public void encodeRequest(final byte version, final ByteBuffer buffer) throws Ex
3336
PVAHeader.encodeMessageHeader(buffer, PVAHeader.FLAG_NONE, PVAHeader.CMD_ECHO, 0);
3437
}
3538
else
36-
{
39+
{ // Issue next 'echo12'
40+
final int count = counter.incrementAndGet();
41+
active_check = String.format("echo%02d", count % 100);
42+
final byte[] check = active_check.getBytes();
3743
logger.log(Level.FINE, () -> "Sending ECHO request (Version " + version + ")");
38-
PVAHeader.encodeMessageHeader(buffer, PVAHeader.FLAG_NONE, PVAHeader.CMD_ECHO, CHECK.length);
39-
buffer.put(CHECK);
44+
PVAHeader.encodeMessageHeader(buffer, PVAHeader.FLAG_NONE, PVAHeader.CMD_ECHO, check.length);
45+
buffer.put(check);
4046
}
4147
}
48+
49+
/** @return Most recently sent echo request */
50+
public String getActiveRequest()
51+
{
52+
return active_check;
53+
}
4254
}

core/pva/src/main/java/org/epics/pva/client/PVAClient.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2019-2023 Oak Ridge National Laboratory.
2+
* Copyright (c) 2019-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -124,9 +124,9 @@ public Collection<ServerInfo> list(final TimeUnit unit, final long duration) thr
124124
return list_replies.values();
125125
}
126126

127-
private void handleListResponse(final InetSocketAddress server, final int version, final Guid guid)
127+
private void handleListResponse(final InetSocketAddress server, final int version, final Guid guid, final boolean tls)
128128
{
129-
logger.log(Level.FINE, () -> guid + " version " + version + ": tcp@" + server);
129+
logger.log(Level.FINE, () -> "Server list response: " + guid + " version " + version + ", tcp@" + server + (tls ? " (TLS)" : ""));
130130
final ServerInfo info = list_replies.computeIfAbsent(guid, g -> new ServerInfo(g));
131131
info.version = version;
132132
info.addresses.add(server);
@@ -221,7 +221,7 @@ void handleSearchResponse(final int channel_id, final InetSocketAddress server,
221221
// Generic server 'list' response?
222222
if (channel_id < 0)
223223
{
224-
handleListResponse(server, version, guid);
224+
handleListResponse(server, version, guid, tls);
225225
return;
226226
}
227227

0 commit comments

Comments
 (0)