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) {
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, type;
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") {
341 }
else if (cmd ==
"uploadAvatar") {
344 }
else if (cmd ==
"uploadTexH"){
346 uploadFile(type, sock, buf, clientName, reply);
347 }
else if (cmd ==
"uploadTexM"){
349 uploadFile(type, sock, buf, clientName, reply);
350 }
else if (cmd ==
"getSessions") {
352 }
else if (cmd ==
"cancelSession") {
353 cancelSession(buf,clientName,cph,reply);
354 }
else if (cmd ==
"cancelAllSessions") {
356 }
else if (cmd ==
"addComtree" && buf.nextLine()) {
357 addComtree(buf,clientName,reply);
359 reply =
"unrecognized input";
361 cerr <<
"sending reply: " << reply << endl;
366 cerr <<
"terminating" << endl;
387 reply =
"login failed: try again";
390 cerr <<
"login succeeded " << clientName << endl;
395 reply =
"login failed: try again";
399 reply =
"misformatted login request";
423 reply =
"name not available, select another";
432 reply =
"unable to add client";
436 reply =
"misformatted new account request";
453 string& clientName,
string& reply) {
457 if (!buf.readRspec(rs) || !buf.
nextLine() ||
458 !buf.
readLine(s1) || s1 !=
"over") {
459 reply =
"misformatted new session request";
464 reply =
"misformatted new session request";
470 reply =
"cannot access client data(" + clientName +
")";
477 reply =
"session rate exceeds available capacity";
485 pktx rpx = cph.
newSession(nmAdr, clientIp, rs, repCp);
488 reply =
"cannot update client data(" + clientName +
")";
489 logger->
log(
"ClientMgr::newSession: cannot update session data "
490 "session state may be inconsistent",2);
496 reply =
"cannot setup session: NetMgr never responded";
500 if (repCp.
mode != CtlPkt::POS_REPLY) {
503 reply =
"cannot setup new session: NetMgr failed (" +
511 reply =
"cannot setup new session: could not create "
528 stringstream ss;
string s;
531 <<
"," << repCp.port1 <<
",";
534 ss <<
"connectNonce: " << repCp.
nonce <<
"\noverAndOut\n";
556 if (clx == 0)
return 0;
559 if (priv != ClientTable::ADMIN && priv != ClientTable::ROOT)
return 0;
563 if (tclx == 0)
return 0;
565 if (priv == ClientTable::ADMIN &&
566 (tpriv == ClientTable::ADMIN || tpriv == ClientTable::ROOT)) {
582 string s, targetName;
585 reply =
"misformatted get profile request";
return;
589 reply =
"insufficient privileges for requested operation";
609 string s, targetName;
612 reply =
"misformatted updateProfile request";
return;
616 string realName, email;
RateSpec defRates, totRates;
618 if (item ==
"realName" && buf.
verify(
':') &&
621 }
else if (item ==
"email" && buf.
verify(
':') &&
624 }
else if (item ==
"defRates" && buf.
verify(
':') &&
625 buf.readRspec(defRates) && buf.
nextLine()) {
627 }
else if (item ==
"totalRates" && buf.
verify(
':') &&
628 buf.readRspec(totRates) && buf.
nextLine()) {
630 }
else if (item ==
"over" && buf.
nextLine()) {
633 reply =
"misformatted update profile request (" +
640 reply =
"insufficient privileges for requested operation";
646 if (tpriv != ClientTable::LIMITED) {
647 if (defRates.isSet() &&
650 if (totRates.isSet() &&
669 string targetName, pwd;
672 reply =
"misformatted change password request";
return;
676 reply =
"insufficient privileges for requested operation";
700 reply =
"misformatted upload photo request";
return;
702 if (type ==
"photo"){
704 fileName =
"clientPhotos/" + clientName +
".jpg";
709 fileName =
"clientAvatars/" + clientName +
".zip";
710 else if (type ==
"hi_res")
711 fileName =
"clientTextures/" + clientName +
".png";
713 fileName =
"clientTextures/" + clientName +
".jpg";
716 if (length > limit) {
717 reply =
"file exceeds byte limit";
return;
722 inFile.open(fileName.c_str(), ofstream::binary);
723 if (!inFile.good()) {
724 reply =
"cannot open file to write";
return;
731 int n = buf.
readBlock(xbuf,min(1000,length-numRcvd));
733 inFile.write(xbuf,n);
735 if (numRcvd == length)
break;
737 if (numRcvd != length) {
738 reply =
"could not transfer complete file";
return;
741 if (!buf.
readLine(s1) || s1 !=
"upload finished" ||
742 !buf.
readLine(s2) || s2 !=
"over") {
743 reply =
"misformatted upload request";
return;
756 string s, targetName;
759 reply =
"misformatted get sessions request";
return;
763 reply =
"insufficient privileges for requested operation";
774 reply.erase(reply.end()-1);
788 string s, targetName, cancelAdrStr;
792 reply =
"misformatted cancel session request";
return;
795 if (cancelAdr == 0) {
796 reply =
"misformatted address";
return;
800 reply =
"insufficient privileges for requested operation";
806 reply =
"invalid session address";
return;
809 reply =
"session address belongs to another client";
return;
818 pktx rpx = cph.
cancelSession(nmAdr, cancelAdr, rtrAdr, repCp);
820 reply =
"cannot cancel session: NetMgr never responded";
824 if (repCp.
mode != CtlPkt::POS_REPLY) {
825 reply =
"cannot complete cancelSession: NetMgr failed (" +
831 reply =
"cannot update session data for " + targetName;
832 logger->
log(
"ClientMgr::cancelSession: cannot update session "
833 "data session state may be inconsistent",2);
851 string s, targetName;
854 reply =
"misformatted cancel all sessions request";
return;
858 reply =
"insufficient privileges for requested operation";
871 reply =
"cannot cancel session: NetMgr never responded";
875 if (repCp.
mode != CtlPkt::POS_REPLY) {
876 reply =
"cannot complete cancelSession: NetMgr failed "
891 void addComtree(
NetBuffer& buf,
string& clientName,
string& reply) {
902 if (p.
srcAdr != nmAdr || cp.
mode != CtlPkt::REQUEST) {
908 cph.
errReply(px,cp,
"no record of session for "
909 "specified client address");
917 if (cp.
type == CtlPkt::CLIENT_CONNECT) {
925 CONNECT_REC : DISCONNECT_REC);
945 logger->
log(
"ClientMgr::writeAcctRecord: cannot write "
946 "to accouting file",2);
949 string typeStr = (recType == NEWSESSION ?
"new session" :
950 (recType == CANCELSESSION ?
"cancel session" :
951 (recType == CONNECT_REC ?
"connect" :
952 (recType == DISCONNECT_REC ?
953 "disconnect" :
"undefined record"))));
955 string now = string(ctime(&t)); now.erase(now.end()-1);
957 acctFile << typeStr <<
", " << now <<
", " << cname <<
", "
969 if (clx < 0 || clx >=
cliTbl->getMaxClients())
return;
995 if (
cliTbl->validClient(clx)) {
1000 s.erase(RECORD_SIZE-1); s +=
"\n";
1002 s.erase(s.length()-1);
1003 int len = RECORD_SIZE - s.length();