11 #include "ClientMgr.h"
17 using namespace forest;
27 int main(
int argc,
char *argv[]) {
28 ipa_t
nmIp,
myIp; uint32_t finTime = 0;
33 (sscanf(argv[3],
"%d", &finTime)) != 1)
34 fatal(
"usage: ClientMgr nmIp myIp fintime");
36 if (!
init(nmIp, myIp))
37 fatal(
"init: Failed to initialize ClientMgr");
51 bool init(ipa_t nmIp1, ipa_t myIp1) {
52 nmIp = nmIp1; myIp = myIp1;
59 logger->
log(
"ClientMgr::init: could not initialize "
71 if (!
sub->init())
return false;
72 sub->setRtrReady(
true);
79 logger->
log(
"ClientMgr::init: could not read clientData "
87 int n =
cliTbl->getMaxClx();
91 for (
int clx = 0; clx <= n; clx++)
writeRecord(clx);
94 logger->
log(
"ClientMgr::init: could not initialize lock "
95 "on client data file",2);
99 acctFile.open(
"acctRecords",fstream::app);
101 logger->
log(
"ClientMgr::init: could not open acctRecords "
129 if (bootSock < 0)
return false;
137 CtlPkt cp(CtlPkt::BOOT_LEAF,CtlPkt::REQUEST,1,p.payload());
138 int plen = cp.
pack();
139 if (plen == 0) { close(bootSock);
return false; }
149 ipa_t srcIp; ipp_t srcPort;
152 if (now > resendTime) {
155 close(bootSock);
return false;
157 resendTime += 1000000;
162 if (nbytes < 0)
continue;
167 logger->
log(
"unexpected response to boot request",
169 close(bootSock);
return false;
172 if (repCp.
type != CtlPkt::CONFIG_LEAF ||
173 repCp.
mode != CtlPkt::REQUEST) {
174 logger->
log(
"unexpected response from NetMgr",2,reply);
175 close(bootSock);
return false;
179 myAdr = repCp.adr1; rtrAdr = repCp.adr2;
180 rtrIp = repCp.ip1; rtrPort = repCp.port1;
185 repCp.
reset(CtlPkt::CONFIG_LEAF,CtlPkt::POS_REPLY,repCp.
seqNum,
188 if (plen == 0) { close(bootSock);
return false; }
194 close(bootSock);
return false;
202 if (now > resendTime) {
205 close(bootSock);
return false;
207 resendTime += 1000000;
211 if (nbytes < 0) { usleep(100000);
continue; }
214 logger->
log(
"unexpected response to boot request",
216 close(bootSock);
return false;
220 if (repCp.
type == CtlPkt::CONFIG_LEAF &&
221 repCp.
mode == CtlPkt::REQUEST) {
223 repCp.
reset(CtlPkt::CONFIG_LEAF,CtlPkt::POS_REPLY,
226 if (plen == 0) { close(bootSock);
return false; }
233 close(bootSock);
return false;
235 }
else if (repCp.
type != CtlPkt::BOOT_LEAF ||
236 repCp.
mode != CtlPkt::POS_REPLY) {
237 logger->
log(
"unexpected response from NetMgr",
239 close(bootSock);
return false;
243 close(bootSock);
return true;
262 bool success =
false;
272 cerr <<
"handler, got packet " << p.
toString(s) << endl;
275 case CtlPkt::CLIENT_CONNECT:
276 case CtlPkt::CLIENT_DISCONNECT:
280 cph.errReply(px,cp,
"invalid control packet "
281 "type for ClientMgr");
286 cerr <<
"handler: operation failed\n"
305 string cmd, reply, clientName;
309 if (!buf.readLine(cmd) || cmd !=
"Forest-login-v1") {
316 while (buf.readAlphas(cmd)) {
317 cerr <<
"cmd=" << cmd << endl;
321 buf.nextLine();
continue;
322 }
else if (cmd ==
"overAndOut") {
323 buf.nextLine();
return true;
324 }
else if (cmd ==
"login") {
325 loggedIn =
login(buf,clientName,reply);
326 }
else if (cmd ==
"newAccount") {
328 }
else if (!loggedIn) {
330 }
else if (cmd ==
"newSession") {
332 }
else if (cmd ==
"getProfile") {
334 }
else if (cmd ==
"updateProfile") {
336 }
else if (cmd ==
"changePassword") {
338 }
else if (cmd ==
"uploadPhoto") {
340 }
else if (cmd ==
"getSessions") {
342 }
else if (cmd ==
"cancelSession") {
343 cancelSession(buf,clientName,cph,reply);
344 }
else if (cmd ==
"cancelAllSessions") {
346 }
else if (cmd ==
"addComtree" && buf.nextLine()) {
347 addComtree(buf,clientName,reply);
349 reply =
"unrecognized input";
351 cerr <<
"sending reply: " << reply << endl;
356 cerr <<
"terminating" << endl;
377 reply =
"login failed: try again";
380 cerr <<
"login succeeded " << clientName << endl;
385 reply =
"login failed: try again";
389 reply =
"misformatted login request";
413 reply =
"name not available, select another";
422 reply =
"unable to add client";
426 reply =
"misformatted new account request";
443 string& clientName,
string& reply) {
447 if (!buf.readRspec(rs) || !buf.
nextLine() ||
448 !buf.
readLine(s1) || s1 !=
"over") {
449 reply =
"misformatted new session request";
454 reply =
"misformatted new session request";
460 reply =
"cannot access client data(" + clientName +
")";
467 reply =
"session rate exceeds available capacity";
475 pktx rpx = cph.
newSession(nmAdr, clientIp, rs, repCp);
478 reply =
"cannot update client data(" + clientName +
")";
479 logger->
log(
"ClientMgr::newSession: cannot update session data "
480 "session state may be inconsistent",2);
486 reply =
"cannot setup session: NetMgr never responded";
490 if (repCp.
mode != CtlPkt::POS_REPLY) {
493 reply =
"cannot setup new session: NetMgr failed (" +
501 reply =
"cannot setup new session: could not create "
518 stringstream ss;
string s;
521 <<
"," << repCp.port1 <<
",";
524 ss <<
"connectNonce: " << repCp.
nonce <<
"\noverAndOut\n";
546 if (clx == 0)
return 0;
549 if (priv != ClientTable::ADMIN && priv != ClientTable::ROOT)
return 0;
553 if (tclx == 0)
return 0;
555 if (priv == ClientTable::ADMIN &&
556 (tpriv == ClientTable::ADMIN || tpriv == ClientTable::ROOT)) {
572 string s, targetName;
575 reply =
"misformatted get profile request";
return;
579 reply =
"insufficient privileges for requested operation";
599 string s, targetName;
602 reply =
"misformatted updateProfile request";
return;
606 string realName, email;
RateSpec defRates, totRates;
608 if (item ==
"realName" && buf.
verify(
':') &&
611 }
else if (item ==
"email" && buf.
verify(
':') &&
614 }
else if (item ==
"defRates" && buf.
verify(
':') &&
615 buf.readRspec(defRates) && buf.
nextLine()) {
617 }
else if (item ==
"totalRates" && buf.
verify(
':') &&
618 buf.readRspec(totRates) && buf.
nextLine()) {
620 }
else if (item ==
"over" && buf.
nextLine()) {
623 reply =
"misformatted update profile request (" +
630 reply =
"insufficient privileges for requested operation";
636 if (tpriv != ClientTable::LIMITED) {
637 if (defRates.isSet() &&
640 if (totRates.isSet() &&
659 string targetName, pwd;
662 reply =
"misformatted change password request";
return;
666 reply =
"insufficient privileges for requested operation";
688 reply =
"misformatted upload photo request";
return;
690 if (length > 50000) {
691 reply =
"photo file exceeds 50000 byte limit";
return;
695 string photoName =
"clientPhotos/"; photoName += clientName +
".jpg";
696 photoFile.open(photoName.c_str(), ofstream::binary);
697 if (!photoFile.good()) {
698 reply =
"cannot open photo file";
return;
705 int n = buf.
readBlock(xbuf,min(1000,length-numRcvd));
707 photoFile.write(xbuf,n);
709 if (numRcvd == length)
break;
711 if (numRcvd != length) {
712 reply =
"could not transfer complete file";
return;
715 if (!buf.
readLine(s1) || s1 !=
"photo finished" ||
716 !buf.
readLine(s2) || s2 !=
"over") {
717 reply =
"misformatted photo request";
return;
730 string s, targetName;
733 reply =
"misformatted get sessions request";
return;
737 reply =
"insufficient privileges for requested operation";
748 reply.erase(reply.end()-1);
762 string s, targetName, cancelAdrStr;
766 reply =
"misformatted cancel session request";
return;
769 if (cancelAdr == 0) {
770 reply =
"misformatted address";
return;
774 reply =
"insufficient privileges for requested operation";
780 reply =
"invalid session address";
return;
783 reply =
"session address belongs to another client";
return;
792 pktx rpx = cph.
cancelSession(nmAdr, cancelAdr, rtrAdr, repCp);
794 reply =
"cannot cancel session: NetMgr never responded";
798 if (repCp.
mode != CtlPkt::POS_REPLY) {
799 reply =
"cannot complete cancelSession: NetMgr failed (" +
805 reply =
"cannot update session data for " + targetName;
806 logger->
log(
"ClientMgr::cancelSession: cannot update session "
807 "data session state may be inconsistent",2);
825 string s, targetName;
828 reply =
"misformatted cancel all sessions request";
return;
832 reply =
"insufficient privileges for requested operation";
845 reply =
"cannot cancel session: NetMgr never responded";
849 if (repCp.
mode != CtlPkt::POS_REPLY) {
850 reply =
"cannot complete cancelSession: NetMgr failed "
865 void addComtree(
NetBuffer& buf,
string& clientName,
string& reply) {
876 if (p.
srcAdr != nmAdr || cp.
mode != CtlPkt::REQUEST) {
882 cph.
errReply(px,cp,
"no record of session for "
883 "specified client address");
891 if (cp.
type == CtlPkt::CLIENT_CONNECT) {
899 CONNECT_REC : DISCONNECT_REC);
919 logger->
log(
"ClientMgr::writeAcctRecord: cannot write "
920 "to accouting file",2);
923 string typeStr = (recType == NEWSESSION ?
"new session" :
924 (recType == CANCELSESSION ?
"cancel session" :
925 (recType == CONNECT_REC ?
"connect" :
926 (recType == DISCONNECT_REC ?
927 "disconnect" :
"undefined record"))));
929 string now = string(ctime(&t)); now.erase(now.end()-1);
931 acctFile << typeStr <<
", " << now <<
", " << cname <<
", "
943 if (clx < 0 || clx >=
cliTbl->getMaxClients())
return;
969 if (
cliTbl->validClient(clx)) {
974 s.erase(RECORD_SIZE-1); s +=
"\n";
976 s.erase(s.length()-1);
977 int len = RECORD_SIZE - s.length();