Renamed projects to follow a naming convention. Moved KDC-specific projects into a separate repository

This commit is contained in:
DTop
2020-02-27 13:33:14 -05:00
parent 81c6cd1fe6
commit a4815223ec
49 changed files with 106 additions and 1903 deletions

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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 "";
}
}

View File

@@ -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;
}
}