Initial commit
[remote/remote-mci.git] / mcs / Session.cc
blobc5745f1be90da83aa05d0ef6b456830e0ec5d794
1 #include "Session.h"
2 #include "macros.h"
4 namespace remote { namespace mcs {
6 Session::Session(int p_fd, sessionmapbyfd_t& p_clientMap )
7 : FileDescriptor(p_fd),
8 authenticated(false),
9 message_in(),
10 sessionMap(p_clientMap)
12 sessionMap[fd] = this;
13 setSendTimeout( fd,0,500000); // 0.5 second host send timeout should be adequate
14 // set keepalive options
15 setKeepAlive( fd, 3, 120, 30);
16 createSessionRecord();
19 Session::~Session()
21 log("Closing client connection!\n");
22 sessionMap.erase(fd);
23 deleteSessionRecord();
26 void Session::destroy(bool silent)
29 motemapbykey_t::iterator mi;
30 // release any controlled motes
31 for ( mi = motes.begin() ; mi != motes.end(); mi++ )
33 try
35 if (mi->second) mi->second->dropSession(false);
37 catch (mysqlpp::Exception e) // don't throw exceptions while destructing
39 if (silent)
41 log("Exception while dropping mote client: %s - record not updated!\n",e.what());
43 else
45 __THROW__(e.what());
50 delete this;
53 void Session::resetDb()
55 mysqlpp::Connection& sqlConn = dbConn.getConnection();
56 mysqlpp::Query reset = sqlConn.query();
57 reset << "delete from session";
58 reset.parse();
59 reset.execute();
62 void Session::createSessionRecord()
64 // create a session record for this connection
65 mysqlpp::Connection& sqlConn = dbConn.getConnection();
66 mysqlpp::Result res;
67 mysqlpp::Query query = sqlConn.query();
68 query << "insert into session(auth) values (0)";
69 query.parse();
70 mysqlpp::ResNSel sqlres = query.execute();
71 if (sqlres.success)
73 session_id = sqlres.insert_id;
74 Message message;
75 MsgSession msgSession(session_id);
76 ClientMsg msg(msgSession);
77 message.sendMsg(fd,msg);
79 else
81 delete this;
82 __THROW__ ("Failed to insert new mote in database!\n");
84 query.reset();
87 void Session::deleteSessionRecord()
89 mysqlpp::Connection& sqlConn = dbConn.getConnection();
90 mysqlpp::Result res;
91 mysqlpp::Query query = sqlConn.query();
92 query << "delete from session where id = '%0:session_id'";
93 query.parse();
94 query.def["session_id"] = session_id;
95 query.execute();
96 query.reset();
97 authenticated = false;
100 bool Session::isAuthenticated()
102 if (authenticated) return true;
103 // look up and verify the authentication in the database
104 mysqlpp::Connection& sqlConn = dbConn.getConnection();
105 mysqlpp::Result res;
106 mysqlpp::Query query = sqlConn.query();
108 query << "select auth from session where id = '%0:session_id'";
109 query.parse();
110 query.def["session_id"] = session_id;
111 res = query.store();
113 if ( res.num_rows() == 1 )
115 authenticated = res.at(0)["auth"];
117 query.reset();
119 if (authenticated){ log("Client authenticated!\n");}
120 else { log("Client not authenticated!\n"); }
121 return authenticated;
124 void Session::freeMote(dbkey_t mote_id)
126 Message message;
127 motemapbykey_t::iterator mi;
128 mi = motes.find(mote_id);
129 if ( mi != motes.end() )
131 motes.erase(mi);
132 MsgClientConfirm confirm( MSGCLIENTCOMMAND_DROPMOTECONTROL, SUCCESS, mote_id );
133 ClientMsg clientMsg(confirm);
134 message.sendMsg(fd,clientMsg);
138 void Session::confirm(dbkey_t mote_id, MsgPayload& moteMsg)
140 Message message;
141 MsgClientConfirm confirm( MSGCLIENTCOMMAND_MOTEMESSAGE, SUCCESS, mote_id, moteMsg );
142 ClientMsg clientMsg(confirm);
144 try {
145 message.sendMsg(fd,clientMsg);
147 catch (remote::protocols::MMSException e)
149 log("Exception: %s\n",e.what());
150 this->destroy();
154 void Session::handleEvent(short events)
156 if ( (events & POLLHUP) || (events & POLLNVAL) ) __THROW__ ("Client connection closed by peer!");
157 if ( (events & POLLIN) || (events & POLLPRI) )
159 // no input is accepted before external authorization
160 if ( !isAuthenticated() )
162 __THROW__ ("Client not authenticated!\n");
165 // wait for an entire message before continuing
166 if (!message_in.nonBlockingRecv(fd))
168 return;
171 uint32_t msglen = message_in.getLength();
172 uint8_t* buffer = message_in.getData();
173 ClientMsg msg(buffer,msglen);
175 switch (msg.getType())
177 case CLIENTMSG_CLIENTREQUEST:
179 MsgClientRequest& msgClientRequest = msg.getClientRequest();
180 handleClientRequest(msgClientRequest);
181 break;
183 default:
184 __THROW__ ("Invalid message type from client!");
185 break;
189 else if ( (events & POLLERR) || (events & POLLHUP) || (events & POLLNVAL) )
191 __THROW__ ("Client connection closed.\n");
195 void Session::handleClientRequest(MsgClientRequest& request)
197 dbkey_t mote_id;
198 motemapbykey_t::const_iterator mi;
199 MsgMoteIdList& idlist = request.getMoteIdList();
201 while( idlist.getNextMoteId(mote_id) )
203 // check the session id
204 switch ( request.getCommand() )
206 case MSGCLIENTCOMMAND_GETMOTECONTROL:
207 getMoteControl(mote_id);
208 break;
209 case MSGCLIENTCOMMAND_DROPMOTECONTROL:
210 dropMoteControl(mote_id);
211 break;
212 case MSGCLIENTCOMMAND_MOTEMESSAGE:
213 handleMoteRequest(mote_id,request.getMoteMsg());
214 break;
215 default:
216 __THROW__ ("Got unknown request from client.\n");
217 break;
223 void Session::handleMoteRequest(dbkey_t mote_id,MsgPayload& request)
226 motemapbykey_t::const_iterator mi;
228 mi = motes.find(mote_id);
230 if ( mi != motes.end() )
232 mi->second->request(request);
234 else
236 MsgClientConfirm confirm( MSGCLIENTCOMMAND_MOTEMESSAGE, MOTE_NOT_CONTROLLED, mote_id );
237 ClientMsg msg(confirm);
238 Message message;
239 message.sendMsg(fd,msg);
243 void Session::getMoteControl( dbkey_t mote_id )
245 Message message;
246 Mote* mote;
247 // figure out which mote is referred to
248 Mote::getById(mote_id,this,&mote);
250 if (mote)
252 motes[mote_id] = mote;
253 MsgClientConfirm confirm( MSGCLIENTCOMMAND_GETMOTECONTROL, SUCCESS, mote_id );
254 ClientMsg msg(confirm);
255 message.sendMsg(fd,msg);
256 } else
258 MsgClientConfirm confirm( MSGCLIENTCOMMAND_GETMOTECONTROL, FAILURE, mote_id );
259 ClientMsg msg(confirm);
260 message.sendMsg(fd,msg);
264 void Session::dropMoteControl(dbkey_t mote_id)
266 Message message;
267 motemapbykey_t::const_iterator mi;
269 mi = motes.find(mote_id);
271 if ( mi != motes.end() )
273 mi->second->dropSession();
274 // dropSession should invoke freeMote that confirms the drop request
276 else
278 MsgClientConfirm confirm( MSGCLIENTCOMMAND_DROPMOTECONTROL, MOTE_NOT_CONTROLLED, mote_id );
279 ClientMsg msg(confirm);
280 message.sendMsg(fd,msg);
285 /*void Session::handleAuthRequest(MsgAuthRequest& authReq)
287 Message message;
288 msg_out.type = SERVERMSG_AUTHORIZECONFIRM;
289 mysqlpp::Connection& sqlConn = dbConn.getConnection();
290 // look up and verify the credentials in the database
291 mysqlpp::Result res;
292 mysqlpp::Query query = sqlConn.query();
294 query << "select up.id user_project_id, up.user_id,up.project_id \
295 from user_project up, user u, project p \
296 where p.name ='%0:project' \
297 and u.login ='%1:username' \
298 and u.password=md5('%2:password') \
299 and up.user_id = u.id \
300 and up.project_id = p.id";
303 query.parse();
304 query.def["project"] = *(new std::string(authReq.getProject().getString()));
305 query.def["username"] = *(new std::string(authReq.getUsername().getString()));
306 query.def["password"] = *(new std::string(authReq.getPassword().getString()));
308 res = query.store();
310 if ( res.num_rows() != 1 )
312 msg_out.getAuthConfirm().result = FAILURE;
313 log("Client not authorized!\n");
315 else
317 user_id = res.at(0)["user_id"];
318 project_id = res.at(0)["project_id"];
319 user_project_id = res.at(0)["user_project_id"];
320 authorized = true;
321 msg_out.getAuthConfirm().result = SUCCESS;
322 log("Client authorized!\n");
324 query.reset();
325 message.sendMsg(fd,msg_out);