nidas  v1.2-1520
McSocket.h
Go to the documentation of this file.
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4; -*-
2 // vim: set shiftwidth=4 softtabstop=4 expandtab:
3 /*
4  ********************************************************************
5  ** NIDAS: NCAR In-situ Data Acquistion Software
6  **
7  ** 2006, Copyright University Corporation for Atmospheric Research
8  **
9  ** This program is free software; you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation; either version 2 of the License, or
12  ** (at your option) any later version.
13  **
14  ** This program is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** The LICENSE.txt file accompanying this software contains
20  ** a copy of the GNU General Public License. If it is not found,
21  ** write to the Free Software Foundation, Inc.,
22  ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  **
24  ********************************************************************
25 */
26 /*
27  ********************************************************************
28  Copyright by the National Center for Atmospheric Research
29 
30  $LastChangedDate$
31 
32  $LastChangedRevision$
33 
34  $LastChangedBy$
35 
36  $HeadURL$
37  ********************************************************************
38 
39 */
40 
41 #ifndef NIDAS_UTIL_MCSOCKET_H
42 #define NIDAS_UTIL_MCSOCKET_H
43 
44 #include <nidas/Config.h> // HAVE_PPOLL
45 
46 #include "Socket.h"
47 #include "DatagramPacket.h"
48 #include "Thread.h"
49 #include "UTime.h"
50 
51 #ifdef HAVE_PPOLL
52 #include <poll.h>
53 #else
54 #include <sys/select.h>
55 #endif
56 
57 #include <list>
58 
59 #include <unistd.h> // need declaration of sleep()
60 
61 namespace nidas { namespace util {
62 
63 struct McSocketData {
64 
68  int magic;
76 
81  unsigned short _listenPort;
82 
86  short _socketType;
87 
91  McSocketData() : magic(0),_requestType(htonl((unsigned)-1)),_listenPort(0),_socketType(htons(SOCK_STREAM)) {}
92 };
93 
101 class McSocketDatagram: public DatagramPacketT<McSocketData>
102 {
103 public:
104  McSocketDatagram(int requestType=-1);
105 
110 
115 
116  int getMagic() const { return ntohl(mcdata.magic); }
117 
118  void setMagic(int val) { mcdata.magic = htonl(val); }
119 
120  int getRequestType() const { return ntohl(mcdata._requestType); }
121 
122  void setRequestType(int val) { mcdata._requestType = htonl(val); }
123 
127  int getRequesterListenPort() const { return ntohs(mcdata._listenPort); }
128 
129  void setRequesterListenPort(int val) { mcdata._listenPort = htons(val); }
130 
135  int getSocketType() const { return ntohs(mcdata._socketType); }
136 
137  void setSocketType(int val) { mcdata._socketType = htons(val); }
138 
143  static const int magicVal;
144 
145 protected:
147 };
148 
149 
150 template <class SocketT>
151 class McSocket;
152 
154 {
155  return SOCK_STREAM;
156 }
157 
159 {
160  return SOCK_DGRAM;
161 }
162 
204 template <class SocketT>
205 class McSocket
206 {
211  friend class McSocketListener;
212 
213  template<class SocketTT>
214  friend class McSocketMulticaster;
215 public:
285  McSocket();
286 
290  McSocket(const McSocket<SocketT>&);
291 
296 
297  virtual ~McSocket();
298 
310  _iface = iaddr;
311  }
312 
314 
318  std::list<Inet4NetworkInterface> getInterfaces() const throw(IOException);
319 
324  {
325  return _mcastAddr;
326  }
327 
333 
340  void setRequestType(int val) { _requestType = val; }
341 
345  int getRequestType() const { return _requestType; }
346 
360  void listen() throw(IOException);
361 
373  SocketT* accept(Inet4PacketInfoX&) throw(IOException);
374 
385  virtual void connected(SocketT*,const Inet4PacketInfoX&) {}
386 
394  void request() throw(IOException);
395 
403  SocketT* connect(Inet4PacketInfoX&) throw(IOException);
404 
408  virtual void close() throw(IOException);
409 
410 private:
420  void offer(SocketT* sock,const Inet4PacketInfoX& pktinfo);
421 
422  void offer(int err);
423 
424  void joinMulticaster();
425 
427 
429 
431 
433 
434  SocketT* _newsocket;
435 
437 
439 
441 
446 
448 
449  // Inet4PacketInfoX _pktinfo;
450 
451 };
452 
460 class McSocketListener: private Thread
461 {
462  template<class SocketT>
463  friend class McSocket;
464 
465 public:
466 
470  static int check() throw();
471 
472 private:
482  static void accept(McSocket<Socket>* sock) throw(Exception);
483 
493  static void accept(McSocket<DatagramSocket>* sock) throw(Exception);
494 
500  static void close(McSocket<Socket>* sock) throw(Exception);
501 
507  static void close(McSocket<DatagramSocket>* sock) throw(Exception);
508 
509  int run() throw(Exception);
510 
511  void interrupt();
512 
513 private:
515 
516  ~McSocketListener();
517 
518  void add(McSocket<Socket>* mcsocket);
519 
520  void add(McSocket<DatagramSocket>* mcsocket);
521 
522  int remove(McSocket<Socket>* mcsocket);
523 
524  int remove(McSocket<DatagramSocket>* mcsocket);
525 
528 
530  McSocketListener& operator=(const McSocketListener&);
531 
532 private:
533 
534  Inet4SocketAddress _mcastAddr;
535 
536  Mutex _mcsocket_mutex;
537 
538  DatagramSocket* _readsock;
539 
540  std::map<int,McSocket<Socket>*> _tcpMcSockets;
541 
542  std::map<int,McSocket<DatagramSocket>*> _udpMcSockets;
543 
544 };
545 
553 template<class SocketTT>
554 class McSocketMulticaster: private Thread
555 {
556  template<class SocketT>
557  friend class McSocket;
558 
559 private:
561 
564 
567 
568  virtual ~McSocketMulticaster();
569 
570  int run() throw(Exception);
571 
572  void interrupt();
573 
574  McSocket<SocketTT>* _mcsocket;
575 
580  ServerSocket* _serverSocket;
581 
586  DatagramSocket* _datagramSocket;
587 
591  DatagramSocket* _requestSocket;
592 
593  Mutex _mcsocketMutex;
594 };
595 
596 }} // namespace nidas namespace util
597 
598 #include "Logger.h"
599 #include <memory>
600 
601 namespace nidas { namespace util {
602 
603 template<class SocketT>
604 McSocket<SocketT>::McSocket(): _mcastAddr(),_iface(),_requestType(-1),
605  _connectCond(),
606  _newsocket(0),_newpktinfo(),
607  _socketOffered(false),_offerErrno(0),
608  _multicaster(0),_multicaster_mutex()
609 {
610 }
611 
612 template<class SocketT>
614  _mcastAddr(x._mcastAddr),_iface(x._iface),
615  _requestType(x._requestType), _connectCond(),
616  _newsocket(0),_newpktinfo(),
617  _socketOffered(false),_offerErrno(0),
618  _multicaster(0),_multicaster_mutex()
619 {
620 }
621 
622 template<class SocketT>
624 {
625  if (&rhs != this) {
626  _mcastAddr = rhs._mcastAddr;
627  _iface = rhs._iface;
628  _requestType = rhs._requestType;
629  _newsocket = 0;
630  _socketOffered = false;
631  _multicaster = 0;
632  }
633  return *this;
634 }
635 
636 template<class SocketT>
638 }
639 
640 template<class SocketT>
641 std::list<Inet4NetworkInterface> McSocket<SocketT>::getInterfaces() const throw(IOException)
642 {
643  MulticastSocket tmpsock(_mcastAddr.getPort());
644  std::list<Inet4NetworkInterface> ifcs = tmpsock.getInterfaces();
645  tmpsock.close();
646  return ifcs;
647 }
648 
649 template<class SocketT>
650 void McSocket<SocketT>::listen() throw(IOException)
651 {
652  if (getRequestType() < 0)
653  throw IOException(_mcastAddr.toString(),"listen",
654  "request number has not been set");
655  _newsocket = 0;
656  _socketOffered = false;
657  try {
659  }
660  catch (const Exception& e) {
661  throw IOException(_mcastAddr.toString(),"accept",e.what());
662  }
663 }
664 
665 /*
666  * Does a listen and then waits for the connection.
667  */
668 template<class SocketT>
669 SocketT* McSocket<SocketT>::accept(Inet4PacketInfoX& pktinfo) throw(IOException)
670 {
671  listen();
672  _connectCond.lock();
673  while(!_socketOffered) _connectCond.wait();
674  SocketT* socket = _newsocket;
675  pktinfo = _newpktinfo;
676  _newsocket = 0;
677  _connectCond.unlock();
678  VLOG(("accept offerErrno=%d", _offerErrno));
679  if (!socket) throw IOException("McSocket","accept",_offerErrno);
680  return socket;
681 }
682 
683 template<class SocketT>
684 void McSocket<SocketT>::request() throw(IOException)
685 {
686  if (getRequestType() < 0)
687  throw IOException(_mcastAddr.toString(),"listen",
688  "request number has not been set");
689  _newsocket = 0;
690  _socketOffered = false;
691  // if (!_mcastAddr.getInet4Address().isMultiCastAddress())
692  // throw IOException(_mcastAddr.toString(),"accept","is not a multicast address");
693 
694  _multicaster_mutex.lock();
695  if (!_multicaster) {
696  _multicaster = new McSocketMulticaster<SocketT>(this);
697  try {
698  _multicaster->start();
699  }
700  catch(const Exception& e) {
701  throw IOException("McSocket","request",e.what());
702  }
703  }
704  _multicaster_mutex.unlock();
705 }
706 
707 /*
708  * Does a request() and then waits for the connection.
709  */
710 template<class SocketT>
711 SocketT* McSocket<SocketT>::connect(Inet4PacketInfoX& pktinfo) throw(IOException)
712 {
713  request();
714  _connectCond.lock();
715  while(!_socketOffered) _connectCond.wait();
716  SocketT* socket = _newsocket;
717  pktinfo = _newpktinfo;
718  _newsocket = 0;
719  _connectCond.unlock();
720  VLOG(("connect offerErrno=%d",_offerErrno));
721  if (!socket) throw IOException("McSocket","connect",_offerErrno);
722  return socket;
723 }
724 
725 template<class SocketT>
727 {
728  // can't do a multicaster->join here, that would deadlock
729  // because we'd be waiting for ourselves,
730  // so we spawn a detached thread to join and delete it.
731 
732  _multicaster_mutex.lock();
733 
734  if (_multicaster) {
735  VLOG(("Mcsocket::offer creating/starting joiner"));
736  ThreadJoiner* joiner = new ThreadJoiner(_multicaster);
737  _multicaster = 0;
738  try {
739  joiner->start();
740  }
741  // shouldn't happen
742  catch(const Exception& e) {
743  Logger::getInstance()->log(LOG_ERR,"%s",e.what());
744  }
745  VLOG(("Mcsocket::offer joiner started"));
746  }
747  VLOG(("Mcsocket::offer doing connectCond.lock"));
748  _multicaster_mutex.unlock();
749 }
750 /*
751  * Method that executes in the thread of the McSocketListener
752  * or the McSocketMulticaster, and notifies whoever did
753  * the listen() or request() that the socket is connected.
754  */
755 template<class SocketT>
756 void McSocket<SocketT>::offer(SocketT* socket,const Inet4PacketInfoX& pktinfo)
757 {
758  joinMulticaster();
759 
760  if (socket) connected(socket,pktinfo);
761 
762  _connectCond.lock();
763  _socketOffered = true;
764  _offerErrno = 0;
765  _newsocket = socket;
766  _newpktinfo = pktinfo;
767  _connectCond.signal();
768  _connectCond.unlock();
769 
770  // note: don't access any class variables or virtual methods
771  // after the above unlock. The calling thread may have
772  // deleted this object after it received the connected Socket.
773 }
774 
775 template<class SocketT>
777 {
778  joinMulticaster();
779 
780  _connectCond.lock();
781  _socketOffered = true;
782  _offerErrno = err;
783  _newsocket = 0;
784  _connectCond.signal();
785  _connectCond.unlock();
786 
787  // note: don't access any class variables or virtual methods
788  // after the above unlock. The calling thread may have
789  // deleted this object after it received the connected Socket.
790 }
791 
792 template<class SocketT>
793 void McSocket<SocketT>::close() throw(IOException)
794 {
795  VLOG(("Mcsocket::close"));
796  _multicaster_mutex.lock();
797  if (_multicaster && _multicaster->isRunning()) _multicaster->interrupt();
798  _multicaster_mutex.unlock();
799 
800  offer(EINTR);
801 
802  try {
804  }
805  catch (const Exception& e) {
806  VLOG(("Mcsocket::close exception: %s", e.what()));
807  throw IOException(_mcastAddr.toString(), "close", e.what());
808  }
809  VLOG(("Mcsocket::close done, this=0x%x", this));
810 }
811 
812 template<class SocketTT>
814  Thread("McSocketMulticaster"),
815  _mcsocket(mcsock),_serverSocket(0),_datagramSocket(0),_requestSocket(0),
816  _mcsocketMutex()
817 {
818  switch (getMcSocketType(mcsock)) {
819  case SOCK_STREAM:
820  _serverSocket = new ServerSocket();
821  _datagramSocket = 0;
822  break;
823  default:
824  _datagramSocket = new DatagramSocket();
825  _serverSocket = 0;
826  break;
827  }
828  // block SIGUSR1, then unblock it in pselect/ppoll
829  blockSignal(SIGUSR1);
830 }
831 
832 template<class SocketT>
834 {
835  if (_serverSocket) {
836  _serverSocket->close();
837  delete _serverSocket;
838  }
839  if (_datagramSocket) {
840  _datagramSocket->close();
841  delete _datagramSocket;
842  }
843  if (_requestSocket) {
844  _requestSocket->close();
845  delete _requestSocket;
846  }
847 }
848 
849 template<class SocketT>
851 {
852  _mcsocketMutex.lock();
853  _mcsocket = 0;
854  _mcsocketMutex.unlock();
855  try {
856  kill(SIGUSR1);
857  }
858  catch(const Exception& e) {
859  PLOG(("%s",e.what()));
860  }
861 }
862 
863 
864 void
866  std::vector<Inet4NetworkInterface>& ifaces);
867 
868 template<class SocketT>
869 int McSocketMulticaster<SocketT>::run() throw(Exception)
870 {
871  MulticastSocket* requestmsock = 0;
872 
873  int sockfd = (_serverSocket ? _serverSocket->getFd() :
874  _datagramSocket->getFd());
875 
876 #ifdef HAVE_PPOLL
877  struct pollfd fds;
878  fds.fd = sockfd;
879 #ifdef POLLRDHUP
880  fds.events = POLLIN | POLLRDHUP;
881 #else
882  fds.events = POLLIN;
883 #endif
884 #else
885  fd_set fdset;
886  FD_ZERO(&fdset);
887 #endif
888 
889  // wait for this amount of time after a datagram send to receive a
890  // connection or receipt of UDP data
891  struct timespec timeout;
892  timeout.tv_sec = 0;
893  timeout.tv_nsec = NSECS_PER_SEC / 4; // portion of a second
894 
895  // get the existing signal mask
896  sigset_t sigmask;
897  pthread_sigmask(SIG_BLOCK,NULL,&sigmask);
898  // unblock SIGUSR1 in pselect/ppoll
899  sigdelset(&sigmask,SIGUSR1);
900 
901  Inet4SocketAddress mcsockaddr =
902  _mcsocket->getInet4McastSocketAddress();
903  Inet4Address mcaddr = mcsockaddr.getInet4Address();
904 
905  std::vector<Inet4NetworkInterface> ifaces;
906 
907  if (mcaddr.isMultiCastAddress())
908  {
909  VLOG(("") << mcsockaddr.toString() << " is a multicast address.");
910  _requestSocket = requestmsock = new MulticastSocket();
911  if (_mcsocket->getInterface().getAddress() == Inet4Address(INADDR_ANY))
912  {
913  listMulticastInterfaces(requestmsock, ifaces);
914  }
915  }
916  else
917  {
918  VLOG(("") << mcsockaddr.toString()
919  << " is not a multicast address, using a datagram request socket.");
920  _requestSocket = new DatagramSocket();
921  }
922 
923  McSocketDatagram dgram;
924  dgram.setMagic(dgram.magicVal);
925  dgram.setSocketAddress(mcsockaddr);
926  dgram.setRequestType(_mcsocket->getRequestType());
927  dgram.setSocketType(getMcSocketType(_mcsocket));
928  if (_serverSocket)
929  dgram.setRequesterListenPort(_serverSocket->getLocalPort());
930  else
931  dgram.setRequesterListenPort(_datagramSocket->getLocalPort());
932 
933  for (int numCasts=0; !isInterrupted() ; numCasts++) {
934  // If multicast, loop over interfaces
935  try {
936  if (requestmsock && ifaces.size() > 0) {
937  Inet4NetworkInterface iface = ifaces[numCasts % ifaces.size()];
938  requestmsock->setInterface(mcaddr,iface);
939  _requestSocket->send(dgram);
940  }
941  else {
942  _requestSocket->send(dgram);
943  }
944  if (!(numCasts % 300)) {
945  ILOG(("") << "sent " << numCasts << " dgrams" <<
946  ", requestType=" << dgram.getRequestType() <<
947  ", port=" << dgram.getRequesterListenPort() <<
948  ", socketType=" << dgram.getSocketType() <<
949  ", len=" << dgram.getLength() <<
950  ", #mcifaces=" << ifaces.size());
951  }
952  }
953  catch(const IOException& e)
954  {
955  // perhaps the interface has disappeared. Log the error.
956  WLOG(("McSocketMulticaster: ")
957  << _requestSocket->getLocalSocketAddress().toString()
958  << ": " << e.what());
959  sleep(10);
960  if (requestmsock)
961  {
962  _requestSocket->close();
963  delete _requestSocket;
964  // close and re-create the socket
965  _requestSocket = requestmsock = new MulticastSocket();
966  // re-create the list of interfaces.
967  listMulticastInterfaces(requestmsock, ifaces);
968  }
969  continue;
970  }
971 
972  int res;
973 #ifdef HAVE_PPOLL
974  res = ::ppoll(&fds,1,&timeout,&sigmask);
975 
976  if (res > 0) {
977 
978  if (fds.revents & POLLERR) {
979  _mcsocketMutex.lock();
980  if (_mcsocket) _mcsocket->offer(errno);
981  _mcsocketMutex.unlock();
982  if (_serverSocket) _serverSocket->close(); // OK to close twice
983  if (_datagramSocket) _datagramSocket->close();
984  _requestSocket->close();
985  throw IOException("McSocket","ppoll",errno);
986  }
987 
988 #ifdef POLLRDHUP
989  if (fds.revents & (POLLHUP | POLLRDHUP))
990 #else
991  if (fds.revents & POLLHUP)
992 #endif
993  WLOG(("%s POLLHUP","McSocket"));
994 
995  }
996 
997 #else
998  assert(sockfd >= 0 && sockfd < FD_SETSIZE); // FD_SETSIZE=1024
999  FD_SET(sockfd, &fdset);
1000  res = ::pselect(sockfd+1,&fdset,0,0,&timeout,&sigmask);
1001 #endif
1002  if (res <= 0) {
1003  if (res == 0) continue;
1004  if (errno == EINTR) break;
1005  _mcsocketMutex.lock();
1006  if (_mcsocket) _mcsocket->offer(errno);
1007  _mcsocketMutex.unlock();
1008  if (_serverSocket) _serverSocket->close(); // OK to close twice
1009  if (_datagramSocket) _datagramSocket->close();
1010  _requestSocket->close();
1011  throw IOException("McSocket","poll/select",errno);
1012  }
1013 
1014  if (_serverSocket) {
1015  Socket* socket = _serverSocket->accept();
1016  DLOG(("accepted socket connection from ") <<
1017  socket->getRemoteSocketAddress().toString() << " on " <<
1018  _serverSocket->getLocalSocketAddress().toString());
1019  _serverSocket->close();
1021  if (socket->getRemoteSocketAddress().getFamily() == AF_INET) {
1022  nidas::util::Inet4SocketAddress remoteAddr =
1023  nidas::util::Inet4SocketAddress((const struct sockaddr_in*)
1025  pktinfo.setRemoteSocketAddress(remoteAddr);
1026  }
1027  if (socket->getLocalSocketAddress().getFamily() == AF_INET) {
1029  nidas::util::Inet4SocketAddress((const struct sockaddr_in*)
1031  pktinfo.setLocalAddress(localAddr.getInet4Address());
1032  pktinfo.setDestinationAddress(localAddr.getInet4Address());
1033  }
1034  _mcsocketMutex.lock();
1035  if (_mcsocket) _mcsocket->offer((SocketT*)socket,pktinfo);
1036  _mcsocketMutex.unlock();
1037  }
1038  else {
1039  // If fishing for UDP responses, send out at least 3 multicasts
1040  // to see if we get more than one response.
1041  if (numCasts < 3) continue;
1042 
1043  // We know there is data at the socket, do a MSG_PEEK to get
1044  // information about the first packet.
1046  _datagramSocket->receive(dgram,pktinfo,MSG_PEEK);
1047  if (dgram.getSocketAddress().getFamily() == AF_INET) {
1048  nidas::util::Inet4SocketAddress remoteAddr =
1049  nidas::util::Inet4SocketAddress((const struct sockaddr_in*)
1051  pktinfo.setRemoteSocketAddress(remoteAddr);
1052  }
1053 
1054  _mcsocketMutex.lock();
1055  if (_mcsocket) _mcsocket->offer((SocketT*)_datagramSocket,pktinfo);
1056  _datagramSocket = 0; // we no longer own _datagramSocket
1057  _mcsocketMutex.unlock();
1058  }
1059  _requestSocket->close();
1060  return RUN_OK;
1061  } // loop until receipt of connection or UDP packet
1062 
1063  VLOG(("McSocketMulticaster break"));
1064  _mcsocketMutex.lock();
1065  if (_mcsocket) _mcsocket->offer(EINTR);
1066  _mcsocketMutex.unlock();
1067  if (_serverSocket) _serverSocket->close();
1068  if (_datagramSocket) _datagramSocket->close();
1069  _requestSocket->close();
1070  VLOG(("McSocketMulticaster run method exiting"));
1071  return RUN_OK;
1072 }
1073 
1074 }} // namespace nidas namespace util
1075 #endif
McSocketMulticaster(McSocket< SocketTT > *mcsocket)
Definition: McSocket.h:813
void signal()
Unblock at least one thread waiting on the condition variable.
Definition: ThreadSupport.h:310
static const int magicVal
Magic value that should be found at the beginning of all received McSocketDatagrams.
Definition: McSocket.h:143
Class for listening on McSocket requests on a specific multicast address and UDP port number...
Definition: McSocket.h:460
McSocket()
Create a McSocket for requesting or accepting multicast requests for a socket connection.
Definition: McSocket.h:604
SocketT * connect(Inet4PacketInfoX &)
Do a request(), and then wait until a TCP connection is established, or a UDP datagram is received ba...
Definition: McSocket.h:711
void listen()
Register with a McSocketListener to listen on the multicast address.
Definition: McSocket.h:650
A datagram socket to be used for multicasts.
Definition: Socket.h:1241
McSocketDatagram & operator=(const McSocketDatagram &rhs)
Assignment operator.
Definition: McSocket.cc:82
Mutex _multicaster_mutex
Definition: McSocket.h:447
void send(const DatagramPacketBase &packet, int flags=0)
Definition: Socket.h:1058
bool isMultiCastAddress() const
Is this address a multicast address? Multicast addresses are in the range 224.0.0.1 to 239.255.255.255, their first four bits are 1110=0xe.
Definition: Inet4Address.h:138
Thread * _multicaster
The thread we start which multicasts for connections.
Definition: McSocket.h:445
void interrupt()
Interrupt this thread.
Definition: McSocket.h:850
void setRemoteSocketAddress(const Inet4SocketAddress &val)
Definition: Inet4PacketInfo.h:104
void lock()
Lock the mutex associated with the condition variable.
Definition: ThreadSupport.h:290
int getMagic() const
Definition: McSocket.h:116
virtual ~McSocket()
Definition: McSocket.h:637
SocketAddress & getSocketAddress() const
Definition: DatagramPacket.h:100
McSocketDatagram(int requestType=-1)
Definition: McSocket.cc:64
void request()
Start issuing requests for a connection by multicasting McSocketDatagrams.
Definition: McSocket.h:684
int getFd() const
Definition: Socket.h:1031
#define err(format, arg...)
Definition: ck_lams.cc:55
void receive(DatagramPacketBase &packet)
Read a packet from the DatagramSocket.
Definition: Socket.h:1038
std::string toString() const
Java style toString: returns &quot;inet:hostname:port&quot;.
Definition: Inet4SocketAddress.cc:84
A socket for sending or receiving datagrams, either unicast, broadcast or multicast.
Definition: Socket.h:912
Datagram that is multicast by a host when it wants a service.
Definition: McSocket.h:101
int getRequesterListenPort() const
What port is the requester listening on for the connection back?
Definition: McSocket.h:127
int getFd() const
Definition: Socket.h:788
void setSocketType(int val)
Definition: McSocket.h:137
void setRequesterListenPort(int val)
Definition: McSocket.h:129
Inet4PacketInfoX _newpktinfo
Definition: McSocket.h:436
Inet4SocketAddress _mcastAddr
Definition: McSocket.h:426
#define ILOG(MSG)
Definition: Logger.h:305
unsigned short _listenPort
Socket port that the remote host is listening on.
Definition: McSocket.h:81
int _requestType
Definition: McSocket.h:430
A IP version 4 socket address, containing a host address, and a port number.
Definition: Inet4SocketAddress.h:41
int _offerErrno
Definition: McSocket.h:440
virtual void setLocalAddress(const Inet4Address &val)
Definition: Inet4PacketInfo.h:56
SocketT * _newsocket
Definition: McSocket.h:434
void listMulticastInterfaces(MulticastSocket *requestmsock, std::vector< Inet4NetworkInterface > &ifaces)
Definition: McSocket.cc:489
void close()
Definition: Socket.h:958
int _requestType
An integer which identifies the type of the request.
Definition: McSocket.h:75
const Inet4SocketAddress & getInet4McastSocketAddress() const
Get the multicast address for listening to requests.
Definition: McSocket.h:323
Cond _connectCond
Definition: McSocket.h:432
virtual std::string toString() const =0
Java style toString.
virtual int getFamily() const =0
Get the family of this SocketAddress, one of the values from /usr/include/sys/socket.h: AF_UNIX, AF_INET, AF_INET6, etc.
virtual void start()
Start the thread running, meaning execute the run method in a separate thread.
Definition: Thread.cc:406
int getLocalPort() const
Get local port number of this socket.
Definition: Socket.h:1107
McSocketData()
Constructor.
Definition: McSocket.h:91
SocketT * accept(Inet4PacketInfoX &)
Like ServerSocket::accept(), this method will return a connected socket.
Definition: McSocket.h:669
Definition: McSocket.h:63
Definition: Inet4PacketInfo.h:92
int run()
The method which will run in its own thread.
Definition: McSocket.h:869
struct McSocketData mcdata
Definition: McSocket.h:146
void log(va_alist)
Build a message from a printf-format string and variable args, and log the message.
Definition: Logger.cc:444
const SocketAddress & getLocalSocketAddress() const
Fetch the local address that this socket is bound to.
Definition: Socket.h:834
A stream (TCP) socket that is used to listen for connections.
Definition: Socket.h:755
void blockSignal(int)
Block a signal in this thread.
Definition: Thread.cc:211
friend class McSocketMulticaster
Definition: McSocket.h:214
void setMagic(int val)
Definition: McSocket.h:118
int getMcSocketType(McSocket< Socket > *)
Definition: McSocket.h:153
bool _socketOffered
Definition: McSocket.h:438
int getRequestType() const
Definition: McSocket.h:120
#define LOG_ERR
Definition: Logger.h:207
Definition: Exception.h:35
void setInterface(Inet4NetworkInterface iaddr)
Set a specific interface for the multicasts.
Definition: McSocket.h:309
Thread which is started by McSocket to multicast requests for connections.
Definition: McSocket.h:554
static Logger * getInstance()
Retrieve the current Logger singleton instance.
Definition: Logger.cc:293
Definition: Thread.h:80
Socket * accept()
Accept connection, return a connected Socket instance.
Definition: Socket.h:808
const SocketAddress & getLocalSocketAddress() const
Get local address of this socket.
Definition: Socket.h:1099
std::list< Inet4NetworkInterface > getInterfaces() const
Return all network interfaces on this system.
Definition: McSocket.h:641
Definition: Inet4NetworkInterface.h:35
virtual ~McSocketMulticaster()
Definition: McSocket.h:833
A McSocket provides a way to establish a TCP stream socket connection, or a pair of UDP datagram sock...
Definition: McSocket.h:151
void lock()
Lock the Mutex.
Definition: ThreadSupport.h:206
static void accept(McSocket< Socket > *sock)
How a McSocket&lt;Socket&gt; registers with a McSocketListener.
Definition: McSocket.cc:95
Inet4NetworkInterface _iface
Definition: McSocket.h:428
int getLocalPort() const
Definition: Socket.h:839
McSocket< SocketT > & operator=(const McSocket< SocketT > &rhs)
Assignment operator.
Definition: McSocket.h:623
A DatagramPacket with a specific structure of data.
Definition: DatagramPacket.h:178
virtual int getLength() const
Get the value for the current number of bytes in data.
Definition: DatagramPacket.h:135
#define VLOG(MSG)
Definition: Logger.h:307
const SocketAddress & getRemoteSocketAddress() const
Get remote address of this socket.
Definition: Socket.h:677
Definition: IOException.h:37
void wait()
Wait on the condition variable.
Definition: ThreadSupport.cc:306
Inet4NetworkInterface getInterface() const
Definition: McSocket.h:313
Inet4Address getInet4Address() const
Return the IP address portion.
Definition: Inet4SocketAddress.h:91
void joinMulticaster()
Definition: McSocket.h:726
void offer(SocketT *sock, const Inet4PacketInfoX &pktinfo)
How a McSocketListener passes back a connected TCP socket or DatagramSocket.
Definition: McSocket.h:756
int getPort() const
Return the port number.
Definition: Inet4SocketAddress.h:81
void close()
close the socket.
Definition: Socket.cc:1549
A stream (TCP) socket.
Definition: Socket.h:430
int getSocketType() const
What socket type does the requester want to establish? SOCK_STREAM or SOCK_DGRAM. ...
Definition: McSocket.h:135
virtual const char * what() const
Definition: Exception.h:98
A wrapper class for a Posix condition variable.
Definition: ThreadSupport.h:245
std::list< Inet4NetworkInterface > getInterfaces() const
Return the IP addresses of all my network interfaces.
Definition: Socket.h:1385
virtual void setDestinationAddress(const Inet4Address &val)
Definition: Inet4PacketInfo.h:65
static void close(McSocket< Socket > *sock)
Remove the given McSocket from the list being served by this listener.
Definition: McSocket.cc:151
short _socketType
Either SOCK_STREAM=1, or SOCK_DGRAM=2.
Definition: McSocket.h:86
virtual void interrupt()
Interrupt this thread.
Definition: Thread.cc:600
In certain situations one needs to &quot;join oneself&quot;, which would be a deadlock.
Definition: Thread.h:573
#define NSECS_PER_SEC
Definition: types.h:98
void setSocketAddress(const SocketAddress &val)
Definition: DatagramPacket.h:102
virtual void connected(SocketT *, const Inet4PacketInfoX &)
Virtual method that is called when a socket connection is established.
Definition: McSocket.h:385
const SocketAddress & getLocalSocketAddress() const
Get local address of this socket.
Definition: Socket.h:691
#define WLOG(MSG)
Definition: Logger.h:303
#define DLOG(MSG)
Definition: Logger.h:306
virtual struct sockaddr * getConstSockAddrPtr() const =0
void unlock()
Unlock the mutex associated with the condition variable.
Definition: ThreadSupport.h:299
#define PLOG(MSG)
Definition: Logger.h:302
void setInterface(Inet4Address maddr, const Inet4NetworkInterface &iface)
Set the interface for a given multicast address.
Definition: Socket.h:1355
void setRequestType(int val)
Set the request type value.
Definition: McSocket.h:340
A C++ wrapper for a POSIX mutex.
Definition: ThreadSupport.h:154
int getRequestType() const
Get the request type number.
Definition: McSocket.h:345
void setInet4McastSocketAddress(const Inet4SocketAddress &val)
Set the multicast address for listening to requests.
Definition: McSocket.h:332
virtual void close()
Unregister this McSocket from the multicasting and listening threads.
Definition: McSocket.h:793
virtual bool isRunning() const
Is this thread running?
Definition: Thread.h:266
void setRequestType(int val)
Definition: McSocket.h:122
Support for IP version 4 host address.
Definition: Inet4Address.h:46
int magic
Magic value that should be found at the beginning of all received datagrams.
Definition: McSocket.h:68
void unlock()
Unlock the Mutex.
Definition: ThreadSupport.h:218