Git Product home page Git Product logo

rlp_01's Introduction

Java RELP Library (rlp_01)

rlp_01 implements RELP protocol in Java using NIO interface and enables users to send syslog formatted messages to a RELP server such as rsyslog.

License

Apache License Version 2.0

Features

Current

Example

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <dependencies>
        <!-- this library -->
        <dependency>
            <groupId>com.teragrep</groupId>
            <artifactId>rlp_01</artifactId>
            <version></version> <!-- see github -->
        </dependency>
        <!-- for syslog rfc5424 formatting -->
        <dependency>
            <groupId>com.cloudbees</groupId>
            <artifactId>syslog-java-client</artifactId>
            <version>1.1.7</version>
        </dependency>
    </dependencies>
</project>
import com.teragrep.rlp_01.RelpBatch;
import com.teragrep.rlp_01.RelpConnection;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmConstraints;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;

import com.cloudbees.syslog.Facility;
import com.cloudbees.syslog.Severity;
import com.cloudbees.syslog.SyslogMessage;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;

class Main {

    public static void main(String[] args) {

        final String serverHostname = "127.0.0.1";
        final int serverPort = 601;

        boolean useTls = false;

        RelpConnection relpConnection;
        if (useTls) {
            try {
                SSLContext sslContext = SSLContextFactory.authenticatedContext(
                        "keystore.jks",
                        "changeit",
                        "TLSv1.3"
                );

                Supplier<SSLEngine> sslEngineSupplier = sslContext::createSSLEngine;
                /*
                // in case there is a need to configure these:
                SSLEngine sslEngine = sslContext.createSSLEngine();
                SSLParameters sslParameters = new SSLParameters();
                sslParameters.setAlgorithmConstraints();
                sslParameters.setCipherSuites();
                sslEngine.setSSLParameters(sslParameters);
                 */

                relpConnection = new RelpConnection(sslEngineSupplier);
            } catch (GeneralSecurityException | IOException exception) {
                exception.printStackTrace();
            }
        } else {
            relpConnection = new RelpConnection();
        }

        Main.openConnection(relpConnection, serverHostname, serverPort); // connection helper method

        RelpBatch relpBatch = new RelpBatch(); // create new relpBatch

        // Craft syslog message
        SyslogMessage syslog = new SyslogMessage()
                .withTimestamp(new Date().getTime())
                .withSeverity(Severity.WARNING)
                .withAppName("appName")
                .withHostname("hostName")
                .withFacility(Facility.USER)
                .withMsg("Hello RELP World!");


        relpBatch.insert(syslog.toRfc5424SyslogMessage().getBytes(StandardCharsets.UTF_8)); // insert one message

        boolean notSent = true;
        while (notSent) { // retry until sent

            try {
                relpConnection.commit(relpBatch); // send batch
            } catch (IOException | TimeoutException e) {
                e.printStackTrace();
            }

            if (!relpBatch.verifyTransactionAll()) { // failed batch
                relpBatch.retryAllFailed(); // re-queue failed events
                relpConnection.tearDown(); // teardown connection
                Main.openConnection(relpConnection, serverHostname, serverPort); // reconnect
            } else { // successful batch
                notSent = false;
            }
        }
    }

    private static void openConnection(RelpConnection relpConnection,
                                       String serverHostname,
                                       int serverPort) {
        // connect helper method
        boolean connected = false;
        while (!connected) {
            try {
                connected = relpConnection.connect(serverHostname, serverPort);  // connect
            } catch (IOException | TimeoutException e) { // error happened during the connect
                e.printStackTrace();
                relpConnection.tearDown(); // retry with clean connection
            }

            if (!connected) {
                // reconnect after an interval
                try {
                    Thread.sleep(500); // reconnect interval
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Debugging

Configure slf4j provider to enable debug messages. RelpParser logs only on trace level.

Contributing

You can involve yourself with our project by opening an issue or submitting a pull request.

Contribution requirements:

  1. All changes must be accompanied by a new or changed test. If you think testing is not required in your pull request, include a sufficient explanation as why you think so.

  2. Security checks must pass

  3. Pull requests must align with the principles and values of extreme programming.

  4. Pull requests must follow the principles of Object Thinking and Elegant Objects (EO).

Read more in our Contributing Guideline.

Contributor License Agreement

Contributors must sign Teragrep Contributor License Agreement before a pull request is accepted to organization’s repositories.

You need to submit the CLA only once. After submitting the CLA you can contribute to all Teragrep’s repositories.

rlp_01's People

Contributors

kortemik avatar rafiabee avatar redturtledonkey avatar ronja-ui avatar strongestnumber9 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

rlp_01's Issues

RelpParser.java does not sanity check TxId / Command / Length sizes

RelpConnection relpConnection = new RelpConnection();
relpConnection.connect("127.0.0.1", 1236);

causes

java.nio.BufferOverflowException
	at java.base/java.nio.Buffer.nextPutIndex(Buffer.java:722)
	at java.base/java.nio.DirectByteBuffer.put(DirectByteBuffer.java:359)
	at com.teragrep.rlp_01.RelpParser.parse(RelpParser.java:135)
	at com.teragrep.rlp_01.RelpConnection.readAcks(RelpConnection.java:257)
	at com.teragrep.rlp_01.RelpConnection.sendBatch(RelpConnection.java:235)
	at com.teragrep.rlp_01.RelpConnection.connect(RelpConnection.java:159)
	at com.teragrep.rlp_01.ConnectionTest.testInvalidReply(ConnectionTest.java:64)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

when server answers just

"200 OK\ncommands=syslog\n";

Note that it is missing the header frame completely

sendRelpRequestAsync write throws and leaves ByteBuffer in invalid state

private void sendRelpRequestAsync(RelpFrameTX relpRequest) throws IOException, TimeoutException {
ByteBuffer byteBuffer;
](

private void sendRelpRequestAsync(RelpFrameTX relpRequest) throws IOException, TimeoutException {
ByteBuffer byteBuffer;
if (relpRequest.length() > this.txBufferSize) {
byteBuffer = ByteBuffer.allocateDirect(relpRequest.length());
}
else {
byteBuffer = this.preAllocatedTXBuffer;
}
relpRequest.write(byteBuffer);
byteBuffer.flip();
relpClientSocket.write(byteBuffer);
byteBuffer.clear();
}
)

java.nio.channels.ClosedByInterruptException
  at java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:202)
  at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:477)
  at com.teragrep.rlp_01.RelpConnection.sendRelpRequestAsync(RelpConnection.java:388)

-->

java.nio.BufferOverflowException
  at java.nio.ByteBuffer.put(ByteBuffer.java:837)
  at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:378)
  at java.nio.ByteBuffer.put(ByteBuffer.java:867)
  at com.teragrep.rlp_01.RelpFrameTX.putHeader(RelpFrameTX.java:117)

migrate from System.out and System.err to SLF4J

migrate from System.out.println and System.err.println to SLF4J. SLF4J is available due to being a dependency at tls-channel, therefore it would be better to use that instead of System.out and System.err.

Umlauts break event length

When running RelpBatchTest I changed the line:
private static final String message = "syslog message";
to test with even one umlaut:
private static final String message = "syslog messäge";

then ran the tests and it fails with:

com.teragrep.rlp_01.RelpBatchTest.testRetryAllFailed
Worker queue count did not match ==> expected: <2> but was: <7>

com.teragrep.rlp_01.RelpBatchTest.testInsert
Did not receive expected value from getRequest ==> expected: <0 syslog 14 syslog messäge> but was: <0 syslog 15 syslog messäge>

rewrite RelpFrame to object-oriented structure

Description
current implementation relies on external control.

perhaps proper one would include RelpParser within the rxFrame and the ByteBuffer representation in txFrame and possibly in rxFrame too?

teardown on never connected RelpConnection throws npe

Describe the bug

Cannot invoke "java.nio.channels.SocketChannel.close()" because "this.socketChannel" is null> java.lang.NullPointerException: Cannot invoke "java.nio.channels.SocketChannel.close()" because "this.socketChannel" is null
        at com.teragrep.rlp_01.RelpClientPlainSocket.close(RelpClientPlainSocket.java:150)
        at com.teragrep.rlp_01.RelpConnection.tearDown(RelpConnection.java:169)

when connection has never been connected

Expected behavior
shouldn't throw, should just be no-op because there is nothing to teardown

How to reproduce
create new RelpConnection and immediately call teardown() on it.

Screenshots

Software version
4.0.1

Desktop (please complete the following information if relevant):

  • OS:
  • Browser:
  • Version:

Additional context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.