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.

632 lines
15 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. send.c
  5. Abstract:
  6. Send packets
  7. Author:
  8. Ahmed Mohamed (ahmedm) 12, 01, 2000
  9. Revision History:
  10. --*/
  11. #include "gs.h"
  12. #include "gsp.h"
  13. #include <stdio.h>
  14. void
  15. GspOpenContext(gs_group_t *gd, gs_context_t **context)
  16. {
  17. gs_context_t *ctx;
  18. int i;
  19. gs_log(("wait on free ctx gid %d\n", gd->g_id));
  20. GsSemaAcquire(gd->g_send.s_sema);
  21. //xxx: this can be done using atomic instruction
  22. GsLockEnter(gd->g_lock);
  23. for (i = 0; i < gd->g_send.s_wsz; i++) {
  24. ctx = &gd->g_send.s_ctxpool[i];
  25. if (ctx->ctx_id == GS_CONTEXT_INVALID_ID) {
  26. break;
  27. }
  28. }
  29. assert(i != gd->g_send.s_wsz);
  30. ctx->ctx_id = (gs_cookie_t) i;
  31. ctx->ctx_bnum = 0;
  32. GsLockExit(gd->g_lock);
  33. gs_log(("got free ctx %d gid %d\n", i, gd->g_id));
  34. *context = ctx;
  35. }
  36. void
  37. GspCloseContext(gs_group_t *gd, gs_context_t *ctx)
  38. {
  39. gs_msg_t *msg;
  40. assert(gd->g_id == ctx->ctx_gid);
  41. gs_log(("release ctx %d gid %d\n", ctx->ctx_id, gd->g_id));
  42. // free/invalidate context
  43. ctx->ctx_id = GS_CONTEXT_INVALID_ID;
  44. GsSemaRelease(gd->g_send.s_sema);
  45. }
  46. void CALLBACK timercallback(UINT id, UINT xxmsg, DWORD_PTR data, DWORD dw1, DWORD dw2)
  47. {
  48. gs_context_t *ctx = (gs_context_t *) data;
  49. gs_group_t *gd;
  50. gs_msg_t *msg;
  51. msg = ctx->ctx_msg;
  52. if (msg == NULL) {
  53. return;
  54. }
  55. gd = GspLookupGroup(ctx->ctx_gid);
  56. assert(gd != NULL);
  57. // resend msg
  58. GsLockEnter(gd->g_lock);
  59. msg = ctx->ctx_msg;
  60. if (msg != NULL) {
  61. ULONG mask = ctx->ctx_mask;
  62. gs_memberid_t id;
  63. // send a reliable point-to-point to non-response nodes
  64. gs_log(("Timercallback mset %x\n", mask));
  65. msg->m_hdr.h_flags |= GS_FLAGS_REPLAY;
  66. for (id = 1; mask; id++, mask = mask >> 1) {
  67. if (mask & 0x2) {
  68. msg_mcast(id, &msg->m_hdr, ctx->ctx_buf, msg->m_hdr.h_len);
  69. }
  70. }
  71. }
  72. GsLockExit(gd->g_lock);
  73. }
  74. void
  75. GspProcessReply(gs_group_t *gd, gs_context_t *ctx, int sid, char *buf, int rlen,
  76. NTSTATUS status)
  77. {
  78. gs_msg_t *msg;
  79. int ctx_rlen;
  80. IO_STATUS_BLOCK *ios = ctx->ctx_ios;
  81. msg = ctx->ctx_msg;
  82. if (msg == NULL) {
  83. err_log(("Error invalid msg in ctx %d, gid %d\n", ctx->ctx_id, gd->g_id));
  84. GsEventSignal(ctx->ctx_event);
  85. //xxx: for debugging
  86. halt(0);
  87. return;
  88. }
  89. if (rlen > 0) {
  90. PVOID *p = ctx->ctx_rbuf;
  91. rlen = min(rlen , msg->m_hdr.h_rlen);
  92. if (p != NULL) {
  93. if (msg->m_hdr.h_type == GS_MSG_TYPE_MCAST) {
  94. p += (sid - 1);
  95. ios += (sid - 1);
  96. }
  97. memcpy(*p, buf, rlen);
  98. }
  99. } else if (msg->m_hdr.h_type == GS_MSG_TYPE_MCAST) {
  100. ios += (sid - 1);
  101. }
  102. ios->Status = status;
  103. ios->Information = rlen;
  104. ctx->ctx_mask &= ~(1 << sid);
  105. gs_log(("process reply len %d gid %d cid %d nid %d mseq %d sz %d mask %x ios %x\n",
  106. rlen, gd->g_id, ctx->ctx_id,
  107. sid, msg->m_hdr.h_mseq, msg->m_hdr.h_rlen, ctx->ctx_mask, ios));
  108. if (ctx->ctx_mask == 0) {
  109. gs_event_t ev = ctx->ctx_event;
  110. if (ctx->ctx_timer) {
  111. timeKillEvent(ctx->ctx_timer);
  112. ctx->ctx_timer = 0;
  113. }
  114. ctx->ctx_msg = NULL;
  115. gd->g_send.s_lseq = msg->m_hdr.h_mseq;
  116. // free msg and signal waiter
  117. GspRemoveMsg(gd, msg);
  118. #if 0
  119. if (ctx->ctx_flags & GS_FLAGS_CLOSE) {
  120. GspCloseContext(gd, ctx);
  121. }
  122. #endif
  123. if (ev) {
  124. gs_log(("Signal ctx %d\n", ctx->ctx_id));
  125. GsEventSignal(ev);
  126. }
  127. } else {
  128. gs_log(("Waiting for more replies %x\n", ctx->ctx_mask));
  129. // place ctx into timer queue if we haven't already done so
  130. if (sid == (int)gd->g_nid) {
  131. ctx->ctx_timer = timeSetEvent(500, 0, (LPTIMECALLBACK)timercallback,
  132. (DWORD_PTR)ctx, TIME_ONESHOT);
  133. if (ctx->ctx_timer == 0) {
  134. printf("Unable to create timer %d\n", GetLastError());
  135. }
  136. }
  137. }
  138. }
  139. void
  140. GspProcessWaitQueue(gs_group_t *gd, gs_seq_info_t *info)
  141. {
  142. int i;
  143. gs_msg_t *last, *cur;
  144. gs_send_state_t *ss;
  145. gs_log(("Process wait queue mid %d mseq %d view %d\n",
  146. gd->g_mid, info->mseq, info->viewnum));
  147. ss = &gd->g_send;
  148. // sequence all ready requests
  149. cur = ss->s_waitqueue;
  150. if (cur == NULL) {
  151. err_log(("Gid %d Empty wait queue!\n", gd->g_id));
  152. halt(1);
  153. }
  154. for (i = 0; cur != NULL; i++) {
  155. cur->m_hdr.h_mseq = info->mseq;
  156. cur->m_hdr.h_bnum = i * (1 << 16);
  157. cur->m_hdr.h_mid = gd->g_mid;
  158. cur->m_hdr.h_viewnum = info->viewnum;
  159. // piggyback our receive state
  160. cur->m_hdr.h_lseq = gd->g_send.s_lseq;
  161. if (cur->m_next == NULL) {
  162. cur->m_hdr.h_flags |= GS_FLAGS_LAST;
  163. }
  164. msg_mcast(gd->g_mset, &cur->m_hdr, cur->m_buf, cur->m_hdr.h_len);
  165. {
  166. gs_context_t *sc;
  167. sc = &ss->s_ctxpool[cur->m_hdr.h_cid];
  168. sc->ctx_mseq = cur->m_hdr.h_mseq;
  169. sc->ctx_bnum = cur->m_hdr.h_bnum + 1;
  170. sc->ctx_flags = cur->m_hdr.h_flags;
  171. }
  172. last = cur;
  173. cur = cur->m_next;
  174. }
  175. // Insert waitqueue into receive side queue
  176. cur = ss->s_waitqueue;
  177. ss->s_waitqueue = NULL;
  178. ss->s_mseq = info->mseq+1;
  179. ss->s_bnum = 0;
  180. GspOrderInsert(gd, cur, last, info->mseq, 0);
  181. GspDispatch(gd);
  182. }
  183. void
  184. GspAllocateSequence(gs_group_t *gd)
  185. {
  186. gs_seq_info_t info;
  187. gs_msg_t msg;
  188. assert(gd->g_send.s_waitqueue != NULL);
  189. if (gd->g_mid == gd->g_nid) {
  190. info.mseq = gd->g_global_seq++;
  191. info.viewnum = gd->g_curview;
  192. GspProcessWaitQueue(gd, &info);
  193. } else {
  194. // remote case
  195. gs_log(("Allocate a seq from mid %x view %d,%d\n", gd->g_mid,
  196. gd->g_startview, gd->g_curview));
  197. msg.m_hdr.h_len = 0;
  198. msg.m_hdr.h_type = GS_MSG_TYPE_SEQALLOC;
  199. msg.m_hdr.h_flags = GS_FLAGS_PTP;
  200. msg.m_hdr.h_viewnum = gd->g_curview;
  201. msg.m_hdr.h_rlen = sizeof(info);
  202. msg.m_hdr.h_cid = 0;
  203. msg.m_hdr.h_gid = gd->g_id;
  204. msg.m_hdr.h_sid = (gs_memberid_t) gd->g_nid;
  205. msg.m_hdr.h_mid = gd->g_mid;
  206. msg.m_hdr.h_mseq = gd->g_send.s_mseq;
  207. msg.m_hdr.h_lseq = gd->g_send.s_lseq;
  208. msg.m_hdr.h_bnum = 0;
  209. memset(msg.m_hdr.h_tag, 0, sizeof(msg.m_hdr.h_tag));
  210. msg_send(gd->g_mid, &msg.m_hdr, NULL, 0);
  211. }
  212. }
  213. NTSTATUS
  214. WINAPI
  215. GsSendDeliveredRequest(HANDLE group, gs_event_t event OPTIONAL,
  216. gs_tag_t tag, PVOID buf, UINT32 len,
  217. PVOID rbuf[], UINT32 rlen,
  218. IO_STATUS_BLOCK ios[],
  219. HANDLE *context)
  220. {
  221. gs_context_t *ctx;
  222. gs_group_t *gd = (gs_group_t *)group;
  223. gs_send_state_t *ss;
  224. BOOLEAN flag;
  225. gs_msg_t *msg;
  226. if (gd == NULL || ios == NULL) {
  227. return ERROR_INVALID_PARAMETER;
  228. }
  229. GspOpenContext(gd, &ctx);
  230. ctx->ctx_flags = GS_FLAGS_DELIVERED;
  231. if (context != NULL) {
  232. ctx->ctx_flags |= GS_FLAGS_CONTINUED;
  233. *context = ctx;
  234. } else {
  235. ctx->ctx_flags |= GS_FLAGS_CLOSE;
  236. }
  237. ctx->ctx_buf = buf;
  238. ctx->ctx_rbuf = rbuf;
  239. ctx->ctx_ios = ios;
  240. if (event == NULL)
  241. event = ctx->ctx_syncevent;
  242. ctx->ctx_event = event;
  243. msg = msg_alloc(buf, len);
  244. assert(msg != NULL);
  245. msg->m_hdr.h_len = (UINT16) len;
  246. msg->m_hdr.h_type = GS_MSG_TYPE_MCAST;
  247. msg->m_hdr.h_flags = ctx->ctx_flags | GS_FLAGS_QUEUED;
  248. msg->m_hdr.h_rlen = (UINT16) rlen;
  249. msg->m_hdr.h_cid = ctx->ctx_id;
  250. msg->m_hdr.h_gid = gd->g_id;
  251. msg->m_hdr.h_sid = (gs_memberid_t) gd->g_nid;
  252. memcpy(msg->m_hdr.h_tag, tag, sizeof(gs_tag_t));
  253. ss = &gd->g_send;
  254. // place context into readylist
  255. GsLockEnter(gd->g_lock);
  256. flag = ss->s_waitqueue == NULL ? TRUE : FALSE;
  257. msg->m_next = ss->s_waitqueue;
  258. ss->s_waitqueue = msg;
  259. ctx->ctx_mask = gd->g_mset;
  260. ctx->ctx_msg = msg;
  261. msg->m_refcnt++;
  262. // check if we have already asked for a global sequence number
  263. if (flag == TRUE) {
  264. GspAllocateSequence(gd);
  265. }
  266. GsLockExit(gd->g_lock);
  267. // wait for replies or acks
  268. if (event) {
  269. gs_log(("Wait on event %x\n", event));
  270. GsEventWait(event);
  271. }
  272. if (ctx->ctx_flags & GS_FLAGS_CLOSE) {
  273. GspCloseContext(gd, ctx);
  274. }
  275. return ERROR_SUCCESS;
  276. }
  277. NTSTATUS
  278. GsSendContinuedRequest(HANDLE context, gs_event_t event OPTIONAL,
  279. gs_tag_t tag, PVOID buf, UINT32 len,
  280. PVOID rbuf[], UINT32 rlen,
  281. IO_STATUS_BLOCK ios[],
  282. BOOLEAN close)
  283. {
  284. gs_context_t *ctx = (gs_context_t *) context;
  285. gs_group_t *gd;
  286. gs_send_state_t *ss;
  287. BOOLEAN flag;
  288. gs_msg_t *msg;
  289. if (ctx == NULL || ios == NULL) {
  290. return ERROR_INVALID_PARAMETER;
  291. }
  292. if (rbuf == NULL && rlen > 0) {
  293. return ERROR_INVALID_PARAMETER;
  294. }
  295. if (buf == NULL && len > 0) {
  296. return ERROR_INVALID_PARAMETER;
  297. }
  298. gd = GspLookupGroup(ctx->ctx_gid);
  299. assert(gd != NULL);
  300. msg = msg_alloc(buf, len);
  301. assert(msg != NULL);
  302. if (close == TRUE) {
  303. ctx->ctx_flags &= ~GS_FLAGS_CONTINUED;
  304. ctx->ctx_flags |= GS_FLAGS_CLOSE;
  305. }
  306. if (event == NULL)
  307. event = ctx->ctx_syncevent;
  308. ctx->ctx_event = event;
  309. ctx->ctx_buf = buf;
  310. ctx->ctx_rbuf = rbuf;
  311. ctx->ctx_ios = ios;
  312. ctx->ctx_msg = msg;
  313. msg->m_hdr.h_len = (UINT16) len;
  314. msg->m_hdr.h_type = GS_MSG_TYPE_MCAST;
  315. msg->m_hdr.h_flags = ctx->ctx_flags | GS_FLAGS_QUEUED;
  316. msg->m_hdr.h_rlen = (UINT16) rlen;
  317. msg->m_hdr.h_cid = ctx->ctx_id;
  318. msg->m_hdr.h_gid = gd->g_id;
  319. msg->m_hdr.h_sid = gd->g_nid;
  320. memcpy(msg->m_hdr.h_tag, tag, sizeof(gs_tag_t));
  321. msg->m_hdr.h_mseq = ctx->ctx_mseq;
  322. msg->m_hdr.h_bnum = ctx->ctx_bnum++;
  323. GsLockEnter(gd->g_lock);
  324. msg->m_hdr.h_lseq = gd->g_send.s_lseq;
  325. msg->m_hdr.h_mid = gd->g_mid;
  326. msg->m_hdr.h_viewnum = gd->g_curview;
  327. ctx->ctx_mask = gd->g_mset;
  328. msg->m_refcnt++;
  329. msg_mcast(gd->g_mset, &msg->m_hdr, buf, len);
  330. GspOrderInsert(gd, msg, msg, ctx->ctx_mseq, ctx->ctx_bnum);
  331. GspDispatch(gd);
  332. GsLockExit(gd->g_lock);
  333. // wait for replies or acks
  334. if (event != NULL) {
  335. gs_log(("Wait on event %x\n", event));
  336. GsEventWait(event);
  337. }
  338. if (ctx->ctx_flags & GS_FLAGS_CLOSE) {
  339. GspCloseContext(gd, ctx);
  340. }
  341. return ERROR_SUCCESS;
  342. }
  343. NTSTATUS
  344. GspSendDirectedRequest(gs_group_t *gd, gs_context_t *ctx, gs_event_t event,
  345. int memberid, gs_tag_t tag,
  346. PVOID buf, UINT32 len,
  347. PVOID rbuf, UINT32 rlen,
  348. IO_STATUS_BLOCK *ios,
  349. UINT32 flags, UINT32 type)
  350. {
  351. gs_send_state_t *ss;
  352. gs_nid_t mid;
  353. gs_msg_t *msg;
  354. int err = ERROR_SUCCESS;
  355. if (rlen > (UINT32)GS_DEFAULT_MAX_MSG_SZ) {
  356. return ERROR_INVALID_PARAMETER;
  357. }
  358. assert(gd != NULL);
  359. msg = msg_alloc(buf, len);
  360. assert(msg != NULL);
  361. if (event == NULL)
  362. event = ctx->ctx_syncevent;
  363. ctx->ctx_flags = (UINT16) flags;
  364. ctx->ctx_event = event;
  365. ctx->ctx_buf = buf;
  366. ctx->ctx_rbuf = rbuf;
  367. ctx->ctx_ios = ios;
  368. msg->m_hdr.h_len = (UINT16) len;
  369. msg->m_hdr.h_type = (UINT16) type;
  370. msg->m_hdr.h_flags = ctx->ctx_flags | GS_FLAGS_PTP;
  371. msg->m_hdr.h_rlen = (UINT16) rlen;
  372. msg->m_hdr.h_cid = ctx->ctx_id;
  373. msg->m_hdr.h_gid = gd->g_id;
  374. msg->m_hdr.h_sid = gd->g_nid;
  375. msg->m_hdr.h_mid = (gs_memberid_t) memberid;
  376. memcpy(msg->m_hdr.h_tag, tag, sizeof(gs_tag_t));
  377. GsLockEnter(gd->g_lock);
  378. ctx->ctx_msg = msg;
  379. ctx->ctx_mask = 1 << memberid;
  380. ss = &gd->g_send;
  381. msg->m_hdr.h_lseq = ss->s_lseq;
  382. msg->m_hdr.h_mseq = ss->s_mseq;
  383. msg->m_hdr.h_bnum = ss->s_bnum++;
  384. msg->m_hdr.h_viewnum = gd->g_curview;
  385. if (gd->g_nid == (gs_memberid_t )memberid) {
  386. // insert into receive queue
  387. msg->m_refcnt++;
  388. msg->m_hdr.h_flags |= GS_FLAGS_QUEUED;
  389. // insert msg into dispatch queue at proper order
  390. GspUOrderInsert(gd, msg, msg, msg->m_hdr.h_mseq, msg->m_hdr.h_bnum);
  391. GspDispatch(gd);
  392. } else {
  393. err = msg_send((gs_memberid_t) memberid, &msg->m_hdr, buf, len);
  394. }
  395. GsLockExit(gd->g_lock);
  396. // wait for replies or acks
  397. if (!err && event != NULL) {
  398. GsEventWait(event);
  399. }
  400. if (ctx->ctx_flags & GS_FLAGS_CLOSE) {
  401. GspCloseContext(gd, ctx);
  402. }
  403. return err;
  404. }
  405. NTSTATUS
  406. WINAPI
  407. GsSendDirectedRequest(HANDLE group, gs_event_t event OPTIONAL,
  408. int memberid, gs_tag_t tag,
  409. PVOID buf, UINT32 len,
  410. PVOID rbuf, UINT32 rlen,
  411. IO_STATUS_BLOCK *ios,
  412. HANDLE *context)
  413. {
  414. gs_group_t *gd = (gs_group_t *)group;
  415. gs_context_t *ctx;
  416. NTSTATUS err;
  417. if (gd == NULL) {
  418. return ERROR_INVALID_HANDLE;
  419. }
  420. GspOpenContext(gd, &ctx);
  421. ctx->ctx_flags = GS_FLAGS_DELIVERED | GS_FLAGS_CONTINUED;
  422. if (context != NULL) {
  423. ctx->ctx_flags |= GS_FLAGS_CONTINUED;
  424. *context = ctx;
  425. } else {
  426. ctx->ctx_flags |= GS_FLAGS_CLOSE;
  427. }
  428. err = GspSendDirectedRequest(gd, ctx, event,
  429. memberid, tag, buf, len, rbuf, rlen,
  430. ios,
  431. ctx->ctx_flags, GS_MSG_TYPE_UCAST);
  432. if (err != ERROR_SUCCESS) {
  433. GspCloseContext(gd, ctx);
  434. }
  435. return err;
  436. }
  437. NTSTATUS
  438. GspSendRequest(gs_group_t *gd, gs_context_t *ctx, gs_event_t event,
  439. int type, gs_sequence_t mid, gs_tag_t tag,
  440. PVOID buf, UINT32 len,
  441. PVOID rbuf[], UINT32 rlen,
  442. IO_STATUS_BLOCK ios[],
  443. UINT32 flags, gs_join_info_t *info)
  444. {
  445. gs_send_state_t *ss;
  446. BOOLEAN flag;
  447. gs_msg_t *msg;
  448. assert(gd != NULL);
  449. msg = msg_alloc(buf, len);
  450. assert(msg != NULL);
  451. msg->m_hdr.h_len = (UINT16) len;
  452. msg->m_hdr.h_type = (UINT16) type;
  453. msg->m_hdr.h_flags = (UINT16) flags;
  454. msg->m_hdr.h_rlen = (UINT16) rlen;
  455. msg->m_hdr.h_cid = ctx->ctx_id;
  456. msg->m_hdr.h_gid = gd->g_id;
  457. msg->m_hdr.h_sid = (gs_memberid_t) gd->g_nid;
  458. memcpy(msg->m_hdr.h_tag, tag, sizeof(gs_tag_t));
  459. msg->m_hdr.h_mseq = info->mseq;
  460. msg->m_hdr.h_lseq = info->mseq;
  461. msg->m_hdr.h_bnum = ctx->ctx_bnum++;
  462. msg->m_hdr.h_mid = (gs_memberid_t) mid;
  463. msg->m_hdr.h_viewnum = info->viewnum;
  464. if (event == NULL)
  465. event = ctx->ctx_syncevent;
  466. ctx->ctx_buf = buf;
  467. ctx->ctx_rbuf = rbuf;
  468. ctx->ctx_ios = ios;
  469. ctx->ctx_event = event;
  470. ctx->ctx_msg = msg;
  471. ctx->ctx_mask = info->mset;
  472. ctx->ctx_mseq = info->mseq;
  473. ctx->ctx_flags = (UINT16) flags;
  474. GsLockEnter(gd->g_lock);
  475. gd->g_send.s_mseq = info->mseq+1;
  476. gd->g_send.s_bnum = 0;
  477. msg_mcast(info->mset, &msg->m_hdr, buf, len);
  478. if (info->mset & (1 << gd->g_nid)) {
  479. msg->m_hdr.h_flags |= GS_FLAGS_QUEUED;
  480. msg->m_refcnt++;
  481. GspOrderInsert(gd, msg, msg, info->mseq, msg->m_hdr.h_bnum);
  482. GspDispatch(gd);
  483. } else {
  484. msg->m_hdr.h_flags |= GS_FLAGS_PTP;
  485. ctx->ctx_timer = timeSetEvent(500, 0, (LPTIMECALLBACK)timercallback,
  486. (DWORD_PTR)ctx, TIME_PERIODIC);
  487. if (ctx->ctx_timer == 0) {
  488. printf("Unable to create timer %d\n", GetLastError());
  489. }
  490. }
  491. GsLockExit(gd->g_lock);
  492. // wait for replies or acks
  493. if (event != NULL) {
  494. GsEventWait(event);
  495. }
  496. if (ctx->ctx_flags & GS_FLAGS_CLOSE) {
  497. GspCloseContext(gd, ctx);
  498. }
  499. return ERROR_SUCCESS;
  500. }