Skip to content

Commit 30823f5

Browse files
Merge pull request #31 from trendmicro/update_to_latest_version_v1.6.3
update to latest version: v1.6.3
2 parents 97906b6 + b8a2ff7 commit 30823f5

10 files changed

Lines changed: 240 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## 1.6.3 - 2026-04-13
4+
5+
- Support new regions af-south-1
6+
- Fix timeout issue
7+
38
## 1.6.2 - 2026-01-19
49

510
- Support new regions eu-west-2 and ca-central-1

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ Creates a new instance of the `AmaasClient` class, and provisions essential sett
187187

188188
| Parameter | Description |
189189
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
190-
| region | The region you obtained your api key. Value provided must be one of the Vision One regions, e.g. `us-east-1`, `eu-central-1`, `ap-northeast-1`, `ap-southeast-2`, `ap-southeast-1`, `ap-south-1`, `me-central-1`,`eu-west-2`,`ca-central-1`, etc. If host is given, region will be ignored. |
190+
| region | The region you obtained your api key. Value provided must be one of the Vision One regions, e.g. `us-east-1`, `eu-central-1`, `ap-northeast-1`, `ap-southeast-2`, `ap-southeast-1`, `ap-south-1`, `me-central-1`,`eu-west-2`,`ca-central-1`,`af-south-1`, etc. If host is given, region will be ignored. |
191191
| host | The host ip address of self hosted AMaaS scanner. Ignore if to use Trend AMaaS service |
192192
| apikey | Your own Vision One API Key. |
193193
| timeoutInSecs | Timeout to cancel the connection to server in seconds. Valid value is 0, 1, 2, ... ; default to 300 seconds. |
@@ -205,7 +205,7 @@ Creates a new instance of the `AmaasClient` class, and provisions essential sett
205205

206206
| Parameter | Description |
207207
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
208-
| region | The region you obtained your api key. Value provided must be one of the Vision One regions, e.g. `us-east-1`, `eu-central-1`, `ap-northeast-1`, `ap-southeast-2`, `ap-southeast-1`, `ap-south-1`, `me-central-1`,`eu-west-2`,`ca-central-1` ,etc. |
208+
| region | The region you obtained your api key. Value provided must be one of the Vision One regions, e.g. `us-east-1`, `eu-central-1`, `ap-northeast-1`, `ap-southeast-2`, `ap-southeast-1`, `ap-south-1`, `me-central-1`,`eu-west-2`,`ca-central-1`,`af-south-1` ,etc. |
209209
| apikey | Your own Vision One API Key. |
210210
| timeoutInSecs | Timeout to cancel the connection to server in seconds. Valid value is 0, 1, 2, ... ; default to 300 seconds. |
211211

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.6.2
1+
1.6.3

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.trend</groupId>
88
<artifactId>file-security-java-sdk</artifactId>
9-
<version>1.6.2</version>
9+
<version>1.6.3</version>
1010

1111
<name>file-security-java-sdk</name>
1212
<url>https://github.com/trendmicro/tm-v1-fs-java-sdk</url>

protos/scan.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ enum Stage {
1515
STAGE_INIT = 0;
1616
STAGE_RUN = 1;
1717
STAGE_FINI = 2;
18+
STAGE_HEARTBEAT = 3;
1819
}
1920

2021
message C2S {

src/main/java/com/trend/cloudone/amaas/AMaasClient.java

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import java.nio.file.Paths;
77
import java.util.Arrays;
88
import java.util.concurrent.CountDownLatch;
9+
import java.util.concurrent.Executors;
10+
import java.util.concurrent.ScheduledExecutorService;
911
import java.util.concurrent.TimeUnit;
1012
import java.util.logging.Level;
1113
import java.util.logging.Logger;
@@ -304,6 +306,7 @@ private static void log(final Level level, final String msg, final Object... par
304306
*/
305307
static class AMaasServerCallback implements StreamObserver<ScanOuterClass.S2C> {
306308
private static final int POLL_TIME_MILLIS = 200;
309+
static final int DEFAULT_HEARTBEAT_INTERVAL_MS = 30 * 1000;
307310

308311
private StreamObserver<ScanOuterClass.C2S> requestObserver;
309312
private AMaasReader reader;
@@ -316,10 +319,57 @@ static class AMaasServerCallback implements StreamObserver<ScanOuterClass.S2C> {
316319
private boolean bulk = true;
317320
private long start = System.currentTimeMillis();
318321
private long timeoutSecs;
322+
private final Object streamLock = new Object();
323+
private volatile boolean streamClosed = false;
324+
private ScheduledExecutorService heartbeatExecutor = null;
325+
private int heartbeatIntervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS;
319326

320327
AMaasServerCallback() {
321328
}
322329

330+
void setHeartbeatIntervalMs(final int intervalMs) {
331+
this.heartbeatIntervalMs = intervalMs;
332+
}
333+
334+
protected void startHeartbeat() {
335+
heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(new java.util.concurrent.ThreadFactory() {
336+
@Override
337+
public Thread newThread(final Runnable r) {
338+
Thread t = new Thread(r, "amaas-heartbeat");
339+
t.setDaemon(true);
340+
return t;
341+
}
342+
});
343+
heartbeatExecutor.scheduleAtFixedRate(new Runnable() {
344+
@Override
345+
public void run() {
346+
if (streamClosed) {
347+
return;
348+
}
349+
ScanOuterClass.C2S hb = ScanOuterClass.C2S.newBuilder()
350+
.setStage(Stage.STAGE_HEARTBEAT)
351+
.build();
352+
synchronized (streamLock) {
353+
if (!streamClosed) {
354+
try {
355+
requestObserver.onNext(hb);
356+
log(Level.FINE, "Sent heartbeat");
357+
} catch (Exception e) {
358+
log(Level.WARNING, "Heartbeat send failed: {0}", e.getMessage());
359+
}
360+
}
361+
}
362+
}
363+
}, heartbeatIntervalMs, heartbeatIntervalMs, TimeUnit.MILLISECONDS);
364+
}
365+
366+
protected void stopHeartbeat() {
367+
if (heartbeatExecutor != null) {
368+
heartbeatExecutor.shutdownNow();
369+
heartbeatExecutor = null;
370+
}
371+
}
372+
323373
private AMaasException processError() {
324374
AMaasException err = null;
325375
if (this.grpcStatus == Status.Code.UNAUTHENTICATED) {
@@ -363,7 +413,13 @@ public void onNext(final ScanOuterClass.S2C s2cMsg) {
363413
case CMD_RETR:
364414
if (s2cMsg.getStage() != Stage.STAGE_RUN) {
365415
log(Level.INFO, "Received unexpected command RETR at stage {0}", s2cMsg.getStage());
366-
requestObserver.onError(new StatusRuntimeException(Status.ABORTED));
416+
synchronized (streamLock) {
417+
if (!streamClosed) {
418+
streamClosed = true;
419+
requestObserver.onError(new StatusRuntimeException(Status.ABORTED));
420+
}
421+
}
422+
return;
367423
}
368424
java.util.List<java.lang.Integer> bulkLength;
369425
java.util.List<java.lang.Integer> bulkOffset;
@@ -401,30 +457,55 @@ public void onNext(final ScanOuterClass.S2C s2cMsg) {
401457

402458
if (TimeUnit.MILLISECONDS.toSeconds(duration) > this.timeoutSecs) {
403459
log(Level.INFO, "DEADLINE_EXCEEDED {0}", duration);
404-
requestObserver.onError(new StatusRuntimeException(Status.DEADLINE_EXCEEDED));
460+
synchronized (streamLock) {
461+
if (!streamClosed) {
462+
streamClosed = true;
463+
requestObserver.onError(new StatusRuntimeException(Status.DEADLINE_EXCEEDED));
464+
}
465+
}
405466
return;
406467
}
407468
}
408-
requestObserver.onNext(request);
469+
synchronized (streamLock) {
470+
if (!streamClosed) {
471+
requestObserver.onNext(request);
472+
}
473+
}
409474
} catch (IOException e) {
410475
log(Level.SEVERE, "Exception when processing server message", e.getMessage());
411-
requestObserver.onError(new StatusRuntimeException(Status.ABORTED));
476+
synchronized (streamLock) {
477+
if (!streamClosed) {
478+
streamClosed = true;
479+
requestObserver.onError(new StatusRuntimeException(Status.ABORTED));
480+
}
481+
}
412482
}
413483
}
414484
break;
415485
case CMD_QUIT:
416486
this.scanResult = s2cMsg.getResult();
417487
log(Level.INFO, "Scan succeeded: result={0} fetchCount={1} fetchSize={2}.", this.scanResult, this.fetchCount, this.fetchSize);
418-
requestObserver.onCompleted();
488+
synchronized (streamLock) {
489+
streamClosed = true;
490+
requestObserver.onCompleted();
491+
}
419492
break;
420493
default:
421494
log(Level.WARNING, "Unknown command");
422-
requestObserver.onError(new StatusRuntimeException(Status.INVALID_ARGUMENT));
495+
synchronized (streamLock) {
496+
if (!streamClosed) {
497+
streamClosed = true;
498+
requestObserver.onError(new StatusRuntimeException(Status.INVALID_ARGUMENT));
499+
}
500+
}
423501
}
424502
}
425503

426504
@Override
427505
public void onError(final Throwable t) {
506+
synchronized (streamLock) {
507+
streamClosed = true;
508+
}
428509
log(Level.WARNING, "scan Failed: {0}", Status.fromThrowable(t));
429510
this.done = true;
430511
this.grpcStatus = Status.fromThrowable(t).getCode();
@@ -433,6 +514,9 @@ public void onError(final Throwable t) {
433514

434515
@Override
435516
public void onCompleted() {
517+
synchronized (streamLock) {
518+
streamClosed = true;
519+
}
436520
log(Level.INFO, "File successfully scanned.");
437521
this.done = true;
438522
this.grpcStatus = Status.Code.OK;
@@ -528,10 +612,13 @@ public String scanRun(final AMaasReader reader, final AMaasScanOptions options)
528612
ScanOuterClass.C2S request = builder.build();
529613

530614
requestObserver.onNext(request);
615+
serverCallback.startHeartbeat();
531616

532-
String scanResult = serverCallback.waitTilExit();
533-
534-
return scanResult;
617+
try {
618+
return serverCallback.waitTilExit();
619+
} finally {
620+
serverCallback.stopHeartbeat();
621+
}
535622
}
536623

537624
/**

src/main/java/com/trend/cloudone/amaas/AMaasRegion.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ final class AMaasRegion {
2525
static final String AWS_TREND_REGION = "us-east-2";
2626
static final String AWS_GB_REGION = "eu-west-2";
2727
static final String AWS_AE_REGION = "me-central-1";
28+
static final String AWS_ZA_REGION = "af-south-1";
2829
static final String C1_JP_REGION = "jp-1";
2930
static final String C1_SG_REGION = "sg-1";
3031
static final String C1_AU_REGION = "au-1";
@@ -35,11 +36,12 @@ final class AMaasRegion {
3536
static final String C1_TREND_REGION = "trend-us-1";
3637
static final String C1_GB_REGION = "gb-1";
3738
static final String C1_AE_REGION = "ae-1";
39+
static final String C1_ZA_REGION = "za-1";
3840

39-
static final List<String> C1_REGIONS = Arrays.asList(new String[]{C1_AU_REGION, C1_CA_REGION, C1_DE_REGION, C1_GB_REGION, C1_IN_REGION, C1_JP_REGION, C1_SG_REGION, C1_US_REGION, C1_TREND_REGION});
40-
static final List<String> V1_REGIONS = Arrays.asList(new String[]{AWS_AU_REGION, AWS_CA_REGION, AWS_DE_REGION, AWS_GB_REGION, AWS_IN_REGION, AWS_JP_REGION, AWS_SG_REGION, AWS_US_REGION, AWS_AE_REGION});
41-
static final List<String> SUPPORTED_V1_REGIONS = Arrays.asList(new String[]{AWS_AU_REGION, AWS_DE_REGION, AWS_JP_REGION, AWS_SG_REGION, AWS_US_REGION, AWS_IN_REGION, AWS_AE_REGION, AWS_CA_REGION, AWS_GB_REGION});
42-
static final List<String> SUPPORTED_C1_REGIONS = Arrays.asList(new String[]{C1_AU_REGION, C1_CA_REGION, C1_DE_REGION, C1_GB_REGION, C1_IN_REGION, C1_JP_REGION, C1_SG_REGION, C1_US_REGION});
41+
static final List<String> C1_REGIONS = Arrays.asList(new String[]{C1_AU_REGION, C1_CA_REGION, C1_DE_REGION, C1_GB_REGION, C1_IN_REGION, C1_JP_REGION, C1_SG_REGION, C1_US_REGION, C1_TREND_REGION, C1_ZA_REGION});
42+
static final List<String> V1_REGIONS = Arrays.asList(new String[]{AWS_AU_REGION, AWS_CA_REGION, AWS_DE_REGION, AWS_GB_REGION, AWS_IN_REGION, AWS_JP_REGION, AWS_SG_REGION, AWS_US_REGION, AWS_AE_REGION, AWS_ZA_REGION});
43+
static final List<String> SUPPORTED_V1_REGIONS = Arrays.asList(new String[]{AWS_AU_REGION, AWS_DE_REGION, AWS_JP_REGION, AWS_SG_REGION, AWS_US_REGION, AWS_IN_REGION, AWS_AE_REGION, AWS_CA_REGION, AWS_GB_REGION, AWS_ZA_REGION});
44+
static final List<String> SUPPORTED_C1_REGIONS = Arrays.asList(new String[]{C1_AU_REGION, C1_CA_REGION, C1_DE_REGION, C1_GB_REGION, C1_IN_REGION, C1_JP_REGION, C1_SG_REGION, C1_US_REGION, C1_ZA_REGION});
4345

4446
static final Map<String, String> V1_TO_C1_REGION_MAPPING = new HashMap<String, String>() {
4547
{
@@ -52,6 +54,7 @@ final class AMaasRegion {
5254
put(AWS_AE_REGION, C1_AE_REGION);
5355
put(AWS_CA_REGION, C1_CA_REGION);
5456
put(AWS_GB_REGION, C1_GB_REGION);
57+
put(AWS_ZA_REGION, C1_ZA_REGION);
5558
}
5659
};
5760

@@ -67,6 +70,7 @@ final class AMaasRegion {
6770
put(C1_CA_REGION, "antimalware.ca-1.cloudone.trendmicro.com");
6871
put(C1_TREND_REGION, "antimalware.trend-us-1.cloudone.trendmicro.com");
6972
put(C1_AE_REGION, "antimalware.ae-1.cloudone.trendmicro.com");
73+
put(C1_ZA_REGION, "antimalware.za-1.cloudone.trendmicro.com");
7074
}
7175
};
7276

0 commit comments

Comments
 (0)