Skip to content

Commit 8fd674c

Browse files
Artem LabazinArtem Labazin
authored andcommitted
Add client sub-project
1 parent 0011cd2 commit 8fd674c

20 files changed

Lines changed: 1343 additions & 13 deletions

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,4 @@ log*.txt*
114114
.vscode/
115115

116116
# Secure incomplete sub-projects
117-
client/
118117
server/

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
12
language: java
23

34
jdk:
45
- oraclejdk8
56

7+
services:
8+
- docker
9+
10+
# Install Erlang for integration tests
11+
before_install:
12+
- wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
13+
- sudo dpkg -i erlang-solutions_1.0_all.deb
14+
- sudo apt-get update -qq
15+
- sudo apt-get install erlang -y
16+
617
install:
718
mvn --settings .settings.xml install -DskipTests=true -Dmaven.javadoc.skip=true -Dgpg.skip -B -V
819

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
## [Unreleased]
1111

12-
- Add EPMD client.
1312
- Add EPMD server.
1413
- Add more unit and integration tests.
1514

16-
## [0.1.0](https://github.com/appulse-projects/epmd-java/releases/tag/0.1.0) - 2018-01-29
15+
## [0.2.1](https://github.com/appulse-projects/epmd-java/releases/tag/0.2.1) - 2018-01-29
1716

1817
### Added
1918

19+
- Add EPMD client.
2020
- Serialization/Deserialization exceptions in `Core`.
2121

2222
### Changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
This is the set of projects, which implementing EPMD server and client.
77

8-
- [Core description](./core/README.md);
8+
- [Core description](./core/README.md)
9+
- [Client description](./client/README.md)
910

1011
## Development
1112

@@ -31,19 +32,20 @@ For building routine automation, I am using [maven](https://maven.apache.org).
3132
To build the project, do the following:
3233

3334
```bash
34-
$> mvn clean package
35+
$> mvn clean compile
3536
...
3637
[INFO] ------------------------------------------------------------------------
3738
[INFO] Reactor Summary:
3839
[INFO]
39-
[INFO] [EPMD] Parent ...................................... SUCCESS [ 1.174 s]
40-
[INFO] [EPMD] Core ........................................ SUCCESS [ 22.003 s]
40+
[INFO] [EPMD] Parent ...................................... SUCCESS [ 0.091 s]
41+
[INFO] [EPMD] Core ........................................ SUCCESS [ 11.966 s]
42+
[INFO] [EPMD] Client ...................................... SUCCESS [ 5.504 s]
4143
[INFO] ------------------------------------------------------------------------
4244
[INFO] BUILD SUCCESS
4345
[INFO] ------------------------------------------------------------------------
44-
[INFO] Total time: 23.966 s
45-
[INFO] Finished at: 2018-01-26T13:58:14+03:00
46-
[INFO] Final Memory: 48M/622M
46+
[INFO] Total time: 18.277 s
47+
[INFO] Finished at: 2018-01-29T10:23:34+03:00
48+
[INFO] Final Memory: 49M/584M
4749
[INFO] ------------------------------------------------------------------------
4850
```
4951

client/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#Overview
2+
3+
Client's library for `EPMD` server.
4+
5+
## Usage
6+
7+
### Add dependency
8+
9+
Include the dependency to your project's pom.xml file:
10+
11+
```xml
12+
<dependencies>
13+
...
14+
<dependency>
15+
<groupId>io.appulse.epmd.java</groupId>
16+
<artifactId>client</artifactId>
17+
<version>0.2.1</version>
18+
</dependency>
19+
...
20+
</dependencies>
21+
```
22+
23+
or Gradle:
24+
25+
```groovy
26+
compile 'io.appulse.epmd.java:client:0.2.1'
27+
```
28+
29+
### Create client
30+
31+
Create `EpmdClient` with default port **4369** or extracted from `ERL_EPMD_PORT` environment variable:
32+
33+
```java
34+
EpmdClient client = new EmpdClient();
35+
```
36+
37+
You are able to specify `EPMD` server port manually:
38+
39+
```java
40+
EpmdClient client = new EmpdClient(9999);
41+
```
42+
43+
### Server interactions
44+
45+
You can use different client's methods:
46+
47+
```java
48+
// register a new Node in EPMD server
49+
int creation = client.register("popa", 9988, R6_ERLANG, TCP, R4, R6);
50+
51+
// lookup node on EPMD server (local/remote)
52+
Optional<NodeInfo> node = client.lookup("remote-node@192.168.1.46");
53+
54+
// get all nodes from EPMD server (local/remote)
55+
List<EpmdInfo.NodeDescription> nodes = client.getNodes();
56+
57+
// dumps all nodes from EPMD server
58+
List<EpmdDump.NodeDump> nodes = client.dumpAll();
59+
60+
// kill EPMD server (if available)
61+
boolean wasKilled = client.kill();
62+
63+
// close client connection
64+
client.close();
65+
```
66+
67+
For more information see `JavaDoc` and source code.

client/pom.xml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!--
4+
Copyright 2018 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
-->
18+
19+
<project xmlns="http://maven.apache.org/POM/4.0.0"
20+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
22+
23+
<modelVersion>4.0.0</modelVersion>
24+
25+
<parent>
26+
<groupId>io.appulse</groupId>
27+
<artifactId>epmd-java</artifactId>
28+
<version>0.2.1</version>
29+
</parent>
30+
31+
<groupId>io.appulse.epmd.java</groupId>
32+
<artifactId>client</artifactId>
33+
<name>[EPMD] Client</name>
34+
<packaging>jar</packaging>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>${project.groupId}</groupId>
39+
<artifactId>core</artifactId>
40+
<version>${project.version}</version>
41+
</dependency>
42+
43+
<dependency>
44+
<groupId>org.testcontainers</groupId>
45+
<artifactId>testcontainers</artifactId>
46+
<version>1.5.1</version>
47+
<scope>test</scope>
48+
</dependency>
49+
</dependencies>
50+
51+
<build>
52+
<plugins>
53+
<plugin>
54+
<groupId>org.apache.maven.plugins</groupId>
55+
<artifactId>maven-source-plugin</artifactId>
56+
</plugin>
57+
<plugin>
58+
<groupId>org.apache.maven.plugins</groupId>
59+
<artifactId>maven-javadoc-plugin</artifactId>
60+
</plugin>
61+
62+
<plugin>
63+
<groupId>org.apache.maven.plugins</groupId>
64+
<artifactId>maven-surefire-plugin</artifactId>
65+
</plugin>
66+
<plugin>
67+
<groupId>org.apache.maven.plugins</groupId>
68+
<artifactId>maven-failsafe-plugin</artifactId>
69+
</plugin>
70+
71+
<plugin>
72+
<groupId>org.codehaus.mojo</groupId>
73+
<artifactId>findbugs-maven-plugin</artifactId>
74+
</plugin>
75+
<plugin>
76+
<groupId>org.apache.maven.plugins</groupId>
77+
<artifactId>maven-pmd-plugin</artifactId>
78+
</plugin>
79+
80+
<plugin>
81+
<groupId>org.apache.maven.plugins</groupId>
82+
<artifactId>maven-checkstyle-plugin</artifactId>
83+
</plugin>
84+
</plugins>
85+
</build>
86+
</project>
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appulse.epmd.java.client;
18+
19+
import static java.util.concurrent.TimeUnit.SECONDS;
20+
import static lombok.AccessLevel.PRIVATE;
21+
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.Closeable;
24+
import java.io.IOException;
25+
import java.net.InetAddress;
26+
import java.net.InetSocketAddress;
27+
import java.net.Socket;
28+
29+
import io.appulse.epmd.java.client.exception.EpmdConnectionException;
30+
import io.appulse.epmd.java.core.mapper.deserializer.MessageDeserializer;
31+
import io.appulse.epmd.java.core.mapper.serializer.MessageSerializer;
32+
import io.appulse.epmd.java.core.model.response.RegistrationResult;
33+
34+
import lombok.NonNull;
35+
import lombok.RequiredArgsConstructor;
36+
import lombok.SneakyThrows;
37+
import lombok.experimental.FieldDefaults;
38+
import lombok.extern.slf4j.Slf4j;
39+
import lombok.val;
40+
41+
/**
42+
*
43+
* @author Artem Labazin
44+
* @since 0.2.1
45+
*/
46+
@Slf4j
47+
@RequiredArgsConstructor
48+
@FieldDefaults(level = PRIVATE, makeFinal = true)
49+
class Connection implements Closeable {
50+
51+
private static final int CONNECT_TIMEOUT;
52+
53+
private static final MessageSerializer SERIALIZER;
54+
55+
private static final MessageDeserializer DESERIALIZER;
56+
57+
static {
58+
CONNECT_TIMEOUT = (int) SECONDS.toMillis(5);
59+
SERIALIZER = new MessageSerializer();
60+
DESERIALIZER = new MessageDeserializer();
61+
}
62+
63+
@NonNull
64+
InetAddress address;
65+
66+
int port;
67+
68+
Socket socket = new Socket();
69+
70+
@SneakyThrows
71+
public void send (@NonNull Object request) {
72+
log.debug("Sending: {}", request);
73+
74+
val bytes = SERIALIZER.serialize(request);
75+
76+
connect();
77+
78+
socket.getOutputStream().write(bytes);
79+
socket.getOutputStream().flush();
80+
81+
log.debug("Message {} was sent", request);
82+
}
83+
84+
public <T> T send (@NonNull Object request, @NonNull Class<T> responseType) throws IOException {
85+
send(request);
86+
87+
val messageBytes = read(responseType);
88+
89+
log.debug("Received bytes:\n{}", messageBytes);
90+
val result = DESERIALIZER.deserialize(messageBytes, responseType);
91+
92+
log.debug("Received message:\n{}", result);
93+
return result;
94+
}
95+
96+
@Override
97+
@SneakyThrows
98+
public void close () {
99+
if (socket.isClosed()) {
100+
log.debug("EPMD connection was already closed");
101+
return;
102+
}
103+
104+
socket.close();
105+
106+
log.debug("EPMD connection (from localhost:{}, to {}) was closed",
107+
socket.getLocalPort(), socket.getRemoteSocketAddress());
108+
}
109+
110+
public boolean isClosed () {
111+
return socket.isClosed();
112+
}
113+
114+
private void connect () {
115+
if (socket.isConnected()) {
116+
log.debug("EPMD connection was already connected");
117+
return;
118+
}
119+
120+
val socketAddress = new InetSocketAddress(address, port);
121+
try {
122+
socket.setTcpNoDelay(true);
123+
socket.connect(socketAddress, CONNECT_TIMEOUT);
124+
} catch (IOException ex) {
125+
val message = String.format("Couldn't connect to EPMD server (%s:%d), maybe it is down",
126+
address.toString(), port);
127+
log.error(message);
128+
throw new EpmdConnectionException(message, ex);
129+
}
130+
131+
log.debug("EPMD connection to {}:{} was established", address, port);
132+
}
133+
134+
private byte[] read (Class<?> responseType) throws IOException {
135+
val outputStream = new ByteArrayOutputStream(32);
136+
val buffer = new byte[32];
137+
138+
while (true) {
139+
val length = socket.getInputStream().read(buffer);
140+
if (length == -1) {
141+
break;
142+
}
143+
outputStream.write(buffer, 0, length);
144+
if (responseType == RegistrationResult.class) {
145+
break;
146+
}
147+
}
148+
149+
return outputStream.toByteArray();
150+
}
151+
}

0 commit comments

Comments
 (0)