Signed-off-by: Hoang Le <hoang.h...@dektech.com.au>
---
 .gitignore                                         |  16 +
 Makefile.am                                        |  12 +-
 configure.ac                                       |  19 +-
 demos/Makefile.am                                  |   4 +
 demos/tipcj/Makefile.am                            |   3 +
 demos/tipcj/connection/Common.java                 |   9 +
 demos/tipcj/connection/Makefile.am                 |  34 ++
 demos/tipcj/connection/Manifest_client.txt         |   3 +
 demos/tipcj/connection/Manifest_server.txt         |   3 +
 demos/tipcj/connection/Tipc_Java_Api_Client.java   | 227 ++++++++
 demos/tipcj/connection/Tipc_Java_Api_Server.java   | 170 ++++++
 demos/tipcj/hello_world/Hello_Java_Api_Client.java |  70 +++
 demos/tipcj/hello_world/Hello_Java_Api_Server.java |  59 ++
 demos/tipcj/hello_world/Makefile.am                |  29 +
 demos/tipcj/hello_world/Manifest_client.txt        |   3 +
 demos/tipcj/hello_world/Manifest_server.txt        |   3 +
 tipcj/Makefile.am                                  |  33 ++
 tipcj/Manifest.txt                                 |   2 +
 tipcj/com/tipcj/Poll.java                          |  47 ++
 tipcj/com/tipcj/ServiceType.java                   |  23 +
 tipcj/com/tipcj/SocketType.java                    |  24 +
 tipcj/com/tipcj/TipcAddr.java                      |  65 +++
 tipcj/com/tipcj/TipcBaseApi.java                   | 166 ++++++
 tipcj/com/tipcj/TipcConfig.java                    |  49 ++
 tipcj/com/tipcj/TipcConn.java                      | 320 +++++++++++
 tipcj/com/tipcj/TipcHelper.java                    |  53 ++
 tipcj/com/tipcj/TipcServiceRange.java              |  65 +++
 tipcj/com/tipcj/TipcSrvConn.java                   | 108 ++++
 tipcj/include/tipcjni.h                            | 221 ++++++++
 tipcj/libtipcj.c                                   | 594 +++++++++++++++++++++
 30 files changed, 2431 insertions(+), 3 deletions(-)
 create mode 100644 demos/tipcj/Makefile.am
 create mode 100644 demos/tipcj/connection/Common.java
 create mode 100644 demos/tipcj/connection/Makefile.am
 create mode 100644 demos/tipcj/connection/Manifest_client.txt
 create mode 100644 demos/tipcj/connection/Manifest_server.txt
 create mode 100644 demos/tipcj/connection/Tipc_Java_Api_Client.java
 create mode 100644 demos/tipcj/connection/Tipc_Java_Api_Server.java
 create mode 100644 demos/tipcj/hello_world/Hello_Java_Api_Client.java
 create mode 100644 demos/tipcj/hello_world/Hello_Java_Api_Server.java
 create mode 100644 demos/tipcj/hello_world/Makefile.am
 create mode 100644 demos/tipcj/hello_world/Manifest_client.txt
 create mode 100644 demos/tipcj/hello_world/Manifest_server.txt
 create mode 100644 tipcj/Makefile.am
 create mode 100644 tipcj/Manifest.txt
 create mode 100644 tipcj/com/tipcj/Poll.java
 create mode 100644 tipcj/com/tipcj/ServiceType.java
 create mode 100644 tipcj/com/tipcj/SocketType.java
 create mode 100644 tipcj/com/tipcj/TipcAddr.java
 create mode 100644 tipcj/com/tipcj/TipcBaseApi.java
 create mode 100644 tipcj/com/tipcj/TipcConfig.java
 create mode 100644 tipcj/com/tipcj/TipcConn.java
 create mode 100644 tipcj/com/tipcj/TipcHelper.java
 create mode 100644 tipcj/com/tipcj/TipcServiceRange.java
 create mode 100644 tipcj/com/tipcj/TipcSrvConn.java
 create mode 100644 tipcj/include/tipcjni.h
 create mode 100644 tipcj/libtipcj.c

diff --git a/.gitignore b/.gitignore
index 39d06a7af575..29f32b08d354 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,19 @@ demos/golang/hello_world/hello_go_api_server
 libtipc/libtipc.a
 test/overlapping_ranges/overlap_client
 test/overlapping_ranges/overlap_server
+
+# Standard shared library
+*.so
+
+# All java .class
+*.class
+*.jar
+
+# All java packages
+tipcj/.libs
+demos/tipcj/hello_world/Hello_Java_Api_Client.tar.gz
+demos/tipcj/hello_world/Hello_Java_Api_Server.tar.gz
+demos/tipcj/hello_world/.libs
+demos/tipcj/connection/Tipc_Java_Api_Client.tar.gz
+demos/tipcj/connection/Tipc_Java_Api_Server.tar.gz
+demos/tipcj/connection/.libs
diff --git a/Makefile.am b/Makefile.am
index 37d0385b9171..bac4bb3d3e4a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1 +1,11 @@
-SUBDIRS=man scripts libtipc demos test utils
+SUBDIRS=man scripts libtipc
+
+if TIPC_GOAPI_EXAMPLE
+SUBDIRS+=golang
+endif
+
+if TIPC_JAVA
+SUBDIRS+=tipcj
+endif
+
+SUBDIRS+=demos test utils
diff --git a/configure.ac b/configure.ac
index c5fa53165526..6ffd6d2552c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@ AC_CHECK_TYPE(struct tipc_sioc_ln_req, [tipc_lss=yes],[], 
[[#include <linux/tipc
 AM_CONDITIONAL(TIPC_LINK_STATE_SUBSCRITION, test "x$tipc_lss" = "xyes")
 
 # Checks for TIPC GO API
-AC_ARG_WITH(goapi,[ --with-goapi  Compile TIPC GO APIs 
examples],[goapi=true],[])
+AC_ARG_WITH(goapi,[ --with-goapi Compile TIPC GO APIs 
examples],[goapi=true],[])
 if test "x$goapi" == "xtrue"; then
        AC_CHECK_PROG([gotool],[go],[true],[])
        if test "x$gotool" != "xtrue"; then
@@ -33,6 +33,17 @@ if test "x$goapi" == "xtrue"; then
 fi
 AM_CONDITIONAL(TIPC_GOAPI_EXAMPLE, test "x$goapi" == "xtrue" -a "x$gotool" == 
"xtrue")
 
+# Checks for TIPC JAVA API
+AC_ARG_WITH(tipcj,[ --with-tipcj Compile TIPC JAVA API and a couple of 
examples],[with_tipcj=true],[])
+if test "x$with_tipcj" == "xtrue"; then
+       AM_PROG_GCJ
+        AC_CHECK_PROG([javac],[javac],[true],[])
+        if test "x$javac" != "xtrue"; then
+                AC_MSG_NOTICE([javac are not available - ignore java 
compiling])
+        fi
+fi
+AM_CONDITIONAL(TIPC_JAVA, test "x$with_tipcj" == "xtrue" -a "x$javac" == 
"xtrue")
+
 AC_CONFIG_FILES([
        Makefile
        libtipc/Makefile
@@ -60,8 +71,12 @@ AC_CONFIG_FILES([
        demos/golang/Makefile
        demos/golang/hello_world/Makefile
        demos/golang/connection/Makefile
-        man/Makefile
+       man/Makefile
        scripts/Makefile
+       tipcj/Makefile
+       demos/tipcj/Makefile
+       demos/tipcj/hello_world/Makefile
+       demos/tipcj/connection/Makefile
        ])
 AM_CONDITIONAL(WITH_SCRIPTS, false)
 AC_ARG_ENABLE(scripts,
diff --git a/demos/Makefile.am b/demos/Makefile.am
index 1d1a9fe17707..475c7044a362 100644
--- a/demos/Makefile.am
+++ b/demos/Makefile.am
@@ -8,3 +8,7 @@ endif
 if TIPC_GOAPI_EXAMPLE
 SUBDIRS+= golang
 endif
+
+if TIPC_JAVA
+SUBDIRS+= tipcj
+endif
diff --git a/demos/tipcj/Makefile.am b/demos/tipcj/Makefile.am
new file mode 100644
index 000000000000..a5b28ac5205e
--- /dev/null
+++ b/demos/tipcj/Makefile.am
@@ -0,0 +1,3 @@
+if TIPC_JAVA
+SUBDIRS = hello_world connection
+endif
diff --git a/demos/tipcj/connection/Common.java 
b/demos/tipcj/connection/Common.java
new file mode 100644
index 000000000000..d1d5f2a3fac6
--- /dev/null
+++ b/demos/tipcj/connection/Common.java
@@ -0,0 +1,9 @@
+package com.tipcj.demos;
+
+public interface Common {
+       public static final int RDM_SRV_TYPE = 18888;
+       public static final int STREAM_SRV_TYPE = 17777;
+       public static final int SEQPKT_SRV_TYPE = 16666;
+       public static final int SRV_INST = 17;
+       public static final int BUF_SIZE = 40;
+}
diff --git a/demos/tipcj/connection/Makefile.am 
b/demos/tipcj/connection/Makefile.am
new file mode 100644
index 000000000000..ec07b5ed4427
--- /dev/null
+++ b/demos/tipcj/connection/Makefile.am
@@ -0,0 +1,34 @@
+bin_PROGRAMS=Tipc_Java_Api_Client Tipc_Java_Api_Server
+
+Tipc_Java_Api_Client_SOURCES=
+Tipc_Java_Api_Server_SOURCES=
+
+CLIENT_OBJECTS=com/tipcj/demos/Common.class \
+                  com/tipcj/demos/Tipc_Java_Api_Client.class
+
+
+SERVER_OBJECTS=com/tipcj/demos/Common.class \
+                  com/tipcj/demos/Tipc_Java_Api_Server.class
+
+CLEANFILES=$(CLIENT_OBJECTS) $(SERVER_OBJECTS)
+
+Tipc_Java_Api_Client$(EXEEXT): $(CLIENT_OBJECTS)
+       $(shell $(MKDIR_P) .libs)
+       $(shell cd .libs && jar cfm ../$@.jar ../Manifest_client.txt 
$(CLIENT_OBJECTS))
+       tar cvfz $@.tar.gz $@.jar  -C ../../../tipcj .libs/libtipcj.jar 
.libs/libtipcj.so
+       cp ../../../tipcj/.libs/libtipcj.jar ../../../tipcj/.libs/libtipcj.so 
.libs
+
+com/tipcj/demos/%.class: %.java
+       @echo "Compiling $<"
+       $(shell $(MKDIR_P) .libs)
+       $(shell javac -cp ../../../tipcj/.libs:.libs -d .libs $< )
+
+Tipc_Java_Api_Server$(EXEEXT): $(SERVER_OBJECTS)
+       $(shell $(MKDIR_P) .libs)
+       $(shell cd .libs && jar cfm ../$@.jar ../Manifest_server.txt 
$(SERVER_OBJECTS))
+       tar cvfz $@.tar.gz $@.jar -C ../../../tipcj .libs/libtipcj.jar 
.libs/libtipcj.so
+       cp ../../../tipcj/.libs/libtipcj.jar ../../../tipcj/.libs/libtipcj.so 
.libs
+
+clean-generic:
+       rm -rf Tipc_Java_Api_Client$(EXEEXT).jar 
Tipc_Java_Api_Server$(EXEEXT).jar Tipc_Java_Api_Client$(EXEEXT).tar.gz 
Tipc_Java_Api_Server$(EXEEXT).tar.gz
+
diff --git a/demos/tipcj/connection/Manifest_client.txt 
b/demos/tipcj/connection/Manifest_client.txt
new file mode 100644
index 000000000000..19a9015fd403
--- /dev/null
+++ b/demos/tipcj/connection/Manifest_client.txt
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.tipcj.demos.Tipc_Java_Api_Client
+Class-Path: .libs/libtipcj.jar .libs/libtipcj.so
diff --git a/demos/tipcj/connection/Manifest_server.txt 
b/demos/tipcj/connection/Manifest_server.txt
new file mode 100644
index 000000000000..ad93f6a304ac
--- /dev/null
+++ b/demos/tipcj/connection/Manifest_server.txt
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.tipcj.demos.Tipc_Java_Api_Server
+Class-Path: .libs/libtipcj.jar .libs/libtipcj.so
diff --git a/demos/tipcj/connection/Tipc_Java_Api_Client.java 
b/demos/tipcj/connection/Tipc_Java_Api_Client.java
new file mode 100644
index 000000000000..42564910475b
--- /dev/null
+++ b/demos/tipcj/connection/Tipc_Java_Api_Client.java
@@ -0,0 +1,227 @@
+package com.tipcj.demos;
+
+import java.nio.ByteBuffer;
+
+import com.tipcj.*;
+
+public class Tipc_Java_Api_Client {
+       public int[] pfds;
+       public short[] events;
+       public Integer[] revents;
+       public TipcSrvConn topSrv;
+       public Integer up;
+       public TipcAddr srvAddr;
+       public TipcConn rdmConn;
+       public TipcConn streamConn;
+       public TipcConn seqpacketConn;
+
+       public long rdm_service_demo() {
+               byte[] inbuf = new byte[Common.BUF_SIZE];
+               ByteBuffer bytebuffer = 
ByteBuffer.allocateDirect(Common.BUF_SIZE);
+               byte[] msg = new String("Hello World!!!").getBytes();
+               int ret;
+               Integer err = new Integer(0); 
+
+               if (up == 0) {
+                       System.out.println("Service on SOCK_RDM went down");
+                       return 0;
+               }
+               System.out.println("-------------------------------------");
+               System.out.println("Service on SOCK_RDM came up");
+               System.out.println("Sending msg: " + new String(msg) + " on 
SOCK_RDM --> " + srvAddr);
+
+               if (rdmConn.Sock_Rejectable() < 0) {
+                       System.err.println("Set rejectable failed");
+                       return 0;
+               }
+
+               if (rdmConn.Sendto(msg, srvAddr) != msg.length) {
+                       System.err.println("sendto() failed");
+                       return 0;
+               }
+
+               ret = rdmConn.Recvfrom(bytebuffer, bytebuffer.limit(), srvAddr, 
null, err);
+               if ((ret < 0) || (err != 0)) {
+                       System.err.println("Unexpected response");
+                       return 0;
+               }
+
+               bytebuffer.get(inbuf, 0, ret);
+               System.out.println("Received response: " + new String(inbuf) + 
" <--" + srvAddr);
+               return srvAddr.Node;
+       }
+
+       public void rdm_reject_demo(long srv_node) {
+               TipcAddr invalid = new TipcAddr(42, 1, srv_node);
+               byte[] msg = new String("Hello World").getBytes();
+               byte[] inbuf = new byte[Common.BUF_SIZE];
+               ByteBuffer bytebuffer = 
ByteBuffer.allocateDirect(Common.BUF_SIZE);
+               Integer err = new Integer(0);
+               int ret;
+
+               if (up == 0) {
+                       return;
+               }
+
+               System.out.println("Sending msg: " + new String(msg) + " on 
SOCK_RDM --> " + invalid + " (non-existing)");
+               if (rdmConn.Sendto(msg, invalid) != msg.length) {
+                       System.out.println("Client sendto() failed: No route to 
host");
+                       return;
+               }
+
+               ret = rdmConn.Recvfrom(bytebuffer, bytebuffer.limit(), srvAddr, 
null, err);
+               if ((ret < 0) || (err == 0)) {
+                       System.err.println(String.format("Unexpected response 
err:%d", err));
+               }
+               bytebuffer.get(inbuf, 0, ret);
+               System.out.println("Received rejected msg: '" + new 
String(inbuf) + "' <-- " + srvAddr + " err:" + err);
+               System.out.println("-------------------------------------");
+       }
+
+       public void stream_service_demo() {
+               TipcAddr srv = new TipcAddr(Common.STREAM_SRV_TYPE, 
Common.SRV_INST, 0);
+               byte[] msg = new String("Hello World").getBytes();
+               byte[] inbuf = new byte[Common.BUF_SIZE];
+               int ret = 0;
+
+               if (up == 0) {
+                       System.out.println("Service on SOCK_STREAM went down");
+                       return;
+               }
+               System.out.println("-------------------------------------");
+               System.out.println("Service on SOCK_STREAM came up");
+               System.out.println("Performing implicit two-way connect with 
message '" + new String(msg) + "' --> " + srv);
+
+               try {
+                               Thread.sleep(1000);
+               } catch (InterruptedException ex) {}
+
+               ret = streamConn.Sendto(msg, srv);
+               if (ret != msg.length) {
+                       System.err.println("send() failed");
+               }
+
+               System.err.println("Receiving ...");
+               ret = streamConn.Recv(inbuf, false);
+               if (ret <= 0) {
+                       System.err.println("Unexpected response");
+                       return;
+               }
+
+               System.out.println("Received response: " + new String(inbuf) + 
" on SOCK_STREAM connection");
+               System.out.println("SOCK_STREAM connection established --> " + 
srvAddr);
+               System.out.println("-------------------------------------");
+       }
+
+       public void seqpacket_service_demo() {
+               TipcAddr srv = new TipcAddr(Common.SEQPKT_SRV_TYPE, 
Common.SRV_INST, 0);
+               byte[] msg = new String("Hello World").getBytes();
+               byte[] inbuf = new byte[Common.BUF_SIZE];
+               int ret = 0;
+
+               if (up == 0) {
+                       System.out.println("Service on SOCK_SEQPACKET went 
down");
+                       return;
+               }
+
+               System.out.println("-------------------------------------");
+               System.out.println("Service on SOCK_SEQPACKET came up");
+
+               System.out.println("Connecting to: -->" + srvAddr);
+
+               ret =  seqpacketConn.Connect(srvAddr);
+               if (ret < 0) {
+                       System.err.println("connect() failed");
+                       return;
+               }
+
+               System.out.println(String.format("Sending msg: %s on 
connection", new String(msg)));
+               ret = seqpacketConn.Send(msg);
+               if (ret != msg.length) {
+                       System.err.println("send() failed");
+                       return;
+               }
+
+               ret = seqpacketConn.Recv(inbuf, true);
+               if (ret <= 0) {
+                       System.err.println("Unexpected response");
+                       return;
+               }
+
+               System.out.println("Received response: " + new String(inbuf) + 
" on SOCK_SEQPACKET connection");
+               System.out.println("-------------------------------------");
+       }
+
+       public Tipc_Java_Api_Client() {
+               /* Create traffic sockets */
+               rdmConn = new TipcConn(SocketType.SOCK_RDM);
+               streamConn = new TipcConn(SocketType.SOCK_STREAM);
+               seqpacketConn = new TipcConn(SocketType.SOCK_SEQPACKET);
+
+               /* Subscribe for service events */
+               topSrv = new TipcSrvConn(0);
+
+               pfds = new int[] {rdmConn.GetFd(), streamConn.GetFd(), 
seqpacketConn.GetFd(), topSrv.getFd()};
+               events = new short[] {Poll.EPOLLIN, Poll.EPOLLIN | 
Poll.EPOLLHUP, Poll.EPOLLIN | Poll.EPOLLHUP, Poll.EPOLLIN | Poll.EPOLLHUP};
+               revents = new Integer[pfds.length];
+
+               srvAddr = new TipcAddr(Common.RDM_SRV_TYPE, Common.SRV_INST, 0);
+               up = new Integer(0);
+
+               System.out.println("Waiting for Service " + srvAddr);
+               TipcSrvConn.SrvWait(srvAddr, -1);
+
+               if (topSrv.SrvScr(Common.RDM_SRV_TYPE, 0, ~0, false, -1) != 0) {
+                       System.err.println("subscribe for RDM server failed");
+               }
+
+               if (topSrv.SrvScr(Common.STREAM_SRV_TYPE, 0, ~0, false, -1) != 
0) {
+                       System.err.println("subscribe for STREAM server 
failed");
+               }
+
+               if (topSrv.SrvScr(Common.SEQPKT_SRV_TYPE, 0, ~0, false, -1) != 
0) {
+                       System.err.println("subscribe for SEQPACKET server 
failed");
+               }
+
+               while (Poll.pollset(pfds, events, revents, 3000000) >=0) {
+                       if ((revents[1] & Poll.EPOLLHUP) != 0) {
+                               System.out.println("SOCK_STREAM connection 
hangup");
+                               streamConn.Close();
+                               streamConn = new 
TipcConn(SocketType.SOCK_STREAM);
+                               pfds[1] = streamConn.GetFd();
+                       }
+
+                       if ((revents[2] & Poll.EPOLLHUP) != 0) {
+                               System.out.println("SOCK_SEQPACKET connection 
hangup");
+                               seqpacketConn.Close();
+                               seqpacketConn = new 
TipcConn(SocketType.SOCK_SEQPACKET);
+                               pfds[2] = seqpacketConn.GetFd();
+                       }
+
+                       if ((revents[3] & Poll.EPOLLIN) != 0) {
+                               if (topSrv.GetEvt(srvAddr, null, up, new 
Integer(0)) != 0) {
+                                       System.err.println("reception of 
service event failed");
+                                       break;
+                               }
+                               if (srvAddr.Type == Common.RDM_SRV_TYPE) {
+                                       long srv_node = rdm_service_demo();
+                                       rdm_reject_demo(srv_node);
+                               }
+
+                               if (srvAddr.Type == Common.STREAM_SRV_TYPE) {
+                                       stream_service_demo();
+                               }
+                               if (srvAddr.Type == Common.SEQPKT_SRV_TYPE) {
+                                       seqpacket_service_demo();
+                               }
+                       }
+               }
+       }
+
+       public static void main(String[] args) {
+               System.out.println("****** TIPC JAVA API Demo Client Started 
******");
+               new Tipc_Java_Api_Client();
+               System.out.println("****** TIPC JAVA API Demo Finished ******");
+       }
+
+}
diff --git a/demos/tipcj/connection/Tipc_Java_Api_Server.java 
b/demos/tipcj/connection/Tipc_Java_Api_Server.java
new file mode 100644
index 000000000000..f71ce8fe370f
--- /dev/null
+++ b/demos/tipcj/connection/Tipc_Java_Api_Server.java
@@ -0,0 +1,170 @@
+package com.tipcj.demos;
+
+import java.math.BigInteger;
+
+import com.tipcj.*;
+
+public class Tipc_Java_Api_Server implements Runnable {
+
+       public TipcConn rdmsd;
+       public TipcConn strsd;
+       public TipcConn pktsd;
+
+       public TipcConn bind_service(int type, int scope, SocketType sktype, 
String sk_str) {
+               TipcConn srv = new TipcConn(sktype);
+               int ret = 0;
+
+               if (srv.GetFd() <= 0) {
+                       System.out.println("failed to create " + sk_str +" 
socket");
+                       return null;
+               }
+
+               ret = srv.Bind(type, 0, ~0, scope);
+               if (ret != 0) {
+                       System.err.println("failed to bind " + sk_str + " 
socket");
+                       srv.Close();
+                       return null;
+               }
+
+               System.out.println("Bound " + sk_str + " socket " + 
srv.Sockaddr() + " to " + new TipcServiceRange(type, 0, ~0, scope));
+               return srv;
+       }
+
+       public void recv_rdm_msg() {
+               byte[] msg = new byte[Common.BUF_SIZE];
+               TipcAddr cli = new TipcAddr();
+               Integer err = new Integer(0);
+
+               int ret = 0;
+
+               ret = rdmsd.Recvfrom(msg, cli, null, err);
+               System.out.println("-------------------------------------");
+               if (ret <= 0) {
+                       System.out.println("unexpected message on RDM socket");
+                       return;
+               }
+
+               System.out.println(String.format("Received msg: %s on SOCK_RDM 
<-- %s", new String(msg), cli));
+               System.out.println(String.format("Responding with: %s --> %s", 
new String("Huh?"), cli));
+
+               ret = rdmsd.Sendto(new String("Huh?").getBytes(), cli);
+               if (ret <= 0) {
+                       System.out.println("Server: failed to send");
+               }
+               System.out.println("-------------------------------------");
+       }
+
+       public int recv_stream_setup() {
+               int newsd;
+               TipcAddr cli = new TipcAddr();
+               byte[] msg = new byte[Common.BUF_SIZE];
+               int ret = -1;
+
+               System.out.println("-------------------------------------");
+
+               strsd.Listen(32);
+               newsd = strsd.Accept(cli);
+               if (newsd <= 0) {
+                       System.out.println("accept on SOCK_STREAM failed");
+                       return -1;
+               }
+
+               ret = strsd.Recv(newsd, msg, false);
+               if (ret <= 0) {
+                       System.out.println("unexpected message on STREAM 
socket\n");
+                       return -1;
+               }
+
+               System.out.println(String.format("Received msg: %s on STREAM 
connection", new String(msg)));
+               System.out.println(String.format("SOCK_STREAM connection 
established --> %s", cli));
+
+               System.out.println(String.format("Responding with: %s", new 
String("Huh?")));
+
+               ret = strsd.Send(newsd, new String("Huh?").getBytes());
+               if (ret <= 0) {
+                       System.out.println("failed to respond");
+                       return -1;
+               }
+
+               System.out.println("-------------------------------------");
+               return newsd;
+       }
+
+       public int recv_seqpacket_setup() {
+               int newsd;
+               TipcAddr cli = new TipcAddr();
+               byte[] msg = new byte[Common.BUF_SIZE];
+               int ret = -1;
+
+               System.out.println("-------------------------------------");
+               pktsd.Listen(32);
+               newsd = pktsd.Accept(cli);
+
+               if (newsd <= 0) {
+                       System.out.println("accept on SOCK_SEQPACKET failed");
+                       return -1;
+               }
+
+               System.out.println(String.format("SOCK_SEQPACKET connection 
established <-- %s", cli));
+
+               ret = pktsd.Recv(newsd, msg, true);
+               if (ret <= 0) {
+                       System.out.println("unexpected message on 
SOCK_SEQPACKET socket\n");
+                       return -1;
+               }
+               System.out.println(String.format("Received msg: %s on 
SOCK_SEQPACKET connection", new String(msg)));
+               System.out.println(String.format("Responding with: %s", new 
String("Huh?")));
+
+               ret = pktsd.Send(newsd, new String("Huh?").getBytes());
+               if (ret <= 0) {
+                       System.out.println("failed to respond");
+                       return -1;
+               }
+
+               System.out.println("-------------------------------------");
+               return newsd;
+       }
+
+       public void run() {
+               // TODO Auto-generated method stub
+               final int[] fds = new int[] {0, 0};
+               final short[] events = new short[] { Poll.EPOLLIN | 
Poll.EPOLLHUP, Poll.EPOLLIN | Poll.EPOLLHUP };
+               final Integer[] revents = new Integer[fds.length];
+
+               while (true) {
+                       recv_rdm_msg();
+                       fds[0] = recv_stream_setup();
+                       fds[1] = recv_seqpacket_setup();
+                       while (Poll.pollset(fds, events, revents, 3000000) >=0) 
{
+                               for (int i = 0; i<fds.length; i++) {
+                                       if ((revents[i] & Poll.EPOLLHUP) != 0) {
+                                               
System.out.println("-------------------------------------");
+                                               if (i == 0) {
+                                                       
System.out.println("SOCK_STREAM Connection hangup");
+                                               } else {
+                                                       
System.out.println("SOCK_SEQPACKET Connection hangup");
+                                               }
+                                               TipcConn.Close(fds[i]);
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+
+       public Tipc_Java_Api_Server() {
+               this.rdmsd = bind_service(Common.RDM_SRV_TYPE, 0, 
SocketType.SOCK_RDM, "RDM");
+               this.strsd = bind_service(Common.STREAM_SRV_TYPE, 0, 
SocketType.SOCK_STREAM, "STREAM");
+               this.pktsd = bind_service(Common.SEQPKT_SRV_TYPE, 0, 
SocketType.SOCK_SEQPACKET, "SEQPACKET");
+       }
+
+       public static void main(String[] args) {
+               System.out.println("****** TIPC JAVA API Demo Server Started 
******");
+               Tipc_Java_Api_Server demo = new Tipc_Java_Api_Server();
+
+               // Looping handle
+               demo.run();
+               System.out.println("****** TIPC JAVA API Demo Server Finished 
******");
+       }
+
+}
diff --git a/demos/tipcj/hello_world/Hello_Java_Api_Client.java 
b/demos/tipcj/hello_world/Hello_Java_Api_Client.java
new file mode 100644
index 000000000000..9ded0891b53e
--- /dev/null
+++ b/demos/tipcj/hello_world/Hello_Java_Api_Client.java
@@ -0,0 +1,70 @@
+package com.tipcj.demos;
+
+import java.nio.ByteBuffer;
+
+import com.tipcj.*;
+
+public class Hello_Java_Api_Client {
+       public static final int SERVER_TYPE  = 18888;
+       public static final int SERVER_INST  = 17;
+       public static final int BUF_SIZE = 40;
+
+       public static void main(String[] args) {
+               TipcConn tipcConn = null;
+               TipcAddr server = new TipcAddr(SERVER_TYPE, SERVER_INST, 0);
+               byte[] inbuf = new byte[BUF_SIZE];
+               byte[] outbuf = new String("Hello World!!!").getBytes();
+               boolean up = false;
+               ByteBuffer bytebuffer = ByteBuffer.allocateDirect(BUF_SIZE);
+
+               System.out.println("****** TIPC hello world client started 
******\n");
+
+               up = TipcSrvConn.SrvWait(server, 10000);
+               if (!up) {
+                       System.out.println("Client: server {" + SERVER_TYPE + 
"," + SERVER_INST + "} not published within 10 [s]");
+                       return;
+               }
+
+               tipcConn = new TipcConn(SocketType.SOCK_RDM);
+               if (tipcConn.Sendto(outbuf, server) < 0) {
+                       System.out.println("Client: failed to send");
+                       tipcConn.Close();
+                       return;
+               }
+
+               System.out.println("Client: sent message: " + new 
String(outbuf));
+
+               int ret = tipcConn.Recv(bytebuffer, bytebuffer.capacity(), 
false);
+               if (ret <= 0 ) {
+                       System.out.println("Client: unexpected response");
+                       tipcConn.Close();
+                       return;
+               }
+
+               bytebuffer.get(inbuf, 0, ret);
+               System.out.println("Client: received response: " + new 
String(inbuf));
+
+               /**
+                * Topology tracking
+                */
+               /**
+               TipcSrvConn srvTrack = new TipcSrvConn(0, 
ServiceType.TIPC_LINK_STATE);
+               TipcAddr srvAddr = new TipcAddr();
+               TipcAddr idAddr = new TipcAddr();
+               Integer upEvt = new Integer(0);
+               Integer expire = new Integer(0);
+
+               while (srvTrack.GetEvt(srvAddr, idAddr, upEvt, expire) >= 0) {
+                       System.out.println(srvAddr + "-" + idAddr + "-" + 
upEvt.toString() + "-" + expire.toString());
+                       try {
+                               //sleep 1 seconds
+                               Thread.sleep(1);
+                       } catch (InterruptedException e) {
+                               e.printStackTrace();
+                       }
+               }
+               */
+               System.out.println("****** TIPC hello client finished ******");
+               tipcConn.Close();
+       }
+}
diff --git a/demos/tipcj/hello_world/Hello_Java_Api_Server.java 
b/demos/tipcj/hello_world/Hello_Java_Api_Server.java
new file mode 100644
index 000000000000..03e9324d2a14
--- /dev/null
+++ b/demos/tipcj/hello_world/Hello_Java_Api_Server.java
@@ -0,0 +1,59 @@
+package com.tipcj.demos;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import com.tipcj.*;
+
+public class Hello_Java_Api_Server {
+       public static final int SERVER_TYPE  = 18888;
+       public static final int SERVER_INST  = 17;
+       public static final int BUF_SIZE = 40;
+
+       public static void main(String[] args) {
+               ByteBuffer bytebuffer = ByteBuffer.allocateDirect(BUF_SIZE);
+               byte[] inbuf = new byte[BUF_SIZE];
+               byte[] outbuf = new String("Uh?").getBytes();
+               TipcConn serverConn = null;
+               int ret;
+
+               System.out.println("****** TIPC hello world server started 
******\n");
+
+               /**
+                * Create TipcConn instance
+                */
+               serverConn = new TipcConn(SocketType.SOCK_RDM);
+
+               /**
+                * Bind to service instance
+                */
+               ret = serverConn.Bind(SERVER_TYPE, SERVER_INST, SERVER_INST, 0);
+               if (ret != 0) {
+                       System.out.println("Server: failed to bind port name");
+                       serverConn.Close();
+                       return;
+               }
+
+               Integer err = new Integer(0);
+               TipcAddr client = new TipcAddr();
+
+               ret = serverConn.Recvfrom(bytebuffer, bytebuffer.capacity(), 
client, null, err);
+               if (ret <= 0) {
+                       System.out.println("Server: unexpected message");
+                       return;
+               }
+
+               bytebuffer.duplicate().get(inbuf, 0, ret);
+               System.out.println("Server: Message received: " + new 
String(inbuf));
+
+               ret = serverConn.Sendto(outbuf, client);
+               if (ret < 0) {
+                       System.out.println("Server: failed to send");
+               }
+
+               System.out.println("Server: Sent response : " + new 
String(outbuf));
+               System.out.println("****** TIPC hello world server finished 
******");
+
+               serverConn.Close();
+       }
+}
diff --git a/demos/tipcj/hello_world/Makefile.am 
b/demos/tipcj/hello_world/Makefile.am
new file mode 100644
index 000000000000..92e5ee6e9dff
--- /dev/null
+++ b/demos/tipcj/hello_world/Makefile.am
@@ -0,0 +1,29 @@
+bin_PROGRAMS=Hello_Java_Api_Client Hello_Java_Api_Server
+
+Hello_Java_Api_Client_SOURCES=
+Hello_Java_Api_Server_SOURCES=
+
+CLIENT_OBJECTS=com/tipcj/demos/Hello_Java_Api_Client.class
+SERVER_OBJECTS=com/tipcj/demos/Hello_Java_Api_Server.class
+CLEANFILES=$(CLIENT_OBJECTS) $(SERVER_OBJECTS)
+
+Hello_Java_Api_Client$(EXEEXT): $(CLIENT_OBJECTS)
+       $(shell $(MKDIR_P) .libs)
+       jar cfm $@.jar ./Manifest_client.txt -C .libs $(CLIENT_OBJECTS)
+       tar cvfz $@.tar.gz $@.jar  -C ../../../tipcj .libs/libtipcj.jar 
.libs/libtipcj.so
+       cp ../../../tipcj/.libs/libtipcj.jar ../../../tipcj/.libs/libtipcj.so 
.libs
+
+com/tipcj/demos/%.class: %.java
+       @echo "Compiling $<"
+       $(shell $(MKDIR_P) .libs)
+       $(shell javac -cp ../../../tipcj/.libs:.libs -d .libs $< )
+
+Hello_Java_Api_Server$(EXEEXT): $(SERVER_OBJECTS)
+       $(shell $(MKDIR_P) .libs)
+       jar cfm $@.jar ./Manifest_server.txt -C .libs $(SERVER_OBJECTS)
+       tar cvfz $@.tar.gz $@.jar -C ../../../tipcj .libs/libtipcj.jar 
.libs/libtipcj.so
+       cp ../../../tipcj/.libs/libtipcj.jar ../../../tipcj/.libs/libtipcj.so 
.libs
+
+clean-generic:
+       rm -rf Hello_Java_Api_Client$(EXEEXT).jar 
Hello_Java_Api_Server$(EXEEXT).jar Hello_Java_Api_Client$(EXEEXT).tar.gz 
Hello_Java_Api_Server$(EXEEXT).tar.gz
+
diff --git a/demos/tipcj/hello_world/Manifest_client.txt 
b/demos/tipcj/hello_world/Manifest_client.txt
new file mode 100644
index 000000000000..85269a85a124
--- /dev/null
+++ b/demos/tipcj/hello_world/Manifest_client.txt
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.tipcj.demos.Hello_Java_Api_Client
+Class-Path: .libs/libtipcj.jar .libs/libtipcj.so
diff --git a/demos/tipcj/hello_world/Manifest_server.txt 
b/demos/tipcj/hello_world/Manifest_server.txt
new file mode 100644
index 000000000000..3a02ffd1935e
--- /dev/null
+++ b/demos/tipcj/hello_world/Manifest_server.txt
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.tipcj.demos.Hello_Java_Api_Server
+Class-Path: .libs/libtipcj.jar .libs/libtipcj.so
diff --git a/tipcj/Makefile.am b/tipcj/Makefile.am
new file mode 100644
index 000000000000..a92b43ea4c31
--- /dev/null
+++ b/tipcj/Makefile.am
@@ -0,0 +1,33 @@
+#AUTOMAKE_OPTIONS=subdir-objects
+CPPFLAGS+=-I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux -I./include
+
+bin_PROGRAMS=tipcj
+tipcj_SOURCES=
+
+TIPCJ_OBJECTS=com/tipcj/ServiceType.class \
+                 com/tipcj/TipcConfig.class \
+                 com/tipcj/SocketType.class \
+                 com/tipcj/TipcBaseApi.class \
+                 com/tipcj/TipcAddr.class \
+                 com/tipcj/TipcConn.class \
+                 com/tipcj/TipcHelper.class \
+                 com/tipcj/TipcSrvConn.class \
+                 com/tipcj/TipcServiceRange.class \
+                 com/tipcj/Poll.class
+
+tipcj$(EXEEXT): libtipcj.so libtipcj.jar
+
+libtipcj.jar:
+       $(shell cd .libs && jar cfm $@ ../Manifest.txt $(TIPCJ_OBJECTS))
+
+libtipcj.so: .libs $(TIPCJ_OBJECTS) include/tipcjni.h
+       $(AM_V_CC)$(COMPILE) -fPIC -shared -o .libs/$@ libtipcj.c 
../libtipc/libtipc.c
+
+include/tipcjni.h:
+       $(shell javah -o $@ -classpath .libs com.tipcj.TipcBaseApi)
+
+com/tipcj/%.class: com/tipcj/%.java
+       $(shell javac -d .libs $< )
+
+.libs:
+       $(shell $(MKDIR_P) .libs)
diff --git a/tipcj/Manifest.txt b/tipcj/Manifest.txt
new file mode 100644
index 000000000000..e8db25f64236
--- /dev/null
+++ b/tipcj/Manifest.txt
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Class-Path: libs/libtipcj.so
diff --git a/tipcj/com/tipcj/Poll.java b/tipcj/com/tipcj/Poll.java
new file mode 100644
index 000000000000..35f0929fbdf6
--- /dev/null
+++ b/tipcj/com/tipcj/Poll.java
@@ -0,0 +1,47 @@
+package com.tipcj;
+
+public class Poll {
+       /**
+        * Epoll event masks
+        */
+       public static final short EPOLLIN         = 0x00000001;
+       public static final short EPOLLPRI        = 0x00000002;
+       public static final short EPOLLOUT        = 0x00000004;
+       public static final short EPOLLERR        = 0x00000008;
+       public static final short EPOLLHUP        = 0x00000010;
+       public static final short EPOLLNVAL       = 0x00000020;
+       public static final short EPOLLRDNORM     = 0x00000040;
+       public static final short EPOLLRDBAND     = 0x00000080;
+       public static final short EPOLLWRNORM     = 0x00000100;
+       public static final short EPOLLWRBAND     = 0x00000200;
+       public static final short EPOLLMSG        = 0x00000400;
+       public static final short EPOLLRDHUP      = 0x00002000;
+
+       /**
+        * JNI instance
+        */
+       static {
+               tipcj = TipcBaseApi.getInstance();
+       }
+
+       public static final int poll(int fd, short events, java.lang.Integer 
revents, int timeout) {
+               return tipcj.tipc_poll(fd, events, revents, timeout);
+       }
+
+       public static final int pollset(int[] fds, short events, 
java.lang.Integer[] revents, int timeout) {
+               short[] jevents = new short[fds.length];
+               for (int i=0; i<fds.length; i++) {
+                       jevents[i] = events;
+               }
+               return pollset(fds, jevents, revents, timeout);
+       }
+
+       public static final int pollset(int[] fds, short[] events, 
java.lang.Integer[] revents, int timeout) {
+               for (int i=0; i<revents.length; i++) {
+                       revents[i] = 0;
+               }
+               return tipcj.tipc_pollset(fds, events, revents, timeout);
+       }
+
+       private static TipcBaseApi tipcj;
+}
diff --git a/tipcj/com/tipcj/ServiceType.java b/tipcj/com/tipcj/ServiceType.java
new file mode 100644
index 000000000000..5f79c9e75bfc
--- /dev/null
+++ b/tipcj/com/tipcj/ServiceType.java
@@ -0,0 +1,23 @@
+package com.tipcj;
+
+public class ServiceType {
+       int val;
+
+       public ServiceType(int srvtype) {
+               this.val = srvtype;
+       }
+
+       public boolean equals(Object obj) {
+               if (obj instanceof ServiceType) {
+                       return val == ((ServiceType) obj).val;
+               }
+               return false;
+       }
+
+       /* node state service type */
+       public static final ServiceType TIPC_NODE_STATE = new 
ServiceType(TipcConfig.TIPC_NODE_STATE);
+       /* topology server service type */
+       public static final ServiceType TIPC_TOP_SRV = new 
ServiceType(TipcConfig.TIPC_TOP_SRV);
+       /* link state service type */
+       public static final ServiceType TIPC_LINK_STATE = new 
ServiceType(TipcConfig.TIPC_LINK_STATE);
+}
diff --git a/tipcj/com/tipcj/SocketType.java b/tipcj/com/tipcj/SocketType.java
new file mode 100644
index 000000000000..6f3d6ae2eb00
--- /dev/null
+++ b/tipcj/com/tipcj/SocketType.java
@@ -0,0 +1,24 @@
+package com.tipcj;
+
+public final class SocketType {
+       int val;
+
+       @SuppressWarnings("unused")
+       private SocketType() {};
+
+       public SocketType(int sktype) {
+               this.val = sktype;
+       }
+
+       public boolean equals(Object obj) {
+               if (obj instanceof SocketType) {
+                       return val == ((SocketType) obj).val;
+               }
+               return false;
+       }
+
+       public static final SocketType SOCK_STREAM    = new SocketType(1); /* 
stream (connection) socket */
+       public static final SocketType SOCK_DGRAM     = new SocketType(2); /* 
datagram (conn.less) socket */
+       public static final SocketType SOCK_RDM       = new SocketType(4); /* 
reliably-delivered message */
+       public static final SocketType SOCK_SEQPACKET = new SocketType(5); /* 
sequential packet socket */
+}
diff --git a/tipcj/com/tipcj/TipcAddr.java b/tipcj/com/tipcj/TipcAddr.java
new file mode 100644
index 000000000000..1670760ff4c5
--- /dev/null
+++ b/tipcj/com/tipcj/TipcAddr.java
@@ -0,0 +1,65 @@
+/**
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2018, Ericsson Canada
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Ericsson Canada nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Version 0.1: Jon Maloy, 2018
+ *
+ * ------------------------------------------------------------------------
+ */
+
+package com.tipcj;
+
+/**
+ * @author Hoang Le (hoang.h...@dektech.com.au)
+ *
+ */
+public class TipcAddr {
+
+       public TipcAddr() {
+               Type = 0;
+               Instance = 0;
+               Node = 0;
+       }
+
+       public TipcAddr(long type, long instance, long node) {
+               Type = type;
+               Instance = instance;
+               Node = node;
+       }
+
+       public long Type = 0;
+       public long Instance = 0;
+       public long Node = 0;
+
+       public String toString() {
+               if (Type != 0) {
+                       return String.format("%d:%d@%x", Type, Instance, Node);
+               }
+               return String.format("0:%010d@%x", Instance, Node);
+       }
+}
diff --git a/tipcj/com/tipcj/TipcBaseApi.java b/tipcj/com/tipcj/TipcBaseApi.java
new file mode 100644
index 000000000000..ffdaced07146
--- /dev/null
+++ b/tipcj/com/tipcj/TipcBaseApi.java
@@ -0,0 +1,166 @@
+/**
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2018, Ericsson Canada
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Ericsson Canada nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Version 0.1: Jon Maloy, 2018
+ *
+ * ------------------------------------------------------------------------
+ */
+package com.tipcj;
+
+/**
+ * 
+ */
+import java.io.*;
+import java.nio.*;
+import java.lang.reflect.Field;
+
+/**
+ * @author Hoang Le (hoang.h...@dektech.com.au)
+ *
+ */
+final class TipcBaseApi {
+
+       /**
+        * Some helper method
+        */
+       protected native int tipc_own_node();
+       protected native String tipc_linkname(long peer, long bearerid);
+
+       /**
+        * Socket: - 'Rejectable': sent messages will return if rejected at
+        * destination
+        */
+       protected native int tipc_socket(int sk_type);
+
+       protected native int tipc_sock_non_block(int sd);
+
+       protected native int tipc_sock_rejectable(int sd);
+
+       protected native int tipc_close(int sd);
+
+       protected native int tipc_sockaddr(int sd, TipcAddr addr);
+
+       protected native int tipc_bind(int sd, long type, long lower, long 
upper, long scope);
+
+       protected native int tipc_unbind(int sd, long type, long lower, long 
upper);
+
+       protected native int tipc_connect(int sd, TipcAddr dst);
+
+       protected native int tipc_listen(int sd, long backlog);
+
+       protected native int tipc_accept(int sd, TipcAddr src);
+
+       protected native int tipc_join(int sd, TipcAddr member, boolean events, 
boolean loopback);
+
+       protected native int tipc_leave(int sd);
+
+       /**
+        * Messaging: - NULL pointer parameters are always accepted - 
tipc_sendto()
+        * to an accepting socket initiates two-way connect - If no err pointer
+        * given, tipc_recvfrom() returns 0 on rejected message - If (*err != 
0) buf
+        * contains a potentially truncated rejected message - Group event:
+        * tipc_recvfrom() returns 0; err == 0/-1 indicates up/down
+        */
+       protected native int tipc_recvfrom(int sd, ByteBuffer buf, int length, 
TipcAddr socket, TipcAddr member,
+                       java.lang.Integer err);
+
+       protected native int tipc_recv(int sd, ByteBuffer buf, int length, 
boolean waitall);
+
+       protected native int tipc_sendmsg(int sd, ByteBuffer msg, int length);
+
+       protected native int tipc_sendto(int sd, ByteBuffer msg, int length, 
TipcAddr dst);
+
+       protected native int tipc_send(int sd, ByteBuffer msg, int length);
+
+       protected native int tipc_mcast(int sd, ByteBuffer msg, int length, 
TipcAddr dst);
+
+       /** Topology Server:
+        * - Expiration time in [ms]
+        * - If (expire < 0) subscription never expires
+        */
+       protected native int tipc_topsrv_conn(long topsrv_node);
+       protected native int tipc_srv_subscr(int sd, long type, long lower, 
long upper, boolean all, int expire);
+       protected native int tipc_srv_evt(int sd, TipcAddr srv, TipcAddr addr, 
java.lang.Integer up, java.lang.Integer expired);
+       protected native boolean tipc_srv_wait(TipcAddr srv, int expire);
+
+       /**
+        * C poll API wrapper
+        */
+       protected native int tipc_poll(int fd, short events, java.lang.Integer 
revents, int timeout);
+       protected native int tipc_pollset(int[] fds, short[] events, 
java.lang.Integer[] revents, int timeout);
+
+       static {
+
+               String libSysPath = System.getProperty("java.library.path");
+               libSysPath += System.getProperty("user.dir") + 
File.pathSeparator + ".libs";
+               System.setProperty("java.library.path", libSysPath);
+
+               try {
+                       /**
+                        * Work-around to make sure java.library.path updated 
at runtime
+                        */
+                       Field fieldSysPath = 
ClassLoader.class.getDeclaredField("sys_paths");
+                       fieldSysPath.setAccessible(true);
+                       fieldSysPath.set(null, null);
+               } catch (Exception e) {
+               }
+
+               /**
+                * Load native library in static initializer of class
+                */
+               try {
+                       System.loadLibrary("tipcj");
+               } catch (UnsatisfiedLinkError e) {
+                       System.out.println("Specific -Djava.library.path where 
libtipcj.so is located");
+               }
+       }
+
+       /**
+        * 
+        */
+       private static final TipcBaseApi instance = new TipcBaseApi();
+
+       /**
+        * 
+        */
+       public static int OwnNode = 0;
+
+       /**
+        * Non expose this class
+        */
+       private TipcBaseApi() {}
+
+       /**
+        * 
+        * @return
+        */
+       protected static TipcBaseApi getInstance() {
+               return instance;
+       }
+}
diff --git a/tipcj/com/tipcj/TipcConfig.java b/tipcj/com/tipcj/TipcConfig.java
new file mode 100644
index 000000000000..41809a9bb649
--- /dev/null
+++ b/tipcj/com/tipcj/TipcConfig.java
@@ -0,0 +1,49 @@
+package com.tipcj;
+
+public interface TipcConfig {
+       public static final int TIPC_WAIT_FOREVER   = ~0; /* timeout for 
permanent subscription */
+
+       /**
+        * Application-accessible service types
+        */
+       public static final int TIPC_NODE_STATE     = 0; /* node state service 
type */
+       public static final int TIPC_TOP_SRV        = 1; /* topology server 
service type */
+       public static final int TIPC_LINK_STATE     = 2; /* link state service 
type */
+       public static final int TIPC_RESERVED_TYPES = 64; /* lowest 
user-allowed service type */
+
+       /**
+        * Publication scopes when binding service / service range
+        */
+       public static final int TIPC_CLUSTER_SCOPE   = 2; /* 0 can also be used 
*/
+       public static final int TIPC_NODE_SCOPE      = 3;
+
+       /**
+        * Limiting values for messages
+        */
+       public static final int TIPC_MAX_USER_MSG_SIZE = 66000;
+
+       /**
+        * Message importance levels
+        */
+       public static final int TIPC_LOW_IMPORTANCE       = 0;
+       public static final int TIPC_MEDIUM_IMPORTANCE    = 1;
+       public static final int TIPC_HIGH_IMPORTANCE      = 2;
+       public static final int TIPC_CRITICAL_IMPORTANCE  = 3;
+
+       /**
+        * Msg rejection/connection shutdown reasons
+        */
+       public static final int TIPC_OK             =  0;
+       public static final int TIPC_ERR_NO_NAME    =  1;
+       public static final int TIPC_ERR_NO_PORT    =  2;
+       public static final int TIPC_ERR_NO_NODE    =  3;
+       public static final int TIPC_ERR_OVERLOAD   =  4;
+       public static final int TIPC_CONN_SHUTDOWN  =  5;
+
+       /**
+        * TIPC topology subscription service definitions
+        */
+       public static final int TIPC_SUB_PORTS      = 0x01;    /* filter: evt 
at each match */
+       public static final int TIPC_SUB_SERVICE    = 0x02;    /* filter: evt 
at first up/last down */
+       public static final int TIPC_SUB_CANCEL     = 0x04;    /* filter: 
cancel a subscription */
+}
diff --git a/tipcj/com/tipcj/TipcConn.java b/tipcj/com/tipcj/TipcConn.java
new file mode 100644
index 000000000000..7def31fa1b21
--- /dev/null
+++ b/tipcj/com/tipcj/TipcConn.java
@@ -0,0 +1,320 @@
+/**
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2018, Ericsson Canada
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Ericsson Canada nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Version 0.1: Jon Maloy, 2018
+ *
+ * ------------------------------------------------------------------------
+ */
+package com.tipcj;
+
+import java.nio.BufferOverflowException;
+/**
+ * @author Hoang Le (hoang.h...@dektech.com.au)
+ *
+ */
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class TipcConn {
+
+       /**
+        * JNI instance
+        */
+       static {
+               tipcj = TipcBaseApi.getInstance();
+       }
+
+       public TipcConn(ByteBuffer buffer, SocketType sk_type) {
+               poolBuffer = buffer;
+               this.Fd = Socket(sk_type);
+               if (this.Fd > 0) {
+                       this.isOpen = true;
+               }
+       }
+
+       public TipcConn(SocketType sk_type) {
+               this.Fd = Socket(sk_type);
+               if (this.Fd > 0) {
+                       this.isOpen = true;
+               }
+               /*
+                * initialize default byte buffer
+                */
+               poolBuffer = 
ByteBuffer.allocateDirect(TipcConfig.TIPC_MAX_USER_MSG_SIZE);
+       }
+
+       /**
+        * Create AF_TIPC socket API
+        */
+       public int Socket(SocketType sk_type) {
+               return tipcj.tipc_socket(sk_type.val);
+       }
+
+       public int GetFd() {
+               return this.Fd;
+       }
+
+       /**
+        * Bind a TIPC socket to service address/socket address
+        */
+       public int Bind(int stype, int lower, int upper, int scope) {
+               return tipcj.tipc_bind(Fd, stype, lower, upper, scope);
+       }
+
+       /**
+        * Unbind a bound address
+        */
+       public int Unbind(int stype, int lower, int upper) {
+               return tipcj.tipc_unbind(Fd, stype, lower, upper);
+       }
+
+       /**
+        * Close a TIPC socket
+        */
+       public int Close() {
+               return tipcj.tipc_close(Fd);
+       }
+
+       /**
+        * Get a bound socket information
+        */
+       public int Sockaddr(TipcAddr tipcAddr) {
+               return tipcj.tipc_sockaddr(Fd, tipcAddr);
+       }
+
+       public TipcAddr Sockaddr() {
+               TipcAddr tipcAddr = new TipcAddr(0,0,0);
+               int ret = 0;
+
+               ret = tipcj.tipc_sockaddr(Fd, tipcAddr);
+               if (ret == 0) {
+                       return tipcAddr;
+               }
+               return null;
+       }
+
+       public int Sock_Non_Block() {
+               return tipcj.tipc_sock_non_block(Fd);
+       }
+
+       /**
+        * Set messages sent from this socket as rejectable
+        */
+       public int Sock_Rejectable() {
+               return tipcj.tipc_sock_rejectable(Fd);
+       }
+
+       public int Connect(TipcAddr dst) {
+               return tipcj.tipc_connect(Fd, dst);
+       }
+
+       public int Listen(int backlog) {
+               return tipcj.tipc_listen(Fd, backlog);
+       }
+
+       public int Accept(TipcAddr src) {
+               int ret = tipcj.tipc_accept(Fd, src);
+               return ret;
+       }
+
+       /**
+        * Group communication API
+        */
+       public int Join(TipcAddr member, boolean events, boolean loopback) {
+               return tipcj.tipc_join(Fd, member, events, loopback);
+       }
+
+       public int Leave() {
+               return tipcj.tipc_leave(Fd);
+       }
+
+       /** Messaging:
+        * - NULL pointer parameters are always accepted
+        * - tipc_sendto() to an accepting socket initiates two-way connect
+        * - If no err pointer given, tipc_recvfrom() returns 0 on rejected 
message
+        * - If (*err != 0) buf contains a potentially truncated rejected 
message
+        * - Group event: tipc_recvfrom() returns 0; err == 0/-1 indicates 
up/down
+        */
+       public int Recvfrom(ByteBuffer buf, int len, TipcAddr socket, TipcAddr 
member, java.lang.Integer err) {
+               return tipcj.tipc_recvfrom(Fd, buf, len, socket, member, err);
+       }
+
+       public int Recvfrom(byte[] rbuf, TipcAddr socket, TipcAddr member, 
java.lang.Integer err) {
+               int ret = 0;
+               ByteBuffer rbytebuf = ByteBuffer.allocateDirect(rbuf.length);
+               rbytebuf.clear();
+
+               ret = Recvfrom(rbytebuf, rbytebuf.remaining(), socket, member, 
err);
+               if (ret > 0) {
+                       rbytebuf.get(rbuf, 0, ret);
+               }
+               rbytebuf.clear();
+               return ret;
+       }
+
+       public int Recv(ByteBuffer buf, int len, boolean waitall) {
+               return tipcj.tipc_recv(Fd, buf, len, waitall);
+       }
+
+       public int Recv(byte[] rbuf, boolean waitall) {
+               int ret = 0;
+               int len = rbuf.length;
+               ByteBuffer rbytebuf = ByteBuffer.allocateDirect(len);
+               rbytebuf.clear();
+
+               ret = tipcj.tipc_recv(Fd, rbytebuf, len, waitall);
+               if (ret > 0) {
+                       rbytebuf.get(rbuf, 0, ret);
+               }
+               rbytebuf.clear();
+               return ret;
+       }
+
+       public static int Recv(int sd, byte[] rbuf, boolean waitall) {
+               int ret = 0;
+               int len = rbuf.length;
+               ByteBuffer rbytebuf = ByteBuffer.allocateDirect(len);
+               rbytebuf.clear();
+
+               ret = tipcj.tipc_recv(sd, rbytebuf, len, waitall);
+               if (ret > 0) {
+                       rbytebuf.get(rbuf, 0, ret);
+               }
+               rbytebuf.clear();
+               return ret;
+       }
+
+       public int Sendmsg(byte[] msg) {
+               int len = msg.length;
+               poolBuffer.clear();
+
+               if (len > poolBuffer.remaining()) {
+                       len = poolBuffer.remaining();
+               }
+
+               try {
+                       poolBuffer.put(msg, 0, len);
+               } catch (BufferOverflowException ex) {
+                       return -1;
+               } catch (ReadOnlyBufferException ex) {
+                       return -1;
+               }
+
+               return tipcj.tipc_send(Fd, poolBuffer, len);
+       }
+
+       public int Sendto(byte[] msg, TipcAddr dst) {
+               int len = msg.length;
+               poolBuffer.clear();
+
+               if (len > poolBuffer.remaining()) {
+                       len = poolBuffer.remaining();
+               }
+
+               try {
+                       poolBuffer.put(msg, 0, len);
+               } catch (BufferOverflowException ex) {
+                       return -1;
+               } catch (ReadOnlyBufferException ex) {
+                       return -1;
+               }
+
+               return tipcj.tipc_sendto(Fd, poolBuffer, len, dst);
+       }
+
+       public int Sendto(ByteBuffer buf, int len, TipcAddr dst) {
+               return tipcj.tipc_sendto(Fd, buf, len, dst);
+       }
+
+       public int Sendmcast(byte[] msg, TipcAddr dst) {
+               int len = msg.length;
+               poolBuffer.clear();
+
+               if (len > poolBuffer.remaining()) {
+                       len = poolBuffer.remaining();
+               }
+
+               try {
+                       poolBuffer.put(msg, 0, len);
+               } catch (BufferOverflowException ex) {
+                       return -1;
+               } catch (ReadOnlyBufferException ex) {
+                       return -1;
+               }
+
+               return tipcj.tipc_mcast(Fd, poolBuffer, len, dst);
+       }
+
+       public int Send(byte[] msg) {
+               int len = msg.length;
+               poolBuffer.clear();
+
+               if (len > poolBuffer.remaining()) {
+                       len = poolBuffer.remaining();
+               }
+
+               try {
+                       poolBuffer.put(msg, 0, len);
+               } catch (BufferOverflowException ex) {
+                       return -1;
+               } catch (ReadOnlyBufferException ex) {
+                       return -1;
+               }
+
+               return tipcj.tipc_send(Fd, poolBuffer, len);
+       }
+
+       public static int Send(int sd, byte[] msg) {
+               int len = msg.length;
+               ByteBuffer rbytebuf = ByteBuffer.allocateDirect(len);
+               rbytebuf.clear();
+
+               try {
+                       rbytebuf.put(msg, 0, len);
+               } catch (BufferOverflowException ex) {
+                       return -1;
+               } catch (ReadOnlyBufferException ex) {
+                       return -1;
+               }
+
+               return tipcj.tipc_send(sd, rbytebuf, len);
+       }
+
+       /**
+        * Close a TIPC socket
+        */
+       public static int Close(int fd) {
+               return tipcj.tipc_close(fd);
+       }
+
+       private static TipcBaseApi tipcj;
+       protected int Fd = 0;
+       protected boolean isOpen = false;
+       private ByteBuffer poolBuffer;
+}
diff --git a/tipcj/com/tipcj/TipcHelper.java b/tipcj/com/tipcj/TipcHelper.java
new file mode 100644
index 000000000000..aee70b8254c8
--- /dev/null
+++ b/tipcj/com/tipcj/TipcHelper.java
@@ -0,0 +1,53 @@
+/**
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2018, Ericsson Canada
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Ericsson Canada nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Version 0.1: Jon Maloy, 2018
+ *
+ * ------------------------------------------------------------------------
+ */
+package com.tipcj;
+
+/**
+ * @author Hoang Le (hoang.h...@dektech.com.au)
+ *
+ */
+public class TipcHelper {
+       /**
+        * JNI instance
+        */
+       static {
+               tipcj = TipcBaseApi.getInstance();
+       }
+
+       public static String Linkname(long peer, long bearerid) {
+               return tipcj.tipc_linkname(peer, bearerid);
+       }
+
+       private static TipcBaseApi tipcj;
+}
diff --git a/tipcj/com/tipcj/TipcServiceRange.java 
b/tipcj/com/tipcj/TipcServiceRange.java
new file mode 100644
index 000000000000..a10408e4716a
--- /dev/null
+++ b/tipcj/com/tipcj/TipcServiceRange.java
@@ -0,0 +1,65 @@
+/**
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2018, Ericsson Canada
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Ericsson Canada nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Version 0.1: Jon Maloy, 2018
+ *
+ * ------------------------------------------------------------------------
+ */
+
+package com.tipcj;
+
+/**
+ * @author Hoang Le (hoang.h...@dektech.com.au)
+ *
+ */
+public class TipcServiceRange {
+
+       public TipcServiceRange() {
+               Type = 0;
+               Lower = 0;
+               Upper = 0;
+               Node = 0;
+       }
+
+       public TipcServiceRange(long type, long lower, long upper, long scope) {
+               Type = type;
+               Lower = lower;
+               Upper = upper;
+               Node = scope;
+       }
+
+       public long Type = 0;
+       public long Lower = 0;
+       public long Upper = 0;
+       public long Node = 0;
+
+       public String toString() {
+               return String.format("%d:%d:%d@%x", Type, Lower, Upper, Node);
+       }
+}
diff --git a/tipcj/com/tipcj/TipcSrvConn.java b/tipcj/com/tipcj/TipcSrvConn.java
new file mode 100644
index 000000000000..063ea794813a
--- /dev/null
+++ b/tipcj/com/tipcj/TipcSrvConn.java
@@ -0,0 +1,108 @@
+/**
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2018, Ericsson Canada
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Ericsson Canada nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Version 0.1: Jon Maloy, 2018
+ *
+ * ------------------------------------------------------------------------
+ */
+package com.tipcj;
+
+/**
+ * @author Hoang Le (hoang.h...@dektech.com.au)
+ *
+ */
+public class TipcSrvConn {
+       /**
+        * JNI instance
+        */
+       static {
+               tipcj = TipcBaseApi.getInstance();
+       }
+
+       @SuppressWarnings("unused")
+       private TipcSrvConn() {};
+
+       /**
+        * Constructor to connect topology server
+        * @param node
+        */
+       public TipcSrvConn(long node) {
+               this.Fd = SrvConn(node);
+       }
+
+       public TipcSrvConn(long node, ServiceType srvType) {
+               this(node);
+               if (this.Fd <= 0) {
+                       return;
+               }
+
+               if (srvType.equals(ServiceType.TIPC_TOP_SRV) || 
srvType.equals(ServiceType.TIPC_LINK_STATE)) {
+                       this.filterEvtAll = true;
+               }
+               /**
+                * Subscribe to subscription(s)
+                */
+               this.SrvScr(srvType.val, 0, Integer.MAX_VALUE, 
this.filterEvtAll, -1);
+       }
+
+       public int getFd() {
+               return this.Fd;
+       }
+
+       /** Topology Server:
+        * - Expiration time in [ms]
+        * - If (expire < 0) subscription never expires
+        */
+       private int SrvConn(long node) {
+               return tipcj.tipc_topsrv_conn(node);
+       }
+
+       public int SrvScr(long type, long lower, long upper, boolean filterAll, 
int expire) {
+               if (this.Fd <=0 ) {
+                       return -1;
+               }
+               return tipcj.tipc_srv_subscr(this.Fd, type, lower, upper, 
filterAll, expire);
+       }
+
+       public int GetEvt(TipcAddr srv, TipcAddr id, java.lang.Integer up, 
java.lang.Integer expired) {
+               return tipcj.tipc_srv_evt(this.Fd, srv, id, up, expired);
+       }
+
+       public static boolean SrvWait(TipcAddr srv, int expire) {
+               return tipcj.tipc_srv_wait(srv, expire);
+       }
+
+       public void Close() {
+               tipcj.tipc_close(this.Fd);
+       }
+
+       private static TipcBaseApi tipcj;
+       protected int Fd = 0;
+       protected boolean filterEvtAll = false;
+}
diff --git a/tipcj/include/tipcjni.h b/tipcj/include/tipcjni.h
new file mode 100644
index 000000000000..9693726aa35b
--- /dev/null
+++ b/tipcj/include/tipcjni.h
@@ -0,0 +1,221 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_tipcj_TipcBaseApi */
+
+#ifndef _Included_com_tipcj_TipcBaseApi
+#define _Included_com_tipcj_TipcBaseApi
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_own_node
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1own_1node
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_linkname
+ * Signature: (JJ)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_tipcj_TipcBaseApi_tipc_1linkname
+  (JNIEnv *, jobject, jlong, jlong);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_socket
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1socket
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sock_non_block
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sock_1non_1block
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sock_rejectable
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sock_1rejectable
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_close
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1close
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sockaddr
+ * Signature: (ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sockaddr
+  (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_bind
+ * Signature: (IJJJJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1bind
+  (JNIEnv *, jobject, jint, jlong, jlong, jlong, jlong);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_unbind
+ * Signature: (IJJJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1unbind
+  (JNIEnv *, jobject, jint, jlong, jlong, jlong);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_connect
+ * Signature: (ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1connect
+  (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_listen
+ * Signature: (IJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1listen
+  (JNIEnv *, jobject, jint, jlong);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_accept
+ * Signature: (ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1accept
+  (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_join
+ * Signature: (ILcom/tipcj/TipcAddr;ZZ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1join
+  (JNIEnv *, jobject, jint, jobject, jboolean, jboolean);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_leave
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1leave
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_recvfrom
+ * Signature: 
(ILjava/nio/ByteBuffer;ILcom/tipcj/TipcAddr;Lcom/tipcj/TipcAddr;Ljava/lang/Integer;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1recvfrom
+  (JNIEnv *, jobject, jint, jobject, jint, jobject, jobject, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_recv
+ * Signature: (ILjava/nio/ByteBuffer;IZ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1recv
+  (JNIEnv *, jobject, jint, jobject, jint, jboolean);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sendmsg
+ * Signature: (ILjava/nio/ByteBuffer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sendmsg
+  (JNIEnv *, jobject, jint, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sendto
+ * Signature: (ILjava/nio/ByteBuffer;ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sendto
+  (JNIEnv *, jobject, jint, jobject, jint, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_send
+ * Signature: (ILjava/nio/ByteBuffer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1send
+  (JNIEnv *, jobject, jint, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_mcast
+ * Signature: (ILjava/nio/ByteBuffer;ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1mcast
+  (JNIEnv *, jobject, jint, jobject, jint, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_topsrv_conn
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1topsrv_1conn
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_srv_subscr
+ * Signature: (IJJJZI)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1srv_1subscr
+  (JNIEnv *, jobject, jint, jlong, jlong, jlong, jboolean, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_srv_evt
+ * Signature: 
(ILcom/tipcj/TipcAddr;Lcom/tipcj/TipcAddr;Ljava/lang/Integer;Ljava/lang/Integer;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1srv_1evt
+  (JNIEnv *, jobject, jint, jobject, jobject, jobject, jobject);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_srv_wait
+ * Signature: (Lcom/tipcj/TipcAddr;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_tipcj_TipcBaseApi_tipc_1srv_1wait
+  (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_poll
+ * Signature: (ISLjava/lang/Integer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1poll
+  (JNIEnv *, jobject, jint, jshort, jobject, jint);
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_pollset
+ * Signature: ([I[S[Ljava/lang/Integer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1pollset
+  (JNIEnv *, jobject, jintArray, jshortArray, jobjectArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tipcj/libtipcj.c b/tipcj/libtipcj.c
new file mode 100644
index 000000000000..76d16ac9d9ac
--- /dev/null
+++ b/tipcj/libtipcj.c
@@ -0,0 +1,594 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <error.h>
+#include <poll.h>
+#include <jni.h>
+#include "tipcc.h"
+#include "tipcjni.h"
+
+/*
+ * Caching java classes and method Ids
+ */
+static jclass jclassInt = NULL;
+static jfieldID jclassIntField = NULL;
+static jmethodID jclassIntNewObject = NULL; /* constructor java.lang.Integer */
+
+static jclass jclassTipcAddr = NULL;
+static jfieldID jtipcAddrType = NULL;
+static jfieldID jtipcAddrInstance = NULL;
+static jfieldID jtipcAddrNode = NULL;
+
+/*
+ * Function to convert from C struct tipc_addr to Java TipcAddr instance
+ */
+static void convertTipcAddrToJNI(JNIEnv* env, const struct tipc_addr* addr, 
jobject jobjTipcAddr) {
+       if (!jobjTipcAddr || !addr)
+               return;
+
+       (*env)->SetLongField(env, jobjTipcAddr, jtipcAddrType, (jlong)(unsigned 
long)addr->type);
+       (*env)->SetLongField(env, jobjTipcAddr, jtipcAddrInstance, 
(jlong)(unsigned long)addr->instance);
+       (*env)->SetLongField(env, jobjTipcAddr, jtipcAddrNode, (jlong)(unsigned 
long)addr->node);
+}
+
+/*
+ * Function to convert from Java TipcAddr instance to C struct tipc_addr
+ */
+static void convertTipcAddrFromJNI(JNIEnv* env, struct tipc_addr* addr, 
jobject jobjTipcAddr) {
+       if (!addr || !jobjTipcAddr)
+               return;
+
+       addr->type = (uint32_t)(*env)->GetLongField(env, jobjTipcAddr, 
jtipcAddrType);
+       addr->instance = (uint32_t)(*env)->GetLongField(env, jobjTipcAddr, 
jtipcAddrInstance);
+       addr->node = (uint32_t)(*env)->GetLongField(env, jobjTipcAddr, 
jtipcAddrNode);
+}
+
+jint throwOutOfMemoryError(JNIEnv *env)
+{
+       jclass localExClass;
+       localExClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
+       if (localExClass) {
+               return (*env)->ThrowNew( env, localExClass, "Out Of Memory");
+       }
+       return -1;
+}
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+       JNIEnv* env;
+       if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
+               return JNI_ERR;
+       } else {
+               jclass localIntClass = (*env)->FindClass(env, 
"java/lang/Integer");
+
+               if (localIntClass) {
+                       jclassInt = (*env)->NewGlobalRef(env, localIntClass);
+                       /*
+                        * Release local ref
+                        */
+                       (*env)->DeleteLocalRef(env, localIntClass);
+                       if (jclassInt == NULL) {
+                               return JNI_ERR;
+                       }
+               }
+
+               jclassIntField = (*env)->GetFieldID(env, jclassInt, "value", 
"I");
+               if (jclassIntField == NULL) {
+                       goto releaseGlobalClassInt;
+               }
+
+               jclassIntNewObject = (*env)->GetMethodID(env, jclassInt, 
"<init>", "(I)V");
+               if (jclassIntNewObject == NULL) {
+                       goto releaseGlobalClassInt;
+               }
+
+               jclass localTipcAddrclass = (*env)->FindClass(env, 
"com/tipcj/TipcAddr");
+               if (localTipcAddrclass == NULL) {
+                       goto releaseGlobalClassInt;
+               } else {
+                       jclassTipcAddr = (*env)->NewGlobalRef(env, 
localTipcAddrclass);
+                       /*
+                        * Release local ref
+                        */
+                       (*env)->DeleteLocalRef(env, localTipcAddrclass);
+               }
+               jtipcAddrType = (*env)->GetFieldID(env, jclassTipcAddr, "Type", 
"J");
+               jtipcAddrInstance = (*env)->GetFieldID(env, jclassTipcAddr, 
"Instance", "J");
+               jtipcAddrNode = (*env)->GetFieldID(env, jclassTipcAddr, "Node", 
"J");
+               if (!jtipcAddrType || !jtipcAddrInstance || !jtipcAddrNode)
+                       goto releaseGlobalClassTipcAddr;
+       }
+
+       return JNI_VERSION_1_6;
+
+releaseGlobalClassTipcAddr:
+       (*env)->DeleteGlobalRef(env, jclassTipcAddr);
+releaseGlobalClassInt:
+       (*env)->DeleteGlobalRef(env, jclassInt);
+       return JNI_ERR;
+}
+
+void JNI_OnUnload(JavaVM *vm, void *reserved) {
+       JNIEnv* env;
+       if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
+               return;
+       } else {
+               (*env)->DeleteGlobalRef(env, jclassInt);
+               (*env)->DeleteGlobalRef(env, jclassTipcAddr);
+       }
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_own_node
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1own_1node
+  (JNIEnv *env, jobject jobj) {
+       return tipc_own_node();
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_linkname
+ * Signature: (JJ)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_tipcj_TipcBaseApi_tipc_1linkname
+  (JNIEnv *env, jobject jobj, jlong peer, jlong bearerid) {
+#define BUF_SZ 40
+       char buf[BUF_SZ] = {0};
+       tipc_linkname(buf, BUF_SZ, peer, bearerid);
+       return (*env)->NewStringUTF(env, buf);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_socket
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1socket
+  (JNIEnv *jenv, jobject jobj, jint sk_type) {
+       int fd;
+       fd = tipc_socket(sk_type);
+       if (fd < 0 ) {
+               printf("Err: [%s]\n", strerror(errno));
+               return 0;
+       }
+       return fd;
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sock_non_block
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sock_1non_1block
+  (JNIEnv *env, jobject obj, jint jfd) {
+       return tipc_sock_non_block(jfd);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sock_rejectable
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sock_1rejectable
+(JNIEnv *env, jobject obj, jint jfd) {
+       return tipc_sock_rejectable(jfd);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_close
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1close
+  (JNIEnv *env, jobject jobj, jint jfd) {
+         return tipc_close(jfd);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sockaddr
+ * Signature: (ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sockaddr
+  (JNIEnv *env, jobject obj, jint jfd, jobject jtipcAddr) {
+       struct tipc_addr addr = {0, 0, 0};
+       int ret = 0;
+
+       ret = tipc_sockaddr(jfd, &addr);
+       if (!ret && jtipcAddr) {
+               convertTipcAddrToJNI(env, &addr, jtipcAddr);
+       }
+
+       return ret;
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_bind
+ * Signature: (IJJJJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1bind
+  (JNIEnv *env, jobject jobj, jint sd, jlong type, jlong lower, jlong upper, 
jlong scope) {
+         return tipc_bind(sd, type, lower, upper, scope);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_unbind
+ * Signature: (IJJJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1unbind
+  (JNIEnv *env, jobject jobj, jint sd, jlong type, jlong lower, jlong upper) {
+       return tipc_unbind(sd, type, lower, upper);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_connect
+ * Signature: (ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1connect
+  (JNIEnv *env, jobject jobj, jint sd, jobject jtipcAddr) {
+       struct tipc_addr addr = {0, 0, 0};
+
+       if (jtipcAddr == NULL) {
+               return -1;
+       }
+       convertTipcAddrFromJNI(env, &addr, jtipcAddr);
+       return tipc_connect(sd, &addr);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_listen
+ * Signature: (IJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1listen
+  (JNIEnv *env, jobject jobj, jint sd, jlong backlog) {
+       return tipc_listen(sd, backlog);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_accept
+ * Signature: (ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1accept
+  (JNIEnv *env, jobject obj, jint sd, jobject jtipcAddr) {
+       struct tipc_addr addr = {0, 0, 0};
+       int ret = 0;
+
+       if (jtipcAddr != NULL) {
+               ret = tipc_accept(sd, &addr);
+               if (ret) {
+                       convertTipcAddrToJNI(env, &addr, jtipcAddr);
+               }
+               return ret;
+       }
+       return tipc_accept(sd, NULL);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_join
+ * Signature: (ILcom/tipcj/TipcAddr;ZZ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1join
+  (JNIEnv *env, jobject obj, jint sd, jobject jtipcAddr, jboolean jevents, 
jboolean jloopback) {
+       struct tipc_addr addr = {0, 0, 0};
+       bool events = 0, loopback = 0;
+
+       if (jevents == JNI_TRUE) {
+               events = 1;
+       }
+
+       if (jloopback == JNI_TRUE) {
+               loopback = 1;
+       }
+
+       if (jtipcAddr != NULL) {
+               convertTipcAddrFromJNI(env, &addr, jtipcAddr);
+       }
+
+       return tipc_join(sd, &addr, events, loopback);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_leave
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1leave
+  (JNIEnv *env, jobject jobj, jint sd) {
+       return tipc_leave(sd);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_recvfrom
+ * Signature: 
(ILjava/nio/ByteBuffer;ILcom/tipcj/TipcAddr;Lcom/tipcj/TipcAddr;Ljava/lang/Integer;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1recvfrom
+  (JNIEnv *env, jobject jobj, jint jfd, jobject jbuf, jint len, jobject 
jsocket, jobject jmemberid, jobject jerr) {
+
+       struct tipc_addr socket = {0, 0, 0};
+       struct tipc_addr memberid = {0, 0, 0};
+       void *buf = NULL;
+       int err = 0;
+       int ret = 0;
+
+       buf = (void *) (*env)->GetDirectBufferAddress (env, jbuf);
+       if (buf == NULL) {
+               return throwOutOfMemoryError(env);
+       }
+
+       /*
+        * Calling TIPC C Api
+        */
+       ret = tipc_recvfrom(jfd, buf, len, &socket, &memberid, &err);
+       /**
+        * Convert c int to jInteger
+        */
+       (*env)->SetIntField(env, jerr, jclassIntField, err);
+       if (jmemberid != NULL) {
+               convertTipcAddrToJNI(env, &memberid, jmemberid);
+       }
+
+       if (jsocket != NULL) {
+               convertTipcAddrToJNI(env, &socket, jsocket);
+       }
+
+       return ret;
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_recv
+ * Signature: (ILjava/nio/ByteBuffer;IZ)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1recv
+  (JNIEnv *env, jobject jobj, jint jfd, jobject jbuf, jint len, jboolean 
jwaitall) {
+       int waitall = 0;
+       void *buf = NULL;
+
+       if (jwaitall == JNI_TRUE)
+               waitall = 1;
+
+       buf = (void *) (*env)->GetDirectBufferAddress (env, jbuf);
+       if (buf == NULL) {
+               return throwOutOfMemoryError(env);
+       }
+
+       return tipc_recv(jfd, buf, len, waitall);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sendmsg
+ * Signature: (ILjava/nio/ByteBuffer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sendmsg
+  (JNIEnv *env, jobject obj, jint jfd, jobject jbuf, jint len) {
+       void *buf = NULL;
+
+       buf = (void *) (*env)->GetDirectBufferAddress (env, jbuf);
+       if (buf == NULL) {
+               return throwOutOfMemoryError(env);
+       }
+
+       return tipc_send(jfd, buf, len);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_sendto
+ * Signature: (ILjava/nio/ByteBuffer;ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1sendto
+  (JNIEnv *env, jobject jobj, jint jfd, jobject jbuf, jint len, jobject 
jtipcAddr) {
+       struct tipc_addr dst = {0,0,0};
+       void *buf = NULL;
+       int ret = 0;
+
+       buf = (void *) (*env)->GetDirectBufferAddress (env, jbuf);
+       if (buf == NULL || jtipcAddr == NULL) {
+               return throwOutOfMemoryError(env);
+       }
+       convertTipcAddrFromJNI(env, &dst, jtipcAddr);
+       /*
+        * Calling TIPC C Api
+        */
+       ret = tipc_sendto(jfd, buf, len, &dst);
+
+       return ret;
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_send
+ * Signature: (ILjava/nio/ByteBuffer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1send
+  (JNIEnv *env, jobject jobj, jint jfd, jobject jbuf, jint len) {
+       /**
+        * TODO
+        */
+       return Java_com_tipcj_TipcBaseApi_tipc_1sendmsg(env, jobj, jfd, jbuf, 
len);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_mcast
+ * Signature: (ILjava/nio/ByteBuffer;ILcom/tipcj/TipcAddr;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1mcast
+  (JNIEnv *env, jobject obj, jint sd, jobject jbuf, jint len, jobject 
jtipcAddr) {
+       struct tipc_addr dst = {0,0,0};
+       void *buf = NULL;
+
+       buf = (void *) (*env)->GetDirectBufferAddress (env, jbuf);
+       if (buf == NULL || jtipcAddr == NULL) {
+               return throwOutOfMemoryError(env);
+       }
+       convertTipcAddrFromJNI(env, &dst, jtipcAddr);
+       return tipc_mcast(sd, buf, len, &dst);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_topsrv_conn
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1topsrv_1conn
+  (JNIEnv *env, jobject obj, jlong node) {
+       return tipc_topsrv_conn((uint32_t)node);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_srv_subscr
+ * Signature: (IJJJZI)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1srv_1subscr
+  (JNIEnv *env, jobject obj, jint sd, jlong type, jlong lower, jlong upper, 
jboolean jall, jint expire) {
+       bool all = false;
+
+       if (jall == JNI_TRUE) {
+               all = true;
+       }
+       return tipc_srv_subscr(sd, (uint32_t)type, (uint32_t)lower, 
(uint32_t)upper, all, expire);
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_srv_evt
+ * Signature: 
(ILcom/tipcj/TipcAddr;Lcom/tipcj/TipcAddr;Ljava/lang/Integer;Ljava/lang/Integer;)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1srv_1evt
+  (JNIEnv *env, jobject obj, jint sd, jobject jsrv, jobject jid, jobject 
javailable, jobject jexpired) {
+       struct tipc_addr srv = {0, 0, 0}, id = {0, 0, 0};
+       int ret = 0;
+       bool available = false, expired = false;
+
+       ret = tipc_srv_evt(sd, &srv, &id, &available, &expired);
+       if (!ret && !expired) {
+               if (jsrv != NULL) {
+                       convertTipcAddrToJNI(env, &srv, jsrv);
+               }
+
+               if (jid != NULL) {
+                       convertTipcAddrToJNI(env, &id, jid);
+               }
+       }
+
+       if (javailable) {
+               (*env)->SetIntField(env, javailable, jclassIntField, available);
+       }
+       if (jexpired) {
+               (*env)->SetIntField(env, jexpired, jclassIntField, expired);
+       }
+
+       return ret;
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_srv_wait
+ * Signature: (Lcom/tipcj/TipcAddr;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_tipcj_TipcBaseApi_tipc_1srv_1wait
+  (JNIEnv *env, jobject jobj, jobject jtipcAddr, jint wait) {
+       struct tipc_addr srv = {0,0,0};
+       int up = 0;
+
+       convertTipcAddrFromJNI(env, &srv, jtipcAddr);
+       up = tipc_srv_wait(&srv, wait);
+       if (up)
+               return JNI_TRUE;
+
+       return JNI_FALSE;
+}
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_poll
+ * Signature: (ISLjava/lang/Integer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1poll
+  (JNIEnv *env, jobject obj, jint jfd, jshort events, jobject revents, jint 
timeout) {
+       struct pollfd pfd;
+       int ret = 0;
+
+       pfd.fd = jfd;
+       pfd.events = events;
+
+       ret = poll(&pfd, 1, timeout);
+       if (ret && revents) {
+               (*env)->SetIntField(env, revents, jclassIntField, pfd.revents);
+       }
+       return ret;
+}
+
+/*
+ * Class:     com_tipcj_TipcBaseApi
+ * Method:    tipc_pollset
+ * Signature: ([I[S[Ljava/lang/Integer;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_tipcj_TipcBaseApi_tipc_1pollset
+  (JNIEnv *env, jobject obj, jintArray jfds, jshortArray jevents, jobjectArray 
revents, jint timeout) {
+       jsize lenFds = (*env)->GetArrayLength(env, jfds);
+       jsize lenEvtArr = (*env)->GetArrayLength(env, jevents);
+       struct pollfd *pfd = NULL;
+       int ret = 0;
+       int i = 0;
+       jint *jintArr = (*env)->GetIntArrayElements(env, jfds, 0);
+       jshort *jshortArr = (*env)->GetShortArrayElements(env, jevents, 0);
+
+       // Validate parameters
+       if (lenEvtArr != lenFds) {
+               goto releaseArr;
+       }
+
+       if (jintArr && jshortArr && lenFds >= 1) {
+               pfd = malloc(lenFds * sizeof(struct pollfd));
+               if (pfd == NULL) {
+                       goto releaseArr;
+               }
+               memset(pfd, 0, lenFds * sizeof(struct pollfd));
+       }
+
+       for (i = 0; i<lenFds; i++) {
+               pfd[i].fd = jintArr[i];
+               pfd[i].events = jshortArr[i];
+               pfd[i].revents = 0;
+       }
+
+       ret = poll(pfd, lenFds, timeout);
+       for (i = 0; i<lenFds; i++) {
+               // return revents from pfd revents
+               jobject obj = (*env)->GetObjectArrayElement(env, revents, i);
+               if (obj == NULL) {
+                       obj = (*env)->NewObject(env, jclassInt, 
jclassIntNewObject, pfd[i].revents);
+                       if (obj != NULL) {
+                               (*env)->SetObjectArrayElement(env, revents, i, 
obj);
+                       }
+               } else {
+                       (*env)->SetIntField(env, obj, jclassIntField, 
pfd[i].revents);
+               }
+       }
+       free(pfd);
+
+releaseArr:
+       (*env)->ReleaseIntArrayElements(env, jfds, jintArr, 0);
+       (*env)->ReleaseShortArrayElements(env, jevents, jshortArr, 0);
+
+       return ret;
+}
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to