8 #include "../../../users.h"
 
  12 BASE_PLUGIN * GetPlugin()
 
  14 return new USERSTAT();
 
  21       version(USTAT_VERSION),
 
  29 pthread_mutex_init(&mutex, NULL);
 
  36 int USERSTAT::ParseSettings()
 
  38 vector<PARAM_VALUE>::iterator i;
 
  41 for(i = settings.moduleParams.begin(); i != settings.moduleParams.end(); ++i)
 
  44     transform(s.begin(), s.end(), s.begin(), USERSTAT::ToLower());
 
  47         if (str2x<uint16_t>(*(i->value.begin()), port)) 
 
  49             errorStr = "'Port' parameter must be a numeric value";
 
  50             printfd(__FILE__, "USERSTAT::ParseSettings() %s\n", errorStr.c_str());
 
  54     if (s == "maxthreads")
 
  56         if (str2x<unsigned>(*(i->value.begin()), maxThreads)) 
 
  58             errorStr = "'MaxThreads' parameter must be a numeric value";
 
  59             printfd(__FILE__, "USERSTAT::ParseSettings() %s\n", errorStr.c_str());
 
  68 int USERSTAT::Prepare()
 
  70 listenSocket = socket(PF_INET, SOCK_STREAM, 0);
 
  74     errorStr = "Create USERSTAT socket failed.";
 
  75     printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
 
  79 printfd(__FILE__, "USERSTAT::Prepare() socket - ok\n");
 
  81 listenAddr.sin_family = PF_INET;
 
  82 listenAddr.sin_port = htons(port);
 
  83 listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
 
  87 if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
 
  89     errorStr = "Setsockopt failed. " + string(strerror(errno));
 
  90     printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
 
  94 printfd(__FILE__, "USERSTAT::Prepare() setsockopt - ok\n");
 
  96 int res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
 
 100     errorStr = "Bind USERSTAT socket failed";
 
 101     printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
 
 105 printfd(__FILE__, "USERSTAT::Prepare() bind - ok port: %d\n", port);
 
 107 res = listen(listenSocket, 0);
 
 110     errorStr = "Listen USERSTAT socket failed";
 
 111     printfd(__FILE__, "USERSTAT::Prepare() %s\n", errorStr.c_str());
 
 114 printfd(__FILE__, "USERSTAT::Prepare() listen - ok\n");
 
 120 int USERSTAT::Finalize()
 
 122 return close(listenSocket);
 
 125 int USERSTAT::Start()
 
 128     errorStr = "Users must be set";
 
 129     printfd(__FILE__, "USERSTAT::Start() %s\n", errorStr.c_str());
 
 133     errorStr = "Store must be set";
 
 134     printfd(__FILE__, "USERSTAT::Start() %s\n", errorStr.c_str());
 
 142 if (pthread_create(&thread, NULL, Run, this))
 
 144     errorStr = "Cannot create thread";
 
 145     printfd(__FILE__, "USERSTAT::Start() %s\n", errorStr.c_str());
 
 155 if (pthread_kill(thread, SIGTERM))
 
 157     errorStr = "Cannot send signal to thread";
 
 158     printfd(__FILE__, "USERSTAT::Stop() %s\n", errorStr.c_str());
 
 161 for (int i = 0; i < 25; i++)
 
 170     errorStr = "Cannot stop thread";
 
 171     printfd(__FILE__, "USERSTAT::Stop() %s\n", errorStr.c_str());
 
 177 void * USERSTAT::Run(void * t)
 
 179 USERSTAT * us = reinterpret_cast<USERSTAT *>(t);
 
 182 struct sockaddr_in outerAddr;
 
 183 socklen_t outerAddrLen;
 
 186 us->isRunning = true;
 
 189     outerSocket = accept(us->listenSocket, (struct sockaddr *)&outerAddr, &outerAddrLen); 
 
 192         std::vector<THREAD_INFO>::iterator it;
 
 193         us->pool.erase(remove_if(us->pool.begin(), us->pool.end(), USERSTAT::IsDone()), us->pool.end());
 
 195         while (us->pool.size() >= us->maxThreads)
 
 198         info.users = us->users;
 
 199         info.store = us->store;
 
 200         info.outerSocket = outerSocket;
 
 203         info.request.Reset();
 
 205         us->pool.push_back(info);
 
 209         if (pthread_create(&thread, NULL, Operate, &(*it)))
 
 211             us->errorStr = "Cannot create thread";
 
 212             printfd(__FILE__, "USERSTAT::Run() %s\n", us->errorStr.c_str());
 
 217 us->isRunning = false;
 
 221 void * USERSTAT::Operate(void * i)
 
 223     THREAD_INFO * info = reinterpret_cast<THREAD_INFO *>(i);
 
 228     int res = read(info->outerSocket, &size, sizeof(size));
 
 229     if (res != sizeof(size))
 
 231         printfd(__FILE__, "USERSTAT::Operate() Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
 
 236     printfd(__FILE__, "USERSTAT::Operate() size = %d\n", size);
 
 239         printfd(__FILE__, "USERSTAT::Operate() Invalid data size.\n");
 
 244     login = new char[size];
 
 246     res = read(info->outerSocket, login, size);
 
 249         printfd(__FILE__, "USERSTAT::Operate() Reading login failed! Wanted %d bytes, got %d bytes.\n", 32, res);
 
 255     l.assign(login, size);
 
 257     res = read(info->outerSocket, &size, sizeof(size));
 
 258     if (res != sizeof(size))
 
 260         printfd(__FILE__, "USERSTAT::Operate() Reading stream size failed! Wanted %d bytes, got %d bytes.\n", sizeof(size), res);
 
 265     printfd(__FILE__, "USERSTAT::Operate() size = %d\n", size);
 
 268         printfd(__FILE__, "USERSTAT::Operate() Invalid data size.\n");
 
 273     buf = new unsigned char[size];
 
 274     res = read(info->outerSocket, buf, size);
 
 277         printfd(__FILE__, "USERSTAT::Operate() Reading stream failed! Wanted %d bytes, got %d bytes.\n", size, res);
 
 283     printfd(__FILE__, "USERSTAT::Operate() Received data: %s\n", buf);
 
 285     if (info->users->FindByName(l, &(info->uit)))
 
 287         printfd(__FILE__, "USERSTAT::Operate() User '%s' not found.\n", login);
 
 292     std::string password = info->uit->property.password;
 
 294     printfd(__FILE__, "USERSTAT::Operate() Requested user: '%s'\n", login);
 
 295     printfd(__FILE__, "USERSTAT::Operate() Encription init using password: '%s'\n", password.c_str());
 
 298     char * key = new char[password.length()];
 
 299     strncpy(key, password.c_str(), password.length());
 
 302                   reinterpret_cast<unsigned char *>(key),
 
 305     for (int i = 0; i < size / 8; ++i) {
 
 308         a = n2l(buf + i * 8);
 
 309         b = n2l(buf + i * 8 + 4);
 
 310         Blowfish_Decrypt(&ctx,
 
 314         l2n(b, buf + i * 8 + 4);
 
 319     printfd(__FILE__, "USERSTAT::Operate() Received XML: %s\n", buf);
 
 321     if (XML_Parse(info->xmlParser,
 
 322                   reinterpret_cast<char *>(buf),
 
 324                   1) != XML_STATUS_OK) {
 
 325         printfd(__FILE__, "USERSTAT::Operate() Invalid password\n", login);
 
 331     if (!info->request.isOk) {
 
 332         printfd(__FILE__, "USERSTAT::Operate() Malformed XML\n");
 
 340     std::cout << "USERSTAT::Operate() Request:" << std::endl;
 
 341     std::for_each(info->request.conf.begin(),
 
 342                   info->request.conf.end(),
 
 343                   THREAD_INFO::LinePrinter());
 
 344     std::for_each(info->request.stat.begin(),
 
 345                   info->request.stat.end(),
 
 346                   THREAD_INFO::LinePrinter());
 
 353 void TIParseXMLStart(void * data, const char * name, const char ** attr)
 
 355     THREAD_INFO * ti = reinterpret_cast<THREAD_INFO *>(data);
 
 356     if (strncmp(name, "request", 7) == 0) {
 
 358             printfd(__FILE__, "ParseXMLStart() 'reqest' tag require a 'login' parameter\n");
 
 359             ti->request.isOk |= false;
 
 362             ti->request.login = *attr;
 
 364     } else if (strncmp(name, "stat", 4)) {
 
 365         ti->pvList = &(ti->request.stat);
 
 366     } else if (strncmp(name, "conf", 4)) {
 
 367         ti->pvList = &(ti->request.conf);
 
 369         if (ti->pvList == NULL) {
 
 370             printfd(__FILE__, "ParseXMLStart() Unexpected tag: '%s'\n", name);
 
 371             ti->request.isOk |= false;
 
 378 void TIParseXMLEnd(void * data, const char * name)
 
 380     THREAD_INFO * ti = reinterpret_cast<THREAD_INFO *>(data);
 
 381     if (strncmp(name, "stat", 4) == 0) {
 
 383     } else if (strncmp(name, "conf", 4) == 0) {
 
 385     } else if (strncmp(name, "request", 7) == 0) {
 
 389 THREAD_INFO::THREAD_INFO() : pvList(NULL),
 
 395     printfd(__FILE__, "THREAD_INFO::THREAD_INFO()\n");
 
 396     xmlParser = XML_ParserCreate(NULL);
 
 400         printfd(__FILE__, "USERSTAT::Run() Couldn't allocate memory for parser\n");
 
 403     XML_ParserReset(xmlParser, NULL);
 
 404     XML_SetElementHandler(xmlParser, TIParseXMLStart, TIParseXMLEnd);
 
 405     XML_SetUserData(xmlParser, this);
 
 408 THREAD_INFO::~THREAD_INFO()
 
 410     printfd(__FILE__, "THREAD_INFO::~THREAD_INFO()\n");
 
 411     XML_ParserFree(xmlParser);
 
 414 int THREAD_INFO::Handle()
 
 428 int THREAD_INFO::HandleConf()
 
 430     PV_LIST::iterator it(request.conf.begin());
 
 432     for (; it != request.conf.end(); ++it)
 
 434         if (it->first == "password")
 
 436             it->second = uit->property.password;
 
 438         else if (it->first == "passive")
 
 440             it->second = uit->property.passive;
 
 442         else if (it->first == "disabled")
 
 444             it->second = uit->property.disabled;
 
 446         else if (it->first == "disabledDetailStat")
 
 448             it->second = uit->property.disabledDetailStat;
 
 450         else if (it->first == "alwaysOnline")
 
 452             it->second = uit->property.alwaysOnline;
 
 454         else if (it->first == "tariffName")
 
 456             it->second = uit->property.tariffName;
 
 458         else if (it->first == "address")
 
 460             it->second = uit->property.address;
 
 462         else if (it->first == "phone")
 
 464             it->second = uit->property.phone;
 
 466         else if (it->first == "email")
 
 468             it->second = uit->property.email;
 
 470         else if (it->first == "note")
 
 472             it->second = uit->property.note;
 
 474         else if (it->first == "realName")
 
 476             it->second = uit->property.realName;
 
 478         else if (it->first == "group")
 
 480             it->second = uit->property.group;
 
 482         else if (it->first == "credit")
 
 484             it->second = uit->property.credit;
 
 486         else if (it->first == "creditExpire")
 
 488             it->second = uit->property.creditExpire;
 
 490         else if (it->first == "nextTariff")
 
 492             it->second = uit->property.nextTariff;
 
 496             printfd(__FILE__, "THREAD_INFO::HandleConf() Invalid param: '%s'\n", it->first.c_str());
 
 503 int THREAD_INFO::HandleStat()
 
 505     PV_LIST::iterator it(request.conf.begin());
 
 507     for (; it != request.conf.end(); ++it)
 
 509         if (it->first == "cash")
 
 511             it->second = uit->property.password;
 
 515             printfd(__FILE__, "THREAD_INFO::HandleConf() Invalid param: '%s'\n", it->first.c_str());