hi

hi
is it a bug of OpenH323?
i have a problem in using openh323,  in the OpenH323 transmission channel, i am send more than 65K of the size of the data, it will not be sent out.
Jan Willamowius | 14 Apr 15:05 2016
Picon

GNU Gatekeeper Survey 2016

Dear GnuGk community,

I have compiled a quick survey where you can indicate what you like
about GnuGk and what is missing. Please feel free to add any other
suggestions you may have.

http://www.gnugk.org/survey-2016.html

In the past, these surveys have always been a great inspiration.

Thanks for your time!

Jan

--

-- 
Jan Willamowius, Founder of the GNU Gatekeeper Project
EMail  : jan <at> willamowius.de
Website: http://www.gnugk.org
Support: http://www.willamowius.com/gnugk-support.html

Relaxed Communications GmbH
Frahmredder 91
22393 Hamburg
Geschäftsführer: Jan Willamowius
HRB 125261 (Amtsgericht Hamburg)
USt-IdNr: DE286003584

Leonardo Nahra | 26 Feb 16:27 2016
Picon

h323plus text messaging

Hello,

I'm working on a conference project,and we will use the H.323 protocol to establish a connection between monitors, so they can exchange information about configuration options of the video stream they'll receive.

So, once a call is established, in addition of exchanging video and audio (that we already have implemented apart), configuration options need to be sent in text format back and forth.

Searching through h323plus I couldn't find a way to send text in a call, can you give me some pointers on how to accomplish that?

Thanks, Nahra.
Jan Willamowius | 16 Feb 15:50 2016
Picon

GNU Gatekeeper 4.1 released

Hi,

I'm happy to announce the availability of GNU Gatekeeper 4.1.

This is mainly a bug fix release. If you are using GnuGk as a server in
a traversal zone or if you do H.239 presentations with Avaya endpoints,
you are strongly encouraged to update. This version also fixes a memory
leak that mainly affects long running gatekeepers with a lot of RAS
traffic. Some of the bugs were long standing, so if you skipped some
previous releases, this is really a good time to update.

The main new feature in this release is expanded LUA support.
Besides LUA authentication and LUA routing, there is now a LuaAcct
module that allows you to run a script on every accounting event of your
choice. Please see the updated manual for details.

You can download the new version from
http://www.gnugk.org/h323download.html

Please see the full change log attached to the end of this mail.

My support website https://www.willamowius.com also got a face lift.
Please check it out as well.

Enjoy!

-- 
Jan Willamowius, Founder of the GNU Gatekeeper Project
EMail  : jan <at> willamowius.de
Website: http://www.gnugk.org
Support: http://www.willamowius.com/gnugk-support.html

Relaxed Communications GmbH
Frahmredder 91
22393 Hamburg
Geschäftsführer: Jan Willamowius
HRB 125261 (Amtsgericht Hamburg)
USt-IdNr: DE286003584

Changes from 4.0 to 4.1
=======================
- BUGFIX(ProxyChannel.cxx) fix crash processing Setup
- BUGFIX(RasSrv.cxx) update IP/port of traversal neighbor on every SCI,
  not only on IP changes
- new status port command: PrintNeighbors
- BUGFIX(ProxyChannel.cxx) fix H.239 inside multiplePayloadStream from
  Avaya XT5000 with H.460.19
- new accounting module: LuaAcct
- LUA: new library "gnugk" to allow access to GnuGk functionality
- BUGFIX(configure) set all detected options in gnugkbuildopts.h on Unix
- BUGFIX(ProxyChannel.cxx) removing H.235 capabilities might have
  skipped items
- BUGFIX(lua.cxx) initialize all LUA variables for LUA routing
- status port configuration (MaxStatusClients, StatusEventBacklog,
  StatusEventBacklogRegex) now changable at runtime
- BUGFIX(GkStatus.cxx) fix StatusEventBacklogRegex for patterns that
  start at the beginning of the event line
- BUGFIX(ProxyChannel.cxx) use RealPresence Group 0-Byte keep-alive for
  IgnoreSignaledH239PrivateIPs (needs LARGE_FDSET to work)
- new switches to set database connect and read timeout (only used by
  MySQL for now)
- new switch to set worker thread idle timeout: [Gatekeeper::Main]
  WorkerThreadIdleTimeout=
- BUGFIX(gk.cxx) better test for gatekeeper shutdown
- BUGFIX(Routing.cxx) fix fromIP for ARQ and LRQ RouteRequests
- BUGFIX(gkauth.cxx) only call Q.931 checks when activated
- BUGFIX(Routing.cxx) fix RouteRequest from unregistered caller who
  doesn't provide any alias
- new switch: [RoutedMode] DisableSettingUDPSourceIP=1

Iurii Gordiienko | 22 Jan 14:08 2016
Picon

H323Connection concurrent access issue

Hi all,

I found an issue with concurrent access during work with H323Connection.
Take a look on H46018Transport::HandleH46018SignallingChannelPDU(PThread * thread)

Simplest schema of this function running:

thread1:
H46018Transport::HandleH46018SignallingChannelPDU(PThread * thread)
{
...
H323Connection * connection = endpoint.CreateConnection(callReference, NULL, this, &pdu);
...
connection->AttachSignalChannel(token, this, true); 
...
connection->HandleSignallingChannel();
...
return connection->HadAnsweredCall();
}

The function connection->HandleSignallingChannel() in really working with "this" (H46018Transport object) all time in the while-loop.

! iv>
thread2:
H323EndPoint::CleanUpConnections() running. In this thread we are running:
1.connection.CleanUpOnCallEnd() - this function will call CleanUpOnTermination() for signallingChannel (H46018Transport object) which running in connection->HandleSignallingChannel() function.
2.delete current H323Connection (which will delete our signallingChannel object also)

The concurrent access issue - in time when we are running connection->HandleSignallingChannel() function from  thread1, the H323Connection object can be deleted and signallingChannel will points to dead object - we have a crash in result. Also it is possible to run the connection->HadAnsweredCall() function for dead "connection" object.

I have had the crash several times for this situation.


Thanks
--
Iurii Gordiienko
Iurii Gordiienko | 21 Jan 18:10 2016
Picon

Bug inH323Capabilities::Remove(H323Capability*)

Hi,

I found a bug - H323Capabilities::Remove function will skip item when doing .RemoveAt operation. In result I have had a crash (in line if (set[outer][middle][inner].GetCapabilityNumber() == capabilityNumber)) for some sets of capabilities.
I can't understand why the crash is occurs but in any way...


Original code:

void H323Capabilities::Remove(H323Capability * capability)
{
  if (capability == NULL)
    return;

  PTRACE(3, "H323\tRemoving capability: " << *capability);

  unsigned capabilityNumber = capability->GetCapabilityNumber();

  for (PINDEX outer = 0; outer < set.GetSize(); outer++) {
    for (PINDEX middle = 0; middle < set[outer].GetSize(); middle++) {! div>
      for (PINDEX inner = 0; inner < set[outer][middle].GetSize(); inner++) {
        if (set[outer][middle][inner].GetCapabilityNumber() == capabilityNumber) {
          set[outer][middle].RemoveAt(inner);
          break;
        }
      }
      if (set[outer][middle].GetSize() == 0)
        set[outer].RemoveAt(middle);

    }
    if (set[outer].GetSize() == 0)
        set.RemoveAt(outer);
  }


My fi x:

void H323Capabilities::Remove(H323Capability * capability)
{
  if (capability == NULL)
    return;
  PTRACE(3, "H323\tRemoving capability: " << *capability);

  unsigned capabilityNumber = capability->GetCapabilityNumber();

  for (PINDEX outer = 0; outer < set.GetSize(); ) {
    for (PINDEX middle = 0; middle < set[outer].GetSize(); ) {
      for (PINDEX inner = 0; inner < set[outer][middle].GetSize(); inner++) {
        if (set[outer][middle][inner].GetCapabilityNumber() == capabilityNumber) {
          set[outer][middle].RemoveAt(inner);
          break;
        }
      }
  & nbsp;   if (set[outer][middle].GetSize())
        ++middle;
      else
        set[outer].RemoveAt(middle);

    }
  &nb! sp; if (set[outer].GetSize())
        ++outer;
    else
        set.RemoveAt(outer);
  }

Thanks
--
Iurii Gordiienko
!
Iurii Gordiienko | 15 Jan 16:08 2016
Picon

H323EndPoint::ParsePartyName issue

Hi,

I'm working with ForwardCall functional and have found a bug if we have forward URL which contains PORT number.
For example, for h323: <at> 192.168.1.1:1726 input string H323EndPoint::ParsePartyName will make address string like ip$192.168.1.1:1726:1726.

The fix is trivial (may be I've not covered all cases):

  // get the various parts of the name
  PString hostOnly = PString();
  PINDEX userPos = remoteParty.Find(' <at> ');
  if (userPos != P_MAX_INDEX) {
    if (gatekeeper != NULL)
      alias = url.AsString();
    else {
      alias = remoteParty.Left(userPos);
      PINDEX portPos = remoteParty.FindLast(':', portPos + 1);
      PINDEX len = (portPos != P_MAX_IND! EX) ? (portPos - userPos - 1) : P_MAX_INDEX;
      hostOnly = remoteParty.Mid(userPos+1, len);
    }
  } else {
     alias = url.GetUserName();
     hostOnly = url.GetHostName();
  } 
  address = hostOnly;



Also we have similar issue for input string without ' <at> ' character. In this case PTLIB::PURL class wrong parse the string (uses 192.168.1.1:1726:1726 as USER).

To fix this issue we need look PTLIB::PURL class futher.

Thanks
--
Iurii Gordiienko
Iurii Gordiienko | 11 Jan 12:46 2016
Picon

Issue with H.263 codecs set

Hi all,

I need an advice - how to work with set of H.263 codecs.
Basically, I have all H.263 codec types capability implemented: H.263, H.263-1998 and H.263-2000. All these capabilities uses same H245_VideoCapability::e_h263VideoCapability value for GetSubType function. In result my localCapabilities variable has all these 3 capabilities as well.

When I receiving remote capabilities the remoteCapabilities variable is loading by H323Capabilities::H323Capabilities(const H323Connection & connection, const H245_TerminalCapabilitySet & pdu) constructor and the function uses code like this (simplified):

H323Capability * capability = localCapabilities.FindCapabil ity(pdu.m_capabilityTable[i].m_capability, capabilityNo, pdu);
if (capability != NULL) 
{
          H323Capability * copy = (H323! Capability *)capability->Clone();
          copy->SetCapabilityNumber(capabilityNo);
          if (copy->OnReceivedPDU(pdu.m_capabilityTable[i].m_capability))
            table.Append(copy);
          else
            delete copy;
}

The main issue -  localCapabilities.FindCapability function returns any first H.263 Capability from it's table, no matter which particular H.263 remote Capability was used, it only checks MainType and SubType... In result if remote side send me, for example, H.263-1998, but I have H.263 and H.263-1998 - I will have H.263 in result... 

Now I'm trying to override Connection::OnReceivedCapabilitySet(const H245_TerminalCapabilitySet & pdu) function, extract H.263 codecs manually, st! ore all these capabilities and update remoteCapabilities after, but may be exists a proper solution for this case?


Thanks
--
Iurii Gordiienko
!
Iurii Gordiienko | 8 Jan 17:03 2016
Picon

Double-delete Capability bug

Hi,

I have found something...
For H323ExtendedVideoCapability::AddAllCapabilities function we are using H323CodecExtendedVideoCapability::AddCapability function for extCapability->AddCapability(*r).
H323CodecExtendedVideoCapability::AddCapability function uses extCapabilities.Add(H323ExtendedVideoFactory::CreateInstance(cap)) function. The function H323ExtendedVideoFactory::CreateInstance(cap) will call "new" if any same "cap" does not is exists for now< for other case it will return the pointer to current actual Capability. But H323CodecExtendedVideoCapability::extCapabilities will delete all items in time of execution 
extCapabilities.RemoveAll() function from H323CodecExtendedVideoCa pability::~H323CodecExtendedVideoCapability(). In result we have "double delete" and undefined behavior (crash for worst case).

------------------------------! --

void H323ExtendedVideoCapability::AddAllCapabilities(
      H323Capabilities & basecapabilities, PINDEX descriptorNum,PINDEX simultaneous)
{
  H323ExtendedVideoFactory::KeyList_T extCaps = H323ExtendedVideoFactory::GetKeyList();
  if (extCaps.size() > 0) {
    H323CodecExtendedVideoCapability * capability = new H323CodecExtendedVideoCapability();
    H323ExtendedVideoFactory::KeyList_T::const_iterator r;
        PINDEX num = P_MAX_INDEX;
        for (r = extCaps.begin(); r != extCaps.end(); ++r) {
           H323CodecExtendedVideoCapability * extCapab ility = (H323CodecExtendedVideoCapability *)capability->Clone();
           extCapability->AddCapability(*r);
      &n! bsp;    num = basecapabilities.SetCapability(descriptorNum, simultaneous,extCapability);
           simultaneous = num;
        }
    simultaneous = P_MAX_INDEX;
    basecapabilities.SetCapability(descriptorNum, simultaneous,new H323ControlExtendedVideoCapability());
    delete capability;
  } 
}

void H323CodecExtendedVideoCapability::AddCapability(const PString & cap)
{
    extCapabilities.Add(H323ExtendedVideoFactory::CreateInstance(cap));
}


-------------------------------------------------

I propose to replace the "void H323CodecExtendedVideoCapability::AddCapability(const PString & cap)" to this one:

void H323CodecExtendedVideoCapability::AddCapability(const PString & cap)
{
! >
    extCapabilities.Add(H323ExtendedVideoFactory::CreateInstance(cap)->clone());
}




Thanks
--
Iurii Gordiienko
!
Iurii Gordiienko | 31 Dec 11:40 2015
Picon

H323EndPoint::InternalMakeCall bug

Hi,

I have found an issue with H323EndPoint::InternalMakeCall function for case when it running from H323EndPoint::ForwardConnection function (may be for some others cases too).
Take a look:
1.We are trying to connect to some host which uses Gatekeeper.
2.From H323EndPoint::ForwardConnection call H323EndPoint::InternalMakeCall function with some internal token="ip$xxx.xxx.xxx.xxx/port"
3.In the body of H323EndPoint::InternalMakeCall we have the replacement current callToken-connection pair to new one with "ip$xxx.xxx.xxx.xxx/port-replaced-1" string, like
    
    connectionsActive.SetAt(adjustedToken, connectionsActive.RemoveAt(newToken)) ;
    connectionsToBeCleaned += adjustedToken;

4.But if for some reason our virtual CreateConnection function returns NULL...
  connection = CreateConnection(lastReference, userData, transport, NULL);
  if (connection == NULL) {
    PTRACE(1, "H323\tCreateConnection returned NULL");
    connectionsMutex.Signal();

    return NULL;
  }

 ... we cannot clear current Connection because it has not actual callToken "ip$xxx.xxx.xxx.xxx/port" but H323EndPoint::connectionsActive has "ip$xxx.xxx.xxx.xxx/port-replaced-1" and endpoint.ClearCall(callToken, reason) or something similar will be failed because not able to found the Connection by own callToken.

5.Also we have redundant call connectionsMutex.Signal().

if (connection == NULL) {
    PTRACE(1, "H323\tCreateConnection returned NULL");
    connectionsMutex.Signal();

    return NULL;
  }


My proposition - just rename back callToken for H323EndPoint::connectionsActive and remove adjustedToken from H323EndPoint::connectionsToBeCleaned if we have NULL connection.
My H323EndPoint::InternalMakeCall function looks like this:

H323Connection * H323EndPoint::InternalMakeCall(const PString & trasferFromToken,
                                                const PString & callIdentity,
                                &nbs p;               unsigned capabilityLevel,
                                                cons! t PString & remoteParty,
                                                H323Transport * transport,
                                                PString & newToken,
                                                void * userData,
                                              &nbsp ; PBoolean supplimentary
                                            !     )
{
  PTRACE(2, "H323\tMaking call to: " << remoteParty);

  PString alias;
  H323TransportAddress address;
  if (!ParsePartyName(remoteParty, alias, address)) {
    PTRACE(2, "H323\tCould not parse \"" << remoteParty << '"');
    return NULL;
  }

#ifdef H323_H46017
  // If H.460.17 use the existing H.460.17 Transport
  if (transport == NULL && RegisteredWithH46017())
      transport = GetH46017Transport();
#endif

  if (transport == NULL) {
    // Restriction: the call must be mad e on the same transport as the one
    // that the gatekeeper is using.
    if (gatekeeper != NULL)
      transport = gatekeeper->GetTransport().GetRemoteAddress().CreateTransport(*this);
! >

    // assume address is an IP address/hostname
    else
      transport = address.CreateTransport(*this);

    if (transport == NULL) {
      PTRACE(1, "H323\tInvalid transport in \"" << remoteParty << '"');
      return NULL;
    }
  }

  H323Connection * connection;

  connectionsMutex.Wait();

  PString adjustedToken;
  unsigned lastReference;
  if (newToken.IsEmpty()) {
    do {
      lastReference = Q931::GenerateCa llReference();
      newToken = BuildConnectionToken(*transport, lastReference, FALSE);
    } while (connectionsActive.Contains(newToken));
! >
  }
  else {
    lastReference = newToken.Mid(newToken.Find('/')+1).AsUnsigned();

    // Move old connection on token to new value and flag for removal
    unsigned tieBreaker = 0;
    do {
      adjustedToken = newToken + "-replaced";
      adjustedToken.sprintf("-%u", ++tieBreaker);
    } while (connectionsActive.Contains(adjustedToken));
    connectionsActive.SetAt(adjustedToken, connectionsActive.RemoveAt(newToken));
    connectionsToBeCleaned += adjustedToken;
    PTRACE(3, "H323\tOverwriting call " << newToken << ", renamed to " << adjustedToken);
  }
  connectionsMutex.Signal();

  connection = CreateConnection(lastReference, userData, transport, NULL);
  if (connection == NULL) {
  !   PTRACE(1, "H323\tCreateConnection returned NULL");
    
    if (!adjustedToken.IsEmpty())
    {
        connectionsMutex.Wait();

        connectionsActive.SetAt(newToken, connectionsActive.RemoveAt(adjustedToken));
        connectionsToBeCleaned -= adjustedToken;

        PTRACE(3, "H323\tOverwriting call " << adjustedToken << ", renamed to " << newToken);

        connectionsMutex.Signal();
    }

    return NULL;
  }
  con nection->SetRemotePartyName(remoteParty);

  if (supplimentary) 
      connection->SetNonCallConnection();    &nb! sp;

  connection->Lock();

  connectionsMutex.Wait();
  connectionsActive.SetAt(newToken, connection);

  connectionsMutex.Signal();

  connection->AttachSignalChannel(newToken, transport, FALSE);

#ifdef H323_H450
  if (capabilityLevel == UINT_MAX)
    connection->HandleTransferCall(trasferFromToken, callIdentity);
  else {
    connection->HandleIntrudeCall(trasferFromToken, callIdentity);
    connection->IntrudeCall(capabilityLevel);
  }
#endif

  PTRACE(3, "H323\tCreated new connection: " << newToken);

#ifdef H323_H46017
  if (RegisteredWithH46017()) {
    H323Connection::CallEndReason reason = connection->SendSignalSetup(alias, address);
  &! nbsp; if (reason != H323Connection::NumCallEndReasons)
      connection->ClearCall(reason);
  } else
#endif
      new H225CallThread(*this, *connection, *transport, alias, address);

  return connection;
}




Thanks
--
Iurii Gordiienko
!
Iurii Gordiienko | 28 Dec 12:30 2015
Picon

H323CodecExtendedVideoCapability::OnSendingPDUstrange behavior

Hi,

Take a look on the H323CodecExtendedVideoCapability::OnSendingPDU function.
I have had some issues with Extended capabilities and have fixed the issue only after change the view order - we need to look the .table first and only if it empty - work with extCapabilities.
For current implementation we always work the extCapabilities only because it always has GetSize()>0 (otherwise we return FALSE at the beginning of this function).

PBoolean H323CodecExtendedVideoCapability::OnSendingPDU(H245_VideoCapability & pdu, CommandType ctype) const 
    if (extCapabilities.GetSize() == 0)
        return FALSE;

   // bla-bla-bla
    
    if (extCapabilities.GetSize() > 0) {
      caps.SetSize(extCapabilities.GetSize());
      for (PINDEX i=0; i< extCapabilities.GetSize(); i++) {
         H245_VideoCapability vidcap;
         ((H323VideoCapability &)extCapabilities[i]).OnSendingPDU(vidcap,ctype);
         caps[i] = vidcap;
      }
    } else {
      caps.SetSize(table.GetSize());
      for (PINDEX i=0; i< table.GetSize(); i++) {
         H245_VideoCapability vidcap;
        ((H323VideoCapability &)table[i]).OnSendingPDU(vidcap,ctype);
        caps[i] = vidcap;
      }
    }

  return TRUE;
}


Thanks
--
Iurii Gordiienko
!

Gmane