mirror of
https://github.com/Telecominfraproject/wlan-cloud-opensync-controller.git
synced 2026-03-21 22:39:22 +00:00
Renamed projects to follow a naming convention. Moved KDC-specific projects into a separate repository
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package ai.connectus.opensync.experiment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ai.connectus.opensync.external.integration.ConnectusOvsdbClientInterface;
|
||||
|
||||
@Profile("ovsdb_manager")
|
||||
@RestController
|
||||
public class OpenSyncConnectusController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpenSyncConnectusController.class);
|
||||
|
||||
@Autowired
|
||||
ConnectusOvsdbClientInterface connectusOvsdbClient;
|
||||
|
||||
@RequestMapping(value = "/connectedClients", method = RequestMethod.GET)
|
||||
public List<String> getConnectedClients()
|
||||
{
|
||||
List<String> ret = new ArrayList<String>(connectusOvsdbClient.getConnectedClientIds());
|
||||
LOG.info("Returning connected clients {}", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/changeRedirectorAddress", method = RequestMethod.POST)
|
||||
public String changeRedirectorAddress(@RequestParam String apId, @RequestParam String newRedirectorAddress)
|
||||
{
|
||||
LOG.info("Changing redirector address for AP {} to {}", apId, newRedirectorAddress);
|
||||
String ret = connectusOvsdbClient.changeRedirectorAddress(apId, newRedirectorAddress);
|
||||
LOG.info("Changed redirector address for AP {} to {}", apId, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package ai.connectus.opensync.experiment;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@ComponentScan(basePackages={"com.whizcontrol", "ai.connectus"})
|
||||
@EnableAutoConfiguration
|
||||
public class OpenSyncProcess {
|
||||
|
||||
/**
|
||||
* <br>{@code java -Dssl.props=file:./ssl.properties -Dlogback.configurationFile=file:./logback.xml -jar ./opensync-experiment-0.0.1-SNAPSHOT.jar}
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext applicationContext = SpringApplication.run(OpenSyncProcess.class, args);
|
||||
// signal start of the application context
|
||||
applicationContext.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package ai.connectus.opensync.mqtt;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.fusesource.mqtt.client.BlockingConnection;
|
||||
import org.fusesource.mqtt.client.MQTT;
|
||||
import org.fusesource.mqtt.client.Message;
|
||||
import org.fusesource.mqtt.client.QoS;
|
||||
import org.fusesource.mqtt.client.Topic;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.protobuf.Descriptors;
|
||||
import com.google.protobuf.MessageOrBuilder;
|
||||
import com.google.protobuf.util.JsonFormat;
|
||||
import com.google.protobuf.util.JsonFormat.TypeRegistry;
|
||||
|
||||
import ai.connectus.opensync.external.integration.OpensyncExternalIntegrationInterface;
|
||||
import ai.connectus.opensync.util.ZlibUtil;
|
||||
import sts.PlumeStats;
|
||||
import sts.PlumeStats.Report;
|
||||
import traffic.NetworkMetadata;
|
||||
import traffic.NetworkMetadata.FlowReport;
|
||||
import wc.stats.IpDnsTelemetry;
|
||||
import wc.stats.IpDnsTelemetry.WCStatsReport;
|
||||
|
||||
@Profile("mqtt_receiver")
|
||||
@Component
|
||||
public class OpensyncMqttClient implements ApplicationListener<ContextClosedEvent> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpensyncMqttClient.class);
|
||||
|
||||
private static final Logger MQTT_LOG = LoggerFactory.getLogger("MQTT_DATA");
|
||||
|
||||
public static Charset utf8 = Charset.forName("UTF-8");
|
||||
|
||||
@Autowired
|
||||
private OpensyncExternalIntegrationInterface extIntegrationInterface;
|
||||
|
||||
|
||||
//
|
||||
// See https://github.com/fusesource/mqtt-client for the docs
|
||||
//
|
||||
|
||||
private boolean keepReconnecting = true;
|
||||
private Thread mqttClientThread;
|
||||
|
||||
public OpensyncMqttClient(
|
||||
@Autowired io.netty.handler.ssl.SslContext sslContext,
|
||||
@Value("${connectus.mqttBroker.address:testportal.123wlan.com}")
|
||||
String mqttBrokerAddress,
|
||||
@Value("${connectus.mqttBroker.listenPort:1883}")
|
||||
int mqttBrokerListenPort,
|
||||
@Value("${connectus.mqttBroker.user:admin}")
|
||||
String username,
|
||||
@Value("${connectus.mqttBroker.password:admin}")
|
||||
String password
|
||||
){
|
||||
|
||||
Runnable mqttClientRunnable = () -> {
|
||||
while(keepReconnecting) {
|
||||
BlockingConnection connection = null;
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
|
||||
// Create a new MQTT connection to the broker.
|
||||
/*
|
||||
* Using SSL connections
|
||||
* If you want to connect over SSL/TLS instead of
|
||||
* TCP, use an "ssl://" or "tls://" URI prefix instead of "tcp://" for
|
||||
* the host field.
|
||||
* Supported protocol values are:
|
||||
*
|
||||
* ssl:// - Use the JVM default version of the SSL algorithm.
|
||||
* sslv*:// - Use a specific SSL version where * is a version supported by your JVM. Example: sslv3
|
||||
* tls:// - Use the JVM default version of the TLS algorithm.
|
||||
* tlsv*:// - Use a specific TLS version where * is a version supported by your JVM. Example: tlsv1.1
|
||||
* The client will use the
|
||||
* default JVM SSLContext which is configured via JVM system properties
|
||||
* unless you configure the MQTT instance using the setSslContext method.
|
||||
*
|
||||
* SSL connections perform blocking operations against internal thread
|
||||
* pool unless you call the setBlockingExecutor method to configure that
|
||||
* executor they will use instead.
|
||||
*
|
||||
*/
|
||||
|
||||
MQTT mqtt = new MQTT();
|
||||
//mqtt.setHost("tcp://192.168.0.137:61616");
|
||||
mqtt.setHost("tls://"+mqttBrokerAddress+":"+mqttBrokerListenPort);
|
||||
LOG.info("Connecting to Artemis using MQTT at {}", mqtt.getHost());
|
||||
mqtt.setClientId("opensync_mqtt");
|
||||
mqtt.setUserName(username);
|
||||
mqtt.setPassword(password);
|
||||
//Note: the following does not work with the serverContext, it has to be the clientContext
|
||||
//mqtt.setSslContext(((JdkSslContext) sslContext).context());
|
||||
//For now we'll rely on regular SSLContext from the JDK
|
||||
|
||||
//TODO: revisit this blocking connection, change it to futureConnection
|
||||
connection = mqtt.blockingConnection();
|
||||
connection.connect();
|
||||
LOG.info("Connected to Artemis cluster at {}", mqtt.getHost());
|
||||
|
||||
// Subscribe to topics:
|
||||
//
|
||||
// new Topic("mqtt/example/publish", QoS.AT_LEAST_ONCE),
|
||||
// new Topic("#", QoS.AT_LEAST_ONCE),
|
||||
// new Topic("test/#", QoS.EXACTLY_ONCE),
|
||||
// new Topic("foo/+/bar", QoS.AT_LEAST_ONCE)
|
||||
Topic[] topics = {
|
||||
new Topic("#", QoS.AT_LEAST_ONCE),
|
||||
};
|
||||
|
||||
connection.subscribe(topics);
|
||||
LOG.info("Subscribed to mqtt topics {}", Arrays.asList(topics));
|
||||
|
||||
//prepare a JSONPrinter to format protobuf messages as json
|
||||
List<Descriptors.Descriptor> protobufDescriptors = new ArrayList<>();
|
||||
protobufDescriptors.addAll(PlumeStats.getDescriptor().getMessageTypes());
|
||||
protobufDescriptors.addAll(IpDnsTelemetry.getDescriptor().getMessageTypes());
|
||||
protobufDescriptors.addAll(NetworkMetadata.getDescriptor().getMessageTypes());
|
||||
TypeRegistry oldRegistry = TypeRegistry.newBuilder().add(protobufDescriptors).build();
|
||||
JsonFormat.Printer jsonPrinter = JsonFormat.printer().includingDefaultValueFields().omittingInsignificantWhitespace().usingTypeRegistry(oldRegistry );
|
||||
|
||||
//main loop - receive messages
|
||||
while(true) {
|
||||
Message mqttMsg = connection.receive(5, TimeUnit.SECONDS);
|
||||
|
||||
if(mqttMsg == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte payload[] = mqttMsg.getPayload();
|
||||
//we acknowledge right after receive because:
|
||||
// a. none of the stats messages are so important that we cannot skip one
|
||||
// b. if there's some kind of problem with the message (decoding or processing) - we want to move on as quickly as possible and not let it get stuck in the queue
|
||||
mqttMsg.ack();
|
||||
|
||||
LOG.trace("received message on topic {} size {}", mqttMsg.getTopic(), payload.length);
|
||||
|
||||
if(payload[0]==0x78) {
|
||||
//looks like zlib-compressed data, let's decompress it before deserializing
|
||||
payload = ZlibUtil.decompress(payload);
|
||||
}
|
||||
|
||||
//attempt to parse the message as protobuf
|
||||
MessageOrBuilder encodedMsg = null;
|
||||
|
||||
try {
|
||||
encodedMsg = Report.parseFrom(payload);
|
||||
MQTT_LOG.debug("topic = {} Report = {}", mqttMsg.getTopic(), jsonPrinter.print(encodedMsg));
|
||||
extIntegrationInterface.processMqttMessage(mqttMsg.getTopic(), (Report) encodedMsg);
|
||||
|
||||
}catch(Exception e) {
|
||||
try {
|
||||
//not a plume_stats report, attempt to deserialize as network_metadata
|
||||
encodedMsg = FlowReport.parseFrom(payload);
|
||||
MQTT_LOG.debug("topic = {} FlowReport = {}", mqttMsg.getTopic(), jsonPrinter.print(encodedMsg));
|
||||
extIntegrationInterface.processMqttMessage(mqttMsg.getTopic(), (FlowReport) encodedMsg);
|
||||
}catch(Exception e1) {
|
||||
|
||||
try {
|
||||
//not a plume_stats report and not network_metadata report, attempt to deserialize as WCStatsReport
|
||||
encodedMsg = WCStatsReport.parseFrom(payload);
|
||||
MQTT_LOG.debug("topic = {} IpDnsTelemetry = {}", mqttMsg.getTopic(), jsonPrinter.print(encodedMsg));
|
||||
extIntegrationInterface.processMqttMessage(mqttMsg.getTopic(), (WCStatsReport) encodedMsg);
|
||||
}catch(Exception e2) {
|
||||
String msgStr = new String(mqttMsg.getPayload(), utf8);
|
||||
MQTT_LOG.debug("topic = {} message = {}", mqttMsg.getTopic(), msgStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
LOG.error("Exception in MQTT receiver", e);
|
||||
} finally {
|
||||
try {
|
||||
if(connection!=null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
} catch(Exception e1) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Thread mqttClientThread = new Thread(mqttClientRunnable, "mqttClientThread");
|
||||
mqttClientThread.setDaemon(true);
|
||||
mqttClientThread.start();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextClosedEvent event) {
|
||||
LOG.debug("Processing ContextClosedEvent event");
|
||||
keepReconnecting = false;
|
||||
mqttClientThread.interrupt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package ai.connectus.opensync.ovsdb;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.vmware.ovsdb.callback.ConnectionCallback;
|
||||
import com.vmware.ovsdb.service.OvsdbClient;
|
||||
import com.vmware.ovsdb.service.OvsdbPassiveConnectionListener;
|
||||
|
||||
import ai.connectus.opensync.external.integration.ConnectusOvsdbClientInterface;
|
||||
import ai.connectus.opensync.external.integration.OpensyncExternalIntegrationInterface;
|
||||
import ai.connectus.opensync.external.integration.OvsdbSession;
|
||||
import ai.connectus.opensync.external.integration.OvsdbSessionMapInterface;
|
||||
import ai.connectus.opensync.external.integration.models.ConnectNodeInfo;
|
||||
import ai.connectus.opensync.external.integration.models.OpensyncAPConfig;
|
||||
import ai.connectus.opensync.ovsdb.dao.OvsdbDao;
|
||||
import ai.connectus.opensync.util.SslUtil;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
|
||||
@Profile("ovsdb_manager")
|
||||
@Component
|
||||
public class ConnectusOvsdbClient implements ConnectusOvsdbClientInterface {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConnectusOvsdbClient.class);
|
||||
|
||||
|
||||
@org.springframework.beans.factory.annotation.Value("${connectus.ovsdb.listenPort:6640}")
|
||||
private int ovsdbListenPort;
|
||||
|
||||
@org.springframework.beans.factory.annotation.Value("${connectus.manager.collectionIntervalSec.deviceStats:10}")
|
||||
private long collectionIntervalSecDeviceStats;
|
||||
|
||||
@Autowired
|
||||
private SslContext sslContext;
|
||||
|
||||
@Autowired
|
||||
private OvsdbPassiveConnectionListener listener;
|
||||
|
||||
@Autowired
|
||||
private OvsdbDao ovsdbDao;
|
||||
|
||||
@Autowired
|
||||
private OpensyncExternalIntegrationInterface extIntegrationInterface;
|
||||
|
||||
@Autowired
|
||||
private OvsdbSessionMapInterface ovsdbSessionMapInterface;
|
||||
|
||||
@PostConstruct
|
||||
private void postCreate() {
|
||||
listenForConnections();
|
||||
}
|
||||
|
||||
public void listenForConnections() {
|
||||
|
||||
ConnectionCallback connectionCallback = new ConnectionCallback() {
|
||||
public void connected(OvsdbClient ovsdbClient) {
|
||||
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
|
||||
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
|
||||
String subjectDn = null;
|
||||
try {
|
||||
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate()).getSubjectDN().getName();
|
||||
|
||||
String clientCn = SslUtil.extractCN(subjectDn);
|
||||
LOG.info("ovsdbClient connecting from {} on port {} clientCn {}", remoteHost, localPort, clientCn);
|
||||
|
||||
ConnectNodeInfo connectNodeInfo = ovsdbDao.getConnectNodeInfo(ovsdbClient);
|
||||
|
||||
//successfully connected - register it in our connectedClients table
|
||||
//In Plume's environment clientCn is not unique that's why we are augmenting it with the serialNumber and using it as a key (equivalent of KDC unique qrCode)
|
||||
String key = clientCn + "_" + connectNodeInfo.serialNumber;
|
||||
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.newSession(key, ovsdbClient);
|
||||
extIntegrationInterface.apConnected(key, connectNodeInfo);
|
||||
|
||||
//push configuration to AP
|
||||
connectNodeInfo = processConnectRequest(ovsdbClient, clientCn, connectNodeInfo);
|
||||
|
||||
LOG.info("ovsdbClient connected from {} on port {} key {} ", remoteHost, localPort, key);
|
||||
|
||||
LOG.info("ovsdbClient connectedClients = {}", ConnectusOvsdbClient.this.ovsdbSessionMapInterface.getNumSessions());
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.error("ovsdbClient error", e);
|
||||
//something is wrong with the SSL
|
||||
ovsdbClient.shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
public void disconnected(OvsdbClient ovsdbClient) {
|
||||
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
|
||||
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
|
||||
String subjectDn = null;
|
||||
try {
|
||||
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate()).getSubjectDN().getName();
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
String clientCn = SslUtil.extractCN(subjectDn);
|
||||
|
||||
//disconnected - deregister ovsdbClient from our connectedClients table
|
||||
//unfortunately we only know clientCn at this point, but in Plume's environment they are not unique
|
||||
//so we are doing a reverse lookup here, and then if we find the key we will remove the entry from the connectedClients.
|
||||
String key = ConnectusOvsdbClient.this.ovsdbSessionMapInterface.lookupClientId(ovsdbClient);
|
||||
|
||||
if(key!=null) {
|
||||
extIntegrationInterface.apDisconnected(key);
|
||||
ConnectusOvsdbClient.this.ovsdbSessionMapInterface.removeSession(key);
|
||||
}
|
||||
|
||||
ovsdbClient.shutdown();
|
||||
|
||||
LOG.info("ovsdbClient disconnected from {} on port {} clientCn {} key {} ", remoteHost, localPort, clientCn, key);
|
||||
LOG.info("ovsdbClient connectedClients = {}", ConnectusOvsdbClient.this.ovsdbSessionMapInterface.getNumSessions());
|
||||
}
|
||||
};
|
||||
|
||||
listener.startListeningWithSsl(ovsdbListenPort, sslContext, connectionCallback).join();
|
||||
|
||||
LOG.debug("manager waiting for connection on port {}...", ovsdbListenPort);
|
||||
}
|
||||
|
||||
private ConnectNodeInfo processConnectRequest(OvsdbClient ovsdbClient, String clientCn, ConnectNodeInfo connectNodeInfo) {
|
||||
|
||||
LOG.debug("Starting Client connect");
|
||||
connectNodeInfo = ovsdbDao.updateConnectNodeInfoOnConnect(ovsdbClient, clientCn, connectNodeInfo);
|
||||
|
||||
String apId = clientCn + "_" + connectNodeInfo.serialNumber;
|
||||
OpensyncAPConfig opensyncAPConfig = extIntegrationInterface.getApConfig(apId);
|
||||
|
||||
ovsdbDao.configureStats(ovsdbClient);
|
||||
|
||||
//Check if device stats is configured in Wifi_Stats_Config table, provision it if needed
|
||||
if(ovsdbDao.getDeviceStatsReportingInterval(ovsdbClient) != collectionIntervalSecDeviceStats) {
|
||||
ovsdbDao.updateDeviceStatsReportingInterval(ovsdbClient, collectionIntervalSecDeviceStats);
|
||||
}
|
||||
|
||||
ovsdbDao.provisionBridgePortInterface(ovsdbClient);
|
||||
|
||||
ovsdbDao.removeAllSsids(ovsdbClient);
|
||||
|
||||
if(opensyncAPConfig!=null) {
|
||||
ovsdbDao.configureWifiRadios(ovsdbClient, opensyncAPConfig.getRadioConfig());
|
||||
ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig.getSsidConfigs());
|
||||
}
|
||||
|
||||
ovsdbDao.configureWifiInet(ovsdbClient);
|
||||
|
||||
LOG.debug("Client connect Done");
|
||||
return connectNodeInfo;
|
||||
}
|
||||
|
||||
public Set<String> getConnectedClientIds(){
|
||||
return ovsdbSessionMapInterface.getConnectedClientIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param apId
|
||||
* @param newRedirectorAddress
|
||||
* @return updated value of the redirector
|
||||
*/
|
||||
public String changeRedirectorAddress(String apId, String newRedirectorAddress) {
|
||||
OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId);
|
||||
if(ovsdbSession == null) {
|
||||
throw new IllegalStateException("AP with id " + apId + " is not connected") ;
|
||||
}
|
||||
|
||||
String ret = ovsdbDao.changeRedirectorAddress(ovsdbSession.getOvsdbClient(), apId, newRedirectorAddress);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processConfigChanged(String apId) {
|
||||
LOG.debug("Starting processConfigChanged for {}", apId);
|
||||
|
||||
OvsdbSession ovsdbSession = ovsdbSessionMapInterface.getSession(apId);
|
||||
if(ovsdbSession == null) {
|
||||
throw new IllegalStateException("AP with id " + apId + " is not connected") ;
|
||||
}
|
||||
|
||||
OvsdbClient ovsdbClient = ovsdbSession.getOvsdbClient();
|
||||
OpensyncAPConfig opensyncAPConfig = extIntegrationInterface.getApConfig(apId);
|
||||
|
||||
if(opensyncAPConfig!=null) {
|
||||
ovsdbDao.removeAllSsids(ovsdbClient);
|
||||
ovsdbDao.configureWifiRadios(ovsdbClient, opensyncAPConfig.getRadioConfig());
|
||||
ovsdbDao.configureSsids(ovsdbClient, opensyncAPConfig.getSsidConfigs());
|
||||
}
|
||||
|
||||
LOG.debug("Finished processConfigChanged for {}", apId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package ai.connectus.opensync.ovsdb;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.vmware.ovsdb.callback.ConnectionCallback;
|
||||
import com.vmware.ovsdb.service.OvsdbClient;
|
||||
import com.vmware.ovsdb.service.OvsdbPassiveConnectionListener;
|
||||
|
||||
import ai.connectus.opensync.ovsdb.dao.OvsdbDao;
|
||||
import ai.connectus.opensync.util.SslUtil;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
|
||||
@Profile("ovsdb_redirector")
|
||||
@Component
|
||||
public class ConnectusOvsdbRedirector {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConnectusOvsdbRedirector.class);
|
||||
|
||||
@org.springframework.beans.factory.annotation.Value("${connectus.ovsdb.redirector.listenPort:6643}")
|
||||
private int ovsdbRedirectorListenPort;
|
||||
|
||||
@Autowired
|
||||
private SslContext sslContext;
|
||||
|
||||
@Autowired
|
||||
private OvsdbDao ovsdbDao;
|
||||
|
||||
@Autowired
|
||||
private OvsdbPassiveConnectionListener listener;
|
||||
|
||||
@PostConstruct
|
||||
private void postCreate() {
|
||||
listenForConnections();
|
||||
}
|
||||
|
||||
public void listenForConnections() {
|
||||
|
||||
ConnectionCallback connectionCallback = new ConnectionCallback() {
|
||||
public void connected(OvsdbClient ovsdbClient) {
|
||||
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
|
||||
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
|
||||
String subjectDn = null;
|
||||
try {
|
||||
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate()).getSubjectDN().getName();
|
||||
|
||||
String clientCn = SslUtil.extractCN(subjectDn);
|
||||
LOG.info("ovsdbClient redirector connected from {} on port {} clientCn {}", remoteHost, localPort, clientCn);
|
||||
ovsdbDao.performRedirect(ovsdbClient, clientCn);
|
||||
|
||||
} catch (Exception e) {
|
||||
//something is wrong with the SSL or with the redirect
|
||||
ovsdbClient.shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected(OvsdbClient ovsdbClient) {
|
||||
String remoteHost = ovsdbClient.getConnectionInfo().getRemoteAddress().getHostAddress();
|
||||
int localPort = ovsdbClient.getConnectionInfo().getLocalPort();
|
||||
String subjectDn = null;
|
||||
try {
|
||||
subjectDn = ((X509Certificate) ovsdbClient.getConnectionInfo().getRemoteCertificate()).getSubjectDN().getName();
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
String clientCn = SslUtil.extractCN(subjectDn);
|
||||
LOG.info("ovsdbClient redirector disconnected from {} on port {} clientCn {}", remoteHost, localPort, clientCn);
|
||||
ovsdbClient.shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
listener.startListeningWithSsl(ovsdbRedirectorListenPort, sslContext, connectionCallback).join();
|
||||
|
||||
LOG.debug("redirector waiting for connection on port {} ...", ovsdbRedirectorListenPort);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package ai.connectus.opensync.ovsdb;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableEntryException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import io.netty.handler.ssl.ClientAuth;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
|
||||
@Configuration
|
||||
public class NettySslContextConfig {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NettySslContextConfig.class);
|
||||
|
||||
@Bean(name="NettySslContextServer")
|
||||
public SslContext nettySslContextServer(
|
||||
@Value("${connectus.ovsdb.trustStore:/Users/dtop/Documents/certs_from_device/truststore.jks}")
|
||||
String trustStoreFileName,
|
||||
|
||||
@Value("${connectus.ovsdb.keyStore:/Users/dtop/Documents/certs_from_device/server.p12}")
|
||||
String keyFileName,
|
||||
|
||||
@Value("${connectus.ovsdb.keyStorePassword:mypassword}")
|
||||
String keyStorePassword
|
||||
){
|
||||
File trustStoreFile = new File(trustStoreFileName);
|
||||
File keyFile = new File(keyFileName);
|
||||
|
||||
SslContext sslContext = null;
|
||||
|
||||
try {
|
||||
char[] pwd = keyStorePassword.toCharArray();
|
||||
|
||||
KeyStore ks = KeyStore.getInstance("PKCS12");
|
||||
//KeyStore ks = KeyStore.getInstance("JKS");
|
||||
try(InputStream is = new FileInputStream(keyFile)){
|
||||
ks.load(is, pwd);
|
||||
}
|
||||
|
||||
for(String alias: Collections.list(ks.aliases())) {
|
||||
LOG.debug("Key Alias: {}", alias);
|
||||
}
|
||||
|
||||
KeyStore trustKs = KeyStore.getInstance("JKS");
|
||||
try(InputStream is = new FileInputStream(trustStoreFile)){
|
||||
trustKs.load(is, pwd);
|
||||
}
|
||||
|
||||
for(String alias: Collections.list(trustKs.aliases())) {
|
||||
LOG.debug("Trust Alias: {}", alias);
|
||||
}
|
||||
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
keyManagerFactory.init(ks, pwd);
|
||||
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
|
||||
trustManagerFactory.init(trustKs);
|
||||
|
||||
SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(keyManagerFactory);
|
||||
sslContextBuilder.trustManager(trustManagerFactory);
|
||||
sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
|
||||
//sslContextBuilder.protocols("TLSv1.2");
|
||||
sslContextBuilder.startTls(true);
|
||||
|
||||
sslContext = sslContextBuilder.build();
|
||||
|
||||
LOG.debug("Built ssl context");
|
||||
} catch (KeyStoreException|CertificateException|NoSuchAlgorithmException|IOException|UnrecoverableEntryException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return sslContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package ai.connectus.opensync.ovsdb;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.vmware.ovsdb.service.OvsdbPassiveConnectionListener;
|
||||
import com.vmware.ovsdb.service.impl.OvsdbPassiveConnectionListenerImpl;
|
||||
|
||||
@Configuration
|
||||
public class OvsdbListenerConfig {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OvsdbListenerConfig.class);
|
||||
|
||||
@Bean
|
||||
public OvsdbPassiveConnectionListener ovsdbPassiveConnectionListener(
|
||||
@org.springframework.beans.factory.annotation.Value("${connectus.ovsdb.listener.threadPoolSize:10}")
|
||||
int threadPoolSize) {
|
||||
LOG.debug("Configuring OvsdbPassiveConnectionListener with thread pool size {}", threadPoolSize);
|
||||
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(threadPoolSize);
|
||||
OvsdbPassiveConnectionListener listener = new OvsdbPassiveConnectionListenerImpl(executorService);
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package ai.connectus.opensync.ovsdb;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.vmware.ovsdb.service.OvsdbClient;
|
||||
|
||||
import ai.connectus.opensync.external.integration.OvsdbSession;
|
||||
import ai.connectus.opensync.external.integration.OvsdbSessionMapInterface;
|
||||
|
||||
@Component
|
||||
public class OvsdbSessionMap implements OvsdbSessionMapInterface {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OvsdbSessionMap.class);
|
||||
|
||||
private final ConcurrentHashMap<String, OvsdbSession> connectedClients = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public OvsdbSession getSession(String apId) {
|
||||
return connectedClients.get(apId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OvsdbSession removeSession(String apId) {
|
||||
return connectedClients.remove(apId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeSession(String apId) {
|
||||
try {
|
||||
connectedClients.get(apId).getOvsdbClient().shutdown();
|
||||
connectedClients.remove(apId);
|
||||
LOG.info("Closed ovsdb session for {}", apId);
|
||||
}catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OvsdbSession newSession(String apId, OvsdbClient ovsdbClient) {
|
||||
OvsdbSession ret = new OvsdbSession();
|
||||
ret.setApId(apId);
|
||||
ret.setOvsdbClient(ovsdbClient);
|
||||
OvsdbSession oldSession = connectedClients.put(apId, ret);
|
||||
|
||||
if(oldSession!=null) {
|
||||
try {
|
||||
oldSession.getOvsdbClient().shutdown();
|
||||
LOG.info("Closed old ovsdb session for {}", apId);
|
||||
}catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
LOG.info("Created new ovsdb session for {}", apId);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumSessions() {
|
||||
return connectedClients.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConnectedClientIds() {
|
||||
return new HashSet<String>(connectedClients.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String lookupClientId(OvsdbClient ovsdbClient) {
|
||||
String key = connectedClients.searchEntries(1,
|
||||
(Entry<String, OvsdbSession> t) -> { return t.getValue().getOvsdbClient().equals(ovsdbClient) ? t.getKey() : null ;}
|
||||
);
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
package ai.connectus.opensync.ovsdb.dao.models;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.vmware.ovsdb.protocol.operation.notation.Uuid;
|
||||
|
||||
public class BridgeInfo implements Cloneable{
|
||||
|
||||
public Set<Uuid> portUuids;
|
||||
|
||||
public String name;
|
||||
public Uuid uuid;
|
||||
|
||||
@Override
|
||||
public BridgeInfo clone() {
|
||||
try {
|
||||
BridgeInfo ret = (BridgeInfo)super.clone();
|
||||
if(portUuids!=null) {
|
||||
ret.portUuids = new HashSet<>(this.portUuids);
|
||||
}
|
||||
return ret;
|
||||
}catch(CloneNotSupportedException e) {
|
||||
throw new IllegalStateException("Cannot clone ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("BridgeInfo [portUuids=%s, name=%s, uuid=%s]", portUuids, name, uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package ai.connectus.opensync.ovsdb.dao.models;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.util.Map;
|
||||
import com.vmware.ovsdb.protocol.operation.notation.Uuid;
|
||||
|
||||
public class InterfaceInfo implements Cloneable{
|
||||
|
||||
public String adminState;
|
||||
public String linkState;
|
||||
public int ifIndex;
|
||||
public int mtu;
|
||||
public int ofport;
|
||||
|
||||
public String name;
|
||||
public String type;
|
||||
public Uuid uuid;
|
||||
|
||||
public Map<String,String> options;
|
||||
|
||||
@Override
|
||||
public InterfaceInfo clone() {
|
||||
try {
|
||||
InterfaceInfo ret = (InterfaceInfo)super.clone();
|
||||
if(options!=null) {
|
||||
ret.options = new HashMap<>(this.options);
|
||||
}
|
||||
return ret;
|
||||
}catch(CloneNotSupportedException e) {
|
||||
throw new IllegalStateException("Cannot clone ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"InterfaceInfo [adminState=%s, linkState=%s, ifIndex=%s, mtu=%s, ofport=%s, name=%s, uuid=%s]",
|
||||
adminState, linkState, ifIndex, mtu, ofport, name, uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package ai.connectus.opensync.ovsdb.dao.models;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.vmware.ovsdb.protocol.operation.notation.Uuid;
|
||||
|
||||
public class PortInfo implements Cloneable{
|
||||
|
||||
public Set<Uuid> interfaceUuids;
|
||||
|
||||
public String name;
|
||||
public Uuid uuid;
|
||||
|
||||
@Override
|
||||
public PortInfo clone() {
|
||||
try {
|
||||
PortInfo ret = (PortInfo)super.clone();
|
||||
if(interfaceUuids!=null) {
|
||||
ret.interfaceUuids = new HashSet<>(this.interfaceUuids);
|
||||
}
|
||||
return ret;
|
||||
}catch(CloneNotSupportedException e) {
|
||||
throw new IllegalStateException("Cannot clone ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PortInfo [interfaceUuids=%s, name=%s, uuid=%s]", interfaceUuids, name, uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package ai.connectus.opensync.ovsdb.dao.models;
|
||||
|
||||
import com.vmware.ovsdb.protocol.operation.notation.Uuid;
|
||||
|
||||
public class WifiInetConfigInfo implements Cloneable{
|
||||
|
||||
public boolean nat;
|
||||
public boolean enabled;
|
||||
public String ifName;
|
||||
public String ifType;
|
||||
public String ipAssignScheme;
|
||||
public boolean network;
|
||||
|
||||
public Uuid uuid;
|
||||
|
||||
@Override
|
||||
public WifiInetConfigInfo clone() {
|
||||
try {
|
||||
WifiInetConfigInfo ret = (WifiInetConfigInfo)super.clone();
|
||||
return ret;
|
||||
}catch(CloneNotSupportedException e) {
|
||||
throw new IllegalStateException("Cannot clone ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"WifiInetConfigInfo [nat=%s, enabled=%s, ifName=%s, ifType=%s, ipAssignScheme=%s, network=%s, uuid=%s]",
|
||||
nat, enabled, ifName, ifType, ipAssignScheme, network, uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package ai.connectus.opensync.ovsdb.dao.models;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.vmware.ovsdb.protocol.operation.notation.Uuid;
|
||||
|
||||
public class WifiRadioConfigInfo implements Cloneable{
|
||||
|
||||
public Set<Uuid> vifConfigUuids;
|
||||
|
||||
public String freqBand;
|
||||
public int channel;
|
||||
public Integer txPower;
|
||||
public String channelMode;
|
||||
public boolean enabled;
|
||||
public String htMode;
|
||||
public Map<String,String> hwConfig;
|
||||
public String country;
|
||||
|
||||
public String ifName;
|
||||
public Uuid uuid;
|
||||
|
||||
@Override
|
||||
public WifiRadioConfigInfo clone() {
|
||||
try {
|
||||
WifiRadioConfigInfo ret = (WifiRadioConfigInfo)super.clone();
|
||||
if(vifConfigUuids!=null) {
|
||||
ret.vifConfigUuids = new HashSet<>(this.vifConfigUuids);
|
||||
}
|
||||
|
||||
if(hwConfig!=null) {
|
||||
ret.hwConfig = new HashMap<>(this.hwConfig);
|
||||
}
|
||||
return ret;
|
||||
}catch(CloneNotSupportedException e) {
|
||||
throw new IllegalStateException("Cannot clone ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"WifiRadioConfigInfo [vifConfigUuids=%s, freqBand=%s, channel=%s, txPower=%s, channelMode=%s, enabled=%s, htMode=%s, hwConfig=%s, country=%s, ifName=%s, uuid=%s]",
|
||||
vifConfigUuids, freqBand, channel, txPower, channelMode, enabled, htMode, hwConfig, country, ifName,
|
||||
uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package ai.connectus.opensync.ovsdb.dao.models;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.vmware.ovsdb.protocol.operation.notation.Uuid;
|
||||
|
||||
/**
|
||||
* radio_type + stats_type + survey_type identifies a record
|
||||
*
|
||||
*/
|
||||
public class WifiStatsConfigInfo implements Cloneable{
|
||||
|
||||
public Set<Integer> channelList;
|
||||
public String radioType;
|
||||
public int reportingInterval;
|
||||
public int samplingInterval;
|
||||
public String statsType;
|
||||
public int surveyIntervalMs;
|
||||
public String surveyType;
|
||||
public Map<String, Integer> threshold;
|
||||
|
||||
public Uuid uuid;
|
||||
|
||||
@Override
|
||||
public WifiStatsConfigInfo clone() {
|
||||
try {
|
||||
WifiStatsConfigInfo ret = (WifiStatsConfigInfo)super.clone();
|
||||
if(channelList!=null) {
|
||||
ret.channelList = new HashSet<>(this.channelList);
|
||||
}
|
||||
if(threshold!=null) {
|
||||
ret.threshold = new HashMap<>(this.threshold);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}catch(CloneNotSupportedException e) {
|
||||
throw new IllegalStateException("Cannot clone ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"WifiStatsConfigInfo [channelList=%s, radioType=%s, reportingInterval=%s, samplingInterval=%s, statsType=%s, surveyIntervalMs=%s, surveyType=%s, threshold=%s, uuid=%s]",
|
||||
channelList, radioType, reportingInterval, samplingInterval, statsType, surveyIntervalMs,
|
||||
surveyType, threshold, uuid);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package ai.connectus.opensync.ovsdb.dao.models;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.vmware.ovsdb.protocol.operation.notation.Uuid;
|
||||
|
||||
public class WifiVifConfigInfo implements Cloneable{
|
||||
|
||||
public String bridge;
|
||||
public int btm;
|
||||
public boolean enabled;
|
||||
public int ftPsk;
|
||||
public int groupRekey;
|
||||
public String ifName;
|
||||
public String mode;
|
||||
public int rrm;
|
||||
public String ssid;
|
||||
public String ssidBroadcast;
|
||||
public boolean uapsdEnable;
|
||||
public int vifRadioIdx;
|
||||
public Map<String,String> security;
|
||||
|
||||
public Uuid uuid;
|
||||
|
||||
@Override
|
||||
public WifiVifConfigInfo clone() {
|
||||
try {
|
||||
WifiVifConfigInfo ret = (WifiVifConfigInfo)super.clone();
|
||||
|
||||
if(security!=null) {
|
||||
ret.security = new HashMap<>(this.security);
|
||||
}
|
||||
return ret;
|
||||
}catch(CloneNotSupportedException e) {
|
||||
throw new IllegalStateException("Cannot clone ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"WifiVifConfigInfo [bridge=%s, btm=%s, enabled=%s, ftPsk=%s, groupRekey=%s, ifName=%s, mode=%s, rrm=%s, ssid=%s, ssidBroadcast=%s, uapsdEnable=%s, vifRadioIdx=%s, security=%s, uuid=%s]",
|
||||
bridge, btm, enabled, ftPsk, groupRekey, ifName, mode, rrm, ssid, ssidBroadcast, uapsdEnable,
|
||||
vifRadioIdx, security, uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package ai.connectus.opensync.util;
|
||||
|
||||
public class SslUtil {
|
||||
|
||||
/**
|
||||
* Examples:<br>
|
||||
* <code>
|
||||
* subject=CN = PP302X-EX, C = US, O = Plume Design Inc., L = Palo Alto, ST = CA, emailAddress = support@plumewifi.com<br>
|
||||
* subject=C = CA, ST = Ontario, L = Ottawa, O = WhizControl Canada Inc, OU = Research and Develpoment, CN = dev-ap-0001, emailAddress = devadmin@123wlan.com
|
||||
* </code>
|
||||
* @param subjectDn
|
||||
* @return Value of the CN attribute of the supplied subject DN, or empty string if it cannot be extracted
|
||||
*/
|
||||
public static String extractCN(String subjectDn) {
|
||||
if(subjectDn==null || subjectDn.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
String[] attrs = subjectDn.split(",");
|
||||
String tmp;
|
||||
int idx;
|
||||
for(String attr : attrs) {
|
||||
tmp = attr.trim();
|
||||
if(tmp.startsWith("CN")) {
|
||||
idx = tmp.indexOf('=');
|
||||
if(idx>0) {
|
||||
return tmp.substring(idx + 1).trim();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package ai.connectus.opensync.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
public class ZlibUtil {
|
||||
|
||||
public static final int MAX_BUFFER_SIZE = 8192;
|
||||
|
||||
public static byte[] compress(byte[] bytesToCompress) {
|
||||
if(bytesToCompress == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(bytesToCompress.length==0) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
Deflater deflater = new Deflater();
|
||||
deflater.setInput(bytesToCompress);
|
||||
deflater.finish();
|
||||
|
||||
byte[] bytesCompressed = new byte[bytesToCompress.length];
|
||||
|
||||
int numberOfBytesAfterCompression = deflater.deflate(bytesCompressed);
|
||||
|
||||
if(numberOfBytesAfterCompression == 0) {
|
||||
throw new IllegalStateException("Compressed size is greater than original?");
|
||||
}
|
||||
|
||||
byte[] returnValues = new byte[numberOfBytesAfterCompression];
|
||||
|
||||
System.arraycopy(bytesCompressed, 0, returnValues, 0, numberOfBytesAfterCompression);
|
||||
|
||||
return returnValues;
|
||||
}
|
||||
|
||||
private static class SizeAndBuffer{
|
||||
int size;
|
||||
byte[] buffer;
|
||||
|
||||
public SizeAndBuffer(int size, byte[] buffer) {
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] decompress(byte[] bytesToDecompress)
|
||||
{
|
||||
if(bytesToDecompress == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(bytesToDecompress.length == 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
byte[] returnValues = null;
|
||||
|
||||
Inflater inflater = new Inflater();
|
||||
int numberOfBytesToDecompress = bytesToDecompress.length;
|
||||
inflater.setInput(bytesToDecompress, 0, numberOfBytesToDecompress);
|
||||
|
||||
int bufferSizeInBytes = numberOfBytesToDecompress;
|
||||
|
||||
int numberOfBytesDecompressedSoFar = 0;
|
||||
List<SizeAndBuffer> bytesDecompressedSoFar = new ArrayList<>();
|
||||
|
||||
try
|
||||
{
|
||||
while (!inflater.needsInput())
|
||||
{
|
||||
byte[] bytesDecompressedBuffer = new byte[bufferSizeInBytes];
|
||||
|
||||
int numberOfBytesDecompressedThisTime = inflater.inflate(bytesDecompressedBuffer);
|
||||
numberOfBytesDecompressedSoFar += numberOfBytesDecompressedThisTime;
|
||||
|
||||
bytesDecompressedSoFar.add(new SizeAndBuffer(numberOfBytesDecompressedThisTime, bytesDecompressedBuffer));
|
||||
}
|
||||
|
||||
|
||||
//now stitch together all the buffers we've collected
|
||||
returnValues = new byte[numberOfBytesDecompressedSoFar];
|
||||
int destPos = 0;
|
||||
int length = 0;
|
||||
|
||||
for(SizeAndBuffer partBuffer : bytesDecompressedSoFar) {
|
||||
length = partBuffer.size;
|
||||
System.arraycopy(partBuffer.buffer, 0, returnValues, destPos, length);
|
||||
destPos += length;
|
||||
}
|
||||
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new IllegalStateException(dfe);
|
||||
}
|
||||
|
||||
inflater.end();
|
||||
|
||||
return returnValues;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user