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.

2786 lines
77 KiB

  1. /*++
  2. Copyright (c) 1996,1997 Microsoft Corporation
  3. Module Name:
  4. SEND.C
  5. Abstract:
  6. Send Handler and Send Thread.
  7. Author:
  8. Aaron Ogus (aarono)
  9. Environment:
  10. Win32/COM
  11. Revision History:
  12. Date Author Description
  13. ====== ====== ============================================================
  14. 12/10/96 aarono Original
  15. 2/18/98 aarono added support for SendEx
  16. 2/18/98 aarono added support for Cancel
  17. 2/20/98 aarono B#18827 not pulling Cancelled sends off queue
  18. 3/09/98 aarono documented workaround for mmTimers on Win95, removed dead code.
  19. 3/29/98 aarono fixed locking for ReliableSend
  20. 3/30/98 aarono make sure erroring sends moved to Done state to avoid reprocess.
  21. 4/14/98 a-peterz B#18340 DPSEND_NOCOPY subsumes DPSEND_NOBUFFERCOPY
  22. 5/18/98 aarono fixed SendEx with scatter gather
  23. 6/6/98 aarono Turn on throttling and windowing
  24. 10/8/99 aarono Improve shutdown handling, avoid 1min hang with pending sends.
  25. 2/12/00 aarono Concurrency issues, fix VOL usage and Refcount
  26. --*/
  27. #include <windows.h>
  28. #include "newdpf.h"
  29. #include <mmsystem.h>
  30. #include <dplay.h>
  31. #include <dplaysp.h>
  32. #include <dplaypr.h>
  33. #include "mydebug.h"
  34. #include "arpd.h"
  35. #include "arpdint.h"
  36. #include "macros.h"
  37. #include "mytimer.h"
  38. #ifdef DEBUG
  39. VOID DQProtocolSend(PSEND pS)
  40. {
  41. DPF(0,"===SEND====pSend %x=====",pS);
  42. #ifdef SIGN
  43. DPF(0,"Signature : %08x", pS->Signature);
  44. #endif
  45. // CRITICAL_SECTION SendLock; // Lock for Send Structure
  46. DPF(0,"RefCount : %d", pS->RefCount);
  47. DPF(0,"SendState: %08x", pS->SendState); // State of this message's transmission.
  48. // Lists and Links...
  49. // union {
  50. // struct _SEND *pNext; // linking on free pool
  51. // BILINK SendQ; // linking on session send queue
  52. // };
  53. // BILINK m_GSendQ; // Global Priority Queue
  54. DPF(0,"pSession: %08x",pS->pSession); // pointer to SESSIONion(gets a ref)
  55. // Send Information
  56. DPF(0,"idFrom: %08x",pS->idFrom);
  57. DPF(0,"idTo: %08x",pS->idTo);
  58. DPF(0,"wIdTo: %08x",pS->wIdTo); // index in table
  59. DPF(0,"wIdFrom: %08x",pS->wIdFrom); // index in table
  60. DPF(0,"dwFlags: %08x",pS->dwFlags); // Send Flags (include reliable)
  61. DPF(0,"pMessage: %08x",pS->pMessage); // Buffer chain describing message.
  62. DPF(0,"MessageSize: %08x",pS->MessageSize); // Total size of the message.
  63. DPF(0,"FrameDataLen: %08x",pS->FrameDataLen); // Data area of each frame.
  64. DPF(0,"nFrames: %08x",pS->nFrames); // Number of frames for this message.
  65. DPF(0,"Priority: %08x",pS->Priority); // Send Priority.
  66. // Vars for reliability
  67. DPF(0,"fSendSmall: %08x",pS->fSendSmall);
  68. DPF(0,"fUpdate: %08x",pS->fUpdate); // update to NS,NR NACKMask made by receive.
  69. DPF(0,"messageid: %08x",pS->messageid); // Message ID number.
  70. DPF(0,"serial: %08x",pS->serial); // serial number.
  71. DPF(0,"OpenWindows %08x",pS->OpenWindow);
  72. DPF(0,"NS: %08x",pS->NS); // Sequence Sent.
  73. DPF(0,"NR: %08x",pS->NR); // Sequence ACKED.
  74. DPF(0,"SendSEQMSK: %08x",pS->SendSEQMSK); // Mask to use.
  75. DPF(0,"NACKMask: %08x",pS->NACKMask); // Bit pattern of NACKed frames.
  76. // These are the values at NR - updated by ACKs
  77. DPF(0,"SendOffset: %08x",pS->SendOffset); // Current offset we are sending.
  78. DPF(0,"pCurrentBuffer: %08x",pS->pCurrentBuffer); // Current buffer being sent.
  79. DPF(0,"CurrentBufferOffset: %08x",pS->CurrentBufferOffset);// Offset in the current buffer of next packet.
  80. // info to update link characteristics when ACKs come in.
  81. //BILINK StatList: // Info for packets already sent.
  82. // Operational Characteristics
  83. // DPF(0,"PendedRetryTimer: %08x\n",pS->PendedRetryTimer);
  84. // DPF(0,"CancelledRetryTimer: %08x\n",pS->CancelledRetryTimer);
  85. DPF(0,"uRetryTimer: %08x",pS->uRetryTimer);
  86. DPF(0,"RetryCount: %08x",pS->RetryCount);// Number of times we retransmitted.
  87. DPF(0,"WindowSize: %08x",pS->WindowSize);// Maximum Window Size.
  88. DPF(0,"tLastACK: %08x",pS->tLastACK);// Time we last got an ACK.
  89. DPF(0,"PacketSize: %08x",pS->PacketSize);// Size of packets to send.
  90. DPF(0,"FrameSize: %08x",pS->FrameSize);// Size of Frames for this send.
  91. // Completion Vars
  92. DPF(0,"hEvent: %08x",pS->hEvent);// Event to wait on for internal send.
  93. DPF(0,"Status: %08x",pS->Status);// Send Completion Status.
  94. DPF(0,"pAsyncInfo: %08x",pS->pAsyncInfo);// ptr to Info for completing Async send(NULL=>internal send)
  95. // DPF(0,"AsyncInfo: // actual info (copied at send call).
  96. }
  97. VOID DQProtocolSession(PSESSION pS)
  98. {
  99. DPF(0,"pProtocol : %08x", pS->pProtocol);
  100. #ifdef SIGN
  101. DPF(0,"Signature : %08x", pS->Signature);
  102. #endif
  103. // Identification
  104. // DPF(0," SessionLock; // Lock for the SESSIONion.
  105. DPF(0,"RefCount : %d", pS->RefCount);
  106. DPF(0,"eState : %d", pS->eState);
  107. DPF(0,"hClosingEvent : %d", pS->hClosingEvent);
  108. DPF(0,"fSendSmall : %d", pS->fSendSmall);
  109. DPF(0,"fSendSmallDG : %d", pS->fSendSmallDG);
  110. DPF(0,"dpid : %08x",pS->dpid);
  111. DPF(0,"iSession; : %d", pS->iSession);
  112. DPF(0,"MaxPacketSize : x%08x %d",pS->MaxPacketSize,pS->MaxPacketSize);
  113. DPF(0,"\n Operating Parameters:SEND \n --------- --------------- \n");
  114. // Operating parameters -- Send
  115. // Common
  116. DPF(0,"Common:\n");
  117. DPF(0,"MaxCSends : %d",pS->MaxCSends);
  118. DPF(0,"Reliable:\n");
  119. // Reliable
  120. DPF(0,"FirstMsg : %08x",pS->FirstMsg); // First message number being transmitted
  121. DPF(0,"LastMsg : %08x",pS->LastMsg); // Last message number being transmitted
  122. DPF(0,"OutMsgMask : %08x",pS->OutMsgMask); // relative to FirstMsg, unacked messages
  123. DPF(0,"nWaitingForMessageid: %08x", pS->nWaitingForMessageid);
  124. // DataGram
  125. DPF(0,"Datagram:\n");
  126. DPF(0,"DGFirstMsg : %08x",pS->DGFirstMsg);
  127. DPF(0,"DGLastMsg : %08x",pS->DGLastMsg);
  128. DPF(0,"DGOutMsgMask : %08x",pS->DGOutMsgMask);
  129. DPF(0,"nWaitingForDGMessageid: %08x",pS->nWaitingForDGMessageid);
  130. // Send stats are tracked seperately since sends may
  131. // no longer be around when completions come in.
  132. //BILINK OldStatList;
  133. // Operating parameters -- Receive
  134. DPF(0,"\n Operating Parameters:RECEIVE \n --------- ------------------ \n");
  135. // DataGram Receive.
  136. // BILINK pDGReceiveQ; // queue of ongoing datagram receives
  137. // Reliable Receive.
  138. // BILINK pRlyReceiveQ; // queue of ongoing reliable receives
  139. // BILINK pRlyWaitingQ; // Queue of out of order reliable receives waiting.
  140. // only used when PROTOCOL_NO_ORDER not set.
  141. DPF(0,"FirstRlyReceive : %08x",pS->FirstRlyReceive);
  142. DPF(0,"LastRlyReceive : %08x",pS->LastRlyReceive);
  143. DPF(0,"InMsgMask : %08x",pS->InMsgMask);
  144. DPF(0,"\n Operating Parameters:STATS \n --------- ---------------- \n");
  145. // Operational characteristics - MUST BE DWORD ALIGNED!!!
  146. DPF(0,"WindowSize :%d",pS->WindowSize);
  147. DPF(0,"DGWindowSize :%d",pS->DGWindowSize);
  148. DPF(0,"MaxRetry :%d",pS->MaxRetry); // Usualy max retries before dropping.
  149. DPF(0,"MinDropTime :%d",pS->MinDropTime); // Min time to retry before dropping.
  150. DPF(0,"MaxDropTime :%d",pS->MaxDropTime); // After this time always drop.
  151. DPF(0,"LocalBytesReceived :%d",pS->LocalBytesReceived); // Total Data Bytes received (including retries).
  152. DPF(0,"RemoteBytesReceived :%d",pS->RemoteBytesReceived); // Last value from remote.
  153. DPF(0,"LongestLatency :%d",pS->LongestLatency); // longest observed latency (msec)
  154. DPF(0,"ShortestLatency :%d",pS->ShortestLatency); // shortest observed latency(msec)
  155. DPF(0,"FpAverageLatency :%d",pS->FpAverageLatency/256);
  156. DPF(0,"FpLocalAverageLatency:%d",pS->FpLocalAverageLatency/256); // Local average latency (msec 24.8) (across fewer samples)
  157. DPF(0,"FpLocalAvgDeviation :%d",pS->FpLocalAvgDeviation/256); // average deviation of latency. (msec 24.8)
  158. DPF(0,"Bandwidth :%d",pS->Bandwidth); // latest observed bandwidth (bps)
  159. DPF(0,"HighestBandwidth :%d",pS->HighestBandwidth); // highest observed bandwidth (bps)
  160. }
  161. VOID DumpSession(SESSION *pSession)
  162. {
  163. BILINK *pBilink;
  164. PSEND pSend;
  165. DWORD dwMaxDump=99;
  166. DQProtocolSession(pSession);
  167. pBilink=pSession->SendQ.next;
  168. while(pBilink != &pSession->SendQ)
  169. {
  170. pSend=CONTAINING_RECORD(pBilink, SEND, SendQ);
  171. DQProtocolSend(pSend);
  172. if((dwMaxDump--)==0) break; // only dump 99 sends
  173. pBilink=pBilink->next;
  174. }
  175. }
  176. #endif
  177. BOOL DGCompleteSend(PSEND pSend);
  178. // a-josbor: for debuggin purposes only
  179. extern DWORD ExtractProtocolIds(PUCHAR pInBuffer, PUINT pdwIdFrom, PUINT pdwIdTo);
  180. INT AddSendRef(PSEND pSend, UINT count)
  181. {
  182. INT newcount;
  183. ASSERT(count > 0);
  184. Lock(&pSend->SendLock);
  185. Lock(&g_SendTimeoutListLock);
  186. if(pSend->bCleaningUp){
  187. DPF(1,"WARNING: ADDSENDREF tried to add reference to cleaning up send %x\n",pSend);
  188. newcount=0;
  189. goto exit;
  190. }
  191. if(!pSend->RefCount){
  192. // Anyone calling addsend ref requires a reference on the session
  193. Unlock(&g_SendTimeoutListLock);
  194. Unlock(&pSend->SendLock);
  195. Lock(&pSend->pSession->pProtocol->m_SessionLock);
  196. Lock(&pSend->pSession->SessionLock);
  197. Lock(&pSend->SendLock);
  198. Lock(&g_SendTimeoutListLock);
  199. InterlockedIncrement((PLONG)&pSend->pSession->RefCount);
  200. Unlock(&pSend->pSession->SessionLock);
  201. Unlock(&pSend->pSession->pProtocol->m_SessionLock);
  202. } else {
  203. newcount=pSend->RefCount;
  204. }
  205. while(count--){
  206. newcount=InterlockedIncrement(&pSend->RefCount);
  207. }
  208. exit:
  209. Unlock(&g_SendTimeoutListLock);
  210. Unlock(&pSend->SendLock);
  211. return newcount;
  212. }
  213. #ifdef DEBUG
  214. // Turn off global optimizations when building DEBUG version since the
  215. // compiler over-writes the return address in this code. NTB#347427
  216. // Should be fixed in compiler post Win2K.
  217. #if _MSC_VER < 0x1100
  218. #pragma optimize("g", off)
  219. #endif
  220. #endif
  221. // Critical Section must not be held when this is called, unless there
  222. // is a reference for holding the critical section (ie. will not hit 0).
  223. INT DecSendRef(PPROTOCOL pProtocol, PSEND pSend)
  224. {
  225. INT count;
  226. PSESSION pSession;
  227. Lock(&pSend->SendLock);
  228. count=InterlockedDecrement((PLONG)&pSend->RefCount);//count is zero if result of dec is zero, otw nonzero but not actual count.
  229. if(!count){
  230. pSession=pSend->pSession;
  231. pSend->bCleaningUp=TRUE;
  232. Unlock(&pSend->SendLock);
  233. // pull the Send off of the global queue and the session queue
  234. Lock(&pProtocol->m_SendQLock);
  235. Lock(&pSession->SessionLock);
  236. Lock(&pSend->SendLock);
  237. Lock(&g_SendTimeoutListLock);
  238. if(!pSend->RefCount){
  239. Delete(&pSend->TimeoutList);
  240. Delete(&pSend->m_GSendQ);
  241. Delete(&pSend->SendQ);
  242. } else {
  243. count=pSend->RefCount;
  244. }
  245. Unlock(&g_SendTimeoutListLock);
  246. Unlock(&pSend->SendLock);
  247. Unlock(&pSession->SessionLock);
  248. Unlock(&pProtocol->m_SendQLock);
  249. if(!count){
  250. DecSessionRef(pSession);
  251. DPF(8,"DecSendRef: pSession %x pSend %x Freeing Send, called from %x\n",pSession, pSend, _ReturnAddress());
  252. FreeHandleTableEntry(&pProtocol->lpHandleTable,&pProtocol->csHandleTable,pSend->dwMsgID);
  253. // Free the message buffer(s) (including memory if WE allocated it).
  254. FreeBufferChainAndMemory(pSend->pMessage);
  255. // OPTIMIZATION:move any Stats we want to keep to the session.
  256. // free the send.(handles the stats for now).
  257. ReleaseSendDesc(pSend);
  258. }
  259. } else {
  260. DPF(8,"DecSendRef: pSession %x pSend %x count %d, called from %x\n",pSend->pSession, pSend, count,_ReturnAddress());
  261. if(count&0x80000000){
  262. DEBUG_BREAK();
  263. }
  264. Unlock(&pSend->SendLock);
  265. }
  266. return count;
  267. }
  268. #ifdef DEBUG
  269. #if _MSC_VER < 1100
  270. #pragma optimize("", on)
  271. #endif
  272. #endif
  273. // SFLAGS_DOUBLEBUFFER - if the send is ASYNCHRONOUS, make a copy of the data
  274. /*=============================================================================
  275. Send - Send a message to a client.
  276. Description:
  277. Used by the client to send a message to another directplay client
  278. or server.
  279. Parameters:
  280. ARPDID idFrom - who is sending this message
  281. ARPDID idTo - target
  282. DWORD dwSendFlags - specifies buffer ownership, priority, reliable
  283. LPVOID pBuffers - Array of buffer and lengths
  284. DWORD dwBufferCount - number of entries in array
  285. PASYNCINFO pAsyncInfo - If specified, call is asynchronous
  286. typedef struct _ASYNCSENDINFO {
  287. UINT Private[4];
  288. HANDLE hEvent;
  289. PSEND_CALLBACK SendCallBack;
  290. PVOID CallBackContext;
  291. UINT Status;
  292. } ASYNCSENDINFO, *PASYNCSENDINFO;
  293. hEvent - event to signal when send completes.
  294. SendCallBack - routine to call when send completes.
  295. CallBackContext - context passed to SendCallBack.
  296. Status - send completion status.
  297. Return Values:
  298. DP_OK - no problem
  299. DPERR_INVALIDPARAMS
  300. -----------------------------------------------------------------------------*/
  301. HRESULT Send(
  302. PPROTOCOL pProtocol,
  303. DPID idFrom,
  304. DPID idTo,
  305. DWORD dwSendFlags,
  306. LPVOID pBuffers,
  307. DWORD dwBufferCount,
  308. DWORD dwSendPri,
  309. DWORD dwTimeOut,
  310. LPVOID lpvUserMsgID,
  311. LPDWORD lpdwMsgID,
  312. BOOL bSendEx,
  313. PASYNCSENDINFO pAsyncInfo
  314. )
  315. {
  316. HRESULT hr=DP_OK;
  317. PSESSION pSession;
  318. PBUFFER pSendBufferChain;
  319. PSEND pSend;
  320. pSession=GetSysSession(pProtocol,idTo);
  321. if(!pSession) {
  322. DPF(4,"NO SESSION for idTo %x, returning SESSIONLOST\n",idTo);
  323. hr=DPERR_CONNECTIONLOST;
  324. goto exit2;
  325. }
  326. pSend=GetSendDesc();
  327. if(!pSend){
  328. ASSERT(0); //TRACE all paths.
  329. hr=DPERR_OUTOFMEMORY;
  330. goto exit;
  331. }
  332. pSend->pProtocol=pProtocol;
  333. // fails by returning 0 in which case cancel won't be available for this send.
  334. pSend->dwMsgID=AllocHandleTableEntry(&pProtocol->lpHandleTable, &pProtocol->csHandleTable, pSend);
  335. if(lpdwMsgID){
  336. *lpdwMsgID=pSend->dwMsgID;
  337. }
  338. pSend->lpvUserMsgID = lpvUserMsgID;
  339. pSend->bSendEx = bSendEx;
  340. // if pAsyncInfo is provided, the call is asynchronous.
  341. // if dwFlags DPSEND_ASYNC is set, the call is async.
  342. // if the call is asynchronous and double buffering is
  343. // required, we must make a copy of the data.
  344. if((pAsyncInfo||(dwSendFlags & DPSEND_ASYNC)) && (!(dwSendFlags & DPSEND_NOCOPY))){
  345. // Need to copy the memory
  346. pSendBufferChain=GetDoubleBufferAndCopy((PMEMDESC)pBuffers,dwBufferCount);
  347. // OPTIMIZATION: if the provider requires contiguous buffers, we should
  348. // break this down into packet allocations, and chain them
  349. // on the send immediately. Using the packet chain to indicate
  350. // to ISend routine that the message is already broken down.
  351. } else {
  352. // Build a send buffer chain for the described buffers.
  353. pSendBufferChain=BuildBufferChain((PMEMDESC)pBuffers,dwBufferCount);
  354. }
  355. if(!pSendBufferChain){
  356. ASSERT(0); //TRACE all paths.
  357. return DPERR_OUTOFMEMORY;
  358. }
  359. pSend->pSession = pSession; //!!! when this is dropped, deref the connection
  360. pSend->pMessage = pSendBufferChain;
  361. pSend->MessageSize = BufferChainTotalSize(pSendBufferChain);
  362. pSend->SendOffset = 0;
  363. pSend->pCurrentBuffer = pSend->pMessage;
  364. pSend->CurrentBufferOffset = 0;
  365. pSend->Priority = dwSendPri;
  366. pSend->dwFlags = dwSendFlags;
  367. if(pAsyncInfo){
  368. pSend->pAsyncInfo = &pSend->AsyncInfo;
  369. pSend->AsyncInfo = *pAsyncInfo; //copy Async info from client.
  370. } else {
  371. pSend->pAsyncInfo = NULL;
  372. if(pSend->dwFlags & DPSEND_ASYNC){
  373. pSend->AsyncInfo.hEvent = 0;
  374. pSend->AsyncInfo.SendCallBack = InternalSendComplete;
  375. pSend->AsyncInfo.CallBackContext= pSend;
  376. pSend->AsyncInfo.pStatus = &pSend->Status;
  377. }
  378. }
  379. pSend->SendState = Start;
  380. pSend->RetryCount = 0;
  381. pSend->PacketSize = pSession->MaxPacketSize;
  382. pSend->fUpdate = FALSE;
  383. pSend->NR = 0;
  384. pSend->NS = 0;
  385. //pSend->SendSEQMSK = // filled in on the fly.
  386. pSend->WindowSize = pSession->WindowSize;
  387. pSend->SAKInterval = (pSend->WindowSize+1)/2;
  388. pSend->SAKCountDown = pSend->SAKInterval;
  389. pSend->uRetryTimer = 0;
  390. pSend->idFrom = idFrom;
  391. pSend->idTo = idTo;
  392. pSend->wIdFrom = GetIndexByDPID(pProtocol, idFrom);
  393. pSend->wIdTo = (WORD)pSession->iSession;
  394. pSend->RefCount = 0; // if provider does async send counts references.
  395. pSend->serial = 0;
  396. pSend->tLastACK = timeGetTime();
  397. pSend->dwSendTime = pSend->tLastACK;
  398. pSend->dwTimeOut = dwTimeOut;
  399. pSend->BytesThisSend = 0;
  400. pSend->messageid = -1; // avoid matching this send in ACK/NACK handlers
  401. pSend->bCleaningUp = FALSE;
  402. hr=ISend(pProtocol,pSession, pSend);
  403. exit:
  404. DecSessionRef(pSession);
  405. exit2:
  406. return hr;
  407. }
  408. /*================================================================================
  409. Send Completion information matrix:
  410. ===================================
  411. (pSend->dwFlags & ASEND_PROTOCOL)
  412. |
  413. Sync Async Internal (Async)
  414. -------------- ----- --------------------
  415. pSend->pAsyncInfo 0 user 0
  416. pSend->AI.SendCallback 0 user InternalSendComplete
  417. pSend->AI.hEvent pSend->hEvent user 0
  418. pSend->AI.pStatus &pSend->Status user &pSend->Status
  419. ---------------------------------------------------------------------------*/
  420. HRESULT ISend(
  421. PPROTOCOL pProtocol,
  422. PSESSION pSession,
  423. PSEND pSend
  424. )
  425. {
  426. HRESULT hr=DP_OK;
  427. DWORD_PTR fAsync;
  428. BOOL fCallDirect=FALSE;
  429. fAsync=(DWORD_PTR)(pSend->pAsyncInfo);
  430. if(!fAsync && !(pSend->dwFlags & (ASEND_PROTOCOL|DPSEND_ASYNC))) {
  431. //Synchronous call, and not a protocol generated packet
  432. pSend->AsyncInfo.SendCallBack=NULL;
  433. //AsyncInfo.CallbackContext=0; //not required.
  434. pSend->AsyncInfo.hEvent=pSend->hEvent;
  435. pSend->AsyncInfo.pStatus=&pSend->Status;
  436. ResetEvent(pSend->hEvent);
  437. }
  438. // don't need to check if ref added here since the send isn't on a list yet.
  439. AddSendRef(pSend,2); // 1 for ISend, 1 for completion.
  440. DPF(9,"ISend: ==>Q\n");
  441. hr=QueueSendOnSession(pProtocol,pSession,pSend);
  442. DPF(9,"ISend: <==Q\n");
  443. if(hr==DP_OK){
  444. if(!fAsync && !(pSend->dwFlags & (ASEND_PROTOCOL|DPSEND_ASYNC))){
  445. // Synchronous call, and not internal, we need
  446. // to wait until the send has completed.
  447. if(!(pSend->dwFlags & DPSEND_GUARANTEED)){
  448. // Non-guaranteed, need to drop dplay lock, in
  449. // guaranteed case, dplay already dropped it for us.
  450. LEAVE_DPLAY();
  451. }
  452. DPF(9,"ISend: Wait==> %x\n",pSend->hEvent);
  453. Wait(pSend->hEvent);
  454. if(!(pSend->dwFlags & DPSEND_GUARANTEED)){
  455. ENTER_DPLAY();
  456. }
  457. DPF(9,"ISend: <== WAIT\n");
  458. hr=pSend->Status;
  459. } else {
  460. hr=DPERR_PENDING;
  461. }
  462. } else {
  463. DecSendRef(pProtocol, pSend); //not going to complete a send that didn't enqueue.
  464. }
  465. DecSendRef(pProtocol,pSend);
  466. return hr;
  467. }
  468. HRESULT QueueSendOnSession(
  469. PPROTOCOL pProtocol, PSESSION pSession, PSEND pSend
  470. )
  471. {
  472. BILINK *pBilink; // walks the links scanning priority
  473. BILINK *pPriQLink; // runs links in the global priority queue.
  474. PSEND pSendWalker; // pointer to send structure
  475. BOOL fFront; // if we put this at the front of the CON SendQ
  476. BOOL fSignalQ=TRUE; // whether to signal the sendQ
  477. // NOTE: locking global and connection queues concurrently,
  478. // -> this better be fast!
  479. ASSERT_SIGN(pSend, SEND_SIGN);
  480. Lock(&pProtocol->m_SendQLock);
  481. Lock(&pSession->SessionLock);
  482. Lock(&pSend->SendLock);
  483. if(pSession->eState != Open){
  484. Unlock(&pSend->SendLock);
  485. Unlock(&pSession->SessionLock);
  486. Unlock(&pProtocol->m_SendQLock);
  487. return DPERR_CONNECTIONLOST;
  488. }
  489. if(!(pSend->dwFlags & ASEND_PROTOCOL)){
  490. pProtocol->m_dwBytesPending += pSend->MessageSize;
  491. pProtocol->m_dwMessagesPending += 1;
  492. }
  493. // Put on Connection SendQ
  494. // First Check if we are highest priority.
  495. pBilink = pSession->SendQ.next;
  496. pSendWalker=CONTAINING_RECORD(pBilink, SEND, SendQ);
  497. if(pBilink == &pSession->SendQ || pSendWalker->Priority < pSend->Priority)
  498. {
  499. InsertAfter(&pSend->SendQ,&pSession->SendQ);
  500. fFront=TRUE;
  501. } else {
  502. // Scan backwards through the SendQ until we find a Send with a higher
  503. // or equal priority and insert ourselves afterwards. This is optimized
  504. // for the same pri send case.
  505. pBilink = pSession->SendQ.prev;
  506. while(TRUE /*pBilink != &pSend->SendQ*/){
  507. pSendWalker = CONTAINING_RECORD(pBilink, SEND, SendQ);
  508. ASSERT_SIGN(pSendWalker, SEND_SIGN);
  509. if(pSend->Priority <= pSendWalker->Priority){
  510. InsertAfter(&pSend->SendQ, &pSendWalker->SendQ);
  511. fFront=FALSE;
  512. break;
  513. }
  514. pBilink=pBilink->prev;
  515. }
  516. ASSERT(pBilink != &pSend->SendQ);
  517. }
  518. //
  519. // Put on Global SendQ
  520. //
  521. if(!fFront){
  522. // We queued it not at the front, therefore there are already
  523. // entries in the Global Queue and we need to be inserted
  524. // after the entry that we are behind, so start scanning the
  525. // global queue backwards from the packet ahead of us in the
  526. // Connection Queue until we find a lower priority packet
  527. // get pointer into previous packet in queue.
  528. pBilink=pSend->SendQ.prev;
  529. // get pointer to the PriorityQ record of the previous packet.
  530. pPriQLink = &(CONTAINING_RECORD(pBilink, SEND, SendQ))->m_GSendQ;
  531. while(pPriQLink != &pProtocol->m_GSendQ){
  532. pSendWalker = CONTAINING_RECORD(pPriQLink, SEND, m_GSendQ);
  533. ASSERT_SIGN(pSendWalker, SEND_SIGN);
  534. if(pSendWalker->Priority < pSend->Priority){
  535. InsertBefore(&pSend->m_GSendQ, &pSendWalker->m_GSendQ);
  536. break;
  537. }
  538. pPriQLink=pPriQLink->next;
  539. }
  540. if(pPriQLink==&pProtocol->m_GSendQ){
  541. // put at the end of the list.
  542. InsertBefore(&pSend->m_GSendQ, &pProtocol->m_GSendQ);
  543. }
  544. } else {
  545. // There was no-one in front of us on the connection. So
  546. // we look at the head of the global queue first and then scan
  547. // from the back.
  548. pBilink = pProtocol->m_GSendQ.next;
  549. pSendWalker=CONTAINING_RECORD(pBilink, SEND, m_GSendQ);
  550. if(pBilink == &pProtocol->m_GSendQ || pSend->Priority > pSendWalker->Priority)
  551. {
  552. InsertAfter(&pSend->m_GSendQ,&pProtocol->m_GSendQ);
  553. } else {
  554. // Scan backwards through the m_GSendQ until we find a Send with a higher
  555. // or equal priority and insert ourselves afterwards. This is optimized
  556. // for the same pri send case.
  557. pBilink = pProtocol->m_GSendQ.prev;
  558. while(TRUE){
  559. pSendWalker = CONTAINING_RECORD(pBilink, SEND, m_GSendQ);
  560. ASSERT_SIGN(pSendWalker, SEND_SIGN);
  561. if(pSend->Priority <= pSendWalker->Priority){
  562. InsertAfter(&pSend->m_GSendQ, &pSendWalker->m_GSendQ);
  563. break;
  564. }
  565. pBilink=pBilink->prev;
  566. }
  567. ASSERT(pBilink != &pProtocol->m_GSendQ);
  568. }
  569. }
  570. // Fixup send state if we are blocking other sends on the session.
  571. if(pSend->dwFlags & DPSEND_GUARANTEED){
  572. if(pSession->nWaitingForMessageid){
  573. DPF(8,"pSession %x, pSend %x Waiting For Id\n",pSession,pSend);
  574. pSend->SendState=WaitingForId;
  575. InterlockedIncrement(&pSession->nWaitingForMessageid);
  576. #ifdef DEBUG
  577. if(pSession->nWaitingForMessageid > 300)
  578. {
  579. DPF(0,"Session %x nWaitingForMessageid is %d, looks like trouble, continue to dump session\n",pSession, pSession->nWaitingForMessageid);
  580. //DEBUG_BREAK();
  581. //DumpSession(pSession);
  582. //DEBUG_BREAK();
  583. }
  584. #endif
  585. fSignalQ=FALSE;
  586. }
  587. } else {
  588. if(pSession->nWaitingForDGMessageid){
  589. DPF(8,"pSession %x, pSend %x Waiting For Id\n",pSession,pSend);
  590. pSend->SendState=WaitingForId;
  591. InterlockedIncrement(&pSession->nWaitingForDGMessageid);
  592. fSignalQ=FALSE;
  593. }
  594. }
  595. #ifdef DEBUG
  596. DPF(9,"SessionQ:");
  597. pBilink=pSession->SendQ.next;
  598. while(pBilink!=&pSession->SendQ){
  599. pSendWalker=CONTAINING_RECORD(pBilink, SEND, SendQ);
  600. ASSERT_SIGN(pSendWalker,SEND_SIGN);
  601. DPF(9,"Send %x pSession %x Pri %x State %d\n",pSendWalker,pSendWalker->pSession,pSendWalker->Priority,pSendWalker->SendState);
  602. pBilink=pBilink->next;
  603. }
  604. DPF(9,"GlobalQ:");
  605. pBilink=pProtocol->m_GSendQ.next;
  606. while(pBilink!=&pProtocol->m_GSendQ){
  607. pSendWalker=CONTAINING_RECORD(pBilink, SEND, m_GSendQ);
  608. ASSERT_SIGN(pSendWalker,SEND_SIGN);
  609. DPF(9,"Send %x pSession %x Pri %x State %d\n",pSendWalker,pSendWalker->pSession,pSendWalker->Priority,pSendWalker->SendState);
  610. pBilink=pBilink->next;
  611. }
  612. #endif
  613. Unlock(&pSend->SendLock);
  614. Unlock(&pSession->SessionLock);
  615. Unlock(&pProtocol->m_SendQLock);
  616. if(fSignalQ){
  617. // tell send thread to process.
  618. SetEvent(pProtocol->m_hSendEvent);
  619. }
  620. return DP_OK;
  621. }
  622. /*=============================================================================
  623. CopyDataToFrame
  624. Description:
  625. Copies data for a frame from the Send to the frame's data area.
  626. Parameters:
  627. pFrameData - pointer to data area
  628. FrameDataSize - Size of the Frame Data area
  629. pSend - send from which to get data
  630. nAhead - number of frames ahead of NR to get data for.
  631. Return Values:
  632. Number of bytes copied.
  633. Notes:
  634. Send must be locked across this call.
  635. -----------------------------------------------------------------------------*/
  636. UINT CopyDataToFrame(
  637. PUCHAR pFrameData,
  638. UINT FrameDataLen,
  639. PSEND pSend,
  640. UINT nAhead)
  641. {
  642. UINT BytesToAdvance, BytesToCopy;
  643. UINT FrameOffset=0;
  644. PUCHAR dest,src;
  645. UINT len;
  646. UINT totlen=0;
  647. UINT SendOffset;
  648. PBUFFER pSrcBuffer;
  649. UINT CurrentBufferOffset;
  650. BytesToAdvance = nAhead*FrameDataLen;
  651. SendOffset = pSend->SendOffset;
  652. pSrcBuffer = pSend->pCurrentBuffer;
  653. CurrentBufferOffset = pSend->CurrentBufferOffset;
  654. //
  655. // Run ahead to the buffer we start getting data from
  656. //
  657. while(BytesToAdvance){
  658. len = pSrcBuffer->len - CurrentBufferOffset;
  659. if(len > BytesToAdvance){
  660. CurrentBufferOffset += BytesToAdvance;
  661. SendOffset+=BytesToAdvance;
  662. BytesToAdvance=0;
  663. } else {
  664. pSrcBuffer=pSrcBuffer->pNext;
  665. CurrentBufferOffset = 0;
  666. BytesToAdvance-=len;
  667. SendOffset+=len;
  668. }
  669. }
  670. //
  671. // Copy the data for the Send into the frame
  672. //
  673. BytesToCopy = pSend->MessageSize - SendOffset;
  674. if(BytesToCopy > FrameDataLen){
  675. BytesToCopy=FrameDataLen;
  676. }
  677. while(BytesToCopy){
  678. ASSERT(pSrcBuffer);
  679. dest= pFrameData + FrameOffset;
  680. src = pSrcBuffer->pData + CurrentBufferOffset;
  681. len = pSrcBuffer->len - CurrentBufferOffset;
  682. if(len > BytesToCopy){
  683. len=BytesToCopy;
  684. CurrentBufferOffset+=len;//OPTIMIZATION?: not used after, don't need.
  685. } else {
  686. pSrcBuffer = pSrcBuffer->pNext;
  687. CurrentBufferOffset = 0;
  688. }
  689. BytesToCopy -= len;
  690. FrameOffset += len;
  691. totlen+=len;
  692. memcpy(dest,src,len);
  693. }
  694. return totlen;
  695. }
  696. // NOTE: ONLY 1 SEND THREAD ALLOWED.
  697. ULONG WINAPI SendThread(LPVOID pProt)
  698. {
  699. PPROTOCOL pProtocol=((PPROTOCOL)pProt);
  700. UINT SendRc;
  701. while(TRUE){
  702. WaitForSingleObject(pProtocol->m_hSendEvent, INFINITE);
  703. Lock(&pProtocol->m_ObjLock);
  704. if(pProtocol->m_eState==ShuttingDown){
  705. Unlock(&pProtocol->m_ObjLock);
  706. // Make sure nothing is still waiting to timeout on the queue
  707. do {
  708. SendRc=SendHandler(pProtocol);
  709. } while (SendRc!=DPERR_NOMESSAGES);
  710. Lock(&pProtocol->m_ObjLock);
  711. pProtocol->m_nSendThreads--;
  712. Unlock(&pProtocol->m_ObjLock);
  713. ExitThread(0);
  714. }
  715. Unlock(&pProtocol->m_ObjLock);
  716. do {
  717. SendRc=SendHandler(pProtocol);
  718. } while (SendRc!=DPERR_NOMESSAGES);
  719. }
  720. return TRUE;
  721. }
  722. // Called with SendLock held.
  723. VOID CancelRetryTimer(PSEND pSend)
  724. {
  725. // UINT mmError;
  726. UINT retrycount=0;
  727. UINT_PTR uRetryTimer;
  728. UINT Unique;
  729. if(pSend->uRetryTimer){
  730. DPF(9,"Canceling Timer %x\n",pSend->uRetryTimer);
  731. // Delete it from the list first so we don't deadlock trying to kill it.
  732. Lock(&g_SendTimeoutListLock);
  733. uRetryTimer=pSend->uRetryTimer;
  734. Unique=pSend->TimerUnique;
  735. pSend->uRetryTimer=0;
  736. if(!EMPTY_BILINK(&pSend->TimeoutList)){
  737. Delete(&pSend->TimeoutList);
  738. InitBilink(&pSend->TimeoutList); // avoids DecSendRef having to know state of bilink.
  739. Unlock(&g_SendTimeoutListLock);
  740. CancelMyTimer(uRetryTimer, Unique);
  741. } else {
  742. Unlock(&g_SendTimeoutListLock);
  743. }
  744. } else {
  745. DPF(9,"CancelRetryTimer:No timer to cancel.\n");
  746. }
  747. }
  748. // Workaround for Win95 mmTimers:
  749. // ==============================
  750. //
  751. // We cannot use a reference count for the timeouts as a result of the following Win95 bug:
  752. //
  753. // The cancelling of mmTimers is non-deterministic. That is, when calling cancel, you cannot
  754. // tell from the return code whether the timer ran, was cancelled or is still going to run.
  755. // Since we use the Send as the context for timeout, we cannot dereference it until we make
  756. // sure it is still valid, since code that cancelled the send and timer may have already freed
  757. // the send memory. We place the sends being timed out on a list and scan the list for the
  758. // send before we use it. If we don't find the send on the list, we ignore the timeout.
  759. //
  760. // Also note, this workaround is not very expensive. The linked list is in the order timeouts
  761. // were scheduled, so generally if the links are approximately the same speed, timeouts will
  762. // be similiar so the context being checked should be near the beginning of the list.
  763. CRITICAL_SECTION g_SendTimeoutListLock;
  764. BILINK g_BilinkSendTimeoutList;
  765. void CALLBACK RetryTimerExpiry( UINT_PTR uID, UINT uMsg, DWORD_PTR dwUser, DWORD dw1, DWORD dw2 )
  766. {
  767. PSEND pSend=(PSEND)(dwUser), pSendWalker;
  768. UINT tWaiting;
  769. BILINK *pBilink;
  770. UINT bFound=FALSE;
  771. DPF(9,"RetryTimerExpiry: %x, expecting %x, pSend %x\n",uID, pSend->uRetryTimer, pSend);
  772. tWaiting=timeGetTime();
  773. // Scan the list of waiting sends to see if this one is still waiting for a timeout.
  774. Lock(&g_SendTimeoutListLock);
  775. pBilink=g_BilinkSendTimeoutList.next;
  776. while(pBilink!=&g_BilinkSendTimeoutList){
  777. pSendWalker=CONTAINING_RECORD(pBilink, SEND, TimeoutList);
  778. pBilink=pBilink->next;
  779. if(pSendWalker == pSend){
  780. if(pSend->uRetryTimer==uID){
  781. Delete(&pSend->TimeoutList);
  782. InitBilink(&pSend->TimeoutList); // avoids DecSendRef having to know state of bilink.
  783. Unlock(&g_SendTimeoutListLock);
  784. // it is ok to call AddSendRef here without the sessionlock because
  785. // there is no way we could be adding the session reference. If
  786. // the refcount is 0, it can only mean the send is already cleaning up
  787. // and we won't try to take the session locks so there is no lock
  788. // ordering problem.
  789. bFound=AddSendRef(pSend,1); // note bFound set to Refcount on send
  790. goto skip_unlock;
  791. }
  792. }
  793. }
  794. Unlock(&g_SendTimeoutListLock);
  795. skip_unlock:
  796. if(bFound){
  797. if(pSend->tRetryScheduled - pSend->tScheduled > 500){
  798. DWORD tm=timeGetTime();
  799. if(tm - pSend->tScheduled < 100 ){
  800. DPF(9,"RETRY TIMER EXPIRY IS WAY TOO EARLY, EXPECTED AT %x ACTUALLY AT %x\n",pSend->tRetryScheduled, tm);
  801. DEBUG_BREAK();
  802. }
  803. }
  804. DPF(9,"RetryTimerExpiry: Waiting For Send Lock...\n");
  805. Lock(&pSend->SendLock);
  806. DPF(9,"RetryTimerExpiry: Got SendLock\n");
  807. if(pSend->uRetryTimer==uID){ // check again, may be cancelled.
  808. pSend->uRetryTimer=0;
  809. switch(pSend->SendState)
  810. {
  811. case Start:
  812. case Sending:
  813. ASSERT(0);
  814. case Done:
  815. break;
  816. case WaitingForAck:
  817. pSend->RetryCount++;
  818. tWaiting-=pSend->tLastACK;
  819. #ifdef DEBUG
  820. {
  821. static int retries;
  822. IN_WRITESTATS InWS;
  823. memset((PVOID)&InWS,0xFF,sizeof(IN_WRITESTATS));
  824. InWS.stat_USER1=((retries++)%20)+1;
  825. DbgWriteStats(&InWS);
  826. }
  827. #endif
  828. if(tWaiting > pSend->pSession->MaxDropTime ||
  829. (pSend->RetryCount > pSend->pSession->MaxRetry && tWaiting > pSend->pSession->MinDropTime)
  830. )
  831. {
  832. DPF(8,"Send %x Timed Out, tWaiting: %d RetryCount: %d\n",pSend,tWaiting,pSend->RetryCount);
  833. pSend->SendState=TimedOut;
  834. } else {
  835. DPF(9,"Timer expired, retrying send %x RetryCount= %d\n",pSend,pSend->RetryCount);
  836. //pSend->NACKMask|=(1<<(pSend->NS-pSend->NR))-1;
  837. pSend->NACKMask |= 1; // just retry 1 frame.
  838. ASSERT_NACKMask(pSend);
  839. pSend->SendState=ReadyToSend;
  840. }
  841. SetEvent(pSend->pSession->pProtocol->m_hSendEvent);
  842. break;
  843. case Throttled:
  844. break;
  845. case ReadyToSend:
  846. default:
  847. break;
  848. }
  849. }
  850. Unlock(&pSend->SendLock);
  851. DecSendRef(pSend->pSession->pProtocol, pSend);
  852. }
  853. }
  854. VOID StartRetryTimer(PSEND pSend)
  855. {
  856. UINT FptLatency;
  857. UINT tLatencyLong;
  858. UINT FptDev;
  859. UINT tRetry;
  860. FptLatency=max(pSend->pSession->FpLocalAverageLatency,pSend->pSession->LastLatency);
  861. FptDev=pSend->pSession->FpLocalAvgDeviation;
  862. tRetry=unFp(FptLatency+3*FptDev);//Latency +3 average deviations
  863. tLatencyLong=unFp(pSend->pSession->FpAverageLatency);
  864. // Sometimes stddev of latency gets badly skewed by the serial driver
  865. // taking a long time to complete locally, avoid setting retry time
  866. // too high by limiting to 2x the long latency average.
  867. if(tLatencyLong > 100 && tRetry > 2*max(tLatencyLong,unFp(FptLatency))){
  868. tRetry = 2*tLatencyLong;
  869. }
  870. if(pSend->RetryCount > 3){
  871. if(pSend->pSession->RemoteBytesReceived==0){
  872. // haven't spoken to remote yet, may be waiting for nametable, so back down hard.
  873. tRetry=5000;
  874. } else if (tRetry < 1000){
  875. // taking a lot of retries to get response, back down.
  876. tRetry=1000;
  877. }
  878. }
  879. if(tRetry < 50){
  880. tRetry=50;
  881. }
  882. ASSERT(tRetry);
  883. if(tRetry > 30000){
  884. DPF(0,"RETRY TIMER REQUESTING %d seconds?\n",tRetry);
  885. }
  886. if(!pSend->uRetryTimer){
  887. Lock(&g_SendTimeoutListLock);
  888. DPF(9,"Setting Retry Timer of %d ms\n", tRetry);
  889. pSend->uRetryTimer=SetMyTimer((tRetry)?(tRetry):1,(tRetry>>2)+1,RetryTimerExpiry,(ULONG_PTR) pSend,&pSend->TimerUnique);
  890. if(pSend->uRetryTimer){
  891. pSend->tScheduled = timeGetTime();
  892. pSend->tRetryScheduled = pSend->tScheduled+tRetry;
  893. InsertBefore(&pSend->TimeoutList, &g_BilinkSendTimeoutList);
  894. } else {
  895. DPF(0,"Start Retry Timer failed to schedule a timer with tRetry=%d for pSend %x\n",tRetry,pSend);
  896. DEBUG_BREAK();
  897. }
  898. DPF(9,"Started Retry Timer %x\n",pSend->uRetryTimer);
  899. Unlock(&g_SendTimeoutListLock);
  900. if(!pSend->uRetryTimer){
  901. ASSERT(0);
  902. }
  903. } else {
  904. ASSERT(0);
  905. }
  906. }
  907. // Called with all necessary locks held.
  908. VOID TimeOutSession(PSESSION pSession)
  909. {
  910. PSEND pSend;
  911. BILINK *pBilink;
  912. UINT nSignalsRequired=0;
  913. // Mark Session Timed out.
  914. pSession->eState=Closing;
  915. // Mark all sends Timed out.
  916. pBilink=pSession->SendQ.next;
  917. while(pBilink != &pSession->SendQ){
  918. pSend=CONTAINING_RECORD(pBilink, SEND, SendQ);
  919. pBilink=pBilink->next;
  920. DPF(9,"TimeOutSession: Force Timing Out Send %x, State %d\n",pSend, pSend->SendState);
  921. switch(pSend->SendState){
  922. case Start:
  923. case Throttled:
  924. case ReadyToSend:
  925. DPF(9,"TimeOutSession: Moving to TimedOut, should be safe\n");
  926. pSend->SendState=TimedOut;
  927. nSignalsRequired += 1;
  928. break;
  929. case Sending:
  930. // can we even get here? If we can this is probably not good
  931. // since the send will reset the retry count and tLastACK.
  932. DPF(9,"TimeOutSession: ALLOWING TimeOut to cancel.(could take 15 secs)\n");
  933. pSend->RetryCount=pSession->MaxRetry;
  934. pSend->tLastACK=timeGetTime()-pSession->MinDropTime;
  935. break;
  936. case WaitingForAck:
  937. DPF(9,"TimeOutSession: Canceling timer and making TimedOut\n");
  938. CancelRetryTimer(pSend);
  939. pSend->SendState = TimedOut;
  940. nSignalsRequired += 1;
  941. break;
  942. case WaitingForId:
  943. // Note, this means we can get signals for ids that aren't used.
  944. DPF(9,"TimeOutSession: Timing Out Send Waiting for ID, GetNextMessageToSend may fail, this is OK\n");
  945. pSend->SendState=TimedOut;
  946. if(pSend->dwFlags & DPSEND_GUARANTEED){
  947. InterlockedDecrement(&pSession->nWaitingForMessageid);
  948. } else {
  949. InterlockedDecrement(&pSession->nWaitingForDGMessageid);
  950. }
  951. nSignalsRequired += 1;
  952. break;
  953. case TimedOut:
  954. case Done:
  955. DPF(9,"TimeOutSession: Send already done or timed out, doesn't need our help\n");
  956. break;
  957. default:
  958. DPF(0,"TimeOutSession, pSession %x found Send %x in Wierd State %d\n",pSession,pSend,pSend->SendState);
  959. ASSERT(0);
  960. break;
  961. } /* switch */
  962. } /* while */
  963. // Create enough signals to process timed out sends.
  964. DPF(9,"Signalling SendQ %d items to process\n",nSignalsRequired);
  965. SetEvent(pSession->pProtocol->m_hSendEvent);
  966. }
  967. UINT WrapSend(PPROTOCOL pProtocol, PSEND pSend, PBUFFER pBuffer)
  968. {
  969. PUCHAR pMessage,pMessageStart;
  970. DWORD dwWrapSize=0;
  971. DWORD dwIdTo=0;
  972. DWORD dwIdFrom=0;
  973. pMessageStart = &pBuffer->pData[pProtocol->m_dwSPHeaderSize];
  974. pMessage = pMessageStart;
  975. dwIdFrom = pSend->wIdFrom;
  976. dwIdTo = pSend->wIdTo;
  977. if(dwIdFrom==0x70){ // avoid looking like a system message 'play'
  978. dwIdFrom=0xFFFF;
  979. }
  980. if(dwIdFrom){
  981. while(dwIdFrom){
  982. *pMessage=(UCHAR)(dwIdFrom & 0x7F);
  983. dwIdFrom >>= 7;
  984. if(dwIdFrom){
  985. *pMessage|=0x80;
  986. }
  987. pMessage++;
  988. }
  989. } else {
  990. *(pMessage++)=0;
  991. }
  992. if(dwIdTo){
  993. while(dwIdTo){
  994. *pMessage=(UCHAR)(dwIdTo & 0x7F);
  995. dwIdTo >>= 7;
  996. if(dwIdTo){
  997. *pMessage|=0x80;
  998. }
  999. pMessage++;
  1000. }
  1001. } else {
  1002. *(pMessage++)=0;
  1003. }
  1004. #if 0 // a-josbor: for debugging only. I left it in in case we ever needed it again
  1005. ExtractProtocolIds(pMessageStart, &dwIdFrom, &dwIdTo);
  1006. ASSERT(dwIdFrom == pSend->wIdFrom);
  1007. ASSERT(dwIdTo == pSend->wIdTo);
  1008. #endif
  1009. return (UINT)(pMessage-pMessageStart);
  1010. }
  1011. #define DROP 0
  1012. #if DROP
  1013. // 1 for send, 0 for drop.
  1014. char droparray[]= {
  1015. 1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,0};
  1016. UINT dropindex=0;
  1017. #endif
  1018. VOID CALLBACK UnThrottle(UINT_PTR uID, UINT uMsg, DWORD_PTR dwUser, DWORD dw1, DWORD dw2)
  1019. {
  1020. PSESSION pSession=(PSESSION)dwUser;
  1021. UINT tMissedBy; // how long we missed the throttle by.
  1022. DWORD tm;
  1023. Lock(&pSession->SessionLock);
  1024. tm=timeGetTime();
  1025. tMissedBy = tm-pSession->tNextSend;
  1026. if( (int)tMissedBy > 0){
  1027. pSession->FpAvgUnThrottleTime -= pSession->FpAvgUnThrottleTime >> 4;
  1028. pSession->FpAvgUnThrottleTime += (Fp(tMissedBy) >> 4);
  1029. DPF(9,"Missed by: %d ms Avg Unthrottle Miss %d.%d ms\n", tMissedBy, pSession->FpAvgUnThrottleTime >> 8, (((pSession->FpAvgUnThrottleTime&0xFF)*100)/256) );
  1030. }
  1031. pSession->uUnThrottle=0;
  1032. pSession->dwFlags |= SESSION_UNTHROTTLED;
  1033. pSession->pProtocol->m_bRescanQueue=TRUE; // tell send routine to restart scan.
  1034. DPF(9,"Unthrottling Session %x at %d\n",pSession, timeGetTime());
  1035. Unlock(&pSession->SessionLock);
  1036. SetEvent(pSession->pProtocol->m_hSendEvent);
  1037. DecSessionRef(pSession);
  1038. }
  1039. VOID Throttle( PSESSION pSession, DWORD tm )
  1040. {
  1041. DWORD tmDelta;
  1042. Lock(&pSession->SessionLock);
  1043. pSession->bhitThrottle=TRUE;
  1044. pSession->dwFlags |= SESSION_THROTTLED;
  1045. tmDelta = pSession->tNextSend - tm;
  1046. if((INT)tmDelta < 0){
  1047. tmDelta=1;
  1048. }
  1049. DPF(9,"Throttling pSession %x for %d ms (until %d)\n",pSession, tmDelta,pSession->tNextSend);
  1050. InterlockedIncrement(&pSession->RefCount);
  1051. pSession->uUnThrottle = SetMyTimer(tmDelta, (tmDelta>>2)?(tmDelta>>2):1, UnThrottle, (DWORD_PTR)pSession, &pSession->UnThrottleUnique);
  1052. if(!pSession->uUnThrottle){
  1053. DPF(0,"UH OH failed to schedule unthrottle event\n");
  1054. DEBUG_BREAK();
  1055. }
  1056. Unlock(&pSession->SessionLock);
  1057. #ifdef DEBUG
  1058. {
  1059. static int throttlecounter;
  1060. IN_WRITESTATS InWS;
  1061. memset((PVOID)&InWS,0xFF,sizeof(IN_WRITESTATS));
  1062. InWS.stat_USER4=((throttlecounter++)%20)+1;
  1063. DbgWriteStats(&InWS);
  1064. }
  1065. #endif
  1066. }
  1067. // Given the current time, the bandwidth we are throttling to and the length of the packet we are sending,
  1068. // calculate the next time we are allowed to send. Also keep a residue from this calculation so that
  1069. // we don't wind up using excessive bandwidth due to rounding, the residue from the last calculation is
  1070. // used in this calculation.
  1071. // Absolute flag means set the next send time relative to tm regardless
  1072. VOID UpdateSendTime(PSESSION pSession, DWORD Len, DWORD tm, BOOL fAbsolute)
  1073. {
  1074. #define SendRate pSession->SendRateThrottle
  1075. #define Residue pSession->tNextSendResidue
  1076. #define tNext pSession->tNextSend
  1077. DWORD tFrame; // amount of time this frame will take on the wire.
  1078. tFrame = (Len+Residue)*1000 / SendRate; // rate is bps, but want to calc bpms, so (Len+Residue)*1000
  1079. Residue = (Len+Residue) - (tFrame * SendRate)/1000 ;
  1080. ASSERT(!(Residue&0x80000000)); // residue better be +ve
  1081. if(fAbsolute || (INT)(tNext - tm) < 0){
  1082. // tNext is less than tm, so calc based on tm.
  1083. tNext = tm+tFrame;
  1084. } else {
  1085. // tNext is greater than tm, so add more wait.
  1086. tNext = tNext+tFrame;
  1087. }
  1088. DPF(8,"UpdateSendTime time %d, tFrame %d, Residue %d, tNext %d",tm,tFrame,Residue,tNext);
  1089. #undef SendRate
  1090. #undef Residue
  1091. #undef tNext
  1092. }
  1093. //CHAR Drop[]={0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,1,0,0};
  1094. //DWORD DropSize = sizeof(Drop);
  1095. //DWORD iDrop=0;
  1096. // AO - added contraint, 1 send thread per session. Since this is not enforced by GetNextMessageToSend
  1097. // 5-21-98 we are effectively restricted to 1 send thread for the protocol. We can fix this by adding
  1098. // a sending state on the session and having GetNextMessageToSend skip sending sessions.
  1099. HRESULT ReliableSend(PPROTOCOL pProtocol, PSEND pSend)
  1100. {
  1101. #define pBigFrame ((pPacket2)(pFrame))
  1102. HRESULT hr;
  1103. PBUFFER pBuffer;
  1104. pPacket1 pFrame;
  1105. PUCHAR pFrameData;
  1106. UINT FrameDataLen;
  1107. UINT FrameTotalLen;
  1108. UINT MaxFrameLen;
  1109. UINT FrameHeaderLen;
  1110. UINT nFramesOutstanding;
  1111. UINT nFramesToSend;
  1112. UINT msk;
  1113. UINT shift;
  1114. UINT WrapSize;
  1115. UINT DPWrapSize; // DirectPlay wrapping only. ([[DPLAY 0xFF]|],From,To)
  1116. DWORD tm=0; // The time, 0 if we haven't retrieved it yet.
  1117. DWORD tmExit=0;
  1118. BOOL bExitEarly=FALSE;
  1119. DPSP_SENDDATA SendData;
  1120. INT iTemp;
  1121. //
  1122. // Sending algorithm is designed to handle NACKs only (there
  1123. // is no special case for sending data the first time). So
  1124. // We send by making it look like the frames we want to send
  1125. // have been NACKed. Every frame we send, we clear the NACK
  1126. // bit for. If an actual NACK comes in, the bit is set.
  1127. // When an ACK comes in, we shift the NACK and ACK masks
  1128. // nACK-NR and if applicable, set new NACK bits.
  1129. //
  1130. Lock(&pSend->SendLock);
  1131. if(pSend->SendState == Done){
  1132. goto unlock_exit;
  1133. }
  1134. nFramesOutstanding=(pSend->NS-pSend->NR);
  1135. if( nFramesOutstanding < pSend->WindowSize){
  1136. // Set NACK bits up to WindowSize (unless over nFrames);
  1137. nFramesToSend=pSend->WindowSize-nFramesOutstanding;
  1138. if(nFramesToSend > pSend->nFrames-pSend->NS){
  1139. nFramesToSend=pSend->nFrames-pSend->NS;
  1140. }
  1141. pSend->NACKMask |= ((1<<nFramesToSend)-1)<<nFramesOutstanding;
  1142. pSend->OpenWindow = nFramesOutstanding + nFramesToSend;
  1143. DPF(9,"Send: pSend->NACKMask %x, OpenWindow %d\n",pSend->NACKMask, pSend->OpenWindow);
  1144. }
  1145. tmExit=timeGetTime()+1000; // always blow out of here in 1 second max.
  1146. Reload:
  1147. msk=1;
  1148. shift=0;
  1149. MaxFrameLen=pSend->FrameSize;
  1150. while(pSend->NACKMask){
  1151. ASSERT_NACKMask(pSend);
  1152. tm=timeGetTime(); // Getting the time is relatively expensive, so we do it once here and pass it around.
  1153. if(((INT)tm - (INT)tmExit) > 0){
  1154. DPF(0,"Breaking Out of Send Loop due to expiry of timer\n");
  1155. bExitEarly=TRUE;
  1156. break;
  1157. }
  1158. #if 1
  1159. if((tm+unFp(pSend->pSession->FpAvgUnThrottleTime)-pSend->pSession->tNextSend) & 0x80000000){
  1160. // we're still too early to do the next send, so throttled this session.
  1161. goto throttle_exit;
  1162. }
  1163. #endif
  1164. if(pSend->NACKMask & msk){
  1165. pBuffer=GetFrameBuffer(MaxFrameLen+pProtocol->m_dwSPHeaderSize+MAX_SEND_HEADER);
  1166. if(!pBuffer){
  1167. pSend->SendState=ReadyToSend;
  1168. SetEvent(pSend->pSession->pProtocol->m_hSendEvent); // keep the queue rolling.
  1169. hr=DPERR_PENDING;
  1170. goto exit;
  1171. }
  1172. WrapSize=pProtocol->m_dwSPHeaderSize; // leave space for SP header.
  1173. DPWrapSize=WrapSend(pProtocol, pSend, pBuffer); // fill in out address wrapping
  1174. WrapSize+=DPWrapSize;
  1175. pFrame=(pPacket1)&pBuffer->pData[WrapSize]; // protocol header after wrapping
  1176. if(pSend->fSendSmall){
  1177. pFrameData=&pFrame->data[0];
  1178. FrameHeaderLen=(UINT)(pFrameData-(PUCHAR)pFrame);
  1179. } else {
  1180. pFrameData=&pBigFrame->data[0];
  1181. FrameHeaderLen=(UINT)(pFrameData-(PUCHAR)pFrame);
  1182. }
  1183. // For calculating nFrames, we assumed MAX_SEND_HEADER, subtract out the unused portion
  1184. // so we don't put to much data in the frame and mess up the accounting.
  1185. pBuffer->len-=(MAX_SEND_HEADER-(FrameHeaderLen+DPWrapSize));
  1186. FrameHeaderLen += WrapSize; // now include wrapping and SPheader space.
  1187. FrameDataLen=CopyDataToFrame(pFrameData, pBuffer->len-FrameHeaderLen, pSend, shift);
  1188. if(!pSend->FrameDataLen){
  1189. pSend->FrameDataLen=FrameDataLen;
  1190. }
  1191. FrameTotalLen=FrameDataLen+FrameHeaderLen;
  1192. pSend->BytesThisSend=FrameTotalLen-WrapSize; //only counting payload
  1193. // Do that protocol thing
  1194. BuildHeader(pSend,pFrame,shift,tm);
  1195. // we know we don't have to check here since we have a reference
  1196. // from finding the send to work on ON the send queue. So it
  1197. // can't go away til we return from this function.
  1198. iTemp=AddSendRef(pSend,1);
  1199. ASSERT(iTemp);
  1200. if(pSend->NR+shift >= pSend->NS){
  1201. pSend->NS = pSend->NR+shift+1;
  1202. }
  1203. pSend->NACKMask &= ~msk;
  1204. DPF(9,"S %2x %2x %2x\n",pBuffer->pData[0], pBuffer->pData[1], pBuffer->pData[2]);
  1205. // Update the next time we are allowed to send.
  1206. UpdateSendTime(pSend->pSession, pSend->BytesThisSend, tm, FALSE);
  1207. Unlock(&pSend->SendLock);
  1208. ASSERT(!(FrameTotalLen &0xFFFF0000));
  1209. // Send this puppy...
  1210. SendData.dwFlags = pSend->dwFlags & ~DPSEND_GUARANTEED;
  1211. SendData.idPlayerTo = pSend->idTo;
  1212. SendData.idPlayerFrom = pSend->idFrom;
  1213. SendData.lpMessage = pBuffer->pData;
  1214. SendData.dwMessageSize = FrameTotalLen;
  1215. SendData.bSystemMessage = 0;
  1216. SendData.lpISP = pProtocol->m_lpISP;
  1217. ENTER_DPLAY();
  1218. Lock(&pProtocol->m_SPLock);
  1219. // if(!(Drop[(iDrop++)%DropSize])){//DEBUG ONLY!
  1220. hr=CALLSP(pProtocol->m_lpDPlay->pcbSPCallbacks->Send,&SendData);
  1221. // }
  1222. Unlock(&pProtocol->m_SPLock);
  1223. LEAVE_DPLAY();
  1224. #ifdef DEBUG
  1225. if(hr != DPERR_PENDING && hr != DP_OK){
  1226. DPF(0,"Wierd error %x from unreliable send in SP\n",hr);
  1227. //DEBUG_BREAK();
  1228. }
  1229. #endif
  1230. if(hr!=DPERR_PENDING){
  1231. FreeFrameBuffer(pBuffer);
  1232. if(!DecSendRef(pProtocol, pSend)){
  1233. ASSERT(0);
  1234. hr=DPERR_PENDING;
  1235. goto exit;
  1236. }
  1237. if(hr != DP_OK){
  1238. Lock(&pSend->SendLock);
  1239. pSend->SendState = TimedOut; // kill the connection.
  1240. SetEvent(pSend->pSession->pProtocol->m_hSendEvent); // keep the queue rolling.
  1241. break;
  1242. }
  1243. }
  1244. Lock(&pSend->SendLock);
  1245. } /* endif (pSend->NACKMask & msk) */
  1246. if(pSend->fUpdate){
  1247. pSend->fUpdate=FALSE;
  1248. goto Reload;
  1249. }
  1250. // Check if we are past windowsize, if so roll back the mask
  1251. // Also if there are earlier bits to ACK.
  1252. if((msk<<=1UL) >= (1UL<<pSend->WindowSize)){
  1253. msk=1;
  1254. shift=0;
  1255. } else {
  1256. shift++;
  1257. }
  1258. } /* end while (pSend->NACKMask) */
  1259. if(pSend->SendState != Done && pSend->SendState != TimedOut){
  1260. if(bExitEarly){
  1261. pSend->SendState=ReadyToSend;
  1262. SetEvent(pSend->pSession->pProtocol->m_hSendEvent); // keep the queue rolling.
  1263. } else {
  1264. pSend->SendState=WaitingForAck;
  1265. StartRetryTimer(pSend);
  1266. }
  1267. } else {
  1268. // We have timed out the send due to killing the session, or
  1269. // we got the final ACK, either way, don't touch the SendState
  1270. }
  1271. unlock_exit:
  1272. Unlock(&pSend->SendLock);
  1273. hr=DPERR_PENDING; // Reliable sends are completed by the ACK.
  1274. exit:
  1275. return hr;
  1276. throttle_exit:
  1277. hr=DPERR_PENDING;
  1278. pSend->SendState=Throttled;
  1279. Unlock(&pSend->SendLock);
  1280. Throttle(pSend->pSession, tm);
  1281. return hr;
  1282. #undef pBigFrame
  1283. }
  1284. // TRUE, didn't reach end, FALSE, no more to send.
  1285. BOOL AdvanceSend(PSEND pSend, UINT AckedLen)
  1286. {
  1287. BOOL rc=TRUE;
  1288. // quick short circuit for small messages.
  1289. if(AckedLen+pSend->SendOffset==pSend->MessageSize){
  1290. rc=FALSE;
  1291. goto exit;
  1292. }
  1293. if(pSend->SendOffset+AckedLen > pSend->MessageSize){
  1294. AckedLen=pSend->MessageSize-pSend->SendOffset;
  1295. }
  1296. pSend->SendOffset+=AckedLen;
  1297. while(AckedLen){
  1298. if(pSend->pCurrentBuffer->len-pSend->CurrentBufferOffset >= AckedLen){
  1299. pSend->CurrentBufferOffset+=AckedLen;
  1300. rc=TRUE;
  1301. break;
  1302. } else {
  1303. AckedLen -= (pSend->pCurrentBuffer->len-pSend->CurrentBufferOffset);
  1304. pSend->pCurrentBuffer=pSend->pCurrentBuffer->pNext;
  1305. pSend->CurrentBufferOffset=0;
  1306. rc=FALSE;
  1307. }
  1308. }
  1309. exit:
  1310. return rc;
  1311. }
  1312. HRESULT DGSend(PPROTOCOL pProtocol, PSEND pSend)
  1313. {
  1314. #define pBigFrame ((pPacket2)(pFrame))
  1315. PBUFFER pBuffer;
  1316. pPacket1 pFrame;
  1317. PUCHAR pFrameData;
  1318. UINT FrameDataLen;
  1319. UINT FrameHeaderLen;
  1320. UINT FrameTotalLen;
  1321. UINT MaxFrameLen;
  1322. UINT nFramesToSend;
  1323. UINT WrapSize;
  1324. UINT DPWrapSize; // DirectPlay wrapping only. ([[DPLAY 0xFF]|],From,To)
  1325. DPSP_SENDDATA SendData;
  1326. DWORD tm;
  1327. HRESULT hr;
  1328. Lock(&pSend->SendLock);
  1329. nFramesToSend=pSend->nFrames-pSend->NR;
  1330. MaxFrameLen=pSend->FrameSize;
  1331. while(nFramesToSend){
  1332. tm=timeGetTime(); // Getting the time is relatively expensive, so we do it once here and pass it around.
  1333. #if 1
  1334. if((tm+unFp(pSend->pSession->FpAvgUnThrottleTime)-pSend->pSession->tNextSend) & 0x80000000){
  1335. // we're still too early to do the next send, so throttled this session.
  1336. goto throttle_exit;
  1337. }
  1338. #endif
  1339. pBuffer=GetFrameBuffer(MaxFrameLen+pProtocol->m_dwSPHeaderSize+MAX_SEND_HEADER);
  1340. if(!pBuffer){
  1341. hr=DPERR_PENDING;
  1342. goto exit;
  1343. }
  1344. WrapSize=pProtocol->m_dwSPHeaderSize; // leave space for SP header.
  1345. DPWrapSize=WrapSend(pProtocol, pSend, pBuffer); // fill in out address wrapping
  1346. WrapSize+=DPWrapSize;
  1347. pFrame=(pPacket1)&pBuffer->pData[WrapSize]; // protocol header after wrapping
  1348. if(pSend->fSendSmall){
  1349. pFrameData=&pFrame->data[0];
  1350. FrameHeaderLen=(UINT)(pFrameData-(PUCHAR)pFrame);
  1351. } else {
  1352. pFrameData=&pBigFrame->data[0];
  1353. FrameHeaderLen=(UINT)(pFrameData-(PUCHAR)pFrame);
  1354. }
  1355. // For calculating nFrames, we assumed MAX_SEND_HEADER, subtract out the unused portion
  1356. // so we don't put to much data in the frame and mess up the accounting.
  1357. pBuffer->len-=(MAX_SEND_HEADER-(FrameHeaderLen+DPWrapSize));
  1358. FrameHeaderLen += WrapSize; // now include wrapping and SPheader space.
  1359. FrameDataLen=CopyDataToFrame(pFrameData, pBuffer->len-FrameHeaderLen, pSend, 0);
  1360. FrameTotalLen=FrameDataLen+FrameHeaderLen;
  1361. pSend->BytesThisSend=FrameTotalLen-WrapSize; //only counting payload
  1362. // Do that protocol thing
  1363. BuildHeader(pSend,pFrame,0,tm);
  1364. //AddSendRef(pSend,1); //already locked, so just add one.
  1365. ASSERT(pSend->RefCount); //verifies ++ below is ok.
  1366. InterlockedIncrement((PLONG)&pSend->RefCount);
  1367. UpdateSendTime(pSend->pSession,pSend->BytesThisSend,tm,FALSE);
  1368. Unlock(&pSend->SendLock);
  1369. // Send this puppy...
  1370. ASSERT(!(pSend->dwFlags & DPSEND_GUARANTEED));
  1371. SendData.dwFlags = pSend->dwFlags;
  1372. SendData.idPlayerTo = pSend->idTo;
  1373. SendData.idPlayerFrom = pSend->idFrom;
  1374. SendData.lpMessage = pBuffer->pData;
  1375. SendData.dwMessageSize = FrameTotalLen;
  1376. SendData.bSystemMessage = 0;
  1377. SendData.lpISP = pProtocol->m_lpISP;
  1378. ENTER_DPLAY();
  1379. Lock(&pProtocol->m_SPLock);
  1380. hr=CALLSP(pProtocol->m_lpDPlay->pcbSPCallbacks->Send,&SendData);
  1381. Unlock(&pProtocol->m_SPLock);
  1382. LEAVE_DPLAY();
  1383. #ifdef DEBUG
  1384. if(hr != DPERR_PENDING && hr != DP_OK){
  1385. DPF(0,"Wierd error %x from unreliable send in SP\n",hr);
  1386. //DEBUG_BREAK();
  1387. }
  1388. #endif
  1389. if(hr!=DPERR_PENDING){
  1390. if(!DecSendRef(pProtocol,pSend)){
  1391. // No async send support in Dplay at lower edge,
  1392. // so we should never get here!
  1393. ASSERT(0);
  1394. }
  1395. FreeFrameBuffer(pBuffer);
  1396. }
  1397. Lock(&pSend->SendLock);
  1398. nFramesToSend--;
  1399. AdvanceSend(pSend,FrameDataLen);
  1400. pSend->NR++;
  1401. pSend->NS++;
  1402. }
  1403. Unlock(&pSend->SendLock);
  1404. DGCompleteSend(pSend);
  1405. hr=DPERR_PENDING; // everything was sent, but already completed by DGCompleteSend
  1406. exit:
  1407. return hr;
  1408. throttle_exit:
  1409. hr=DPERR_PENDING;
  1410. pSend->SendState=Throttled;
  1411. Unlock(&pSend->SendLock);
  1412. Throttle(pSend->pSession, tm);
  1413. return hr;
  1414. #undef pBigFrame
  1415. }
  1416. BOOL DGCompleteSend(PSEND pSend)
  1417. {
  1418. UINT bit;
  1419. UINT MsgMask;
  1420. PSESSION pSession;
  1421. pSend->SendState=Done;
  1422. pSession=pSend->pSession;
  1423. Lock(&pSession->SessionLock);
  1424. if(!pSend->fSendSmall){
  1425. MsgMask = 0xFFFF;
  1426. } else {
  1427. MsgMask =0xFF;
  1428. }
  1429. DPF(9,"CompleteSend\n");
  1430. //
  1431. // Update Session information for completion of this send.
  1432. //
  1433. bit = ((pSend->messageid-pSession->DGFirstMsg) & MsgMask)-1;
  1434. // clear the message mask bit for the completed send.
  1435. if(pSession->DGOutMsgMask & 1<<bit){
  1436. pSession->DGOutMsgMask &= ~(1<<bit);
  1437. } else {
  1438. return FALSE;
  1439. }
  1440. // slide the first message count forward for each low
  1441. // bit clear in Message mask.
  1442. while(pSession->DGLastMsg-pSession->DGFirstMsg){
  1443. if(!(pSession->DGOutMsgMask & 1)){
  1444. pSession->DGFirstMsg=(pSession->DGFirstMsg+1)&MsgMask;
  1445. pSession->DGOutMsgMask >>= 1;
  1446. if(pSession->nWaitingForDGMessageid){
  1447. pSession->pProtocol->m_bRescanQueue=TRUE;
  1448. SetEvent(pSession->pProtocol->m_hSendEvent);
  1449. }
  1450. } else {
  1451. break;
  1452. }
  1453. }
  1454. //
  1455. // Return the Send to the pool and complete the waiting client.
  1456. //
  1457. Unlock(&pSession->SessionLock);
  1458. ASSERT(pSend->RefCount);
  1459. // Send completed, do completion
  1460. DoSendCompletion(pSend, DP_OK);
  1461. DecSendRef(pSession->pProtocol, pSend); // for completion.
  1462. return TRUE;
  1463. }
  1464. // Send a fully formatted System packet (ACK, nACK, etc..)
  1465. HRESULT SystemSend(PPROTOCOL pProtocol, PSEND pSend)
  1466. {
  1467. PBUFFER pBuffer;
  1468. DPSP_SENDDATA SendData;
  1469. HRESULT hr;
  1470. PSESSION pSession;
  1471. pBuffer=pSend->pMessage;
  1472. DPF(9,"System Send pBuffer %x pData %x len %d, idTo %x \n",pBuffer, pBuffer->pData, pBuffer->len, pSend->idTo);
  1473. pSession=GetSysSessionByIndex(pProtocol, pSend->wIdTo); // adds a ref on session.
  1474. // |
  1475. if(!pSession){ // |
  1476. hr=DPERR_INVALIDPLAYER; // |
  1477. goto exit; // |
  1478. } // |
  1479. // |
  1480. SendData.idPlayerTo = pSession->dpid; // |
  1481. DecSessionRef(pSession); // <----+ frees ref here.
  1482. // Send this puppy...
  1483. SendData.dwFlags = 0;
  1484. SendData.idPlayerFrom = pSend->idFrom;
  1485. SendData.lpMessage = pBuffer->pData;
  1486. SendData.dwMessageSize = pBuffer->len;
  1487. SendData.bSystemMessage = 0;
  1488. SendData.lpISP = pProtocol->m_lpISP;
  1489. ENTER_DPLAY();
  1490. Lock(&pProtocol->m_SPLock);
  1491. hr=CALLSP(pProtocol->m_lpDPlay->pcbSPCallbacks->Send,&SendData);
  1492. Unlock(&pProtocol->m_SPLock);
  1493. LEAVE_DPLAY();
  1494. #ifdef DEBUG
  1495. if(hr!=DP_OK){
  1496. DPF(0,"UNSUCCESSFUL SEND in SYSTEM SEND, hr=%x\n",hr);
  1497. }
  1498. #endif
  1499. exit:
  1500. return hr;
  1501. #undef pBigFrame
  1502. }
  1503. VOID DoSendCompletion(PSEND pSend, INT Status)
  1504. {
  1505. #ifdef DEBUG
  1506. if(Status != DP_OK){
  1507. DPF(8,"Send Error pSend %x, Status %x\n",pSend,Status);
  1508. }
  1509. #endif
  1510. if(!(pSend->dwFlags & ASEND_PROTOCOL)){
  1511. EnterCriticalSection(&pSend->pProtocol->m_SendQLock);
  1512. pSend->pProtocol->m_dwBytesPending -= pSend->MessageSize;
  1513. pSend->pProtocol->m_dwMessagesPending -= 1;
  1514. DPF(8,"SC: Messages pending %d\n",pSend->pProtocol->m_dwMessagesPending);
  1515. LeaveCriticalSection(&pSend->pProtocol->m_SendQLock);
  1516. }
  1517. if(pSend->pAsyncInfo){
  1518. // ASYNC_SEND
  1519. if(pSend->AsyncInfo.pStatus){
  1520. (*pSend->AsyncInfo.pStatus)=Status;
  1521. }
  1522. if(pSend->AsyncInfo.SendCallBack){
  1523. (*pSend->AsyncInfo.SendCallBack)(pSend->AsyncInfo.CallBackContext,Status);
  1524. }
  1525. if(pSend->AsyncInfo.hEvent){
  1526. DPF(9,"ASYNC_SENDCOMPLETE: Signalling Event %x\n",pSend->AsyncInfo.hEvent);
  1527. SetEvent(pSend->AsyncInfo.hEvent);
  1528. }
  1529. } else if (!(pSend->dwFlags&(ASEND_PROTOCOL|DPSEND_ASYNC))){
  1530. // SYNC_SEND
  1531. if(pSend->AsyncInfo.pStatus){
  1532. (*pSend->AsyncInfo.pStatus)=Status;
  1533. }
  1534. if(pSend->AsyncInfo.hEvent){
  1535. DPF(9,"SYNC_SENDCOMPLETE: Signalling Event %x\n",pSend->AsyncInfo.hEvent);
  1536. SetEvent(pSend->AsyncInfo.hEvent);
  1537. }
  1538. } else {
  1539. // PROTOCOL INTERNAL ASYNC SEND
  1540. if(pSend->AsyncInfo.pStatus){
  1541. (*pSend->AsyncInfo.pStatus)=Status;
  1542. }
  1543. if(pSend->AsyncInfo.SendCallBack){
  1544. (*pSend->AsyncInfo.SendCallBack)(pSend->AsyncInfo.CallBackContext,Status);
  1545. }
  1546. }
  1547. }
  1548. /*=============================================================================
  1549. SendHandler - Send the next message that needs to send packets.
  1550. Description:
  1551. Finds a message on the send queue that needs to send packets and deserves
  1552. to use some bandwidth, either because it is highest priority or because
  1553. all the higher priority messages are waiting for ACKs. Then sends as many
  1554. packets as possible before hitting the throttling limit.
  1555. Returns when the throttle limit is hit, or all packets for this send have
  1556. been sent.
  1557. Parameters:
  1558. pARPD pObj - pointer to the ARPD object to send packets on.
  1559. Return Values:
  1560. -----------------------------------------------------------------------------*/
  1561. HRESULT SendHandler(PPROTOCOL pProtocol)
  1562. {
  1563. PSEND pSend;
  1564. HRESULT hr=DP_OK;
  1565. PSESSION pSession;
  1566. // adds ref to send and session if found
  1567. pSend=GetNextMessageToSend(pProtocol);
  1568. if(!pSend){
  1569. goto nothing_to_send;
  1570. }
  1571. //DPF(4,"==>Send\n");
  1572. switch(pSend->pSession->eState){
  1573. case Open:
  1574. switch(pSend->SendState){
  1575. case Done: // Send handlers must deal with Done.
  1576. DPF(9,"Calling SendHandler for Done Send--should just return\n");
  1577. case Sending:
  1578. //
  1579. // Send as many frames as we can given the window size.
  1580. //
  1581. // Send handlers dump packets on the wire, if they expect
  1582. // to be completed later, they return PENDING in which case
  1583. // their completion handlers must do the cleanup. If they
  1584. // return OK, it means everything for this send is done and
  1585. // we do the cleanup.
  1586. if(pSend->dwFlags & ASEND_PROTOCOL){
  1587. hr=SystemSend(pProtocol, pSend);
  1588. } else if(pSend->dwFlags & DPSEND_GUARANTEE){
  1589. hr=ReliableSend(pProtocol, pSend);
  1590. } else {
  1591. hr=DGSend(pProtocol, pSend);
  1592. }
  1593. break;
  1594. case TimedOut:
  1595. hr=DPERR_CONNECTIONLOST;
  1596. pSend->SendState=Done;
  1597. break;
  1598. case Cancelled:
  1599. hr=DPERR_USERCANCEL;
  1600. pSend->SendState=Done;
  1601. break;
  1602. case UserTimeOut:
  1603. hr=DPERR_TIMEOUT;
  1604. pSend->SendState=Done;
  1605. break;
  1606. default:
  1607. DPF(0,"SendHandler: Invalid pSend %x SendState: %d\n",pSend,pSend->SendState);
  1608. ASSERT(0);
  1609. }
  1610. break;
  1611. case Closing:
  1612. switch(pSend->SendState){
  1613. case TimedOut:
  1614. DPF(8,"Returning CONNECTIONLOST on timed out message %x\n",DPERR_CONNECTIONLOST);
  1615. hr=DPERR_CONNECTIONLOST;
  1616. break;
  1617. default:
  1618. DPF(8,"Send for session in Closing State, returning %x\n",DPERR_INVALIDPLAYER);
  1619. hr=DPERR_INVALIDPLAYER;
  1620. break;
  1621. }
  1622. pSend->SendState=Done;
  1623. break;
  1624. case Closed:
  1625. DPF(8,"Send for session in Closed State, returning %x",DPERR_INVALIDPLAYER);
  1626. hr=DPERR_INVALIDPLAYER;
  1627. pSend->SendState=Done;
  1628. break;
  1629. }
  1630. //DPF(4,"<==Send Leaving,rc=%x\n",hr);
  1631. if( hr != DPERR_PENDING ){
  1632. Lock(&pSend->SendLock);
  1633. ASSERT(pSend->RefCount);
  1634. //
  1635. // Send completed, do completion
  1636. //
  1637. DoSendCompletion(pSend, hr);
  1638. Unlock(&pSend->SendLock);
  1639. DecSendRef(pProtocol, pSend); // for completion
  1640. }
  1641. pSession=pSend->pSession;
  1642. DecSendRef(pProtocol,pSend); // Balances GetNextMessageToSend
  1643. DecSessionRef(pSession); // Balances GetNextMessageToSend
  1644. return hr;
  1645. nothing_to_send:
  1646. return DPERR_NOMESSAGES;
  1647. }
  1648. /*=============================================================================
  1649. Build Header - fill in the frame header for a packet to be sent.
  1650. Description:
  1651. Enough space is left in the frame to go on the wire (pFrame) to fit the
  1652. message header. One of two types of headers is built, depending on the
  1653. value of the fSendSmall field of the packet. If fSendSmall is TRUE, a compact
  1654. header is built, this lowers overhead on slow media. If fSendSmall is FALSE
  1655. a larger header that can support larger windows is built. The header
  1656. is filled into the front of pFrame.
  1657. Parameters:
  1658. pARPD pObj - pointer to the ARPD object to send packets on.
  1659. Return Values:
  1660. -----------------------------------------------------------------------------*/
  1661. VOID BuildHeader(PSEND pSend,pPacket1 pFrame, UINT shift, DWORD tm)
  1662. {
  1663. #define pBigFrame ((pPacket2)(pFrame))
  1664. PSENDSTAT pStat=NULL;
  1665. UINT seq;
  1666. UINT bitEOM,bitSTA,bitSAK=0;
  1667. DWORD BytesSent;
  1668. DWORD RemoteBytesReceived;
  1669. DWORD tRemoteBytesReceived;
  1670. DWORD bResetBias=FALSE;
  1671. // on first frame of a message, set the start bit (STA).
  1672. if(pSend->NR+shift==0){
  1673. bitSTA=STA;
  1674. } else {
  1675. bitSTA=0;
  1676. }
  1677. // on the last frome of a message set the end of message bit (EOM)
  1678. if(pSend->nFrames==pSend->NR+shift+1){
  1679. bitEOM=EOM;
  1680. } else {
  1681. bitEOM=0;
  1682. }
  1683. // if we haven't set EOM and we haven't requested an ACK in 1/4 the
  1684. // round trip latency, set the SAK bit, to ensure we have at least
  1685. // 2 ACK's in flight for feedback to the send throttle control system.
  1686. // Don't create extra ACKs if round trip is less than 100 ms.
  1687. if(!bitEOM || !(pSend->dwFlags & DPSEND_GUARANTEED)){
  1688. DWORD tmDeltaSAK = tm-pSend->pSession->tLastSAK;
  1689. if(((int)tmDeltaSAK > 50 ) &&
  1690. (tmDeltaSAK > (unFp(pSend->pSession->FpLocalAverageLatency)>>2))
  1691. )
  1692. {
  1693. bitSAK=SAK;
  1694. }
  1695. }
  1696. // If we re-transmitted we need to send a SAK
  1697. // despite the SAK countdown.
  1698. if((!bitSAK) &&
  1699. (pSend->dwFlags & DPSEND_GUARANTEED) &&
  1700. ((pSend->NACKMask & (pSend->NACKMask-1)) == 0) &&
  1701. (bitEOM==0)
  1702. )
  1703. {
  1704. bitSAK=SAK;
  1705. }
  1706. if(!(--pSend->SAKCountDown)){
  1707. bitSAK=SAK;
  1708. }
  1709. if(bitSAK|bitEOM){
  1710. pSend->pSession->tLastSAK = tm;
  1711. pSend->SAKCountDown=pSend->SAKInterval;
  1712. pStat=GetSendStat();
  1713. }
  1714. if(pSend->fSendSmall){
  1715. pFrame->flags=CMD|bitEOM|bitSTA|bitSAK;
  1716. seq=(pSend->NR+shift+1) & pSend->SendSEQMSK;
  1717. pFrame->messageid = (byte)pSend->messageid;
  1718. pFrame->sequence = (byte)seq;
  1719. pFrame->serial = (byte)(pSend->serial++);
  1720. if(pStat){
  1721. pStat->serial=pFrame->serial;
  1722. }
  1723. } else {
  1724. pBigFrame->flags=CMD|BIG|bitEOM|bitSTA|bitSAK;
  1725. seq=((pSend->NR+shift+1) & pSend->SendSEQMSK);
  1726. pBigFrame->messageid = (word)pSend->messageid;
  1727. pBigFrame->sequence = (word)seq;
  1728. pBigFrame->serial = (byte)pSend->serial++;
  1729. if(pStat){
  1730. pStat->serial=pBigFrame->serial;
  1731. }
  1732. }
  1733. if(pSend->dwFlags & DPSEND_GUARANTEE){
  1734. pFrame->flags |= RLY;
  1735. }
  1736. // count the number of bytes we have sent.
  1737. Lock(&pSend->pSession->SessionStatLock);
  1738. pSend->pSession->BytesSent+=pSend->BytesThisSend;
  1739. BytesSent=pSend->pSession->BytesSent;
  1740. RemoteBytesReceived=pSend->pSession->RemoteBytesReceived;
  1741. tRemoteBytesReceived=pSend->pSession->tRemoteBytesReceived;
  1742. if(pStat && pSend->pSession->bResetBias &&
  1743. ((--pSend->pSession->bResetBias) == 0))
  1744. {
  1745. bResetBias=TRUE;
  1746. }
  1747. Unlock(&pSend->pSession->SessionStatLock);
  1748. if(pStat){
  1749. pStat->sequence=seq;
  1750. pStat->messageid=pSend->messageid;
  1751. pStat->tSent=tm;
  1752. pStat->LocalBytesSent=BytesSent;
  1753. pStat->RemoteBytesReceived=RemoteBytesReceived;
  1754. pStat->tRemoteBytesReceived=tRemoteBytesReceived;
  1755. pStat->bResetBias=bResetBias;
  1756. if(pSend->dwFlags & DPSEND_GUARANTEED){
  1757. InsertBefore(&pStat->StatList,&pSend->StatList);
  1758. } else {
  1759. Lock(&pSend->pSession->SessionStatLock);
  1760. InsertBefore(&pStat->StatList,&pSend->pSession->DGStatList);
  1761. Unlock(&pSend->pSession->SessionStatLock);
  1762. }
  1763. }
  1764. #undef pBigFrame
  1765. }
  1766. #if 0
  1767. // release sends waiting for an id.
  1768. VOID UnWaitSends(PSESSION pSession, DWORD fReliable)
  1769. {
  1770. BILINK *pBilink;
  1771. PSEND pSendWalker;
  1772. pBilink=pSession->SendQ.next;
  1773. while(pBilink != &pSession->SendQ){
  1774. pSendWalker=CONTAINING_RECORD(pBilink,SEND,SendQ);
  1775. pBilink=pBilink->next;
  1776. if(pSendWalker->SendState==WaitingForId){
  1777. if(fReliable){
  1778. if(pSendWalker->dwFlags & DPSEND_GUARANTEED){
  1779. pSendWalker->SendState=Start;
  1780. }
  1781. } else {
  1782. if(!(pSendWalker->dwFlags & DPSEND_GUARANTEED)){
  1783. pSendWalker->SendState=Start;
  1784. }
  1785. }
  1786. }
  1787. }
  1788. if(fReliable){
  1789. pSession->nWaitingForMessageid=0;
  1790. } else {
  1791. pSession->nWaitingForDGMessageid=0;
  1792. }
  1793. }
  1794. #endif
  1795. // Check if a datagram send can be started, if it can update teh
  1796. // Session and the Send.
  1797. BOOL StartDatagramSend(PSESSION pSession, PSEND pSend, UINT MsgIdMask)
  1798. {
  1799. BOOL bFoundSend;
  1800. UINT bit;
  1801. // BOOL bTransition=FALSE;
  1802. if((pSession->DGLastMsg-pSession->DGFirstMsg < pSession->MaxCDGSends)){
  1803. bFoundSend=TRUE;
  1804. if(pSend->SendState==WaitingForId){
  1805. InterlockedDecrement(&pSession->nWaitingForDGMessageid);
  1806. }
  1807. bit=(pSession->DGLastMsg-pSession->DGFirstMsg)&MsgIdMask;
  1808. ASSERT(bit<30);
  1809. pSession->DGOutMsgMask |= 1<<bit;
  1810. pSession->DGLastMsg =(pSession->DGLastMsg+1)&MsgIdMask;
  1811. pSend->messageid =pSession->DGLastMsg;
  1812. pSend->FrameSize =pSession->MaxPacketSize-MAX_SEND_HEADER;
  1813. // Calculate number of frames required for this send.
  1814. pSend->nFrames =(pSend->MessageSize/pSend->FrameSize);
  1815. if(pSend->FrameSize*pSend->nFrames < pSend->MessageSize || !pSend->nFrames){
  1816. pSend->nFrames++;
  1817. }
  1818. pSend->NR=0;
  1819. pSend->FrameDataLen=0;// hack
  1820. pSend->fSendSmall=pSession->fSendSmallDG;
  1821. if(pSend->fSendSmall){
  1822. pSend->SendSEQMSK = 0xFF;
  1823. } else {
  1824. pSend->SendSEQMSK = 0xFFFF;
  1825. }
  1826. } else {
  1827. #if 0
  1828. if(pSession->fSendSmallDG && pSession->DGFirstMsg < 0xFF-MAX_SMALL_CSENDS) {
  1829. // Ran out of IDs, Transition to Large headers.
  1830. DPF(9,"OUT OF IDS, DATAGRAMS GOING TO LARGE FRAMES\n");
  1831. pSession->MaxCDGSends = MAX_LARGE_DG_CSENDS;
  1832. pSession->DGWindowSize = MAX_LARGE_WINDOW;
  1833. pSession->fSendSmallDG = FALSE;
  1834. bTransition=TRUE;
  1835. }
  1836. #endif
  1837. bFoundSend=FALSE;
  1838. if(pSend->SendState==Start){
  1839. InterlockedIncrement(&pSession->nWaitingForDGMessageid);
  1840. DPF(9,"StartDatagramSend: No Id's Avail: nWaitingForDGMessageid %x\n",pSession->nWaitingForDGMessageid);
  1841. pSend->SendState=WaitingForId;
  1842. #if 0
  1843. if(bTransition){
  1844. UnWaitSends(pSession,FALSE);
  1845. SetEvent(pSession->pProtocol->m_hSendEvent);
  1846. }
  1847. #endif
  1848. } else {
  1849. DPF(9,"Couldn't start datagram send on pSend %x State %d pSession %x\n",pSend,pSend->SendState,pSession);
  1850. if(pSend->SendState!=WaitingForId){
  1851. ASSERT(0);
  1852. }
  1853. }
  1854. }
  1855. return bFoundSend;
  1856. }
  1857. BOOL StartReliableSend(PSESSION pSession, PSEND pSend, UINT MsgIdMask)
  1858. {
  1859. BOOL bFoundSend;
  1860. UINT bit;
  1861. // BOOL bTransition=FALSE;
  1862. ASSERT(pSend->dwFlags & DPSEND_GUARANTEED);
  1863. if((pSession->LastMsg-pSession->FirstMsg & MsgIdMask) < pSession->MaxCSends){
  1864. DPF(9,"StartReliableSend: FirstMsg: x%x LastMsg: x%x\n",pSession->FirstMsg, pSession->LastMsg);
  1865. bFoundSend=TRUE;
  1866. if(pSend->SendState==WaitingForId){
  1867. InterlockedDecrement(&pSession->nWaitingForMessageid);
  1868. }
  1869. bit=(pSession->LastMsg-pSession->FirstMsg)&MsgIdMask;
  1870. #ifdef DEBUG
  1871. if(!(bit<pSession->MaxCSends)){
  1872. DEBUG_BREAK();
  1873. }
  1874. #endif
  1875. pSession->OutMsgMask |= 1<<bit;
  1876. pSession->LastMsg =(pSession->LastMsg+1)&MsgIdMask;
  1877. DPF(9,"StartReliableSend: pSend %x assigning id x%x\n",pSend,pSession->LastMsg);
  1878. pSend->messageid =pSession->LastMsg;
  1879. pSend->FrameSize =pSession->MaxPacketSize-MAX_SEND_HEADER;
  1880. // Calculate number of frames required for this send.
  1881. pSend->nFrames =(pSend->MessageSize/pSend->FrameSize);
  1882. if(pSend->FrameSize*pSend->nFrames < pSend->MessageSize || !pSend->nFrames){
  1883. pSend->nFrames++;
  1884. }
  1885. pSend->NR=0;
  1886. pSend->FrameDataLen=0;// hack
  1887. pSend->fSendSmall=pSession->fSendSmall;
  1888. if(pSend->fSendSmall){
  1889. pSend->SendSEQMSK = 0xFF;
  1890. } else {
  1891. pSend->SendSEQMSK = 0xFFFF;
  1892. }
  1893. } else {
  1894. #if 0
  1895. if (pSession->fSendSmall && pSession->FirstMsg < 0xFF-MAX_SMALL_CSENDS){
  1896. // Ran out of IDs, Transition to Large headers - but only if we aren't going
  1897. // to confuse the wrapping code.
  1898. DPF(8,"OUT OF IDS, RELIABLE SENDS GOING TO LARGE FRAMES\n");
  1899. pSession->MaxCSends = MAX_LARGE_CSENDS;
  1900. pSession->WindowSize = MAX_LARGE_WINDOW;
  1901. pSession->fSendSmall = FALSE;
  1902. bTransition = TRUE;
  1903. }
  1904. #endif
  1905. bFoundSend=FALSE;
  1906. if(pSend->SendState==Start){
  1907. bFoundSend=FALSE;
  1908. // Reliable, waiting for id.
  1909. InterlockedIncrement(&pSession->nWaitingForMessageid);
  1910. pSend->SendState=WaitingForId;
  1911. DPF(9,"StartReliableSend: No Id's Avail: nWaitingForMessageid %x\n",pSession->nWaitingForMessageid);
  1912. #if 0
  1913. if(bTransition){
  1914. UnWaitSends(pSession,TRUE);
  1915. SetEvent(pSession->pProtocol->m_hSendEvent);
  1916. }
  1917. #endif
  1918. } else {
  1919. bFoundSend=FALSE;
  1920. DPF(9,"Couldn't start reliable send on pSend %x State %d pSession %x\n",pSend,pSend->SendState,pSession);
  1921. if(pSend->SendState!=WaitingForId){
  1922. ASSERT(0);
  1923. }
  1924. }
  1925. }
  1926. return bFoundSend;
  1927. }
  1928. BOOL CheckUserTimeOut(PSEND pSend)
  1929. {
  1930. if(pSend->dwTimeOut){
  1931. if((timeGetTime()-pSend->dwSendTime) > pSend->dwTimeOut){
  1932. pSend->SendState=UserTimeOut;
  1933. return TRUE;
  1934. }
  1935. }
  1936. return FALSE;
  1937. }
  1938. /*=============================================================================
  1939. GetNextMessageToSend
  1940. Description:
  1941. Scans the send queue for a message that is the current priority and
  1942. is in the ready to send state or throttled state (we shouldn't even
  1943. get here unless the throttle was removed.) If we find such a message
  1944. we return a pointer to the caller.
  1945. Adds a reference to the Send and the Session.
  1946. Parameters:
  1947. PPROTOCOOL pProtocol - pointer to the PROTOCOL object to send packets on.
  1948. Return Values:
  1949. NULL - no message should be sent.
  1950. PSEND - message to send.
  1951. -----------------------------------------------------------------------------*/
  1952. PSEND GetNextMessageToSend(PPROTOCOL pProtocol)
  1953. {
  1954. PSEND pSend;
  1955. BILINK *pBilink;
  1956. UINT CurrentSendPri;
  1957. BOOL bFoundSend;
  1958. PSESSION pSession;
  1959. UINT MsgIdMask;
  1960. Lock(&pProtocol->m_SendQLock);
  1961. DPF(9,"==>GetNextMessageToSend\n");
  1962. Top:
  1963. bFoundSend = FALSE;
  1964. pProtocol->m_bRescanQueue=FALSE;
  1965. if(EMPTY_BILINK(&pProtocol->m_GSendQ)){
  1966. Unlock(&pProtocol->m_SendQLock);
  1967. DPF(9,"GetNextMessageToSend: called with nothing in queue, heading for the door.\n");
  1968. goto exit;
  1969. }
  1970. pBilink = pProtocol->m_GSendQ.next;
  1971. pSend = CONTAINING_RECORD(pBilink, SEND, m_GSendQ);
  1972. CurrentSendPri = pSend->Priority;
  1973. while(pBilink != &pProtocol->m_GSendQ){
  1974. pSession=pSend->pSession;
  1975. ASSERT_SIGN(pSession, SESSION_SIGN);
  1976. Lock(&pSession->SessionLock);
  1977. if(pProtocol->m_bRescanQueue){
  1978. DPF(9,"RESCAN of QUEUE FORCED IN GETNEXTMESSAGETOSEND\n");
  1979. Unlock(&pSession->SessionLock);
  1980. goto Top;
  1981. }
  1982. if(pSession->dwFlags & SESSION_UNTHROTTLED){
  1983. // unthrottle happened, so rewind.
  1984. DPF(9,"Unthrottling Session %x\n",pSession);
  1985. pSession->dwFlags &= ~(SESSION_THROTTLED|SESSION_UNTHROTTLED);
  1986. }
  1987. Lock(&pSend->SendLock);
  1988. switch(pSession->eState){
  1989. case Open:
  1990. if((pSend->dwFlags & DPSEND_GUARANTEE)?(pSession->fSendSmall):(pSession->fSendSmallDG)){
  1991. MsgIdMask = 0xFF;
  1992. } else {
  1993. MsgIdMask = 0xFFFF;
  1994. }
  1995. if(!(pSend->dwFlags & ASEND_PROTOCOL) && (pSession->dwFlags & SESSION_THROTTLED)){
  1996. // don't do sends on a throttled session, unless they are internal sends.
  1997. break;
  1998. }
  1999. switch(pSend->SendState){
  2000. case Start:
  2001. case WaitingForId:
  2002. DPF(9,"Found Send in State %d, try Going to Sending State\n",pSend->SendState);
  2003. // Just starting, need an id.
  2004. if(!(pSend->dwFlags & ASEND_PROTOCOL) && CheckUserTimeOut(pSend)){
  2005. if(pSend->SendState==WaitingForId){
  2006. // fixup WaitingForId count on timed out send.
  2007. if(pSend->dwFlags&DPSEND_GUARANTEED){
  2008. InterlockedDecrement(&pSession->nWaitingForMessageid);
  2009. } else {
  2010. InterlockedDecrement(&pSession->nWaitingForDGMessageid);
  2011. }
  2012. }
  2013. bFoundSend=TRUE;
  2014. break;
  2015. }
  2016. if(pSend->dwFlags&ASEND_PROTOCOL){
  2017. DPF(9,"System Send in Start State, Going to Sending State\n");
  2018. bFoundSend=TRUE;
  2019. pSend->SendState=Sending;
  2020. break;
  2021. } else if(!(pSend->dwFlags&DPSEND_GUARANTEED)) {
  2022. //check_datagram:
  2023. bFoundSend=StartDatagramSend(pSession,pSend, MsgIdMask);
  2024. } else {
  2025. // NOT DataGram, .: reliable...
  2026. //check_reliable:
  2027. bFoundSend=StartReliableSend(pSession,pSend, MsgIdMask);
  2028. #ifdef DEBUG
  2029. if(bFoundSend){
  2030. BILINK *pBiSendWalker=pSend->SendQ.prev;
  2031. PSEND pSendWalker;
  2032. while(pBiSendWalker != &pSession->SendQ){
  2033. pSendWalker=CONTAINING_RECORD(pBiSendWalker,SEND,SendQ);
  2034. pBiSendWalker=pBiSendWalker->prev;
  2035. if((pSendWalker->SendState==Start || pSendWalker->SendState==WaitingForId)&&
  2036. pSendWalker->dwFlags&DPSEND_GUARANTEED &&
  2037. !(pSendWalker->dwFlags&ASEND_PROTOCOL) &&
  2038. pSendWalker->Priority >= pSend->Priority){
  2039. DPF(0,"Send %x got id %x but Send %x still in state %x on Session %x\n",pSend,pSend->messageid,pSendWalker,pSendWalker->SendState,pSession);
  2040. DEBUG_BREAK();
  2041. }
  2042. }
  2043. }
  2044. #endif
  2045. }
  2046. if(bFoundSend){
  2047. if(pSession->dwFlags & SESSION_THROTTLED)
  2048. {
  2049. pSend->SendState=Throttled;
  2050. bFoundSend=FALSE;
  2051. } else {
  2052. pSend->SendState=Sending;
  2053. }
  2054. }
  2055. break;
  2056. case ReadyToSend:
  2057. DPF(9,"Found Send in ReadyToSend State, going to Sending State\n");
  2058. bFoundSend=TRUE;
  2059. if(pSession->dwFlags & SESSION_THROTTLED)
  2060. {
  2061. pSend->SendState=Throttled;
  2062. bFoundSend=FALSE;
  2063. } else {
  2064. pSend->SendState=Sending;
  2065. }
  2066. break;
  2067. case Throttled:
  2068. ASSERT(!(pSession->dwFlags & SESSION_THROTTLED));
  2069. DPF(9,"Found Send in Throttled State, unthrottling going to Sending State\n");
  2070. bFoundSend=TRUE;
  2071. pSend->SendState=Sending;
  2072. if(pSession->dwFlags & SESSION_THROTTLED)
  2073. {
  2074. pSend->SendState=Throttled;
  2075. bFoundSend=FALSE;
  2076. } else {
  2077. pSend->SendState=Sending;
  2078. }
  2079. break;
  2080. case TimedOut:
  2081. DPF(9,"Found TimedOut Send.\n");
  2082. TimeOutSession(pSession);
  2083. bFoundSend=TRUE;
  2084. break;
  2085. case Cancelled:
  2086. bFoundSend=TRUE;
  2087. break;
  2088. default:
  2089. ASSERT(pSend->SendState <= Done);
  2090. break;
  2091. } /* end switch(SendState) */
  2092. break;
  2093. default:
  2094. switch(pSend->SendState){
  2095. case Sending:
  2096. case Done:
  2097. DPF(9,"GetNextMessageToSend: Session %x was in state %d ,pSend %x SendState %d, leaving...\n",pSession, pSession->eState, pSend, pSend->SendState);
  2098. //bFoundSend=FALSE;
  2099. break;
  2100. case WaitingForAck:
  2101. CancelRetryTimer(pSend);
  2102. pSend->SendState=TimedOut;
  2103. DPF(9,"Moved WaitingForAck send to TimedOut and returning pSession %x was in State %d pSend %x\n",pSession,pSession->eState,pSend);
  2104. bFoundSend=TRUE;
  2105. break;
  2106. default:
  2107. DPF(9,"GetNextMessageToSend: Session %x was in state %d ,returning pSend %x SendState %d\n",pSession, pSession->eState, pSend, pSend->SendState);
  2108. bFoundSend=TRUE;
  2109. break;
  2110. }
  2111. break;
  2112. } /* end switch pSession->eState */
  2113. if(bFoundSend){
  2114. if(AddSendRef(pSend,1)){
  2115. InterlockedIncrement(&pSession->RefCount);
  2116. } else {
  2117. bFoundSend=FALSE;
  2118. }
  2119. }
  2120. Unlock(&pSend->SendLock);
  2121. Unlock(&pSession->SessionLock);
  2122. if(bFoundSend){
  2123. if(pSend->NS==0){
  2124. pSend->tLastACK=timeGetTime();
  2125. }
  2126. break;
  2127. }
  2128. pBilink=pBilink->next;
  2129. pSend=CONTAINING_RECORD(pBilink, SEND, m_GSendQ);
  2130. } /* end while (pBilink != &pProtocol->m_GSendQ) */
  2131. Unlock(&pProtocol->m_SendQLock);
  2132. exit:
  2133. if(bFoundSend){
  2134. DPF(9,"<==GetNextMessageToSend %x\n",pSend);
  2135. return pSend;
  2136. } else {
  2137. DPF(9,"<==GetNextMessageToSend NULL\n");
  2138. return NULL;
  2139. }
  2140. }