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"
#include "JMath/JConstants.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 556 of file JLigier.cc.

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