Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Classes | Namespaces | Typedefs | Functions
JLigier.cc File Reference

ControlHost server. More...

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <deque>
#include <set>
#include "Jeep/JParser.hh"
#include "Jeep/JMessage.hh"
#include "JLang/JMemory.hh"
#include "JLang/JSharedCounter.hh"
#include "JNet/JSocket.hh"
#include "JNet/JSocketChannel.hh"
#include "JNet/JServerSocket.hh"
#include "JNet/JSelect.hh"
#include "JNet/JControlHost.hh"
#include "JSystem/JSystemToolkit.hh"

Go to the source code of this file.

Classes

class  JNET::JMemory_t< T >
 
class  JNET::JDispatch
 Data structure of a ControlHost message. More...
 
class  JNET::JClient
 ControlHost client manager. More...
 
class  JNET::JClientList
 List of ControlHost client managers. More...
 

Namespaces

 JNET
 Interprocess communication.
 

Typedefs

typedef JPrefix JNET::JPrefix_t
 
typedef JSocketInputChannel
< JPrefix_t > 
JNET::JSocketInputChannel_t
 

Functions

int JNET::getSizeOfPacket (const JPrefix_t &prefix)
 Get total size of internet packet. More...
 
void JNET::setSizeOfPacket (const int size, JPrefix_t &prefix)
 Set total size of internet packet. More...
 
std::ostream & JNET::operator<< (std::ostream &out, const JDispatch &message)
 Print message. More...
 
std::ostream & JNET::operator<< (std::ostream &out, const JSocket &socket)
 Print socket. More...
 
std::ostream & JNET::operator<< (std::ostream &out, const JSocketStatus &status)
 Print socket status. More...
 
std::ostream & JNET::operator<< (std::ostream &out, const JSocketInputBuffer &buffer)
 Print socket input buffer. More...
 
int main (int argc, char *argv[])
 

Detailed Description

ControlHost server.

Author
mdejong

Definition in file JLigier.cc.

Function Documentation

int main ( int  argc,
char *  argv[] 
)

Definition at line 555 of file JLigier.cc.

556 {
557  using namespace std;
558  using namespace JPP;
559 
560  int port;
561  int backlog;
562  int timeout_us;
563  int buffer_size;
564  int debug;
565 
566  try {
567 
568  JParser<> zap("ControlHost server.");
569 
570  zap['P'] = make_field(port) = DISPATCH_PORT;
571  zap['q'] = make_field(backlog) = 1024;
572  zap['T'] = make_field(timeout_us) = 1;
573  zap['s'] = make_field(buffer_size) = 262144;
574  zap['Q'] = make_field(JClient::QUEUE_LIMIT) = 100;
575  zap['M'] = make_field(JDispatch::MEMORY_LIMIT) = (JSYSTEM::getRAM() >> 1);
576  zap['d'] = make_field(debug) = 0;
577 
578  zap(argc, argv);
579  }
580  catch(const exception &error) {
581  FATAL(error.what() << endl);
582  }
583 
584 
585  JServerSocket server(port, backlog);
586  JSelect select;
587  JClientList clientList;
588 
589 
590  DEBUG("Port " << setw(10) << port << endl);
591  DEBUG("Memory limit " << setw(10) << JDispatch::MEMORY_LIMIT << endl);
592  DEBUG("Queue limit " << setw(10) << JClient::QUEUE_LIMIT << endl);
593 
594 
595  for ( ; ; ) {
596 
597  select.reset();
598  select.setReaderMask(server);
599 
600  for (JClientList::iterator client = clientList.begin(); client != clientList.end(); ++client) {
601 
602  if (!client->in.isReady()) {
603  select.setReaderMask(*client);
604  }
605 
606  if (client->out.isReset()) {
607 
608  if (!client->queue.empty()) {
609 
610  DEBUG("Client" << *client << ".set" << client->queue.front() << endl);
611 
612  client->out.set(client->queue.front());
613  client->decrementRequest();
614 
615  select.setWriterMask(*client);
616  }
617 
618  } else if (client->out.isBusy()) {
619 
620  select.setWriterMask(*client);
621  }
622  }
623 
624  if (select(timeout_us) > 0) {
625 
626  for (JClientList::iterator client = clientList.begin(); client != clientList.end(); ) {
627 
628  try {
629 
630  if (select.hasReaderMask(*client)) {
631 
632  try {
633  client->in.read();
634  }
635  catch(const exception& error) {
636 
637  ERROR("Remove (3) client" << *client << "<" << client->getNickname() << ">: " << error.what() << endl);
638 
639  if (client->getNickname() != "") {
640  clientList.add(JDispatch(DISPTAG_Died, client->getNickname()));
641  }
642 
643  client->shutdown();
644 
645  client = clientList.erase(client);
646 
647  continue;
648  }
649 
650  DEBUG("Client" << *client << ".read" << static_cast<const JSocketInputBuffer&>(client->in) << endl);
651  }
652 
653  if (client->in.isReady()) {
654 
655  DEBUG("Message" << *client << ' ' << client->in.prefix.c_str() << ' ' << client->in.size() << endl);
656 
657  bool special = JControlHost::maybe_special(client->in.prefix);
658 
659  if (special) {
660 
661  client->in.seekg(sizeof(JPrefix_t)); // skip prefix
662 
663  if (client->in.prefix.getTag() == DISPTAG_Subscribe) {
664 
665  client->setSubscription(string(client->in.getRemainingData(), client->in.getRemainingSize()));
666 
667  } else if (client->in.prefix.getTag() == DISPTAG_MyId) {
668 
669  client->setNickname(string(client->in.getRemainingData(), client->in.getRemainingSize()));
670 
671  clientList.add(JDispatch(DISPTAG_Born, client->getNickname()));
672 
673  } else if (client->in.prefix.getTag() == DISPTAG_Gime) {
674 
675  client->incrementRequest();
676 
677  } else if (client->in.prefix.getTag() == DISPTAG_Always) {
678 
679  client->setRequestAll();
680 
681  } else if (client->in.prefix.getTag() == DISPTAG_WhereIs) {
682 
683  string nick_name(client->in.getRemainingData(), client->in.getRemainingSize());
684  string buffer;
685 
686  for (JClientList::iterator i = clientList.begin(); i != clientList.end(); ++i) {
687  if (i->getNickname() == nick_name) {
688  buffer += " " + i->getHostname();
689  }
690  }
691 
692  JControlHost socket(*client);
693 
694  socket.PutFullString(DISPTAG_WhereIs, buffer.substr(buffer.empty() ? 0 : 1));
695 
696  DEBUG("Remove (1) client" << *client << endl);
697 
698  client->shutdown();
699 
700  client = clientList.erase(client);
701 
702  continue; // skip any action
703 
704  } else {
705 
706  special = false; // not a reserved tag.
707  }
708  }
709 
710  if (!special) {
711 
712  clientList.add(JDispatch(client->in.prefix, client->in.data()));
713 
714  if (JDispatch::MEMORY_TOTAL > JDispatch::MEMORY_LIMIT) {
715 
716  WARNING("Memory " << setw(10) << JDispatch::MEMORY_TOTAL << " > " << setw(10) << JDispatch::MEMORY_LIMIT << endl);
717 
718  clientList.drop();
719  }
720  }
721 
722  client->in.reset();
723  }
724 
725  if (select.hasWriterMask(*client)) {
726 
727  client->out.write();
728 
729  DEBUG("Client" << *client << ".write" << static_cast<const JSocketStatus&>(client->out) << endl);
730 
731  if (client->out.isReady()) {
732  client->out.reset();
733  client->queue.pop_front();
734  }
735  }
736 
737  ++client;
738  }
739  catch(const exception& error) {
740 
741  DEBUG("Remove (2) client" << *client << "<" << client->getNickname() << ">: " << error.what() << endl);
742 
743  if (client->getNickname() != "") {
744  clientList.add(JDispatch(DISPTAG_Died, client->getNickname()));
745  }
746 
747  client->shutdown();
748 
749  client = clientList.erase(client);
750  }
751  }
752 
753  if (select.hasReaderMask(server)) {
754 
755  JSocket socket;
756 
757  socket.accept(server.getFileDescriptor());
758 
759  socket.setSendBufferSize (buffer_size);
760  socket.setReceiveBufferSize(buffer_size);
761 
762  socket.setKeepAlive (true);
763  socket.setNonBlocking(true);
764 
765  DEBUG("New client" << socket << endl);
766 
767  clientList.push_back(JClient(socket));
768  }
769  }
770  }
771 }
Utility class to parse command line options.
Definition: JParser.hh:1410
static const JTag DISPTAG_Subscribe("_Subscri")
Special ControlHost tags.
static const int DISPATCH_PORT
Default ControlHost port.
Definition: JHostname.hh:24
#define WARNING(A)
Definition: JMessage.hh:63
static const JTag DISPTAG_Died("Died")
static const JTag DISPTAG_MyId("_MyId")
static const JTag DISPTAG_WhereIs("_WhereIs")
JPrefix JPrefix_t
Definition: JLigier.cc:28
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1836
static const size_t buffer_size
#define ERROR(A)
Definition: JMessage.hh:64
int debug
debug level
Definition: JSirene.cc:59
#define FATAL(A)
Definition: JMessage.hh:65
static const JTag DISPTAG_Born("Born")
unsigned long long int getRAM()
Get RAM of this CPU.
static const JTag DISPTAG_Gime("_Gime")
static const JTag DISPTAG_Always("_Always")
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:60