Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

610 lines
17 KiB

  1. #include "precomp.h"
  2. SIP_MESSAGE::SIP_MESSAGE()
  3. {
  4. ZeroMemory( this, sizeof SIP_MESSAGE );
  5. InitializeListHead(&m_HeaderList);
  6. ParseState = SIP_PARSE_STATE_INIT;
  7. }
  8. SIP_MESSAGE::~SIP_MESSAGE()
  9. {
  10. if (CSeqMethodStr != NULL)
  11. {
  12. free(CSeqMethodStr);
  13. }
  14. FreeHeaderList();
  15. }
  16. void SIP_MESSAGE::Reset()
  17. {
  18. ParseState = SIP_PARSE_STATE_INIT;
  19. BaseBuffer = NULL;
  20. ContentLengthSpecified = FALSE;
  21. MsgBody.Offset = 0;
  22. MsgBody.Length = 0;
  23. FreeHeaderList();
  24. }
  25. // Both do essentially the same thing.
  26. #define InsertBeforeListElement(ListElement, NewElement) \
  27. InsertTailList(ListElement, NewElement)
  28. HRESULT SIP_MESSAGE::AddHeader(
  29. IN OFFSET_STRING *pHeaderName,
  30. IN SIP_HEADER_ENUM HeaderId,
  31. IN OFFSET_STRING *pHeaderValue
  32. )
  33. {
  34. HRESULT hr;
  35. SIP_HEADER_ENTRY *pNewHeaderEntry = new SIP_HEADER_ENTRY;
  36. if (pNewHeaderEntry == NULL)
  37. {
  38. return E_OUTOFMEMORY;
  39. }
  40. pNewHeaderEntry->HeaderName = *pHeaderName;
  41. pNewHeaderEntry->HeaderId = HeaderId;
  42. pNewHeaderEntry->HeaderValue = *pHeaderValue;
  43. LIST_ENTRY *pListEntry;
  44. SIP_HEADER_ENTRY *pHeaderEntry;
  45. pListEntry = m_HeaderList.Flink;
  46. while (pListEntry != &m_HeaderList)
  47. {
  48. pHeaderEntry = CONTAINING_RECORD(pListEntry,
  49. SIP_HEADER_ENTRY,
  50. ListEntry);
  51. // Do an unsigned comparsion so that unknown headers
  52. // are pushed to the end.
  53. if ((ULONG)HeaderId < (ULONG)pHeaderEntry->HeaderId)
  54. {
  55. break;
  56. }
  57. pListEntry = pListEntry->Flink;
  58. }
  59. // Insert before the tail or the element we found with a greater HeaderId
  60. InsertBeforeListElement(pListEntry, &pNewHeaderEntry->ListEntry);
  61. return S_OK;
  62. }
  63. VOID SIP_MESSAGE::FreeHeaderList()
  64. {
  65. LIST_ENTRY *pListEntry;
  66. SIP_HEADER_ENTRY *pHeaderEntry;
  67. while (!IsListEmpty(&m_HeaderList))
  68. {
  69. pListEntry = RemoveHeadList(&m_HeaderList);
  70. pHeaderEntry = CONTAINING_RECORD(pListEntry,
  71. SIP_HEADER_ENTRY,
  72. ListEntry);
  73. delete pHeaderEntry;
  74. }
  75. }
  76. HRESULT
  77. SIP_MESSAGE::StoreCallId()
  78. {
  79. SIP_HEADER_ENTRY *pHeaderEntry;
  80. ULONG NumHeaders;
  81. HRESULT hr;
  82. ENTER_FUNCTION("SIP_MESSAGE::StoreCallId");
  83. hr = GetHeader(SIP_HEADER_CALL_ID, &pHeaderEntry, &NumHeaders);
  84. if (hr != S_OK)
  85. {
  86. LOG((RTC_ERROR, "%s Couldn't find Call-Id header %x",
  87. __fxName, hr));
  88. return hr;
  89. }
  90. else if (NumHeaders != 1)
  91. {
  92. LOG((RTC_ERROR, "%s More than one Call-Id header in message",
  93. __fxName));
  94. return E_FAIL;
  95. }
  96. CallId = pHeaderEntry->HeaderValue;
  97. return S_OK;
  98. }
  99. HRESULT
  100. SIP_MESSAGE::StoreCSeq()
  101. {
  102. HRESULT hr;
  103. PSTR CSeqHeader;
  104. ULONG CSeqHeaderLen;
  105. ULONG BytesParsed = 0;
  106. ENTER_FUNCTION("SIP_MESSAGE::StoreCSeq");
  107. hr = GetSingleHeader(SIP_HEADER_CSEQ, &CSeqHeader, &CSeqHeaderLen);
  108. if (hr != S_OK)
  109. {
  110. LOG((RTC_ERROR, "%s Couldn't find CSeq header %x",
  111. __fxName, hr));
  112. return hr;
  113. }
  114. hr = ParseCSeq(CSeqHeader, CSeqHeaderLen, &BytesParsed,
  115. &CSeq, &CSeqMethodId, &CSeqMethodStr);
  116. if (hr != S_OK)
  117. {
  118. LOG((RTC_ERROR, "%s Parsing CSeq header failed %x",
  119. __fxName, hr));
  120. return hr;
  121. }
  122. // check for unknown method id also that both the strings
  123. // for the method are the same.
  124. if (MsgType == SIP_MESSAGE_TYPE_REQUEST &&
  125. Request.MethodId != CSeqMethodId)
  126. {
  127. LOG((RTC_ERROR, "%s Request Method Id doesn't match CSeq method Id",
  128. __fxName));
  129. return E_FAIL;
  130. }
  131. return S_OK;
  132. }
  133. // Also checks whether the Content-Type is "application/sdp"
  134. HRESULT
  135. SIP_MESSAGE::GetSDPBody(
  136. OUT PSTR *pSDPBody,
  137. OUT ULONG *pSDPBodyLen
  138. )
  139. {
  140. HRESULT hr;
  141. PSTR ContentTypeHdrValue;
  142. ULONG ContentTypeHdrValueLen;
  143. ENTER_FUNCTION("SIP_MESSAGE::GetSDPBody");
  144. if (MsgBody.Length == 0)
  145. {
  146. *pSDPBody = NULL;
  147. *pSDPBodyLen = 0;
  148. return S_OK;
  149. }
  150. // We have Message Body. Check type.
  151. hr = GetSingleHeader(SIP_HEADER_CONTENT_TYPE,
  152. &ContentTypeHdrValue,
  153. &ContentTypeHdrValueLen);
  154. if (hr != S_OK)
  155. {
  156. LOG((RTC_ERROR, "%s - couldn't find Content-Type header",
  157. __fxName));
  158. return E_FAIL;
  159. }
  160. if (IsContentTypeSdp(ContentTypeHdrValue, ContentTypeHdrValueLen))
  161. {
  162. *pSDPBody = MsgBody.GetString(BaseBuffer);
  163. *pSDPBodyLen = MsgBody.Length;
  164. return S_OK;
  165. }
  166. else
  167. {
  168. LOG((RTC_ERROR, "%s - invalid Content-Type %.*s",
  169. __fxName, ContentTypeHdrValueLen, ContentTypeHdrValue));
  170. return E_FAIL;
  171. }
  172. }
  173. // Returns the number of headers if there are multiple headers.
  174. // Should we store the headers in sorted order and do a binary
  175. // search.
  176. // All the headers with the same header name are stored consecutively.
  177. HRESULT SIP_MESSAGE::GetHeader(
  178. IN SIP_HEADER_ENUM HeaderId,
  179. OUT SIP_HEADER_ENTRY **ppHeaderEntry,
  180. OUT ULONG *pNumHeaders
  181. )
  182. {
  183. LIST_ENTRY *pListEntry;
  184. SIP_HEADER_ENTRY *pHeaderEntry;
  185. *ppHeaderEntry = NULL;
  186. *pNumHeaders = 0;
  187. pListEntry = m_HeaderList.Flink;
  188. while (pListEntry != &m_HeaderList)
  189. {
  190. pHeaderEntry = CONTAINING_RECORD(pListEntry,
  191. SIP_HEADER_ENTRY,
  192. ListEntry);
  193. if (HeaderId == pHeaderEntry->HeaderId)
  194. {
  195. *ppHeaderEntry = pHeaderEntry;
  196. while (pListEntry != &m_HeaderList &&
  197. HeaderId == pHeaderEntry->HeaderId)
  198. {
  199. (*pNumHeaders)++;
  200. pListEntry = pListEntry->Flink;
  201. pHeaderEntry = CONTAINING_RECORD(pListEntry,
  202. SIP_HEADER_ENTRY,
  203. ListEntry);
  204. }
  205. return S_OK;
  206. }
  207. pListEntry = pListEntry->Flink;
  208. }
  209. return RTC_E_SIP_HEADER_NOT_PRESENT;
  210. }
  211. // Can be used to get headers such as From, To, CallId,
  212. // which are guaranteed to have just one header (unlike Via, Contact)
  213. HRESULT
  214. SIP_MESSAGE::GetSingleHeader(
  215. IN SIP_HEADER_ENUM HeaderId,
  216. OUT PSTR *pHeaderValue,
  217. OUT ULONG *pHeaderValueLen
  218. )
  219. {
  220. SIP_HEADER_ENTRY *pHeaderEntry;
  221. ULONG NumHeaders;
  222. HRESULT hr;
  223. ENTER_FUNCTION("SIP_MESSAGE::GetSingleHeader");
  224. hr = GetHeader(HeaderId, &pHeaderEntry, &NumHeaders);
  225. if (hr != S_OK)
  226. {
  227. return hr;
  228. }
  229. else if (NumHeaders != 1)
  230. {
  231. LOG((RTC_ERROR, "%s - more than one header : %d",
  232. __fxName, NumHeaders));
  233. return E_FAIL;
  234. }
  235. *pHeaderValueLen = pHeaderEntry->HeaderValue.Length;
  236. *pHeaderValue = pHeaderEntry->HeaderValue.GetString(BaseBuffer);
  237. return S_OK;
  238. }
  239. // Same as GetSingleHeader() except that it could be used
  240. // to get for headers such as Contact which could have multiple
  241. // headers in a message. This function is called if we only care
  242. // about processing the first header.
  243. HRESULT
  244. SIP_MESSAGE::GetFirstHeader(
  245. IN SIP_HEADER_ENUM HeaderId,
  246. OUT PSTR *pHeaderValue,
  247. OUT ULONG *pHeaderValueLen
  248. )
  249. {
  250. SIP_HEADER_ENTRY *pHeaderEntry;
  251. ULONG NumHeaders;
  252. HRESULT hr;
  253. hr = GetHeader(HeaderId, &pHeaderEntry, &NumHeaders);
  254. if (hr != S_OK)
  255. {
  256. return hr;
  257. }
  258. *pHeaderValueLen = pHeaderEntry->HeaderValue.Length;
  259. *pHeaderValue = pHeaderEntry->HeaderValue.GetString(BaseBuffer);
  260. return S_OK;
  261. }
  262. HRESULT
  263. SIP_MESSAGE::GetStoredMultipleHeaders(
  264. IN SIP_HEADER_ENUM HeaderId,
  265. OUT COUNTED_STRING **pStringArray,
  266. OUT ULONG *pNumHeaders
  267. )
  268. {
  269. LIST_ENTRY *pListEntry;
  270. SIP_HEADER_ENTRY *pHeaderEntry;
  271. ULONG NumHeaders = 0;
  272. COUNTED_STRING *StringArray;
  273. HRESULT hr;
  274. ULONG i;
  275. *pStringArray = NULL;
  276. *pNumHeaders = 0;
  277. hr = GetHeader(HeaderId, &pHeaderEntry, &NumHeaders);
  278. if (hr != S_OK)
  279. {
  280. return hr;
  281. }
  282. StringArray = (COUNTED_STRING *) malloc(NumHeaders * sizeof(COUNTED_STRING));
  283. if (StringArray == NULL)
  284. return E_OUTOFMEMORY;
  285. ZeroMemory(StringArray, NumHeaders * sizeof(COUNTED_STRING));
  286. pListEntry = (LIST_ENTRY *)
  287. (pHeaderEntry + FIELD_OFFSET(SIP_HEADER_ENTRY, ListEntry));
  288. for (i = 0; i < NumHeaders; i++)
  289. {
  290. PSTR HeaderValue;
  291. ULONG HeaderLen;
  292. pHeaderEntry = CONTAINING_RECORD(pListEntry,
  293. SIP_HEADER_ENTRY,
  294. ListEntry);
  295. HeaderLen = pHeaderEntry->HeaderValue.Length;
  296. HeaderValue = pHeaderEntry->HeaderValue.GetString(BaseBuffer);
  297. StringArray[i].Buffer = (PSTR) malloc(HeaderLen + 1);
  298. if (StringArray[i].Buffer == NULL)
  299. {
  300. hr = E_OUTOFMEMORY;
  301. goto error;
  302. }
  303. strncpy(StringArray[i].Buffer, HeaderValue, HeaderLen);
  304. StringArray[i].Buffer[HeaderLen] = '\0';
  305. StringArray[i].Length = HeaderLen;
  306. pListEntry = pListEntry->Flink;
  307. }
  308. *pNumHeaders = NumHeaders;
  309. *pStringArray = StringArray;
  310. return S_OK;
  311. error:
  312. if (StringArray != NULL)
  313. {
  314. for (i = 0; i < NumHeaders; i++)
  315. {
  316. if (StringArray[i].Buffer != NULL)
  317. free(StringArray[i].Buffer);
  318. }
  319. free(StringArray);
  320. }
  321. return hr;
  322. }
  323. // The list should be sorted descending using QValue.
  324. HRESULT
  325. SIP_MESSAGE::InsertInContactHeaderList(
  326. IN OUT LIST_ENTRY *pContactHeaderList,
  327. IN CONTACT_HEADER *pNewContactHeader
  328. )
  329. {
  330. LIST_ENTRY *pListEntry;
  331. CONTACT_HEADER *pContactHeader;
  332. pListEntry = pContactHeaderList->Flink;
  333. while (pListEntry != pContactHeaderList)
  334. {
  335. pContactHeader = CONTAINING_RECORD(pListEntry,
  336. CONTACT_HEADER,
  337. m_ListEntry);
  338. // Do an unsigned comparsion so that unknown headers
  339. // are pushed to the end.
  340. if (pNewContactHeader->m_QValue > pContactHeader->m_QValue)
  341. {
  342. break;
  343. }
  344. pListEntry = pListEntry->Flink;
  345. }
  346. // Insert before the tail or the element we found with a greater HeaderId
  347. InsertBeforeListElement(pListEntry, &pNewContactHeader->m_ListEntry);
  348. return S_OK;
  349. }
  350. // pContactHeaderList is the list head. This routine will parse all
  351. // the contact headers into CONTACT_HEADER structures
  352. // (allocated using new) and will add those structures to this
  353. // list. The caller delete the structures when cleaning up the list.
  354. // This function assumes that InitializeListHead() has been called
  355. // earlier on pContactHeaderList.
  356. // The list should be sorted using QValue.
  357. HRESULT
  358. SIP_MESSAGE::ParseContactHeaders(
  359. OUT LIST_ENTRY *pContactHeaderList
  360. )
  361. {
  362. HRESULT hr;
  363. LIST_ENTRY *pListEntry;
  364. SIP_HEADER_ENTRY *pHeaderEntry;
  365. CONTACT_HEADER *pContactHeader;
  366. ULONG NumHeaders = 0;
  367. ULONG i;
  368. ULONG BytesParsed;
  369. PSTR HeaderValue;
  370. ULONG HeaderLen;
  371. ASSERT(IsListEmpty(pContactHeaderList));
  372. ENTER_FUNCTION("SIP_MESSAGE::ParseContactHeaders");
  373. hr = GetHeader(SIP_HEADER_CONTACT, &pHeaderEntry, &NumHeaders);
  374. if (hr != S_OK)
  375. {
  376. LOG((RTC_ERROR, "%s Couldn't find Contact header in msg %x",
  377. __fxName, hr));
  378. return hr;
  379. }
  380. pListEntry = (LIST_ENTRY *)
  381. (pHeaderEntry + FIELD_OFFSET(SIP_HEADER_ENTRY, ListEntry));
  382. for (i = 0; i < NumHeaders; i++)
  383. {
  384. pHeaderEntry = CONTAINING_RECORD(pListEntry,
  385. SIP_HEADER_ENTRY,
  386. ListEntry);
  387. HeaderLen = pHeaderEntry->HeaderValue.Length;
  388. HeaderValue = pHeaderEntry->HeaderValue.GetString(BaseBuffer);
  389. BytesParsed = 0;
  390. while (BytesParsed < HeaderLen)
  391. {
  392. pContactHeader = new CONTACT_HEADER;
  393. if (pContactHeader == NULL)
  394. {
  395. LOG((RTC_ERROR, "%s allocating pContactHeader failed",
  396. __fxName));
  397. FreeContactHeaderList(pContactHeaderList);
  398. return E_OUTOFMEMORY;
  399. }
  400. ZeroMemory( pContactHeader, sizeof(CONTACT_HEADER) );
  401. hr = ParseContactHeader(HeaderValue, HeaderLen, &BytesParsed,
  402. pContactHeader);
  403. if (hr != S_OK)
  404. {
  405. // If parsing a contact header fails we just skip it.
  406. delete pContactHeader;
  407. LOG((RTC_ERROR,
  408. "%s ParseContactHeader failed: %x - skipping Contact header %.*s",
  409. __fxName, hr, HeaderLen, HeaderValue));
  410. break;
  411. }
  412. InsertInContactHeaderList(pContactHeaderList, pContactHeader);
  413. }
  414. pListEntry = pListEntry->Flink;
  415. }
  416. if (IsListEmpty(pContactHeaderList))
  417. {
  418. LOG((RTC_ERROR, "%s - no valid Contact headers returning hr: %x",
  419. __fxName, hr));
  420. return hr;
  421. }
  422. return S_OK;
  423. }
  424. // pRecordRouteHeaderList is the list head. This routine will parse
  425. // all the Record-Route headers into RECORD_ROUTE_HEADER structures
  426. // (allocated using new) and will add those structures to this
  427. // list. The caller delete the structures when cleaning up the list.
  428. // This function assumes that InitializeListHead() has been
  429. // called earlier on pRecordRouteHeaderList.
  430. // The headers are in the order they appear in the message.
  431. HRESULT
  432. SIP_MESSAGE::ParseRecordRouteHeaders(
  433. OUT LIST_ENTRY *pRecordRouteHeaderList
  434. )
  435. {
  436. HRESULT hr;
  437. LIST_ENTRY *pListEntry;
  438. SIP_HEADER_ENTRY *pHeaderEntry;
  439. RECORD_ROUTE_HEADER *pRecordRouteHeader;
  440. ULONG NumHeaders = 0;
  441. ULONG i;
  442. ULONG BytesParsed;
  443. PSTR HeaderValue;
  444. ULONG HeaderLen;
  445. ENTER_FUNCTION("SIP_MESSAGE::ParseRecordRouteHeaders");
  446. hr = GetHeader(SIP_HEADER_RECORD_ROUTE, &pHeaderEntry, &NumHeaders);
  447. if (hr != S_OK)
  448. {
  449. LOG((RTC_TRACE, "%s Couldn't find Record-Route header in msg %x",
  450. __fxName, hr));
  451. return hr;
  452. }
  453. pListEntry = (LIST_ENTRY *)
  454. (pHeaderEntry + FIELD_OFFSET(SIP_HEADER_ENTRY, ListEntry));
  455. for (i = 0; i < NumHeaders; i++)
  456. {
  457. pHeaderEntry = CONTAINING_RECORD(pListEntry,
  458. SIP_HEADER_ENTRY,
  459. ListEntry);
  460. HeaderLen = pHeaderEntry->HeaderValue.Length;
  461. HeaderValue = pHeaderEntry->HeaderValue.GetString(BaseBuffer);
  462. BytesParsed = 0;
  463. while (BytesParsed < HeaderLen)
  464. {
  465. pRecordRouteHeader = new RECORD_ROUTE_HEADER();
  466. if (pRecordRouteHeader == NULL)
  467. {
  468. LOG((RTC_ERROR, "%s allocating pContactHeader failed",
  469. __fxName));
  470. return E_OUTOFMEMORY;
  471. }
  472. hr = ParseRecordRouteHeader(HeaderValue, HeaderLen, &BytesParsed,
  473. pRecordRouteHeader);
  474. if (hr != S_OK)
  475. {
  476. delete pRecordRouteHeader;
  477. LOG((RTC_ERROR, "%s ParseRecordRouteHeader failed: %x",
  478. __fxName, hr));
  479. return hr;
  480. }
  481. InsertTailList(pRecordRouteHeaderList,
  482. &pRecordRouteHeader->m_ListEntry);
  483. }
  484. pListEntry = pListEntry->Flink;
  485. }
  486. return S_OK;
  487. }