sdpchunk.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:43k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: sdpchunk.cpp,v 1.7.8.1 2004/07/09 02:05:16 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. /****************************************************************************
  50.  *  Defines
  51.  */
  52. #define DFLT_PAYLOAD_MIME_TYPE   "data/x-unknown"
  53. #define CHAR_LF 0x0a
  54. #define CHAR_CR 0x0d
  55. #define BAD_PULL_TABLE_IDX  0xFFFFFFFF
  56. #define MAX_INT_TEXT_LENGTH 10
  57. #define N_CLIPRECT_COORDS   4
  58. #define FMPT_PREFIX     "FMTP"
  59. #define FMPT_PREFIX_SIZE    (sizeof(FMPT_PREFIX) - 1)
  60. /****************************************************************************
  61.  *  Includes
  62.  */
  63. //#include "hlxclib/stdlib.h"
  64. #include "hxstrutl.h"
  65. #include "hxassert.h"
  66. #include "sdpchunk.h"
  67. #include "hxstring.h"
  68. #include "hxslist.h"
  69. #include "sdppyldinfo.h"
  70. /****************************************************************************
  71.  *  Locals
  72.  */
  73. /****************************************************************************
  74.  *  Pull Functions
  75. */
  76. static HX_RESULT PullSessionName(char* pData,
  77.                                  ULONG32 ulLength,
  78.                                  IHXValues* pSDPValues,
  79.                                  IHXCommonClassFactory* pClassFactory);
  80. static HX_RESULT PullMediaDesc (char* pData,
  81.                                  ULONG32 ulLength, 
  82.                                  IHXValues* pSDPValues,
  83.                                  IHXCommonClassFactory* pClassFactory);
  84. static HX_RESULT PullRTPMap (char* pData,
  85.                                  ULONG32 ulLength, 
  86.                                  IHXValues* pSDPValues,
  87.                                  IHXCommonClassFactory* pClassFactory);
  88. static HX_RESULT PullControl (char* pData,
  89.                                  ULONG32 ulLength, 
  90.                                  IHXValues* pSDPValues,
  91.                                  IHXCommonClassFactory* pClassFactory);
  92. static HX_RESULT PullClipRect (char* pData, 
  93.                                  ULONG32 ulLength, 
  94.                                  IHXValues* pSDPValues,
  95.                                  IHXCommonClassFactory* pClassFactory);
  96. static HX_RESULT PullBufferDelay(char* pData, 
  97.                                  ULONG32 ulLength, 
  98.                                  IHXValues* pSDPValues,
  99.                                  IHXCommonClassFactory* pClassFactory);
  100. static HX_RESULT PullFormatParams(char* pData, 
  101.                                  ULONG32 ulLength, 
  102.                                  IHXValues* pSDPValues,
  103.                                  IHXCommonClassFactory* pClassFactory);
  104. static HX_RESULT PullGroupID (char* pData, 
  105.                                  ULONG32 ulLength, 
  106.                                  IHXValues* pSDPValues,
  107.                                  IHXCommonClassFactory* pClassFactory);
  108. static HX_RESULT PullGroupBitrate(char* pData, 
  109.                                  ULONG32 ulLength, 
  110.                                  IHXValues* pSDPValues,
  111.                                  IHXCommonClassFactory* pClassFactory);
  112. static HX_RESULT PullBandwidth (char* pData,
  113.                                  ULONG32 ulLength, 
  114.                                  IHXValues* pSDPValues,
  115.                                  IHXCommonClassFactory* pClassFactory);
  116. /****************************************************************************
  117.  *  Local Utilities
  118.  */
  119. inline static ULONG32 GetPullTableIdx(const SDPRecordPuller* pTable,
  120.                                       char* pData, 
  121.                                       ULONG32 ulRecordSize);
  122. inline static char* FindSDPFieldByIdx(char* pData, 
  123.                                       ULONG32 ulLength, 
  124.                                       ULONG32 ulIdx);
  125. inline static char* FindSDPFieldEnd(char* pData, 
  126.                                     ULONG32 ulLength);
  127. inline static char* FindCRLF(char* pData, 
  128.                              ULONG32 ulLength);
  129. inline static HX_RESULT  PullLine(char* pData, 
  130.                              ULONG32 ulLength,
  131.                              REF(IHXBuffer*) pLine,
  132.                              IHXCommonClassFactory* pClassFactory);
  133. inline static char* SkipSDPFieldEnd(char* pData,
  134.                                     ULONG32 ulLength);
  135. inline static void OrderUp(LONG32 &l1, LONG32 &l2);
  136. /****************************************************************************
  137.  *  Pull Tables - must be NULL terminated
  138.  */
  139. const SDPRecordPuller SessionPullTable[] =
  140. {
  141.     {"s=",     sizeof("s=") - 1, PullSessionName},
  142.     {"b=",     sizeof("b=") - 1, PullBandwidth},
  143.     {NULL,     0, NULL}
  144. };
  145. const SDPRecordPuller MediaPullTable[] =
  146. {
  147.     {"m=",     sizeof("m=") - 1, PullMediaDesc},
  148.     {"a=rtpmap:",    sizeof("a=rtpmap:") - 1, PullRTPMap},
  149.     {"a=control:",   sizeof("a=control:") - 1, NULL},
  150.     {"b=",     sizeof("b=") - 1, PullBandwidth},
  151.     {NULL,     0, NULL}
  152. };
  153. const SDPRecordPuller TimePullTable[] =
  154. {
  155.     {NULL,     0, NULL}
  156. };
  157. const SDPRecordPuller GenericPullTable[] =
  158. {
  159.     {NULL,     0, NULL}
  160. };
  161. const SDPRecordPuller RendererPullTable[] =
  162. {
  163.     {"a=cliprect:", sizeof("a=cliprect:") - 1, PullClipRect},
  164.     {"a=x-bufferdelay:", sizeof("a=x-bufferdelay:") - 1, PullBufferDelay}, 
  165.     {"a=fmtp:", sizeof("a=fmtp:") - 1, PullFormatParams},
  166.     {NULL, 0, NULL}
  167. };
  168. const SDPRecordPuller GroupPullTable[] =
  169. {
  170.     {"a=x-alternate:group=", sizeof("a=x-alternate:group=") - 1, PullGroupID},
  171.     {"a=x-alternate:datarate=", sizeof("a=x-alternate:datarate=") - 1, PullGroupBitrate},
  172.     {NULL, 0, NULL}
  173. };
  174. /****************************************************************************
  175.  *  Global Utility fuinctions
  176.  */
  177. /****************************************************************************
  178.  *  SDPParseChunk - use context
  179.  */
  180. HX_RESULT SDPParseChunk(char* pData,
  181.                         ULONG32 ulDataLen,
  182.                         IHXValues* &pSDPValues,
  183.                         IHXCommonClassFactory *pClassFactory,
  184.                         SDPChunkContext SDPContext,
  185.                         BOOL bPullRecords)
  186. {
  187.     HX_RESULT retVal = HXR_OK;
  188.     const SDPRecordPuller* pPullTable = NULL;
  189.     switch (SDPContext)
  190.     {
  191.     case SDPCTX_Media:
  192.         pPullTable = MediaPullTable;
  193.         break;
  194.     case SDPCTX_Session:
  195.         pPullTable = SessionPullTable;
  196.         break;
  197.     case SDPCTX_Group:
  198.         pPullTable = GroupPullTable;
  199.         break;
  200.     case SDPCTX_Time:
  201.         pPullTable = TimePullTable;
  202.         break;
  203.     case SDPCTX_Generic:
  204.         pPullTable = GenericPullTable;
  205.         break;
  206.     case SDPCTX_Renderer:
  207.         pPullTable = RendererPullTable;
  208.         break;
  209.     default:
  210.         retVal = HXR_INVALID_PARAMETER;
  211.         break;
  212.     }
  213.     if (SUCCEEDED(retVal))
  214.     {
  215.         retVal = SDPParseChunk(pData,
  216.                                ulDataLen,
  217.                                pSDPValues,
  218.                                pClassFactory,
  219.                                pPullTable,
  220.                                bPullRecords);
  221.     }
  222.     return retVal;
  223. }
  224. /****************************************************************************
  225.  *  SDPParseChunk - use custom pull table
  226.  */
  227. HX_RESULT SDPParseChunk(char* pData,
  228.                         ULONG32 ulDataLen,
  229.                         IHXValues* &pSDPValues,
  230.                         IHXCommonClassFactory *pClassFactory,
  231.                         const SDPRecordPuller* pPullTable,
  232.                         BOOL bPullRecords)
  233. {
  234.     HX_RESULT retVal = HXR_OK;
  235.     IHXBuffer* pSDPBuffer = NULL;
  236.     char* pSDPData = NULL;
  237.     char* pPattern;
  238.     ULONG32 ulRecordSize;
  239.     ULONG32 ulPullTableIdx;
  240.     BOOL bSDPValuesMadeHere = FALSE;
  241.     
  242.     if ((pData == NULL) || (ulDataLen == 0))
  243.     {
  244.         if (pSDPValues == NULL)
  245.         {
  246.             retVal = HXR_FAIL;
  247.         }
  248.         return retVal;
  249.     }
  250.     if (!pSDPValues)
  251.     {
  252.         bSDPValuesMadeHere = TRUE;
  253.         retVal = pClassFactory->CreateInstance(CLSID_IHXValues,
  254.                                                  (void**) &pSDPValues);
  255.     }
  256.     if (bPullRecords)
  257.     {
  258.         if (SUCCEEDED(retVal))
  259.         {
  260.             retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
  261.                 (void**) &pSDPBuffer);
  262.         }
  263.         
  264.         if (SUCCEEDED(retVal))
  265.         {
  266.             retVal = pSDPBuffer->SetSize(ulDataLen + 1);
  267.         }
  268.     }
  269.     if (SUCCEEDED(retVal))
  270.     {
  271.         if (pPullTable == NULL)
  272.         {
  273.             retVal = HXR_INVALID_PARAMETER;
  274.         }
  275.     }
  276.     if (SUCCEEDED(retVal))
  277.     {
  278.         if (pSDPBuffer)
  279.         {
  280.             pSDPData = (char*) pSDPBuffer->GetBuffer();
  281.         }
  282.         
  283.         do
  284.         {
  285.             pPattern = StrNChr(pData, CHAR_LF, ulDataLen);
  286.             if (pPattern == NULL)
  287.             {
  288.                 ulRecordSize = ulDataLen;
  289.             }
  290.             else
  291.             {
  292.                 ulRecordSize = pPattern - pData;
  293.                 pPattern = SkipSDPFieldEnd(pPattern, 
  294.                                            ulDataLen - ulRecordSize);
  295.                 ulRecordSize = pPattern - pData;
  296.             }
  297.             
  298.             ulPullTableIdx = GetPullTableIdx(pPullTable, 
  299.                                              pData,
  300.                                              ulRecordSize);
  301.             if (ulPullTableIdx == BAD_PULL_TABLE_IDX)
  302.             {
  303.                 if (pSDPData)
  304.                 {
  305.                     // keep this entry as SDP data
  306.                     memcpy(pSDPData, pData, ulRecordSize); /* Flawfinder: ignore */
  307.                     pSDPData += ulRecordSize;
  308.                 }
  309.             }
  310.             else
  311.             {
  312.                 // pull this record out of SDP data
  313.                 if (pPullTable[ulPullTableIdx].pPullFunc)
  314.                 {
  315.                     retVal = (*(pPullTable[ulPullTableIdx].pPullFunc))(
  316.                                     pData,
  317.                                     ulRecordSize,
  318.                                     pSDPValues,
  319.                                     pClassFactory);
  320.                 }
  321.             }
  322.             pData +=  ulRecordSize;
  323.             ulDataLen -= ulRecordSize;
  324.         } while ((ulDataLen != 0) && SUCCEEDED(retVal));
  325.     }
  326.    
  327.     if (SUCCEEDED(retVal) && pSDPData)
  328.     {
  329.         HX_ASSERT(((ULONG32) (pSDPData - ((char *) pSDPBuffer->GetBuffer())) )
  330.                   < pSDPBuffer->GetSize());
  331.         if (((char *) pSDPBuffer->GetBuffer()) != pSDPData)
  332.         {
  333.             *pSDPData = '';
  334.             pSDPValues->SetPropertyCString("SDPData", pSDPBuffer);
  335.         }
  336.     }
  337.     HX_RELEASE(pSDPBuffer);
  338.     if (FAILED(retVal) && bSDPValuesMadeHere)
  339.     {
  340.         HX_RELEASE(pSDPValues);
  341.     }
  342.     return retVal;
  343. }
  344. /****************************************************************************
  345.  *  SDPMapPayloadToMime
  346.  */
  347. HX_RESULT SDPMapPayloadToMime(ULONG32 ulPayloadType,
  348.                               IHXBuffer* &pMimeType,
  349.                               IHXCommonClassFactory *pClassFactory)
  350. {
  351.     HX_RESULT retVal = HXR_OK;
  352.     HX_ASSERT(pClassFactory);
  353.     if (!pMimeType)
  354.     {
  355.         retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
  356.                                                (void**) &pMimeType);
  357.     }
  358.     if (SUCCEEDED(retVal))
  359.     {
  360.         const char* pPayloadMime = DFLT_PAYLOAD_MIME_TYPE;
  361.         if (SDPIsKnownPayload(ulPayloadType))
  362.         {
  363.             pPayloadMime = SDPMapPayloadToMimeType(ulPayloadType);
  364.         }
  365.         retVal = pMimeType->Set((UCHAR*) pPayloadMime, 
  366.                                 strlen(pPayloadMime) + 1);
  367.     }
  368.     return retVal;
  369. }
  370. /****************************************************************************
  371.  *  SDPIsFixedRatePayload
  372.  */
  373. BOOL SDPIsFixedRatePayload(ULONG32 ulPayloadType)
  374. {
  375.     if (SDPIsStaticPayload(ulPayloadType))
  376.     {
  377.         return !SDPIsTimestampDeliverable(ulPayloadType);
  378.     }
  379.     return FALSE;
  380. }
  381. /****************************************************************************
  382.  *  SDPMapMimeToSamplesPerSecond
  383.  */
  384. ULONG32 SDPMapMimeToSamplesPerSecond(IHXBuffer* pMimeTypeBuffer)
  385. {
  386.     ULONG32 ulPayload = 0;
  387.     ULONG32 ulSamplesPerSecond = 0;
  388.     if (SUCCEEDED(SDPMapMimeToPayload(pMimeTypeBuffer, ulPayload)))
  389.     {
  390.         ulSamplesPerSecond = SDPMapPayloadToSamplesPerSecond(ulPayload);
  391.     }
  392.     else
  393.     {
  394.         const char* pTargetMimeType = (const char*)pMimeTypeBuffer->GetBuffer();
  395.         ulSamplesPerSecond = SDPMapMimeTypeToSampleRate(pTargetMimeType);
  396.     }
  397.     return ulSamplesPerSecond;
  398. }
  399. /****************************************************************************
  400.  *  SDPIsKnownPayload
  401.  */
  402. BOOL SDPIsKnownPayload(ULONG32 ulPayloadType)
  403. {
  404.     return (SDPIsStaticPayload(ulPayloadType) &&
  405.             (SDPMapPayloadToMimeType(ulPayloadType) != NULL));
  406. }
  407. /****************************************************************************
  408.  *  SDPMapMimeToPayloadID
  409.  */
  410. HX_RESULT SDPMapMimeToPayload(IHXBuffer* pMimeTypeBuffer, ULONG32 &ulPayload)
  411. {
  412.     ULONG32 ulId;
  413.     HX_RESULT retVal = HXR_FAIL;
  414.     char* pMimeType = NULL;
  415.     char* pEncodingName;
  416.     if (pMimeTypeBuffer)
  417.     {
  418.         pMimeType = (char *) pMimeTypeBuffer->GetBuffer();
  419.     }
  420.     if (pMimeType &&
  421.         (pEncodingName = strchr((char*) pMimeType, '/')))
  422.     {
  423.         pEncodingName++;
  424.         
  425.         for (ulId = 0; SDPIsStaticPayload(ulId); ulId++)
  426.         {
  427.             if (SDPMapPayloadToEncodingName(ulId) &&
  428.                 !strcasecmp(SDPMapPayloadToEncodingName(ulId),
  429.                             pEncodingName))
  430.             {
  431.                 ulPayload = ulId;
  432.                 retVal = HXR_OK;
  433.                 break;
  434.             }
  435.         }
  436.     }
  437.     return retVal;
  438. }
  439. /****************************************************************************
  440.  *  Pull Functions
  441.  */
  442. /****************************************************************************
  443.  *  Pull Functions
  444.  */
  445. /*
  446.  * "s=" text CRLF
  447.  */
  448. static HX_RESULT PullSessionName(char* pData,
  449.                                  ULONG32 ulLength,
  450.                                  IHXValues* pSDPValues,
  451.                                  IHXCommonClassFactory* pClassFactory)
  452. {
  453.     HX_ASSERT(pData && !strncmp(pData, "s=", 2));
  454.     HX_RESULT retVal = HXR_FAIL;
  455.     IHXBuffer* pSessionName = NULL;
  456.     retVal = PullLine(pData + 2, ulLength - 2, pSessionName, pClassFactory);
  457.     if (SUCCEEDED(retVal))
  458.     {
  459.       retVal = pSDPValues->SetPropertyCString("Title", pSessionName);
  460.     }
  461.     HX_RELEASE(pSessionName);
  462.     return retVal;
  463. }
  464. static HX_RESULT PullMediaDesc (char* pData, 
  465.                                  ULONG32 ulLength, 
  466.                                  IHXValues* pSDPValues,
  467.                                  IHXCommonClassFactory* pClassFactory)
  468. {
  469.     char* pPattern;
  470.     ULONG32 ulPayloadType = 0;
  471.     IHXBuffer* pMimeType = NULL;
  472.     HX_RESULT retVal = HXR_FAIL;
  473.     // Extract Payload Type
  474.     pPattern = FindSDPFieldByIdx(pData, ulLength, 3);
  475.     if (pPattern != NULL)
  476.     {
  477.         char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  478.         char* pNumEnd;
  479.         ULONG32 ulNumTextLength = (ulLength - (pPattern - pData));
  480.         if (ulNumTextLength > MAX_INT_TEXT_LENGTH)
  481.         {
  482.             ulNumTextLength = MAX_INT_TEXT_LENGTH;
  483.         }
  484.         memcpy(pNumBuffer, pPattern, ulNumTextLength); /* Flawfinder: ignore */
  485.         pNumBuffer[ulNumTextLength] = '';
  486.         ulPayloadType = strtol(pNumBuffer, &pNumEnd, 10);
  487.         if (pNumEnd > pNumBuffer)
  488.         {
  489.             retVal = HXR_OK;
  490.         }
  491.     }
  492.     // Prepare Mime Type
  493.     if (SUCCEEDED(retVal))
  494.     {
  495.         const char* pPayloadMime = NULL;
  496.         ULONG32 ulPayloadMimeLength = 0;
  497.         char* pMimeStart = NULL;
  498.         ULONG32 ulMimeLength = 0;
  499.         if (SDPIsStaticPayload(ulPayloadType))
  500.         {
  501.             pPayloadMime = SDPMapPayloadToEncodingName(ulPayloadType);
  502.             retVal = HXR_FAIL;
  503.             if (pPayloadMime != NULL)
  504.             {
  505.                 ulPayloadMimeLength = strlen(pPayloadMime) + 1;
  506.                 pSDPValues->SetPropertyULONG32(
  507.                     "SamplesPerSecond",
  508.                     SDPMapPayloadToSamplesPerSecond(ulPayloadType));
  509.                 UINT16 uChannels = 
  510.                     SDPMapPayloadToChannels(ulPayloadType);
  511.                 if (uChannels > 0)
  512.                 {
  513.                     pSDPValues->SetPropertyULONG32(
  514.                         "Channels",
  515.                         uChannels);
  516.                 }
  517.                 retVal = HXR_OK;
  518.             }
  519.         }
  520.         if (SUCCEEDED(retVal))
  521.         {
  522.             // extract portion of mime type
  523.             // - will be completed when rtp map encountered
  524.             // if this is not a static payload
  525.             pPattern = StrNChr((char *) pData, ' ', ulLength);
  526.             pMimeStart = pData + 2;
  527.             
  528.             retVal = HXR_FAIL;
  529.             
  530.             if ((pPattern != NULL) &&
  531.                 ((pPattern - pData) > 2))
  532.             {
  533.                 ulMimeLength = pPattern - pData - 2;
  534.                 
  535.                 retVal = pClassFactory->CreateInstance(
  536.                     CLSID_IHXBuffer,
  537.                     (void**) &pMimeType);
  538.             }
  539.             
  540.             if (SUCCEEDED(retVal))
  541.             {
  542.                 retVal = pMimeType->SetSize(ulMimeLength + 
  543.                                             ulPayloadMimeLength + 
  544.                                             1);
  545.             }
  546.             
  547.             if (SUCCEEDED(retVal))
  548.             {
  549.                 memcpy(pMimeType->GetBuffer(), /* Flawfinder: ignore */
  550.                        pMimeStart, 
  551.                        ulMimeLength);
  552.                 if (ulPayloadMimeLength > 0)
  553.                 {
  554.                     memcpy(pMimeType->GetBuffer() + ulMimeLength + 1, /* Flawfinder: ignore */
  555.                            pPayloadMime, 
  556.                            ulPayloadMimeLength - 1);
  557.                     pMimeType->GetBuffer()[ulMimeLength] = '/';
  558.                 }
  559.                 
  560.                 pMimeType->GetBuffer()[ulMimeLength + 
  561.                                        ulPayloadMimeLength] = '';
  562.             }
  563.         }
  564.     }
  565.     if (SUCCEEDED(retVal))
  566.     {
  567.         pSDPValues->SetPropertyULONG32("RTPPayloadType", ulPayloadType);
  568.         pSDPValues->SetPropertyCString("MimeType", pMimeType);
  569.     }
  570.     HX_RELEASE(pMimeType);
  571.     return retVal;
  572. }
  573. static HX_RESULT PullRTPMap(char* pData, 
  574.                             ULONG32 ulLength, 
  575.                             IHXValues* pSDPValues,
  576.                             IHXCommonClassFactory* pClassFactory)
  577. {
  578.     char* pPattern = NULL;
  579.     char* pPatternEnd = NULL;
  580.     char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  581.     char* pNumEnd = NULL;
  582.     ULONG32 ulPatternLength = 0;
  583.     ULONG32 ulPayloadType = 0;
  584.     ULONG32 ulMediaPayloadType = 0;
  585.     HX_RESULT retVal = HXR_FAIL;
  586.     // Extract the Payload Type
  587.     pPattern = StrNChr((char *) pData, ':',  ulLength);
  588.     if (pPattern)
  589.     {
  590.         ulPatternLength = (ulLength - ((++pPattern) - pData));
  591.         if (ulPatternLength > MAX_INT_TEXT_LENGTH)
  592.         {
  593.             ulPatternLength = MAX_INT_TEXT_LENGTH;
  594.         }
  595.         memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  596.         pNumBuffer[ulPatternLength] = '';
  597.         ulPayloadType = strtol(pNumBuffer, &pNumEnd, 10);
  598.         
  599.         if (pNumEnd > pNumBuffer)
  600.         {
  601.             retVal = pSDPValues->GetPropertyULONG32(
  602.                 "RTPPayloadType", ulMediaPayloadType);
  603.         }
  604.     }
  605.     // Check if this is the payload type entry we are looking for
  606.     if (SUCCEEDED(retVal) && 
  607.         (ulMediaPayloadType == ulPayloadType))
  608.     {
  609.         IHXBuffer* pMimeType = NULL;
  610.         ULONG32 ulOldMimeTextLength;
  611.         BOOL bHasParams = TRUE;
  612.         // Locate New and Old Mime Name Section
  613.         pPattern = StrNChr((char *) pData, ' ',  ulLength);
  614.         retVal = HXR_FAIL;
  615.         if (pPattern)
  616.         {
  617.             pPattern++;
  618.             
  619.             pPatternEnd = StrNChr(pPattern, 
  620.                                   '/',
  621.                                   ulLength - (pPattern - pData));
  622.             if (pPatternEnd == NULL)
  623.             {
  624.                 bHasParams = FALSE;
  625.                 pPatternEnd = FindSDPFieldEnd(pPattern,
  626.                                               ulLength - (pPattern - pData));
  627.             }
  628.             
  629.             ulPatternLength = pPatternEnd - pPattern;
  630.             
  631.             if (ulPatternLength != 0)
  632.             {
  633.                 retVal = pSDPValues->GetPropertyCString(
  634.                     "MimeType", pMimeType);
  635.             }
  636.         }
  637.         // Realocate memory for combined name
  638.         if (SUCCEEDED(retVal))
  639.         {
  640.             pMimeType->Release();   // OK since pSDPValues has ref.
  641.             ulOldMimeTextLength = pMimeType->GetSize() - 1;
  642.             retVal = pMimeType->SetSize(
  643.                 ulOldMimeTextLength + ulPatternLength + 2);
  644.         }
  645.         // Copy in new Mime Name section
  646.         if (SUCCEEDED(retVal))
  647.         {
  648.             char *pMimeData = (char*) pMimeType->GetBuffer();
  649.             memcpy(pMimeData + ulOldMimeTextLength + 1, /* Flawfinder: ignore */
  650.                    pPattern,
  651.                    ulPatternLength);
  652.             pMimeData[ulOldMimeTextLength] = '/';
  653.             pMimeData[pMimeType->GetSize() - 1] = '';
  654.         }
  655.         // Check for parameters following mime type
  656.         if (SUCCEEDED(retVal))
  657.         {
  658.             ULONG32 ulParamIdx = 0;
  659.             while (bHasParams)
  660.             {
  661.                 pPattern += ulPatternLength + 1;
  662.                  
  663.                 pPatternEnd = StrNChr(pPattern, 
  664.                                       '/',
  665.                                       ulLength - (pPattern - pData));
  666.                 if (pPatternEnd == NULL)
  667.                 {
  668.                     bHasParams = FALSE;
  669.                     pPatternEnd = FindSDPFieldEnd(
  670.                                     pPattern,
  671.                                     ulLength - (pPattern - pData));
  672.                 }
  673.                 ulPatternLength = pPatternEnd - pPattern;
  674.             
  675.                 if (ulPatternLength != 0)
  676.                 {
  677.                     LONG32 lValue;
  678.                     if (ulPatternLength > MAX_INT_TEXT_LENGTH)
  679.                     {
  680.                         ulPatternLength = MAX_INT_TEXT_LENGTH;
  681.                     }
  682.                     
  683.                     memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  684.                     pNumBuffer[ulPatternLength] = '';
  685.                     
  686.                     lValue = strtol(pNumBuffer, &pNumEnd, 10);
  687.                     if (pNumEnd > pNumBuffer)
  688.                     {
  689.                         switch (ulParamIdx)
  690.                         {
  691.                         case 0:
  692.                             pSDPValues->SetPropertyULONG32(
  693.                                 "SamplesPerSecond", (ULONG32) lValue);
  694.                             break;
  695.                         case 1:
  696.                             pSDPValues->SetPropertyULONG32(
  697.                                 "Channels", (ULONG32) lValue);
  698.                             break;
  699.                         default:
  700.                             // do nothing
  701.                             break;
  702.                         }
  703.                     }
  704.                 }
  705.                 ulParamIdx++;
  706.             }
  707.         }
  708.     }
  709.     return retVal;
  710. }
  711. static HX_RESULT PullControl(char* pData, 
  712.                              ULONG32 ulLength, 
  713.                              IHXValues* pSDPValues,
  714.                              IHXCommonClassFactory* pClassFactory)
  715. {
  716.     char* pPattern = NULL;
  717.     char* pPatternEnd = NULL;
  718.     ULONG32 ulPatternLength = 0;
  719.     IHXBuffer* pControl = NULL;
  720.     HX_RESULT retVal = HXR_FAIL;
  721.     pPattern = StrNChr((char *) pData, ':', ulLength);
  722.     if (pPattern)
  723.     {
  724.         pPattern++;
  725.         pPatternEnd = FindSDPFieldEnd(
  726.             pPattern, ulLength - (pPattern - pData));
  727.         ulPatternLength = pPatternEnd - pPattern;
  728.         if (ulPatternLength > 0)
  729.         {
  730.             retVal = pClassFactory->CreateInstance(
  731.                 CLSID_IHXBuffer,
  732.                 (void**) &pControl);
  733.         }
  734.     }
  735.     if (SUCCEEDED(retVal))
  736.     {
  737.         retVal = pControl->SetSize(ulPatternLength + 1);
  738.         memcpy(pControl->GetBuffer(), /* Flawfinder: ignore */
  739.                pPattern, 
  740.                ulPatternLength);
  741.         (pControl->GetBuffer())[ulPatternLength] = '';
  742.         pSDPValues->SetPropertyCString("Control", pControl);
  743.         HX_RELEASE(pControl);
  744.     }
  745.     return retVal;
  746. }
  747. static HX_RESULT PullClipRect(char* pData, 
  748.                               ULONG32 ulLength, 
  749.                               IHXValues* pSDPValues,
  750.                               IHXCommonClassFactory* pClassFactory)
  751. {
  752.     char* pPattern;
  753.     ULONG32 ulPatternLength;
  754.     char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  755.     char* pNumEnd;
  756.     ULONG32 ulIdx = 0;
  757.     LONG32 lCoord[N_CLIPRECT_COORDS];
  758.     HX_RESULT retVal = HXR_FAIL;
  759.     pPattern = StrNChr((char *) pData, ':', ulLength);
  760.     if (pPattern)
  761.     {
  762.         do
  763.         {
  764.             ulPatternLength = (ulLength - ((++pPattern) - pData));
  765.             
  766.             if (ulPatternLength > MAX_INT_TEXT_LENGTH)
  767.             {
  768.                 ulPatternLength = MAX_INT_TEXT_LENGTH;
  769.             }
  770.             
  771.             memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  772.             pNumBuffer[ulPatternLength] = '';
  773.             
  774.             lCoord[ulIdx] = strtol(pNumBuffer, &pNumEnd, 10);
  775.             if (pNumEnd == pNumBuffer)
  776.             {
  777.                 break;
  778.             }
  779.         } while (((++ulIdx) < N_CLIPRECT_COORDS) &&
  780.                  (pPattern = StrNChr((char *) pPattern, ',', ulLength)));
  781.         if (ulIdx == N_CLIPRECT_COORDS)
  782.         {
  783.             retVal = HXR_OK;
  784.         }
  785.     }
  786.     if (SUCCEEDED(retVal))
  787.     {
  788.         OrderUp(lCoord[0], lCoord[2]);
  789.         OrderUp(lCoord[1], lCoord[3]);
  790.         pSDPValues->SetPropertyULONG32("ClipFrameLeft", lCoord[1]);
  791.         pSDPValues->SetPropertyULONG32("ClipFrameRight", lCoord[3]);
  792.         pSDPValues->SetPropertyULONG32("ClipFrameTop", lCoord[0]);
  793.         pSDPValues->SetPropertyULONG32("ClipFrameBottom", lCoord[2]);
  794.     }
  795.     return retVal;
  796. }
  797. static HX_RESULT PullFormatParams(char* pData, 
  798.                                   ULONG32 ulLength, 
  799.                                   IHXValues* pSDPValues,
  800.                                   IHXCommonClassFactory* pClassFactory)
  801. {
  802.     char* pPattern = NULL;
  803.     char* pPatternEnd = NULL;
  804.     BOOL bParmNumeric = FALSE;
  805.     ULONG32 ulParmValue = 0;
  806.     ULONG32 ulPatternLength = 0;
  807.     char* pParmName = NULL;
  808.     IHXBuffer* pParmValue = NULL;
  809.     HX_RESULT retVal = HXR_FAIL;
  810.     // Find the start of name-value tuple
  811.     pPattern = FindSDPFieldEnd((char*) pData, ulLength);
  812.     if (pPattern)
  813.     {
  814.         ulPatternLength = (ulLength - (pPattern - pData));
  815.         retVal = HXR_OK;
  816.     }
  817.     do
  818.     {
  819.         // Find the start of name-value tuple
  820.         if (SUCCEEDED(retVal))
  821.         {
  822.             retVal = HXR_FAIL;
  823.             
  824.             pPattern = SkipSDPFieldEnd(pPattern, ulPatternLength);
  825.             if (pPattern)
  826.             {
  827.                 ulPatternLength = (ulLength - (pPattern - pData));
  828.                 retVal = HXR_OK;
  829.             }
  830.         }
  831.         if (SUCCEEDED(retVal))
  832.         {
  833.             if (ulPatternLength == 0)
  834.             {
  835.                 // Done: no more tuples
  836.                 break;
  837.             }
  838.         }
  839.         // Parse the tuple name
  840.         if (SUCCEEDED(retVal))
  841.         {
  842.             retVal = HXR_FAIL;
  843.             pPatternEnd = StrNChr((char*) pPattern, '=', ulPatternLength);
  844.             if (pPatternEnd)
  845.             {
  846.                 retVal = HXR_OK;
  847.             }
  848.         }
  849.         if (SUCCEEDED(retVal))
  850.         {
  851.             retVal = HXR_FAIL;
  852.             ulPatternLength = pPatternEnd - pPattern;
  853.             if (ulPatternLength > 0)
  854.             {
  855.                 retVal = HXR_OK;
  856.             }
  857.         }
  858.         if (SUCCEEDED(retVal))
  859.         {
  860.             retVal = HXR_OUTOFMEMORY;
  861.             pParmName = new char [ulPatternLength + FMPT_PREFIX_SIZE + 1];
  862.             if (pParmName)
  863.             {
  864.                 retVal = HXR_OK;
  865.             }
  866.         }
  867.         if (SUCCEEDED(retVal))
  868.         {
  869.             memcpy(pParmName, /* Flawfinder: ignore */
  870.                    FMPT_PREFIX,
  871.                    FMPT_PREFIX_SIZE);
  872.             memcpy(pParmName + FMPT_PREFIX_SIZE, /* Flawfinder: ignore */
  873.                    pPattern, 
  874.                    ulPatternLength);
  875.             pParmName[ulPatternLength + FMPT_PREFIX_SIZE] = '';
  876.             pPattern = pPatternEnd;
  877.             ulPatternLength = (ulLength - ((++pPattern) - pData));
  878.         }
  879.         // Parse the tuple value
  880.         if (SUCCEEDED(retVal))
  881.         {
  882.             retVal = HXR_FAIL;
  883.             pPatternEnd = StrNChr(pPattern, ';', ulPatternLength);
  884.             if (!pPatternEnd)
  885.             {
  886.                 pPatternEnd = FindSDPFieldEnd(pPattern, ulPatternLength);
  887.             }
  888.             if (pPatternEnd)
  889.             {
  890.                 ulPatternLength = pPatternEnd - pPattern;
  891.             }
  892.             if (ulPatternLength > 0)
  893.             {
  894.                 retVal = HXR_OK;
  895.             }
  896.         }
  897.         bParmNumeric = FALSE;
  898.         if (SUCCEEDED(retVal) && (ulPatternLength <= (MAX_INT_TEXT_LENGTH - 1)))
  899.         {
  900.             char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  901.             char* pNumEnd = NULL;
  902.             memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  903.             pNumBuffer[ulPatternLength] = '';
  904.             ulParmValue = strtol(pNumBuffer, &pNumEnd, 10);
  905.             if (pNumEnd && (pNumEnd == (pNumBuffer + ulPatternLength)))
  906.             {
  907.                 bParmNumeric = TRUE;
  908.             }
  909.         }
  910.         if (bParmNumeric)
  911.         {
  912.             if (SUCCEEDED(retVal))
  913.             {
  914.                 retVal = pSDPValues->SetPropertyULONG32(pParmName, 
  915.                                                         ulParmValue);
  916.             }
  917.         }
  918.         else
  919.         {
  920.             if (SUCCEEDED(retVal))
  921.             {
  922.                 retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
  923.                     (void**) &pParmValue);
  924.             }
  925.             
  926.             if (SUCCEEDED(retVal))
  927.             {
  928.                 retVal = pParmValue->SetSize(ulPatternLength + 1);
  929.             }
  930.             
  931.             if (SUCCEEDED(retVal))
  932.             {
  933.                 UINT8* pBufferData = pParmValue->GetBuffer();
  934.                 memcpy(pBufferData, pPattern, ulPatternLength); /* Flawfinder: ignore */
  935.                 pBufferData[ulPatternLength] = '';
  936.                 
  937.                 retVal = pSDPValues->SetPropertyCString(pParmName, pParmValue);
  938.             }
  939.         }
  940.         if (SUCCEEDED(retVal))
  941.         {
  942.             ulPatternLength = 0;
  943.             pPattern = pPatternEnd;
  944.             if (pPattern)
  945.             {
  946.                 ulPatternLength = (ulLength - ((++pPattern) - pData));
  947.             }
  948.         }
  949.         HX_VECTOR_DELETE(pParmName);
  950.         HX_RELEASE(pParmValue);
  951.     } while (SUCCEEDED(retVal) && (ulPatternLength != 0));
  952.     return retVal;
  953. }
  954. static HX_RESULT PullBufferDelay(char* pData, 
  955.                                  ULONG32 ulLength, 
  956.                                  IHXValues* pSDPValues,
  957.                                  IHXCommonClassFactory* pClassFactory)
  958. {
  959.     char* pPattern;
  960.     ULONG32 ulPatternLength;
  961.     char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  962.     char* pNumEnd;
  963.     ULONG32 ulPreroll;
  964.     double fPreroll;
  965.     HX_RESULT retVal = HXR_FAIL;
  966.     if (pSDPValues->GetPropertyULONG32("Preroll", ulPreroll) != HXR_OK)
  967.     {
  968.         pPattern = StrNChr((char *) pData, ':', ulLength);
  969.         if (pPattern)
  970.         {
  971.             ulPatternLength = (ulLength - ((++pPattern) - pData));
  972.             
  973.             if (ulPatternLength > MAX_INT_TEXT_LENGTH)
  974.             {
  975.                 ulPatternLength = MAX_INT_TEXT_LENGTH;
  976.             }
  977.             
  978.             memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  979.             pNumBuffer[ulPatternLength] = '';
  980.             
  981.             fPreroll = strtod(pNumBuffer, &pNumEnd);
  982.             
  983.             if (pNumEnd > pNumBuffer)
  984.             {
  985.                 retVal = pSDPValues->SetPropertyULONG32(
  986.                     "Preroll", 
  987.                     (ULONG32) (fPreroll * 1000.0 + 0.5));
  988.             }
  989.         }
  990.     }
  991.     return retVal;
  992. }
  993. static HX_RESULT PullGroupID(char* pData, 
  994.                              ULONG32 ulLength, 
  995.                              IHXValues* pSDPValues,
  996.                              IHXCommonClassFactory* pClassFactory)
  997. {
  998.     char* pPattern;
  999.     ULONG32 ulPatternLength;
  1000.     char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  1001.     char* pNumEnd;
  1002.     ULONG32 ulGroupID;
  1003.     HX_RESULT retVal = HXR_FAIL;
  1004.     pPattern = StrNChr((char *) pData, ':', ulLength);
  1005.     if (pPattern)
  1006.     {
  1007.         ulPatternLength = (ulLength - ((++pPattern) - pData));
  1008.         pPattern = StrNChr((char *) pPattern, '=', ulPatternLength);
  1009.     }
  1010.     
  1011.     if (pPattern)
  1012.     {
  1013.         ulPatternLength = (ulLength - ((++pPattern) - pData));
  1014.         
  1015.         if (ulPatternLength > MAX_INT_TEXT_LENGTH)
  1016.         {
  1017.             ulPatternLength = MAX_INT_TEXT_LENGTH;
  1018.         }
  1019.         
  1020.         memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  1021.         pNumBuffer[ulPatternLength] = '';
  1022.         
  1023.         ulGroupID = strtol(pNumBuffer, &pNumEnd, 10);
  1024.                 
  1025.         if (pNumEnd > pNumBuffer)
  1026.         {
  1027.             retVal = pSDPValues->SetPropertyULONG32(
  1028.                 "AlternateGroupID",
  1029.                 ulGroupID);
  1030.         }
  1031.     }
  1032.     return retVal;
  1033. }
  1034. static HX_RESULT PullGroupBitrate(char* pData, 
  1035.                                   ULONG32 ulLength, 
  1036.                                   IHXValues* pSDPValues,
  1037.                                   IHXCommonClassFactory* pClassFactory)
  1038. {
  1039.     char* pPattern;
  1040.     ULONG32 ulPatternLength;
  1041.     char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  1042.     char* pNumEnd;
  1043.     ULONG32 ulGroupBitrate;
  1044.     HX_RESULT retVal = HXR_FAIL;
  1045.     pPattern = StrNChr((char *) pData, ':', ulLength);
  1046.    
  1047.     if (pPattern)
  1048.     {
  1049.         ulPatternLength = (ulLength - ((++pPattern) - pData));
  1050.         
  1051.         pPattern = StrNChr((char *) pPattern, '=', ulPatternLength);
  1052.     }
  1053.     if (pPattern)
  1054.     {
  1055.         ulPatternLength = (ulLength - ((++pPattern) - pData));
  1056.         
  1057.         if (ulPatternLength > MAX_INT_TEXT_LENGTH)
  1058.         {
  1059.             ulPatternLength = MAX_INT_TEXT_LENGTH;
  1060.         }
  1061.         
  1062.         memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  1063.         pNumBuffer[ulPatternLength] = '';
  1064.         
  1065.         ulGroupBitrate = strtol(pNumBuffer, &pNumEnd, 10);
  1066.                 
  1067.         if (pNumEnd > pNumBuffer)
  1068.         {
  1069.             retVal = pSDPValues->SetPropertyULONG32(
  1070.                 "AlternateGroupBitrate",
  1071.                 ulGroupBitrate);
  1072.         }
  1073.     }
  1074.     return retVal;
  1075. }
  1076. static HX_RESULT PullBandwidth (char* pData,
  1077.                                  ULONG32 ulLength, 
  1078.                                  IHXValues* pSDPValues,
  1079.                                  IHXCommonClassFactory* pClassFactory)
  1080. {        
  1081.     char* pPattern;
  1082.     ULONG32 ulPatternLength;
  1083.     char pNumBuffer[MAX_INT_TEXT_LENGTH + 1]; /* Flawfinder: ignore */
  1084.     char* pNumEnd;
  1085.     HX_RESULT retVal = HXR_FAIL;
  1086.     char* pPropName = NULL;
  1087.     ULONG32 ulBandwidth = 0;
  1088.     
  1089.     pPattern = StrNChr((char *) pData, ':', ulLength);           
  1090.     if (pPattern)
  1091.     {
  1092.         ulPatternLength = (ulLength - ((++pPattern) - pData));
  1093.         
  1094.         if (ulPatternLength > MAX_INT_TEXT_LENGTH)
  1095.         {
  1096.             ulPatternLength = MAX_INT_TEXT_LENGTH;
  1097.         }
  1098.         
  1099.         memcpy(pNumBuffer, pPattern, ulPatternLength); /* Flawfinder: ignore */
  1100.         pNumBuffer[ulPatternLength] = '';
  1101.         
  1102.         ulBandwidth = strtol(pNumBuffer, &pNumEnd, 10);
  1103.         if (pNumEnd > pNumBuffer)
  1104.         {     
  1105.     // skip b=
  1106.     pData += 2;
  1107.     ulLength -= 2;
  1108.     if (StrNStr((char*)pData, "AS:", ulLength, 3))
  1109.     {        
  1110. pPropName = "AvgBitRate";
  1111. ulBandwidth *= 1000;
  1112.     }
  1113.     else if (StrNStr((char*)pData, "RR:", ulLength, 3))
  1114.     {        
  1115. pPropName = "RtcpRRRate";
  1116.     }
  1117.     else if (StrNStr((char*)pData, "RS:", ulLength, 3))
  1118.     {        
  1119. pPropName = "RtcpRSRate";
  1120.     }
  1121.     else
  1122.     {
  1123. // fine, ignore
  1124. retVal = HXR_OK;
  1125.     }    
  1126.         }
  1127. if (pPropName)
  1128. {
  1129.     retVal = pSDPValues->SetPropertyULONG32(pPropName, ulBandwidth);     
  1130. }
  1131.     }
  1132.     return retVal;
  1133. }
  1134. /****************************************************************************
  1135.  *  Local Utilities
  1136.  */
  1137. inline static ULONG32 GetPullTableIdx(const SDPRecordPuller* pTable,
  1138.                                       char* pData, 
  1139.                                       ULONG32 ulRecordSize)
  1140. {
  1141.     ULONG32 ulIdx = 0;
  1142.     HX_ASSERT(pTable);
  1143.     while (pTable->pSDPMatch != NULL)
  1144.     {
  1145.         if (pTable->ulSDPMatchSize <= ulRecordSize)
  1146.         {
  1147.             if (!strncmp(pTable->pSDPMatch, 
  1148.                          pData, 
  1149.                          pTable->ulSDPMatchSize))
  1150.             {
  1151.                 return ulIdx;
  1152.             }
  1153.         }
  1154.         pTable++;
  1155.         ulIdx++;
  1156.     }
  1157.     return BAD_PULL_TABLE_IDX;
  1158. }
  1159. inline static char* FindSDPFieldByIdx(char* pData, 
  1160.                                        ULONG32 ulLength, 
  1161.                                        ULONG32 ulIdx)
  1162. {
  1163.     char* pField;
  1164.     while((ulIdx != 0) && (pData != NULL))
  1165.     {
  1166.         pField = StrNChr((char *) pData, ' ', ulLength);
  1167.         if (pField)
  1168.         {
  1169.             ulLength -= ((++pField) - pData);  
  1170.             ulIdx--;
  1171.         }
  1172.         pData = pField;
  1173.     } 
  1174.     if (ulLength == 0)
  1175.     {
  1176.         pData = NULL;
  1177.     }
  1178.     return pData;
  1179. }
  1180. inline static char* FindSDPFieldEnd(char* pData, 
  1181.                                      ULONG32 ulLength)
  1182. {
  1183.     while((ulLength != 0) &&
  1184.           (*pData != ' ') &&
  1185.           (*pData != CHAR_CR) &&
  1186.           (*pData != CHAR_LF))
  1187.     {
  1188.         pData++;
  1189.         ulLength--;
  1190.     } 
  1191.     return pData;
  1192. }
  1193. inline static char* FindCRLF(char* pData, 
  1194.                              ULONG32 ulLength)
  1195. {
  1196.     HX_ASSERT(pData && ulLength);
  1197.     
  1198.     while((0 != ulLength) &&
  1199.           (CHAR_CR != *pData))
  1200.     {
  1201.         pData++;
  1202.         ulLength--;
  1203.     } 
  1204.     if (ulLength)
  1205.     {
  1206.         if (*(pData+1) == CHAR_LF)
  1207.         {
  1208.             // found it
  1209.             return pData;
  1210.         }
  1211.         else
  1212.         {
  1213.             pData++;
  1214.             ulLength--;
  1215.             return FindCRLF(pData, ulLength);
  1216.         }
  1217.     }
  1218.     return NULL;
  1219. }
  1220. /*
  1221.  * saves what pData points to upto CRLF sequence in pLine ('' terminated)
  1222.  */
  1223. inline static HX_RESULT PullLine(char* pData, 
  1224.                              ULONG32 ulLength,
  1225.                              REF(IHXBuffer*) pLine,
  1226.                              IHXCommonClassFactory* pClassFactory)
  1227. {
  1228.     HX_ASSERT(pData && ulLength);
  1229.     
  1230.     char* pc = NULL;
  1231.     HX_RESULT retVal = HXR_FAIL;
  1232.     pc = FindCRLF((char*)pData, ulLength);
  1233.     if (pc)
  1234.     {
  1235.         HX_ASSERT((pc > pData) && (ulLength > (ULONG32)(pc - pData)));
  1236.         ulLength = pc - pData;
  1237.         retVal = HXR_OK;
  1238.     }
  1239.     if (SUCCEEDED(retVal))
  1240.     {
  1241.         retVal = pClassFactory->CreateInstance
  1242.             (CLSID_IHXBuffer, (void**) &pLine);
  1243.     }
  1244.     if (SUCCEEDED(retVal))
  1245.     {
  1246.         retVal = pLine->SetSize(ulLength + 1);
  1247.         BYTE* pcLine = pLine->GetBuffer();
  1248.         memcpy(pcLine, pData, ulLength); /* Flawfinder: ignore */
  1249.         pcLine[ulLength] = '';
  1250.     }
  1251.     return retVal;            
  1252. }
  1253. inline static char* SkipSDPFieldEnd(char* pData, ULONG32 ulSize)
  1254. {
  1255.     while((ulSize > 0) &&
  1256.           ((*pData == CHAR_CR) ||
  1257.            (*pData == CHAR_LF) ||
  1258.            (*pData == ' ')))
  1259.     {
  1260.         pData++;
  1261.         ulSize--;
  1262.     } 
  1263.     return pData;
  1264. }
  1265. inline static void OrderUp(LONG32 &l1, LONG32 &l2)
  1266. {
  1267.     LONG32 temp;
  1268.     if (l1 > l2)
  1269.     {
  1270.         temp = l1;
  1271.         l1 = l2;
  1272.         l2 = temp;
  1273.     }
  1274. }