MoteHost: Cleanup fdset related variables in serviceLoop()
[remote/remote-mci.git] / mcs / Session.cc
blob56ac3c1a334b1c485c63926a0518a51791affcc1
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 session 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 = " << session_id;
93 query.execute();
94 query.reset();
95 authenticated = false;
98 bool Session::isAuthenticated()
100 if (authenticated) return true;
101 // look up and verify the authentication in the database
102 mysqlpp::Connection& sqlConn = dbConn.getConnection();
103 mysqlpp::Result res;
104 mysqlpp::Query query = sqlConn.query();
106 query << "select auth from session where id = " << session_id;
107 res = query.store();
109 if ( res.num_rows() == 1 )
111 authenticated = res.at(0)["auth"];
113 query.reset();
115 if (authenticated){ log("Client authenticated!\n");}
116 else { log("Client not authenticated!\n"); }
117 return authenticated;
120 void Session::freeMote(dbkey_t mote_id)
122 Message message;
123 motemapbykey_t::iterator mi;
124 mi = motes.find(mote_id);
125 if ( mi != motes.end() )
127 motes.erase(mi);
128 MsgClientConfirm confirm( MSGCLIENTCOMMAND_DROPMOTECONTROL, SUCCESS, mote_id );
129 ClientMsg clientMsg(confirm);
130 message.sendMsg(fd,clientMsg);
134 void Session::confirm(dbkey_t mote_id, MsgPayload& moteMsg)
136 Message message;
137 MsgClientConfirm confirm( MSGCLIENTCOMMAND_MOTEMESSAGE, SUCCESS, mote_id, moteMsg );
138 ClientMsg clientMsg(confirm);
140 try {
141 message.sendMsg(fd,clientMsg);
143 catch (remote::protocols::MMSException e)
145 log("Exception: %s\n",e.what());
146 this->destroy();
150 void Session::handleEvent(short events)
152 if ( (events & POLLHUP) || (events & POLLNVAL) ) __THROW__ ("Client connection closed by peer!");
153 if ( (events & POLLIN) || (events & POLLPRI) )
155 // no input is accepted before external authorization
156 if ( !isAuthenticated() )
158 __THROW__ ("Client not authenticated!\n");
161 // wait for an entire message before continuing
162 if (!message_in.nonBlockingRecv(fd))
164 return;
167 uint32_t msglen = message_in.getLength();
168 uint8_t* buffer = message_in.getData();
169 ClientMsg msg(buffer,msglen);
171 switch (msg.getType())
173 case CLIENTMSG_CLIENTREQUEST:
175 MsgClientRequest& msgClientRequest = msg.getClientRequest();
176 handleClientRequest(msgClientRequest);
177 break;
179 default:
180 __THROW__ ("Invalid message type from client!");
181 break;
185 else if ( (events & POLLERR) || (events & POLLHUP) || (events & POLLNVAL) )
187 __THROW__ ("Client connection closed.\n");
191 void Session::handleClientRequest(MsgClientRequest& request)
193 dbkey_t mote_id;
194 motemapbykey_t::const_iterator mi;
195 MsgMoteIdList& idlist = request.getMoteIdList();
197 while( idlist.getNextMoteId(mote_id) )
199 // check the session id
200 switch ( request.getCommand() )
202 case MSGCLIENTCOMMAND_GETMOTECONTROL:
203 getMoteControl(mote_id);
204 break;
205 case MSGCLIENTCOMMAND_DROPMOTECONTROL:
206 dropMoteControl(mote_id);
207 break;
208 case MSGCLIENTCOMMAND_MOTEMESSAGE:
209 handleMoteRequest(mote_id,request.getMoteMsg());
210 break;
211 default:
212 __THROW__ ("Got unknown request from client.\n");
213 break;
219 void Session::handleMoteRequest(dbkey_t mote_id,MsgPayload& request)
222 motemapbykey_t::const_iterator mi;
224 mi = motes.find(mote_id);
226 if ( mi != motes.end() )
228 mi->second->request(request);
230 else
232 MsgClientConfirm confirm( MSGCLIENTCOMMAND_MOTEMESSAGE, MOTE_NOT_CONTROLLED, mote_id );
233 ClientMsg msg(confirm);
234 Message message;
235 message.sendMsg(fd,msg);
239 void Session::getMoteControl( dbkey_t mote_id )
241 Message message;
242 Mote* mote;
243 // figure out which mote is referred to
244 Mote::getById(mote_id,this,&mote);
246 if (mote)
248 motes[mote_id] = mote;
249 MsgClientConfirm confirm( MSGCLIENTCOMMAND_GETMOTECONTROL, SUCCESS, mote_id );
250 ClientMsg msg(confirm);
251 message.sendMsg(fd,msg);
252 } else
254 MsgClientConfirm confirm( MSGCLIENTCOMMAND_GETMOTECONTROL, FAILURE, mote_id );
255 ClientMsg msg(confirm);
256 message.sendMsg(fd,msg);
260 void Session::dropMoteControl(dbkey_t mote_id)
262 Message message;
263 motemapbykey_t::const_iterator mi;
265 mi = motes.find(mote_id);
267 if ( mi != motes.end() )
269 mi->second->dropSession();
270 // dropSession should invoke freeMote that confirms the drop request
272 else
274 MsgClientConfirm confirm( MSGCLIENTCOMMAND_DROPMOTECONTROL, MOTE_NOT_CONTROLLED, mote_id );
275 ClientMsg msg(confirm);
276 message.sendMsg(fd,msg);