15 using namespace forest;
26 int main(
int argc,
char *argv[]) {
27 ipa_t
nmIp,
myIp; uint32_t finTime = 0;
32 (sscanf(argv[3],
"%d", &finTime)) != 1)
33 fatal(
"usage: ClientMgr nmIp myIp fintime");
35 if (!
init(nmIp, myIp))
36 fatal(
"init: Failed to initialize ClientMgr");
50 bool init(ipa_t nmIp1, ipa_t myIp1) {
51 nmIp = nmIp1; myIp = myIp1;
58 logger->
log(
"ClientMgr::init: could not initialize "
70 if (!
sub->init())
return false;
71 sub->setRtrReady(
true);
78 logger->
log(
"ClientMgr::init: could not read clientData "
86 int n =
cliTbl->getMaxClx();
90 for (
int clx = 0; clx <= n; clx++)
writeRecord(clx);
93 logger->
log(
"ClientMgr::init: could not initialize lock "
94 "on client data file",2);
98 acctFile.open(
"acctRecords",fstream::app);
100 logger->
log(
"ClientMgr::init: could not open acctRecords "
112 if (bootSock < 0)
return false;
120 CtlPkt cp(CtlPkt::BOOT_LEAF,CtlPkt::REQUEST,1,p.payload());
121 int plen = cp.
pack();
122 if (plen == 0) { close(bootSock);
return false; }
132 ipa_t srcIp; ipp_t srcPort;
135 if (now > resendTime) {
138 close(bootSock);
return false;
140 resendTime += 1000000;
144 if (nbytes < 0) { usleep(100000);
continue; }
149 logger->
log(
"unexpected response to boot request",
151 close(bootSock);
return false;
154 if (repCp.
type != CtlPkt::CONFIG_LEAF ||
155 repCp.
mode != CtlPkt::REQUEST) {
156 logger->
log(
"unexpected response from NetMgr",2,reply);
157 close(bootSock);
return false;
161 myAdr = repCp.adr1; rtrAdr = repCp.adr2;
162 rtrIp = repCp.ip1; rtrPort = repCp.port1;
167 repCp.
reset(CtlPkt::CONFIG_LEAF,CtlPkt::POS_REPLY,repCp.
seqNum,
170 if (plen == 0) { close(bootSock);
return false; }
176 close(bootSock);
return false;
184 if (now > resendTime) {
187 close(bootSock);
return false;
189 resendTime += 1000000;
193 if (nbytes < 0) { usleep(100000);
continue; }
196 logger->
log(
"unexpected response to boot request",
198 close(bootSock);
return false;
202 if (repCp.
type == CtlPkt::CONFIG_LEAF &&
203 repCp.
mode == CtlPkt::REQUEST) {
205 repCp.
reset(CtlPkt::CONFIG_LEAF,CtlPkt::POS_REPLY,
208 if (plen == 0) { close(bootSock);
return false; }
215 close(bootSock);
return false;
217 }
else if (repCp.
type != CtlPkt::BOOT_LEAF ||
218 repCp.
mode != CtlPkt::POS_REPLY) {
219 logger->
log(
"unexpected response from NetMgr",
221 close(bootSock);
return false;
225 close(bootSock);
return true;
252 bool success =
false;
263 case CtlPkt::CLIENT_CONNECT:
264 case CtlPkt::CLIENT_DISCONNECT:
268 cph.
errReply(px,cp,
"invalid control packet "
269 "type for ClientMgr");
274 cerr <<
"handler: operation failed\n"
289 int clx;
string clientName;
292 if (!
loginDialog(sock,buf,clientName))
return true;
293 userDialog(sock,cph,buf,clientName);
304 string client, pwd, s0, s1, s2, s3;
306 if (!buf.
readWord(s0) || s0 !=
"Forest-login-v1" ||
331 "try again\nover\n");
340 "try again\nover\n");
343 "misformatted login "
350 }
else if (s1 ==
"newAccount") {
362 "available: try again\n"
367 ClientTable::STANDARD);
379 "misformatted login "
392 if (numFailures >= 3) {
404 if (cmd ==
"newSession") {
406 }
else if (cmd ==
"getProfile") {
408 }
else if (cmd ==
"updateProfile") {
410 }
else if (cmd ==
"changePassword") {
412 }
else if (cmd ==
"uploadPhoto") {
414 }
else if (cmd ==
"getSessions") {
416 }
else if (cmd ==
"cancelSession") {
417 cancelSessions(buf,clientName,reply);
418 }
else if (cmd ==
"addComtree" && buf.
nextLine()) {
419 addComtree(buf,clientName,reply);
420 }
else if (cmd ==
"over" && buf.
nextLine()) {
422 }
else if (cmd ==
"overAndOut" && buf.
nextLine()) {
425 reply =
"unrecognized input";
427 if (sock == -1)
break;
428 cerr <<
"sending reply: " << reply << endl;
432 cerr <<
"terminating" << endl;
436 string& clientName,
string& reply) {
440 if (!buf.readRspec(rs) || !buf.
nextLine() ||
441 !buf.
readLine(s1) || s1 !=
"over") {
442 reply =
"unrecognized input";
447 reply =
"unrecognized input";
453 reply =
"cannot access client data(" + clientName +
")";
460 reply =
"session rate exceeds available capacity";
469 reply =
"cannot complete login: NetMgr never responded";
472 if (repCp.
mode != CtlPkt::POS_REPLY) {
474 reply =
"cannot complete login: NetMgr failed (" +
482 reply =
"cannot complete login: could not create "
498 writeAcctRecord(cliName, repCp.adr1, clientIp, repCp.adr2, NEWSESSION);
501 stringstream ss;
string s;
504 <<
"," << repCp.port1 <<
",";
507 ss <<
"connectNonce: " << repCp.
nonce <<
"\noverAndOut\n";
515 string s, targetName;
516 cerr <<
"reading target name\n";
518 reply =
"could not read target name";
return;
520 cerr <<
"clientName=" << clientName <<
" targetName=" << targetName << endl;
523 reply =
"cannot access client data(" + clientName +
")";
527 if (targetName == clientName) {
533 reply =
"no such target client";
return;
536 if (priv != ClientTable::ADMIN && priv != ClientTable::ROOT) {
537 reply =
"this operation requires administrative "
544 if (priv != ClientTable::ROOT && tpriv == ClientTable::ROOT) {
545 reply =
"this operation requires root privileges";
560 string s, targetName;
561 cerr <<
"reading target name\n";
563 reply =
"could not read target name";
return;
567 reply =
"cannot access client data(" + clientName +
")";
570 cerr <<
"got (" << targetName <<
") and I am (" << clientName <<
")" << endl;
572 if (targetName == clientName) {
578 reply =
"no such target client";
582 if (priv != ClientTable::ADMIN && priv != ClientTable::ROOT) {
583 reply =
"this operation requires administrative "
590 if (priv != ClientTable::ROOT &&
591 (tpriv == ClientTable::ROOT ||
592 tpriv == ClientTable::ADMIN)) {
593 reply =
"this operation requires root privileges";
604 string realName, email;
RateSpec defRates, totRates;
606 if (item ==
"realName" && buf.
verify(
':') &&
609 }
else if (item ==
"email" && buf.
verify(
':') &&
612 }
else if (item ==
"defRates" && buf.
verify(
':') &&
613 buf.readRspec(defRates) && buf.
nextLine()) {
615 }
else if (item ==
"totalRates" && buf.
verify(
':') &&
616 buf.readRspec(totRates) && buf.
nextLine()) {
618 }
else if ((item ==
"over" && buf.
nextLine()) ||
619 (item ==
"overAndOut" && buf.
nextLine())) {
622 reply =
"misformatted request (" + item +
")";
628 reply =
"could not update target client data";
633 if (priv != ClientTable::LIMITED) {
634 if (defRates.isSet() &&
637 if (totRates.isSet() &&
642 reply =
"profile updated";
648 string s, targetName;
650 reply =
"could not read target name";
return;
654 reply =
"cannot access client data(" + clientName +
")";
658 if (targetName == clientName) {
664 reply =
"no such target";
return;
670 if (priv != ClientTable::ADMIN && priv != ClientTable::ROOT) {
671 reply =
"this operation requires administrative "
675 if (priv != ClientTable::ROOT &&
676 (tpriv == ClientTable::ROOT ||
677 tpriv == ClientTable::ADMIN)) {
678 reply =
"this operation requires root privileges";
684 cerr <<
"item=" << item <<
"\nbuf=" << buf.toString(s);
685 if (item ==
"password" && buf.
verify(
':') &&
688 }
else if ((item ==
"over" && buf.
nextLine()) ||
689 (item ==
"overAndOut" && buf.
nextLine())) {
692 reply =
"misformatted request (" + item +
")";
698 reply =
"cannot access target client data(" + targetName +
")";
710 reply =
"cannot read length";
return;
712 if (length > 50000) {
713 reply =
"photo file exceeds 50000 byte limit";
return;
717 photoFile.open(
"clientPhotos/" + clientName +
".jpg",ofstream::binary);
718 if (!photoFile.good()) {
719 reply =
"cannot open photo file";
return;
726 int n = buf.
readBlock(xbuf,min(1000,length-numRcvd));
728 photoFile.write(xbuf,n);
730 if (numRcvd == length)
break;
732 if (numRcvd != length) {
733 reply =
"could not transfer complete file";
return;
736 if (!buf.
readLine(s1) || s1 !=
"photo finished" ||
737 !buf.
readLine(s2) || s2 !=
"over") {
738 reply =
"file transfer incomplete";
return;
741 reply =
"photo received";
752 void cancelSession(
NetBuffer& buf,
string& clientName,
string& reply) {
761 void addComtree(
NetBuffer& buf,
string& clientName,
string& reply) {
772 cph.
errReply(px,cp,
"no record of session for "
773 "specified client address");
781 if (cp.
type == CtlPkt::CLIENT_DISCONNECT) {
787 CONNECT_REC : DISCONNECT_REC);
807 logger->
log(
"ClientMgr::writeAcctRecord: cannot write "
808 "to accouting file",2);
811 string typeStr = (recType == NEWSESSION ?
"new session" :
812 (recType == CONNECT_REC ?
"connect" :
813 (recType == DISCONNECT_REC ?
814 "disconnect" :
"undefined record")));
816 string now = string(ctime(&t)); now.erase(now.end()-1);
818 acctFile << typeStr <<
", " << now <<
", " << cname <<
", "
844 if (clx < 0 || clx >=
cliTbl->getMaxClients())
return;
870 if (
cliTbl->validClient(clx)) {
875 s.erase(RECORD_SIZE-1); s +=
"\n";
877 s.erase(s.length()-1);
878 int len = RECORD_SIZE - s.length();