Source code of Windows XP (NT5)
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.

1758 lines
53 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1998-1999 Microsoft Corporation
  4. *
  5. * CALL.C - PPTP Call layer functionality
  6. *
  7. * Author: Stan Adermann (stana)
  8. *
  9. * Created: 7/28/1998
  10. *
  11. *****************************************************************************/
  12. #include "raspptp.h"
  13. ULONG CallStateToLineCallStateMap[NUM_CALL_STATES] = {
  14. LINECALLSTATE_UNKNOWN, // STATE_CALL_INVALID
  15. LINECALLSTATE_UNKNOWN, // STATE_CALL_CLOSED
  16. LINECALLSTATE_IDLE, // STATE_CALL_IDLE
  17. LINECALLSTATE_IDLE, // STATE_CALL_OFFHOOK
  18. LINECALLSTATE_OFFERING, // STATE_CALL_OFFERING
  19. LINECALLSTATE_OFFERING, // STATE_CALL_PAC_OFFERING
  20. LINECALLSTATE_OFFERING, // STATE_CALL_PAC_WAIT
  21. LINECALLSTATE_DIALING, // STATE_CALL_DIALING
  22. LINECALLSTATE_PROCEEDING, // STATE_CALL_PROCEEDING
  23. LINECALLSTATE_CONNECTED, // STATE_CALL_ESTABLISHED
  24. LINECALLSTATE_CONNECTED, // STATE_CALL_WAIT_DISCONNECT
  25. LINECALLSTATE_DISCONNECTED, // STATE_CALL_CLEANUP
  26. };
  27. ULONG CallSerialNumber = 0;
  28. VOID
  29. CallpAckTimeout(
  30. IN PVOID SystemSpecific1,
  31. IN PVOID Context,
  32. IN PVOID SystemSpecific2,
  33. IN PVOID SystemSpecific3
  34. );
  35. VOID
  36. CallpCloseTimeout(
  37. IN PVOID SystemSpecific1,
  38. IN PVOID Context,
  39. IN PVOID SystemSpecific2,
  40. IN PVOID SystemSpecific3
  41. );
  42. VOID
  43. CallpDialTimeout(
  44. IN PVOID SystemSpecific1,
  45. IN PVOID Context,
  46. IN PVOID SystemSpecific2,
  47. IN PVOID SystemSpecific3
  48. );
  49. VOID
  50. CallProcessRxPackets(
  51. IN PVOID SystemSpecific1,
  52. IN PVOID Context,
  53. IN PVOID SystemSpecific2,
  54. IN PVOID SystemSpecific3
  55. );
  56. VOID
  57. CallpFinalDeref(IN PCALL_SESSION pCall);
  58. VOID
  59. InitCallLayer()
  60. {
  61. LARGE_INTEGER Time;
  62. NdisGetCurrentSystemTime(&Time);
  63. CallSerialNumber = Time.HighPart;
  64. }
  65. VOID
  66. CallAssignSerialNumber(
  67. PCALL_SESSION pCall
  68. )
  69. {
  70. ASSERT(IS_CALL(pCall));
  71. ASSERT_LOCK_HELD(&pCall->Lock);
  72. pCall->SerialNumber = (USHORT)NdisInterlockedIncrement(&CallSerialNumber);
  73. }
  74. PCALL_SESSION
  75. CallAlloc(PPPTP_ADAPTER pAdapter)
  76. {
  77. PCALL_SESSION pCall;
  78. DEBUGMSG(DBG_FUNC, (DTEXT("+CallAlloc\n")));
  79. pCall = MyMemAlloc(sizeof(CALL_SESSION), TAG_PPTP_CALL);
  80. if (pCall)
  81. {
  82. NdisZeroMemory(pCall, sizeof(CALL_SESSION));
  83. pCall->Signature = TAG_PPTP_CALL;
  84. pCall->pAdapter = pAdapter;
  85. pCall->Close.Checklist = CALL_CLOSE_COMPLETE;
  86. NdisAllocateSpinLock(&pCall->Lock);
  87. NdisInitializeListHead(&pCall->RxPacketList);
  88. NdisInitializeListHead(&pCall->TxPacketList);
  89. NdisMInitializeTimer(&pCall->Close.Timer,
  90. pAdapter->hMiniportAdapter,
  91. CallpCloseTimeout,
  92. pCall);
  93. NdisMInitializeTimer(&pCall->Ack.Timer,
  94. pAdapter->hMiniportAdapter,
  95. CallpAckTimeout,
  96. pCall);
  97. NdisMInitializeTimer(&pCall->DialTimer,
  98. pAdapter->hMiniportAdapter,
  99. CallpDialTimeout,
  100. pCall);
  101. PptpInitializeDpc(&pCall->ReceiveDpc,
  102. pAdapter->hMiniportAdapter,
  103. CallProcessRxPackets,
  104. pCall);
  105. pCall->Ack.Packet.StartBuffer = pCall->Ack.PacketBuffer;
  106. pCall->Ack.Packet.EndBuffer = pCall->Ack.PacketBuffer + sizeof(pCall->Ack.PacketBuffer);
  107. pCall->Ack.Packet.CurrentBuffer = pCall->Ack.Packet.EndBuffer;
  108. pCall->Ack.Packet.CurrentLength = 0;
  109. INIT_REFERENCE_OBJECT(pCall, CallpFinalDeref);
  110. //
  111. // Instead of calling:
  112. // CallSetState(pCall, STATE_CALL_CLOSED, 0, UNLOCKED);
  113. //
  114. // it is better to set the state manually since the former creates an exception to our locking
  115. // scheme (First lock call, then lock adapter) exposing a potential deadlock in CallFindAndLock():
  116. //
  117. // - CallFindAndLock takes the Call lock then the Adapter lock.
  118. // - CallFindAndLock takes the adapter lock then calls CallAlloc which calls
  119. // setcallstate which takes the Call lock.
  120. //
  121. // Although this is a hypothetical scenario since the deadlock will never occur as the new
  122. // call context is not in the adapter's call array yet, but let's be consistent.
  123. //
  124. pCall->State = STATE_CALL_CLOSED;
  125. }
  126. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("-CallAlloc %08x\n"), pCall));
  127. return pCall;
  128. }
  129. VOID
  130. CallpCleanup(
  131. IN PPPTP_WORK_ITEM pWorkItem
  132. )
  133. {
  134. PCALL_SESSION pCall = pWorkItem->Context;
  135. BOOLEAN SignalLineDown = FALSE;
  136. BOOLEAN Cancelled;
  137. BOOLEAN FreeNow = FALSE;
  138. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallpCleanup %08x\n"), pCall));
  139. ASSERT(IS_CALL(pCall));
  140. NdisAcquireSpinLock(&pCall->Lock);
  141. // Signal CLEANUP state
  142. if (!(pCall->Close.Checklist&CALL_CLOSE_CLEANUP_STATE))
  143. {
  144. if (pCall->State!=STATE_CALL_CLEANUP)
  145. {
  146. CallSetState(pCall, STATE_CALL_CLEANUP, 0, LOCKED);
  147. }
  148. pCall->Close.Checklist |= CALL_CLOSE_CLEANUP_STATE;
  149. }
  150. if (REFERENCE_COUNT(pCall)>2)
  151. {
  152. DEBUGMSG(DBG_CALL, (DTEXT("CallpCleanup: too many references (%d)\n"), REFERENCE_COUNT(pCall)));
  153. goto ccDone;
  154. }
  155. if (pCall->Close.Expedited)
  156. {
  157. if ((pCall->Close.Checklist&CALL_CLOSE_DROP) &&
  158. !(pCall->Close.Checklist&CALL_CLOSE_DROP_COMPLETE))
  159. {
  160. pCall->Close.Checklist |= CALL_CLOSE_DROP_COMPLETE;
  161. DEBUGMSG(DBG_CALL, (DTEXT("TapiDrop Completed\n")));
  162. NdisReleaseSpinLock(&pCall->Lock);
  163. NdisMSetInformationComplete(pCall->pAdapter->hMiniportAdapter, NDIS_STATUS_SUCCESS);
  164. NdisAcquireSpinLock(&pCall->Lock);
  165. }
  166. if (!(pCall->Close.Checklist&CALL_CLOSE_DISCONNECT))
  167. {
  168. pCall->Close.Checklist |= CALL_CLOSE_DISCONNECT;
  169. if (pCall->pCtl)
  170. {
  171. NdisReleaseSpinLock(&pCall->Lock);
  172. CtlDisconnectCall(pCall);
  173. NdisAcquireSpinLock(&pCall->Lock);
  174. }
  175. }
  176. if (!(pCall->Close.Checklist&CALL_CLOSE_LINE_DOWN) &&
  177. (pCall->Close.Checklist&CALL_CLOSE_DROP_COMPLETE))
  178. {
  179. SignalLineDown = TRUE;
  180. pCall->Close.Checklist |= CALL_CLOSE_LINE_DOWN;
  181. NdisReleaseSpinLock(&pCall->Lock);
  182. TapiLineDown(pCall);
  183. NdisAcquireSpinLock(&pCall->Lock);
  184. }
  185. }
  186. else // !Expedited
  187. {
  188. if (!(pCall->Close.Checklist&CALL_CLOSE_DISCONNECT))
  189. {
  190. pCall->Close.Checklist |= CALL_CLOSE_DISCONNECT;
  191. if (pCall->pCtl)
  192. {
  193. NdisReleaseSpinLock(&pCall->Lock);
  194. CtlDisconnectCall(pCall);
  195. NdisAcquireSpinLock(&pCall->Lock);
  196. }
  197. }
  198. if (!(pCall->Close.Checklist&CALL_CLOSE_DROP))
  199. {
  200. goto ccDone;
  201. }
  202. if (!(pCall->Close.Checklist&CALL_CLOSE_DROP_COMPLETE))
  203. {
  204. pCall->Close.Checklist |= CALL_CLOSE_DROP_COMPLETE;
  205. DEBUGMSG(DBG_CALL, (DTEXT("TapiDrop Completed 2\n")));
  206. NdisReleaseSpinLock(&pCall->Lock);
  207. NdisMSetInformationComplete(pCall->pAdapter->hMiniportAdapter, NDIS_STATUS_SUCCESS);
  208. NdisAcquireSpinLock(&pCall->Lock);
  209. }
  210. if (!(pCall->Close.Checklist&CALL_CLOSE_LINE_DOWN) &&
  211. (pCall->Close.Checklist&CALL_CLOSE_DROP_COMPLETE))
  212. {
  213. DEBUGMSG(DBG_CALL, (DTEXT("Signalling Line Down 2\n")));
  214. pCall->Close.Checklist |= CALL_CLOSE_LINE_DOWN;
  215. NdisReleaseSpinLock(&pCall->Lock);
  216. TapiLineDown(pCall);
  217. NdisAcquireSpinLock(&pCall->Lock);
  218. }
  219. }
  220. if ((pCall->Close.Checklist&CALL_CLOSE_COMPLETE)!=CALL_CLOSE_COMPLETE)
  221. {
  222. goto ccDone;
  223. }
  224. NdisReleaseSpinLock(&pCall->Lock);
  225. NdisMCancelTimer(&pCall->DialTimer, &Cancelled);
  226. NdisMCancelTimer(&pCall->Close.Timer, &Cancelled);
  227. NdisMCancelTimer(&pCall->Ack.Timer, &Cancelled);
  228. NdisAcquireSpinLock(&pCall->Lock);
  229. if (Cancelled)
  230. {
  231. pCall->Ack.PacketQueued = FALSE;
  232. }
  233. //pCall->hTapiLine = 0;
  234. //pCall->DeviceId = 0;
  235. pCall->Close.Expedited = FALSE;
  236. pCall->UseUdp = (PptpTunnelConfig&CONFIG_INITIATE_UDP) ? TRUE : FALSE;
  237. pCall->CallerId[0] = '\0';
  238. NdisZeroMemory(&pCall->Remote, sizeof(pCall->Remote));
  239. pCall->Packet.SequenceNumber = pCall->Packet.AckNumber = 0;
  240. CallSetState(pCall,
  241. #if SINGLE_LINE
  242. STATE_CALL_IDLE,
  243. #else
  244. (pCall->Open ? STATE_CALL_IDLE : STATE_CALL_CLOSED),
  245. #endif
  246. 0, LOCKED);
  247. DEBUGMSG(DBG_CALL, (DTEXT("Call:%08x Cleanup complete, state==%d\n"),
  248. pCall, pCall->State));
  249. #if SINGLE_LINE
  250. #if 0 // Keep these structures and reuse the memory. They will be cleaned up in AdapterFree()
  251. if (REFERENCE_COUNT(pCall)==1)
  252. {
  253. CallDetachFromAdapter(pCall);
  254. DEREFERENCE_OBJECT(pCall); // For the initial reference.
  255. FreeNow = TRUE;
  256. }
  257. #endif
  258. #else
  259. if (!pCall->Open && !REFERENCE_COUNT(pCall))
  260. {
  261. FreeNow = TRUE;
  262. }
  263. #endif
  264. ccDone:
  265. pCall->Close.Scheduled = FALSE;
  266. NdisReleaseSpinLock(&pCall->Lock);
  267. DEBUGMSG(DBG_FUNC, (DTEXT("-CallpCleanup Checklist:%08x\n"), pCall->Close.Checklist));
  268. if (FreeNow)
  269. {
  270. CallFree(pCall);
  271. }
  272. }
  273. VOID
  274. CallCleanup(
  275. PCALL_SESSION pCall,
  276. BOOLEAN Locked
  277. )
  278. {
  279. DEBUGMSG(DBG_FUNC, (DTEXT("+CallCleanup\n")));
  280. if (!Locked)
  281. {
  282. NdisAcquireSpinLock(&pCall->Lock);
  283. }
  284. ASSERT_LOCK_HELD(&pCall->Lock);
  285. if (!(pCall->Close.Scheduled) &&
  286. ScheduleWorkItem(CallpCleanup, pCall, NULL, 0)==NDIS_STATUS_SUCCESS)
  287. {
  288. pCall->Close.Scheduled = TRUE;
  289. }
  290. if (!Locked)
  291. {
  292. NdisReleaseSpinLock(&pCall->Lock);
  293. }
  294. DEBUGMSG(DBG_FUNC, (DTEXT("-CallCleanup\n")));
  295. }
  296. // Call lock must be held when calling this.
  297. VOID
  298. CallDetachFromAdapter(PCALL_SESSION pCall)
  299. {
  300. DEBUGMSG(DBG_FUNC, (DTEXT("+CallDetachFromAdapter %08x\n"), pCall));
  301. NdisAcquireSpinLock(&pCall->pAdapter->Lock);
  302. #if SINGLE_LINE
  303. pCall->pAdapter->pCallArray[pCall->DeviceId] = NULL;
  304. #else
  305. pCall->pAdapter->pCallArray[DeviceIdToIndex(pCall->pAdapter, pCall->DeviceId)] = NULL;
  306. #endif
  307. NdisReleaseSpinLock(&pCall->pAdapter->Lock);
  308. pCall->Open = FALSE;
  309. DEBUGMSG(DBG_FUNC, (DTEXT("-CallDetachFromAdapter\n")));
  310. }
  311. VOID
  312. CallFree(PCALL_SESSION pCall)
  313. {
  314. BOOLEAN NotUsed;
  315. if (!pCall)
  316. {
  317. return;
  318. }
  319. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallFree %p\n"), pCall));
  320. ASSERT(IS_CALL(pCall));
  321. // This duplicates some of the cleanup code, but attempting to stop
  322. // the driver without first stopping tapi can result in an ungraceful
  323. // shutdown.
  324. NdisMCancelTimer(&pCall->DialTimer, &NotUsed);
  325. NdisMCancelTimer(&pCall->Close.Timer, &NotUsed);
  326. NdisMCancelTimer(&pCall->Ack.Timer, &NotUsed);
  327. ASSERT(pCall->Signature==TAG_PPTP_CALL);
  328. ASSERT(IsListEmpty(&pCall->RxPacketList));
  329. ASSERT(IsListEmpty(&pCall->TxPacketList));
  330. NdisFreeSpinLock(&pCall->Lock);
  331. MyMemFree(pCall, sizeof(CALL_SESSION));
  332. DEBUGMSG(DBG_FUNC, (DTEXT("-CallFree\n")));
  333. }
  334. PCALL_SESSION FASTCALL
  335. CallGetCall(
  336. IN PPPTP_ADAPTER pAdapter,
  337. IN ULONG_PTR ulDeviceId
  338. )
  339. {
  340. PCALL_SESSION pCall = NULL;
  341. DEBUGMSG(DBG_FUNC, (DTEXT("+CallGetCall %d\n"), ulDeviceId));
  342. NdisAcquireSpinLock(&pAdapter->Lock);
  343. #if SINGLE_LINE
  344. if (ulDeviceId<pAdapter->Info.Endpoints)
  345. {
  346. pCall = pAdapter->pCallArray[ulDeviceId];
  347. }
  348. #else
  349. if (ulDeviceId>=pAdapter->Tapi.DeviceIdBase &&
  350. ulDeviceId<pAdapter->Tapi.DeviceIdBase+pAdapter->Info.Endpoints)
  351. {
  352. pCall = pAdapter->pCallArray[ulDeviceId - pAdapter->Tapi.DeviceIdBase];
  353. }
  354. #endif
  355. NdisReleaseSpinLock(&pAdapter->Lock);
  356. DEBUGMSG(DBG_FUNC, (DTEXT("-CallGetCall %08x\n"), pCall));
  357. return pCall;
  358. }
  359. BOOLEAN FASTCALL
  360. CallIsValidCall(
  361. IN PPPTP_ADAPTER pAdapter,
  362. IN ULONG_PTR ulDeviceId
  363. )
  364. {
  365. BOOLEAN IsValid = FALSE;
  366. DEBUGMSG(DBG_FUNC, (DTEXT("+CallIsValidCall %d\n"), ulDeviceId));
  367. #if SINGLE_LINE
  368. if (ulDeviceId==pAdapter->Tapi.DeviceIdBase)
  369. {
  370. IsValid = TRUE;
  371. }
  372. #else
  373. if (ulDeviceId>=pAdapter->Tapi.DeviceIdBase &&
  374. ulDeviceId<pAdapter->Tapi.DeviceIdBase+pAdapter->Info.Endpoints)
  375. {
  376. IsValid = TRUE;
  377. }
  378. #endif
  379. DEBUGMSG(DBG_FUNC, (DTEXT("-CallIsValidCall %d\n"), IsValid));
  380. return IsValid;
  381. }
  382. PCALL_SESSION
  383. CallFindAndLock(
  384. IN PPPTP_ADAPTER pAdapter,
  385. IN CALL_STATE State,
  386. IN ULONG Flags
  387. )
  388. {
  389. LONG i, inc;
  390. PCALL_SESSION pCall = NULL;
  391. BOOLEAN fNewCallCreated = FALSE;
  392. DEBUGMSG(DBG_FUNC, (DTEXT("+CallFindAndLock %d\n"), State));
  393. do
  394. {
  395. if (pCall)
  396. {
  397. NdisReleaseSpinLock(&pCall->Lock);
  398. }
  399. pCall = NULL;
  400. // Find a call that matches our state. Start from the beginning (again)
  401. // This shouldn't be an infinite loop because we will either hit the end
  402. // or find a valid call in just a couple tries.
  403. NdisAcquireSpinLock(&pAdapter->Lock);
  404. if (Flags&FIND_INCOMING)
  405. {
  406. // Outgoing calls start top down
  407. inc = -1;
  408. i = pAdapter->Info.Endpoints - 1;
  409. }
  410. else
  411. {
  412. // Incoming calls start bottom up (0)
  413. inc = 1;
  414. i = 0;
  415. }
  416. while ( (Flags&FIND_INCOMING) ? (i>=0) : (i<(signed)pAdapter->Info.Endpoints) )
  417. {
  418. if (!pAdapter->pCallArray[i])
  419. {
  420. if (State==STATE_CALL_IDLE)
  421. {
  422. pCall = CallAlloc(pAdapter);
  423. if (pCall)
  424. {
  425. fNewCallCreated = TRUE;
  426. pCall->DeviceId = (unsigned)i;
  427. break;
  428. }
  429. }
  430. }
  431. else if (pAdapter->pCallArray[i]->State == State)
  432. {
  433. pCall = pAdapter->pCallArray[i];
  434. break;
  435. }
  436. i += inc;
  437. }
  438. NdisReleaseSpinLock(&pAdapter->Lock);
  439. if (pCall)
  440. {
  441. NdisAcquireSpinLock( &pCall->Lock );
  442. if ( fNewCallCreated )
  443. {
  444. CallSetState(pCall, STATE_CALL_IDLE, 0, LOCKED);
  445. NdisAcquireSpinLock( &pAdapter->Lock );
  446. pAdapter->pCallArray[i] = pCall;
  447. NdisReleaseSpinLock( &pAdapter->Lock );
  448. }
  449. }
  450. // The state could change while we were taking the lock, so look again.
  451. } while ( pCall && pCall->State!=State );
  452. DEBUGMSG(DBG_FUNC, (DTEXT("-CallFindAndLock %08x\n"), pCall));
  453. return pCall;
  454. }
  455. NDIS_STATUS
  456. CallEventCallClearRequest(
  457. PCALL_SESSION pCall,
  458. UNALIGNED PPTP_CALL_CLEAR_REQUEST_PACKET *pPacket,
  459. PCONTROL_TUNNEL pCtl
  460. )
  461. {
  462. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  463. PPPTP_CALL_DISCONNECT_NOTIFY_PACKET pReply;
  464. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallEventCallClearRequest\n")));
  465. pReply = CtlAllocPacket(pCall->pCtl, CALL_DISCONNECT_NOTIFY);
  466. // We don't really care if we fail this allocation because PPTP can clean up
  467. // along other avenues, and the cleanup just won't be as pretty.
  468. if (pReply)
  469. {
  470. pReply->CallId = htons(pCall->Packet.CallId);
  471. Status = CtlSend(pCtl, pReply);
  472. }
  473. CallCleanup(pCall, UNLOCKED);
  474. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallEventCallClearRequest %08x\n"), Status));
  475. return Status;
  476. }
  477. NDIS_STATUS
  478. CallEventCallDisconnectNotify(
  479. PCALL_SESSION pCall,
  480. UNALIGNED PPTP_CALL_DISCONNECT_NOTIFY_PACKET *pPacket
  481. )
  482. {
  483. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  484. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallEventCallDisconnectNotify\n")));
  485. if (IS_CALL(pCall))
  486. {
  487. CallCleanup(pCall, UNLOCKED);
  488. }
  489. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallEventCallDisconnectNotify %08x\n"), Status));
  490. return Status;
  491. }
  492. NDIS_STATUS
  493. CallEventCallInConnect(
  494. IN PCALL_SESSION pCall,
  495. IN UNALIGNED PPTP_CALL_IN_CONNECT_PACKET *pPacket
  496. )
  497. {
  498. DEBUGMSG(DBG_FUNC, (DTEXT("+CallEventCallInConnect\n")));
  499. ASSERT(IS_CALL(pCall));
  500. NdisAcquireSpinLock(&pCall->Lock);
  501. if (pCall->State==STATE_CALL_PAC_WAIT)
  502. {
  503. pCall->Speed = htonl(pPacket->ConnectSpeed);
  504. CallSetState(pCall, STATE_CALL_ESTABLISHED, htonl(pPacket->ConnectSpeed), LOCKED);
  505. }
  506. NdisReleaseSpinLock(&pCall->Lock);
  507. DEBUGMSG(DBG_FUNC, (DTEXT("-CallEventCallInConnect\n")));
  508. return NDIS_STATUS_SUCCESS;
  509. }
  510. NDIS_STATUS
  511. CallEventCallInRequest(
  512. IN PPPTP_ADAPTER pAdapter,
  513. IN PCONTROL_TUNNEL pCtl,
  514. IN UNALIGNED PPTP_CALL_IN_REQUEST_PACKET *pPacket
  515. )
  516. {
  517. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  518. PCALL_SESSION pCall;
  519. DEBUGMSG(DBG_FUNC, (DTEXT("+CallEventCallInRequest\n")));
  520. pCall = CallFindAndLock(pAdapter, STATE_CALL_IDLE, FIND_INCOMING);
  521. if (pCall)
  522. {
  523. NDIS_TAPI_EVENT TapiEvent;
  524. // We have a call in idle state, spinlock acquired
  525. pCall->Inbound = TRUE;
  526. pCall->Remote.CallId = htons(pPacket->CallId);
  527. pCall->Remote.Address = pCtl->Remote.Address;
  528. pCall->Remote.Address.Address[0].Address[0].sin_port = htons(PptpUdpPort);
  529. pCall->SerialNumber = htons(pPacket->SerialNumber);
  530. pCall->Close.Checklist &= ~CALL_CLOSE_DISCONNECT;
  531. CallConnectToCtl(pCall, pCtl, TRUE);
  532. NdisReleaseSpinLock(&pCall->Lock);
  533. pPacket->DialingNumber[MAX_PHONE_NUMBER_LENGTH-1] = '\0';
  534. strcpy(pPacket->DialingNumber, pCall->CallerId);
  535. #if SINGLE_LINE
  536. TapiEvent.htLine = pAdapter->Tapi.hTapiLine;
  537. #else
  538. TapiEvent.htLine = pCall->hTapiLine;
  539. #endif
  540. LOGMSG(FLL_DETAILED, (DTEXT(LOGHDRS"LINE_NEWCALL:%d\n"),
  541. LOGHDR(27, pCall->Remote.Address.Address[0].Address[0].in_addr),
  542. pCall->DeviceId));
  543. TapiEvent.htCall = 0;
  544. TapiEvent.ulMsg = LINE_NEWCALL;
  545. TapiEvent.ulParam1 = pCall->DeviceId;
  546. TapiEvent.ulParam2 = 0;
  547. TapiEvent.ulParam3 = 0;
  548. NdisMIndicateStatus(pCall->pAdapter->hMiniportAdapter,
  549. NDIS_STATUS_TAPI_INDICATION,
  550. &TapiEvent,
  551. sizeof(TapiEvent));
  552. NdisAcquireSpinLock(&pCall->Lock);
  553. pCall->hTapiCall = TapiEvent.ulParam2;
  554. CallSetState(pCall, STATE_CALL_PAC_OFFERING, 0, LOCKED);
  555. NdisReleaseSpinLock(&pCall->Lock);
  556. DEBUGMSG(DBG_TAPI, (DTEXT("LINE_NEWCALL on %d returned htCall %d\n"),
  557. pCall->DeviceId, TapiEvent.ulParam2));
  558. DEBUGMSG(DBG_CALL, (DTEXT("New in call request: Call:%08x Ctl:%08x Addr:%08x\n"),
  559. pCall, pCtl, pCall->Remote.Address.Address[0].Address[0].in_addr));
  560. }
  561. else
  562. {
  563. PPTP_CALL_OUT_REPLY_PACKET *pReply = CtlAllocPacket(pCtl, CALL_IN_REPLY);
  564. if (pReply)
  565. {
  566. pReply->PeerCallId = pPacket->CallId;
  567. pReply->ResultCode = RESULT_CALL_IN_ERROR;
  568. pReply->ErrorCode = PPTP_STATUS_INSUFFICIENT_RESOURCES;
  569. // No call was available. Send a rejection.
  570. Status = CtlSend(pCtl, pReply);
  571. }
  572. }
  573. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallEventCallInRequest %08x\n"), Status));
  574. return Status;
  575. }
  576. NDIS_STATUS
  577. CallEventCallOutRequest(
  578. IN PPPTP_ADAPTER pAdapter,
  579. IN PCONTROL_TUNNEL pCtl,
  580. IN UNALIGNED PPTP_CALL_OUT_REQUEST_PACKET *pPacket
  581. )
  582. {
  583. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  584. PCALL_SESSION pCall;
  585. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallEventCallOutRequest\n")));
  586. pCall = CallFindAndLock(pAdapter, STATE_CALL_IDLE, FIND_INCOMING);
  587. if (pCall)
  588. {
  589. NDIS_TAPI_EVENT TapiEvent;
  590. // We have a call in idle state, spinlock acquired
  591. pCall->Inbound = TRUE;
  592. pCall->Remote.CallId = htons(pPacket->CallId);
  593. pCall->Remote.Address = pCtl->Remote.Address;
  594. pCall->Remote.Address.Address[0].Address[0].sin_port = htons(PptpUdpPort);
  595. pCall->SerialNumber = htons(pPacket->SerialNumber);
  596. IpAddressToString(htonl(pCtl->Remote.Address.Address[0].Address[0].in_addr), pCall->CallerId);
  597. pCall->Close.Checklist &= ~CALL_CLOSE_DISCONNECT;
  598. CallConnectToCtl(pCall, pCtl, TRUE);
  599. NdisReleaseSpinLock(&pCall->Lock);
  600. #if SINGLE_LINE
  601. TapiEvent.htLine = pAdapter->Tapi.hTapiLine;
  602. #else
  603. TapiEvent.htLine = pCall->hTapiLine;
  604. #endif
  605. LOGMSG(FLL_DETAILED, (DTEXT(LOGHDRS"LINE_NEWCALL:%d\n"),
  606. LOGHDR(27, pCall->Remote.Address.Address[0].Address[0].in_addr),
  607. pCall->DeviceId));
  608. TapiEvent.htCall = 0;
  609. TapiEvent.ulMsg = LINE_NEWCALL;
  610. TapiEvent.ulParam1 = pCall->DeviceId;
  611. TapiEvent.ulParam2 = 0;
  612. TapiEvent.ulParam3 = 0;
  613. NdisMIndicateStatus(pCall->pAdapter->hMiniportAdapter,
  614. NDIS_STATUS_TAPI_INDICATION,
  615. &TapiEvent,
  616. sizeof(TapiEvent));
  617. NdisAcquireSpinLock(&pCall->Lock);
  618. pCall->hTapiCall = TapiEvent.ulParam2;
  619. CallSetState(pCall, STATE_CALL_OFFERING, 0, LOCKED);
  620. NdisReleaseSpinLock(&pCall->Lock);
  621. DEBUGMSG(DBG_TAPI, (DTEXT("LINE_NEWCALL on %d returned htCall %d\n"),
  622. pCall->DeviceId, TapiEvent.ulParam2));
  623. DEBUGMSG(DBG_CALL, (DTEXT("New call request: Call:%08x Ctl:%08x Addr:%hs\n"),
  624. pCall, pCtl, pCall->CallerId));
  625. }
  626. else
  627. {
  628. PPTP_CALL_OUT_REPLY_PACKET *pReply = CtlAllocPacket(pCtl, CALL_OUT_REPLY);
  629. if (pReply)
  630. {
  631. pReply->PeerCallId = pPacket->CallId;
  632. pReply->ResultCode = RESULT_CALL_OUT_ERROR;
  633. pReply->ErrorCode = PPTP_STATUS_INSUFFICIENT_RESOURCES;
  634. // No call was available. Send a rejection.
  635. Status = CtlSend(pCtl, pReply);
  636. }
  637. }
  638. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallEventCallOutRequest %08x\n"), Status));
  639. return Status;
  640. }
  641. NDIS_STATUS
  642. CallEventCallOutReply(
  643. IN PCALL_SESSION pCall,
  644. IN UNALIGNED PPTP_CALL_OUT_REPLY_PACKET *pPacket
  645. )
  646. {
  647. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallEventCallOutReply\n")));
  648. OsFileLogFlush(); // After the last connection message do a flush
  649. ASSERT(IS_CALL(pCall));
  650. NdisAcquireSpinLock(&pCall->Lock);
  651. if (pPacket->ResultCode==RESULT_CALL_OUT_CONNECTED)
  652. {
  653. if (pCall->State!=STATE_CALL_PROCEEDING ||
  654. pCall->Packet.CallId!=htons(pPacket->PeerCallId))
  655. {
  656. // Something's wrong. Ignore it.
  657. }
  658. else
  659. {
  660. LOGMSG(FLL_USER, (DTEXT(LOGHDRS"Call Successfully Established\n"),
  661. LOGHDR(25, pCall->pCtl->Remote.Address.Address[0].Address[0].in_addr)));
  662. pCall->Remote.CallId = htons(pPacket->CallId);
  663. pCall->Speed = pCall->pCtl->Speed;
  664. CallSetState(pCall, STATE_CALL_ESTABLISHED, htonl(pPacket->ConnectSpeed), LOCKED);
  665. }
  666. }
  667. else
  668. {
  669. // The call fails for some reason.
  670. CallCleanup(pCall, LOCKED);
  671. }
  672. NdisReleaseSpinLock(&pCall->Lock);
  673. DEBUGMSG(DBG_FUNC, (DTEXT("-CallEventCallOutReply\n")));
  674. return NDIS_STATUS_SUCCESS;
  675. }
  676. NDIS_STATUS
  677. CallEventDisconnect(
  678. PCALL_SESSION pCall
  679. )
  680. {
  681. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  682. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallEventDisconnect %08x\n"), pCall));
  683. ASSERT(IS_CALL(pCall));
  684. CallCleanup(pCall, UNLOCKED);
  685. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallEventDisconnect %08x\n"), Status));
  686. return Status;
  687. }
  688. NDIS_STATUS
  689. CallEventConnectFailure(
  690. PCALL_SESSION pCall,
  691. NDIS_STATUS FailureReason
  692. )
  693. {
  694. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  695. ULONG DisconnectMode;
  696. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallEventConnectFailure %08x\n"), FailureReason));
  697. ASSERT(IS_CALL(pCall));
  698. switch (FailureReason)
  699. {
  700. case STATUS_CONNECTION_REFUSED:
  701. case STATUS_IO_TIMEOUT:
  702. DisconnectMode = LINEDISCONNECTMODE_NOANSWER;
  703. break;
  704. case STATUS_BAD_NETWORK_PATH:
  705. case STATUS_NETWORK_UNREACHABLE:
  706. case STATUS_HOST_UNREACHABLE:
  707. DisconnectMode = LINEDISCONNECTMODE_UNREACHABLE;
  708. break;
  709. case STATUS_CONNECTION_ABORTED:
  710. DisconnectMode = LINEDISCONNECTMODE_REJECT;
  711. break;
  712. case STATUS_REMOTE_NOT_LISTENING:
  713. DisconnectMode = LINEDISCONNECTMODE_BADADDRESS;
  714. break;
  715. default:
  716. DisconnectMode = LINEDISCONNECTMODE_UNKNOWN;
  717. break;
  718. }
  719. CallSetState(pCall, STATE_CALL_CLEANUP, DisconnectMode, UNLOCKED);
  720. CallCleanup(pCall, UNLOCKED);
  721. DEBUGMSG(DBG_FUNC, (DTEXT("-CallEventConnectFailure\n")));
  722. return Status;
  723. }
  724. NDIS_STATUS
  725. CallEventOutboundTunnelEstablished(
  726. IN PCALL_SESSION pCall,
  727. IN NDIS_STATUS EventStatus
  728. )
  729. {
  730. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallEventOutboundTunnelEstablished %08x\n"), EventStatus));
  731. ASSERT(IS_CALL(pCall));
  732. DEBUGMSG(DBG_CALL, (DTEXT("Tunnel Established:Inbound:%d State:%d\n"),
  733. pCall->Inbound, pCall->State));
  734. if (!pCall->Inbound && pCall->State==STATE_CALL_DIALING)
  735. {
  736. PPTP_CALL_OUT_REQUEST_PACKET *pPacket = CtlAllocPacket(pCall->pCtl, CALL_OUT_REQUEST);
  737. if (!pPacket)
  738. {
  739. // Fatal for this call.
  740. CallCleanup(pCall, UNLOCKED);
  741. }
  742. else
  743. {
  744. BOOLEAN Cancelled;
  745. USHORT NewCallId;
  746. NdisAcquireSpinLock(&pCall->Lock);
  747. CallSetState(pCall, STATE_CALL_PROCEEDING, 0, LOCKED);
  748. NdisMCancelTimer(&pCall->DialTimer, &Cancelled);
  749. CallAssignSerialNumber(pCall);
  750. NewCallId = (USHORT)((pCall->SerialNumber << CALL_ID_INDEX_BITS) + pCall->DeviceId);
  751. if (pCall->Packet.CallId == NewCallId)
  752. {
  753. // Don't allow a line to have the same CallId twice in a row.
  754. NewCallId += (1<<CALL_ID_INDEX_BITS);
  755. }
  756. pCall->Packet.CallId = NewCallId;
  757. // Our call ID is a function of the serial number (initially random)
  758. // and the DeviceId. This is so we can (CallId&0xfff) on incoming packets
  759. // and instantly have the proper id.
  760. pPacket->CallId = htons(pCall->Packet.CallId);
  761. pPacket->SerialNumber = htons(pCall->SerialNumber);
  762. pPacket->MinimumBPS = htonl(300);
  763. pPacket->MaximumBPS = htonl(100000000);
  764. pPacket->BearerType = htonl(BEARER_ANALOG|BEARER_DIGITAL); // Either
  765. pPacket->FramingType = htonl(FRAMING_ASYNC|FRAMING_SYNC); // Either
  766. pPacket->RecvWindowSize = htons(PPTP_RECV_WINDOW); // ToDo: make configurable
  767. pPacket->ProcessingDelay = 0;
  768. pPacket->PhoneNumberLength = htons((USHORT)strlen(pCall->CallerId));
  769. strcpy(pPacket->PhoneNumber, pCall->CallerId);
  770. // ToDo: subaddress
  771. NdisReleaseSpinLock(&pCall->Lock);
  772. CtlSend(pCall->pCtl, pPacket); // ToDo: return value
  773. }
  774. }
  775. DEBUGMSG(DBG_FUNC, (DTEXT("-CallEventOutboundTunnelEstablished\n")));
  776. return NDIS_STATUS_SUCCESS;
  777. }
  778. NDIS_STATUS
  779. CallReceiveDatagramCallback(
  780. IN PVOID pContext,
  781. IN PTRANSPORT_ADDRESS pAddress,
  782. IN PUCHAR pBuffer,
  783. IN ULONG ulLength
  784. )
  785. {
  786. PPPTP_ADAPTER pAdapter = (PPPTP_ADAPTER)pContext;
  787. PTA_IP_ADDRESS pIpAddress = (PTA_IP_ADDRESS)pAddress;
  788. PCALL_SESSION pCall = NULL;
  789. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  790. PIP4_HEADER pIp = (PIP4_HEADER)pBuffer;
  791. PGRE_HEADER pGre = (PGRE_HEADER)(pIp + 1);
  792. PVOID pPayload;
  793. LONG GreLength, PayloadLength;
  794. BOOLEAN ReturnBufferNow = TRUE;
  795. PDGRAM_CONTEXT pDgContext = ALIGN_UP_POINTER(pBuffer+ulLength, ULONG_PTR);
  796. DEBUGMSG(DBG_FUNC, (DTEXT("+CallReceiveDatagramCallback\n")));
  797. ASSERT(sizeof(IP4_HEADER)==20);
  798. DEBUGMEM(DBG_PACKET, pBuffer, ulLength, 1);
  799. NdisInterlockedIncrement(&Counters.PacketsReceived);
  800. // First line of defense against bad packets.
  801. if (pIp->HeaderLength*4!=sizeof(IP4_HEADER) ||
  802. pIp->Version!=4 ||
  803. pIp->Protocol!=PptpProtocolNumber ||
  804. ulLength<sizeof(IP4_HEADER)+sizeof(GRE_HEADER)+sizeof(ULONG) ||
  805. pIpAddress->TAAddressCount!=1 ||
  806. pIpAddress->Address[0].AddressLength!=TDI_ADDRESS_LENGTH_IP ||
  807. pIpAddress->Address[0].AddressType!=TDI_ADDRESS_TYPE_IP)
  808. {
  809. DEBUGMSG(DBG_PACKET|DBG_RX, (DTEXT("Rx: IP header invalid\n")));
  810. Status = NDIS_STATUS_FAILURE;
  811. goto crdcDone;
  812. }
  813. GreLength = sizeof(GRE_HEADER) +
  814. (pGre->SequenceNumberPresent ? sizeof(ULONG) : 0) +
  815. (pGre->AckSequenceNumberPresent ? sizeof(ULONG) : 0);
  816. pPayload = (PUCHAR)pGre + GreLength;
  817. PayloadLength = (signed)ulLength - sizeof(IP4_HEADER) - GreLength;
  818. if (htons(pGre->KeyLength)>PayloadLength ||
  819. pGre->StrictSourceRoutePresent ||
  820. pGre->RecursionControl ||
  821. !pGre->KeyPresent ||
  822. pGre->RoutingPresent ||
  823. pGre->ChecksumPresent ||
  824. pGre->Version!=1 ||
  825. pGre->Flags ||
  826. pGre->ProtocolType!=GRE_PROTOCOL_TYPE_NS)
  827. {
  828. DEBUGMSG(DBG_PACKET|DBG_RX, (DTEXT("Rx: GRE header invalid\n")));
  829. DEBUGMEM(DBG_PACKET, pGre, GreLength, 1);
  830. Status = NDIS_STATUS_FAILURE;
  831. goto crdcDone;
  832. }
  833. else
  834. {
  835. // Just in case the datagram is longer than necessary, take only what
  836. // the GRE header indicates.
  837. PayloadLength = htons(pGre->KeyLength);
  838. }
  839. // Demultiplex the packet
  840. pCall = CallGetCall(pAdapter, CallIdToDeviceId(htons(pGre->KeyCallId)));
  841. if (!IS_CALL(pCall))
  842. {
  843. Status = NDIS_STATUS_FAILURE;
  844. goto crdcDone;
  845. }
  846. if(!PptpValidateAddress || pIpAddress->Address[0].Address[0].in_addr == pCall->Remote.Address.Address[0].Address[0].in_addr)
  847. {
  848. pDgContext->pBuffer = pBuffer;
  849. pDgContext->pGreHeader = pGre;
  850. pDgContext->hCtdi = pAdapter->hCtdiDg;
  851. NdisAcquireSpinLock(&pCall->Lock);
  852. pCall->UseUdp = FALSE;
  853. NdisReleaseSpinLock(&pCall->Lock);
  854. if (CallQueueReceivePacket(pCall, pDgContext)==NDIS_STATUS_SUCCESS)
  855. {
  856. REFERENCE_OBJECT(pCall);
  857. ReturnBufferNow = FALSE;
  858. }
  859. }
  860. else
  861. {
  862. Status = NDIS_STATUS_FAILURE;
  863. }
  864. crdcDone:
  865. if (ReturnBufferNow)
  866. {
  867. (void)
  868. CtdiReceiveComplete(pAdapter->hCtdiDg, pBuffer);
  869. }
  870. if (Status!=NDIS_STATUS_SUCCESS)
  871. {
  872. NdisInterlockedIncrement(&Counters.PacketsRejected);
  873. }
  874. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallReceiveDatagramCallback %08x\n"), Status));
  875. return Status;
  876. }
  877. NDIS_STATUS
  878. CallReceiveUdpCallback(
  879. IN PVOID pContext,
  880. IN PTRANSPORT_ADDRESS pAddress,
  881. IN PUCHAR pBuffer,
  882. IN ULONG ulLength
  883. )
  884. {
  885. PPPTP_ADAPTER pAdapter = (PPPTP_ADAPTER)pContext;
  886. PTA_IP_ADDRESS pIpAddress = (PTA_IP_ADDRESS)pAddress;
  887. PCALL_SESSION pCall = NULL;
  888. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  889. PGRE_HEADER pGre = (PGRE_HEADER)pBuffer;
  890. PVOID pPayload;
  891. LONG GreLength, PayloadLength;
  892. BOOLEAN ReturnBufferNow = TRUE;
  893. PDGRAM_CONTEXT pDgContext = ALIGN_UP_POINTER(pBuffer+ulLength, ULONG_PTR);
  894. DEBUGMSG(DBG_FUNC, (DTEXT("+CallReceiveDatagramCallback\n")));
  895. DEBUGMEM(DBG_PACKET, pBuffer, ulLength, 1);
  896. NdisInterlockedIncrement(&Counters.PacketsReceived);
  897. // First line of defense against bad packets.
  898. if (pIpAddress->Address[0].Address[0].sin_port!=ntohs(PptpProtocolNumber) ||
  899. ulLength<sizeof(GRE_HEADER)+sizeof(ULONG) ||
  900. pIpAddress->TAAddressCount!=1 ||
  901. pIpAddress->Address[0].AddressLength!=TDI_ADDRESS_LENGTH_IP ||
  902. pIpAddress->Address[0].AddressType!=TDI_ADDRESS_TYPE_IP)
  903. {
  904. DEBUGMSG(DBG_PACKET|DBG_RX, (DTEXT("Rx: GRE header invalid\n")));
  905. Status = NDIS_STATUS_FAILURE;
  906. goto crdcDone;
  907. }
  908. GreLength = sizeof(GRE_HEADER) +
  909. (pGre->SequenceNumberPresent ? sizeof(ULONG) : 0) +
  910. (pGre->AckSequenceNumberPresent ? sizeof(ULONG) : 0);
  911. pPayload = (PUCHAR)pGre + GreLength;
  912. PayloadLength = (signed)ulLength - GreLength;
  913. if (htons(pGre->KeyLength)>PayloadLength ||
  914. pGre->StrictSourceRoutePresent ||
  915. pGre->RecursionControl ||
  916. !pGre->KeyPresent ||
  917. pGre->RoutingPresent ||
  918. pGre->ChecksumPresent ||
  919. pGre->Version!=1 ||
  920. pGre->Flags ||
  921. pGre->ProtocolType!=GRE_PROTOCOL_TYPE_NS)
  922. {
  923. DEBUGMSG(DBG_PACKET|DBG_RX, (DTEXT("Rx: GRE header invalid\n")));
  924. DEBUGMEM(DBG_PACKET, pGre, GreLength, 1);
  925. Status = NDIS_STATUS_FAILURE;
  926. goto crdcDone;
  927. }
  928. else
  929. {
  930. // Just in case the datagram is longer than necessary, take only what
  931. // the GRE header indicates.
  932. PayloadLength = htons(pGre->KeyLength);
  933. }
  934. // Demultiplex the packet
  935. pCall = CallGetCall(pAdapter, CallIdToDeviceId(htons(pGre->KeyCallId)));
  936. if (!IS_CALL(pCall))
  937. {
  938. Status = NDIS_STATUS_FAILURE;
  939. goto crdcDone;
  940. }
  941. pDgContext->pBuffer = pBuffer;
  942. pDgContext->pGreHeader = pGre;
  943. pDgContext->hCtdi = pAdapter->hCtdiUdp;
  944. NdisAcquireSpinLock(&pCall->Lock);
  945. pCall->UseUdp = TRUE;
  946. NdisReleaseSpinLock(&pCall->Lock);
  947. if (CallQueueReceivePacket(pCall, pDgContext)==NDIS_STATUS_SUCCESS)
  948. {
  949. REFERENCE_OBJECT(pCall);
  950. ReturnBufferNow = FALSE;
  951. }
  952. crdcDone:
  953. if (ReturnBufferNow)
  954. {
  955. (void)
  956. CtdiReceiveComplete(pAdapter->hCtdiUdp, pBuffer);
  957. }
  958. if (Status!=NDIS_STATUS_SUCCESS)
  959. {
  960. NdisInterlockedIncrement(&Counters.PacketsRejected);
  961. // ToDo: cleanup?
  962. }
  963. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallReceiveDatagramCallback %08x\n"), Status));
  964. return Status;
  965. }
  966. BOOLEAN
  967. CallConnectToCtl(
  968. IN PCALL_SESSION pCall,
  969. IN PCONTROL_TUNNEL pCtl,
  970. IN BOOLEAN CallLocked
  971. )
  972. {
  973. BOOLEAN Connected = FALSE;
  974. DEBUGMSG(DBG_FUNC, (DTEXT("+CallConnectCtl\n")));
  975. if (!CallLocked)
  976. {
  977. NdisAcquireSpinLock(&pCall->Lock);
  978. }
  979. ASSERT_LOCK_HELD(&pCall->Lock);
  980. NdisAcquireSpinLock(&pCall->pAdapter->Lock);
  981. if (!pCall->pCtl)
  982. {
  983. pCall->pCtl = pCtl;
  984. InsertTailList(&pCtl->CallList, &pCall->ListEntry);
  985. Connected = TRUE;
  986. REFERENCE_OBJECT(pCtl); // Pair in CallDisconnectFromCtl
  987. }
  988. NdisReleaseSpinLock(&pCall->pAdapter->Lock);
  989. if (!CallLocked)
  990. {
  991. NdisReleaseSpinLock(&pCall->Lock);
  992. }
  993. DEBUGMSG(DBG_FUNC, (DTEXT("-CallConnectCtl %d\n"), Connected));
  994. return Connected;
  995. }
  996. VOID
  997. CallDisconnectFromCtl(
  998. IN PCALL_SESSION pCall,
  999. IN PCONTROL_TUNNEL pCtl
  1000. )
  1001. {
  1002. BOOLEAN Deref = FALSE;
  1003. DEBUGMSG(DBG_FUNC, (DTEXT("+CallDisconnectFromCtl\n")));
  1004. NdisAcquireSpinLock(&pCall->Lock);
  1005. NdisAcquireSpinLock(&pCall->pAdapter->Lock);
  1006. ASSERT(pCall->pCtl==pCtl);
  1007. if (pCall->pCtl==pCtl)
  1008. {
  1009. pCall->pCtl = NULL;
  1010. RemoveEntryList(&pCall->ListEntry);
  1011. Deref = TRUE;
  1012. }
  1013. NdisReleaseSpinLock(&pCall->pAdapter->Lock);
  1014. NdisReleaseSpinLock(&pCall->Lock);
  1015. if (Deref)
  1016. {
  1017. DEREFERENCE_OBJECT(pCtl);
  1018. }
  1019. DEBUGMSG(DBG_FUNC, (DTEXT("-CallDisconnectFromCtl\n")));
  1020. }
  1021. NDIS_STATUS
  1022. CallSetLinkInfo(
  1023. PPPTP_ADAPTER pAdapter,
  1024. IN PNDIS_WAN_SET_LINK_INFO pRequest
  1025. )
  1026. {
  1027. PCALL_SESSION pCall;
  1028. PCONTROL_TUNNEL pCtl;
  1029. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1030. PPPTP_SET_LINK_INFO_PACKET pPacket;
  1031. DEBUGMSG(DBG_FUNC, (DTEXT("+CallSetLinkInfo\n")));
  1032. // Verify the ID
  1033. pCall = CallGetCall(pAdapter, LinkHandleToId(pRequest->NdisLinkHandle));
  1034. if (!pCall)
  1035. {
  1036. Status = NDIS_STATUS_FAILURE;
  1037. goto csliDone;
  1038. }
  1039. ASSERT(IS_CALL(pCall));
  1040. NdisAcquireSpinLock(&pCall->Lock);
  1041. pCall->WanLinkInfo = *pRequest;
  1042. #if 0
  1043. DBG_X(DBG_NDIS, pCall->WanLinkInfo.MaxSendFrameSize);
  1044. DBG_X(DBG_NDIS, pCall->WanLinkInfo.MaxRecvFrameSize);
  1045. DBG_X(DBG_NDIS, pCall->WanLinkInfo.HeaderPadding);
  1046. DBG_X(DBG_NDIS, pCall->WanLinkInfo.TailPadding);
  1047. DBG_X(DBG_NDIS, pCall->WanLinkInfo.SendACCM);
  1048. DBG_X(DBG_NDIS, pCall->WanLinkInfo.RecvACCM);
  1049. #endif
  1050. pCtl = pCall->pCtl;
  1051. NdisReleaseSpinLock(&pCall->Lock);
  1052. // Report the new ACCMs to the peer.
  1053. pPacket = CtlAllocPacket(pCtl, SET_LINK_INFO);
  1054. if (!pPacket)
  1055. {
  1056. Status = NDIS_STATUS_RESOURCES;
  1057. }
  1058. else
  1059. {
  1060. pPacket->PeerCallId = ntohs(pCall->Remote.CallId);
  1061. pPacket->SendAccm = ntohl(pCall->WanLinkInfo.SendACCM);
  1062. pPacket->RecvAccm = ntohl(pCall->WanLinkInfo.RecvACCM);
  1063. Status = CtlSend(pCtl, pPacket);
  1064. }
  1065. csliDone:
  1066. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallSetLinkInfo %08x\n"), Status));
  1067. return Status;
  1068. }
  1069. VOID
  1070. CallSetState(
  1071. IN PCALL_SESSION pCall,
  1072. IN CALL_STATE State,
  1073. IN ULONG_PTR StateParam,
  1074. IN BOOLEAN Locked
  1075. )
  1076. {
  1077. ULONG OldLineCallState = CallGetLineCallState(pCall->State);
  1078. ULONG NewLineCallState = CallGetLineCallState(State);
  1079. DEBUGMSG(DBG_FUNC, (DTEXT("+CallSetState %d\n"), State));
  1080. if (State!=pCall->State)
  1081. {
  1082. LOGMSG(FLL_DETAILED, (DTEXT(LOGHDRS"Call(%d) state change. Old:%d New:%d\n"),
  1083. LOGHDR(26, pCall->Remote.Address.Address[0].Address[0].in_addr),
  1084. pCall->DeviceId, pCall->State, State));
  1085. }
  1086. ASSERT(IS_CALL(pCall));
  1087. if (!Locked)
  1088. {
  1089. NdisAcquireSpinLock(&pCall->Lock);
  1090. }
  1091. ASSERT_LOCK_HELD(&pCall->Lock);
  1092. pCall->State = State;
  1093. if (!Locked)
  1094. {
  1095. NdisReleaseSpinLock(&pCall->Lock);
  1096. }
  1097. if (OldLineCallState!=NewLineCallState &&
  1098. pCall->hTapiCall)
  1099. {
  1100. NDIS_TAPI_EVENT TapiEvent;
  1101. DEBUGMSG(DBG_TAPI|DBG_NDIS, (DTEXT("PPTP: Indicating new LINE_CALLSTATE %x\n"), NewLineCallState));
  1102. #if SINGLE_LINE
  1103. TapiEvent.htLine = pCall->pAdapter->Tapi.hTapiLine;
  1104. #else
  1105. TapiEvent.htLine = pCall->hTapiLine;
  1106. #endif
  1107. TapiEvent.htCall = pCall->hTapiCall;
  1108. TapiEvent.ulMsg = LINE_CALLSTATE;
  1109. TapiEvent.ulParam1 = NewLineCallState;
  1110. TapiEvent.ulParam2 = StateParam;
  1111. TapiEvent.ulParam3 = LINEMEDIAMODE_DIGITALDATA; // ToDo: is this required?
  1112. if (Locked)
  1113. {
  1114. NdisReleaseSpinLock(&pCall->Lock);
  1115. }
  1116. NdisMIndicateStatus(pCall->pAdapter->hMiniportAdapter,
  1117. NDIS_STATUS_TAPI_INDICATION,
  1118. &TapiEvent,
  1119. sizeof(TapiEvent));
  1120. if (Locked)
  1121. {
  1122. NdisAcquireSpinLock(&pCall->Lock);
  1123. }
  1124. }
  1125. DEBUGMSG(DBG_FUNC, (DTEXT("-CallSetState\n")));
  1126. }
  1127. GRE_HEADER DefaultGreHeader = {
  1128. 0, // Recursion control
  1129. 0, // Strict source route present
  1130. 0, // Sequence Number present
  1131. 1, // Key present
  1132. 0, // Routing present
  1133. 0, // Checksum present
  1134. 1, // Version
  1135. 0, // Flags
  1136. 0, // Ack present
  1137. GRE_PROTOCOL_TYPE_NS
  1138. };
  1139. VOID
  1140. CallpSendCompleteDeferred(
  1141. IN PPPTP_WORK_ITEM pWorkItem
  1142. )
  1143. {
  1144. PCALL_SESSION pCall = pWorkItem->Context;
  1145. PNDIS_WAN_PACKET pPacket = pWorkItem->pBuffer;
  1146. NDIS_STATUS Result = pWorkItem->Length;
  1147. DEBUGMSG(DBG_FUNC, (DTEXT("+CallpSendCompleteDeferred\n")));
  1148. NdisMWanSendComplete(pCall->pAdapter->hMiniportAdapter,
  1149. pPacket,
  1150. Result);
  1151. DEREFERENCE_OBJECT(pCall);
  1152. DEBUGMSG(DBG_FUNC, (DTEXT("-CallpSendCompleteDeferred\n")));
  1153. }
  1154. VOID
  1155. CallpSendComplete(
  1156. IN PVOID pContext,
  1157. IN PVOID pDatagramContext,
  1158. IN PUCHAR pBuffer,
  1159. IN NDIS_STATUS Result
  1160. )
  1161. {
  1162. PCALL_SESSION pCall = pContext;
  1163. PNDIS_WAN_PACKET pPacket = pDatagramContext;
  1164. DEBUGMSG(DBG_FUNC|DBG_TX, (DTEXT("+CallpSendComplete pCall=%x, pPacket=%x, Result=%x\n"), pCall, pPacket, Result));
  1165. ASSERT(IS_CALL(pCall));
  1166. if (Result!=NDIS_STATUS_SUCCESS)
  1167. {
  1168. DEBUGMSG(DBG_ERROR, (DTEXT("Failed to send datagram %08x\n"), Result));
  1169. NdisInterlockedIncrement(&Counters.PacketsSentError);
  1170. }
  1171. if (pPacket==&pCall->Ack.Packet)
  1172. {
  1173. NdisAcquireSpinLock(&pCall->Lock);
  1174. pCall->Ack.PacketQueued = FALSE;
  1175. NdisReleaseSpinLock(&pCall->Lock);
  1176. }
  1177. else
  1178. {
  1179. // When we complet packets immediately, we can get into trouble if a
  1180. // packet has recursed. We need a way to short-circuit a recursing
  1181. // completion so we don't blow the stack.
  1182. // We store a count of times we've completed a packet in the same
  1183. // context and defer to a thread after a certain number of trips through.
  1184. if ((NdisInterlockedIncrement(&pCall->SendCompleteRecursion)<PptpSendRecursionLimit) ||
  1185. ScheduleWorkItem(CallpSendCompleteDeferred, pCall, pPacket, Result)!=NDIS_STATUS_SUCCESS)
  1186. {
  1187. NdisMWanSendComplete(pCall->pAdapter->hMiniportAdapter,
  1188. pPacket,
  1189. Result);
  1190. DEREFERENCE_OBJECT(pCall);
  1191. }
  1192. NdisInterlockedDecrement(&pCall->SendCompleteRecursion);
  1193. }
  1194. DEBUGMSG(DBG_FUNC, (DTEXT("-CallpSendComplete\n")));
  1195. }
  1196. #define TRANSMIT_SEND_SEQ 1
  1197. #define TRANSMIT_SEND_ACK 2
  1198. #define TRANSMIT_MASK 0x3
  1199. ULONG GreSize[4] = {
  1200. sizeof(GRE_HEADER),
  1201. sizeof(GRE_HEADER) + sizeof(ULONG),
  1202. sizeof(GRE_HEADER) + sizeof(ULONG),
  1203. sizeof(GRE_HEADER) + sizeof(ULONG) * 2
  1204. };
  1205. NDIS_STATUS
  1206. CallTransmitPacket(
  1207. PCALL_SESSION pCall,
  1208. PNDIS_WAN_PACKET pPacket,
  1209. ULONG Flags,
  1210. ULONG SequenceNumber,
  1211. ULONG Ack
  1212. )
  1213. {
  1214. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1215. ULONG Length;
  1216. PULONG pSequence, pAck;
  1217. PGRE_HEADER pGreHeader;
  1218. DEBUGMSG(DBG_FUNC, (DTEXT("+CallTransmitPacket\n")));
  1219. if (!IS_CALL(pCall) || pCall->State!=STATE_CALL_ESTABLISHED)
  1220. {
  1221. goto ctpDone;
  1222. }
  1223. Length = GreSize[Flags&TRANSMIT_MASK];
  1224. pGreHeader = (PGRE_HEADER) (pPacket->CurrentBuffer - Length);
  1225. pSequence = pAck = (PULONG)(pGreHeader + 1);
  1226. *pGreHeader = DefaultGreHeader;
  1227. if (Flags&TRANSMIT_SEND_SEQ)
  1228. {
  1229. pGreHeader->SequenceNumberPresent = 1;
  1230. *pSequence = htonl(SequenceNumber);
  1231. pAck++;
  1232. }
  1233. pGreHeader->KeyLength = htons((USHORT)pPacket->CurrentLength);
  1234. pGreHeader->KeyCallId = htons(pCall->Remote.CallId);
  1235. if (Flags&TRANSMIT_SEND_ACK)
  1236. {
  1237. pGreHeader->AckSequenceNumberPresent = 1;
  1238. *pAck = htonl(Ack);
  1239. }
  1240. Status = CtdiSendDatagram((pCall->UseUdp ? pCall->pAdapter->hCtdiUdp : pCall->pAdapter->hCtdiDg),
  1241. CallpSendComplete,
  1242. pCall,
  1243. pPacket,
  1244. (PTRANSPORT_ADDRESS)&pCall->Remote.Address,
  1245. (PVOID)pGreHeader,
  1246. pPacket->CurrentLength + Length);
  1247. NdisInterlockedIncrement(&Counters.PacketsSent);
  1248. ctpDone:
  1249. DEBUGMSG(DBG_FUNC|DBG_ERR(Status), (DTEXT("-CallTransmitPacket %08x\n"), Status));
  1250. return Status;
  1251. }
  1252. VOID
  1253. CallProcessRxPackets(
  1254. IN PVOID SystemSpecific1,
  1255. IN PVOID Context,
  1256. IN PVOID SystemSpecific2,
  1257. IN PVOID SystemSpecific3
  1258. )
  1259. {
  1260. PCALL_SESSION pCall = Context;
  1261. ULONG_PTR ReceiveMax = 100;
  1262. NDIS_STATUS Status;
  1263. DEBUGMSG(DBG_FUNC, (DTEXT("+CallProcessRxPackets\n")));
  1264. ASSERT(IS_CALL(pCall));
  1265. NdisAcquireSpinLock(&pCall->Lock);
  1266. // First send up any received packets.
  1267. while (ReceiveMax-- && !IsListEmpty(&pCall->RxPacketList))
  1268. {
  1269. PDGRAM_CONTEXT pDgram;
  1270. PLIST_ENTRY pListEntry = RemoveHeadList(&pCall->RxPacketList);
  1271. pCall->RxPacketsPending--;
  1272. pDgram = CONTAINING_RECORD(pListEntry,
  1273. DGRAM_CONTEXT,
  1274. ListEntry);
  1275. if (pCall->State==STATE_CALL_ESTABLISHED &&
  1276. htons(pDgram->pGreHeader->KeyCallId)==pCall->Packet.CallId &&
  1277. IS_LINE_UP(pCall))
  1278. {
  1279. LONG GreLength, PayloadLength;
  1280. PVOID pPayload;
  1281. BOOLEAN SetAckTimer = FALSE;
  1282. ULONG Sequence;
  1283. if (pDgram->pGreHeader->SequenceNumberPresent)
  1284. {
  1285. // Call is still in good state, indicate the packet.
  1286. Sequence = htonl(GreSequence(pDgram->pGreHeader));
  1287. pCall->Remote.SequenceNumber = Sequence + 1;
  1288. if (IsListEmpty(&pCall->TxPacketList) && !pCall->Ack.PacketQueued && pDgram->pGreHeader->KeyLength)
  1289. {
  1290. // We only ack if there aren't already other transmits sent, and this
  1291. // isn't an ack-only packet.
  1292. SetAckTimer = pCall->Ack.PacketQueued = TRUE;
  1293. }
  1294. }
  1295. if (!PptpEchoAlways)
  1296. {
  1297. pCall->pCtl->Echo.Needed = FALSE;
  1298. }
  1299. NdisReleaseSpinLock(&pCall->Lock);
  1300. if (SetAckTimer)
  1301. {
  1302. NdisMSetTimer(&pCall->Ack.Timer, 100);
  1303. }
  1304. GreLength = sizeof(GRE_HEADER) +
  1305. (pDgram->pGreHeader->SequenceNumberPresent ? sizeof(ULONG) : 0) +
  1306. (pDgram->pGreHeader->AckSequenceNumberPresent ? sizeof(ULONG) : 0);
  1307. pPayload = (PUCHAR)pDgram->pGreHeader + GreLength;
  1308. PayloadLength = htons(pDgram->pGreHeader->KeyLength);
  1309. if (PayloadLength && pDgram->pGreHeader->SequenceNumberPresent)
  1310. {
  1311. NdisMWanIndicateReceive(&Status,
  1312. pCall->pAdapter->hMiniportAdapter,
  1313. pCall->NdisLinkContext,
  1314. pPayload,
  1315. PayloadLength);
  1316. if (Status==NDIS_STATUS_SUCCESS)
  1317. {
  1318. NdisMWanIndicateReceiveComplete(pCall->pAdapter->hMiniportAdapter,
  1319. pCall->NdisLinkContext);
  1320. }
  1321. }
  1322. NdisAcquireSpinLock(&pCall->Lock);
  1323. }
  1324. else if (pCall->State!=STATE_CALL_ESTABLISHED || !IS_LINE_UP(pCall))
  1325. {
  1326. // If this call is being torn down, we want to put priority on
  1327. // clearing out any packets left over. It should go fast since
  1328. // we're not indicating them up.
  1329. ReceiveMax = 100;
  1330. }
  1331. DEREFERENCE_OBJECT(pCall);
  1332. (void)CtdiReceiveComplete(pDgram->hCtdi, pDgram->pBuffer);
  1333. }
  1334. if (IsListEmpty(&pCall->RxPacketList))
  1335. {
  1336. pCall->Receiving = FALSE;
  1337. }
  1338. else
  1339. {
  1340. PptpQueueDpc(&pCall->ReceiveDpc);
  1341. }
  1342. NdisReleaseSpinLock(&pCall->Lock);
  1343. DEREFERENCE_OBJECT(pCall);
  1344. DEBUGMSG(DBG_FUNC, (DTEXT("-CallProcessRxPackets\n")));
  1345. }
  1346. BOOLEAN
  1347. CallProcessPackets(
  1348. PCALL_SESSION pCall,
  1349. ULONG TransferMax
  1350. )
  1351. {
  1352. LIST_ENTRY LocalList;
  1353. BOOLEAN MorePacketsToTransfer = FALSE;
  1354. ULONG TransmitFlags = 0;
  1355. NDIS_STATUS Status;
  1356. ULONG Ack, Seq;
  1357. ULONG ReceiveMax = TransferMax;
  1358. DEBUGMSG(DBG_FUNC, (DTEXT("+CallProcessPackets\n")));
  1359. ASSERT(sizeof(GRE_HEADER)==8);
  1360. ASSERT(IS_CALL(pCall));
  1361. REFERENCE_OBJECT(pCall);
  1362. InitializeListHead(&LocalList);
  1363. NdisAcquireSpinLock(&pCall->Lock);
  1364. Seq = pCall->Packet.SequenceNumber;
  1365. while (TransferMax-- && !IsListEmpty(&pCall->TxPacketList))
  1366. {
  1367. PLIST_ENTRY pListEntry = RemoveHeadList(&pCall->TxPacketList);
  1368. InsertTailList(&LocalList, pListEntry);
  1369. if (CONTAINING_RECORD(pListEntry,
  1370. NDIS_WAN_PACKET,
  1371. WanPacketQueue)!=&pCall->Ack.Packet)
  1372. {
  1373. pCall->Packet.SequenceNumber++;
  1374. }
  1375. }
  1376. if (!IsListEmpty(&pCall->TxPacketList) || !IsListEmpty(&pCall->RxPacketList))
  1377. {
  1378. MorePacketsToTransfer = TRUE;
  1379. }
  1380. else
  1381. {
  1382. pCall->Transferring = FALSE;
  1383. }
  1384. if (!IsListEmpty(&LocalList) &&
  1385. pCall->Packet.AckNumber!=pCall->Remote.SequenceNumber)
  1386. {
  1387. TransmitFlags |= TRANSMIT_SEND_ACK;
  1388. pCall->Packet.AckNumber = pCall->Remote.SequenceNumber;
  1389. // Ack tracks the Remote.SequenceNumber, which is actually the
  1390. // sequence of the NEXT packet, so we need to translate when
  1391. // we prepare to send an ack.
  1392. Ack = pCall->Remote.SequenceNumber - 1;
  1393. }
  1394. NdisReleaseSpinLock(&pCall->Lock);
  1395. while (!IsListEmpty(&LocalList))
  1396. {
  1397. PNDIS_WAN_PACKET pPacket;
  1398. PLIST_ENTRY pListEntry = RemoveHeadList(&LocalList);
  1399. pPacket = CONTAINING_RECORD(pListEntry,
  1400. NDIS_WAN_PACKET,
  1401. WanPacketQueue);
  1402. if (pPacket!=&pCall->Ack.Packet || TransmitFlags&TRANSMIT_SEND_ACK)
  1403. {
  1404. if (pPacket==&pCall->Ack.Packet)
  1405. {
  1406. TransmitFlags &= ~TRANSMIT_SEND_SEQ;
  1407. }
  1408. else
  1409. {
  1410. TransmitFlags |= TRANSMIT_SEND_SEQ;
  1411. Seq++;
  1412. }
  1413. Status = CallTransmitPacket(pCall, pPacket, TransmitFlags, Seq-1, Ack);
  1414. if (Status!=NDIS_STATUS_PENDING && pPacket!=&pCall->Ack.Packet)
  1415. {
  1416. if (pPacket==&pCall->Ack.Packet)
  1417. {
  1418. NdisAcquireSpinLock(&pCall->Lock);
  1419. pCall->Ack.PacketQueued = FALSE;
  1420. NdisReleaseSpinLock(&pCall->Lock);
  1421. }
  1422. else
  1423. {
  1424. // We didn't send the packet, so tell NDIS we're done with it.
  1425. NdisMWanSendComplete(pCall->pAdapter->hMiniportAdapter,
  1426. pPacket,
  1427. NDIS_STATUS_SUCCESS); // so I lied. Sue me.
  1428. DEREFERENCE_OBJECT(pCall);
  1429. }
  1430. }
  1431. }
  1432. else
  1433. {
  1434. // it was the ack-only packet, and we already sent an ack.
  1435. NdisAcquireSpinLock(&pCall->Lock);
  1436. pCall->Ack.PacketQueued = FALSE;
  1437. NdisReleaseSpinLock(&pCall->Lock);
  1438. }
  1439. TransmitFlags &= ~TRANSMIT_SEND_ACK;
  1440. }
  1441. DEREFERENCE_OBJECT(pCall);
  1442. DEBUGMSG(DBG_FUNC, (DTEXT("-CallProcessPackets %d\n"), MorePacketsToTransfer));
  1443. return MorePacketsToTransfer;
  1444. }
  1445. VOID
  1446. CallpAckTimeout(
  1447. IN PVOID SystemSpecific1,
  1448. IN PVOID Context,
  1449. IN PVOID SystemSpecific2,
  1450. IN PVOID SystemSpecific3
  1451. )
  1452. {
  1453. PCALL_SESSION pCall = Context;
  1454. DEBUGMSG(DBG_FUNC, (DTEXT("+CallpAckTimeout\n")));
  1455. if (IS_CALL(pCall))
  1456. {
  1457. if (pCall->State!=STATE_CALL_ESTABLISHED ||
  1458. CallQueueTransmitPacket(pCall, &pCall->Ack.Packet)!=NDIS_STATUS_PENDING)
  1459. {
  1460. NdisAcquireSpinLock(&pCall->Lock);
  1461. pCall->Ack.PacketQueued = FALSE;
  1462. NdisReleaseSpinLock(&pCall->Lock);
  1463. }
  1464. }
  1465. DEBUGMSG(DBG_FUNC, (DTEXT("-CallpAckTimeout\n")));
  1466. }
  1467. VOID
  1468. CallpDialTimeout(
  1469. IN PVOID SystemSpecific1,
  1470. IN PVOID Context,
  1471. IN PVOID SystemSpecific2,
  1472. IN PVOID SystemSpecific3
  1473. )
  1474. {
  1475. PCALL_SESSION pCall = Context;
  1476. DEBUGMSG(DBG_FUNC, (DTEXT("+CallpDialTimeout\n")));
  1477. LOGMSG(FLL_USER, (DTEXT(LOGHDRS"Call(%d) timed out in dialing state\n"),
  1478. LOGHDR(4, pCall->Remote.Address.Address[0].Address[0].in_addr),
  1479. pCall->DeviceId));
  1480. ASSERT(IS_CALL(pCall));
  1481. if (pCall->State==STATE_CALL_DIALING)
  1482. {
  1483. CallCleanup(pCall, UNLOCKED);
  1484. }
  1485. DEBUGMSG(DBG_FUNC, (DTEXT("-CallpDialTimeout\n")));
  1486. }
  1487. VOID
  1488. CallpCloseTimeout(
  1489. IN PVOID SystemSpecific1,
  1490. IN PVOID Context,
  1491. IN PVOID SystemSpecific2,
  1492. IN PVOID SystemSpecific3
  1493. )
  1494. {
  1495. PCALL_SESSION pCall = Context;
  1496. DEBUGMSG(DBG_FUNC, (DTEXT("+CallpCloseTimeout\n")));
  1497. ASSERT(IS_CALL(pCall));
  1498. pCall->Close.Expedited = TRUE;
  1499. CallCleanup(pCall, UNLOCKED);
  1500. // ToDo: check for failure.
  1501. DEBUGMSG(DBG_FUNC, (DTEXT("-CallpCloseTimeout\n")));
  1502. }
  1503. VOID CallpFinalDeref(PCALL_SESSION pCall)
  1504. {
  1505. DEBUGMSG(DBG_FUNC|DBG_CALL, (DTEXT("+CallpFinalDeref\n")));
  1506. }
  1507. VOID CallpCleanupLooseEnds(PPPTP_ADAPTER pAdapter)
  1508. {
  1509. ULONG i;
  1510. DEBUGMSG(DBG_FUNC, (DTEXT("+CallpCleanupLooseEnds\n")));
  1511. for (i=0; i<pAdapter->Info.Endpoints; i++)
  1512. {
  1513. PCALL_SESSION pCall = pAdapter->pCallArray[i];
  1514. if (IS_CALL(pCall))
  1515. {
  1516. NdisAcquireSpinLock(&pCall->Lock);
  1517. if (IS_CALL(pCall) && pCall->State==STATE_CALL_CLEANUP)
  1518. {
  1519. CallCleanup(pCall, LOCKED);
  1520. }
  1521. NdisReleaseSpinLock(&pCall->Lock);
  1522. }
  1523. }
  1524. DEBUGMSG(DBG_FUNC, (DTEXT("-CallpCleanupLooseEnds\n")));
  1525. }