Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / examples / OICMiddle / RestInput.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "WrapResource.h"
22 #include "RestInput.h"
23 #include "LineInput.h"
24 #include "OICMiddle.h"
25
26 using namespace std;
27
28 #define BUFLEN 10000
29
30 static bool enableDebug = false; // set to true to print debug messages
31
32 void printDebugMessage(std::string message)
33 {
34     if (enableDebug) {
35         cout << "RestInput: " << message  << endl;
36     }
37 }
38
39 RestInput::RestInput(LineInput *lineInput) : m_lineInput(lineInput)
40 {
41     m_data = (char*)malloc(BUFLEN);
42     m_threadCount = 0;
43 }
44
45 RestInput::~RestInput()
46 {
47     free(m_data);
48     close(m_sockfd);
49 }
50
51 bool RestInput::init()
52 {
53     m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
54     if (m_sockfd < 0) {
55         cerr << "Failed to open socket. Exiting" << endl;
56         return false;
57     }
58     m_port = 1441; //listening on port 1441
59
60     m_serverAddr.sin_family = AF_INET;
61     m_serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
62     m_serverAddr.sin_port = htons(m_port);
63
64     if (::bind(m_sockfd, (struct sockaddr*)&m_serverAddr, sizeof m_serverAddr) < 0) {
65         cerr << "Failed to bind. Exiting " << endl;
66         return false;
67     }
68
69     listen(m_sockfd, MAX_CONNS);
70     startAccept(m_sockfd);
71     return true;
72 }
73
74 // accept incoming connection(s)
75 void RestInput::startAccept(int &sockfd)
76 {
77     if (m_threadCount >= MAX_CONNS) {
78         cerr << " Max # of connections reached. Skipping " << endl;
79         return;
80     } else {
81         while (true) {
82             int connfd = accept(sockfd, (struct sockaddr *)NULL, NULL);
83             if (connfd < 0) {
84                 cerr << " Failed to accept incoming connection " << endl;
85                 return;
86             }
87             int n = read(connfd, m_data, BUFLEN);
88             close(connfd);
89             if (n < 0) {
90                 cerr << "Failed to read from socket" << endl;
91                 return;
92             }
93             startThread();
94         }
95     }
96 }
97
98 // start client thread
99 void RestInput::startThread()
100 {
101     std::thread t(&RestInput::processClient, this);
102     m_thread[m_threadCount] = std::move(t);
103     m_thread[m_threadCount++].join();
104 }
105
106 // process read commands for the client
107 void RestInput::processClient(void)
108 {
109     std::string restCmd = m_data;
110     std::size_t found = restCmd.find('\n');
111     if (found != std::string::npos) {
112         restCmd = restCmd.substr(0, found-1);
113     }
114     handleRead(restCmd);
115 }
116
117 void RestInput::handleRead(std::string& restCmd)
118 {
119     parseString(restCmd);
120     if (restCmd.find("exit") == 0) {
121         std::thread::id id = std::this_thread::get_id();
122         for(int i = 0; i < m_threadCount; ++i) {
123             if (id == m_thread[i].get_id()) {
124                 m_thread[i].detach();
125                 --m_threadCount;
126                 cout << "Exiting thread " << id << endl;
127             }
128         }
129         return;
130     }
131     stringstream ss;
132     observecb_t cb;
133     std::string msg = "command sent to LineInput is: " + restCmd;
134     printDebugMessage(msg);
135     m_lineInput->processLine(restCmd, ss, cb);
136     if (restCmd.find("show") != string::npos) {
137         // if command is show, we want to list out the details of each resource
138         handleShow(ss, cb);
139     }
140 }
141
142 void RestInput::handleShow(stringstream &ss, observecb_t &cb) {
143     std::string temp = ss.str();
144     size_t n = std::count(temp.begin(), temp.end(), '\n'); // number of resources found
145     std::stringstream sstm;
146     std::string lineInputData;
147
148     for (size_t i = 0; i < n; ++i) {
149         sstm.str("");
150         sstm << "details " << i;
151         lineInputData = sstm.str();
152         std::string msg = "Details: " + lineInputData;
153         printDebugMessage(msg);
154         m_lineInput->processLine(lineInputData, ss, cb);
155         sstm.str("");
156         sstm << "get " << i;
157         lineInputData = sstm.str();
158         msg = "Get: " + lineInputData;
159         printDebugMessage(msg);
160         m_lineInput->processLine(lineInputData, ss, cb);
161     }
162 }
163
164 void RestInput::parseString(std::string &toParse)
165 {
166     std::size_t pos = toParse.find("HTTP"); // split on HTTP
167     toParse = toParse.substr(0, pos);
168     pos = toParse.find("/"); // find 1st occurance of /
169     toParse = toParse.substr(pos + 1, toParse.size() - 1);
170     std::replace(toParse.begin(), toParse.end(), '/', ' '); // replace all '/' with ' '
171 }