--- /dev/null
+/target/
+*.class
\ No newline at end of file
--- /dev/null
+This project contains series of modules for building cloud services.
+
+Modules
+
+1. stack - Java 1.7 based CoAP over TCP implementation.
+2. interface - cloud interface server that accept incoming IoTivity clients connection.
+3. resource_directory - resource directory server that store clients resource models.
+4. account - account server that handle clients credential using OAuth2.
+5. samples - sample IoTivity clients that show how clients working with cloud.
+
+Each cloud modules has README file how to install and run.
+You can run each modules on single computer or PAAS.
+
+Note. resource_directory should launched before interface and account.
+
+Architecture
+client--------interface_server--------resource_directory_server--------mongo_db
+ \---------------account_server-------------------mongo_db
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>CloudAccount</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+This project contains the Account Server code.
+
+
+Build and Run
+
+1) Install Apache Maven if you don't have it
+
+ http://maven.apache.org
+
+2) Build a CloudStack. If you are building first time, then build the stack.
+
+ go to "stack" folder in root directory
+ $ mvn install
+
+3) Build a .jar file
+
+ $ mvn install
+
+ - The CloudAccount-0.0.1-SNAPSHOT.jar file will be placed in the "target" folder
+
+4) Run .jar file
+
+ go to "target" folder
+ $ java -jar CloudAccount-0.0.1-SNAPSHOT.jar arg1(AccountServer CoAP Server Port)
+ e.g. java -jar CloudAccount-0.0.1-SNAPSHOT.jar 5685
+
+ - Before you run a Accout server, You need to set up following steps.
+ 1) Install MongoDB
+ 2) Install Github certificates for github.com and *.github.com.
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.iotivity.cloud</groupId>
+ <artifactId>CloudAccount</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.iotivity.cloud</groupId>
+ <artifactId>CloudStack</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mongodb</groupId>
+ <artifactId>mongo-java-driver</artifactId>
+ <version>3.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oltu.oauth2</groupId>
+ <artifactId>org.apache.oltu.oauth2.client</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.iotivity.cloud.accountserver.AccountServer</mainClass>
+ <addClasspath>true</addClasspath>
+ <classpathPrefix>lib/</classpathPrefix>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <outputDirectory>target/lib</outputDirectory>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver;
+
+import java.net.InetSocketAddress;
+
+import org.iotivity.cloud.accountserver.resources.AccountResource;
+import org.iotivity.cloud.accountserver.resources.AuthResource;
+import org.iotivity.cloud.base.CoapServer;
+import org.iotivity.cloud.base.ResourceManager;
+import org.iotivity.cloud.util.Logger;
+import org.iotivity.cloud.util.Net;
+
+/**
+ *
+ * This class is in charge of running account server.
+ *
+ */
+public class AccountServer {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("-----Account SERVER-----");
+ String hostAddress = Net.getMyIpAddress();
+ if (hostAddress.equals("") == true) {
+ Logger.e("cannot find host address.");
+ return;
+ }
+
+ if (args.length != 1) {
+ Logger.e("coap server port required");
+ return;
+ }
+
+ ResourceManager resourceManager = null;
+
+ CoapServer coapServer = null;
+
+ coapServer = new CoapServer();
+
+ resourceManager = new ResourceManager();
+ coapServer.addHandler(resourceManager);
+
+ resourceManager.registerResource(new AuthResource());
+ resourceManager.registerResource(new AccountResource());
+
+ coapServer
+ .startServer(new InetSocketAddress(Integer.parseInt(args[0])));
+ }
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.accountserver.oauth.GitHub;
+import org.iotivity.cloud.util.Logger;
+
+/**
+ *
+ * This class provides a set of API to handle requests for registering account
+ * information of authorized user, and publishing and finding resources.
+ *
+ */
+public class AccountServerManager {
+
+ public Boolean registerUserAccount(String userId, String deviceId) {
+
+ Boolean ret = false;
+
+ // store info to OAuthDBManager
+ ret = AccountDBManager.getInstance().registerUserDevice(userId,
+ deviceId);
+
+ return ret;
+ }
+
+ public String registerUserAccount(String userId) {
+
+ String sessionCode = null;
+ sessionCode = generateSessionCode();
+
+ // store info to OAuthDBManager
+ AccountDBManager.getInstance().registerUserSessionCode(userId,
+ sessionCode);
+
+ return sessionCode;
+ }
+
+ /**
+ * API for requesting user identifier to interested authorization server
+ *
+ * @param accessToeken
+ * access token
+ * @param authServer
+ * authorization server
+ * @return String - user identifier
+ */
+ public String requestUserId(String authCode, String authServer) {
+
+ String userId = null;
+
+ String accessToken = getAccessToken(authCode, authServer);
+ userId = getUserId(accessToken, authServer);
+
+ return userId;
+ }
+
+ public String requestUserId(String sessionCode) {
+
+ String userId = null;
+
+ // get userId from MongDB
+ userId = AccountDBManager.getInstance().getUserId(sessionCode);
+
+ return userId;
+ }
+
+ /**
+ * API for getting devices according to authorized user from database
+ *
+ * @param userId
+ * identifier of authorized user
+ * @return ArrayList<String> - list of devices
+ */
+ public ArrayList<String> requestAccountDevices(String userId) {
+
+ Logger.d("userId= " + userId);
+
+ ArrayList<String> deviceList = AccountDBManager.getInstance()
+ .getDevices(userId);
+
+ return deviceList;
+ }
+
+ /**
+ * API for requesting access token to interested authorization server
+ *
+ * @param authServer
+ * server name for authorization
+ * @param authCode
+ * authorization code
+ * @return ArrayList<String> - array list of name of authorization servers
+ */
+ private String getAccessToken(String authCode, String authServer) {
+
+ String accessToken = null;
+
+ if (authServer.equals(Const.GITHUB)) {
+
+ GitHub gitHub = new GitHub();
+ accessToken = gitHub.requestAccessToken(authCode);
+
+ } else {
+
+ Logger.e("unsupported auth.server = " + authServer);
+ }
+
+ return accessToken;
+ }
+
+ private String getUserId(String accessToken, String authServer) {
+
+ String userId = null;
+
+ if (authServer.equals(Const.GITHUB)) {
+
+ GitHub gitHub = new GitHub();
+ userId = gitHub.requestGetUserInfo(accessToken);
+
+ } else {
+
+ Logger.e("unsupported auth.server = " + authServer);
+ }
+
+ return userId;
+ }
+
+ private String generateSessionCode() {
+
+ String sessionCode = "";
+
+ Random random = new Random();
+ int randomNum = random.nextInt(122);
+ char code;
+
+ // generate 16byte key with 0-9, A-Z, a-z
+ for (int k = 0; k < 16; k++) {
+ while (true) {
+ if ((randomNum >= 48 && randomNum <= 57)
+ || (randomNum >= 65 && randomNum <= 90)
+ || (randomNum >= 97 && randomNum <= 122)) {
+
+ code = (char) randomNum;
+ sessionCode += code;
+
+ randomNum = random.nextInt(122);
+ break;
+
+ } else {
+
+ randomNum = random.nextInt(122);
+ }
+ }
+ }
+
+ return sessionCode;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver;
+
+public class Const {
+
+ // MongoDB
+ public static final String DEVICE_TABLE = "USER_DEVICE";
+ public static final String SESSION_TABLE = "USER_SESSION";
+ public static final String DB_NAME = "ACCOUNTSERVER_DB";
+ public static final String USER_ID = "userId";
+ public static final String DEVICE_ID = "deviceId";
+ public static final String SESSION_CODE = "sessionCode";
+
+ // Resource Uri
+ public static final String AUTH_URI = "oic/auth";
+ public static final String ACCOUNT_URI = "oic/account";
+
+ // query parameter
+ public static final String REQ_TYPE = "reqtype";
+
+ // request type
+ public static final String TYPE_REGISTER = "register";
+ public static final String TYPE_LOGIN = "login";
+ public static final String TYPE_PUBLISH = "publish";
+ public static final String TYPE_FIND = "find";
+
+ // request payload
+ public static final String REQUEST_AUTH_CODE = "authcode";
+ public static final String REQUEST_AUTH_SERVER = "authprovider";
+ public static final String REQUEST_DEVICE_ID = "deviceid";
+ public static final String REQUEST_USER_ID = "userid";
+ public static final String REQUEST_SESSION_CODE = "session";
+
+ // response
+ public static final String RESPONSE_SESSION_CODE = "session";
+ public static final String RESPONSE_USER_ID = "userid";
+ public static final String RESPONSE_STATE = "state";
+ public static final String RESPONSE_DEVICES = "devices";
+
+ // auth servers
+ public static final String GITHUB = "github";
+ public static final String GOOGLE = "google";
+ public static final String FACEBOOK = "facebook";
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.db;
+
+import java.util.ArrayList;
+
+import org.iotivity.cloud.accountserver.Const;
+
+/**
+ *
+ * This class provides a set of APIs managing database.
+ *
+ */
+public class AccountDBManager {
+
+ private static AccountDBManager accoutDBManager = new AccountDBManager();
+ private MongoDB mongoDB;
+
+ private AccountDBManager() {
+
+ try {
+
+ mongoDB = new MongoDB(Const.DB_NAME);
+
+ mongoDB.createTable(Const.DEVICE_TABLE);
+ mongoDB.createTable(Const.SESSION_TABLE);
+
+ registerAdminAccount();
+
+ } catch (Exception e) {
+
+ e.printStackTrace();
+
+ }
+ }
+
+ public static AccountDBManager getInstance() {
+
+ return accoutDBManager;
+ }
+
+ private void registerAdminAccount() {
+
+ String adminId = "admin";
+ String adminSessionCode = "00000000";
+
+ UserSession userSession = new UserSession();
+
+ userSession.setUserId(adminId);
+ userSession.setSessionCode(adminSessionCode);
+
+ mongoDB.createResource(userSession);
+ mongoDB.printResources();
+ }
+
+ /**
+ * API for storing session information of authorized user to mongoDB
+ *
+ * @param userId
+ * identifier of authorized user
+ * @param sessionCode
+ * session code
+ * @return Boolean - true if stored, false if not
+ */
+ public Boolean registerUserSessionCode(String userId, String sessionCode) {
+
+ UserSession userSession = new UserSession();
+
+ userSession.setUserId(userId);
+ userSession.setSessionCode(sessionCode);
+
+ mongoDB.createResource(userSession);
+ mongoDB.printResources();
+
+ return true;
+ }
+
+ public Boolean registerUserDevice(String userId, String deviceId) {
+
+ UserDevice userDevice = new UserDevice();
+
+ userDevice.setUserId(userId);
+ userDevice.setDeviceId(deviceId);
+
+ mongoDB.createResource(userDevice);
+ mongoDB.printResources();
+
+ return true;
+ }
+
+ public String getUserId(String sessionCode) {
+
+ String userId = null;
+
+ userId = mongoDB.getUserId(sessionCode);
+
+ return userId;
+ }
+
+ /**
+ * API for getting devices according to authorized user
+ *
+ * @param userId
+ * identifier of authorized user
+ * @return ArrayList<String> - list of devices
+ */
+ public ArrayList<String> getDevices(String userId) {
+
+ ArrayList<String> deviceList = new ArrayList<String>();
+
+ deviceList = mongoDB.getDevices(userId);
+
+ return deviceList;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.db;
+
+import java.util.ArrayList;
+
+import org.bson.Document;
+import org.iotivity.cloud.accountserver.Const;
+import org.iotivity.cloud.util.Logger;
+
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoCursor;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.Filters;
+
+/**
+ *
+ * This class provides a set of APIs to use MongoDB APIs.
+ *
+ */
+public class MongoDB {
+
+ private MongoClient mongoClient = null;
+ private MongoDatabase db = null;
+
+ /**
+ * API creating MongoClient and initializing MongoDatabase
+ *
+ * @param dbname
+ * database name to create MongoDatabase
+ * @throws Exception
+ */
+ public MongoDB(String dbname) throws Exception {
+ mongoClient = new MongoClient();
+ mongoClient.dropDatabase(dbname);
+ db = mongoClient.getDatabase(dbname);
+ }
+
+ /**
+ * API creating collection
+ *
+ * @param tableName
+ * collection name
+ */
+ public void createTable(String tableName) {
+ db.createCollection(tableName);
+ }
+
+ /**
+ * API deleting collection
+ *
+ * @param tableName
+ * collection name
+ */
+ public void deleteTable(String tableName) {
+ db.getCollection(tableName).drop();
+ }
+
+ public MongoDatabase getMongoDatabase() {
+ return db;
+ }
+
+ /**
+ * API for storing information of authorized users
+ *
+ * @param accountInfo
+ * information of authorized users
+ * @param tablename
+ * table name of mongoDB
+ */
+ public void createResource(UserSession userSession) {
+
+ Document doc = createDocument(userSession);
+ MongoCollection<Document> collection = db
+ .getCollection(Const.SESSION_TABLE);
+
+ if (collection.findOneAndReplace(Filters.and(
+ Filters.eq(Const.USER_ID, doc.get(Const.USER_ID)),
+ Filters.eq(Const.SESSION_CODE, doc.get(Const.SESSION_CODE))),
+ doc) == null) {
+
+ collection.insertOne(doc);
+ }
+
+ return;
+ }
+
+ public void createResource(UserDevice userDevice) {
+
+ Document doc = createDocument(userDevice);
+ MongoCollection<Document> collection = db
+ .getCollection(Const.DEVICE_TABLE);
+
+ if (collection.findOneAndReplace(
+ Filters.and(Filters.eq(Const.USER_ID, doc.get(Const.USER_ID)),
+ Filters.eq(Const.DEVICE_ID, doc.get(Const.DEVICE_ID))),
+ doc) == null) {
+
+ collection.insertOne(doc);
+ }
+
+ return;
+ }
+
+ private Document createDocument(UserSession userSession) {
+
+ Document doc = new Document(Const.USER_ID, userSession.getUserId())
+ .append(Const.SESSION_CODE, userSession.getSessionCode());
+
+ return doc;
+ }
+
+ private Document createDocument(UserDevice userDevice) {
+
+ Document doc = new Document(Const.USER_ID, userDevice.getUserId())
+ .append(Const.DEVICE_ID, userDevice.getDeviceId());
+
+ return doc;
+ }
+
+ private UserSession convertSessionDocToResource(Document doc) {
+
+ UserSession userSession = new UserSession();
+
+ userSession.setUserId(doc.getString(Const.USER_ID));
+ userSession.setSessionCode(doc.getString(Const.SESSION_CODE));
+
+ return userSession;
+ }
+
+ private UserDevice convertDeviceDocToResource(Document doc) {
+
+ UserDevice userDevice = new UserDevice();
+
+ userDevice.setUserId(doc.getString(Const.USER_ID));
+ userDevice.setDeviceId(doc.getString(Const.DEVICE_ID));
+
+ return userDevice;
+ }
+
+ public String getUserId(String sessionCode) {
+
+ String userId = null;
+
+ MongoCollection<Document> collection = db
+ .getCollection(Const.SESSION_TABLE);
+
+ MongoCursor<Document> cursor = collection
+ .find(Filters.eq(Const.SESSION_CODE, sessionCode)).iterator();
+
+ try {
+
+ while (cursor.hasNext()) {
+
+ Document doc = cursor.next();
+ UserSession userSession = convertSessionDocToResource(doc);
+
+ userId = userSession.getUserId();
+ break;
+ }
+
+ } finally {
+
+ cursor.close();
+ }
+
+ return userId;
+ }
+
+ /**
+ * API for getting devices according to user from mongoDB
+ *
+ * @param userId
+ * user identifier
+ * @param tablename
+ * table name of mongoDB
+ */
+ public ArrayList<String> getDevices(String userId) {
+
+ ArrayList<String> deviceList = new ArrayList<String>();
+
+ MongoCollection<Document> collection = db
+ .getCollection(Const.DEVICE_TABLE);
+
+ MongoCursor<Document> cursor = collection
+ .find(Filters.eq(Const.USER_ID, userId)).iterator();
+
+ try {
+
+ while (cursor.hasNext()) {
+
+ Document doc = cursor.next();
+ UserDevice userDeivce = convertDeviceDocToResource(doc);
+
+ deviceList.add(userDeivce.getDeviceId());
+ }
+
+ } finally {
+
+ cursor.close();
+ }
+
+ return deviceList;
+ }
+
+ private ArrayList<UserSession> readSessionResources() {
+
+ ArrayList<UserSession> userSessionList = new ArrayList<UserSession>();
+
+ MongoCollection<Document> collection = db
+ .getCollection(Const.SESSION_TABLE);
+ MongoCursor<Document> cursor = collection.find().iterator();
+
+ while (cursor.hasNext()) {
+
+ Document doc = cursor.next();
+ userSessionList.add(convertSessionDocToResource(doc));
+ }
+
+ cursor.close();
+
+ return userSessionList;
+ }
+
+ private ArrayList<UserDevice> readDeviceResources() {
+
+ ArrayList<UserDevice> userDeviceList = new ArrayList<UserDevice>();
+
+ MongoCollection<Document> collection = db
+ .getCollection(Const.DEVICE_TABLE);
+ MongoCursor<Document> cursor = collection.find().iterator();
+
+ while (cursor.hasNext()) {
+
+ Document doc = cursor.next();
+ userDeviceList.add(convertDeviceDocToResource(doc));
+ }
+
+ cursor.close();
+
+ return userDeviceList;
+ }
+
+ public void printResources() {
+
+ ArrayList<UserDevice> dlist = readDeviceResources();
+ int size = dlist.size();
+
+ Logger.i("*Table: " + Const.DEVICE_TABLE);
+ for (int i = 0; i < size; i++) {
+
+ UserDevice item = dlist.get(i);
+
+ Logger.i("[" + i + "]" + item.getUserId() + ", "
+ + item.getDeviceId());
+ }
+
+ ArrayList<UserSession> slist = readSessionResources();
+ size = slist.size();
+
+ Logger.i("*Table: " + Const.SESSION_TABLE);
+
+ for (int i = 0; i < size; i++) {
+
+ UserSession item = slist.get(i);
+
+ Logger.i("[" + i + "]" + item.getUserId() + ", "
+ + item.getSessionCode());
+
+ }
+ }
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.db;
+
+/**
+ *
+ * This class provides a set of APIs storing device information of authorized
+ * user.
+ *
+ */
+public class UserDevice {
+
+ private String userId = null;
+ private String deviceId = null;
+
+ public void setUserId(String id) {
+ this.userId = id;
+ }
+
+ public void setDeviceId(String id) {
+ this.deviceId = id;
+ }
+
+ public String getUserId() {
+ return this.userId;
+ }
+
+ public String getDeviceId() {
+ return this.deviceId;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.db;
+
+/**
+ *
+ * This class provides a set of APIs storing session information of authorized
+ * user.
+ *
+ */
+public class UserSession {
+
+ private String userId = null;
+ private String sessionCode = null;
+
+ public void setUserId(String id) {
+ this.userId = id;
+ }
+
+ public void setSessionCode(String code) {
+ this.sessionCode = code;
+ }
+
+ public String getUserId() {
+ return this.userId;
+ }
+
+ public String getSessionCode() {
+ return this.sessionCode;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.oauth;
+
+import org.apache.oltu.oauth2.client.OAuthClient;
+import org.apache.oltu.oauth2.client.URLConnectionClient;
+import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
+import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
+import org.apache.oltu.oauth2.client.response.GitHubTokenResponse;
+import org.apache.oltu.oauth2.client.response.OAuthResourceResponse;
+import org.apache.oltu.oauth2.common.OAuth;
+import org.apache.oltu.oauth2.common.OAuthProviderType;
+import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
+import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.apache.oltu.oauth2.common.message.types.GrantType;
+import org.iotivity.cloud.accountserver.util.JSONUtil;
+import org.iotivity.cloud.util.Logger;
+
+/**
+ *
+ * This class provides APIs relating authorization for GitHub.
+ *
+ */
+public class GitHub extends OAuthServer {
+
+ final static private String client_id = "ea9c18f540323b0213d0";
+ final static private String secret = "4bc0cd9fe21269507eb8eba3a32664a0f598dbc9";
+ final static private String resource_url = "https://api.github.com/user";
+
+ @Override
+ public String requestAccessToken(String authCode) {
+
+ String accessToken = null;
+
+ try {
+
+ OAuthClientRequest request = OAuthClientRequest
+ .tokenProvider(OAuthProviderType.GITHUB)
+ .setGrantType(GrantType.AUTHORIZATION_CODE)
+ .setClientId(client_id).setClientSecret(secret)
+ .setCode(authCode).buildBodyMessage();
+
+ OAuthClient oAuthClient = new OAuthClient(
+ new URLConnectionClient());
+ GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(request,
+ GitHubTokenResponse.class);
+
+ accessToken = oAuthResponse.getAccessToken();
+
+ } catch (OAuthSystemException | OAuthProblemException e) {
+ e.printStackTrace();
+ }
+
+ return accessToken;
+ }
+
+ @Override
+ public String requestGetUserInfo(String accessToken) {
+
+ String userInfo = "{}";
+
+ try {
+
+ OAuthClientRequest request = new OAuthBearerClientRequest(
+ resource_url).setAccessToken(accessToken)
+ .buildQueryMessage();
+
+ OAuthClient oAuthClient = new OAuthClient(
+ new URLConnectionClient());
+ OAuthResourceResponse resourceResponse = oAuthClient.resource(
+ request, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
+
+ userInfo = resourceResponse.getBody();
+ Logger.d("userInfo: " + userInfo);
+
+ } catch (OAuthSystemException | OAuthProblemException e) {
+ e.printStackTrace();
+ }
+
+ JSONUtil util = new JSONUtil();
+ String userIdKey = "login";
+ String userId = util.parseJSON(userInfo, userIdKey);
+
+ return userId;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.oauth;
+
+/**
+ *
+ * This class provides abstraction of APIs relating authorization for OAuth 2.0
+ *
+ */
+public abstract class OAuthServer {
+
+ /**
+ * API for requesting access token
+ *
+ * @param authCode
+ * authorization code
+ * @return access token
+ */
+ public abstract String requestAccessToken(String authCode);
+
+ /**
+ * API for getting user's information
+ *
+ * @param accessToken
+ * access token
+ * @return String - user information of json type
+ */
+ public abstract String requestGetUserInfo(String accessToken);
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.iotivity.cloud.accountserver.AccountServerManager;
+import org.iotivity.cloud.accountserver.Const;
+import org.iotivity.cloud.accountserver.util.CoapMessageBuilder;
+import org.iotivity.cloud.accountserver.util.JSONUtil;
+import org.iotivity.cloud.base.Resource;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+import org.iotivity.cloud.util.Logger;
+
+import io.netty.channel.ChannelHandlerContext;
+
+/**
+ *
+ * This class provides a set of APIs to handle requests for publishing and
+ * finding resources.
+ *
+ */
+public class AccountResource extends Resource {
+
+ public AccountResource() {
+ setUri(Const.ACCOUNT_URI);
+ }
+
+ @Override
+ public void onRequestReceived(ChannelHandlerContext ctx,
+ CoapRequest request) {
+
+ Logger.d("AccountResource IN");
+
+ if (ctx == null || request == null) {
+ Logger.d("ctx or request msg is null");
+ }
+
+ else {
+ CoapMethod method = request.getRequestMethod();
+
+ switch (method) {
+ case GET:
+ try {
+ handleGetRequest(ctx, request);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+
+ case POST:
+ try {
+ handlePostRequest(ctx, request);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+
+ default:
+ Logger.w("method[" + method + "] is not supported");
+ break;
+ }
+ }
+ }
+
+ /**
+ * API for handling GET message
+ *
+ * @param ctx
+ * ChannelHandlerContext of request message
+ * @param request
+ * CoAP request message
+ * @throws Exception
+ */
+ private void handleGetRequest(ChannelHandlerContext ctx,
+ CoapRequest request) throws Exception {
+
+ String reqType = extractQuery(request, Const.REQ_TYPE);
+
+ if (reqType == null)
+ throw new IllegalArgumentException(
+ "request type is null in query!");
+
+ CoapResponse response = null;
+
+ switch (reqType) {
+
+ case Const.TYPE_FIND:
+ response = handleFindRequest(request);
+ break;
+ default:
+ Logger.w("reqType[" + reqType + "] is not supported");
+ }
+
+ ctx.write(response);
+
+ }
+
+ /**
+ * API for handling POST message
+ *
+ * @param ctx
+ * ChannelHandlerContext of request message
+ * @param request
+ * CoAP request message
+ * @throws Exception
+ */
+ private void handlePostRequest(ChannelHandlerContext ctx,
+ CoapRequest request) throws Exception {
+
+ String reqType = extractQuery(request, Const.REQ_TYPE);
+
+ if (reqType == null)
+ throw new IllegalArgumentException(
+ "request type is null in query!");
+
+ CoapResponse response = null;
+
+ switch (reqType) {
+ case Const.TYPE_PUBLISH:
+ response = handlePublishRequest(request);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "request type is not supported");
+ }
+
+ ctx.write(response);
+ }
+
+ private CoapResponse handlePublishRequest(CoapRequest request) {
+
+ String payload = request.getPayloadString();
+
+ JSONUtil util = new JSONUtil();
+ String userId = util.parseJSON(payload, Const.REQUEST_USER_ID);
+ String deviceId = util.parseJSON(payload, Const.REQUEST_DEVICE_ID);
+
+ Logger.d("userId: " + userId + ", deviceId: " + deviceId);
+
+ AccountServerManager oauthServerManager = new AccountServerManager();
+ Boolean status = oauthServerManager.registerUserAccount(userId,
+ deviceId);
+
+ Logger.d("status : " + status);
+
+ CoapMessageBuilder responseMessage = new CoapMessageBuilder();
+ CoapResponse coapResponse = null;
+
+ if (status) {
+ coapResponse = responseMessage.buildCoapResponse(request.getToken(),
+ CoapStatus.CREATED);
+ } else {
+ coapResponse = responseMessage.buildCoapResponse(request.getToken(),
+ CoapStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ return coapResponse;
+ }
+
+ private CoapResponse handleFindRequest(CoapRequest request) {
+
+ String payload = request.getPayloadString();
+ // String payload = getPayloadString(request.getPayload());
+
+ JSONUtil util = new JSONUtil();
+ String userId = util.parseJSON(payload, Const.REQUEST_USER_ID);
+
+ Logger.d("userId: " + userId);
+
+ AccountServerManager oauthServerManager = new AccountServerManager();
+ ArrayList<String> deviceList = oauthServerManager
+ .requestAccountDevices(userId);
+
+ ResponseObject response = new ResponseObject();
+ response.setDeviceList(deviceList);
+
+ String responseJson = convertFindResponseToJson(response);
+ Logger.d("responseJson: " + responseJson);
+
+ CoapMessageBuilder responseMessage = new CoapMessageBuilder();
+ CoapResponse coapResponse = responseMessage.buildCoapResponse(
+ request.getToken(), responseJson, CoapStatus.CONTENT);
+
+ return coapResponse;
+ }
+
+ private String convertFindResponseToJson(ResponseObject response) {
+
+ HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
+
+ ArrayList<String> deviceList = response.getDeviceList();
+ responseMap.put(Const.RESPONSE_DEVICES, deviceList);
+
+ JSONUtil jsonUtil = new JSONUtil();
+ String responseJson = jsonUtil.writeJSON(responseMap);
+
+ return responseJson;
+ }
+
+ private String extractQuery(CoapRequest request, String key) {
+
+ String value = null;
+
+ List<String> Segments = request.getUriQuerySegments();
+
+ for (String s : Segments) {
+
+ String pair[] = s.split("=");
+
+ if (pair[0].equals(key)) {
+
+ value = pair[1];
+ }
+ }
+
+ return value;
+ }
+
+ /*
+ * private static String getPayloadString(byte[] payload) {
+ *
+ * if (payload == null) return "";
+ *
+ * return new String(payload, Charset.forName("UTF-8")); }
+ */
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.iotivity.cloud.accountserver.AccountServerManager;
+import org.iotivity.cloud.accountserver.Const;
+import org.iotivity.cloud.accountserver.util.CoapMessageBuilder;
+import org.iotivity.cloud.accountserver.util.JSONUtil;
+import org.iotivity.cloud.base.Resource;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+import org.iotivity.cloud.util.Logger;
+
+import io.netty.channel.ChannelHandlerContext;
+
+/**
+ *
+ * This class provides a set of APIs to register account information of
+ * authorized user.
+ *
+ */
+public class AuthResource extends Resource {
+
+ public AuthResource() {
+ setUri(Const.AUTH_URI);
+ }
+
+ @Override
+ public void onRequestReceived(ChannelHandlerContext ctx, CoapRequest request) {
+
+ Logger.d("AuthResource IN");
+
+ if (ctx == null || request == null) {
+ Logger.d("ctx or request msg is null");
+ }
+
+ else {
+ CoapMethod method = request.getRequestMethod();
+
+ switch (method) {
+ case POST:
+ try {
+ handlePostRequest(ctx, request);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+
+ default:
+ Logger.w("method(" + method + ") is not supported");
+ break;
+ }
+ }
+ }
+
+ /**
+ * API for handling POST message
+ *
+ * @param ctx
+ * ChannelHandlerContext of request message
+ * @param request
+ * CoAP request message
+ * @throws Exception
+ */
+ private void handlePostRequest(ChannelHandlerContext ctx,
+ CoapRequest request) throws Exception {
+
+ String reqType = extractQuery(request, Const.REQ_TYPE);
+
+ if (reqType == null)
+ throw new IllegalArgumentException("request type is null in query!");
+
+ CoapResponse response = null;
+
+ switch (reqType) {
+ case Const.TYPE_REGISTER:
+ response = handleRegisterRequest(request);
+ break;
+ case Const.TYPE_LOGIN:
+ response = handleLoginRequest(request);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "request type is not supported");
+ }
+
+ ctx.write(response);
+ }
+
+ private CoapResponse handleLoginRequest(CoapRequest request) {
+
+ String payload = request.getPayloadString();
+
+ JSONUtil util = new JSONUtil();
+ String sessionCode = util
+ .parseJSON(payload, Const.REQUEST_SESSION_CODE);
+
+ Logger.d("sessionCode: " + sessionCode);
+
+ AccountServerManager oauthServerManager = new AccountServerManager();
+ String userId = oauthServerManager.requestUserId(sessionCode);
+ Logger.d("userId: " + userId);
+
+ CoapMessageBuilder responseMessage = new CoapMessageBuilder();
+ CoapResponse coapResponse = null;
+
+ if (userId != null) {
+
+ ResponseObject response = new ResponseObject();
+ response.setUserId(userId);
+
+ String responseJson = convertLoginResponseToJson(response);
+ Logger.d("responseJson: " + responseJson);
+
+ coapResponse = responseMessage.buildCoapResponse(
+ request.getToken(), responseJson, CoapStatus.CREATED);
+
+ } else {
+
+ coapResponse = responseMessage.buildCoapResponse(
+ request.getToken(), CoapStatus.INTERNAL_SERVER_ERROR);
+
+ }
+
+ return coapResponse;
+ }
+
+ private CoapResponse handleRegisterRequest(CoapRequest request) {
+
+ String payload = request.getPayloadString();
+
+ JSONUtil util = new JSONUtil();
+ String authCode = util.parseJSON(payload, Const.REQUEST_AUTH_CODE);
+ String authServer = util.parseJSON(payload, Const.REQUEST_AUTH_SERVER);
+
+ Logger.d("authCode: " + authCode + ", authServer: " + authServer);
+
+ AccountServerManager oauthServerManager = new AccountServerManager();
+
+ String userId = oauthServerManager.requestUserId(authCode, authServer);
+ String sessionCode = oauthServerManager.registerUserAccount(userId);
+
+ Logger.d("userId: " + userId + ", sessionCode: " + sessionCode);
+
+ CoapMessageBuilder responseMessage = new CoapMessageBuilder();
+ CoapResponse coapResponse = null;
+
+ if (userId != null && sessionCode != null) {
+
+ ResponseObject response = new ResponseObject();
+ response.setSessionCode(sessionCode);
+ response.setUserId(userId);
+
+ String responseJson = convertRegisterResponseToJson(response);
+ Logger.d("responseJson: " + responseJson);
+
+ coapResponse = responseMessage.buildCoapResponse(
+ request.getToken(), responseJson, CoapStatus.CREATED);
+
+ } else {
+
+ coapResponse = responseMessage.buildCoapResponse(
+ request.getToken(), CoapStatus.UNAUTHORIZED);
+
+ }
+
+ return coapResponse;
+ }
+
+ private String convertRegisterResponseToJson(ResponseObject response) {
+
+ HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
+
+ String sessionCode = response.getSessionCode();
+ String userId = response.getUserId();
+
+ if (userId != null)
+ responseMap.put(Const.RESPONSE_USER_ID, userId);
+
+ if (sessionCode != null)
+ responseMap.put(Const.RESPONSE_SESSION_CODE, sessionCode);
+
+ JSONUtil jsonUtil = new JSONUtil();
+ String responseJson = jsonUtil.writeJSON(responseMap);
+
+ return responseJson;
+ }
+
+ private String convertLoginResponseToJson(ResponseObject response) {
+
+ HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
+
+ String userId = response.getUserId();
+
+ if (userId != null)
+ responseMap.put(Const.RESPONSE_USER_ID, userId);
+
+ JSONUtil jsonUtil = new JSONUtil();
+ String responseJson = jsonUtil.writeJSON(responseMap);
+
+ return responseJson;
+ }
+
+ private String extractQuery(CoapRequest request, String key) {
+
+ String value = null;
+
+ List<String> Segments = request.getUriQuerySegments();
+
+ for (String s : Segments) {
+
+ String pair[] = s.split("=");
+
+ if (pair[0].equals(key)) {
+
+ value = pair[1];
+ }
+ }
+
+ return value;
+ }
+
+ /*
+ * private static String getPayloadString(byte[] payload) {
+ *
+ * if (payload == null) return "";
+ *
+ * return new String(payload, Charset.forName("UTF-8")); }
+ */
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.resources;
+
+import java.util.ArrayList;
+
+/**
+ *
+ * This class provides a set of APIs to manage data for response according to
+ * request.
+ *
+ */
+public class ResponseObject {
+ // private String channel = null;
+ private String sessionCode = null;
+ private String userId = null;
+ private ArrayList<String> deviceList = null;
+
+ ResponseObject() {
+ deviceList = new ArrayList<String>();
+ }
+
+ public String getUserId() {
+ return this.userId;
+ }
+
+ public void setUserId(String id) {
+ this.userId = id;
+ }
+
+ public String getSessionCode() {
+ return this.sessionCode;
+ }
+
+ public void setSessionCode(String code) {
+ this.sessionCode = code;
+ }
+
+ public void setDeviceList(ArrayList<String> list) {
+ this.deviceList = list;
+ }
+
+ public ArrayList<String> getDeviceList() {
+ return this.deviceList;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.util;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapOption;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+
+/**
+ *
+ * This class provides utility for making CoAP request and response.
+ *
+ */
+public class CoapMessageBuilder {
+
+ public static final int APPLICATION_JSON = 50;
+
+ public CoapResponse buildCoapResponse(byte[] token, CoapStatus status) {
+
+ return buildCoapResponse(token, null, status);
+ }
+
+ public CoapResponse buildCoapResponse(byte[] token, String jsonString,
+ CoapStatus status) {
+
+ CoapResponse coapResponse = new CoapResponse(status);
+
+ coapResponse.setToken(token);
+
+ byte[] bytes = ByteBuffer.allocate(4)
+ .putInt(CoapMessageBuilder.APPLICATION_JSON).array();
+ coapResponse.addOption(CoapOption.CONTENT_FORMAT.getvalue(), bytes);
+
+ if (jsonString != null)
+ coapResponse
+ .setPayload(jsonString.getBytes(StandardCharsets.UTF_8));
+
+ return coapResponse;
+ }
+
+ public CoapRequest buildCoapRequest(byte[] token, String jsonString) {
+
+ CoapRequest coapRequest = new CoapRequest(CoapMethod.GET);
+
+ coapRequest.setToken(token);
+
+ byte[] bytes = ByteBuffer.allocate(4)
+ .putInt(CoapMessageBuilder.APPLICATION_JSON).array();
+ coapRequest.addOption(CoapOption.CONTENT_FORMAT.getvalue(), bytes);
+
+ coapRequest.setPayload(jsonString.getBytes(StandardCharsets.UTF_8));
+
+ return coapRequest;
+ }
+
+ /*
+ *
+ * public String getJsonAuthServerResponse() {
+ *
+ * return "{ \"" + OAuthConstant.AUTH_SERVER + "\" : \"" +
+ * OAuthConstant.AUTH_SERVER_GITHUB + "\" }"; }
+ *
+ * public String getJsonAuthInfoResponse() {
+ *
+ * return "\n{\n" + " \"" + OAuthConstant.AUTH_ADDRESS + "\" : \"" +
+ * OAuthConstant.GITHUB_ADDRESS + "\",\n" + " \"" +
+ * OAuthConstant.AUTH_RESPONSE_TYPE + "\" : \"" +
+ * OAuthConstant.AUTH_CODE_VALUE + "\",\n" + " \"" +
+ * OAuthConstant.AUTH_CLIENT_ID + "\" : \"" + OAuthConstant.GITHUB_CLIENT_ID
+ * + "\",\n" + " \"" + OAuthConstant.AUTH_REDIRECT_URI + "\" : \"" +
+ * OAuthConstant.GITHUB_REDIRECT_URL + "\"" + "\n}"; }
+ *
+ * public String getJsonAuthQueryRequest(String auth_server, String
+ * auth_code, String auth_di) {
+ *
+ * return "\n{\n" + " \"" + OAuthConstant.AUTH_TYPE + "\" : \"" +
+ * OAuthConstant.AUTH_TYPE_QUERY + "\",\n" + " \"" +
+ * OAuthConstant.AUTH_SERVER + "\" : \"" + auth_server + "\",\n" + " \"" +
+ * OAuthConstant.AUTH_CODE + "\" : \"" + auth_code + "\",\n" + " \"" +
+ * OAuthConstant.AUTH_DEVICE_ID + "\" : \"" + auth_di + "\"" + "\n}"; }
+ */
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.accountserver.util;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ *
+ * This class provides utility for parsing JSON object and converting data to
+ * JSON string.
+ *
+ */
+public class JSONUtil {
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ public String parseJSON(String jsonString, String key) {
+
+ if (jsonString == null || jsonString.equals(""))
+ return null;
+
+ String value = null;
+
+ try {
+ @SuppressWarnings("unchecked")
+ Map<String, String> jsonMap = mapper.readValue(jsonString,
+ Map.class);
+ value = jsonMap.get(key);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+
+ return value;
+ }
+
+ public String writeJSON(HashMap<Object, Object> data) {
+ if (data == null)
+ return null;
+
+ String json = null;
+ try {
+ json = mapper.writeValueAsString(data);
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+
+ if (json == null)
+ json = "{}";
+
+ return json;
+ }
+}
--- /dev/null
+package org.iotivity.cloud.testaccountserver;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Test;
+import org.iotivity.cloud.accountserver.Const;
+import org.iotivity.cloud.accountserver.resources.AccountResource;
+import org.iotivity.cloud.accountserver.resources.AuthResource;
+import org.iotivity.cloud.accountserver.util.JSONUtil;
+import org.iotivity.cloud.base.CoapClient;
+import org.iotivity.cloud.base.CoapServer;
+import org.iotivity.cloud.base.ResourceManager;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+
+public class TestAccountServer {
+
+ private AuthResource authResource = new AuthResource();
+ private AccountResource accountResource = new AccountResource();
+
+ private CoapServer coapServer = null;
+ private CoapClient coapClient = null;
+ private static String sessionCode = null;
+
+ static class CoapClientHandler extends
+ SimpleChannelInboundHandler<CoapResponse> {
+
+ ChannelHandlerContext connectCtx = null;
+
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ connectCtx = ctx;
+ }
+
+ @Override
+ protected void channelRead0(ChannelHandlerContext arg0,
+ CoapResponse arg1) throws Exception {
+
+ if (arg1.getTokenString().equals("1111")) {
+
+ String json = arg1.getPayloadString();
+ JSONUtil util = new JSONUtil();
+
+ sessionCode = util.parseJSON(json, "session");
+ }
+
+ }
+ }
+
+ public void startServer() throws Exception {
+
+ coapServer = new CoapServer();
+
+ ResourceManager resourceManager = new ResourceManager();
+ coapServer.addHandler(resourceManager);
+
+ resourceManager.registerResource(new AuthResource());
+ resourceManager.registerResource(new AccountResource());
+
+ coapServer.startServer(new InetSocketAddress(5685));
+ }
+
+ public ChannelHandlerContext startClient() throws Exception {
+
+ coapClient = new CoapClient();
+
+ CoapClientHandler coapHandler = new CoapClientHandler();
+ coapClient.addHandler(coapHandler);
+
+ coapClient.startClient(new InetSocketAddress("127.0.0.1", 5685));
+
+ return coapHandler.connectCtx;
+ }
+
+ @Test
+ public void testHandleRegisterRequest() throws Exception {
+
+ System.out.println("Write your authCode before test by following url.");
+ System.out
+ .println("https://github.com/login?return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3Dea9c18f540323b0213d0%26redirect_uri%3Dhttp%253A%252F%252Fwww.example.com%252Foauth_callback%252F");
+
+ String authCode = "a05c2d8f6531ec15230e"; // write your authCode here.
+ String authServer = "github";
+
+ String json = "{\"authcode\":\"" + authCode + "\",\"authprovider\":\""
+ + authServer + "\"}";
+
+ CoapRequest request = new CoapRequest(CoapMethod.POST);
+ request.setUriPath(Const.AUTH_URI);
+ request.setUriQuery("reqtype=register");
+ request.setToken("1111".getBytes(StandardCharsets.UTF_8));
+ request.setPayload(json.getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+ authResource.onRequestReceived(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandlerLoginReqeust() throws Exception {
+
+ String json = "{\"session\":\"" + sessionCode + "\"}";
+
+ CoapRequest request = new CoapRequest(CoapMethod.POST);
+ request.setUriPath(Const.AUTH_URI);
+ request.setUriQuery("reqtype=login");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+ request.setPayload(json.getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+ authResource.onRequestReceived(ctx, request);
+
+ coapClient.sendRequest(request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandlerPublishReqeust() throws Exception {
+
+ String userId = "eyedglen";
+ String deviceId = "d0001";
+ String json = "{\"userid\":\"" + userId + "\",\"deviceId\":\""
+ + deviceId + "\"}";
+
+ CoapRequest request = new CoapRequest(CoapMethod.POST);
+ request.setUriPath(Const.ACCOUNT_URI);
+ request.setUriQuery("reqtype=publish");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+ request.setPayload(json.getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+ accountResource.onRequestReceived(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandlerFindReqeust() throws Exception {
+
+ String userId = "eyedglen";
+ String json = "{\"userid\":\"" + userId + "\"}";
+
+ CoapRequest request = new CoapRequest(CoapMethod.POST);
+ request.setUriPath(Const.ACCOUNT_URI);
+ request.setUriQuery("reqtype=find");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+ request.setPayload(json.getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+ accountResource.onRequestReceived(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>CloudInterface</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+This project contains the Cloud Interface(CI) Server code.
+
+Build and Run
+
+1) Install Apache Maven if you don't have it
+
+ http://maven.apache.org
+
+2) Build a CloudStack. If you are building first time, then build the stack.
+
+ go to "stack" folder in root directory
+ $ mvn install
+
+3) Build a .jar file
+
+ $ mvn install
+
+ - The CloudInterface-0.0.1-SNAPSHOT.jar file will be placed in the "target" folder
+
+4) Run .jar file
+
+ go to "target" folder
+ $ java -jar CloudInterface-0.0.1-SNAPSHOT.jar arg1(CI CoAP Server Port) arg2(RD CoAP Server IP) arg3(RD CoAP Server Port) arg4(Account Server IP) arg5(Account Server Port)
+ e.g. java -jar CloudInterface-0.0.1-SNAPSHOT.jar 5683 127.0.0.1 5684 127.0.0.1 5685
+
+ - Before running a CI server, you should run a RD server and a Acccount server first.
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.iotivity.cloud</groupId>
+ <artifactId>CloudInterface</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.iotivity.cloud</groupId>
+ <artifactId>CloudStack</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.iotivity.cloud.ciserver.CloudInterfaceServer</mainClass>
+ <addClasspath>true</addClasspath>
+ <classpathPrefix>lib/</classpathPrefix>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <outputDirectory>target/lib</outputDirectory>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.ciserver;
+
+import java.net.InetSocketAddress;
+
+import org.iotivity.cloud.base.CoapServer;
+import org.iotivity.cloud.base.ResourceManager;
+import org.iotivity.cloud.base.SessionManager;
+import org.iotivity.cloud.ciserver.protocols.CoapAuthHandler;
+import org.iotivity.cloud.ciserver.protocols.CoapRelayHandler;
+import org.iotivity.cloud.ciserver.resources.KeepAliveResource;
+import org.iotivity.cloud.util.CoapLogHandler;
+import org.iotivity.cloud.util.Logger;
+import org.iotivity.cloud.util.Net;
+
+public class CloudInterfaceServer {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("-----CI SERVER-------");
+ String hostAddress = Net.getMyIpAddress();
+ if (hostAddress.equals("") == true) {
+ Logger.e("cannot find host address.");
+ return;
+ }
+
+ if (args.length != 5) {
+ Logger.e(
+ "coap server port and RDServer_Address port AccountServer_Address Port required\n"
+ + "ex) 5683 127.0.0.1 5684 127.0.0.1 5685\n");
+ return;
+ }
+
+ ResourceManager resourceManager = null;
+ SessionManager sessionManager = null;
+ CoapServer coapServer = null;
+
+ coapServer = new CoapServer();
+
+ sessionManager = new SessionManager();
+
+ resourceManager = new ResourceManager(sessionManager);
+
+ coapServer.addHandler(
+ new CoapAuthHandler(args[3], Integer.parseInt(args[4])));
+
+ coapServer.addHandler(new CoapLogHandler());
+
+ // Comment the following one line to make CI server run alone
+ coapServer.addHandler(new CoapRelayHandler(sessionManager, args[1],
+ Integer.parseInt(args[2]), args[3], Integer.parseInt(args[4])));
+
+ coapServer.addHandler(resourceManager);
+
+ resourceManager.registerResource(new KeepAliveResource(sessionManager,
+ new int[] { 1, 2, 4, 8 }));
+
+ coapServer
+ .startServer(new InetSocketAddress(Integer.parseInt(args[0])));
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.ciserver;
+
+import io.netty.util.AttributeKey;
+
+public class Constants {
+ public static final String RD_URI = "oic/rd"; // resource
+ // publish uri
+ public static final String KEEP_ALIVE_URI = "oic/ping"; // keepalive
+ // resource uri
+ public static final String WELL_KNOWN_URI = "oic/res"; // resource
+ // discover uri
+
+ public static final String DEVICE_LIST = "st=didList"; // oauth device
+ // list riquery
+
+ public static final String AUTH_URI = "oic/auth";
+ public static final String ACCOUNT_URI = "oic/account";
+
+ public static final AttributeKey<String> Attribute_UserId = AttributeKey
+ .newInstance("userId");
+}
--- /dev/null
+package org.iotivity.cloud.ciserver.protocols;
+
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.iotivity.cloud.base.CoapClient;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+import org.iotivity.cloud.ciserver.Constants;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.JSONUtil;
+import org.iotivity.cloud.util.Logger;
+
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.util.AttributeKey;
+
+@Sharable
+public class CoapAuthHandler extends ChannelDuplexHandler {
+
+ private static final AttributeKey<ChannelHandlerContext> keyAuthClient = AttributeKey
+ .newInstance("authCtx");
+
+ private class AccountHandler
+ extends SimpleChannelInboundHandler<CoapResponse> {
+
+ @Override
+ public void channelRead0(ChannelHandlerContext ctx, CoapResponse msg)
+ throws Exception {
+ Logger.d("Receive response from account, forward to client");
+
+ ChannelHandlerContext ctxToDevice = ctx.channel()
+ .attr(keyAuthClient).get();
+
+ if (msg.getResponseCode() == CoapStatus.CREATED) {
+ Map<String, String> response = JSONUtil
+ .parseJSON(new String(msg.getPayload(), StandardCharsets.UTF_8));
+
+ String userId = response.get("userid");
+ if (userId != null) {
+ ctxToDevice.channel().attr(Constants.Attribute_UserId)
+ .set(userId);
+ }
+ msg.setPayload(cbor.encodingPayloadToCbor(response));
+
+ CoapAuthHandler authHandler = ctxToDevice.channel().pipeline()
+ .get(CoapAuthHandler.class);
+
+ ctxToDevice.channel().pipeline().remove(authHandler);
+ }
+
+ ctxToDevice.writeAndFlush(msg);
+
+ if (msg.getResponseCode() != CoapStatus.CREATED)
+ ctxToDevice.close();
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx,
+ Throwable cause) {
+ cause.printStackTrace();
+ ctx.close();
+ }
+ }
+
+ private CoapClient accountClient = new CoapClient();
+
+ public CoapAuthHandler(String accountAddress, int accountPort) {
+
+ accountClient.addHandler(new AccountHandler());
+ try {
+ accountClient.startClient(
+ new InetSocketAddress(accountAddress, accountPort));
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private Cbor<HashMap<Object, Object>> cbor = new Cbor<HashMap<Object, Object>>();
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg)
+ throws Exception {
+
+ if (msg instanceof CoapRequest) {
+ CoapRequest request = (CoapRequest) msg;
+ switch (request.getUriPath()) {
+ // This handler only used for initial handshake
+ case Constants.AUTH_URI:
+ HashMap<Object, Object> payloadData = cbor
+ .parsePayloadFromCbor(request.getPayload(),
+ HashMap.class);
+ request.setPayload(
+ JSONUtil.writeJSON(payloadData).getBytes(StandardCharsets.UTF_8));
+ accountClient.getChannelFuture().channel()
+ .attr(keyAuthClient).set(ctx);
+ accountClient.sendRequest(request);
+ return;
+
+ case Constants.KEEP_ALIVE_URI:
+ super.channelRead(ctx, msg);
+ return;
+
+ default:
+ CoapResponse response = new CoapResponse(
+ CoapStatus.UNAUTHORIZED);
+ Logger.e("Sending UNAUTHORIZED to client");
+ ctx.writeAndFlush(response);
+ break;
+ }
+ }
+
+ Logger.d("Invalid packet for authenticating");
+ ctx.close();
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.ciserver.protocols;
+
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.iotivity.cloud.base.CoapClient;
+import org.iotivity.cloud.base.SessionManager;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+import org.iotivity.cloud.ciserver.Constants;
+import org.iotivity.cloud.util.Logger;
+import org.iotivity.cloud.util.Net;
+
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.util.AttributeKey;
+
+/**
+ *
+ * This class is relay handler relating Cloud Interface
+ *
+ */
+@Sharable
+public class CoapRelayHandler extends ChannelDuplexHandler {
+
+ /////////// Handler for Resource Directory
+ private static final AttributeKey<ChannelHandlerContext> keyRDClient = AttributeKey
+ .newInstance("rdCtx");
+
+ private static class RDHandler
+ extends SimpleChannelInboundHandler<CoapResponse> {
+ @Override
+ public void channelRead0(ChannelHandlerContext ctx, CoapResponse msg)
+ throws Exception {
+ Logger.d("Receive response from RD, forward to client");
+
+ ChannelHandlerContext ctxToDevice = ctx.channel().attr(keyRDClient)
+ .get();
+ ctxToDevice.writeAndFlush(msg);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx,
+ Throwable cause) {
+ cause.printStackTrace();
+ ctx.close();
+ }
+ }
+
+ private CoapClient rdClient = new CoapClient();
+ ///////////
+
+ ////////// Handler for Account Server
+ private static final AttributeKey<List<CoapRequest>> keyAccountClient = AttributeKey
+ .newInstance("accountCtx");
+
+ private class AccountHandler
+ extends SimpleChannelInboundHandler<CoapResponse> {
+ @Override
+ public void channelRead0(ChannelHandlerContext ctx, CoapResponse msg)
+ throws Exception {
+ Logger.d("Receive response from AS, make request to RD");
+
+ CoapRequest rdRequest = null;
+
+ switch (msg.getResponseCode()) {
+ case CREATED:
+ // response of POST request
+ rdRequest = ctx.channel().attr(keyAccountClient).get()
+ .remove(0);
+ rdClient.sendRequest(rdRequest);
+ break;
+
+ case CONTENT:
+ // response of GET request, contains did list
+ rdRequest = ctx.channel().attr(keyAccountClient).get()
+ .remove(0);
+ // change uri to send RD
+ rdRequest.setUriPath(Constants.RD_URI);
+ rdRequest.setUriQuery(Constants.DEVICE_LIST);
+ rdRequest.setPayload(msg.getPayload());
+ rdClient.sendRequest(rdRequest);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx,
+ Throwable cause) {
+ cause.printStackTrace();
+ ctx.close();
+ }
+ }
+
+ private CoapClient asClient = new CoapClient();
+ //////////
+
+ private SessionManager sessionManager = null;
+
+ public CoapRelayHandler(SessionManager sessionManager, String rdAddress,
+ int rdPort, String acAddress, int acPort) {
+ this.sessionManager = sessionManager;
+
+ rdClient.addHandler(new RDHandler());
+
+ asClient.addHandler(new AccountHandler());
+
+ try {
+ rdClient.startClient(new InetSocketAddress(rdAddress, rdPort));
+ asClient.startClient(new InetSocketAddress(acAddress, acPort));
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ asClient.getChannelFuture().channel().attr(keyAccountClient)
+ .set(new ArrayList<CoapRequest>());
+ }
+
+ private static final AttributeKey<ChannelHandlerContext> keyDevice = AttributeKey
+ .newInstance("deviceCtx");
+
+ private HashMap<String, CoapClient> ciRelayClients = new HashMap<String, CoapClient>();
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg)
+ throws Exception {
+
+ if (msg instanceof CoapRequest) {
+ CoapRequest request = (CoapRequest) msg;
+ // Parse uri, send to RD
+ String uriPath = request.getUriPath();
+ CoapRequest accountRequest = null;
+ String userId, deviceId, authPayload;
+ CoapResponse response = null;
+
+ Logger.d("Request received, URI: " + uriPath);
+ switch (uriPath) {
+ case Constants.AUTH_URI:
+ // This case user wants to logout
+ if (request.getUriQuery().endsWith("logout")) {
+ ctx.channel().attr(Constants.Attribute_UserId).remove();
+ response = new CoapResponse(CoapStatus.DELETED);
+ } else {
+ response = new CoapResponse(CoapStatus.BAD_REQUEST);
+ }
+ ctx.writeAndFlush(response);
+ break;
+
+ case Constants.RD_URI:
+ // RD POST means publish device to server
+ switch (request.getRequestMethod()) {
+ case POST:
+ userId = ctx.channel()
+ .attr(Constants.Attribute_UserId).get();
+ deviceId = request.decodeDeviceId();
+ authPayload = String.format(
+ "{\"userid\":\"%s\",\"deviceid\":\"%s\"}",
+ userId, deviceId);
+ accountRequest = new CoapRequest(CoapMethod.POST);
+ accountRequest.setUriPath(Constants.ACCOUNT_URI);
+ accountRequest.setUriQuery("reqtype=publish");
+ accountRequest.setToken(request.getToken());
+ accountRequest.setPayload(authPayload.getBytes(StandardCharsets.UTF_8));
+
+ // TODO: deviceId must be registered after session
+ // granted
+ Logger.d("Adding deviceId to session: " + deviceId);
+ sessionManager.addSession(deviceId, ctx);
+ break;
+
+ default:
+ Logger.e("Unsupported request type");
+ break;
+ }
+
+ rdClient.getChannelFuture().channel().attr(keyRDClient)
+ .set(ctx);
+
+ // Add original request to list for future use
+ asClient.getChannelFuture().channel().attr(keyAccountClient)
+ .get().add(request);
+ asClient.sendRequest(accountRequest);
+ return;
+
+ case Constants.WELL_KNOWN_URI:
+ switch (request.getRequestMethod()) {
+ case GET:
+ userId = ctx.channel()
+ .attr(Constants.Attribute_UserId).get();
+ authPayload = String.format("{\"userid\":\"%s\"}",
+ userId);
+ accountRequest = new CoapRequest(CoapMethod.GET);
+ accountRequest.setUriPath(Constants.ACCOUNT_URI);
+ accountRequest.setUriQuery("reqtype=find");
+ accountRequest.setToken(request.getToken());
+ accountRequest.setPayload(authPayload.getBytes());
+ break;
+
+ default:
+ Logger.e("Unsupported request type");
+ break;
+ }
+
+ rdClient.getChannelFuture().channel().attr(keyRDClient)
+ .set(ctx);
+
+ // Add original request to list for future use
+ asClient.getChannelFuture().channel().attr(keyAccountClient)
+ .get().add(request);
+ asClient.sendRequest(accountRequest);
+ return;
+
+ case Constants.KEEP_ALIVE_URI:
+ break;
+
+ default:
+ List<String> uriPathList = request.getUriPathSegments();
+ String originUriPathList = request.getUriPath();
+ Logger.i("uriPahtList: " + uriPathList.toString());
+ String ciAddress = uriPathList.get(0);
+ String did = uriPathList.get(1);
+
+ Logger.i("CI address: " + ciAddress);
+ Logger.i("did: " + did);
+
+ // TODO: getMyIP ?
+ String hostAddress = Net.getMyIpAddress().replace("/", "");
+ Logger.i("hostAddress : " + hostAddress);
+ // if published CI is mine
+ if (hostAddress.equals(ciAddress) == true) {
+ // find ctx about did, and send msg
+ Logger.d("published CI is mine");
+ String resource = new String();
+ List<String> pathSegments = uriPathList.subList(2,
+ uriPathList.size());
+ for (String path : pathSegments) {
+ resource += "/";
+ resource += path;
+ }
+ Logger.i("resource: " + resource);
+ request.setUriPath(resource);
+
+ ChannelHandlerContext deviceCtx = sessionManager
+ .querySession(did);
+ if (deviceCtx != null) {
+ deviceCtx.attr(keyDevice).set(ctx);
+ deviceCtx.writeAndFlush(request);
+ } else {
+ Logger.e("deviceCtx is null");
+ response = new CoapResponse(CoapStatus.FORBIDDEN);
+ response.setToken(request.getToken());
+ ctx.writeAndFlush(response);
+ }
+ } else {
+ // if CI is not connected, connect and send msg
+ CoapClient otherCI = null;
+ synchronized (ciRelayClients) {
+ otherCI = ciRelayClients.get(ciAddress);
+ if (otherCI == null) {
+ otherCI = new CoapClient();
+ otherCI.startClient(
+ new InetSocketAddress(ciAddress, 5683));
+ ciRelayClients.put(ciAddress, otherCI);
+ }
+ }
+ request.setUriPath(originUriPathList);
+ otherCI.sendRequest(request);
+ }
+ return;
+ }
+
+ } else if (msg instanceof CoapResponse) {
+ if (ctx.attr(keyDevice).get() != null) {
+ Logger.i("ctx.channel : "
+ + ctx.attr(keyDevice).get().channel().toString());
+ ctx.attr(keyDevice).get().writeAndFlush(msg);
+ return;
+ }
+ }
+
+ super.channelRead(ctx, msg);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+
+ cause.printStackTrace();
+ ctx.close();
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.ciserver.resources;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.iotivity.cloud.base.Resource;
+import org.iotivity.cloud.base.SessionManager;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+import org.iotivity.cloud.ciserver.Constants;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Logger;
+
+import io.netty.channel.ChannelHandlerContext;
+
+/**
+ *
+ * This class provides a set of APIs to use KeepAlive Resource for ensuring the
+ * connection.
+ *
+ */
+public class KeepAliveResource extends Resource {
+
+ private int[] intervals;
+ private HashMap<ChannelHandlerContext, Long> connectPool;
+ private Timer timer;
+ private Cbor<HashMap<String, Integer>> cbor;
+ private SessionManager sessionManager = null;
+
+ public void setIntervals(int[] intervals) {
+ this.intervals = intervals;
+ }
+
+ public int[] getIntervals() {
+ return this.intervals;
+ }
+
+ public KeepAliveResource(SessionManager sessionManager, int[] intervals) {
+ setUri(Constants.KEEP_ALIVE_URI);
+ setIntervals(intervals);
+ this.sessionManager = sessionManager;
+ connectPool = new HashMap<ChannelHandlerContext, Long>();
+ timer = new Timer();
+ timer.schedule(new KeepAliveTask(), 30000, 60000);
+ cbor = new Cbor<HashMap<String, Integer>>();
+ }
+
+ /**
+ * API for receiving message(message to keepalive resource)
+ *
+ * @param ctx
+ * ChannelHandlerContext of request message
+ * @param request
+ * CoAP request message
+ */
+ @Override
+ public void onRequestReceived(ChannelHandlerContext ctx,
+ CoapRequest request) {
+
+ CoapResponse response = null;
+
+ switch (request.getRequestMethod()) {
+ // First message to KeepAlive from resource
+ case GET:
+ if (intervals != null) {
+ response = makePingConfigMessage(request);
+ connectPool.put(ctx, System.currentTimeMillis()
+ + (intervals[0] * (long) 60000));
+ }
+ break;
+ // interval Message to KeepAlive After receiving GET Message
+ case PUT:
+ HashMap<String, Integer> payloadData = null;
+ payloadData = cbor.parsePayloadFromCbor(request.getPayload(),
+ new HashMap<String, Integer>().getClass());
+
+ Logger.d("Receive payloadData : " + payloadData);
+ Logger.d("interval : " + payloadData.get("in"));
+
+ connectPool.put(ctx, System.currentTimeMillis()
+ + (payloadData.get("in") * (long) 60000));
+
+ response = makeResponse(request);
+ break;
+
+ case POST:
+ break;
+
+ case DELETE:
+ break;
+ }
+
+ ctx.writeAndFlush(response);
+ }
+
+ /**
+ * API for making response to Resource
+ *
+ * @param request
+ * ChannelHandlerContext of request message
+ */
+ private CoapResponse makeResponse(CoapRequest request) {
+ CoapResponse response = new CoapResponse(CoapStatus.VALID);
+ response.setToken(request.getToken());
+
+ return response;
+ }
+
+ /**
+ * API for making interval and first response to Resource
+ *
+ * @param request
+ * ChannelHandlerContext of request message
+ */
+ private CoapResponse makePingConfigMessage(CoapRequest request) {
+ CoapResponse response = new CoapResponse(CoapStatus.CONTENT);
+ response.setToken(request.getToken());
+
+ HashMap<String, int[]> payloadData = new HashMap<String, int[]>();
+ payloadData.put("inarray", intervals);
+
+ byte[] cborData = cbor.encodingPayloadToCbor(payloadData);
+
+ response.setPayload(cborData);
+
+ Logger.d("Send payloadData : " + payloadData);
+
+ return response;
+ }
+
+ /**
+ * API for managing session
+ */
+ public class KeepAliveTask extends TimerTask {
+
+ @Override
+ public void run() {
+ Map<ChannelHandlerContext, Long> map = Collections
+ .synchronizedMap(connectPool);
+ Set<ChannelHandlerContext> keySet = map.keySet();
+ ArrayList<ChannelHandlerContext> deleteList = new ArrayList<ChannelHandlerContext>();
+ Iterator<ChannelHandlerContext> iterator = null;
+ synchronized (map) {
+ iterator = keySet.iterator();
+ Long currentTime = System.currentTimeMillis();
+ // check interval
+ while (iterator.hasNext()) {
+ ChannelHandlerContext key = iterator.next();
+ Long lifeTime = (Long) map.get(key);
+ Logger.d("KeepAliveTask Operating : "
+ + key.channel().toString() + ", Time : "
+ + (lifeTime - currentTime));
+ if (lifeTime < currentTime) {
+ deleteList.add(key);
+ }
+ }
+
+ }
+ iterator = deleteList.iterator();
+ // remove session
+ while (iterator.hasNext()) {
+ ChannelHandlerContext key = iterator.next();
+ Logger.d("KeepAliveTask Remove");
+ connectPool.remove(key);
+ sessionManager.removeSessionByChannel(key);
+ key.close();
+ }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>CloudResourceDirectory</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+This project contains the Resource Directory(RD) Server code.
+
+Build and Run
+
+1) Install Apache Maven if you don't have it
+
+ http://maven.apache.org
+
+2) Install Mongo DB if you don't have it
+
+ http://www.mongodb.org/downloads
+
+3) Build a CloudStack. If you are building first time, then build the stack.
+
+ go to "stack" folder in root directory
+ $ mvn install
+
+4) Build a .jar file
+
+ $ mvn install
+
+ - The CloudResourceDirectory-0.0.1-SNAPSHOT.jar file will be placed in the "target" folder
+
+5) Run .jar file
+
+ go to "target" folder
+ $ java -jar CloudResourceDirectory-0.0.1-SNAPSHOT.jar arg1(RD CoAP Server Port)
+ e.g java -jar CloudResourceDirectory-0.0.1-SNAPSHOT.jar 5684
+
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.iotivity.cloud</groupId>
+ <artifactId>CloudResourceDirectory</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.iotivity.cloud</groupId>
+ <artifactId>CloudStack</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mongodb</groupId>
+ <artifactId>mongo-java-driver</artifactId>
+ <version>3.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.iotivity.cloud.rdserver.ResourceDirectoryServer</mainClass>
+ <addClasspath>true</addClasspath>
+ <classpathPrefix>lib/</classpathPrefix>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <outputDirectory>target/lib</outputDirectory>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.rdserver;
+
+public class Constants {
+ public static final String RD_TABLE = "RD_TABLE";
+ public static final String RD_DB_NAME = "RDDB";
+
+ public static final String RD_URI = "oic/rd";
+
+ public static final String RS_DEVICE_NAME = "n";
+ public static final String RS_DEVICE_ID = "di";
+ public static final String RS_BASE_URI = "baseURI";
+ public static final String RS_BITMAP = "bm";
+ public static final String RS_HOSTING_PORT = "port";
+ public static final String RS_INS = "ins";
+ public static final String RS_RTS = "rts";
+ public static final String RS_DREL = "drel";
+ public static final String RS_TTL = "ttl";
+ public static final String RS_HREF = "href";
+ public static final String RS_RESOURCE_TYPE = "rt";
+ public static final String RS_INTERFACE = "if";
+ public static final String RS_REL = "rel";
+ public static final String RS_OBS = "obs";
+ public static final String RS_TITLE = "title";
+ public static final String RS_URI = "uri";
+ public static final String RS_MEDIA_TYPE = "mt";
+ public static final String RS_RESOURCE_TYPE_RDPUBLISH = "oic.wk.rdpub";
+
+ public static final String RS_SEARCH_TYPE = "st";
+ public static final String RS_SEARCH_TYPE_DEVICE_LIST = "didList";
+ public static final String RS_DEVICE_LIST_KEY = "devices";
+}
--- /dev/null
+package org.iotivity.cloud.rdserver;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JSONUtil {
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ public ArrayList<String> parseJSON(byte[] payload, String key) {
+
+ if (payload == null)
+ return null;
+
+ ArrayList<String> value = null;
+
+ try {
+ @SuppressWarnings("unchecked")
+ Map<String, ArrayList<String>> jsonMap = mapper.readValue(payload,
+ Map.class);
+ value = jsonMap.get(key);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+
+ return value;
+ }
+
+ public byte[] writeJSON(HashMap<Object, Object> data) throws Exception {
+ if (data == null)
+ return null;
+
+ byte[] json = null;
+ try {
+ json = mapper.writeValueAsBytes(data);
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+
+ if (json == null)
+ json = "{}".getBytes(StandardCharsets.UTF_8);
+
+ return json;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.rdserver;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.bson.Document;
+import org.iotivity.cloud.rdserver.resources.LinksPayloadFormat;
+import org.iotivity.cloud.rdserver.resources.PublishPayloadFormat;
+
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoCursor;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.Filters;
+
+/**
+ *
+ * This class provides a set of APIs to use MongoDB APIs.
+ *
+ */
+public class MongoDB {
+
+ private MongoClient mongoClient = null;
+ private MongoDatabase db = null;
+
+ /**
+ * API creating MongoClient and initializing MongoDatabase
+ *
+ * @param dbname
+ * database name to create MongoDatabase
+ * @throws Exception
+ */
+ public MongoDB(String dbname) throws Exception {
+ mongoClient = new MongoClient();
+ mongoClient.dropDatabase(dbname);
+ db = mongoClient.getDatabase(dbname);
+ }
+
+ /**
+ * API creating collection
+ *
+ * @param tableName
+ * collection name
+ */
+ public void createTable(String tableName) {
+ db.createCollection(tableName);
+ }
+
+ /**
+ * API deleting collection
+ *
+ * @param tableName
+ * collection name
+ */
+ public void deleteTable(String tableName) {
+ db.getCollection(tableName).drop();
+ }
+
+ private ArrayList<Document> createDocuments(
+ PublishPayloadFormat publishPayloadFormat) {
+
+ Iterator<LinksPayloadFormat> linksPayloadFormatIter = publishPayloadFormat
+ .getLinks().iterator();
+ ArrayList<Document> docList = new ArrayList<Document>();
+
+ while (linksPayloadFormatIter.hasNext()) {
+ LinksPayloadFormat links = linksPayloadFormatIter.next();
+ Document doc = new Document(Constants.RS_DEVICE_NAME,
+ publishPayloadFormat.getDeviceName())
+ .append(Constants.RS_DEVICE_ID,
+ publishPayloadFormat.getDi())
+ .append(Constants.RS_BASE_URI,
+ publishPayloadFormat.getBaseUri())
+ .append(Constants.RS_BITMAP,
+ publishPayloadFormat.getBitmap())
+ .append(Constants.RS_HOSTING_PORT,
+ publishPayloadFormat.getPort())
+ .append(Constants.RS_INS,
+ publishPayloadFormat.getIns())
+ .append(Constants.RS_RTS,
+ publishPayloadFormat.getRts())
+ .append(Constants.RS_DREL,
+ publishPayloadFormat.getDrel())
+ .append(Constants.RS_TTL,
+ publishPayloadFormat.getTtl())
+ .append(Constants.RS_HREF, links.getHref())
+ .append(Constants.RS_RESOURCE_TYPE, links.getRt())
+ .append(Constants.RS_INTERFACE, links.getItf())
+ .append(Constants.RS_REL, links.getRel())
+ .append(Constants.RS_OBS, links.isObs())
+ .append(Constants.RS_TITLE, links.getTitle())
+ .append(Constants.RS_URI, links.getUri())
+ .append(Constants.RS_INS, links.getIns())
+ .append(Constants.RS_MEDIA_TYPE, links.getMt());
+ docList.add(doc);
+ }
+
+ return docList;
+ }
+
+ private PublishPayloadFormat convertDocumentToResourceFormat(Document doc) {
+ PublishPayloadFormat publishPayloadFormat = new PublishPayloadFormat();
+ LinksPayloadFormat linksPayloadFormat = new LinksPayloadFormat();
+ ArrayList<LinksPayloadFormat> list = new ArrayList<LinksPayloadFormat>();
+
+ publishPayloadFormat
+ .setDeviceName(doc.getString(Constants.RS_DEVICE_NAME));
+ publishPayloadFormat.setDi(doc.getString(Constants.RS_DEVICE_ID));
+ publishPayloadFormat.setBaseUri(doc.getString(Constants.RS_BASE_URI));
+ publishPayloadFormat.setBitmap(doc.getInteger(Constants.RS_BITMAP));
+ publishPayloadFormat.setPort(doc.getInteger(Constants.RS_HOSTING_PORT));
+ publishPayloadFormat.setIns(doc.getInteger(Constants.RS_INS));
+ publishPayloadFormat.setRts(doc.getString(Constants.RS_RTS));
+ publishPayloadFormat.setDrel(doc.getString(Constants.RS_DREL));
+ publishPayloadFormat.setTtl(doc.getInteger(Constants.RS_TTL));
+
+ linksPayloadFormat.setHref(doc.getString(Constants.RS_HREF));
+ linksPayloadFormat
+ .setRt((ArrayList<String>) doc.get(Constants.RS_RESOURCE_TYPE));
+ linksPayloadFormat
+ .setItf((ArrayList<String>) doc.get(Constants.RS_INTERFACE));
+ linksPayloadFormat.setRel(doc.getString(Constants.RS_REL));
+ linksPayloadFormat.setObs(doc.getBoolean(Constants.RS_OBS));
+ linksPayloadFormat.setTitle(doc.getString(Constants.RS_TITLE));
+ linksPayloadFormat.setUri(doc.getString(Constants.RS_URI));
+ linksPayloadFormat.setIns(doc.getInteger(Constants.RS_INS));
+ linksPayloadFormat
+ .setMt((ArrayList<String>) doc.get(Constants.RS_MEDIA_TYPE));
+
+ list.add(linksPayloadFormat);
+ publishPayloadFormat.setLinks(list);
+
+ return publishPayloadFormat;
+ }
+
+ /**
+ * API for storing information of published resources
+ *
+ * @param publishPayloadFormat
+ * information of published resources to store in collection
+ * @param tablename
+ * collection name
+ */
+ public void createResource(PublishPayloadFormat publishPayloadFormat,
+ String tablename) {
+ ArrayList<Document> docList = createDocuments(publishPayloadFormat);
+ Iterator<Document> docIter = docList.iterator();
+
+ MongoCollection<Document> collection = db.getCollection(tablename);
+
+ while (docIter.hasNext()) {
+ Document doc = docIter.next();
+
+ if (collection.findOneAndReplace(
+ Filters.and(Filters.eq(Constants.RS_DEVICE_ID,
+ doc.get(Constants.RS_DEVICE_ID)),
+ Filters.eq(Constants.RS_INS, doc.get(Constants.RS_INS))),
+ doc) == null) {
+
+ collection.insertOne(doc);
+ }
+ }
+ }
+
+ /**
+ * API for finding resources matched filterValue of filterKey in collection
+ *
+ * @param filterKey
+ * field name in collection
+ * @param filterValue
+ * field value about field name
+ * @param tablename
+ * collection name
+ * @return ArrayList<PublishPayloadFormat> - array list of resource
+ * information
+ */
+ public ArrayList<PublishPayloadFormat> readResource(String filterKey,
+ String filterValue, String tablename) {
+ MongoCollection<Document> collection = db.getCollection(tablename);
+ ArrayList<PublishPayloadFormat> resourceFormatList = new ArrayList<PublishPayloadFormat>();
+ MongoCursor<Document> cursor = collection
+ .find(Filters.eq(filterKey, filterValue)).iterator();
+ try {
+ while (cursor.hasNext()) {
+ Document doc = cursor.next();
+ resourceFormatList.add(convertDocumentToResourceFormat(doc));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return resourceFormatList;
+ }
+
+ /**
+ * API for finding resources matched filterValue of filterKey and a
+ * particular device ID in collection
+ *
+ * @param di
+ * device id
+ * @param filterKey
+ * field name in collection
+ * @param filterValue
+ * field value about field name
+ * @param tablename
+ * collection name
+ * @return ArrayList<PublishPayloadFormat> - array list of resource
+ * information
+ */
+ public ArrayList<PublishPayloadFormat> readResourceAboutDid(String di,
+ String filterKey, String filterValue, String tablename) {
+ MongoCollection<Document> collection = db.getCollection(tablename);
+ ArrayList<PublishPayloadFormat> resourceFormatList = new ArrayList<PublishPayloadFormat>();
+ MongoCursor<Document> cursor = collection
+ .find(Filters.and(Filters.eq(Constants.RS_DEVICE_ID, di),
+ Filters.eq(filterKey, filterValue)))
+ .iterator();
+ try {
+ while (cursor.hasNext()) {
+ Document doc = cursor.next();
+ resourceFormatList.add(convertDocumentToResourceFormat(doc));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return resourceFormatList;
+ }
+
+ /**
+ * API for deleting resources about a particular device ID in collection
+ *
+ * @param di
+ * device id
+ * @param tablename
+ * collection name
+ */
+ public void deleteResourceAboutDid(String di, String tablename) {
+
+ MongoCollection<Document> collection = db.getCollection(tablename);
+
+ collection.findOneAndDelete(Filters.eq(Constants.RS_DEVICE_ID, di));
+ }
+
+ /**
+ * API for deleting resources about a particular device ID and ins in
+ * collection
+ *
+ * @param di
+ * device id
+ * @param ins
+ * ins
+ * @param tablename
+ * collection name
+ */
+ public void deleteResourceAboutDidAndIns(String di, String ins,
+ String tablename) {
+
+ MongoCollection<Document> collection = db.getCollection(tablename);
+
+ collection.findOneAndDelete(
+ Filters.and(Filters.eq(Constants.RS_DEVICE_ID, di),
+ Filters.eq(Constants.RS_INS, ins)));
+
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.rdserver;
+
+import java.net.InetSocketAddress;
+
+import org.iotivity.cloud.base.CoapServer;
+import org.iotivity.cloud.base.ResourceManager;
+import org.iotivity.cloud.rdserver.resources.ResourceDirectoryResource;
+import org.iotivity.cloud.util.Logger;
+import org.iotivity.cloud.util.Net;
+
+public class ResourceDirectoryServer {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("-----RD SERVER-----");
+ String hostAddress = Net.getMyIpAddress();
+ if (hostAddress.equals("") == true) {
+ Logger.e("cannot find host address.");
+ return;
+ }
+
+ if (args.length != 1) {
+ Logger.e("coap server port required");
+ return;
+ }
+
+ ResourceManager resourceManager = null;
+
+ CoapServer coapServer = null;
+
+ coapServer = new CoapServer();
+
+ resourceManager = new ResourceManager();
+
+ coapServer.addHandler(resourceManager);
+
+ resourceManager.registerResource(new ResourceDirectoryResource());
+
+ coapServer
+ .startServer(new InetSocketAddress(Integer.parseInt(args[0])));
+ }
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.rdserver.resources;
+
+import java.util.ArrayList;
+
+public class LinksPayloadFormat {
+ /** This is the target relative URI. */
+ String href;
+ /**
+ * Resource Type - A standard OIC specified or vendor defined resource type
+ * of the resource referenced by the target URI.
+ */
+ ArrayList<String> rt;
+ /**
+ * Interface - The interfaces supported by the resource referenced by the
+ * target URI.
+ */
+ ArrayList<String> itf;
+ /**
+ * The relation of the target URI referenced by the link to the context URI;
+ * The default value is null.
+ */
+ String rel;
+ /**
+ * Specifies if the resource referenced by the target URIis observable or
+ * not.
+ */
+ boolean obs;
+ /**
+ * A title for the link relation. Can be used by the UI to provide a
+ * context.
+ */
+ String title;
+ /**
+ * This is used to override the context URI e.g. override the URI of the
+ * containing collection.
+ */
+ String uri;
+ /**
+ * The instance identifier for this web link in an array of web links - used
+ * in links.
+ */
+ int ins;
+ /**
+ * A hint of the media type of the representation of the resource referenced
+ * by the target URI.
+ */
+ ArrayList<String> mt;
+
+ public LinksPayloadFormat() {
+ rt = new ArrayList<String>();
+ itf = new ArrayList<String>();
+ mt = new ArrayList<String>();
+ }
+
+ public String getHref() {
+ return href;
+ }
+
+ public void setHref(String href) {
+ this.href = href;
+ }
+
+ public ArrayList<String> getRt() {
+ return rt;
+ }
+
+ public void setRt(ArrayList<String> rt) {
+ this.rt = rt;
+ }
+
+ public ArrayList<String> getItf() {
+ return itf;
+ }
+
+ public void setItf(ArrayList<String> itf) {
+ this.itf = itf;
+ }
+
+ public String getRel() {
+ return rel;
+ }
+
+ public void setRel(String rel) {
+ this.rel = rel;
+ }
+
+ public boolean isObs() {
+ return obs;
+ }
+
+ public void setObs(boolean obs) {
+ this.obs = obs;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public int getIns() {
+ return ins;
+ }
+
+ public void setIns(int ins) {
+ this.ins = ins;
+ }
+
+ public ArrayList<String> getMt() {
+ return mt;
+ }
+
+ public void setMt(ArrayList<String> mt) {
+ this.mt = mt;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.rdserver.resources;
+
+import java.util.ArrayList;
+
+public class PublishPayloadFormat {
+
+ /** Name of tags. */
+ String deviceName;
+ /** Device identifier. */
+ String di;
+ /** The base URI where the resources are hold. */
+ String baseUri;
+ /** Bitmap holds observable, discoverable, secure option flag. */
+ int bitmap;
+ /** Port set in case, the secure flag is set above. */
+ int port;
+ /** Id for each set of links i.e. tag. */
+ int ins;
+ /**
+ * Defines the list of allowable resource types (for Target and anchors) in
+ * links included in the collection; new links being created can only be
+ * from this list.
+ */
+ String rts;
+ /**
+ * When specified this is the default relationship to use when an OIC Link
+ * does not specify an explicit relationship with *rel* parameter.
+ */
+ String drel;
+ /** Time to keep holding resource. */
+ int ttl;
+
+ ArrayList<LinksPayloadFormat> links;
+
+ public PublishPayloadFormat() {
+ links = new ArrayList<LinksPayloadFormat>();
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ public void setDeviceName(String deviceName) {
+ this.deviceName = deviceName;
+ }
+
+ public String getDi() {
+ return di;
+ }
+
+ public void setDi(String di) {
+ this.di = di;
+ }
+
+ public String getBaseUri() {
+ return baseUri;
+ }
+
+ public void setBaseUri(String baseUri) {
+ this.baseUri = baseUri;
+ }
+
+ public int getBitmap() {
+ return bitmap;
+ }
+
+ public void setBitmap(int bitmap) {
+ this.bitmap = bitmap;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public int getIns() {
+ return ins;
+ }
+
+ public void setIns(int ins) {
+ this.ins = ins;
+ }
+
+ public String getRts() {
+ return rts;
+ }
+
+ public void setRts(String rts) {
+ this.rts = rts;
+ }
+
+ public String getDrel() {
+ return drel;
+ }
+
+ public void setDrel(String drel) {
+ this.drel = drel;
+ }
+
+ public int getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(int ttl) {
+ this.ttl = ttl;
+ }
+
+ public ArrayList<LinksPayloadFormat> getLinks() {
+ return links;
+ }
+
+ public void setLinks(ArrayList<LinksPayloadFormat> links) {
+ this.links = links;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.rdserver.resources;
+
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.iotivity.cloud.base.Resource;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapOption;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+import org.iotivity.cloud.rdserver.Constants;
+import org.iotivity.cloud.rdserver.JSONUtil;
+import org.iotivity.cloud.rdserver.MongoDB;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Logger;
+import org.iotivity.cloud.util.Net;
+
+import io.netty.channel.ChannelHandlerContext;
+
+/**
+ *
+ * This class provides a set of APIs relating Resource Directory
+ *
+ */
+public class ResourceDirectoryResource extends Resource {
+
+ private Cbor<ArrayList<Object>> cbor;
+ private MongoDB mongoDB;
+
+ public ResourceDirectoryResource() {
+ setUri(Constants.RD_URI);
+ cbor = new Cbor<ArrayList<Object>>();
+ try {
+ mongoDB = new MongoDB(Constants.RD_DB_NAME);
+ mongoDB.createTable(Constants.RD_TABLE);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onRequestReceived(ChannelHandlerContext ctx,
+ CoapRequest request) {
+
+ Logger.d("ResourceDirectoryResource IN");
+
+ if (ctx == null || request == null) {
+ Logger.d("ctx or request msg is null");
+ }
+
+ else {
+ switch (request.getRequestMethod()) {
+ case GET:
+ Logger.d("Request message is GET message");
+ try {
+ handleGetRequest(ctx, request);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+
+ case PUT:
+ Logger.d("Request message is PUT message");
+ break;
+
+ case POST:
+ Logger.d("Request message is POST message");
+ try {
+ handlePostRequest(ctx, request);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+
+ case DELETE:
+ Logger.d("Request message is DELETE message");
+ try {
+ handleDeleteRequest(ctx, request);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+ }
+ }
+ }
+
+ private CoapResponse makePublishResponse(CoapRequest request)
+ throws Exception {
+ CoapResponse response = new CoapResponse(CoapStatus.CREATED);
+ response.setToken(request.getToken());
+ return response;
+ }
+
+ private CoapResponse makeDeleteResponse(CoapRequest request)
+ throws Exception {
+ CoapResponse response = new CoapResponse(CoapStatus.DELETED);
+ response.setToken(request.getToken());
+ return response;
+ }
+
+ private CoapResponse makeDiscoveryResponse(CoapRequest request,
+ ArrayList<PublishPayloadFormat> foundResource) throws Exception {
+
+ CoapResponse response = new CoapResponse(CoapStatus.CONTENT);
+ response.setToken(request.getToken());
+
+ // make payload
+ ArrayList<HashMap<Object, Object>> discoverPayload = new ArrayList<HashMap<Object, Object>>();
+
+ for (PublishPayloadFormat pubPayload : foundResource) {
+
+ LinksPayloadFormat links = pubPayload.links.get(0);
+ LinkedHashMap<Object, Object> discoverLinks = new LinkedHashMap<Object, Object>();
+ discoverLinks.put(Constants.RS_HREF, links.getHref());
+ discoverLinks.put(Constants.RS_RESOURCE_TYPE, links.getRt().get(0));
+ discoverLinks.put(Constants.RS_INTERFACE, links.getItf().get(0));
+ HashMap<Object, Object> pres = new HashMap<Object, Object>();
+ pres.put(Constants.RS_BITMAP, pubPayload.getBitmap());
+ discoverLinks.put("p", pres);
+
+ ArrayList<Object> linksArray = null;
+ for (HashMap<Object, Object> segmentPayload : discoverPayload) {
+ // exist di
+ if (segmentPayload.get(Constants.RS_DEVICE_ID)
+ .equals(pubPayload.getDi())) {
+ linksArray = new ArrayList<Object>();
+ linksArray = (ArrayList<Object>) segmentPayload
+ .get("links");
+ linksArray.add(discoverLinks);
+ segmentPayload.put("links", linksArray);
+ }
+ }
+ if (linksArray == null) {
+ HashMap<Object, Object> discoverRes = new HashMap<Object, Object>();
+ linksArray = new ArrayList<Object>();
+ discoverRes.put(Constants.RS_DEVICE_ID, pubPayload.getDi());
+ linksArray.add(discoverLinks);
+ discoverRes.put("links", linksArray);
+ discoverPayload.add(discoverRes);
+ }
+ }
+
+ // TODO : device id is decoded to byte in IoTivity. So, temporarily we
+ // cast the type of device id to byte.
+ for (HashMap<Object, Object> segmentPayload : discoverPayload) {
+ String stringDi = segmentPayload.get(Constants.RS_DEVICE_ID)
+ .toString();
+ segmentPayload.put(Constants.RS_DEVICE_ID, stringDi.getBytes(StandardCharsets.UTF_8));
+ }
+
+ Logger.i("discoverPayload :" + discoverPayload.toString());
+
+ byte[] bytes = ByteBuffer.allocate(4).putInt(60).array();
+ response.addOption(CoapOption.CONTENT_FORMAT.getvalue(), bytes);
+
+ byte[] encodedPaylod = cbor.encodingPayloadToCbor(discoverPayload);
+ response.setPayload(encodedPaylod);
+
+ return response;
+
+ }
+
+ private HashMap<String, String> extractFiltersFromQuery(List<String> query)
+ throws Exception {
+
+ if (query == null) {
+ throw new IllegalArgumentException("query is null!");
+ }
+
+ HashMap<String, String> filters = new HashMap<String, String>();
+ for (String queryPara : query) {
+ StringTokenizer keyValuePair = new StringTokenizer(queryPara, "=");
+ if (keyValuePair.countTokens() < 2) {
+ // query error
+ filters = null;
+ } else {
+ String key = keyValuePair.nextToken();
+ String value = keyValuePair.nextToken();
+ if (key.equals(Constants.RS_INTERFACE)) {
+ filters.put(Constants.RS_INTERFACE, value);
+ } else if (key.equals(Constants.RS_RESOURCE_TYPE)) {
+ filters.put(Constants.RS_RESOURCE_TYPE, value);
+ } else if (key.equals(Constants.RS_DEVICE_ID)) {
+ filters.put(Constants.RS_DEVICE_ID, value);
+ } else if (key.equals(Constants.RS_INS)) {
+ filters.put(Constants.RS_INS, value);
+ } else if (key.equals(Constants.RS_SEARCH_TYPE)) {
+ filters.put(Constants.RS_SEARCH_TYPE, value);
+ }
+ }
+ }
+
+ return filters;
+ }
+
+ /**
+ * API for handling GET message(message to discovery resources)
+ *
+ * @param ctx
+ * ChannelHandlerContext of request message
+ * @param request
+ * CoAP request message
+ * @throws Exception
+ */
+ public void handleGetRequest(ChannelHandlerContext ctx, CoapRequest request)
+ throws Exception {
+ HashMap<String, String> filters = extractFiltersFromQuery(
+ request.getUriQuerySegments());
+
+ ArrayList<PublishPayloadFormat> foundResource = null;
+
+ if (filters == null) {
+ throw new IllegalArgumentException("filters is null");
+ } else if (filters.get(Constants.RS_SEARCH_TYPE) == null) {
+ Logger.d("st is null, so this is the get msg about public devices");
+ if (filters.get(Constants.RS_INTERFACE) != null) {
+ foundResource = mongoDB.readResource(Constants.RS_INTERFACE,
+ filters.get(Constants.RS_INTERFACE),
+ Constants.RD_TABLE);
+ } else if (filters.get(Constants.RS_RESOURCE_TYPE) != null) {
+ foundResource = mongoDB.readResource(Constants.RS_RESOURCE_TYPE,
+ filters.get(Constants.RS_RESOURCE_TYPE),
+ Constants.RD_TABLE);
+ } else {
+ throw new IllegalArgumentException("rt & if is null");
+ }
+
+ CoapResponse response = makeDiscoveryResponse(request,
+ foundResource);
+ ctx.writeAndFlush(response);
+
+ } else {
+ if (filters.get(Constants.RS_SEARCH_TYPE)
+ .equals(Constants.RS_SEARCH_TYPE_DEVICE_LIST)) {
+ Logger.d(
+ "st is not null, so this is the get msg about private devices");
+ // parse payload
+ byte[] payload = request.getPayload();
+ JSONUtil util = new JSONUtil();
+ ArrayList<String> deviceList = util.parseJSON(payload,
+ Constants.RS_DEVICE_LIST_KEY);
+ if (deviceList == null) {
+ throw new IllegalArgumentException("deviceList is null");
+ }
+
+ if (filters.get(Constants.RS_INTERFACE) != null) {
+ foundResource = new ArrayList<PublishPayloadFormat>();
+ for (String deviceId : deviceList) {
+ foundResource.addAll(mongoDB.readResourceAboutDid(
+ deviceId, Constants.RS_INTERFACE,
+ filters.get(Constants.RS_INTERFACE),
+ Constants.RD_TABLE));
+ }
+ } else if (filters.get(Constants.RS_RESOURCE_TYPE) != null) {
+ foundResource = new ArrayList<PublishPayloadFormat>();
+ for (String deviceId : deviceList) {
+ foundResource.addAll(mongoDB.readResourceAboutDid(
+ deviceId, Constants.RS_RESOURCE_TYPE,
+ filters.get(Constants.RS_RESOURCE_TYPE),
+ Constants.RD_TABLE));
+ }
+ } else {
+ throw new IllegalArgumentException("rt & if is null");
+ }
+
+ CoapResponse response = makeDiscoveryResponse(request,
+ foundResource);
+ ctx.writeAndFlush(response);
+ } else {
+ throw new IllegalArgumentException("value of st is not corret");
+ }
+ }
+ }
+
+ /**
+ * API for handling POST message(message to publish or update resources)
+ *
+ * @param ctx
+ * ChannelHandlerContext of request message
+ * @param request
+ * CoAP request message
+ * @throws Exception
+ */
+ public void handlePostRequest(ChannelHandlerContext ctx,
+ CoapRequest request) throws Exception {
+
+ HashMap<String, String> filters = extractFiltersFromQuery(
+ request.getUriQuerySegments());
+
+ if (filters == null) {
+ throw new IllegalArgumentException("filters is null");
+ } else if (filters.get(Constants.RS_RESOURCE_TYPE) == null) {
+ throw new IllegalArgumentException("rt is null");
+ } else if (filters.get(Constants.RS_RESOURCE_TYPE)
+ .equals(Constants.RS_RESOURCE_TYPE_RDPUBLISH)) {
+ Logger.d("This request is publish msg!");
+
+ PublishPayloadFormat pubPayload = new PublishPayloadFormat();
+
+ String ciAddress = ((InetSocketAddress) ctx.channel()
+ .remoteAddress()).getAddress().getHostAddress();
+
+ if (ciAddress.equalsIgnoreCase("127.0.0.1")) {
+ ciAddress = Net.getMyIpAddress().replace("/", "");
+ }
+
+ ArrayList<Object> payloadData = cbor.parsePayloadFromCbor(
+ request.getPayload(), ArrayList.class);
+
+ Logger.i("payloadData: " + payloadData.toString());
+
+ HashMap<Object, Object> tags = (HashMap<Object, Object>) payloadData
+ .get(0);
+
+ if (tags == null) {
+ throw new IllegalArgumentException("tags is null!");
+ }
+
+ if (tags.get(Constants.RS_DEVICE_ID) != null) {
+ pubPayload.setDi(tags.get(Constants.RS_DEVICE_ID).toString());
+ Logger.i("di : " + pubPayload.getDi());
+ } else {
+ throw new IllegalArgumentException("device id is null!");
+ }
+
+ if (tags.get(Constants.RS_DEVICE_NAME) != null) {
+ pubPayload.setDeviceName(
+ tags.get(Constants.RS_DEVICE_NAME).toString());
+ Logger.i("device name : " + pubPayload.getDeviceName());
+ }
+
+ if (tags.get(Constants.RS_BASE_URI) != null) {
+ pubPayload
+ .setBaseUri(tags.get(Constants.RS_BASE_URI).toString());
+ Logger.i("baseURI : " + pubPayload.getBaseUri());
+ }
+
+ if (tags.get(Constants.RS_BITMAP) != null) {
+ pubPayload.setBitmap((int) tags.get(Constants.RS_BITMAP));
+ Logger.i("bm : " + pubPayload.getBitmap());
+ }
+
+ if (tags.get(Constants.RS_HOSTING_PORT) != null) {
+ pubPayload.setPort((int) tags.get(Constants.RS_HOSTING_PORT));
+ Logger.i("port : " + pubPayload.getPort());
+ }
+
+ if (tags.get(Constants.RS_INS) != null) {
+ pubPayload.setIns((int) tags.get(Constants.RS_INS));
+ Logger.i("ins : " + pubPayload.getIns());
+ }
+
+ if (tags.get(Constants.RS_RTS) != null) {
+ pubPayload.setRts(tags.get(Constants.RS_RTS).toString());
+ Logger.i("rts : " + pubPayload.getRts());
+ }
+
+ if (tags.get(Constants.RS_DREL) != null) {
+ pubPayload.setDrel(tags.get(Constants.RS_DREL).toString());
+ Logger.i("drel : " + pubPayload.getDrel());
+ }
+
+ if (tags.get(Constants.RS_TTL) != null) {
+ pubPayload.setTtl((int) tags.get(Constants.RS_TTL));
+ Logger.i("ttl : " + pubPayload.getTtl());
+ }
+
+ ArrayList<LinkedHashMap<Object, Object>> publishLinks = (ArrayList<LinkedHashMap<Object, Object>>) payloadData
+ .get(1);
+
+ if (publishLinks == null) {
+ throw new IllegalArgumentException("publishLinks is null!");
+ }
+
+ for (LinkedHashMap<Object, Object> o : publishLinks) {
+
+ LinksPayloadFormat storeLinks = new LinksPayloadFormat();
+
+ if (o.get(Constants.RS_HREF) != null) {
+ String prefix = "/" + ciAddress + "/" + pubPayload.getDi();
+ storeLinks.setHref(
+ prefix + o.get(Constants.RS_HREF).toString());
+ Logger.i("href : " + storeLinks.getHref());
+ }
+
+ if (o.get(Constants.RS_RESOURCE_TYPE) != null) {
+ storeLinks.setRt((ArrayList<String>) o
+ .get(Constants.RS_RESOURCE_TYPE));
+ Logger.i("rt : " + storeLinks.getRt().toString());
+ }
+
+ if (o.get(Constants.RS_INTERFACE) != null) {
+ storeLinks.setItf(
+ (ArrayList<String>) o.get(Constants.RS_INTERFACE));
+ Logger.i("if : " + storeLinks.getItf().toString());
+ }
+
+ if (o.get(Constants.RS_REL) != null) {
+ storeLinks.setRel(o.get(Constants.RS_REL).toString());
+ Logger.i("rel : " + storeLinks.getRel());
+ }
+
+ if (o.get(Constants.RS_OBS) != null) {
+ storeLinks.setObs((boolean) o.get(Constants.RS_OBS));
+ Logger.i("obs : " + storeLinks.isObs());
+ }
+
+ if (o.get(Constants.RS_TITLE) != null) {
+ storeLinks.setTitle(o.get(Constants.RS_TITLE).toString());
+ Logger.i("title : " + storeLinks.getTitle());
+ }
+
+ if (o.get(Constants.RS_URI) != null) {
+ storeLinks.setUri(o.get(Constants.RS_URI).toString());
+ Logger.i("uri : " + storeLinks.getUri());
+ }
+
+ if (o.get(Constants.RS_INS) != null) {
+ storeLinks.setIns((int) (o.get(Constants.RS_INS)));
+ Logger.i("ins : " + storeLinks.getIns());
+ }
+
+ if (o.get(Constants.RS_MEDIA_TYPE) != null) {
+ storeLinks.setMt(
+ (ArrayList<String>) o.get(Constants.RS_MEDIA_TYPE));
+ Logger.i("mt : " + storeLinks.getMt().toString());
+ }
+
+ pubPayload.links.add(storeLinks);
+ }
+
+ mongoDB.createResource(pubPayload, Constants.RD_TABLE);
+
+ CoapResponse response = makePublishResponse(request);
+ ctx.writeAndFlush(response);
+
+ } else {
+ throw new IllegalArgumentException("rt is not correct");
+ }
+ }
+
+ /**
+ * API for handling Delete message(message to delete published resources)
+ *
+ * @param ctx
+ * ChannelHandlerContext of request message
+ * @param request
+ * CoAP request message
+ * @throws Exception
+ */
+ public void handleDeleteRequest(ChannelHandlerContext ctx,
+ CoapRequest request) throws Exception {
+ HashMap<String, String> filters = extractFiltersFromQuery(
+ request.getUriQuerySegments());
+
+ if (filters == null) {
+ throw new IllegalArgumentException("filters is null");
+ } else if (filters.get(Constants.RS_DEVICE_ID) == null) {
+ throw new IllegalArgumentException("di is null");
+ } else {
+ if (filters.get(Constants.RS_INS) == null) {
+ mongoDB.deleteResourceAboutDid(
+ filters.get(Constants.RS_DEVICE_ID),
+ Constants.RD_TABLE);
+ } else {
+ mongoDB.deleteResourceAboutDidAndIns(
+ filters.get(Constants.RS_DEVICE_ID),
+ filters.get(Constants.RS_INS), Constants.RD_TABLE);
+ }
+ CoapResponse response = makeDeleteResponse(request);
+ ctx.writeAndFlush(response);
+ }
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.testrdserver;
+
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import org.iotivity.cloud.base.CoapClient;
+import org.iotivity.cloud.base.CoapServer;
+import org.iotivity.cloud.base.ResourceManager;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.iotivity.cloud.rdserver.Constants;
+import org.iotivity.cloud.rdserver.JSONUtil;
+import org.iotivity.cloud.rdserver.resources.ResourceDirectoryResource;
+import org.iotivity.cloud.util.Cbor;
+import org.junit.Test;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+
+public class RDServerTest {
+
+ private ResourceDirectoryResource rdResource = new ResourceDirectoryResource();
+ private CoapServer coapServer = null;
+ private CoapClient coapClient = null;
+
+ static class CoapClientHandler
+ extends SimpleChannelInboundHandler<CoapResponse> {
+
+ ChannelHandlerContext connectCtx = null;
+
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ connectCtx = ctx;
+ }
+
+ @Override
+ protected void channelRead0(ChannelHandlerContext arg0,
+ CoapResponse arg1) throws Exception {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ public void startServer() throws Exception {
+ coapServer = new CoapServer();
+ ResourceManager resourceManager = new ResourceManager();
+ coapServer.addHandler(resourceManager);
+ resourceManager.registerResource(new ResourceDirectoryResource());
+ coapServer.startServer(new InetSocketAddress(5683));
+ }
+
+ public ChannelHandlerContext startClient() throws Exception {
+ coapClient = new CoapClient();
+ CoapClientHandler coapHandler = new CoapClientHandler();
+ coapClient.addHandler(coapHandler);
+ coapClient.startClient(new InetSocketAddress("127.0.0.1", 5683));
+ return coapHandler.connectCtx;
+ }
+
+ public CoapRequest makePublishPayload() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.POST);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("rt=oic.wk.rdPub");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ ArrayList<Object> payload = new ArrayList<Object>();
+
+ HashMap<Object, Object> tags = new HashMap<Object, Object>();
+ tags.put("di", "98f7483c-5a31-4161-ba7e-9c13e0d");
+ tags.put("bm", (int) 1);
+ tags.put("ttl", (int) 86400);
+
+ ArrayList<LinkedHashMap<Object, Object>> publishLinks = new ArrayList<LinkedHashMap<Object, Object>>();
+ LinkedHashMap<Object, Object> link = new LinkedHashMap<Object, Object>();
+ link.put("href", "/a/light");
+ ArrayList<String> rt = new ArrayList<String>();
+ ArrayList<String> itf = new ArrayList<String>();
+ ArrayList<String> mt = new ArrayList<String>();
+ rt.add("core.light");
+ link.put("rt", rt);
+
+ itf.add("oic.if.baseline");
+ link.put("if", itf);
+
+ mt.add("application/json");
+ link.put("mt", mt);
+
+ link.put("ins", 1);
+
+ publishLinks.add(link);
+
+ payload.add(tags);
+ payload.add(publishLinks);
+
+ Cbor<ArrayList<Object>> cbor = new Cbor<ArrayList<Object>>();
+
+ request.setPayload(cbor.encodingPayloadToCbor(payload));
+
+ return request;
+ }
+
+ @Test
+ public void testHandlePostRequest() throws Exception {
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handlePostRequest(ctx, makePublishPayload());
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+
+ }
+
+ @Test
+ public void testHandleGetRequest_notExistVaule() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.GET);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("rt=core.light");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handleGetRequest(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandleGetRequest_existValue() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.GET);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("rt=core.light");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handlePostRequest(ctx, makePublishPayload());
+
+ rdResource.handleGetRequest(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandleGetRequestBySt_existValue() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.GET);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("rt=core.light&st=didList");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ HashMap<Object, Object> data = new HashMap<Object, Object>();
+ ArrayList<String> didList = new ArrayList<String>();
+ didList.add("98f7483c-5a31-4161-ba7e-9c13e0d");
+ data.put("devices", didList);
+ JSONUtil util = new JSONUtil();
+ byte[] payload = util.writeJSON(data);
+ request.setPayload(payload);
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handlePostRequest(ctx, makePublishPayload());
+
+ rdResource.handleGetRequest(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandleDeleteRequestByDi_notExistVaule() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.DELETE);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("di=98f7483c-5a31-4161-ba7e-9c13e0d");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handlePostRequest(ctx, makePublishPayload());
+
+ rdResource.handleDeleteRequest(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandleDeleteRequestByDi_existVaule() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.DELETE);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("di=98f7483c-5a31-4161-ba7e-9c13e0d");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handleDeleteRequest(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandleDeleteRequestByIns_notExistVaule() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.DELETE);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("di=98f7483c-5a31-4161-ba7e-9c13e0d&ins=1");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handleDeleteRequest(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testHandleDeleteRequestByIns_existVaule() throws Exception {
+
+ CoapRequest request = new CoapRequest(CoapMethod.DELETE);
+ request.setUriPath(Constants.RD_URI);
+ request.setUriQuery("di=98f7483c-5a31-4161-ba7e-9c13e0d&ins=1");
+ request.setToken("1234".getBytes(StandardCharsets.UTF_8));
+
+ startServer();
+ ChannelHandlerContext ctx = startClient();
+
+ rdResource.handlePostRequest(ctx, makePublishPayload());
+
+ rdResource.handleDeleteRequest(ctx, request);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/test/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>CloudStack</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+This project contains the common stack for all server instances.
+
+Build
+
+1) Install Apache Maven if you don't have it
+
+ http://maven.apache.org
+
+2) Build a .jar file
+
+ $ mvn install
+
+ - The CloudStack-0.0.1-SNAPSHOT.jar file will be placed in the "target" folder.
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.iotivity.cloud</groupId>
+ <artifactId>CloudStack</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-all</artifactId>
+ <version>4.0.29.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20140107</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-cbor</artifactId>
+ <version>2.4.0</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <inherited>true</inherited>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.iotivity.cloud.base.protocols.coap.CoapDecoder;
+import org.iotivity.cloud.base.protocols.coap.CoapEncoder;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.util.concurrent.GenericFutureListener;
+
+public class CoapClient {
+
+ private static class CoAPClientInitializer
+ extends ChannelInitializer<SocketChannel> {
+
+ private List<ChannelHandler> additionalHandlers = new ArrayList<ChannelHandler>();
+
+ public CoAPClientInitializer() {
+ }
+
+ public void addHandler(ChannelHandler handler) {
+ additionalHandlers.add(handler);
+ }
+
+ @Override
+ public void initChannel(SocketChannel ch) {
+ ChannelPipeline p = ch.pipeline();
+ /*
+ * if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); }
+ */
+ p.addLast(new CoapDecoder());
+ p.addLast(new CoapEncoder());
+ for (ChannelHandler handler : additionalHandlers) {
+ p.addLast(handler);
+ }
+ }
+ }
+
+ private ChannelFuture channelFuture;
+
+ CoAPClientInitializer initializer = new CoAPClientInitializer();
+
+ public void addHandler(ChannelHandler handler) {
+ initializer.addHandler(handler);
+ }
+
+ public void startClient(final InetSocketAddress inetSocketAddress)
+ throws InterruptedException {
+ // Create bootstrap
+
+ EventLoopGroup bossGroup = new NioEventLoopGroup();
+ // bossGroup = new
+ // EpollEventLoopGroup(Runtime.getRuntime().availableProcessors() * 2);
+
+ try {
+ Bootstrap b = new Bootstrap();
+ b.group(bossGroup);
+ b.channel(NioSocketChannel.class);
+ b.option(ChannelOption.TCP_NODELAY, true);
+ b.option(ChannelOption.SO_KEEPALIVE, true);
+ b.option(ChannelOption.SO_REUSEADDR, true);
+
+ b.handler(initializer);
+
+ channelFuture = b.connect(inetSocketAddress).sync();
+
+ channelFuture
+ .addListener(new GenericFutureListener<ChannelFuture>() {
+ @Override
+ public void operationComplete(ChannelFuture future)
+ throws Exception {
+ System.out.println(
+ "Connection status of TCP CoAP CLIENT : "
+ + future.isSuccess());
+ }
+ });
+ } finally {
+ }
+ }
+
+ public ChannelFuture getChannelFuture() {
+ return channelFuture;
+ }
+
+ public void sendRequest(CoapRequest request) {
+ channelFuture.channel().writeAndFlush(request);
+ }
+
+ /**
+ * stop connection
+ */
+ public void stopClient() {
+
+ try {
+ if (channelFuture != null) {
+ channelFuture.channel().disconnect().sync().addListener(
+ new GenericFutureListener<ChannelFuture>() {
+
+ public void operationComplete(ChannelFuture future)
+ throws Exception {
+ System.out.println(
+ "DisConnection status of TCP CoAP CLIENT : "
+ + future.isSuccess());
+ }
+ });
+ }
+ } catch (InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.net.InetSocketAddress;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.net.ssl.SSLException;
+
+import org.iotivity.cloud.base.protocols.coap.CoapDecoder;
+import org.iotivity.cloud.base.protocols.coap.CoapEncoder;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
+import io.netty.util.concurrent.GenericFutureListener;
+
+public class CoapServer {
+
+ private static class CoAPServerInitializer
+ extends ChannelInitializer<SocketChannel> {
+
+ private List<ChannelHandler> additionalHandlers = new ArrayList<ChannelHandler>();
+
+ public CoAPServerInitializer() {
+ }
+
+ public void addHandler(ChannelHandler handler) {
+ additionalHandlers.add(handler);
+ }
+
+ @Override
+ public void initChannel(SocketChannel ch) {
+ ChannelPipeline p = ch.pipeline();
+ /*
+ * if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); }
+ */
+ p.addLast(new CoapDecoder());
+ p.addLast(new CoapEncoder());
+ for (ChannelHandler handler : additionalHandlers) {
+ p.addLast(handler);
+ }
+ }
+ }
+
+ EventLoopGroup bossGroup = new NioEventLoopGroup(1);
+
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+
+ CoAPServerInitializer initializer = new CoAPServerInitializer();
+
+ public void addHandler(ChannelHandler handler) {
+ initializer.addHandler(handler);
+ }
+
+ public void startServer(InetSocketAddress inetSocketAddress)
+ throws CertificateException, SSLException, InterruptedException {
+
+ try {
+ ServerBootstrap b = new ServerBootstrap();
+ b.group(bossGroup, workerGroup);
+ b.channel(NioServerSocketChannel.class);
+ b.option(ChannelOption.TCP_NODELAY, true);
+ b.option(ChannelOption.SO_KEEPALIVE, true);
+ b.handler(new LoggingHandler(LogLevel.INFO));
+
+ b.childHandler(initializer);
+
+ ChannelFuture ch = b.bind(inetSocketAddress).sync();
+ ch.addListener(new GenericFutureListener<ChannelFuture>() {
+
+ @Override
+ public void operationComplete(ChannelFuture future)
+ throws Exception {
+ // TODO Auto-generated method stub
+ System.out
+ .println("Connection status of TCP CoAP SERVER : "
+ + future.isSuccess());
+ }
+
+ });
+ } finally {
+ }
+
+ }
+
+ public void stopServer() {
+ // shut down all event loops
+ if (bossGroup != null) {
+ bossGroup.shutdownGracefully();
+
+ try {
+ bossGroup.terminationFuture().sync();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ if (workerGroup != null) {
+ workerGroup.shutdownGracefully();
+
+ try {
+ workerGroup.terminationFuture().sync();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.net.ssl.SSLException;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.http.ClientCookieEncoder;
+import io.netty.handler.codec.http.DefaultCookie;
+import io.netty.handler.codec.http.DefaultFullHttpRequest;
+import io.netty.handler.codec.http.HttpClientCodec;
+import io.netty.handler.codec.http.HttpContent;
+import io.netty.handler.codec.http.HttpContentDecompressor;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpObject;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.codec.http.HttpResponse;
+import io.netty.handler.codec.http.HttpVersion;
+import io.netty.handler.codec.http.LastHttpContent;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import io.netty.util.CharsetUtil;
+
+public class HttpClient {
+
+ private static class HttpClientInitializer
+ extends ChannelInitializer<SocketChannel> {
+
+ public static class HttpSnoopClientHandler
+ extends SimpleChannelInboundHandler<HttpObject> {
+
+ @Override
+ public void channelRead0(ChannelHandlerContext ctx,
+ HttpObject msg) {
+ if (msg instanceof HttpResponse) {
+ HttpResponse response = (HttpResponse) msg;
+
+ System.err.println("STATUS: " + response.getStatus());
+ System.err.println(
+ "VERSION: " + response.getProtocolVersion());
+ System.err.println();
+
+ if (!response.headers().isEmpty()) {
+ for (String name : response.headers().names()) {
+ for (String value : response.headers()
+ .getAll(name)) {
+ System.err.println(
+ "HEADER: " + name + " = " + value);
+ }
+ }
+ System.err.println();
+ }
+
+ if (HttpHeaders.isTransferEncodingChunked(response)) {
+ System.err.println("CHUNKED CONTENT {");
+ } else {
+ System.err.println("CONTENT {");
+ }
+ }
+ if (msg instanceof HttpContent) {
+ HttpContent content = (HttpContent) msg;
+
+ System.err.print(
+ content.content().toString(CharsetUtil.UTF_8));
+ System.err.flush();
+
+ if (content instanceof LastHttpContent) {
+ System.err.println("} END OF CONTENT");
+ ctx.close();
+ }
+ }
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx,
+ Throwable cause) {
+ cause.printStackTrace();
+ ctx.close();
+ }
+ }
+
+ private final SslContext sslCtx;
+
+ public HttpClientInitializer(SslContext sslCtx) {
+ this.sslCtx = sslCtx;
+ }
+
+ @Override
+ public void initChannel(SocketChannel ch) {
+ ChannelPipeline p = ch.pipeline();
+
+ // Enable HTTPS if necessary.
+ if (sslCtx != null) {
+ p.addLast(sslCtx.newHandler(ch.alloc()));
+ }
+
+ p.addLast(new HttpClientCodec());
+
+ // Remove the following line if you don't want automatic content
+ // decompression.
+ p.addLast(new HttpContentDecompressor());
+
+ // Uncomment the following line if you don't want to handle
+ // HttpContents.
+ // p.addLast(new HttpObjectAggregator(1048576));
+
+ p.addLast(new HttpSnoopClientHandler());
+ }
+ }
+
+ public void connect(String strUrl)
+ throws URISyntaxException, InterruptedException, SSLException {
+ URI uri = new URI(strUrl);
+
+ String scheme = uri.getScheme() == null ? "http" : uri.getScheme();
+ String host = uri.getHost() == null ? "127.0.0.1" : uri.getHost();
+
+ int port = uri.getPort();
+
+ if (port == -1) {
+ if ("http".equalsIgnoreCase(scheme)) {
+ port = 80;
+ } else if ("https".equalsIgnoreCase(scheme)) {
+ port = 443;
+ }
+ }
+
+ if (!"http".equalsIgnoreCase(scheme)
+ && !"https".equalsIgnoreCase(scheme)) {
+ return;
+ }
+
+ final boolean ssl = "https".equalsIgnoreCase(scheme);
+ final SslContext sslCtx;
+
+ if (ssl) {
+ sslCtx = SslContextBuilder.forClient()
+ .trustManager(InsecureTrustManagerFactory.INSTANCE).build();
+ } else {
+ sslCtx = null;
+ }
+
+ EventLoopGroup group = new NioEventLoopGroup();
+
+ try {
+ Bootstrap b = new Bootstrap();
+ b.group(group);
+ b.channel(NioSocketChannel.class);
+ b.handler(new HttpClientInitializer(sslCtx));
+
+ Channel ch = b.connect(host, port).sync().channel();
+
+ HttpRequest request = new DefaultFullHttpRequest(
+ HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
+ request.headers().set(HttpHeaders.Names.HOST, host);
+ request.headers().set(HttpHeaders.Names.CONNECTION,
+ HttpHeaders.Values.CLOSE);
+ request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING,
+ HttpHeaders.Values.GZIP);
+
+ request.headers().set(HttpHeaders.Names.COOKIE,
+ ClientCookieEncoder.encode(
+ new DefaultCookie("my-cookie", "foo"),
+ new DefaultCookie("another-cookie", "bar")));
+
+ ch.writeAndFlush(request);
+
+ ch.closeFuture().sync();
+ } finally {
+ group.shutdownGracefully();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.net.InetSocketAddress;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.net.ssl.SSLException;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
+import io.netty.util.concurrent.GenericFutureListener;
+
+public class HttpServer {
+
+ private static class HttpServerInitializer
+ extends ChannelInitializer<SocketChannel> {
+
+ private List<ChannelHandler> additionalHandlers = new ArrayList<ChannelHandler>();
+
+ public HttpServerInitializer() {
+ }
+
+ public void addHandler(ChannelHandler handler) {
+ additionalHandlers.add(handler);
+ }
+
+ @Override
+ public void initChannel(SocketChannel ch) {
+ ChannelPipeline p = ch.pipeline();
+ /*
+ * if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); }
+ */
+ p.addLast(new HttpRequestDecoder());
+ // Uncomment the following line if you don't want to handle
+ // HttpChunks.
+ // p.addLast(new HttpObjectAggregator(1048576));
+ p.addLast(new HttpResponseEncoder());
+ // Remove the following line if you don't want automatic content
+ // compression.
+ // p.addLast(new HttpContentCompressor());
+ for (ChannelHandler handler : additionalHandlers) {
+ p.addLast(handler);
+ }
+ }
+
+ }
+
+ EventLoopGroup bossGroup = new NioEventLoopGroup(1);
+
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+
+ HttpServerInitializer initializer = new HttpServerInitializer();
+
+ public void addHandler(ChannelHandler handler) {
+ initializer.addHandler(handler);
+ }
+
+ public void startServer(InetSocketAddress inetSocketAddress)
+ throws CertificateException, SSLException, InterruptedException {
+
+ try {
+ ServerBootstrap b = new ServerBootstrap();
+ b.group(bossGroup, workerGroup);
+ b.channel(NioServerSocketChannel.class);
+ b.handler(new LoggingHandler(LogLevel.INFO));
+
+ b.childHandler(initializer);
+
+ ChannelFuture ch = b.bind(inetSocketAddress).sync();
+ ch.addListener(new GenericFutureListener<ChannelFuture>() {
+
+ @Override
+ public void operationComplete(ChannelFuture future)
+ throws Exception {
+ // TODO Auto-generated method stub
+ System.out
+ .println("Connection status of TCP Http SERVER : "
+ + future.isSuccess());
+ }
+
+ });
+ } finally {
+ }
+
+ }
+
+ public void stopServer() {
+ // shut down all event loops
+ if (bossGroup != null) {
+ bossGroup.shutdownGracefully();
+
+ try {
+ bossGroup.terminationFuture().sync();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ if (workerGroup != null) {
+ workerGroup.shutdownGracefully();
+
+ try {
+ workerGroup.terminationFuture().sync();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+
+import io.netty.channel.ChannelHandlerContext;
+
+public abstract class Resource {
+
+ public Resource() {
+ }
+
+ private String uri;
+ private String type;
+ private String rif; // resource interface
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getRif() {
+ return rif;
+ }
+
+ public void setRif(String rif) {
+ this.rif = rif;
+ }
+
+ public abstract void onRequestReceived(ChannelHandlerContext ctx,
+ CoapRequest request);
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.util.ArrayList;
+
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.util.Logger;
+
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+
+@Sharable
+public class ResourceManager extends SimpleChannelInboundHandler<CoapRequest> {
+
+ private ArrayList<Resource> resources = new ArrayList<Resource>();
+ SessionManager sessionManager = null;
+
+ public ResourceManager() {
+
+ }
+
+ public ResourceManager(SessionManager sessionManager) {
+ this.sessionManager = sessionManager;
+ }
+
+ @Override
+ public void channelReadComplete(ChannelHandlerContext ctx) {
+ ctx.flush();
+ }
+
+ @Override
+ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+ Logger.d("Channel Inactive");
+ sessionManager.removeSessionByChannel(ctx);
+ super.channelInactive(ctx);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+
+ cause.printStackTrace();
+ ctx.close();
+ }
+
+ @Override
+ public void channelRead0(ChannelHandlerContext ctx, CoapRequest request)
+ throws Exception {
+
+ Resource res = queryResourceHandler(request.getUriPath());
+
+ if (res != null) {
+ res.onRequestReceived(ctx, request);
+ }
+ }
+
+ private Resource queryResourceHandler(String query_uri) {
+
+ Resource res = null;
+
+ for (Resource r : resources) {
+
+ String uri = r.getUri();
+ if (uri.contains(query_uri)) {
+ res = r;
+ break;
+ }
+ }
+
+ return res;
+ }
+
+ public void registerResource(Resource res) {
+
+ synchronized (this) {
+ resources.add(res);
+ }
+ }
+
+ public void unregisterResource(Resource res) {
+
+ synchronized (this) {
+ resources.remove(res);
+ }
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.iotivity.cloud.util.Logger;
+
+import io.netty.channel.ChannelHandlerContext;
+
+public class SessionManager {
+
+ HashMap<String, ChannelHandlerContext> sessions = new HashMap<String, ChannelHandlerContext>();
+
+ public void addSession(String did, ChannelHandlerContext ctx) {
+ synchronized (sessions) {
+ sessions.put(did, ctx);
+ }
+ }
+
+ public void removeSession(String did) {
+
+ synchronized (sessions) {
+ sessions.remove(did);
+ }
+ }
+
+ public void removeSessionByChannel(ChannelHandlerContext ctx) {
+ synchronized (sessions) {
+ if (!isThereCtxChannel(ctx)) {
+ Logger.d("Already Session Removed : "
+ + ctx.channel().toString());
+ return;
+ }
+ Iterator<String> iterator = sessions.keySet().iterator();
+ while (iterator.hasNext()) {
+ String key = (String) iterator.next();
+ if (ctx.channel().toString()
+ .equals(querySession(key).channel().toString())) {
+ Logger.d("Session Remove : " + ctx.channel().toString());
+ removeSession(key);
+ break;
+ }
+ }
+ }
+ }
+
+ public ChannelHandlerContext querySession(String did) {
+ ChannelHandlerContext ctx = null;
+
+ synchronized (sessions) {
+ ctx = sessions.get(did);
+ }
+
+ return ctx;
+ }
+
+ public boolean isThereCtx(ChannelHandlerContext ctx) {
+
+ synchronized (sessions) {
+ return sessions.containsValue(ctx);
+ }
+ }
+
+ public boolean isThereCtxChannel(ChannelHandlerContext ctx) {
+
+ synchronized (sessions) {
+ Iterator<String> iterator = sessions.keySet().iterator();
+ while (iterator.hasNext()) {
+ String key = (String) iterator.next();
+ if (ctx.channel().toString()
+ .equals(querySession(key).channel().toString())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public List<String> getSessions() {
+ return new ArrayList<String>(sessions.keySet());
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base.protocols.coap;
+
+import java.util.List;
+
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
+public class CoapDecoder extends ByteToMessageDecoder {
+
+ private enum ParsingState {
+ SHIM_HEADER, OPTION_PAYLOAD_LENGTH, CODE_TOKEN_OPTION, PAYLOAD, FINISH
+ }
+
+ private ParsingState nextState = ParsingState.SHIM_HEADER;
+ private int bufferToRead = 1;
+ private int tokenLength = 0;
+ private int optionPayloadLength = 0;
+ private CoapMessage partialMsg = null;
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in,
+ List<Object> out) throws Exception {
+
+ while (in.isReadable(bufferToRead)) {
+
+ switch (nextState) {
+ case SHIM_HEADER:
+ int shimHeader = in.readByte();
+ bufferToRead = (shimHeader >>> 4) & 0x0F;
+ tokenLength = (shimHeader) & 0x0F;
+ switch (bufferToRead) {
+ case 13:
+ bufferToRead = 1;
+ nextState = ParsingState.OPTION_PAYLOAD_LENGTH;
+ break;
+ case 14:
+ bufferToRead = 2;
+ nextState = ParsingState.OPTION_PAYLOAD_LENGTH;
+ break;
+ case 15:
+ bufferToRead = 4;
+ nextState = ParsingState.OPTION_PAYLOAD_LENGTH;
+ break;
+ default:
+ optionPayloadLength = bufferToRead;
+ bufferToRead += 1 + tokenLength; // code + tkl
+ nextState = ParsingState.CODE_TOKEN_OPTION;
+ break;
+ }
+ break;
+
+ case OPTION_PAYLOAD_LENGTH:
+ switch (bufferToRead) {
+ case 1:
+ optionPayloadLength = 13 + (in.readByte() & 0xFF);
+ break;
+
+ case 2:
+ optionPayloadLength = 269
+ + (((in.readByte() & 0xFF) << 8)
+ + (in.readByte() & 0xFF));
+ break;
+
+ case 4:
+ optionPayloadLength = 65805
+ + (((in.readByte() & 0xFF) << 24)
+ + ((in.readByte() & 0xFF) << 16)
+ + ((in.readByte() & 0xFF) << 8)
+ + (in.readByte() & 0xFF));
+ break;
+ }
+ nextState = ParsingState.CODE_TOKEN_OPTION;
+ bufferToRead = 1 + tokenLength + optionPayloadLength; // code
+ // +
+ // tkl
+ break;
+
+ case CODE_TOKEN_OPTION:
+ int code = in.readByte() & 0xFF;
+
+ if (code <= 31) {
+ partialMsg = new CoapRequest(CoapMethod.valueOf(code));
+ } else {
+ partialMsg = new CoapResponse(CoapStatus.valueOf(code));
+ }
+
+ if (tokenLength > 0) {
+ byte[] token = new byte[tokenLength];
+ in.readBytes(token);
+ partialMsg.setToken(token);
+ }
+
+ if (optionPayloadLength > 0) {
+ int optionLen = parseOptions(partialMsg, in,
+ optionPayloadLength);
+ if (optionPayloadLength > optionLen) {
+ nextState = ParsingState.PAYLOAD;
+ bufferToRead = optionPayloadLength - optionLen;
+ continue;
+ }
+ }
+
+ nextState = ParsingState.FINISH;
+ bufferToRead = 0;
+
+ break;
+
+ case PAYLOAD:
+ byte[] payload = new byte[bufferToRead];
+ in.readBytes(payload);
+ partialMsg.setPayload(payload);
+ nextState = ParsingState.FINISH;
+ bufferToRead = 0;
+ break;
+
+ case FINISH:
+ nextState = ParsingState.SHIM_HEADER;
+ bufferToRead = 1;
+ out.add(partialMsg);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ in.discardReadBytes();
+ }
+
+ private int parseOptions(CoapMessage coapMessage, ByteBuf byteBuf,
+ int maxLength) {
+
+ int preOptionNum = 0;
+
+ int startPos = byteBuf.readerIndex();
+
+ int firstByte = byteBuf.readByte() & 0xFF;
+
+ while (firstByte != 0xFF && maxLength > 0) {
+ int optionDelta = (firstByte & 0xF0) >>> 4;
+ int optionLength = firstByte & 0x0F;
+
+ if (optionDelta == 13) {
+ optionDelta = 13 + byteBuf.readByte() & 0xFF;
+ } else if (optionDelta == 14) {
+ optionDelta = 269 + ((byteBuf.readByte() & 0xFF) << 8)
+ + (byteBuf.readByte() & 0xFF);
+ }
+
+ if (optionLength == 13) {
+ optionLength = 13 + byteBuf.readByte() & 0xFF;
+ } else if (optionLength == 14) {
+ optionLength = 269 + ((byteBuf.readByte() & 0xFF) << 8)
+ + (byteBuf.readByte() & 0xFF);
+ }
+
+ int curOptionNum = preOptionNum + optionDelta;
+ byte[] optionValue = new byte[optionLength];
+ byteBuf.readBytes(optionValue);
+
+ coapMessage.addOption(curOptionNum, optionValue);
+
+ preOptionNum = curOptionNum;
+ if (maxLength > byteBuf.readerIndex() - startPos) {
+ firstByte = byteBuf.readByte() & 0xFF;
+ } else {
+ break;
+ }
+ }
+
+ /// return option length
+ return byteBuf.readerIndex() - startPos;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base.protocols.coap;
+
+import java.util.List;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToByteEncoder;
+
+public class CoapEncoder extends MessageToByteEncoder<CoapMessage> {
+
+ @Override
+ protected void encode(ChannelHandlerContext ctx, CoapMessage msg,
+ ByteBuf out) throws Exception {
+
+ CoapMessage coapMessage = (CoapMessage) msg;
+
+ ByteBuf optBuf = Unpooled.directBuffer();
+
+ /**
+ * encode options
+ */
+ encodeOptions(optBuf, coapMessage);
+ long length = optBuf.readableBytes();
+
+ if (coapMessage.getPayloadSize() > 0) {
+ // + 1 means 8bits delimiter
+ length += 1 + coapMessage.getPayloadSize();
+ }
+
+ calcShimHeader(coapMessage, out, length);
+
+ out.writeByte(coapMessage.getCode());
+
+ if (coapMessage.getTokenLength() > 0) {
+ out.writeBytes(coapMessage.getToken());
+ }
+
+ // Write option
+ if (optBuf.readableBytes() > 0) {
+ out.writeBytes(optBuf);
+ }
+
+ optBuf.release();
+
+ if (coapMessage.getPayloadSize() > 0) {
+ out.writeByte(255);
+ out.writeBytes(coapMessage.getPayload());
+ }
+ }
+
+ private void calcShimHeader(CoapMessage coapMessage, ByteBuf byteBuf,
+ long length) {
+ if (length < 13) {
+ byteBuf.writeByte(((int) length & 0x0F) << 4
+ | (coapMessage.getTokenLength() & 0x0F));
+ } else if (length < 269) {
+ byteBuf.writeShort((13 & 0x0F) << 12
+ | (coapMessage.getTokenLength() & 0x0F) << 8
+ | (((int) length - 13) & 0xFF));
+ } else if (length < 65805) {
+ byteBuf.writeByte(
+ (14 & 0x0F) << 4 | (coapMessage.getTokenLength() & 0x0F));
+ byteBuf.writeShort(((int) length - 269) & 0xFFFF);
+ } else if (length < Integer.MAX_VALUE * 2) {
+ byteBuf.writeByte(
+ (15 & 0x0F) << 4 | (coapMessage.getTokenLength() & 0x0F));
+ byteBuf.writeLong((length - 65805) & 0xFFFFFFFF);
+ } else {
+ throw new IllegalArgumentException(
+ "Length must be less than 4GB " + length);
+ }
+ }
+
+ private void encodeOptions(ByteBuf byteBuf, CoapMessage coapMessage)
+ throws Exception {
+ int preOptionNum = 0;
+
+ for (int i = 0; i < 40; i++) {
+ List<byte[]> values = coapMessage.getOption(i);
+ if (values != null) {
+ for (byte[] value : values) {
+ writeOption(i - preOptionNum,
+ value != null ? value.length : 0, byteBuf, value);
+ preOptionNum = i;
+ }
+ }
+ }
+ }
+
+ private void writeOption(int optionDelta, int optionLength, ByteBuf byteBuf,
+ byte[] value) {
+
+ if (optionDelta < 13) {
+ if (optionLength < 13) {
+ byteBuf.writeByte(
+ ((optionDelta & 0xFF) << 4) | (optionLength & 0xFF));
+ } else if (optionLength < 269) {
+ byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (13 & 0xFF));
+ byteBuf.writeByte((optionLength - 13) & 0xFF);
+ } else {
+ byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (14 & 0xFF));
+ byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
+ byteBuf.writeByte((optionLength - 269) & 0xFF);
+ }
+ }
+
+ else if (optionDelta < 269) {
+ if (optionLength < 13) {
+ byteBuf.writeByte(((13 & 0xFF) << 4) | (optionLength & 0xFF));
+ byteBuf.writeByte((optionDelta - 13) & 0xFF);
+ } else if (optionLength < 269) {
+ byteBuf.writeByte(((13 & 0xFF) << 4) | (13 & 0xFF));
+ byteBuf.writeByte((optionDelta - 13) & 0xFF);
+ byteBuf.writeByte((optionLength - 13) & 0xFF);
+ } else {
+ byteBuf.writeByte((13 & 0xFF) << 4 | (14 & 0xFF));
+ byteBuf.writeByte((optionDelta - 13) & 0xFF);
+ byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
+ byteBuf.writeByte((optionLength - 269) & 0xFF);
+ }
+ }
+
+ else if (optionDelta < 65805) {
+
+ if (optionLength < 13) {
+ byteBuf.writeByte(((14 & 0xFF) << 4) | (optionLength & 0xFF));
+ byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
+ byteBuf.writeByte((optionDelta - 269) & 0xFF);
+ }
+
+ else if (optionLength < 269) {
+ byteBuf.writeByte(((14 & 0xFF) << 4) | (13 & 0xFF));
+ byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
+ byteBuf.writeByte((optionDelta - 269) & 0xFF);
+ byteBuf.writeByte((optionLength - 13) & 0xFF);
+ }
+
+ else {
+ byteBuf.writeByte(((14 & 0xFF) << 4) | (14 & 0xFF));
+ byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
+ byteBuf.writeByte((optionDelta - 269) & 0xFF);
+ byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
+ byteBuf.writeByte((optionLength - 269) & 0xFF);
+ }
+ } else {
+ throw new IllegalArgumentException(
+ "Unsupported option delta " + optionDelta);
+ }
+
+ if (optionLength > 0) {
+ byteBuf.writeBytes(value);
+ }
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base.protocols.coap;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.iotivity.cloud.base.protocols.coap.enums.CoapOption;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Logger;
+
+public class CoapMessage {
+
+ private int tokenLength = 0;
+ protected int code = 0;
+ private byte[] token = null;
+
+ private byte[] payload = null;
+
+ // Option fields
+ protected List<byte[]> if_match = null;
+ protected byte[] uri_host = null;
+ protected List<byte[]> etag = null;
+ protected boolean if_none_match = false;
+ protected byte[] uri_port = null;
+ protected List<byte[]> location_path = null;
+ protected List<byte[]> uri_path = null;
+ protected byte[] content_format = null;
+ protected byte[] max_age = null;
+ protected List<byte[]> uri_query = null;
+ protected byte[] accept = null;
+ protected List<byte[]> location_query = null;
+ protected byte[] proxy_uri = null;
+ protected byte[] proxy_scheme = null;
+ protected byte[] size1 = null;
+ protected boolean observe = false;
+
+ public CoapMessage() {
+ }
+
+ public int getTokenLength() {
+ return this.tokenLength;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public byte[] getToken() {
+ return token;
+ }
+
+ public void setToken(byte[] token) {
+ this.token = token;
+ this.tokenLength = token.length;
+ }
+
+ public int getPayloadSize() {
+ return payload == null ? 0 : payload.length;
+ }
+
+ public byte[] getPayload() {
+ return payload;
+ }
+
+ public void setPayload(byte[] payload) {
+ this.payload = payload;
+ }
+
+ public void addOption(int optnum, byte[] value) {
+ switch (optnum) {
+ // IF_MATCH
+ case 1:
+ if (if_match == null) {
+ if_match = new ArrayList<byte[]>();
+ }
+ if_match.add(value);
+ break;
+
+ // URI_HOST
+ case 3:
+ uri_host = value;
+ break;
+
+ // ETAG
+ case 4:
+ if (etag == null) {
+ etag = new ArrayList<byte[]>();
+ }
+ etag.add(value);
+ break;
+
+ // IF_NONE_MATCH
+ case 5:
+ if_none_match = true;
+ break;
+
+ // URI_PORT
+ case 7:
+ uri_port = value;
+ break;
+
+ // LOCATION_PATH
+ case 8:
+ if (location_path == null) {
+ location_path = new ArrayList<byte[]>();
+ }
+ location_path.add(value);
+ break;
+
+ // URI_PATH
+ case 11:
+ if (uri_path == null) {
+ uri_path = new ArrayList<byte[]>();
+ }
+ uri_path.add(value);
+ break;
+
+ // CONTENT_FORMAT
+ case 12:
+ content_format = value;
+ break;
+
+ // MAX_AGE
+ case 14:
+ max_age = value;
+ break;
+
+ // URI_QUERY
+ case 15:
+ if (uri_query == null) {
+ uri_query = new ArrayList<byte[]>();
+ }
+ uri_query.add(value);
+ break;
+
+ // ACCEPT
+ case 17:
+ accept = value;
+ break;
+
+ // LOCATION_QUERY
+ case 20:
+ if (location_query == null) {
+ location_query = new ArrayList<byte[]>();
+ }
+ location_query.add(value);
+ break;
+
+ // PROXY_URI
+ case 35:
+ proxy_uri = value;
+ break;
+
+ // PROXY_SCHEME
+ case 39:
+ proxy_scheme = value;
+ break;
+
+ // SIZE1
+ case 60:
+ size1 = value;
+ break;
+
+ // OBSERVE
+ case 6:
+ observe = true;
+ break;
+ }
+ }
+
+ public List<byte[]> getOption(int optnum) {
+ switch (optnum) {
+ // IF_MATCH
+ case 1:
+ return if_match;
+
+ // URI_HOST
+ case 3:
+ return uri_host != null ? Arrays.asList(uri_host) : null;
+
+ // ETAG
+ case 4:
+ return etag;
+
+ // IF_NONE_MATCH
+ case 5:
+ return if_none_match == true ? new ArrayList<byte[]>() : null;
+
+ // URI_PORT
+ case 7:
+ return uri_port != null ? Arrays.asList(uri_port) : null;
+
+ // LOCATION_PATH
+ case 8:
+ return location_path;
+
+ // URI_PATH
+ case 11:
+ return uri_path;
+
+ // CONTENT_FORMAT
+ case 12:
+ return content_format != null ? Arrays.asList(content_format)
+ : null;
+
+ // MAX_AGE
+ case 14:
+ return max_age != null ? Arrays.asList(max_age) : null;
+
+ // URI_QUERY
+ case 15:
+ return uri_query;
+
+ // ACCEPT
+ case 17:
+ return accept != null ? Arrays.asList(content_format) : null;
+
+ // LOCATION_QUERY
+ case 20:
+ return location_query;
+
+ // PROXY_URI
+ case 35:
+ return proxy_uri != null ? Arrays.asList(proxy_uri) : null;
+
+ // PROXY_SCHEME
+ case 39:
+ return proxy_scheme != null ? Arrays.asList(proxy_scheme)
+ : null;
+
+ // SIZE1
+ case 60:
+ return size1 != null ? Arrays.asList(size1) : null;
+
+ // OBSERVE
+ case 6:
+ return observe == true ? new ArrayList<byte[]>() : null;
+ }
+
+ return null;
+ }
+
+ public String getTokenString() {
+ StringBuffer strBuffer = new StringBuffer(token == null ? "null" : "");
+ if (token != null)
+ for (byte b : token)
+ strBuffer.append(String.format("%02x", b & 0xff)); // hexadecimal(16)
+ return strBuffer.toString();
+ }
+
+ public String getContentFormatString() {
+ List<byte[]> contentFormatList = getOption(
+ CoapOption.CONTENT_FORMAT.getvalue());
+ byte[] contentFormat = null;
+ if (contentFormatList != null && !contentFormatList.isEmpty())
+ contentFormat = contentFormatList.get(0);
+ StringBuffer strBuffer = new StringBuffer(
+ contentFormat == null ? "null" : "");
+ if (contentFormat != null)
+ for (byte b : contentFormat)
+ strBuffer.append(String.format("%02d", b & 0xff)); // decimal(10)
+ return strBuffer.toString();
+ }
+
+ public String getPayloadString() {
+ if (payload == null)
+ return "";
+ return new String(payload, Charset.forName("UTF-8"));
+ }
+
+ public String decodeDeviceId() {
+ Cbor<ArrayList<Object>> cbor = new Cbor<ArrayList<Object>>();
+ ArrayList<Object> decodedPayload = null;
+
+ if (payload == null) {
+ throw new IllegalArgumentException("payload is null");
+ }
+
+ else {
+ decodedPayload = cbor.parsePayloadFromCbor(payload,
+ ArrayList.class);
+
+ HashMap<Object, Object> tags = (HashMap<Object, Object>) decodedPayload
+ .get(0);
+
+ String deviceId = tags.get("di").toString();
+
+ if (deviceId == null) {
+ throw new IllegalArgumentException("deviceId is null");
+ }
+
+ Logger.i("deviceId : " + deviceId);
+
+ return deviceId;
+ }
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base.protocols.coap;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+
+public class CoapRequest extends CoapMessage {
+ public CoapRequest(CoapMethod method) {
+ this.code = method.getCode();
+ }
+
+ public CoapMethod getRequestMethod() {
+ return CoapMethod.valueOf(code);
+ }
+
+ public void setUriPath(String path) {
+ if (uri_path == null) {
+ uri_path = new ArrayList<byte[]>();
+ }
+ clearUriPath();
+
+ String[] pathSegments = path.split("/");
+ for (String pathSegment : pathSegments) {
+ if (pathSegment.length() == 0)
+ continue;
+ uri_path.add(pathSegment.getBytes(StandardCharsets.UTF_8));
+ }
+ }
+
+ public String getUriPath() {
+ if (uri_path == null) {
+ return null;
+ }
+ StringBuilder path = new StringBuilder();
+ int nItem = uri_path.size();
+ for (byte[] pathSegment : uri_path) {
+ path.append(new String(pathSegment, StandardCharsets.UTF_8));
+ if (--nItem > 0) {
+ path.append('/');
+ }
+ }
+ return path.toString();
+ }
+
+ public List<String> getUriPathSegments() {
+ List<String> segments = new ArrayList<String>();
+ if (uri_path != null) {
+ for (byte[] pathSegment : uri_path) {
+ segments.add(new String(pathSegment, StandardCharsets.UTF_8));
+ }
+ }
+ return segments;
+ }
+
+ public void setUriQuery(String query) {
+ if (uri_query == null) {
+ uri_query = new ArrayList<byte[]>();
+ }
+ String[] querySegments = query.split("&");
+ for (String querySegment : querySegments) {
+ uri_query.add(querySegment.getBytes(StandardCharsets.UTF_8));
+ }
+ }
+
+ public String getUriQuery() {
+ if (uri_query == null) {
+ return null;
+ }
+ StringBuilder uriQuery = new StringBuilder();
+ int nItem = uri_query.size();
+ for (byte[] querySegment : uri_query) {
+ uriQuery.append(new String(querySegment, StandardCharsets.UTF_8));
+ if (--nItem > 0) {
+ uriQuery.append('&');
+ }
+ }
+ return uriQuery.toString();
+ }
+
+ public List<String> getUriQuerySegments() {
+ List<String> segments = new ArrayList<String>();
+ for (byte[] querySegment : uri_query) {
+ segments.add(new String(querySegment, StandardCharsets.UTF_8));
+ }
+ return segments;
+ }
+
+ public void clearUriPath() {
+ uri_path.clear();
+ }
+
+ public void setAccept(byte[] accepts) {
+ accept = accepts;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base.protocols.coap;
+
+import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+
+public class CoapResponse extends CoapMessage {
+ public CoapResponse(CoapStatus status) {
+ this.code = status.getCode();
+ }
+
+ public CoapStatus getResponseCode() {
+ return CoapStatus.valueOf(code);
+ }
+}
--- /dev/null
+package org.iotivity.cloud.base.protocols.coap.enums;
+
+public enum CoapMethod {
+ GET(1), POST(2), PUT(3), DELETE(4);
+
+ public static CoapMethod valueOf(int code) {
+ switch (code) {
+ case 1:
+ return CoapMethod.GET;
+
+ case 2:
+ return CoapMethod.POST;
+
+ case 3:
+ return CoapMethod.PUT;
+
+ case 4:
+ return CoapMethod.DELETE;
+ }
+
+ throw new IllegalArgumentException("Invalid Method value");
+ }
+
+ private final int code;
+
+ private CoapMethod(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+}
--- /dev/null
+package org.iotivity.cloud.base.protocols.coap.enums;
+
+public enum CoapOption {
+ IF_MATCH(1), URI_HOST(3), ETAG(4), IF_NONE_MATCH(5), URI_PORT(
+ 7), LOCATION_PATH(8), URI_PATH(11), CONTENT_FORMAT(12), MAX_AGE(
+ 14), URI_QUERY(15), ACCEPT(17), LOCATION_QUERY(
+ 20), PROXY_URI(35), PROXY_SCHEME(39), SIZE1(
+ 60), OBSERVE(6);
+
+ public static CoapOption valueOf(int option) {
+ switch (option) {
+ case 1:
+ return CoapOption.IF_MATCH;
+
+ case 3:
+ return CoapOption.URI_HOST;
+
+ case 4:
+ return CoapOption.ETAG;
+
+ case 5:
+ return CoapOption.IF_NONE_MATCH;
+
+ case 7:
+ return CoapOption.URI_PORT;
+
+ case 8:
+ return CoapOption.LOCATION_PATH;
+
+ case 11:
+ return CoapOption.URI_PATH;
+
+ case 12:
+ return CoapOption.CONTENT_FORMAT;
+
+ case 14:
+ return CoapOption.MAX_AGE;
+
+ case 15:
+ return CoapOption.URI_QUERY;
+
+ case 17:
+ return CoapOption.ACCEPT;
+
+ case 20:
+ return CoapOption.LOCATION_QUERY;
+
+ case 35:
+ return CoapOption.PROXY_URI;
+
+ case 39:
+ return CoapOption.PROXY_SCHEME;
+
+ case 60:
+ return CoapOption.SIZE1;
+
+ case 6:
+ return CoapOption.OBSERVE;
+ }
+
+ throw new IllegalArgumentException("Invalid option value");
+ }
+
+ private final int value;
+
+ private CoapOption(int value) {
+ this.value = value;
+ }
+
+ public int getvalue() {
+ return value;
+ }
+}
--- /dev/null
+package org.iotivity.cloud.base.protocols.coap.enums;
+
+public enum CoapStatus {
+ // Success 2.xx
+ CREATED(65), DELETED(66), VALID(67), CHANGED(68), CONTENT(69),
+ // Client Error 4.xx
+ BAD_REQUEST(128), UNAUTHORIZED(129), BAD_OPTION(130), FORBIDDEN(131),
+ //
+ NOT_FOUND(132), METHOD_NOT_ALLOWED(133), NOT_ACCEPTABLE(134),
+ //
+ PRECONDITION_FAILED(140), REQUEST_ENTITY_TOO_LARGE(141),
+ //
+ UNSUPPORTED_CONTENT_FORMAT(143),
+ // Server Error 5.xx
+ INTERNAL_SERVER_ERROR(160), NOT_IMPLEMENTED(161), BAD_GATEWAY(162),
+ //
+ SERVICE_UNAVAILABLE(163), GATEWAY_TIMEOUT(164), PROXY_NOT_SUPPORTED(165);
+
+ public static CoapStatus valueOf(int code) {
+ switch (code) {
+ case 65:
+ return CoapStatus.CREATED;
+
+ case 66:
+ return CoapStatus.DELETED;
+
+ case 67:
+ return CoapStatus.VALID;
+
+ case 68:
+ return CoapStatus.CHANGED;
+
+ case 69:
+ return CoapStatus.CONTENT;
+
+ case 128:
+ return CoapStatus.BAD_REQUEST;
+
+ case 129:
+ return CoapStatus.UNAUTHORIZED;
+
+ case 130:
+ return CoapStatus.BAD_OPTION;
+
+ case 131:
+ return CoapStatus.FORBIDDEN;
+
+ case 132:
+ return CoapStatus.NOT_FOUND;
+
+ case 133:
+ return CoapStatus.METHOD_NOT_ALLOWED;
+
+ case 134:
+ return CoapStatus.NOT_ACCEPTABLE;
+
+ case 140:
+ return CoapStatus.PRECONDITION_FAILED;
+
+ case 141:
+ return CoapStatus.REQUEST_ENTITY_TOO_LARGE;
+
+ case 143:
+ return CoapStatus.UNSUPPORTED_CONTENT_FORMAT;
+
+ case 160:
+ return CoapStatus.INTERNAL_SERVER_ERROR;
+
+ case 161:
+ return CoapStatus.NOT_IMPLEMENTED;
+
+ case 162:
+ return CoapStatus.BAD_GATEWAY;
+
+ case 163:
+ return CoapStatus.SERVICE_UNAVAILABLE;
+
+ case 164:
+ return CoapStatus.GATEWAY_TIMEOUT;
+
+ case 165:
+ return CoapStatus.PROXY_NOT_SUPPORTED;
+ }
+
+ throw new IllegalArgumentException("Invalid Status value");
+ }
+
+ private final int code;
+
+ private CoapStatus(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base.protocols.proxy;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.iotivity.cloud.base.SessionManager;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.CoapResponse;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Logger;
+
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.codec.http.HttpResponse;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+import io.netty.handler.codec.http.QueryStringDecoder;
+import io.netty.util.AttributeKey;
+import io.netty.util.CharsetUtil;
+
+@Sharable
+public class CoapHttpProxyHandler extends ChannelDuplexHandler {
+
+ // Proxy converts http request to coaprequest and coapresponse to
+ // httpresponse
+ private SessionManager sessionManager = null;
+
+ private static final AttributeKey<ChannelHandlerContext> keyHttpCtx = AttributeKey
+ .newInstance("httpCtx");
+
+ public CoapHttpProxyHandler(SessionManager sessionManager) {
+ this.sessionManager = sessionManager;
+ }
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg)
+ throws Exception {
+
+ // in case of Receive Request from http
+ if (msg instanceof HttpRequest) {
+ // Check uri query param that contains coap device uuid
+ // then search those and create coapRequest and send
+ HttpRequest httpRequest = (HttpRequest) msg;
+ QueryStringDecoder queryStringDecoder = new QueryStringDecoder(
+ httpRequest.getUri());
+
+ List<String> didList = queryStringDecoder.parameters().get("di");
+
+ if (didList != null) {
+ ChannelHandlerContext coapClient = sessionManager
+ .querySession(didList.get(0));
+
+ if (coapClient != null) {
+ List<String> uriList = queryStringDecoder.parameters()
+ .get("href");
+ if (uriList != null) {
+ coapClient.channel().attr(keyHttpCtx).set(ctx);
+ coapClient.writeAndFlush(httpRequestToCoAPRequest(
+ uriList.get(0), (HttpRequest) msg));
+
+ return;
+ }
+ } else {
+ Logger.d("Unable to find session: " + didList.get(0));
+ }
+ }
+
+ // Prints available sessions to html
+
+ ctx.writeAndFlush(printsAvailableSessions())
+ .addListener(ChannelFutureListener.CLOSE);
+ return;
+ }
+
+ if (msg instanceof CoapResponse) {
+ ctx.channel().attr(keyHttpCtx).get()
+ .writeAndFlush(
+ coapResponseToHttpResponse((CoapResponse) msg))
+ .addListener(ChannelFutureListener.CLOSE);
+ return;
+ }
+
+ // Pass to upper-layer
+ super.channelRead(ctx, msg);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ cause.printStackTrace();
+ ctx.close();
+ }
+
+ HttpResponse printsAvailableSessions() {
+
+ StringBuilder strBuilder = new StringBuilder();
+ List<String> sessions = sessionManager.getSessions();
+
+ strBuilder.append("<html>");
+ strBuilder.append("<b>Available sessions</b><br>");
+
+ for (String session : sessions) {
+ strBuilder.append(session);
+ strBuilder.append("<br>");
+ }
+
+ strBuilder.append("</html>");
+
+ HttpResponse response = new DefaultFullHttpResponse(
+ HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
+ Unpooled.copiedBuffer(strBuilder.toString(),
+ CharsetUtil.UTF_8));
+ response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
+ "text/html; charset=UTF-8");
+
+ return response;
+ }
+
+ HttpResponse httpRequestToSendError() {
+ HttpResponse response = new DefaultFullHttpResponse(
+ HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND,
+ Unpooled.copiedBuffer(
+ "Failure: " + HttpResponseStatus.NOT_FOUND + "\r\n",
+ CharsetUtil.UTF_8));
+ response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
+ "text/html; charset=UTF-8");
+
+ return response;
+ }
+
+ CoapRequest httpRequestToCoAPRequest(String uri, HttpRequest httpRequest) {
+ CoapRequest coapRequest;
+
+ // TODO: coapRequest converter required
+ // coapRequest.getOptions().setUriQuery();
+ if (httpRequest.getMethod() == HttpMethod.GET) {
+ coapRequest = new CoapRequest(CoapMethod.GET);
+ } else if (httpRequest.getMethod() == HttpMethod.PUT) {
+ coapRequest = new CoapRequest(CoapMethod.PUT);
+ } else if (httpRequest.getMethod() == HttpMethod.POST) {
+ coapRequest = new CoapRequest(CoapMethod.POST);
+ } else if (httpRequest.getMethod() == HttpMethod.DELETE) {
+ coapRequest = new CoapRequest(CoapMethod.DELETE);
+ } else {
+ throw new IllegalArgumentException();
+ }
+
+ coapRequest.setUriPath(uri);
+
+ return coapRequest;
+ }
+
+ HttpResponse coapResponseToHttpResponse(CoapResponse coapResponse) {
+
+ Cbor<HashMap<String, Object>> cbor = new Cbor<HashMap<String, Object>>();
+
+ HashMap<String, Object> rep = cbor
+ .parsePayloadFromCbor(coapResponse.getPayload(), HashMap.class);
+
+ StringBuilder strBuilder = new StringBuilder();
+
+ for (Entry<String, Object> entry : rep.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue().toString();
+ strBuilder.append("Key: " + key + " Value: " + value + "<br>");
+ }
+
+ HttpResponse httpResponse = new DefaultFullHttpResponse(
+ HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
+ Unpooled.wrappedBuffer(strBuilder.toString().getBytes(StandardCharsets.UTF_8)));
+
+ httpResponse.headers().set(HttpHeaders.Names.CONTENT_TYPE,
+ "text/html; charset=UTF-8");
+
+ // TODO: httpResponse converter required
+
+ return httpResponse;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.util;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
+
+public class Cbor<T> {
+ private CBORFactory f;
+ private ObjectMapper mapper;
+
+ public Cbor() {
+ f = new CBORFactory();
+ mapper = new ObjectMapper(f);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T parsePayloadFromCbor(byte[] cborPayload,
+ Class<? extends Object> class1) {
+ T payload = null;
+ try {
+ payload = (T) mapper.readValue(cborPayload, class1);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return payload;
+ }
+
+ public byte[] encodingPayloadToCbor(Object payload) {
+ byte[] cborData = null;
+ try {
+ cborData = mapper.writeValueAsBytes(payload);
+ } catch (JsonProcessingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return cborData;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.util;
+
+import org.iotivity.cloud.base.protocols.coap.CoapMessage;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+
+/**
+ *
+ * This class provides a set of APIs to print out logs for CoAP request and
+ * response.
+ *
+ */
+@Sharable
+public class CoapLogHandler extends ChannelDuplexHandler {
+
+ @Override
+ public void write(ChannelHandlerContext ctx, Object msg,
+ ChannelPromise promise) {
+
+ if (msg instanceof CoapMessage) {
+
+ CoapMessage coapMessage = (CoapMessage) msg;
+
+ StringBuilder strBuilder = new StringBuilder();
+ strBuilder.append(getStringCtx(ctx));
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ strBuilder.append(getStringCoapMessage(coapMessage));
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ Logger.d(strBuilder.toString());
+
+ } else if (msg instanceof String) {
+
+ String message = (String) msg;
+
+ StringBuilder strBuilder = new StringBuilder();
+ strBuilder.append(getStringCtx(ctx));
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ strBuilder.append(message);
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ Logger.d(strBuilder.toString());
+
+ ByteBuf outByteBuf = ctx.alloc().buffer();
+ outByteBuf.writeBytes(message.getBytes());
+ }
+
+ ctx.write(msg);
+ }
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg)
+ throws Exception {
+
+ if (msg instanceof CoapMessage) {
+
+ CoapMessage coapMessage = (CoapMessage) msg;
+
+ StringBuilder strBuilder = new StringBuilder();
+ strBuilder.append(getStringCtx(ctx));
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ strBuilder.append(getStringCoapMessage(coapMessage));
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ Logger.d(strBuilder.toString());
+
+ } else if (msg instanceof ByteBuf) {
+
+ ByteBuf inByteBuf = (ByteBuf) msg;
+
+ String message = null;
+ StringBuffer strBuffer = new StringBuffer();
+ while (inByteBuf.isReadable()) {
+ strBuffer.append((char) inByteBuf.readByte());
+ }
+ message = strBuffer.toString();
+
+ StringBuilder strBuilder = new StringBuilder();
+ strBuilder.append(getStringCtx(ctx));
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ strBuilder.append(message);
+ strBuilder.append(
+ "\n/******************************************************************************/\n");
+ Logger.d(strBuilder.toString());
+ }
+
+ ctx.fireChannelRead(msg);
+ }
+
+ private String getStringCtx(ChannelHandlerContext ctx) {
+
+ StringBuilder strBuilder = new StringBuilder();
+
+ strBuilder.append("\n");
+ strBuilder.append("Local Address: ");
+ strBuilder.append(ctx.channel().localAddress().toString());
+
+ strBuilder.append("\n");
+ strBuilder.append("Remote Address: ");
+ strBuilder.append(ctx.channel().remoteAddress().toString());
+
+ return strBuilder.toString();
+ }
+
+ private String getStringCoapMessage(CoapMessage coapMessage) {
+
+ StringBuilder strBuilder = new StringBuilder();
+
+ strBuilder.append("Code: ");
+ strBuilder.append(coapMessage.getCode());
+ strBuilder.append("\n");
+
+ strBuilder.append("Token Length: ");
+ strBuilder.append(coapMessage.getTokenLength());
+ strBuilder.append("\n");
+
+ strBuilder.append("Token Data: ");
+ strBuilder.append(coapMessage.getTokenString());
+ strBuilder.append("\n");
+
+ if (coapMessage instanceof CoapRequest) {
+
+ CoapRequest coapRequest = (CoapRequest) coapMessage;
+
+ strBuilder.append("Option URI_PATH: ");
+ strBuilder.append(coapRequest.getUriPath());
+ strBuilder.append("\n");
+
+ strBuilder.append("Option URI_QUERY: ");
+ strBuilder.append(coapRequest.getUriQuery());
+ strBuilder.append("\n");
+ }
+
+ strBuilder.append("Option CONTENT_FORMAT: ");
+ strBuilder.append(coapMessage.getContentFormatString());
+ strBuilder.append("\n");
+
+ strBuilder.append("Payload Length: ");
+ strBuilder.append(coapMessage.getPayloadSize());
+
+ strBuilder.append("\n");
+ strBuilder.append("Payload Data: ");
+ strBuilder.append(coapMessage.getPayloadString());
+
+ return strBuilder.toString();
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.util;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ *
+ * This class provides utility for parsing JSON object and converting data to
+ * JSON string.
+ *
+ */
+public class JSONUtil {
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ public static String parseJSON(String jsonString, String key) {
+
+ if (jsonString == null || jsonString.equals(""))
+ return null;
+
+ String value = null;
+
+ try {
+ @SuppressWarnings("unchecked")
+ Map<String, String> jsonMap = mapper.readValue(jsonString,
+ Map.class);
+ value = jsonMap.get(key);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+
+ return value;
+ }
+
+ public static Map<String, String> parseJSON(String jsonString)
+ throws JsonParseException, JsonMappingException, IOException {
+
+ Map<String, String> map = null;
+
+ try {
+ @SuppressWarnings("unchecked")
+ Map<String, String> jsonMap = mapper.readValue(jsonString,
+ Map.class);
+ map = jsonMap;
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+
+ return map;
+ }
+
+ public static String writeJSON(HashMap<Object, Object> data) {
+ if (data == null)
+ return null;
+
+ String json = null;
+ try {
+ json = mapper.writeValueAsString(data);
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+
+ if (json == null)
+ json = "{}";
+
+ return json;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+public class Logger {
+
+ public static final int VERBOSE = 0;
+ public static final int DEBUG = 1;
+ public static final int INFO = 2;
+ public static final int WARNING = 3;
+ public static final int ERROR = 4;
+
+ private static int logLevel = DEBUG;
+
+ public static void setLogLevel(int level) {
+ logLevel = level;
+ }
+
+ public static void v(String log) {
+ printLog(VERBOSE, log);
+ }
+
+ public static void d(String log) {
+ printLog(DEBUG, log);
+ }
+
+ public static void i(String log) {
+ printLog(INFO, log);
+ }
+
+ public static void w(String log) {
+ printLog(WARNING, log);
+ }
+
+ public static void e(String log) {
+ printLog(ERROR, log);
+ }
+
+ public static void w(String log, Exception ex) {
+ printLog(WARNING, log);
+ ex.printStackTrace();
+ }
+
+ public static void w(String log, Throwable th) {
+ printLog(WARNING, log);
+ th.printStackTrace();
+ }
+
+ public static void e(String log, Exception ex) {
+ printLog(ERROR, log);
+ ex.printStackTrace();
+ }
+
+ public static void e(String log, Throwable th) {
+ printLog(ERROR, log);
+ th.printStackTrace();
+ }
+
+ private static void printLog(int level, String log) {
+
+ if (logLevel > level)
+ return;
+
+ String format = "";
+ format += getTime();
+ format += " [" + getLogLevelString(level) + "]";
+
+ if (level >= ERROR) {
+ format += " [" + getDetailInfo() + "]";
+ }
+
+ format += " " + log;
+
+ System.out.println(format);
+ }
+
+ private static String getDetailInfo() {
+
+ String res = "";
+
+ StackTraceElement ste = Thread.currentThread().getStackTrace()[4];
+ String className = ste.getClassName()
+ .substring(ste.getClassName().lastIndexOf(".") + 1);
+
+ res += ste.getFileName() + ", " + className + "." + ste.getMethodName()
+ + "(), line:" + ste.getLineNumber();
+
+ return res;
+ }
+
+ private static String getTime() {
+ Calendar calendar = Calendar.getInstance();
+ SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSS");
+
+ return dateFormat.format(calendar.getTime());
+ }
+
+ private static String getLogLevelString(int level) {
+
+ String res = "";
+
+ if (level == VERBOSE) {
+ res = "V";
+ } else if (level == DEBUG) {
+ res = "D";
+ } else if (level == INFO) {
+ res = "I";
+ } else if (level == WARNING) {
+ res = "W";
+ } else if (level == ERROR) {
+ res = "E";
+ }
+
+ return res;
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.util;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+
+public class Net {
+
+ public static String getMyIpAddress() {
+
+ try {
+ for (Enumeration<NetworkInterface> en = NetworkInterface
+ .getNetworkInterfaces(); en.hasMoreElements();) {
+ NetworkInterface intf = en.nextElement();
+ for (Enumeration<InetAddress> enumIpAddr = intf
+ .getInetAddresses(); enumIpAddr.hasMoreElements();) {
+ InetAddress inetAddress = enumIpAddr.nextElement();
+ if (!inetAddress.isLoopbackAddress()
+ && !inetAddress.isLinkLocalAddress()
+ && inetAddress.isSiteLocalAddress()) {
+ return inetAddress.toString();
+ }
+ }
+ }
+ } catch (SocketException ex) {
+ Logger.e("SocketException", ex);
+ }
+
+ return "";
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.net.InetSocketAddress;
+
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
+import org.junit.Test;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+
+public class CoapClientTest {
+
+ private static class CoapHandler
+ extends SimpleChannelInboundHandler<CoapRequest> {
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, CoapRequest msg)
+ throws Exception {
+ // TODO Auto-generated method stub
+ }
+ }
+
+ @Test
+ public void testAddHandler() throws Exception {
+ CoapServer coapServer = new CoapServer();
+ coapServer.startServer(new InetSocketAddress(5683));
+ CoapClient coapClient = new CoapClient();
+ coapClient.startClient(new InetSocketAddress("127.0.0.1", 5683));
+ coapClient.addHandler(new CoapHandler());
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testAddHandlerSendRequest() throws Exception {
+ CoapServer coapServer = new CoapServer();
+ coapServer.startServer(new InetSocketAddress(5683));
+
+ CoapClient coapClient = new CoapClient();
+ coapClient.startClient(new InetSocketAddress("127.0.0.1", 5683));
+ coapClient.addHandler(new CoapHandler());
+
+ CoapRequest request = new CoapRequest(CoapMethod.GET);
+ coapClient.sendRequest(request);
+
+ CoapRequest request2 = new CoapRequest(CoapMethod.GET);
+ request2.setToken("1234".getBytes());
+ coapClient.sendRequest(request2);
+
+ CoapRequest request3 = new CoapRequest(CoapMethod.GET);
+ request3.setPayload("sample1".getBytes());
+ coapClient.sendRequest(request3);
+
+ CoapRequest request4 = new CoapRequest(CoapMethod.GET);
+ request4.setToken("5576".getBytes());
+ request4.setPayload("sample2".getBytes());
+ coapClient.sendRequest(request4);
+
+ CoapRequest request5 = new CoapRequest(CoapMethod.GET);
+ request5.setToken("565761".getBytes());
+ coapClient.sendRequest(request5);
+
+ CoapRequest request6 = new CoapRequest(CoapMethod.GET);
+ coapClient.sendRequest(request6);
+
+ CoapRequest request7 = new CoapRequest(CoapMethod.GET);
+ coapClient.sendRequest(request7);
+
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testStartStopClient() throws Exception {
+ CoapServer coapServer = new CoapServer();
+ coapServer.startServer(new InetSocketAddress(5683));
+ CoapClient coapClient = new CoapClient();
+ coapClient.startClient(new InetSocketAddress("127.0.0.1", 5683));
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+
+ @Test
+ public void testSendRequest() throws Exception {
+ CoapServer coapServer = new CoapServer();
+ coapServer.startServer(new InetSocketAddress(5683));
+ CoapClient coapClient = new CoapClient();
+ coapClient.startClient(new InetSocketAddress("127.0.0.1", 5683));
+ CoapRequest request = new CoapRequest(CoapMethod.GET);
+ coapClient.sendRequest(request);
+ coapClient.stopClient();
+ coapServer.stopServer();
+ }
+}
--- /dev/null
+/*
+ * //******************************************************************
+ * //
+ * // Copyright 2016 Samsung Electronics All Rights Reserved.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //
+ * // Licensed under the Apache License, Version 2.0 (the "License");
+ * // you may not use this file except in compliance with the License.
+ * // You may obtain a copy of the License at
+ * //
+ * // http://www.apache.org/licenses/LICENSE-2.0
+ * //
+ * // Unless required by applicable law or agreed to in writing, software
+ * // distributed under the License is distributed on an "AS IS" BASIS,
+ * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * // See the License for the specific language governing permissions and
+ * // limitations under the License.
+ * //
+ * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.cloud.base;
+
+import java.net.InetSocketAddress;
+
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+import org.junit.Test;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+
+public class CoapServerTest {
+ private static class CoapHandler
+ extends SimpleChannelInboundHandler<CoapRequest> {
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, CoapRequest msg)
+ throws Exception {
+ // TODO Auto-generated method stub
+ }
+ }
+
+ @Test
+ public void testAddHandler() throws Exception {
+ CoapServer server = new CoapServer();
+ server.startServer(new InetSocketAddress(5683));
+ server.addHandler(new CoapHandler());
+ server.stopServer();
+ }
+
+ @Test
+ public void testStartStopServer() throws Exception {
+ CoapServer server = new CoapServer();
+ server.startServer(new InetSocketAddress(5683));
+ server.stopServer();
+ }
+}