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.

1393 lines
42 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. rplpush.c
  5. Abstract:
  6. This module contains functions of the PUSH handler component
  7. of the Replicator.
  8. These functions handle the pull requests from a Pull Partner
  9. Functions:
  10. RplPushInit
  11. ExecuteWrkItm
  12. HandleAddVersMapReq
  13. HandleSndEntriesReq
  14. HandleUpdNtf
  15. HandleUpdVersNoReq
  16. Portability:
  17. This module is portable
  18. Author:
  19. Pradeep Bahl (PradeepB) Jan-1993
  20. Revision History:
  21. Modification date Person Description of modification
  22. ----------------- ------- ----------------------------
  23. --*/
  24. /*
  25. * Includes
  26. */
  27. #include "wins.h"
  28. #include "nmsnmh.h"
  29. #include "nms.h"
  30. #include "rpl.h"
  31. #include "rplmsgf.h"
  32. #include "rplpush.h"
  33. #include "rplpull.h"
  34. #include "winsevt.h"
  35. #include "winsque.h"
  36. #include "nmsdb.h"
  37. #include "winsmsc.h"
  38. #include "winscnf.h"
  39. #include "comm.h"
  40. /*
  41. * Local Macro Declarations
  42. */
  43. //
  44. // The amount of time the push thread will wait after its last activity
  45. // before exiting. This is kept to be 5 mts for now.
  46. //
  47. // It is a good idea to keep it less than the Min. Replication time
  48. // interval
  49. //
  50. #define WAIT_TIME_BEFORE_EXITING (300000)
  51. /*
  52. * Local Typedef Declarations
  53. */
  54. /*
  55. * Global Variable Definitions
  56. */
  57. HANDLE RplPushCnfEvtHdl;
  58. BOOL fRplPushThdExists = FALSE;
  59. /*
  60. * Local Variable Definitions
  61. */
  62. /*
  63. * Local Function Prototype Declarations
  64. */
  65. STATIC
  66. STATUS
  67. HandleAddVersMapReq(
  68. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  69. );
  70. STATIC
  71. STATUS
  72. HandleSndEntriesReq(
  73. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  74. );
  75. STATIC
  76. VOID
  77. HandleUpdNtf(
  78. #if PRSCONN
  79. BOOL fPrsConn,
  80. #endif
  81. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  82. );
  83. STATIC
  84. VOID
  85. HandleUpdVersNoReq(
  86. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  87. );
  88. STATIC
  89. VOID
  90. ExecuteWrkItm(
  91. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  92. );
  93. /* prototypes for functions local to this module go here */
  94. STATUS
  95. RplPushInit(
  96. LPVOID pParam
  97. )
  98. /*++
  99. Routine Description:
  100. This function is the start function of the Push Thread.
  101. The function blocks on an auto-reset event variable until signalled
  102. When signalled it
  103. dequeues a work item from from its work queue and executes it
  104. Arguments:
  105. pParam
  106. Externals Used:
  107. None
  108. Return Value:
  109. Success status codes -- WINS_SUCCESS
  110. Error status codes -- WINS_FAILURE
  111. Error Handling:
  112. Called by:
  113. ERplInit
  114. Side Effects:
  115. Comments:
  116. None
  117. --*/
  118. {
  119. HANDLE ThdEvtArr[2];
  120. PQUE_RPL_REQ_WRK_ITM_T pWrkItm;
  121. DWORD ArrInd;
  122. DWORD RetVal;
  123. BOOL fSignaled;
  124. UNREFERENCED_PARAMETER(pParam);
  125. try {
  126. //
  127. // Initialize the thd
  128. //
  129. NmsDbThdInit(WINS_E_RPLPUSH);
  130. DBGMYNAME("Replicator Push Thread\n");
  131. //
  132. // We do this at each thread creation to save on STATIC storage. This
  133. // way when the thread is not there we don't consume resources.
  134. //
  135. ThdEvtArr[0] = NmsTermEvt;
  136. ThdEvtArr[1] = QueRplPushQueHd.EvtHdl;
  137. while(TRUE)
  138. {
  139. try {
  140. /*
  141. * Block until signaled or until timer expiry
  142. */
  143. WinsMscWaitTimedUntilSignaled(
  144. ThdEvtArr,
  145. 2,
  146. &ArrInd,
  147. WAIT_TIME_BEFORE_EXITING,
  148. &fSignaled
  149. );
  150. //
  151. // If the wait was interrupted due to a termination signal or
  152. // if the wait timed out, exit the thread.
  153. //
  154. if (!fSignaled || (ArrInd == 0))
  155. {
  156. //
  157. // if the thread has timed out, we need to exit it. Before
  158. // we do that, we check whether some thread sneaked in
  159. // a message after the timeout
  160. //
  161. if (!fSignaled)
  162. {
  163. PQUE_HD_T pQueHd = pWinsQueQueHd[QUE_E_RPLPUSH];
  164. //
  165. // QueGetWrkItm also enters the Push thread's critical
  166. // section. I don't want to write a separate function
  167. // or overload the QueGetWrkItem function to avoid
  168. // the double entry into the critical section.
  169. //
  170. EnterCriticalSection(&pQueHd->CrtSec);
  171. RetVal = QueGetWrkItm(
  172. QUE_E_RPLPUSH,
  173. (LPVOID)&pWrkItm
  174. );
  175. //
  176. // if we got a request execute it.
  177. //
  178. if (RetVal != WINS_NO_REQ)
  179. {
  180. LeaveCriticalSection(&pQueHd->CrtSec);
  181. NmsDbOpenTables(WINS_E_RPLPUSH);
  182. ExecuteWrkItm(pWrkItm);
  183. NmsDbCloseTables();
  184. }
  185. else
  186. {
  187. //
  188. // set the flag to FALSE so that if a message
  189. // comes for this Push thread, it is created.
  190. //
  191. fRplPushThdExists = FALSE;
  192. WinsThdPool.ThdCount--;
  193. WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].
  194. fTaken = FALSE;
  195. //
  196. // Be sure to close the handle, otherwise
  197. // the thread object will stay.
  198. //
  199. CloseHandle(
  200. WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].
  201. ThdHdl
  202. );
  203. LeaveCriticalSection(&pQueHd->CrtSec);
  204. WinsMscTermThd(WINS_SUCCESS,
  205. WINS_DB_SESSION_EXISTS);
  206. }
  207. }
  208. else //signaled for termination by the main thread
  209. {
  210. WinsMscTermThd(WINS_SUCCESS,
  211. WINS_DB_SESSION_EXISTS);
  212. }
  213. }
  214. /*
  215. *loop forever until all work items have been handled
  216. */
  217. while(TRUE)
  218. {
  219. /*
  220. * dequeue the request from the queue
  221. */
  222. RetVal = QueGetWrkItm(
  223. QUE_E_RPLPUSH,
  224. (LPVOID)&pWrkItm
  225. );
  226. if (RetVal == WINS_NO_REQ)
  227. {
  228. break;
  229. }
  230. NmsDbOpenTables(WINS_E_RPLPUSH);
  231. ExecuteWrkItm(pWrkItm);
  232. NmsDbCloseTables();
  233. //
  234. // Check for termination here since WINS could be under
  235. // stress with a large number of messages in the queue.
  236. // We don't want to delay the stop.
  237. //
  238. WinsMscChkTermEvt(
  239. #ifdef WINSDBG
  240. WINS_E_RPLPUSH,
  241. #endif
  242. FALSE
  243. );
  244. }
  245. } // end of try
  246. except(EXCEPTION_EXECUTE_HANDLER) {
  247. DBGPRINTEXC("Replicator Push thread");
  248. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  249. }
  250. } // end of while
  251. } // end of try
  252. except (EXCEPTION_EXECUTE_HANDLER) {
  253. DBGPRINTEXC("Replicator Push thread");
  254. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_ABNORMAL_SHUTDOWN);
  255. //
  256. // If NmsDbThdInit comes back with an exception, it is possible
  257. // that the session has not yet been started. Passing
  258. // WINS_DB_SESSION_EXISTS however is ok
  259. //
  260. WinsMscTermThd(WINS_FAILURE, WINS_DB_SESSION_EXISTS);
  261. }
  262. //
  263. // We should never get here.
  264. //
  265. return(WINS_FAILURE);
  266. }
  267. VOID
  268. ExecuteWrkItm(
  269. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  270. )
  271. /*++
  272. Routine Description:
  273. The function executes a work item. The work item can either be
  274. a push notification request from within this WINS (from an NBT thread)
  275. or a replication request (from a remote WINS)
  276. Arguments:
  277. pWrkItm - ptr to a work item
  278. Externals Used:
  279. None
  280. Return Value:
  281. None
  282. Error Handling:
  283. Called by:
  284. RplPushInit
  285. Side Effects:
  286. Comments:
  287. None
  288. --*/
  289. {
  290. RPLMSGF_MSG_OPCODE_E PullReqType_e;
  291. #if PRSCONN
  292. BOOL fPrsConn = FALSE;
  293. #endif
  294. BOOL fPushNtf = FALSE;
  295. //
  296. // get the opcode
  297. //
  298. RplMsgfUfmPullPnrReq(
  299. pWrkItm->pMsg,
  300. pWrkItm->MsgLen,
  301. &PullReqType_e
  302. );
  303. switch(PullReqType_e)
  304. {
  305. case(RPLMSGF_E_ADDVERSNO_MAP_REQ):
  306. HandleAddVersMapReq(pWrkItm);
  307. #ifdef WINSDBG
  308. NmsCtrs.RplPushCtrs.NoAddVersReq++;
  309. #endif
  310. break;
  311. case(RPLMSGF_E_SNDENTRIES_REQ):
  312. HandleSndEntriesReq(pWrkItm);
  313. #ifdef WINSDBG
  314. NmsCtrs.RplPushCtrs.NoSndEntReq++;
  315. #endif
  316. break;
  317. #if PRSCONN
  318. case(RPLMSGF_E_UPDATE_NTF_PRS):
  319. case(RPLMSGF_E_UPDATE_NTF_PROP_PRS):
  320. fPrsConn = TRUE;
  321. #endif
  322. case(RPLMSGF_E_UPDATE_NTF):
  323. case(RPLMSGF_E_UPDATE_NTF_PROP):
  324. fPushNtf = TRUE;
  325. #if PRSCONN
  326. HandleUpdNtf(fPrsConn, pWrkItm);
  327. #else
  328. HandleUpdNtf(pWrkItm);
  329. #endif
  330. #ifdef WINSDBG
  331. NmsCtrs.RplPushCtrs.NoUpdNtfReq++;
  332. #endif
  333. break;
  334. case(RPLMSGF_E_UPDVERSNO_REQ):
  335. #ifdef WINSDBG
  336. NmsCtrs.RplPushCtrs.NoUpdVersReq++;
  337. #endif
  338. HandleUpdVersNoReq(pWrkItm);
  339. break;
  340. default:
  341. #ifdef WINSDBG
  342. NmsCtrs.RplPushCtrs.NoInvReq++;
  343. #endif
  344. DBGPRINT1(ERR, "RplPush: ExecuteWrkItm: Invalid Opcode (%d)\n",
  345. PullReqType_e);
  346. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  347. break;
  348. }
  349. //
  350. // If the message is not an update notification,
  351. // Free the message buffer. For an update
  352. // notification, the message is handed to
  353. // the PULL thread to handle. Therefore, we should not free it
  354. // The work items needs to be freed always since we always allocate
  355. // a new work item when queuing a request.
  356. //
  357. if ( !fPushNtf)
  358. {
  359. ECommFreeBuff(pWrkItm->pMsg - COMM_HEADER_SIZE);
  360. }
  361. //
  362. // Deallocate the work item
  363. //
  364. QueDeallocWrkItm( RplWrkItmHeapHdl, pWrkItm );
  365. return;
  366. }
  367. STATUS
  368. HandleAddVersMapReq(
  369. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  370. )
  371. /*++
  372. Routine Description:
  373. This function handles a "send address - version # " request
  374. Arguments:
  375. pWrkItm - Work item that carries the request and associated info
  376. Externals Used:
  377. None
  378. Return Value:
  379. Success status codes --
  380. Error status codes --
  381. Error Handling:
  382. Called by:
  383. Side Effects:
  384. Comments:
  385. None
  386. --*/
  387. {
  388. LPBYTE pRspBuff;
  389. DWORD RspMsgLen;
  390. PRPL_ADD_VERS_NO_T pPullAddNVersNo;
  391. DWORD i = 0;
  392. DWORD MaxNoOfOwners;
  393. PRPL_CONFIG_REC_T pPnr;
  394. COMM_ADD_T WinsAdd;
  395. BOOL fRplPnr = FALSE;
  396. BOOL fExc = FALSE;
  397. struct in_addr InAddr;
  398. PCOMM_ADD_T pWinsAdd;
  399. PNMSDB_WINS_STATE_E pWinsState_e;
  400. DWORD SizeOfBuff;
  401. BOOL fRspBuffAlloc = FALSE;
  402. #if SUPPORT612WINS > 0
  403. BOOL fIsPnrBeta1Wins;
  404. #endif
  405. DBGENTER("HandleAddVersMapReq\n");
  406. //
  407. // We need to handle this request only if
  408. // either the WINS that sent this message is one of our
  409. // pull pnrs or if the fRplOnlyWCnfPnrs in the registry is FALSE
  410. //
  411. EnterCriticalSection(&WinsCnfCnfCrtSec);
  412. try {
  413. if (WinsCnf.fRplOnlyWCnfPnrs)
  414. {
  415. if ((pPnr = WinsCnf.PushInfo.pPushCnfRecs) != NULL)
  416. {
  417. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  418. //
  419. // Search for the Cnf record for the WINS we want to
  420. // send the PUSH notification to/Replicate with.
  421. //
  422. for (
  423. ;
  424. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  425. &&
  426. !fRplPnr;
  427. // no third expression
  428. )
  429. {
  430. //
  431. // Check if this is the one we want
  432. //
  433. if (pPnr->WinsAdd.Add.IPAdd == WinsAdd.Add.IPAdd)
  434. {
  435. //
  436. // We are done. Set the fRplPnr flag to TRUE so that
  437. // we break out of the loop.
  438. //
  439. // Note: Don't use break since that would cause
  440. // a search for a 'finally' block
  441. //
  442. fRplPnr = TRUE;
  443. continue; //so that we break out of the loop
  444. }
  445. //
  446. // Get the next record that follows this one sequentially
  447. //
  448. pPnr = WinsCnfGetNextRplCnfRec(
  449. pPnr,
  450. RPL_E_IN_SEQ //seq. traversal
  451. );
  452. }
  453. }
  454. }
  455. else
  456. {
  457. fRplPnr = TRUE;
  458. }
  459. }
  460. except(EXCEPTION_EXECUTE_HANDLER) {
  461. DBGPRINTEXC("HandleAddVersMapReq");
  462. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_EXC_PULL_TRIG_PROC);
  463. fExc = TRUE;
  464. }
  465. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  466. try {
  467. if (fRplPnr)
  468. {
  469. VERS_NO_T MinOwnVersNo;
  470. BOOL fOwnInited = FALSE;
  471. DWORD TotNoOfOwners;
  472. MaxNoOfOwners = 0;
  473. WINS_ASSIGN_INT_TO_LI_M(MinOwnVersNo, 1);
  474. DBGPRINT1(TMP, "HandleAddVersMap: WINS (%x) made an AddVersMap request\n", WinsAdd.Add.IPAdd);
  475. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  476. TotNoOfOwners = NmsDbNoOfOwners;
  477. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  478. WinsMscAlloc(sizeof(RPL_ADD_VERS_NO_T) * TotNoOfOwners, &pPullAddNVersNo);
  479. //
  480. // If version counter value > 1, we will send it
  481. //
  482. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  483. if (LiGtr(NmsNmhMyMaxVersNo, MinOwnVersNo))
  484. {
  485. /*
  486. * Get the max. version no for entries owned by self
  487. *
  488. * The reason we subtract 1 from NmsNmhMyMaxVersNo is because
  489. * it contains the version number to be given to the next record
  490. * to be registered/updated.
  491. */
  492. NMSNMH_DEC_VERS_NO_M(
  493. NmsNmhMyMaxVersNo,
  494. pPullAddNVersNo->VersNo
  495. );
  496. pPullAddNVersNo->OwnerWinsAdd = NmsLocalAdd;
  497. pPullAddNVersNo->StartVersNo = NmsDbStartVersNo;
  498. MaxNoOfOwners++;
  499. fOwnInited = TRUE;
  500. }
  501. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  502. //
  503. // BUG 26196
  504. // Note: These critical sections are taken in the order given below
  505. // by the RPC thread executing GetConfig
  506. //
  507. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  508. EnterCriticalSection(&RplVersNoStoreCrtSec);
  509. try {
  510. for (i = 1; i < TotNoOfOwners; i++)
  511. {
  512. //
  513. // If the highest version number for an owner as identified
  514. // by the RplPullOwnerVersNo table is zero, there is no
  515. // need to send the mapping of this owner. The reason
  516. // we may have a such an entry in our in-memory table is
  517. // because 1)All records of the owner got deleted. Local
  518. // WINS got terminated and reinvoked. On reinvocation, it
  519. // did not find any records in the db.
  520. // 2)Local WINS received a Pull range
  521. // request for an owner that it did not know about.
  522. // Since Pull Range request comes in as a
  523. // "SndEntries" request, the Push thread has
  524. // no way of distinguishing it from a normal
  525. // 2 message pull request. For a 2 message
  526. // request, "SndEntries" request will always
  527. // have a subset of the WINS servers that
  528. // have records in our db.
  529. //
  530. if (LiGtrZero((pRplPullOwnerVersNo+i)->VersNo) &&
  531. (pNmsDbOwnAddTbl+i)->WinsState_e == NMSDB_E_WINS_ACTIVE)
  532. {
  533. PVERS_NO_T pStartVersNo;
  534. (pPullAddNVersNo+MaxNoOfOwners)->VersNo = (pRplPullOwnerVersNo+i)->VersNo;
  535. //
  536. // Note: Since RplPullOwnerVersNo[i] is > 0, the
  537. // State of the entry can not be deleted (see
  538. // RplPullPullEntrie)
  539. //
  540. RPL_FIND_ADD_BY_OWNER_ID_M(i, pWinsAdd, pWinsState_e,
  541. pStartVersNo);
  542. (pPullAddNVersNo+MaxNoOfOwners)->OwnerWinsAdd = *pWinsAdd;
  543. (pPullAddNVersNo+MaxNoOfOwners++)->StartVersNo = *pStartVersNo;
  544. DBGPRINT3(RPLPUSH, "HandleAddVersMap:Owner Add (%x) - Vers. No (%d %d)\n", pWinsAdd->Add.IPAdd, (pRplPullOwnerVersNo+i)->VersNo.HighPart, (pRplPullOwnerVersNo+i)->VersNo.LowPart);
  545. }
  546. PERF("Speed it up by using pointer arithmetic")
  547. }
  548. }
  549. except(EXCEPTION_EXECUTE_HANDLER) {
  550. DBGPRINTEXC("HandleAddVersMapReq");
  551. DBGPRINT1(EXC, "HandleAddVersMapReq: Exc. while checking vers. nos of owners\n", GetExceptionCode());
  552. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_EXC_PULL_TRIG_PROC);
  553. }
  554. //
  555. // Let us initialize RplPullOwnerVersNo entry for the local WINS
  556. //
  557. // This is done so that if we later on pull from the remote WINS,
  558. // we don't end up pulling our own records
  559. //
  560. if (fOwnInited)
  561. {
  562. pRplPullOwnerVersNo->VersNo = pPullAddNVersNo->VersNo;
  563. pRplPullOwnerVersNo->StartVersNo = pPullAddNVersNo->StartVersNo;
  564. DBGPRINT3(RPLPUSH, "HandleAddVersMap: Owner Add (%x) - Vers. No (%d %d)\n", NmsLocalAdd.Add.IPAdd, (pRplPullOwnerVersNo+i)->VersNo.HighPart, (pRplPullOwnerVersNo+i)->VersNo.LowPart);
  565. }
  566. LeaveCriticalSection(&RplVersNoStoreCrtSec);
  567. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  568. #if SUPPORT612WINS > 0
  569. COMM_IS_PNR_BETA1_WINS_M(&pWrkItm->DlgHdl, fIsPnrBeta1Wins);
  570. #endif
  571. SizeOfBuff = RPLMSGF_ADDVERSMAP_RSP_SIZE_M(MaxNoOfOwners);
  572. WinsMscAlloc(SizeOfBuff, &pRspBuff);
  573. fRspBuffAlloc = TRUE;
  574. /*
  575. * format the response
  576. */
  577. RplMsgfFrmAddVersMapRsp(
  578. #if SUPPORT612WINS > 0
  579. fIsPnrBeta1Wins,
  580. #endif
  581. RPLMSGF_E_ADDVERSNO_MAP_RSP,
  582. pRspBuff + COMM_N_TCP_HDR_SZ,
  583. SizeOfBuff - COMM_N_TCP_HDR_SZ,
  584. pPullAddNVersNo,
  585. MaxNoOfOwners,
  586. 0,
  587. &RspMsgLen
  588. );
  589. //
  590. // Free the memory we allocated earlier
  591. //
  592. WinsMscDealloc(pPullAddNVersNo);
  593. /*
  594. * Send the response. We don't check the return code. ECommSndRsp
  595. * may have failed due to communication failure. There is nothing
  596. * more to be done for either the success of failure case.
  597. */
  598. (VOID)ECommSndRsp(
  599. &pWrkItm->DlgHdl,
  600. pRspBuff + COMM_N_TCP_HDR_SZ,
  601. RspMsgLen
  602. );
  603. //
  604. // We don't end the dialogue. It will get terminated when
  605. // the initiator terminates it.
  606. //
  607. }
  608. else
  609. {
  610. if (!fExc)
  611. {
  612. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  613. DBGPRINT1(RPLPUSH, "HandleAddVersMapReq: Got a pull request message from a WINS to which we are not allowed to push replicas. Address of WINS is (%x)\n",
  614. WinsAdd.Add.IPAdd
  615. );
  616. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  617. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr),
  618. WINS_EVT_ADD_VERS_MAP_REQ_NOT_ACCEPTED,
  619. TRUE);
  620. }
  621. //
  622. // We need to end the dialogue. The work item and the message
  623. // will get deallocated by the caller
  624. //
  625. //
  626. // End the implicit dialogue
  627. //
  628. (VOID)ECommEndDlg(&pWrkItm->DlgHdl);
  629. }
  630. }
  631. except(EXCEPTION_EXECUTE_HANDLER) {
  632. DBGPRINTEXC("HandleAddVersMapReq");
  633. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  634. }
  635. if (fRspBuffAlloc)
  636. {
  637. WinsMscDealloc(pRspBuff);
  638. }
  639. DBGLEAVE("HandleAddVersMapReq\n")
  640. return(WINS_SUCCESS);
  641. }
  642. STATUS
  643. HandleSndEntriesReq(
  644. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  645. )
  646. /*++
  647. Routine Description:
  648. This function handles the "send data entries req"
  649. Arguments:
  650. pWrkItm - Work item carrying info about the "Send Entries" request from
  651. a remote WINS
  652. Externals Used:
  653. None
  654. Return Value:
  655. Success status codes -- WINS_SUCCESS
  656. Error status codes -- WINS_FAILURE
  657. Error Handling:
  658. Called by:
  659. RplPushInit()
  660. Side Effects:
  661. Comments:
  662. None
  663. --*/
  664. {
  665. COMM_ADD_T WinsAdd; /*address of WINS server whose records
  666. *are being requested*/
  667. VERS_NO_T MaxVers, MinVers; /*max. amd min. versions of
  668. *records*/
  669. FUTURES("use NMSDB_ROW_INFO_T structure - Maybe")
  670. PRPL_REC_ENTRY_T pBuff;
  671. LPBYTE pStartBuff = NULL;
  672. DWORD RspBufLen;
  673. DWORD NoOfRecs = 0;
  674. DWORD i;
  675. LPBYTE pNewPos;
  676. LPBYTE pTxBuff;
  677. LPBYTE pStartTxBuff;
  678. STATUS RetStat;
  679. PWINSTHD_TLS_T pTls;
  680. BOOL fGetDataRecs = FALSE;
  681. PRPL_CONFIG_REC_T pPnr;
  682. BOOL fOnlyDynRecs = FALSE;
  683. DWORD RplType = WINSCNF_RPL_DEFAULT_TYPE;
  684. DWORD RplTypeFMsg;
  685. BYTE Name[1]; //dummy to prevent RtlCopyMemory from
  686. //barfing
  687. COMM_ADD_T ReqWinsAdd;
  688. #if SUPPORT612WINS > 0
  689. BOOL fIsPnrBeta1Wins;
  690. #endif
  691. DBGENTER("HandleSndEntriesReq\n");
  692. GET_TLS_M(pTls);
  693. pTls->HeapHdl = NULL;
  694. //#ifdef WINSDBG
  695. try {
  696. //#endif
  697. //
  698. // Check if this is one of our configured partners. If yes,
  699. // pass the value of fOnlyDynRecs to NmsDbGetDataRecs.
  700. //
  701. // We allow access to even those WINSs that are not partners since
  702. // we need to let them do revalidation of replicas (except for
  703. // this replication activity, all other from non-configured partners
  704. // is stopped at the first step - HandleAddVersMapReq).
  705. //
  706. if ((pPnr = RplGetConfigRec(RPL_E_PUSH, &pWrkItm->DlgHdl, NULL)) != NULL)
  707. {
  708. fOnlyDynRecs = pPnr->fOnlyDynRecs;
  709. RplType = pPnr->RplType;
  710. }
  711. #if SUPPORT612WINS > 0
  712. COMM_IS_PNR_BETA1_WINS_M(&pWrkItm->DlgHdl, fIsPnrBeta1Wins);
  713. #endif
  714. /*
  715. * Unformat the request message
  716. */
  717. RplMsgfUfmSndEntriesReq(
  718. #if SUPPORT612WINS > 0
  719. fIsPnrBeta1Wins,
  720. #endif
  721. pWrkItm->pMsg + 4, /*past the
  722. *opcode */
  723. &WinsAdd,
  724. &MaxVers,
  725. &MinVers,
  726. &RplTypeFMsg
  727. );
  728. // ASSERTMSG("Min. Vers. No is >= Max. Vers. No", LiGeq(MaxVers, MinVers));
  729. FUTURES("Check if the request is a PULL RANGE request. If it is, honor it")
  730. FUTURES("only if the Requesting WINS is under the PUSH key or RplOnlyWCnfPnrs")
  731. FUTURES("is set to 0")
  732. COMM_INIT_ADD_FR_DLG_HDL_M(&ReqWinsAdd, &pWrkItm->DlgHdl);
  733. #ifdef WINSDBG
  734. DBGPRINT2(TMP, "HandleSndEntriesReq: WINS (%x) made a SndEntries request for Owner = (%x) \n", ReqWinsAdd.Add.IPAdd, WinsAdd.Add.IPAdd);
  735. DBGPRINT4(TMP, "HandleSndEntriesReq: Min Vers No (%d %d); Max Vers No = (%d %d)\n", MinVers.HighPart, MinVers.LowPart, MaxVers.HighPart, MaxVers.LowPart);
  736. #endif
  737. if (RplType == WINSCNF_RPL_DEFAULT_TYPE)
  738. {
  739. DBGPRINT2(RPLPUSH, "HandleSndEntriesReq: Pnr (%x) is requesting replication of type (%x)\n", ReqWinsAdd.Add.IPAdd, RplTypeFMsg);
  740. // WINSEVT_LOG_INFO_M(ReqWinsAdd.Add.IPAdd, WINS_EVT_PNR_PARTIAL_RPL_TYPE);
  741. RplType = RplTypeFMsg;
  742. }
  743. /*
  744. *
  745. * Call database manager function to get the records. No need
  746. * to check the return status here
  747. */
  748. (VOID)NmsDbGetDataRecs(
  749. WINS_E_RPLPUSH,
  750. THREAD_PRIORITY_NORMAL, //not looked at
  751. MinVers,
  752. MaxVers,
  753. 0, //not of use here
  754. LiEqlZero(MaxVers) ? TRUE : FALSE, //if max. vers.
  755. //no. is zero,
  756. //we want all
  757. //recs.
  758. FALSE, //not looked at in this call
  759. NULL, //must be NULL since we are not
  760. //doing scavenging of clutter
  761. &WinsAdd,
  762. fOnlyDynRecs,
  763. RplType,
  764. (LPVOID *)&pStartBuff,
  765. &RspBufLen,
  766. &NoOfRecs
  767. );
  768. fGetDataRecs = TRUE;
  769. //
  770. // Allocate a buffer for transmitting the records. Even if the
  771. // above function failed, we still should have received a buffer
  772. // from it (pStartBuff). Note: RspBufLen contains the size of memory
  773. // required for a flattened stream of records.
  774. //
  775. pStartTxBuff = WinsMscHeapAlloc(pTls->HeapHdl, RspBufLen);
  776. pTxBuff = pStartTxBuff + COMM_N_TCP_HDR_SZ;
  777. pBuff = (PRPL_REC_ENTRY_T)pStartBuff;
  778. DBGPRINT4(RPLPUSH, "Formatting 1st record for sending --name (%s)\nfGrp (%d)\nVersNo (%d %d)\n", pBuff->pName/*pBuff->Name*/,
  779. pBuff->fGrp,
  780. pBuff->VersNo.HighPart,
  781. pBuff->VersNo.LowPart
  782. );
  783. /*
  784. * format the response
  785. *
  786. * Note: It is quite possible that NmsDbGetDataRecs retrieved 0
  787. * records. Even if it did, we are still assured of getting
  788. * a buffer of the RPL_CONFIG_REC_SIZE size. Since at the
  789. * time of allocation, memory is 'zero'ed by default, we
  790. * won't run into any problems in the following function
  791. * call. Check out this function to reassure yourself.
  792. *
  793. * Like mentioned in NmsDbGetDataRecs, the following call
  794. * will serve to format a valid response to the remote WINS
  795. */
  796. RplMsgfFrmSndEntriesRsp(
  797. #if SUPPORT612WINS > 0
  798. fIsPnrBeta1Wins,
  799. #endif
  800. pTxBuff,
  801. NoOfRecs,
  802. NOTE("expedient HACK - for now. Later on modify FrmSndEntriesRsp ")
  803. NoOfRecs ? pBuff->pName : Name,
  804. pBuff->NameLen,
  805. pBuff->fGrp,
  806. pBuff->NoOfAdds,
  807. pBuff->NodeAdd,
  808. pBuff->Flag,
  809. pBuff->VersNo,
  810. TRUE, /*First time*/
  811. &pNewPos
  812. );
  813. PERF("Change RplFrmSndEntriesRsp so that it does the looping itself")
  814. for (i = 1; i < NoOfRecs; i++)
  815. {
  816. pBuff = (PRPL_REC_ENTRY_T)((LPBYTE)pBuff + RPL_REC_ENTRY_SIZE);
  817. // DBGPRINT4(RPLPUSH, "Formatting record for sending --name (%s)\nfGrp (%d)\nVersNo (%d %d)\n", pBuff->pName/*pBuff->Name*/, pBuff->fGrp, pBuff->VersNo.HighPart, pBuff->VersNo.LowPart);
  818. /*
  819. * Format the response
  820. */
  821. RplMsgfFrmSndEntriesRsp(
  822. #if SUPPORT612WINS > 0
  823. fIsPnrBeta1Wins,
  824. #endif
  825. pNewPos,
  826. NoOfRecs, //not used by func
  827. pBuff->pName,
  828. pBuff->NameLen,
  829. pBuff->fGrp,
  830. pBuff->NoOfAdds,
  831. pBuff->NodeAdd,
  832. pBuff->Flag,
  833. pBuff->VersNo,
  834. FALSE, /*Not First time*/
  835. &pNewPos
  836. );
  837. }
  838. RspBufLen = (ULONG) (pNewPos - pTxBuff);
  839. /*
  840. * Call ECommSndRsp to send the response.
  841. */
  842. RetStat = ECommSndRsp(
  843. &pWrkItm->DlgHdl,
  844. pTxBuff,
  845. RspBufLen
  846. );
  847. #ifdef WINSDBG
  848. {
  849. // COMM_IP_ADD_T IPAdd;
  850. struct in_addr InAdd;
  851. // COMM_GET_IPADD_M(&pWrkItm->DlgHdl, &IPAdd);
  852. InAdd.s_addr = htonl(ReqWinsAdd.Add.IPAdd);
  853. if (RetStat != WINS_SUCCESS)
  854. {
  855. DBGPRINT2(RPLPUSH, "HandleSndEntriesReq: ERROR: Could not send (%d) records to WINS with address = (%s)\n",
  856. NoOfRecs,
  857. inet_ntoa(InAdd)
  858. );
  859. }
  860. else
  861. {
  862. DBGPRINT2(RPLPUSH, "HandleSndEntriesReq: Sent (%d) records to WINS with address = (%s)\n",
  863. NoOfRecs,
  864. inet_ntoa(InAdd)
  865. );
  866. }
  867. }
  868. #endif
  869. //#ifdef WINSDBG
  870. }
  871. except(EXCEPTION_EXECUTE_HANDLER) {
  872. DBGPRINTEXC("HandleSndEntriesReq");
  873. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  874. } //end of exception handler
  875. //#endif
  876. if (fGetDataRecs)
  877. {
  878. //
  879. // Free the buffer, allocated by NmsDbGetDataRecs and the Tx Buff
  880. //
  881. // The work item and the message it holds are freed by the caller
  882. //
  883. pBuff = (PRPL_REC_ENTRY_T)pStartBuff;
  884. for (i=0; i<NoOfRecs; i++)
  885. {
  886. DWORD EntType;
  887. if (pBuff->pName != NULL)
  888. {
  889. WinsMscHeapFree(pTls->HeapHdl, pBuff->pName);
  890. }
  891. EntType = NMSDB_ENTRY_TYPE_M(pBuff->Flag);
  892. if (((EntType == NMSDB_SPEC_GRP_ENTRY) || (EntType == NMSDB_MULTIHOMED_ENTRY)) && (pBuff->pNodeAdd != NULL))
  893. {
  894. WinsMscHeapFree(pTls->HeapHdl, pBuff->pNodeAdd);
  895. }
  896. pBuff = (PRPL_REC_ENTRY_T)((LPBYTE)pBuff + RPL_REC_ENTRY_SIZE);
  897. }
  898. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  899. WinsMscHeapFree(pTls->HeapHdl, pStartTxBuff);
  900. WinsMscHeapDestroy(pTls->HeapHdl);
  901. }
  902. DBGLEAVE("HandleSndEntriesReq\n");
  903. return(WINS_SUCCESS);
  904. }
  905. VOID
  906. HandleUpdNtf(
  907. #if PRSCONN
  908. BOOL fPrsConn,
  909. #endif
  910. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  911. )
  912. /*++
  913. Routine Description:
  914. This function is called to handle an update notification message
  915. received from a remote WINS
  916. Arguments:
  917. fPrsConn - Indicates whether the connection is persistent or not
  918. pWrkItm - Work Item containing the message and other relevant info
  919. Externals Used:
  920. None
  921. Return Value:
  922. None
  923. Error Handling:
  924. Called by:
  925. RplPushInit()
  926. Side Effects:
  927. Comments:
  928. None
  929. --*/
  930. {
  931. PRPL_CONFIG_REC_T pPnr;
  932. COMM_ADD_T WinsAdd;
  933. BOOL fRplPnr = FALSE;
  934. BOOL fExc = FALSE;
  935. struct in_addr InAddr;
  936. DWORD RplType;
  937. DBGENTER("HandleUpdNtf - PUSH thread\n");
  938. //
  939. // We need to forward this request to the PULL thread only if
  940. // either the WINS that sent this notification is one of our
  941. // push pnrs or if the fRplOnlyWCnfPnrs in the registry is FALSE
  942. //
  943. FUTURES("user RplGetConfigRec instead of the following code")
  944. EnterCriticalSection(&WinsCnfCnfCrtSec);
  945. try {
  946. if (WinsCnf.fRplOnlyWCnfPnrs)
  947. {
  948. if ((pPnr = WinsCnf.PullInfo.pPullCnfRecs) != NULL)
  949. {
  950. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  951. //
  952. // Search for the Cnf record for the WINS we want to
  953. // send the PUSH notification to/Replicate with.
  954. //
  955. for (
  956. ;
  957. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  958. &&
  959. !fRplPnr;
  960. // no third expression
  961. )
  962. {
  963. //
  964. // Check if this is the one we want
  965. //
  966. if (pPnr->WinsAdd.Add.IPAdd == WinsAdd.Add.IPAdd)
  967. {
  968. //
  969. // We are done. Set the fRplPnr flag to TRUE so that
  970. // we break out of the loop.
  971. //
  972. // Note: Don't use break since that would cause
  973. // a search for a 'finally' block
  974. //
  975. fRplPnr = TRUE;
  976. RplType = pPnr->RplType;
  977. continue; //so that we break out of the loop
  978. }
  979. //
  980. // Get the next record that follows this one sequentially
  981. //
  982. pPnr = WinsCnfGetNextRplCnfRec(
  983. pPnr,
  984. RPL_E_IN_SEQ //seq. traversal
  985. );
  986. }
  987. }
  988. }
  989. else
  990. {
  991. fRplPnr = TRUE;
  992. RplType = WinsCnf.PullInfo.RplType;
  993. }
  994. }
  995. except(EXCEPTION_EXECUTE_HANDLER) {
  996. DBGPRINTEXC("HandleUpdNtf");
  997. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_EXC_PUSH_TRIG_PROC);
  998. fExc = TRUE;
  999. }
  1000. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1001. #ifdef WINSDBG
  1002. try {
  1003. #endif
  1004. if (fRplPnr)
  1005. {
  1006. //
  1007. // Inform the TCP listener thread that it should stop
  1008. // monitoring the dialogue since we are handing it over to
  1009. // the PULL thread
  1010. //
  1011. #if PRSCONN
  1012. if (!fPrsConn)
  1013. #endif
  1014. {
  1015. if (!ECommProcessDlg(&pWrkItm->DlgHdl, COMM_E_NTF_STOP_MON))
  1016. {
  1017. //
  1018. // Free the buffer
  1019. //
  1020. ECommFreeBuff(pWrkItm->pMsg - COMM_HEADER_SIZE);
  1021. DBGPRINT0(ERR, "HandleUpdNtf - PUSH thread. No Upd Ntf could be sent. It could be because the link went down\n");
  1022. return;
  1023. }
  1024. else
  1025. {
  1026. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  1027. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  1028. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr),
  1029. WINS_EVT_UPD_NTF_ACCEPTED, TRUE);
  1030. }
  1031. }
  1032. //
  1033. // Forward the request to the Pull thread
  1034. //
  1035. ERplInsertQue(
  1036. WINS_E_RPLPUSH,
  1037. QUE_E_CMD_HDL_PUSH_NTF,
  1038. &pWrkItm->DlgHdl,
  1039. pWrkItm->pMsg, //msg containing the push ntf
  1040. pWrkItm->MsgLen, //msg length
  1041. ULongToPtr(RplType), //context to pass
  1042. 0 //no magic no
  1043. );
  1044. //
  1045. // The Pull thread will now terminate the dlg
  1046. //
  1047. }
  1048. else //we need to reject this trigger
  1049. {
  1050. if (!fExc)
  1051. {
  1052. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  1053. DBGPRINT1(RPLPUSH, "HandleUpdNtf: Got a push trigger from a WINS with which we are not allowed to pull replicas. Address of WINS is (%d)\n",
  1054. WinsAdd.Add.IPAdd
  1055. );
  1056. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  1057. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr),
  1058. WINS_EVT_UPD_NTF_NOT_ACCEPTED, TRUE);
  1059. }
  1060. //
  1061. // We need to first deallocate the message and then end the
  1062. // dialogue. The work item will get deallocated by the caller
  1063. //
  1064. //
  1065. // Free the buffer
  1066. //
  1067. ECommFreeBuff(pWrkItm->pMsg - COMM_HEADER_SIZE);
  1068. //
  1069. // End the implicit dialogue
  1070. //
  1071. (VOID)ECommEndDlg(&pWrkItm->DlgHdl);
  1072. }
  1073. #ifdef WINSDBG
  1074. }
  1075. except(EXCEPTION_EXECUTE_HANDLER) {
  1076. DBGPRINTEXC("HandleUpdNtf");
  1077. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  1078. }
  1079. #endif
  1080. DBGLEAVE("HandleUpdNtf - PUSH thread\n");
  1081. return;
  1082. }
  1083. VOID
  1084. HandleUpdVersNoReq(
  1085. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. This function is called to handle an update version number
  1090. request received from a remote WINS
  1091. This message is sent by a remote WINS as a result of a clash
  1092. during replication.
  1093. Arguments:
  1094. pWrkItm - work item
  1095. Externals Used:
  1096. None
  1097. Return Value:
  1098. None
  1099. Error Handling:
  1100. Called by:
  1101. RplPushInit()
  1102. Side Effects:
  1103. Comments:
  1104. None
  1105. --*/
  1106. {
  1107. BYTE Name[NMSDB_MAX_NAM_LEN];
  1108. DWORD NameLen;
  1109. BYTE Rcode;
  1110. DWORD RspBuffLen;
  1111. BYTE RspBuff[RPLMSGF_UPDVERSNO_RSP_SIZE];
  1112. COMM_ADD_T WinsAdd;
  1113. struct in_addr InAddr;
  1114. DBGENTER("HandleUpdVerdNoReq\n");
  1115. #ifdef WINSDBG
  1116. try {
  1117. #endif
  1118. //
  1119. // log an event
  1120. //
  1121. COMM_GET_IPADD_M(&pWrkItm->DlgHdl, &WinsAdd.Add.IPAdd);
  1122. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  1123. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr), WINS_EVT_REM_WINS_INF, TRUE);
  1124. /*
  1125. * Unformat the request message
  1126. */
  1127. RplMsgfUfmUpdVersNoReq(
  1128. pWrkItm->pMsg + 4, /*past the
  1129. *opcode */
  1130. Name,
  1131. &NameLen
  1132. );
  1133. //
  1134. // handle the request
  1135. //
  1136. NmsNmhUpdVersNo( Name, NameLen, &Rcode, &WinsAdd );
  1137. //
  1138. //Format the response
  1139. //
  1140. RplMsgfFrmUpdVersNoRsp(
  1141. RspBuff + COMM_N_TCP_HDR_SZ,
  1142. Rcode,
  1143. &RspBuffLen
  1144. );
  1145. //
  1146. // Send the response. No need to check the return code.
  1147. //
  1148. (VOID)ECommSndRsp(
  1149. &pWrkItm->DlgHdl,
  1150. RspBuff + COMM_N_TCP_HDR_SZ,
  1151. RspBuffLen
  1152. );
  1153. //
  1154. // No need to end the dialogue. The initiator of the dlg will end it.
  1155. //
  1156. #ifdef WINSDBG
  1157. }
  1158. except(EXCEPTION_EXECUTE_HANDLER) {
  1159. DBGPRINTEXC("HandleUpdVersNoReq");
  1160. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  1161. }
  1162. #endif
  1163. DBGLEAVE("HandleUpdVerdNoReq\n");
  1164. return;
  1165. } // HandleUpdVersNoReq()
  1166.