Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package live555 for openSUSE:Factory checked 
in at 2026-11-10 14:38:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/live555 (Old)
 and      /work/SRC/openSUSE:Factory/.live555.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "live555"

Tue Nov 10 14:38:37 2026 rev:54 rq:1396219 version:2026.11.08

Changes:
--------
--- /work/SRC/openSUSE:Factory/live555/live555.changes  2026-11-01 
22:23:46.009862928 +0100
+++ /work/SRC/openSUSE:Factory/.live555.new.3759290/live555.changes     
2026-11-10 14:38:44.224338311 +0100
@@ -1,0 +2,17 @@
+Mon Nov  9 04:50:17 UTC 2026 - Bjørn Lie <[email protected]>
+
+- Update to version 2026.11.08:
+  * In "MultiFramedRTPSource" (for handling RTP reception), handle the case
+    where a malformed RTP special header could cause no data to get delivered,
+    and get us into an infinite loop. We now reject (the rest of) the packet in
+    this case.
+- Changes from version 2026.11.05:
+  * Updated the 'authentication' fix that we made in version 2026.09.23: We no
+    longer "reset()" the "Authenticator" if we get a "303" (REDIRECT) response,
+    because the new server might still want to do Digest authentication (with
+    the same username+password as the original server).
+    Instead, once we receive a request for Digest authentication, we no longer
+    allow Basic authentication (for this "RTSPClient") - either for the same
+    server, or for any server that we get redirected to.
+
+-------------------------------------------------------------------

Old:
----
  live.2026.10.24.tar.gz
  live.2026.10.29.tar.gz

New:
----
  live.2026.11.08.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ live555.spec ++++++
--- /var/tmp/diff_new_pack.IkWZGu/_old  2026-11-10 14:38:45.169377863 +0100
+++ /var/tmp/diff_new_pack.IkWZGu/_new  2026-11-10 14:38:45.170377905 +0100
@@ -19,7 +19,7 @@
 
 %define lmdmaj 122
 Name:           live555
-Version:        2026.10.29
+Version:        2026.11.08
 Release:        0
 Summary:        LIVE555 Streaming Media
 License:        LGPL-2.1-only

++++++ live.2026.10.24.tar.gz -> live.2026.11.08.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/BasicUsageEnvironment/BasicTaskScheduler.cpp 
new/live/BasicUsageEnvironment/BasicTaskScheduler.cpp
--- old/live/BasicUsageEnvironment/BasicTaskScheduler.cpp       2026-10-24 
05:04:52.000000000 +0200
+++ new/live/BasicUsageEnvironment/BasicTaskScheduler.cpp       2026-11-08 
17:12:02.000000000 +0100
@@ -17,6 +17,10 @@
 // Basic Usage Environment: for a simple, non-scripted, console application
 // Implementation
 
+// REMINDER: You should not make major changes to this code.  This code is 
intended to
+// implement just a basic, simple task scheduler.  If you want a more complex 
task scheduler,
+// then you should use subclassing, with separate source code files.
+// See: http://live555.com/liveMedia/faq.html#modifying-and-extending
 
 #include "BasicUsageEnvironment.hh"
 #include "HandlerSet.hh"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp 
new/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp
--- old/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp    2026-10-24 
05:04:52.000000000 +0200
+++ new/live/BasicUsageEnvironment/BasicUsageEnvironment.cpp    2026-11-08 
17:12:02.000000000 +0100
@@ -17,6 +17,11 @@
 // Basic Usage Environment: for a simple, non-scripted, console application
 // Implementation
 
+// REMINDER: You should not make major changes to this code.  This code is 
intended to
+// implement just a basic, simple "UsageEnvironment".  If you want a more 
complex implementation,
+// then you should use subclassing, with separate source code files.
+// See: http://live555.com/liveMedia/faq.html#modifying-and-extending
+
 #include "BasicUsageEnvironment.hh"
 #include <stdio.h>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh 
new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh
--- old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh     
2026-10-24 05:04:52.000000000 +0200
+++ new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh     
2026-11-08 17:12:02.000000000 +0100
@@ -19,8 +19,8 @@
 #ifndef _BASICUSAGEENVIRONMENT_VERSION_HH
 #define _BASICUSAGEENVIRONMENT_VERSION_HH
 
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING   "2026.10.24"
-#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT              1792800000
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING   "2026.11.08"
+#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT              1794096000
 
 extern char const* const BasicUsageEnvironmentLibraryVersionStr;
 extern int const BasicUsageEnvironmentLibraryVersionInt;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/live/UsageEnvironment/include/UsageEnvironment_version.hh 
new/live/UsageEnvironment/include/UsageEnvironment_version.hh
--- old/live/UsageEnvironment/include/UsageEnvironment_version.hh       
2026-10-24 05:04:52.000000000 +0200
+++ new/live/UsageEnvironment/include/UsageEnvironment_version.hh       
2026-11-08 17:12:02.000000000 +0100
@@ -19,8 +19,8 @@
 #ifndef _USAGEENVIRONMENT_VERSION_HH
 #define _USAGEENVIRONMENT_VERSION_HH
 
-#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING        "2026.10.24"
-#define USAGEENVIRONMENT_LIBRARY_VERSION_INT           1792800000
+#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING        "2026.11.08"
+#define USAGEENVIRONMENT_LIBRARY_VERSION_INT           1794096000
 
 extern char const* const UsageEnvironmentLibraryVersionStr;
 extern int const UsageEnvironmentLibraryVersionInt;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/config.linux-with-shared-libraries 
new/live/config.linux-with-shared-libraries
--- old/live/config.linux-with-shared-libraries 2026-10-24 05:05:53.000000000 
+0200
+++ new/live/config.linux-with-shared-libraries 2026-11-08 17:12:18.000000000 
+0100
@@ -4,7 +4,7 @@
 # One or more interfaces were added, but no existing interfaces were changed 
or removed => CURRENT += 1; REVISION = 0; AGE += 1
 
 libliveMedia_VERSION_CURRENT=122
-libliveMedia_VERSION_REVISION=1
+libliveMedia_VERSION_REVISION=5
 libliveMedia_VERSION_AGE=0
 libliveMedia_LIB_SUFFIX=so.$(shell expr $(libliveMedia_VERSION_CURRENT) - 
$(libliveMedia_VERSION_AGE)).$(libliveMedia_VERSION_AGE).$(libliveMedia_VERSION_REVISION)
 
@@ -19,7 +19,7 @@
 libUsageEnvironment_LIB_SUFFIX=so.$(shell expr 
$(libUsageEnvironment_VERSION_CURRENT) - 
$(libUsageEnvironment_VERSION_AGE)).$(libUsageEnvironment_VERSION_AGE).$(libUsageEnvironment_VERSION_REVISION)
 
 libgroupsock_VERSION_CURRENT=33
-libgroupsock_VERSION_REVISION=2
+libgroupsock_VERSION_REVISION=3
 libgroupsock_VERSION_AGE=0
 libgroupsock_LIB_SUFFIX=so.$(shell expr $(libgroupsock_VERSION_CURRENT) - 
$(libgroupsock_VERSION_AGE)).$(libgroupsock_VERSION_AGE).$(libgroupsock_VERSION_REVISION)
 #####
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/groupsock/Groupsock.cpp 
new/live/groupsock/Groupsock.cpp
--- old/live/groupsock/Groupsock.cpp    2026-10-24 05:04:52.000000000 +0200
+++ new/live/groupsock/Groupsock.cpp    2026-11-08 17:12:02.000000000 +0100
@@ -248,12 +248,12 @@
 }
 
 void Groupsock::multicastSendOnly() {
-  // We disable this code for now, because - on some systems - leaving the 
multicast group seems to cause sent packets
-  // to not be received by other applications (at least, on the same host).
+  // We disable this code for now, because - on some systems - leaving the 
multicast group seems
+  // to cause sent packets to not be received by other applications (at least, 
on the same host).
 #if 0
-  socketLeaveGroup(env(), socketNum(), groupAddress(r);
+  socketLeaveGroup(env(), socketNum(), groupAddress());
   for (destRecord* dests = fDests; dests != NULL; dests = dests->fNext) {
-    socketLeaveGroup(env(), socketNum(), dests->fGroupEId.groupAddress(r);
+    socketLeaveGroup(env(), socketNum(), dests->fGroupEId.groupAddress());
   }
 #endif
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/groupsock/include/groupsock_version.hh 
new/live/groupsock/include/groupsock_version.hh
--- old/live/groupsock/include/groupsock_version.hh     2026-10-24 
05:04:52.000000000 +0200
+++ new/live/groupsock/include/groupsock_version.hh     2026-11-08 
17:12:02.000000000 +0100
@@ -19,8 +19,8 @@
 #ifndef _GROUPSOCK_VERSION_HH
 #define _GROUPSOCK_VERSION_HH
 
-#define GROUPSOCK_LIBRARY_VERSION_STRING       "2026.10.24"
-#define GROUPSOCK_LIBRARY_VERSION_INT          1792800000
+#define GROUPSOCK_LIBRARY_VERSION_STRING       "2026.11.08"
+#define GROUPSOCK_LIBRARY_VERSION_INT          1794096000
 
 extern char const* const groupsockLibraryVersionStr;
 extern int const groupsockLibraryVersionInt;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/hlsProxy/live555HLSProxy.cpp 
new/live/hlsProxy/live555HLSProxy.cpp
--- old/live/hlsProxy/live555HLSProxy.cpp       2026-10-24 05:04:52.000000000 
+0200
+++ new/live/hlsProxy/live555HLSProxy.cpp       2026-11-08 17:12:02.000000000 
+0100
@@ -462,7 +462,7 @@
 
   // Then, rewrite our ".m3u8" file with the new list of segments:
   if (ourM3U8FileName == NULL) {
-    size_t fileNameSize = strlen(hlsPrefix) + 5/*strlen(".m3u8")*/ + 1;
+    size_t const fileNameSize = strlen(hlsPrefix) + 5/*strlen(".m3u8")*/ + 1;
     ourM3U8FileName = new char[fileNameSize];
     if (ourM3U8FileName == NULL) exit(1);
     snprintf(ourM3U8FileName, fileNameSize, "%s.m3u8", hlsPrefix);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/#RTPInterface.cpp# 
new/live/liveMedia/#RTPInterface.cpp#
--- old/live/liveMedia/#RTPInterface.cpp#       2026-10-24 05:04:52.000000000 
+0200
+++ new/live/liveMedia/#RTPInterface.cpp#       1970-01-01 01:00:00.000000000 
+0100
@@ -1,371 +0,0 @@
-@ RTPInterface::handleRead(socket %d): getpeername() returned %d: 
%s:0x%04x\n", tcpSocketNum, gpnResult, AddressString(fromAddress).val(), 
portNum(fromAddress));
-    
-    while ((curBytesRead = (fNextTCPReadTLSState != NULL && 
fNextTCPReadTLSState->isNeeded)
-           ? fNextTCPReadTLSState->read(&buffer[bytesRead], curBytesToRead)
-           : readSocket(envir(), fNextTCPReadStreamSocketNum,
-                        &buffer[bytesRead], curBytesToRead,
-                        fromAddress)) > 0) {
-      bytesRead += curBytesRead;
-      if (bytesRead >= totBytesToRead) break;
-      curBytesToRead -= curBytesRead;
-    }
-    fNextTCPReadSize -= bytesRead;
-    if (fNextTCPReadSize == 0) {
-      // We've read all of the data that we asked for
-      readSuccess = True;
-    } else if (curBytesRead < 0) {
-      // There was an error reading the socket
-      bytesRead = 0;
-      readSuccess = False;
-    } else {
-      // We need to read more bytes, and there was not an error reading the 
socket
-      packetReadWasIncomplete = True;
-      return True;
-    }
-    fNextTCPReadStreamSocketNum = -1; // default, for next time
-  }
-
-  if (readSuccess && fAuxReadHandlerFunc != NULL) {
-    // Also pass the newly-read packet data to our auxilliary handler:
-    (*fAuxReadHandlerFunc)(fAuxReadHandlerClientData, buffer, bytesRead);
-  }
-  return readSuccess;
-}
-
-void RTPInterface::stopNetworkReading() {
-  // Normal case
-  if (fGS != NULL) 
envir().taskScheduler().turnOffBackgroundReadHandling(fGS->socketNum());
-
-  // Also turn off read handling on each of our TCP connections:
-  for (tcpStreamRecord* streams = fTCPStreams; streams != NULL; streams = 
streams->fNext) {
-    deregisterSocket(envir(), streams->fStreamSocketNum, 
streams->fStreamChannelId);
-  }
-}
-
-
-////////// Helper Functions - Implementation /////////
-
-Boolean RTPInterface::sendRTPorRTCPPacketOverTCP(u_int8_t* packet, unsigned 
packetSize,
-                                                int socketNum, unsigned char 
streamChannelId,
-                                                TLSState* tlsState) {
-#ifdef DEBUG_SEND
-  fprintf(stderr, "sendRTPorRTCPPacketOverTCP: %d bytes over channel %d 
(socket %d)\n",
-         packetSize, streamChannelId, socketNum); fflush(stderr);
-#endif
-  // Send a RTP/RTCP packet over TCP, using the encoding defined in RFC 2326, 
section 10.12:
-  //     $<streamChannelId><packetSize><packet>
-  // (If the initial "send()" of '$<streamChannelId><packetSize>' succeeds, 
then we force
-  // the subsequent "send()" for the <packet> data to succeed, even if we have 
to do so with
-  // a blocking "send()".)
-  do {
-    u_int8_t framingHeader[4];
-    framingHeader[0] = '$';
-    framingHeader[1] = streamChannelId;
-    framingHeader[2] = (u_int8_t) ((packetSize&0xFF00)>>8);
-    framingHeader[3] = (u_int8_t) (packetSize&0xFF);
-    if (!sendDataOverTCP(socketNum, tlsState, framingHeader, 4, False)) break;
-
-    if (!sendDataOverTCP(socketNum, tlsState, packet, packetSize, True)) break;
-#ifdef DEBUG_SEND
-    fprintf(stderr, "sendRTPorRTCPPacketOverTCP: completed\n"); fflush(stderr);
-#endif
-
-    return True;
-  } while (0);
-
-#ifdef DEBUG_SEND
-  fprintf(stderr, "sendRTPorRTCPPacketOverTCP: failed! (errno %d)\n", 
envir().getErrno()); fflush(stderr);
-#endif
-  return False;
-}
-
-#ifndef RTPINTERFACE_BLOCKING_WRITE_TIMEOUT_MS
-#define RTPINTERFACE_BLOCKING_WRITE_TIMEOUT_MS 500
-#endif
-
-Boolean RTPInterface::sendDataOverTCP(int socketNum, TLSState* tlsState,
-                                     u_int8_t const* data, unsigned dataSize,
-                                     Boolean forceSendToSucceed) {
-  int sendResult = (tlsState != NULL && tlsState->isNeeded)
-    ? tlsState->write((char const*)data, dataSize)
-    : send(socketNum, (char const*)data, dataSize, MSG_NOSIGNAL/*flags*/);
-  if (sendResult < (int)dataSize) {
-    // The TCP send() failed - at least partially.
-
-    unsigned numBytesSentSoFar = sendResult < 0 ? 0 : (unsigned)sendResult;
-    if (numBytesSentSoFar > 0 || (forceSendToSucceed && envir().getErrno() == 
EAGAIN)) {
-      // The OS's TCP send buffer has filled up (because the stream's bitrate 
has exceeded
-      // the capacity of the TCP connection!).
-      // Force this data write to succeed, by blocking if necessary until it 
does:
-      unsigned numBytesRemainingToSend = dataSize - numBytesSentSoFar;
-#ifdef DEBUG_SEND
-      fprintf(stderr, "sendDataOverTCP: resending %d-byte send (blocking)\n", 
numBytesRemainingToSend); fflush(stderr);
-#endif
-      makeSocketBlocking(socketNum, RTPINTERFACE_BLOCKING_WRITE_TIMEOUT_MS);
-      sendResult = (tlsState != NULL && tlsState->isNeeded)
-       ? tlsState->write((char const*)(&data[numBytesSentSoFar]), 
numBytesRemainingToSend)
-       : send(socketNum, (char const*)(&data[numBytesSentSoFar]), 
numBytesRemainingToSend, MSG_NOSIGNAL/*flags*/);
-      makeSocketNonBlocking(socketNum);
-      if ((unsigned)sendResult != numBytesRemainingToSend) {
-       // The blocking "send()" failed, or timed out.  In either case, we 
assume that the
-       // TCP connection has failed (or is 'hanging' indefinitely), and we 
stop using it
-       // (for both RTP and RTP).
-       // (If we kept using the socket here, the RTP or RTCP packet write 
would be in an
-       //  incomplete, inconsistent state.)
-#ifdef DEBUG_SEND
-       fprintf(stderr, "sendDataOverTCP: blocking send() failed (delivering %d 
bytes out of %d); closing socket %d\n", sendResult, numBytesRemainingToSend, 
socketNum); fflush(stderr);
-#endif
-       removeStreamSocket(socketNum, 0xFF);
-       return False;
-      }
-
-      return True;
-    } else if (sendResult < 0 && envir().getErrno() != EAGAIN) {
-      // Because the "send()" call failed, assume that the socket is now 
unusable, so stop
-      // using it (for both RTP and RTCP):
-      removeStreamSocket(socketNum, 0xFF);
-    }
-
-    return False;
-  }
-
-  return True;
-}
-
-SocketDescriptor::SocketDescriptor(UsageEnvironment& env, int socketNum, 
TLSState* tlsState)
-  : fEnv(env), fOurSocketNum(socketNum), fTLSState(tlsState),
-    fSubChannelHashTable(HashTable::create(ONE_WORD_HASH_KEYS)),
-   fServerRequestAlternativeByteHandler(NULL), 
fServerRequestAlternativeByteHandlerClientData(NULL),
-   fReadErrorOccurred(False), fDeleteMyselfNext(False), 
fAreInReadHandlerLoop(False), fTCPReadingState(AWAITING_DOLLAR) {
-}
-
-SocketDescriptor::~SocketDescriptor() {
-  fDeleteMyselfNext = False;
-  fEnv.taskScheduler().turnOffBackgroundReadHandling(fOurSocketNum);
-  removeSocketDescription(fEnv, fOurSocketNum);
-
-  if (fSubChannelHashTable != NULL) {
-    // Remove knowledge of this socket from any "RTPInterface"s that are using 
it:
-    HashTable::Iterator* iter = 
HashTable::Iterator::create(*fSubChannelHashTable);
-    RTPInterface* rtpInterface;
-    char const* key;
-
-    while ((rtpInterface = (RTPInterface*)(iter->next(key))) != NULL) {
-      u_int64_t streamChannelIdLong = (u_int64_t)key;
-      unsigned char streamChannelId = (unsigned char)streamChannelIdLong;
-
-      rtpInterface->removeStreamSocket(fOurSocketNum, streamChannelId);
-    }
-    delete iter;
-
-    // Then remove the hash table entries themselves, and then remove the hash 
table:
-    while (fSubChannelHashTable->RemoveNext() != NULL) {}
-    delete fSubChannelHashTable;
-  }
-
-  // Finally:
-  if (fServerRequestAlternativeByteHandler != NULL) {
-    // Hack: Pass a special character to our alternative byte handler, to tell 
it that either
-    // - an error occurred when reading the TCP socket, or
-    // - no error occurred, but it needs to take over control of the TCP 
socket once again.
-    u_int8_t specialChar = fReadErrorOccurred ? 0xFF : 0xFE;
-    
(*fServerRequestAlternativeByteHandler)(fServerRequestAlternativeByteHandlerClientData,
 specialChar);
-  }
-}
-
-void SocketDescriptor::registerRTPInterface(unsigned char streamChannelId,
-                                           RTPInterface* rtpInterface) {
-  Boolean isFirstRegistration = fSubChannelHashTable->IsEmpty();
-#if defined(DEBUG_SEND)||defined(DEBUG_RECEIVE)
-  fprintf(stderr, "SocketDescriptor(socket %d)::registerRTPInterface(channel 
%d): isFirstRegistration %d\n", fOurSocketNum, streamChannelId, 
isFirstRegistration);
-#endif
-  fSubChannelHashTable->Add((char const*)(long)streamChannelId,
-                           rtpInterface);
-
-  if (isFirstRegistration) {
-    // Arrange to handle reads on this TCP socket:
-    TaskScheduler::BackgroundHandlerProc* handler
-      = (TaskScheduler::BackgroundHandlerProc*)&tcpReadHandler;
-    fEnv.taskScheduler().
-      setBackgroundHandling(fOurSocketNum, SOCKET_READABLE|SOCKET_EXCEPTION, 
handler, this);
-  }
-}
-
-RTPInterface* SocketDescriptor
-::lookupRTPInterface(unsigned char streamChannelId) {
-  char const* lookupArg = (char const*)(long)streamChannelId;
-  return (RTPInterface*)(fSubChannelHashTable->Lookup(lookupArg));
-}
-
-void SocketDescriptor
-::deregisterRTPInterface(unsigned char streamChannelId) {
-#if defined(DEBUG_SEND)||defined(DEBUG_RECEIVE)
-  fprintf(stderr, "SocketDescriptor(socket %d)::deregisterRTPInterface(channel 
%d)\n", fOurSocketNum, streamChannelId);
-#endif
-  fSubChannelHashTable->Remove((char const*)(long)streamChannelId);
-
-  if (fSubChannelHashTable->IsEmpty()) {
-    // No more interfaces are using us, so it's curtains for us now:
-    if (fAreInReadHandlerLoop) {
-      fDeleteMyselfNext = True; // we can't delete ourself yet, but we'll do 
so from "tcpReadHandler()" below
-    } else {
-      delete this;
-    }
-  }
-}
-
-void SocketDescriptor::tcpReadHandler(SocketDescriptor* socketDescriptor, int 
mask) {
-  // Call the read handler until it returns false, with a limit to avoid 
starving other sockets
-  unsigned count = 2000;
-  Boolean areInRecursiveCall = socketDescriptor->fAreInReadHandlerLoop;
-
-  socketDescriptor->fAreInReadHandlerLoop = True;
-  while (!socketDescriptor->fDeleteMyselfNext && 
socketDescriptor->tcpReadHandler1(mask) && --count > 0) {}
-  if (!areInRecursiveCall) {
-    socketDescriptor->fAreInReadHandlerLoop = False;
-    if (socketDescriptor->fDeleteMyselfNext) delete socketDescriptor;
-  }
-}
-
-Boolean SocketDescriptor::tcpReadHandler1(int mask) {
-  // We expect the following data over the TCP channel:
-  //   optional RTSP command or response bytes (before the first '$' character)
-  //   a '$' character
-  //   a 1-byte channel id
-  //   a 2-byte packet size (in network byte order)
-  //   the packet data.
-  // However, because the socket is being read asynchronously, this data might 
arrive in pieces.
-  
-  u_int8_t c;
-  struct sockaddr_storage dummy; // not used
-  if (fTCPReadingState != AWAITING_PACKET_DATA) {
-    int result = (fTLSState != NULL && fTLSState->isNeeded)
-      ? fTLSState->read(&c, 1)
-      : readSocket(fEnv, fOurSocketNum, &c, 1, dummy);
-    if (result == 0) { // There was no more data to read
-      return False;
-    } else if (result != 1) { // error reading TCP socket, so we will no 
longer handle it
-#ifdef DEBUG_RECEIVE
-      fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): 
readSocket(1 byte) returned %d (error)\n", fOurSocketNum, result);
-#endif
-      fReadErrorOccurred = True;
-      fDeleteMyselfNext = True;
-      return False;
-    }
-  }
-
-  Boolean callAgain = True;
-  switch (fTCPReadingState) {
-    case AWAITING_DOLLAR: {
-      if (c == '$') {
-#ifdef DEBUG_RECEIVE
-       fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): Saw 
'$'\n", fOurSocketNum);
-#endif
-       fTCPReadingState = AWAITING_STREAM_CHANNEL_ID;
-      } else {
-       // This character is part of a RTSP request or command, which is 
handled separately:
-       if (fServerRequestAlternativeByteHandler != NULL && c != 0xFF && c != 
0xFE) {
-         // Hack: 0xFF and 0xFE are used as special signaling characters, so 
don't send them
-         
(*fServerRequestAlternativeByteHandler)(fServerRequestAlternativeByteHandlerClientData,
 c);
-       }
-      }
-      break;
-    }
-    case AWAITING_STREAM_CHANNEL_ID: {
-      // The byte that we read is the stream channel id.
-      if (lookupRTPInterface(c) != NULL) { // sanity check
-       fStreamChannelId = c;
-       fTCPReadingState = AWAITING_SIZE1;
-      } else {
-       // This wasn't a stream channel id that we expected.  We're (somehow) 
in a strange state.  Try to recover:
-#ifdef DEBUG_RECEIVE
-       fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): Saw 
nonexistent stream channel id: 0x%02x\n", fOurSocketNum, c);
-#endif
-       fTCPReadingState = AWAITING_DOLLAR;
-      }
-      break;
-    }
-    case AWAITING_SIZE1: {
-      // The byte that we read is the first (high) byte of the 16-bit RTP or 
RTCP packet 'size'.
-      fSizeByte1 = c;
-      fTCPReadingState = AWAITING_SIZE2;
-      break;
-    }
-    case AWAITING_SIZE2: {
-      // The byte that we read is the second (low) byte of the 16-bit RTP or 
RTCP packet 'size'.
-      unsigned short size = (fSizeByte1<<8)|c;
-      
-      // Record the information about the packet data that will be read next:
-      RTPInterface* rtpInterface = lookupRTPInterface(fStreamChannelId);
-      if (rtpInterface != NULL) {
-       rtpInterface->fNextTCPReadSize = size;
-       rtpInterface->fNextTCPReadStreamSocketNum = fOurSocketNum;
-       rtpInterface->fNextTCPReadStreamChannelId = fStreamChannelId;
-       rtpInterface->fNextTCPReadTLSState = fTLSState;
-      }
-      fTCPReadingState = AWAITING_PACKET_DATA;
-      break;
-    }
-    case AWAITING_PACKET_DATA: {
-      callAgain = False;
-      fTCPReadingState = AWAITING_DOLLAR; // the next state, unless we end up 
having to read more data in the current state
-      // Call the appropriate read handler to get the packet data from the TCP 
stream:
-      RTPInterface* rtpInterface = lookupRTPInterface(fStreamChannelId);
-      if (rtpInterface != NULL) {
-       if (rtpInterface->fNextTCPReadSize == 0) {
-         // We've already read all the data for this packet.
-         break;
-       }
-       if (rtpInterface->fReadHandlerProc != NULL) {
-#ifdef DEBUG_RECEIVE
-         fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): 
reading %d bytes on channel %d\n", fOurSocketNum, 
rtpInterface->fNextTCPReadSize, rtpInterface->fNextTCPReadStreamChannelId);
-#endif
-         fTCPReadingState = AWAITING_PACKET_DATA;
-         rtpInterface->fReadHandlerProc(rtpInterface->fOwner, mask);
-       } else {
-#ifdef DEBUG_RECEIVE
-         fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): No 
handler proc for \"rtpInterface\" for channel %d; need to skip %d remaining 
bytes\n", fOurSocketNum, fStreamChannelId, rtpInterface->fNextTCPReadSize);
-#endif
-         int result = (fTLSState != NULL && fTLSState->isNeeded)
-           ? fTLSState->read(&c, 1)
-           : readSocket(fEnv, fOurSocketNum, &c, 1, dummy);
-         if (result < 0) { // error reading TCP socket, so we will no longer 
handle it
-#ifdef DEBUG_RECEIVE
-           fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): 
readSocket(1 byte) returned %d (error)\n", fOurSocketNum, result);
-#endif
-           fReadErrorOccurred = True;
-           fDeleteMyselfNext = True;
-           return False;
-         } else {
-           fTCPReadingState = AWAITING_PACKET_DATA;
-           if (result == 1) {
-             --rtpInterface->fNextTCPReadSize;
-             callAgain = True;
-           }
-         }
-       }
-      }
-#ifdef DEBUG_RECEIVE
-      else fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): No 
\"rtpInterface\" for channel %d\n", fOurSocketNum, fStreamChannelId);
-#endif
-    }
-  }
-
-  return callAgain;
-}
-
-
-////////// tcpStreamRecord implementation //////////
-
-tcpStreamRecord
-::tcpStreamRecord(int streamSocketNum, unsigned char streamChannelId,
-                 TLSState* tlsState,
-                 tcpStreamRecord* next)
-  : fNext(next),
-    fStreamSocketNum(streamSocketNum), fStreamChannelId(streamChannelId),
-    fTLSState(tlsState) {
-}
-
-tcpStreamRecord::~tcpStreamRecord() {
-  delete fNext;
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/Media.cpp new/live/liveMedia/Media.cpp
--- old/live/liveMedia/Media.cpp        2026-10-24 05:04:52.000000000 +0200
+++ new/live/liveMedia/Media.cpp        2026-11-08 17:12:02.000000000 +0100
@@ -153,10 +153,8 @@
   }
 }
 
-void MediaLookupTable::generateNewName(char* mediumName,
-                                      unsigned /*maxLen*/) {
-  // We should really use snprintf() here, but not all systems have it
-  sprintf(mediumName, "liveMedia%d", fNameGenerator++);
+void MediaLookupTable::generateNewName(char* mediumName, unsigned maxLen) {
+  snprintf(mediumName, maxLen, "liveMedia%d", fNameGenerator++);
 }
 
 MediaLookupTable::MediaLookupTable(UsageEnvironment& env)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MultiFramedRTPSink.cpp 
new/live/liveMedia/MultiFramedRTPSink.cpp
--- old/live/liveMedia/MultiFramedRTPSink.cpp   2026-10-24 05:04:52.000000000 
+0200
+++ new/live/liveMedia/MultiFramedRTPSink.cpp   2026-11-08 17:12:02.000000000 
+0100
@@ -430,7 +430,7 @@
     // sending the next packet.
     struct timeval timeNow;
     gettimeofday(&timeNow, NULL);
-    int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
+    int64_t secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
     int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - 
timeNow.tv_usec);
     if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that 
the time-to-delay is non-negative:
       uSecondsToGo = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/MultiFramedRTPSource.cpp 
new/live/liveMedia/MultiFramedRTPSource.cpp
--- old/live/liveMedia/MultiFramedRTPSource.cpp 2026-10-24 05:04:52.000000000 
+0200
+++ new/live/liveMedia/MultiFramedRTPSource.cpp 2026-11-08 17:12:02.000000000 
+0100
@@ -181,6 +181,13 @@
                    fCurPacketRTPSeqNum, fCurPacketRTPTimestamp,
                    fPresentationTime, fCurPacketHasBeenSynchronizedUsingRTCP,
                    fCurPacketMarkerBit);
+    if (frameSize == 0) {
+      // A "frameSize" of zero means that no data was delivered, perhaps due 
to a malformed
+      // header.  Reject the rest of the packet, so that we continue to make 
progress:
+      fReorderingBuffer->releaseUsedPacket(nextPacket);
+      fNeedDelivery = True;
+      continue;
+    }
     fFrameSize += frameSize;
 
     if (!nextPacket->hasUsableData()) {
@@ -188,7 +195,7 @@
       fReorderingBuffer->releaseUsedPacket(nextPacket);
     }
 
-    if (fCurrentPacketCompletesFrame && fFrameSize > 0) {
+    if (fCurrentPacketCompletesFrame) {
       // We have all the data that the client wants.
       if (fNumTruncatedBytes > 0) {
        envir() << "MultiFramedRTPSource::doGetNextFrame1(): The total received 
frame size exceeds the client's buffer size ("
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/OnDemandServerMediaSubsession.cpp 
new/live/liveMedia/OnDemandServerMediaSubsession.cpp
--- old/live/liveMedia/OnDemandServerMediaSubsession.cpp        2026-10-24 
05:04:52.000000000 +0200
+++ new/live/liveMedia/OnDemandServerMediaSubsession.cpp        2026-11-08 
17:12:02.000000000 +0100
@@ -142,7 +142,7 @@
     streamToken = fLastStreamToken;
   } else {
     // Normal case: Create a new media source:
-    unsigned streamBitrate;
+    unsigned streamBitrate = 0;
     FramedSource* mediaSource
       = createNewStreamSource(clientSessionId, streamBitrate);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/ProxyServerMediaSession.cpp 
new/live/liveMedia/ProxyServerMediaSession.cpp
--- old/live/liveMedia/ProxyServerMediaSession.cpp      2026-10-24 
05:04:52.000000000 +0200
+++ new/live/liveMedia/ProxyServerMediaSession.cpp      2026-11-08 
17:12:02.000000000 +0100
@@ -19,6 +19,10 @@
 // another (unicast or multicast) RTSP/RTP stream.
 // Implementation
 
+// REMINDER: You should not make major changes to this code.
+// If you want more features, then you should use subclassing, with separate 
source code files.
+// See: http://live555.com/liveMedia/faq.html#modifying-and-extending
+
 #include "liveMedia.hh"
 #include "RTSPCommon.hh"
 #include "GroupsockHelper.hh" // for "our_random()"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTCP.cpp new/live/liveMedia/RTCP.cpp
--- old/live/liveMedia/RTCP.cpp 2026-10-24 05:04:52.000000000 +0200
+++ new/live/liveMedia/RTCP.cpp 2026-11-08 17:12:02.000000000 +0100
@@ -116,8 +116,9 @@
     return (double) (timeNow.tv_sec + timeNow.tv_usec/1000000.0);
 }
 
-static unsigned const maxRTCPPacketSize = 1438;
-       // bytes (1500, minus some allowance for IP, UDP headers; SRTCP 
trailers)
+static unsigned const maxRTCPPacketSize = 65536;
+       // allow for unusually large RTCP packets, especially when received 
over TCP
+        // (in which case there's no preceding IP and UDP headers)
 static unsigned const preferredRTCPPacketSize = 1000; // bytes
 
 RTCPInstance::RTCPInstance(UsageEnvironment& env, Groupsock* RTCPgs,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTPSink.cpp 
new/live/liveMedia/RTPSink.cpp
--- old/live/liveMedia/RTPSink.cpp      2026-10-24 05:04:52.000000000 +0200
+++ new/live/liveMedia/RTPSink.cpp      2026-11-08 17:12:02.000000000 +0100
@@ -74,8 +74,9 @@
   if (rtpPayloadType() >= 96) { // the payload format type is dynamic
     char* encodingParamsPart;
     if (numChannels() != 1) {
-      encodingParamsPart = new char[1 + 20 /* max int len */];
-      sprintf(encodingParamsPart, "/%d", numChannels());
+      size_t const encodingParamsPartSize = 1 + 20 /* max int len */;
+      encodingParamsPart = new char[encodingParamsPartSize];
+      snprintf(encodingParamsPart, encodingParamsPartSize, "/%d", 
numChannels());
     } else {
       encodingParamsPart = strDup("");
     }
@@ -84,9 +85,9 @@
       + 3 /* max char len */ + strlen(rtpPayloadFormatName())
       + 20 /* max int len */ + strlen(encodingParamsPart);
     char* rtpmapLine = new char[rtpmapLineSize];
-    sprintf(rtpmapLine, rtpmapFmt,
-           rtpPayloadType(), rtpPayloadFormatName(),
-           rtpTimestampFrequency(), encodingParamsPart);
+    snprintf(rtpmapLine, rtpmapLineSize, rtpmapFmt,
+            rtpPayloadType(), rtpPayloadFormatName(),
+            rtpTimestampFrequency(), encodingParamsPart);
     delete[] encodingParamsPart;
 
     return rtpmapLine;
@@ -107,7 +108,7 @@
     
     unsigned keyMgmtLineSize = strlen(keyMgmtFmt) + strlen(base64EncodedData);
     char* keyMgmtLine = new char[keyMgmtLineSize];
-    sprintf(keyMgmtLine, keyMgmtFmt, base64EncodedData);
+    snprintf(keyMgmtLine, keyMgmtLineSize, keyMgmtFmt, base64EncodedData);
     delete[] base64EncodedData;
 
     return keyMgmtLine;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTSPClient.cpp 
new/live/liveMedia/RTSPClient.cpp
--- old/live/liveMedia/RTSPClient.cpp   2026-10-24 05:04:52.000000000 +0200
+++ new/live/liveMedia/RTSPClient.cpp   2026-11-08 17:12:02.000000000 +0100
@@ -128,8 +128,9 @@
                                              char const* parameterName, char 
const* parameterValue,
                                              Authenticator* authenticator) {
   if (fCurrentAuthenticator < authenticator) fCurrentAuthenticator = 
*authenticator;
-  char* paramString = new char[strlen(parameterName) + strlen(parameterValue) 
+ 10];
-  sprintf(paramString, "%s: %s\r\n", parameterName, parameterValue);
+  size_t const paramStringSize = strlen(parameterName) + 
strlen(parameterValue) + 10;
+  char* paramString = new char[paramStringSize];
+  snprintf(paramString, paramStringSize, "%s: %s\r\n", parameterName, 
parameterValue);
   unsigned result = sendRequest(new RequestRecord(++fCSeq, "SET_PARAMETER", 
responseHandler, &session, NULL, False, 0.0, 0.0, 0.0, paramString));
   delete[] paramString;
   return result;
@@ -143,11 +144,12 @@
   //    parameterName is NULL or "" means: Send no body in the request.
   //    parameterName is non-empty means: Send "<parameterName>\r\n" as the 
request body.  
   unsigned parameterNameLen = parameterName == NULL ? 0 : 
strlen(parameterName);
-  char* paramString = new char[parameterNameLen + 3]; // the 3 is for \r\n + 
the '\0' byte
+  size_t const paramStringSize = parameterNameLen + 3; // the 3 is for \r\n + 
the '\0' byte
+  char* paramString = new char[paramStringSize];
   if (parameterName == NULL || parameterName[0] == '\0') {
     paramString[0] = '\0';
   } else {
-    sprintf(paramString, "%s\r\n", parameterName);
+    snprintf(paramString, paramStringSize, "%s\r\n", parameterName);
   }
   unsigned result = sendRequest(new RequestRecord(++fCSeq, "GET_PARAMETER", 
responseHandler, &session, NULL, False, 0.0, 0.0, 0.0, paramString));
   delete[] paramString;
@@ -384,7 +386,7 @@
   unsigned const headerSize = strlen(formatStr) + strlen(userAgentName);
   delete[] fUserAgentHeaderStr;
   fUserAgentHeaderStr = new char[headerSize];
-  sprintf(fUserAgentHeaderStr, formatStr, userAgentName);
+  snprintf(fUserAgentHeaderStr, headerSize, formatStr, userAgentName);
   fUserAgentHeaderStrLen = strlen(fUserAgentHeaderStr);
 }
 
@@ -429,7 +431,7 @@
   unsigned userAgentNameSize
     = strlen(applicationName) + strlen(libPrefix) + strlen(libName) + 
strlen(liveMediaLibraryVersionStr) + strlen(libSuffix) + 1;
   char* userAgentName = new char[userAgentNameSize];
-  sprintf(userAgentName, "%s%s%s%s%s", applicationName, libPrefix, libName, 
liveMediaLibraryVersionStr, libSuffix);
+  snprintf(userAgentName, userAgentNameSize, "%s%s%s%s%s", applicationName, 
libPrefix, libName, liveMediaLibraryVersionStr, libSuffix);
   setUserAgentString(userAgentName);
   delete[] userAgentName;
 }
@@ -450,6 +452,7 @@
   fRequestsAwaitingResponse.reset();
 
   setBaseURL(NULL);
+  fTCPStreamIdCount = 0;
 
   fCurrentAuthenticator.reset();
 
@@ -526,7 +529,7 @@
       unsigned contentLengthHeaderSize = strlen(contentLengthHeaderFmt)
        + 20 /* max int len */;
       contentLengthHeader = new char[contentLengthHeaderSize];
-      sprintf(contentLengthHeader, contentLengthHeaderFmt, contentStrLen);
+      snprintf(contentLengthHeader, contentLengthHeaderSize, 
contentLengthHeaderFmt, contentStrLen);
       contentLengthHeaderWasAllocated = True;
     }
 
@@ -552,15 +555,15 @@
       + strlen(contentLengthHeader)
       + contentStrLen;
     cmd = new char[cmdSize];
-    sprintf(cmd, cmdFmt,
-           request->commandName(), cmdURL, protocolStr,
-           request->cseq(),
-           authenticatorStr,
-           fUserAgentHeaderStr,
-           fRequireStr,
-            extraHeaders,
-           contentLengthHeader,
-           contentStr);
+    snprintf(cmd, cmdSize, cmdFmt,
+            request->commandName(), cmdURL, protocolStr,
+            request->cseq(),
+            authenticatorStr,
+            fUserAgentHeaderStr,
+            fRequireStr,
+            extraHeaders,
+            contentLengthHeader,
+            contentStr);
     delete[] authenticatorStr;
     if (cmdURLWasAllocated) delete[] cmdURL;
     if (extraHeadersWereAllocated) delete[] extraHeaders;
@@ -581,7 +584,7 @@
       char const* errFmt = "%s write() failed: ";
       unsigned const errLength = strlen(errFmt) + 
strlen(request->commandName());
       char* err = new char[errLength];
-      sprintf(err, errFmt, request->commandName());
+      snprintf(err, errLength, errFmt, request->commandName());
       envir().setResultErrMsg(err);
       delete[] err;
       break;
@@ -611,8 +614,9 @@
 static char* createSessionString(char const* sessionId) {
   char* sessionStr;
   if (sessionId != NULL) {
-    sessionStr = new char[20+strlen(sessionId)];
-    sprintf(sessionStr, "Session: %s\r\n", sessionId);
+    size_t const sessionStrSize = 20 + strlen(sessionId);
+    sessionStr = new char[sessionStrSize];
+    snprintf(sessionStr, sessionStrSize, "Session: %s\r\n", sessionId);
   } else {
     sessionStr = strDup("");
   }
@@ -626,7 +630,7 @@
     // This is the default value; we don't need a "Speed:" header:
     buf[0] = '\0';
   } else {
-    sprintf(buf, "Speed: %.3f\r\n",speed);
+    snprintf(buf, sizeof buf, "Speed: %.3f\r\n", speed);
   }
 
   return strDup(buf);
@@ -639,7 +643,7 @@
     buf[0] = '\0';
   } else {
     Locale l("C", Numeric);
-    sprintf(buf, "Scale: %f\r\n", scale);
+    snprintf(buf, sizeof buf, "Scale: %f\r\n", scale);
   }
 
   return strDup(buf);
@@ -667,11 +671,11 @@
     } else if (end < 0) {
       // There's no end time:
       Locale l("C", Numeric);
-      sprintf(buf, "Range: npt=%.3f-\r\n", start);
+      snprintf(buf, sizeof buf, "Range: npt=%.3f-\r\n", start);
     } else {
       // There's both a start and an end time; include them both in the 
"Range:" hdr
       Locale l("C", Numeric);
-      sprintf(buf, "Range: npt=%.3f-%.3f\r\n", start, end);
+      snprintf(buf, sizeof buf, "Range: npt=%.3f-%.3f\r\n", start, end);
     }
   }
 
@@ -713,9 +717,10 @@
       transportFmt = "Transport: RAW/RAW/UDP%s%s%s=%d-%d\r\n";
     }
     
-    cmdURL = new char[strlen(prefix) + strlen(separator) + strlen(suffix) + 1];
+    size_t const cmdURLSize = strlen(prefix) + strlen(separator) + 
strlen(suffix) + 1;
+    cmdURL = new char[cmdURLSize];
     cmdURLWasAllocated = True;
-    sprintf(cmdURL, "%s%s%s", prefix, separator, suffix);
+    snprintf(cmdURL, cmdURLSize, "%s%s%s", prefix, separator, suffix);
     
     // Construct a "Transport:" header.
     char const* transportTypeStr;
@@ -747,8 +752,8 @@
     unsigned transportSize = strlen(transportFmt)
       + strlen(transportTypeStr) + strlen(modeStr) + strlen(portTypeStr) + 2*5 
/* max port len */;
     char* transportStr = new char[transportSize];
-    sprintf(transportStr, transportFmt,
-           transportTypeStr, modeStr, portTypeStr, rtpNumber, rtcpNumber);
+    snprintf(transportStr, transportSize, transportFmt,
+            transportTypeStr, modeStr, portTypeStr, rtpNumber, rtcpNumber);
     
     // When sending more than one "SETUP" request, include a "Session:" header 
in the 2nd and later commands:
     char* sessionStr = createSessionString(fLastSessionId);
@@ -761,9 +766,11 @@
 
     // The "Transport:", "Session:" (if present), "Blocksize:" (if present), 
and "KeyMgmt:" (if present)
     // headers make up the 'extra headers':
-    extraHeaders = new char[transportSize + strlen(sessionStr) + 
strlen(blocksizeStr) + strlen(keyMgmtStr) + 1];
+    size_t const extraHeadersSize
+      = transportSize + strlen(sessionStr) + strlen(blocksizeStr) + 
strlen(keyMgmtStr) + 1;
+    extraHeaders = new char[extraHeadersSize];
     extraHeadersWereAllocated = True;
-    sprintf(extraHeaders, "%s%s%s%s", transportStr, sessionStr, blocksizeStr, 
keyMgmtStr);
+    snprintf(extraHeaders, extraHeadersSize, "%s%s%s%s", transportStr, 
sessionStr, blocksizeStr, keyMgmtStr);
     delete[] transportStr; delete[] sessionStr; delete[] blocksizeStr; 
delete[] keyMgmtStr;
   } else if (strcmp(request->commandName(), "GET") == 0 || 
strcmp(request->commandName(), "POST") == 0) {
     // We will be sending a HTTP (not a RTSP) request.
@@ -807,9 +814,9 @@
        + strlen(fSessionCookie);
       extraHeaders = new char[extraHeadersSize];
       extraHeadersWereAllocated = True;
-      sprintf(extraHeaders, extraHeadersFmt,
-             serverAddressString.val(),
-             fSessionCookie);
+      snprintf(extraHeaders, extraHeadersSize, extraHeadersFmt,
+              serverAddressString.val(),
+              fSessionCookie);
     } else { // "POST"
       char const* const extraHeadersFmt =
        "Host: %s\r\n"
@@ -824,9 +831,9 @@
        + strlen(fSessionCookie);
       extraHeaders = new char[extraHeadersSize];
       extraHeadersWereAllocated = True;
-      sprintf(extraHeaders, extraHeadersFmt,
-             serverAddressString.val(),
-             fSessionCookie);
+      snprintf(extraHeaders, extraHeadersSize, extraHeadersFmt,
+              serverAddressString.val(),
+              fSessionCookie);
     }
   } else { // "PLAY", "PAUSE", "TEARDOWN", "RECORD", "SET_PARAMETER", 
"GET_PARAMETER"
     // First, make sure that we have a RTSP session in progress
@@ -847,9 +854,10 @@
       // Media-level operation
       char const *prefix, *separator, *suffix;
       constructSubsessionURL(*request->subsession(), prefix, separator, 
suffix);
-      cmdURL = new char[strlen(prefix) + strlen(separator) + strlen(suffix) + 
1];
+      size_t const cmdURLSize = strlen(prefix) + strlen(separator) + 
strlen(suffix) + 1;
+      cmdURL = new char[cmdURLSize];
       cmdURLWasAllocated = True;
-      sprintf(cmdURL, "%s%s%s", prefix, separator, suffix);
+      snprintf(cmdURL, cmdURLSize, "%s%s%s", prefix, separator, suffix);
       
       sessionId = request->subsession()->sessionId();
       originalScale = request->subsession()->scale();
@@ -863,9 +871,11 @@
       float speed = request->session() != NULL ? request->session()->speed() : 
request->subsession()->speed();
       char* speedStr = createSpeedString(speed);
       char* rangeStr = createRangeString(request->start(), request->end(), 
request->absStartTime(), request->absEndTime());
-      extraHeaders = new char[strlen(sessionStr) + strlen(scaleStr) + 
strlen(speedStr) + strlen(rangeStr) + 1];
+      size_t const extraHeadersSize =
+       strlen(sessionStr) + strlen(scaleStr) + strlen(speedStr) + 
strlen(rangeStr) + 1;
+      extraHeaders = new char[extraHeadersSize];
       extraHeadersWereAllocated = True;
-      sprintf(extraHeaders, "%s%s%s%s", sessionStr, scaleStr, speedStr, 
rangeStr);
+      snprintf(extraHeaders, extraHeadersSize, "%s%s%s%s", sessionStr, 
scaleStr, speedStr, rangeStr);
       delete[] sessionStr; delete[] scaleStr; delete[] speedStr; delete[] 
rangeStr;
     } else {
       // Create a "Session:" header; this makes up our 'extra headers':
@@ -987,21 +997,21 @@
        + strlen(auth.username()) + strlen(auth.realm())
        + strlen(auth.nonce()) + strlen(url) + strlen(response);
       authenticatorStr = new char[authBufSize];
-      sprintf(authenticatorStr, authFmt,
-             auth.username(), auth.realm(),
-             auth.nonce(), url, response);
+      snprintf(authenticatorStr, authBufSize, authFmt,
+              auth.username(), auth.realm(),
+              auth.nonce(), url, response);
       auth.reclaimDigestResponse(response);
     } else { // Basic authentication
       char const* const authFmt = "Authorization: Basic %s\r\n";
 
       unsigned usernamePasswordLength = strlen(auth.username()) + 1 + 
strlen(auth.password());
       char* usernamePassword = new char[usernamePasswordLength+1];
-      sprintf(usernamePassword, "%s:%s", auth.username(), auth.password());
+      snprintf(usernamePassword, usernamePasswordLength+1, "%s:%s", 
auth.username(), auth.password());
 
       char* response = base64Encode(usernamePassword, usernamePasswordLength);
       unsigned const authBufSize = strlen(authFmt) + strlen(response) + 1;
       authenticatorStr = new char[authBufSize];
-      sprintf(authenticatorStr, authFmt, response);
+      snprintf(authenticatorStr, authBufSize, authFmt, response);
       delete[] response; delete[] usernamePassword;
     }
 
@@ -1026,8 +1036,9 @@
   }
 
   if (maxPacketSize > 0) {
-    blocksizeStr = new char[25]; // more than enough space
-    sprintf(blocksizeStr, "Blocksize: %u\r\n", maxPacketSize);
+    size_t const blocksizeStrSize = 25; // more than enough space
+    blocksizeStr = new char[blocksizeStrSize];
+    snprintf(blocksizeStr, blocksizeStrSize, "Blocksize: %u\r\n", 
maxPacketSize);
   } else {
     blocksizeStr = strDup("");
   }
@@ -1050,7 +1061,7 @@
     
     unsigned keyMgmtSize = strlen(keyMgmtFmt) + strlen(url) + 
strlen(base64EncodedData);
     keyMgmtStr = new char[keyMgmtSize];
-    sprintf(keyMgmtStr, keyMgmtFmt,
+    snprintf(keyMgmtStr, keyMgmtSize, keyMgmtFmt,
            url, base64EncodedData);
     delete[] base64EncodedData;
   }
@@ -1439,9 +1450,11 @@
     realmHasChanged = fCurrentAuthenticator.realm() == NULL || 
strcmp(fCurrentAuthenticator.realm(), realm) != 0;
     isStale = _strncasecmp(stale, "true", 4) == 0;
     fCurrentAuthenticator.setRealmAndNonce(realm, nonce);
+    disallowBasicAuthentication(); // any future authentication request must 
be Digest
   } else if (sscanf(paramsStr, "Digest realm=\"%[^\"]\", nonce=\"%[^\"]\"", 
realm, nonce) == 2) {
     realmHasChanged = fCurrentAuthenticator.realm() == NULL || 
strcmp(fCurrentAuthenticator.realm(), realm) != 0;
     fCurrentAuthenticator.setRealmAndNonce(realm, nonce);
+    disallowBasicAuthentication(); // any future authentication request must 
be Digest
   } else if (sscanf(paramsStr, "Basic realm=\"%[^\"]\"", realm) == 1 && 
fAllowBasicAuthentication) {
     realmHasChanged = fCurrentAuthenticator.realm() == NULL || 
strcmp(fCurrentAuthenticator.realm(), realm) != 0;
     fCurrentAuthenticator.setRealmAndNonce(realm, NULL); // Basic 
authentication
@@ -1880,7 +1893,7 @@
              = (oldBaseURLTail - fBaseURL) + 8/* for "/stream=" */ + 
strlen(headerParamsStr);
            char* newBaseURL = new char[newBaseURLLen + 1];
                // Note: We couldn't use "asprintf()", because some compilers 
don't support it
-           sprintf(newBaseURL, "%.*s/stream=%s",
+           snprintf(newBaseURL, newBaseURLLen + 1, "%.*s/stream=%s",
                     (int)(oldBaseURLTail - fBaseURL), fBaseURL, 
headerParamsStr);
            setBaseURL(newBaseURL);
            delete[] newBaseURL;
@@ -1908,8 +1921,8 @@
        unsigned remainingBufferSize = responseBufferSize - 
fResponseBytesAlreadySeen;
        if (numExtraBytesNeeded > remainingBufferSize) {
          char tmpBuf[200];
-         sprintf(tmpBuf, "Response buffer size (%d) is too small for 
\"Content-Length:\" %d (need a buffer size of >= %d bytes\n",
-                 responseBufferSize, contentLength, fResponseBytesAlreadySeen 
+ numExtraBytesNeeded);
+         snprintf(tmpBuf, sizeof tmpBuf, "Response buffer size (%d) is too 
small for \"Content-Length:\" %d (need a buffer size of >= %d bytes\n",
+                  responseBufferSize, contentLength, fResponseBytesAlreadySeen 
+ numExtraBytesNeeded);
          envir().setResultMsg(tmpBuf);
          break;
        }
@@ -1963,7 +1976,6 @@
          }
        } else if (responseCode == 301 || responseCode == 302) { // redirection
          resetTCPSockets(); // because we need to connect somewhere else next
-         fCurrentAuthenticator.reset();
          needToResendCommand = True;
        }
        
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/RTSPServer.cpp 
new/live/liveMedia/RTSPServer.cpp
--- old/live/liveMedia/RTSPServer.cpp   2026-10-24 05:04:52.000000000 +0200
+++ new/live/liveMedia/RTSPServer.cpp   2026-11-08 17:12:02.000000000 +0100
@@ -1363,7 +1363,8 @@
       if (streamingMode != UNKNOWN) break; // more than one 'streaming mode' 
is not allowed
 
       streamingMode = RTP_TCP;
-    } else if (strcmp(field, "RTP/AVP") == 0 || strcmp(field, "RTP/SAVP") == 
0) {
+    } else if (strcmp(field, "RTP/AVP") == 0 || strcmp(field, "RTP/AVP/UDP") 
== 0
+              || strcmp(field, "RTP/SAVP") == 0) {
       if (streamingMode != UNKNOWN) break; // more than one 'streaming mode' 
is not allowed
 
       streamingMode = RTP_UDP;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/ProxyServerMediaSession.hh 
new/live/liveMedia/include/ProxyServerMediaSession.hh
--- old/live/liveMedia/include/ProxyServerMediaSession.hh       2026-10-24 
05:04:52.000000000 +0200
+++ new/live/liveMedia/include/ProxyServerMediaSession.hh       2026-11-08 
17:12:02.000000000 +0100
@@ -19,6 +19,10 @@
 // another (unicast or multicast) RTSP/RTP stream.
 // C++ header
 
+// REMINDER: You should not make major changes to this code.
+// If you want more features, then you should use subclassing, with separate 
source code files.
+// See: http://live555.com/liveMedia/faq.html#modifying-and-extending
+
 #ifndef _PROXY_SERVER_MEDIA_SESSION_HH
 #define _PROXY_SERVER_MEDIA_SESSION_HH
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/live/liveMedia/include/liveMedia_version.hh 
new/live/liveMedia/include/liveMedia_version.hh
--- old/live/liveMedia/include/liveMedia_version.hh     2026-10-24 
05:04:52.000000000 +0200
+++ new/live/liveMedia/include/liveMedia_version.hh     2026-11-08 
17:12:02.000000000 +0100
@@ -19,8 +19,8 @@
 #ifndef _LIVEMEDIA_VERSION_HH
 #define _LIVEMEDIA_VERSION_HH
 
-#define LIVEMEDIA_LIBRARY_VERSION_STRING       "2026.10.24"
-#define LIVEMEDIA_LIBRARY_VERSION_INT          1792800000
+#define LIVEMEDIA_LIBRARY_VERSION_STRING       "2026.11.08"
+#define LIVEMEDIA_LIBRARY_VERSION_INT          1794096000
 
 extern char const* const liveMediaLibraryVersionStr;
 extern int const liveMediaLibraryVersionInt;

Reply via email to