ROOT logo
// $Id: UdpPacketListener.cxx 2667 2012-02-25 02:21:06Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "UdpPacketListener.h"
#include "UdpPacketListener.c7"

#include "Stones/SUdpPacket.h"

#include "Gled/GThread.h"

#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

// UdpPacketListener

//______________________________________________________________________________
//
//

ClassImp(UdpPacketListener);

//==============================================================================

void UdpPacketListener::_init()
{
  mSuckPort     = 9930;
  mSocket       = 0;
  mSuckerThread = 0;
}

UdpPacketListener::UdpPacketListener(const Text_t* n, const Text_t* t) :
  UdpPacketSource(n, t)
{
  _init();
}

UdpPacketListener::~UdpPacketListener()
{}

//==============================================================================

void* UdpPacketListener::tl_Suck(UdpPacketListener* s)
{
  s->Suck();
  s->mSuckerThread = 0;
  return 0;
}

void UdpPacketListener::Suck()
{
  static const Exc_t _eh("UdpPacketListener::Suck ");

  if ((mSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    throw _eh + "socket failed: " + strerror(errno);

  {
    struct addrinfo *result;
    struct addrinfo  hints;
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family   = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_protocol = IPPROTO_UDP;
    hints.ai_flags    = AI_PASSIVE | AI_NUMERICSERV;

    int error = getaddrinfo(0, TString::Format("%hu", mSuckPort), &hints, &result);
    if (error != 0)
      throw _eh + "getaddrinfo failed: " + gai_strerror(error);

    if (bind(mSocket, result->ai_addr, result->ai_addrlen) == -1)
      throw _eh + "bind failed: " + strerror(errno);

    freeaddrinfo(result);
  }

  const int     buf_size = 65536;
  unsigned char buf[buf_size];
  int           flags = 0;

  struct sockaddr_in addr;
  socklen_t slen = sizeof(sockaddr_in);

  while (true)
  {
    ssize_t len = recvfrom(mSocket, buf, buf_size, flags,
			   (sockaddr*) &addr, &slen);
    if (len == -1)
    {
      ISwarn(_eh + "recvfrom failed: " + strerror(errno));
      continue;
    }
    else if (len == 0)
    {
      ISwarn(_eh + "recvfrom returned 0, not expected.");
      continue;
    }

    GTime recv_time(GTime::I_Now);

    /*
      XrdXrootdMonHeader *xmh = (XrdXrootdMonHeader*) buf;
      Char_t   code = xmh->code;
      UChar_t  pseq = xmh->pseq;
      UShort_t plen = ntohs(xmh->plen);
      Int_t    stod = ntohl(xmh->stod);

      if (len != plen)
      {
      ISerr(_eh + GForm("message size mismatch: got %zd, xrd-len=%hu (bufsize=%zd).", len, plen, buf_size));
      // This means either our buf-size is too small or the other guy is pushing it.
      // Should probably stop reporting errors from this IP.
      // XXXX Does it really help having it on stack?
      // XXXX Anyway, do additional checks in here about buf-size, got less, etc.
      continue;
      }
    */

    UInt_t   in4a = addr.sin_addr.s_addr; // Kept in net order
    UShort_t port = ntohs(addr.sin_port);

    UChar_t *addr_p = (UChar_t*) &addr.sin_addr.s_addr;

    SUdpPacket *p =  new SUdpPacket(recv_time, addr_p, 4, port, buf, len);

    if (G_DEBUG > 1)
    {
      Char_t   hn_buf[64];
      getnameinfo((sockaddr*) &addr, slen, hn_buf, 64, 0, 0, NI_DGRAM);

      TString fqhn(hn_buf);
      fqhn.ToLower();

      char *foo = (char*) &in4a;
      printf("Message from: %hhu.%hhu.%hhu.%hhu:%hu, fqdn=%s, len=%zd\n",
             foo[0], foo[1], foo[2], foo[3], port, hn_buf, len);
    }

    mConsumerSet.DeliverToQueues(p);
  }
}

//==============================================================================

void UdpPacketListener::StartAllServices()
{
  static const Exc_t _eh("UdpPacketListener::StartAllServices ");

  {
    GLensReadHolder _lck(this);
    if (mSuckerThread)
      throw _eh + "already running.";

    mSuckerThread = new GThread("UdpPacketListener-Sucker",
                                (GThread_foo) tl_Suck, this,
                                false);
    mSuckerThread->SetNice(0);
  }

  mSuckerThread->Spawn();
}

void UdpPacketListener::StopAllServices()
{
  static const Exc_t _eh("UdpPacketListener::StopAllServices ");

  GThread *thr = 0;
  {
    GLensReadHolder _lck(this);
    if ( ! GThread::IsValidPtr(mSuckerThread))
      throw _eh + "not running.";
    thr = mSuckerThread;
    GThread::InvalidatePtr(mSuckerThread);
  }

  thr->Cancel();
  thr->Join();
  close(mSocket);

  {
    GLensReadHolder _lck(this);
    mSuckerThread = 0;
    mSocket = 0;
  }
}
 UdpPacketListener.cxx:1
 UdpPacketListener.cxx:2
 UdpPacketListener.cxx:3
 UdpPacketListener.cxx:4
 UdpPacketListener.cxx:5
 UdpPacketListener.cxx:6
 UdpPacketListener.cxx:7
 UdpPacketListener.cxx:8
 UdpPacketListener.cxx:9
 UdpPacketListener.cxx:10
 UdpPacketListener.cxx:11
 UdpPacketListener.cxx:12
 UdpPacketListener.cxx:13
 UdpPacketListener.cxx:14
 UdpPacketListener.cxx:15
 UdpPacketListener.cxx:16
 UdpPacketListener.cxx:17
 UdpPacketListener.cxx:18
 UdpPacketListener.cxx:19
 UdpPacketListener.cxx:20
 UdpPacketListener.cxx:21
 UdpPacketListener.cxx:22
 UdpPacketListener.cxx:23
 UdpPacketListener.cxx:24
 UdpPacketListener.cxx:25
 UdpPacketListener.cxx:26
 UdpPacketListener.cxx:27
 UdpPacketListener.cxx:28
 UdpPacketListener.cxx:29
 UdpPacketListener.cxx:30
 UdpPacketListener.cxx:31
 UdpPacketListener.cxx:32
 UdpPacketListener.cxx:33
 UdpPacketListener.cxx:34
 UdpPacketListener.cxx:35
 UdpPacketListener.cxx:36
 UdpPacketListener.cxx:37
 UdpPacketListener.cxx:38
 UdpPacketListener.cxx:39
 UdpPacketListener.cxx:40
 UdpPacketListener.cxx:41
 UdpPacketListener.cxx:42
 UdpPacketListener.cxx:43
 UdpPacketListener.cxx:44
 UdpPacketListener.cxx:45
 UdpPacketListener.cxx:46
 UdpPacketListener.cxx:47
 UdpPacketListener.cxx:48
 UdpPacketListener.cxx:49
 UdpPacketListener.cxx:50
 UdpPacketListener.cxx:51
 UdpPacketListener.cxx:52
 UdpPacketListener.cxx:53
 UdpPacketListener.cxx:54
 UdpPacketListener.cxx:55
 UdpPacketListener.cxx:56
 UdpPacketListener.cxx:57
 UdpPacketListener.cxx:58
 UdpPacketListener.cxx:59
 UdpPacketListener.cxx:60
 UdpPacketListener.cxx:61
 UdpPacketListener.cxx:62
 UdpPacketListener.cxx:63
 UdpPacketListener.cxx:64
 UdpPacketListener.cxx:65
 UdpPacketListener.cxx:66
 UdpPacketListener.cxx:67
 UdpPacketListener.cxx:68
 UdpPacketListener.cxx:69
 UdpPacketListener.cxx:70
 UdpPacketListener.cxx:71
 UdpPacketListener.cxx:72
 UdpPacketListener.cxx:73
 UdpPacketListener.cxx:74
 UdpPacketListener.cxx:75
 UdpPacketListener.cxx:76
 UdpPacketListener.cxx:77
 UdpPacketListener.cxx:78
 UdpPacketListener.cxx:79
 UdpPacketListener.cxx:80
 UdpPacketListener.cxx:81
 UdpPacketListener.cxx:82
 UdpPacketListener.cxx:83
 UdpPacketListener.cxx:84
 UdpPacketListener.cxx:85
 UdpPacketListener.cxx:86
 UdpPacketListener.cxx:87
 UdpPacketListener.cxx:88
 UdpPacketListener.cxx:89
 UdpPacketListener.cxx:90
 UdpPacketListener.cxx:91
 UdpPacketListener.cxx:92
 UdpPacketListener.cxx:93
 UdpPacketListener.cxx:94
 UdpPacketListener.cxx:95
 UdpPacketListener.cxx:96
 UdpPacketListener.cxx:97
 UdpPacketListener.cxx:98
 UdpPacketListener.cxx:99
 UdpPacketListener.cxx:100
 UdpPacketListener.cxx:101
 UdpPacketListener.cxx:102
 UdpPacketListener.cxx:103
 UdpPacketListener.cxx:104
 UdpPacketListener.cxx:105
 UdpPacketListener.cxx:106
 UdpPacketListener.cxx:107
 UdpPacketListener.cxx:108
 UdpPacketListener.cxx:109
 UdpPacketListener.cxx:110
 UdpPacketListener.cxx:111
 UdpPacketListener.cxx:112
 UdpPacketListener.cxx:113
 UdpPacketListener.cxx:114
 UdpPacketListener.cxx:115
 UdpPacketListener.cxx:116
 UdpPacketListener.cxx:117
 UdpPacketListener.cxx:118
 UdpPacketListener.cxx:119
 UdpPacketListener.cxx:120
 UdpPacketListener.cxx:121
 UdpPacketListener.cxx:122
 UdpPacketListener.cxx:123
 UdpPacketListener.cxx:124
 UdpPacketListener.cxx:125
 UdpPacketListener.cxx:126
 UdpPacketListener.cxx:127
 UdpPacketListener.cxx:128
 UdpPacketListener.cxx:129
 UdpPacketListener.cxx:130
 UdpPacketListener.cxx:131
 UdpPacketListener.cxx:132
 UdpPacketListener.cxx:133
 UdpPacketListener.cxx:134
 UdpPacketListener.cxx:135
 UdpPacketListener.cxx:136
 UdpPacketListener.cxx:137
 UdpPacketListener.cxx:138
 UdpPacketListener.cxx:139
 UdpPacketListener.cxx:140
 UdpPacketListener.cxx:141
 UdpPacketListener.cxx:142
 UdpPacketListener.cxx:143
 UdpPacketListener.cxx:144
 UdpPacketListener.cxx:145
 UdpPacketListener.cxx:146
 UdpPacketListener.cxx:147
 UdpPacketListener.cxx:148
 UdpPacketListener.cxx:149
 UdpPacketListener.cxx:150
 UdpPacketListener.cxx:151
 UdpPacketListener.cxx:152
 UdpPacketListener.cxx:153
 UdpPacketListener.cxx:154
 UdpPacketListener.cxx:155
 UdpPacketListener.cxx:156
 UdpPacketListener.cxx:157
 UdpPacketListener.cxx:158
 UdpPacketListener.cxx:159
 UdpPacketListener.cxx:160
 UdpPacketListener.cxx:161
 UdpPacketListener.cxx:162
 UdpPacketListener.cxx:163
 UdpPacketListener.cxx:164
 UdpPacketListener.cxx:165
 UdpPacketListener.cxx:166
 UdpPacketListener.cxx:167
 UdpPacketListener.cxx:168
 UdpPacketListener.cxx:169
 UdpPacketListener.cxx:170
 UdpPacketListener.cxx:171
 UdpPacketListener.cxx:172
 UdpPacketListener.cxx:173
 UdpPacketListener.cxx:174
 UdpPacketListener.cxx:175
 UdpPacketListener.cxx:176
 UdpPacketListener.cxx:177
 UdpPacketListener.cxx:178
 UdpPacketListener.cxx:179
 UdpPacketListener.cxx:180
 UdpPacketListener.cxx:181
 UdpPacketListener.cxx:182
 UdpPacketListener.cxx:183
 UdpPacketListener.cxx:184
 UdpPacketListener.cxx:185
 UdpPacketListener.cxx:186
 UdpPacketListener.cxx:187
 UdpPacketListener.cxx:188
 UdpPacketListener.cxx:189