Add ad hoc WiFi communication function
Change-Id: I6ec986708bfa2dcdf1cc2ed121f249fabd99ac86
diff --git a/src/osx-adhoc.mm b/src/osx-adhoc.mm
new file mode 100644
index 0000000..fcaf146
--- /dev/null
+++ b/src/osx-adhoc.mm
@@ -0,0 +1,142 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017, Regents of the University of California,
+ *
+ * This file is part of NFD Control Center. See AUTHORS.md for complete list of NFD
+ * authors and contributors.
+ *
+ * NFD Control Center is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD Control Center is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with NFD
+ * Control Center, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "osx-adhoc.hpp"
+
+#include <ndn-cxx/name.hpp>
+#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
+
+#ifdef OSX_BUILD
+
+#import <CoreWLAN/CoreWLAN.h>
+#import <CoreWLAN/CoreWLANConstants.h>
+#import <CoreWLAN/CWInterface.h>
+#import <CoreWLAN/CWWiFiClient.h>
+#import <CoreWLAN/CoreWLANTypes.h>
+
+namespace ndn {
+namespace ncc {
+
+const std::string adhocUri = "udp4://224.0.23.170:56363";
+const std::set<Name> adhocPrefixes = {"/", "/adhoc"};
+const NSUInteger g_channel = 11;
+const uint16_t ROUTE_ORIGIN_NCC = 67;
+
+Adhoc::Adhoc(Face& face, KeyChain& keychain)
+ : m_face(face)
+ , m_keyChain(keychain)
+ , m_controller(new nfd::Controller(m_face, m_keyChain))
+ , m_faceMonitor(new nfd::FaceMonitor(m_face))
+{
+ m_faceMonitor->onNotification.connect(bind(&Adhoc::onNotification, this, _1));
+}
+
+Adhoc::~Adhoc()
+{
+ delete m_faceMonitor;
+ delete m_controller;
+}
+
+bool
+Adhoc::createAdhoc()
+{
+ m_faceMonitor->start();
+
+ NSString* networkName =
+ [[NSString alloc] initWithCString:"NDNdirect" encoding:NSASCIIStringEncoding];
+ NSString* passphrase =
+ [[NSString alloc] initWithCString:"NDNhello" encoding:NSASCIIStringEncoding];
+ NSArray* airportInterfaces = [CWWiFiClient interfaceNames];
+ NSString* interfaceName = [airportInterfaces objectAtIndex:0];
+ CWWiFiClient* wifiInterfaces = [[CWWiFiClient alloc] init];
+ CWInterface* airport = [wifiInterfaces interfaceWithName:interfaceName];
+
+ NSError* error = nil;
+ NSData* data = [networkName dataUsingEncoding:NSUTF8StringEncoding];
+ BOOL created = [airport startIBSSModeWithSSID:data
+ security:kCWIBSSModeSecurityNone
+ channel:g_channel
+ password:passphrase
+ error:&error];
+
+ if (!created) {
+ return false;
+ }
+ else {
+ unregisterRoutes(ndn::nfd::ROUTE_ORIGIN_AUTOCONF);
+ return true;
+ }
+}
+
+void
+Adhoc::destroyAdhoc()
+{
+ unregisterRoutes(ROUTE_ORIGIN_NCC);
+ m_faceMonitor->stop();
+
+ NSArray* airportInterfaces = [CWWiFiClient interfaceNames];
+ NSString* interfaceName = [airportInterfaces objectAtIndex:0];
+ CWWiFiClient* wifiInterfaces = [[CWWiFiClient alloc] init];
+ CWInterface* airport = [wifiInterfaces interfaceWithName:interfaceName];
+ [airport disassociate];
+
+ NSError* err = nil;
+
+ [airport setPower:NO error:&err];
+ [NSThread sleepForTimeInterval: 3.0];
+ [airport setPower:YES error:&err];
+}
+
+void
+Adhoc::onNotification(const ndn::nfd::FaceEventNotification& notification)
+{
+ if (notification.getKind() == ndn::nfd::FACE_EVENT_CREATED &&
+ notification.getRemoteUri() == adhocUri &&
+ notification.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) {
+ for (const auto& prefix : adhocPrefixes) {
+ ndn::nfd::ControlParameters params;
+ params
+ .setName(prefix)
+ .setFaceId(notification.getFaceId())
+ .setOrigin(ROUTE_ORIGIN_NCC);
+ m_controller->start<ndn::nfd::RibRegisterCommand>(params, nullptr, nullptr);
+ }
+ }
+}
+
+void
+Adhoc::unregisterRoutes(uint16_t origin)
+{
+ m_controller->fetch<ndn::nfd::RibDataset>([this, origin] (const std::vector<nfd::RibEntry>& ribs) {
+ for (const auto& rib : ribs) {
+ for (const auto& route : rib.getRoutes()) {
+ if (route.getOrigin() == origin) {
+ ndn::nfd::ControlParameters params;
+ params.setFaceId(route.getFaceId());
+ m_controller->start<ndn::nfd::FaceDestroyCommand>(params, nullptr, nullptr);
+ }
+ }
+ }
+ }, nullptr);
+}
+
+} // namespace ncc
+} // namespace ndn
+
+#endif // OSX_BUILD